X7ROOT File Manager
Current Path:
/home/gfecatvj/public_html/772799
home
/
gfecatvj
/
public_html
/
772799
/
📁
..
📄
0.9.rb.9.rb.tar.gz
(2.05 KB)
📄
0.9.rb.tar
(78.5 KB)
📄
0.tar
(9.5 KB)
📄
0.tar.gz
(108 B)
📄
0.zip
(1.06 KB)
📄
00.0.0.tar.gz
(120 B)
📄
00.0.tar
(2 KB)
📄
00.tar
(12 KB)
📄
00.tar.gz
(451 B)
📄
00.zip
(2 KB)
📄
00bash.tar
(2 KB)
📄
00bash.tar.gz
(290 B)
📄
00bash.zip
(525 B)
📄
00systemd.tar
(11 KB)
📄
00systemd.tar.gz
(1.92 KB)
📄
00systemd.zip
(9.31 KB)
📄
00warpclock.tar
(3.5 KB)
📄
00warpclock.tar.gz
(559 B)
📄
00warpclock.zip
(1.09 KB)
📄
01.0.0.tar.gz
(124 B)
📄
01.0.tar
(2 KB)
📄
01.1.1.tar.gz
(126 B)
📄
01.1.tar
(2 KB)
📄
01.2.2.tar.gz
(130 B)
📄
01.2.tar
(2 KB)
📄
01.3.3.tar.gz
(126 B)
📄
01.3.tar
(2 KB)
📄
01fips.tar
(13.5 KB)
📄
01fips.tar.gz
(2.9 KB)
📄
01fips.zip
(9.32 KB)
📄
01systemd-initrd.tar
(3.5 KB)
📄
01systemd-initrd.tar.gz
(674 B)
📄
01systemd-initrd.zip
(1.95 KB)
📄
02.0.0.tar.gz
(131 B)
📄
02.0.tar
(2 KB)
📄
02systemd-networkd.tar
(4 KB)
📄
02systemd-networkd.tar.gz
(690 B)
📄
02systemd-networkd.zip
(2.35 KB)
📄
03.0.0.tar.gz
(139 B)
📄
03.0.tar
(2 KB)
📄
03c55b51ab44102ad490af8bab232c669c3d35.tar
(88 KB)
📄
03c55b51ab44102ad490af8bab232c669c3d35.tar.gz
(29.89 KB)
📄
03modsign.tar
(3.5 KB)
📄
03modsign.tar.gz
(538 B)
📄
03modsign.zip
(1.25 KB)
📄
03rescue.tar
(2 KB)
📄
03rescue.tar.gz
(298 B)
📄
03rescue.zip
(541 B)
📄
04.0.0.tar.gz
(140 B)
📄
04.0.tar
(2 KB)
📄
04watchdog-modules.tar
(3.5 KB)
📄
04watchdog-modules.tar.gz
(811 B)
📄
04watchdog.tar
(4.5 KB)
📄
04watchdog.tar.gz
(590 B)
📄
04watchdog.zip
(1.71 KB)
📄
05.0.0.tar.gz
(137 B)
📄
05.0.tar
(2 KB)
📄
05busybox.tar
(2.5 KB)
📄
05busybox.tar.gz
(358 B)
📄
05busybox.zip
(734 B)
📄
05nss-softokn.tar
(2 KB)
📄
05nss-softokn.tar.gz
(280 B)
📄
05nss-softokn.zip
(455 B)
📄
06.0.0.tar.gz
(137 B)
📄
06.0.tar
(2 KB)
📄
06ac53f782e5d655985704dbf9cb5289064685.tar
(261 KB)
📄
06ac53f782e5d655985704dbf9cb5289064685.tar.gz
(51.21 KB)
📄
06rngd.tar
(4 KB)
📄
06rngd.tar.gz
(924 B)
📄
06rngd.zip
(1.64 KB)
📄
07.0.0.tar.gz
(134 B)
📄
07.0.tar
(2 KB)
📄
0889b0e65adac2585fede8e2161886b87ed108.tar
(8.5 KB)
📄
0889b0e65adac2585fede8e2161886b87ed108.tar.gz
(2.72 KB)
📄
08c059084d3b6bc1e465f9ee381350f17cf03e.tar
(450 KB)
📄
08c059084d3b6bc1e465f9ee381350f17cf03e.tar.gz
(185.52 KB)
📄
08e883cda2ec44df43726a44aa4dc22d45705c.tar
(197 KB)
📄
08e883cda2ec44df43726a44aa4dc22d45705c.tar.gz
(86.63 KB)
📄
098.tar
(25.5 KB)
📄
098.tar.gz
(18.19 KB)
📄
09f7d426feffd371.css.css.tar.gz
(2.97 KB)
📄
09f7d426feffd371.css.tar
(19 KB)
📄
0b21af9fa70dcf2c.css.css.tar.gz
(9.87 KB)
📄
0b21af9fa70dcf2c.css.tar
(85 KB)
📄
0c51d8b72d1b0355f543e818e29445731ba79f.tar
(13.5 KB)
📄
0c51d8b72d1b0355f543e818e29445731ba79f.tar.gz
(5.61 KB)
📄
0cd3e62c283b718c.css.css.tar.gz
(10.63 KB)
📄
0cd3e62c283b718c.css.tar
(98 KB)
📄
0fcfaf7348d5e02b.css.css.tar.gz
(11.67 KB)
📄
0fcfaf7348d5e02b.css.tar
(95.5 KB)
📄
1.0.rb.0.rb.tar.gz
(1.61 KB)
📄
1.0.rb.tar
(71.5 KB)
📄
1.bin.bin.tar.gz
(132 B)
📄
1.bin.tar
(4 KB)
📄
1.php.php.tar.gz
(965 B)
📄
1.php.tar
(4 KB)
📄
1.png.png.tar.gz
(46.96 KB)
📄
1.png.tar
(49 KB)
📄
1.tar
(11.97 MB)
📄
1.tar.gz
(7.33 MB)
📄
1.txt.tar
(2 KB)
📄
1.txt.txt.tar.gz
(212 B)
📄
1.zip
(11.81 MB)
📄
10-default-yama-scope.conf.conf.tar.gz
(1.01 KB)
📄
10-default-yama-scope.conf.tar
(3.5 KB)
📄
10-dm.rules.rules.tar.gz
(2.87 KB)
📄
10-dm.rules.tar
(9 KB)
📄
10.png.png.tar.gz
(43.48 KB)
📄
10.png.tar
(45.5 KB)
📄
10.tar
(8 KB)
📄
10.tar.gz
(287 B)
📄
10.zip
(1.06 KB)
📄
1020200.tar
(59 KB)
📄
1020200.tar.gz
(20.01 KB)
📄
1020200.zip
(56.06 KB)
📄
1020201.tar
(36.5 KB)
📄
1020201.tar.gz
(10.63 KB)
📄
1020201.zip
(34.67 KB)
📄
1020201coex.tar
(2 KB)
📄
1020201coex.tar.gz
(366 B)
📄
1020201coex.zip
(542 B)
📄
1028.tar
(32 KB)
📄
1028.tar.gz
(7.77 KB)
📄
1028.zip
(22.47 KB)
📄
1040.bin.bin.tar.gz
(19 KB)
📄
1040.bin.tar
(34.5 KB)
📄
10i18n.tar
(20.5 KB)
📄
10i18n.tar.gz
(5.11 KB)
📄
10i18n.zip
(16 KB)
📄
11-dm-parts.rules.rules.tar.gz
(868 B)
📄
11-dm-parts.rules.tar
(3 KB)
📄
11.tar
(8 KB)
📄
11.tar.gz
(286 B)
📄
11.zip
(1.06 KB)
📄
12.tar
(8 KB)
📄
12.tar.gz
(286 B)
📄
12.zip
(1.06 KB)
📄
1200.bin.bin.tar.gz
(3.13 KB)
📄
1200.bin.tar
(7 KB)
📄
12160.bin.bin.tar.gz
(17.09 KB)
📄
12160.bin.tar
(29 KB)
📄
1280.bin.bin.tar.gz
(18.89 KB)
📄
1280.bin.tar
(33 KB)
📄
12Point.fs.fs.tar.gz
(413 B)
📄
12Point.fs.tar
(2.5 KB)
📄
13-dm-disk.rules.rules.tar.gz
(944 B)
📄
13-dm-disk.rules.tar
(6 KB)
📄
13.tar
(8 KB)
📄
13.tar.gz
(285 B)
📄
13.zip
(1.06 KB)
📄
14.tar
(8 KB)
📄
14.tar.gz
(289 B)
📄
14.zip
(1.06 KB)
📄
15.tar
(8 KB)
📄
15.tar.gz
(287 B)
📄
15.zip
(1.06 KB)
📄
1502_00.tar
(242.5 KB)
📄
1502_00.tar.gz
(75.82 KB)
📄
1502_00.zip
(241.04 KB)
📄
17f0_10.tar
(369.5 KB)
📄
17f0_10.tar.gz
(74.86 KB)
📄
17f0_10.zip
(368.1 KB)
📄
17f0_11.tar
(369.5 KB)
📄
17f0_11.tar.gz
(74.87 KB)
📄
17f0_11.zip
(368.1 KB)
📄
1ee2d32e6db595497986f65b071f86b8e852ad.tar
(91 KB)
📄
1ee2d32e6db595497986f65b071f86b8e852ad.tar.gz
(37.03 KB)
📄
1f3bb6565ddbe95653f063203297ea1311998f.tar
(18 KB)
📄
1f3bb6565ddbe95653f063203297ea1311998f.tar.gz
(6.36 KB)
📄
1f9ee.tar
(2 KB)
📄
1f9ee.tar.gz
(191 B)
📄
1f9ee.zip
(248 B)
📄
1fa.tar
(32 KB)
📄
1fa.tar.gz
(7.77 KB)
📄
1fa.zip
(22.56 KB)
📄
1index.php.php.tar.gz
(10.6 KB)
📄
1index.php.tar
(62.5 KB)
📄
2.0.rb.0.rb.tar.gz
(806 B)
📄
2.0.rb.tar
(27 KB)
📄
2.0.tar
(5.59 MB)
📄
2.0.tar.gz
(1.78 MB)
📄
2.0.zip
(5.44 MB)
📄
2.10.0.tar
(693 KB)
📄
2.10.0.tar.gz
(80.02 KB)
📄
2.10.0.zip
(680.55 KB)
📄
2.6.tar
(2.4 MB)
📄
2.6.tar.gz
(683.76 KB)
📄
2.6.zip
(2.39 MB)
📄
2.bin.bin.tar.gz
(132 B)
📄
2.bin.tar
(4 KB)
📄
2.png.png.tar.gz
(40.5 KB)
📄
2.png.tar
(42.5 KB)
📄
2.tar
(9 KB)
📄
2.tar.gz
(284 B)
📄
2.txt.tar
(2 KB)
📄
2.txt.txt.tar.gz
(173 B)
📄
2.zip
(1.06 KB)
📄
20-OUI.hwdb.hwdb.tar.gz
(452.71 KB)
📄
20-OUI.hwdb.tar
(4.25 MB)
📄
20-acpi-vendor.hwdb.hwdb.tar.gz
(30.65 KB)
📄
20-acpi-vendor.hwdb.tar
(149 KB)
📄
20-dmi-id.hwdb.hwdb.tar.gz
(271 B)
📄
20-dmi-id.hwdb.tar
(3 KB)
📄
20-grub.install.install.tar.gz
(2.22 KB)
📄
20-grub.install.tar
(9.5 KB)
📄
20-grubby.install.install.tar.gz
(788 B)
📄
20-grubby.install.tar
(4 KB)
📄
20-net-ifname.hwdb.hwdb.tar.gz
(217 B)
📄
20-net-ifname.hwdb.tar
(2 KB)
📄
20-pci-classes.hwdb.hwdb.tar.gz
(2.24 KB)
📄
20-pci-classes.hwdb.tar
(32 KB)
📄
20-sdio-classes.hwdb.hwdb.tar.gz
(332 B)
📄
20-sdio-classes.hwdb.tar
(2.5 KB)
📄
20-sdio-vendor-model.hwdb.hwdb.tar.gz
(1.09 KB)
📄
20-sdio-vendor-model.hwdb.tar
(6 KB)
📄
20-usb-classes.hwdb.hwdb.tar.gz
(1.62 KB)
📄
20-usb-classes.hwdb.tar
(18 KB)
📄
20-vmbus-class.hwdb.hwdb.tar.gz
(812 B)
📄
20-vmbus-class.hwdb.tar
(6 KB)
📄
2022_KR.pm.pm.tar.gz
(1010 B)
📄
2022_KR.pm.tar
(3.5 KB)
📄
21.png.png.tar.gz
(38.7 KB)
📄
21.png.tar
(41.5 KB)
📄
212c81711fa65e21.css.css.tar.gz
(10.77 KB)
📄
212c81711fa65e21.css.tar
(99.5 KB)
📄
219d0251aac374169711f0fa95c39f4344e947.tar
(42.5 KB)
📄
219d0251aac374169711f0fa95c39f4344e947.tar.gz
(18.39 KB)
📄
21N1.tar
(26.32 MB)
📄
21N1.tar.gz
(14.06 MB)
📄
21N1.zip
(26.32 MB)
📄
21a5b26cc6252dd28796a74d128561b79246e1.tar
(18 KB)
📄
21a5b26cc6252dd28796a74d128561b79246e1.tar.gz
(5.85 KB)
📄
23b968c84b44c7ceeb722e393c978d8247da1b.tar
(14.5 KB)
📄
23b968c84b44c7ceeb722e393c978d8247da1b.tar.gz
(5.36 KB)
📄
24.tar
(8 KB)
📄
24.tar.gz
(288 B)
📄
24.zip
(1.06 KB)
📄
25.tar
(8 KB)
📄
25.tar.gz
(297 B)
📄
25.zip
(1.07 KB)
📄
26.tar
(8 KB)
📄
26.tar.gz
(287 B)
📄
26.zip
(1.06 KB)
📄
263e3597b253981d7aae4ead5179e66941a15e.tar
(85 KB)
📄
263e3597b253981d7aae4ead5179e66941a15e.tar.gz
(33.59 KB)
📄
27.tar
(8 KB)
📄
27.tar.gz
(288 B)
📄
27.zip
(1.06 KB)
📄
28.tar
(8 KB)
📄
28.tar.gz
(289 B)
📄
28.zip
(1.06 KB)
📄
29.tar
(8 KB)
📄
29.tar.gz
(295 B)
📄
29.zip
(1.08 KB)
📄
2b943f7559d1b583ddc617eac76c42a269f120.tar
(13.5 KB)
📄
2b943f7559d1b583ddc617eac76c42a269f120.tar.gz
(6.05 KB)
📄
2fa0532f891b9bb16fbc05dfc06bbb731f0583.tar
(12.5 KB)
📄
2fa0532f891b9bb16fbc05dfc06bbb731f0583.tar.gz
(2.92 KB)
📄
2to3.tar
(3 KB)
📄
2to3.tar.gz
(171 B)
📄
3.004006.tar
(1.39 MB)
📄
3.004006.tar.gz
(403.64 KB)
📄
3.004006.zip
(1.35 MB)
📄
3.bin.bin.tar.gz
(130 B)
📄
3.bin.tar
(4 KB)
📄
3.png.png.tar.gz
(42.29 KB)
📄
3.png.tar
(44.5 KB)
📄
3.tar
(9 KB)
📄
3.tar.gz
(285 B)
📄
3.txt.tar
(2 KB)
📄
3.txt.txt.tar.gz
(155 B)
📄
3.zip
(1.06 KB)
📄
30.tar
(8 KB)
📄
30.tar.gz
(298 B)
📄
30.zip
(1.08 KB)
📄
30000.tar
(7.5 KB)
📄
30000.tar.gz
(1.77 KB)
📄
30000.zip
(4.47 KB)
📄
30101.tar
(21.5 KB)
📄
30101.tar.gz
(7.9 KB)
📄
30101.zip
(18.77 KB)
📄
30101coex.tar
(30.5 KB)
📄
30101coex.tar.gz
(9.28 KB)
📄
30101coex.zip
(26.06 KB)
📄
30convertfs.tar
(9.5 KB)
📄
30convertfs.tar.gz
(2.16 KB)
📄
30convertfs.zip
(6.84 KB)
📄
31.tar
(8 KB)
📄
31.tar.gz
(287 B)
📄
31.zip
(1.06 KB)
📄
31242b.tar
(65 KB)
📄
31242b.tar.gz
(21.22 KB)
📄
31242b.zip
(63.33 KB)
📄
32.tar
(8 KB)
📄
32.tar.gz
(297 B)
📄
32.zip
(1.08 KB)
📄
33.png.png.tar.gz
(38.7 KB)
📄
33.png.tar
(41.5 KB)
📄
33.tar
(8 KB)
📄
33.tar.gz
(297 B)
📄
33.zip
(1.08 KB)
📄
33cd79d77b928f3c3e4513006887dbef585619.tar
(407 KB)
📄
33cd79d77b928f3c3e4513006887dbef585619.tar.gz
(155.33 KB)
📄
34.tar
(8 KB)
📄
34.tar.gz
(286 B)
📄
34.zip
(1.06 KB)
📄
34788a888ede783dea74f0338ce3ba8ecce8f2.tar
(13.5 KB)
📄
34788a888ede783dea74f0338ce3ba8ecce8f2.tar.gz
(4.39 KB)
📄
34d4362ab18eaa09913782a34f9e85f60c7f03.tar
(111 KB)
📄
34d4362ab18eaa09913782a34f9e85f60c7f03.tar.gz
(50.27 KB)
📄
35.tar
(8 KB)
📄
35.tar.gz
(297 B)
📄
35.zip
(1.08 KB)
📄
3550.bin.bin.tar.gz
(3.95 KB)
📄
3550.bin.tar
(12 KB)
📄
35network-legacy.tar
(54 KB)
📄
35network-legacy.tar.gz
(11.29 KB)
📄
35network-legacy.zip
(44.42 KB)
📄
35network-manager.tar
(8 KB)
📄
35network-manager.tar.gz
(1.49 KB)
📄
35network-manager.zip
(3.93 KB)
📄
36.tar
(8 KB)
📄
36.tar.gz
(297 B)
📄
36.zip
(1.08 KB)
📄
38C0800.bin.bin.tar.gz
(4.16 KB)
📄
38C0800.bin.tar
(7 KB)
📄
38C1600.bin.bin.tar.gz
(4.7 KB)
📄
38C1600.bin.tar
(8 KB)
📄
39efc797250ec716ad27df6214fa2581354112.tar
(9 KB)
📄
39efc797250ec716ad27df6214fa2581354112.tar.gz
(3.42 KB)
📄
3CCFEM556.cis.cis.tar.gz
(222 B)
📄
3CCFEM556.cis.tar
(3 KB)
📄
3CXEM556.cis.cis.tar.gz
(223 B)
📄
3CXEM556.cis.tar
(2 KB)
📄
3a6d6cc3b46fe3cb77a9db09aa75e5d88097eb.tar
(18 KB)
📄
3a6d6cc3b46fe3cb77a9db09aa75e5d88097eb.tar.gz
(5.92 KB)
📄
3af3df85c340c7faabadba2ec3094d84ecc4c1.tar
(47.5 KB)
📄
3af3df85c340c7faabadba2ec3094d84ecc4c1.tar.gz
(16.44 KB)
📄
3c5c9c1bf4c9271fe00a2f33aeaf3f549277e5.tar
(45.5 KB)
📄
3c5c9c1bf4c9271fe00a2f33aeaf3f549277e5.tar.gz
(21.04 KB)
📄
3c90e3f53dbfb593.css.css.tar.gz
(7.5 KB)
📄
3c90e3f53dbfb593.css.tar
(61.5 KB)
📄
3cf320bb195f0a50ddcaaf47ad3cea64fb5dd5.tar
(13 KB)
📄
3cf320bb195f0a50ddcaaf47ad3cea64fb5dd5.tar.gz
(3.28 KB)
📄
3com.tar
(45.5 KB)
📄
3com.tar.gz
(29.79 KB)
📄
3com.zip
(43.66 KB)
📄
3d3c4ea76360a0bdebf8501c9a09b3d3d74f8b.tar
(13.5 KB)
📄
3d3c4ea76360a0bdebf8501c9a09b3d3d74f8b.tar.gz
(4.11 KB)
📄
3df09ac1a37f9e8839e276fd6250548b643d1f.tar
(13 KB)
📄
3df09ac1a37f9e8839e276fd6250548b643d1f.tar.gz
(3.28 KB)
📄
3eb1c84132d4d050.css.css.tar.gz
(6.63 KB)
📄
3eb1c84132d4d050.css.tar
(50 KB)
📄
4.000001.tar
(1.39 MB)
📄
4.000001.tar.gz
(397.14 KB)
📄
4.000001.zip
(1.35 MB)
📄
4.18.0-477.10.1.lve.el8.x86_64.tar
(466 KB)
📄
4.18.0-477.10.1.lve.el8.x86_64.tar.gz
(106.84 KB)
📄
4.18.0-477.10.1.lve.el8.x86_64.zip
(464.54 KB)
📄
4.18.0-513.5.1.lve.el8.x86_64.tar
(994.5 KB)
📄
4.18.0-513.5.1.lve.el8.x86_64.tar.gz
(225.53 KB)
📄
4.18.0-513.5.1.lve.el8.x86_64.zip
(992.52 KB)
📄
4.bin.bin.tar.gz
(132 B)
📄
4.bin.tar
(4 KB)
📄
4.png.png.tar.gz
(38.9 KB)
📄
4.png.tar
(41 KB)
📄
4.tar
(9 KB)
📄
4.tar.gz
(295 B)
📄
4.txt.tar
(2 KB)
📄
4.txt.txt.tar.gz
(159 B)
📄
4.zip
(1.07 KB)
📄
40-elevator.rules.rules.tar.gz
(511 B)
📄
40-elevator.rules.tar
(2.5 KB)
📄
40-redhat.rules.rules.tar.gz
(900 B)
📄
40-redhat.rules.tar
(3.5 KB)
📄
40-usb-blacklist.rules.rules.tar.gz
(389 B)
📄
40-usb-blacklist.rules.tar
(2 KB)
📄
400.shtml.shtml.tar.gz
(241 B)
📄
400.shtml.tar
(2 KB)
📄
401.shtml.shtml.tar.gz
(225 B)
📄
401.shtml.tar
(2 KB)
📄
403.shtml.shtml.tar.gz
(225 B)
📄
403.shtml.tar
(2 KB)
📄
404.shtml.shtml.tar.gz
(225 B)
📄
404.shtml.tar
(2 KB)
📄
40network.tar
(35.5 KB)
📄
40network.tar.gz
(8.26 KB)
📄
40network.zip
(30.95 KB)
📄
413.shtml.shtml.tar.gz
(234 B)
📄
413.shtml.tar
(2 KB)
📄
425.tar
(25.5 KB)
📄
425.tar.gz
(18.18 KB)
📄
45dc6d7ae94bb9877be088e6d08870da74481d.tar
(391 KB)
📄
45dc6d7ae94bb9877be088e6d08870da74481d.tar.gz
(148.12 KB)
📄
45ifcfg.tar
(11.5 KB)
📄
45ifcfg.tar.gz
(2.63 KB)
📄
45ifcfg.zip
(9.24 KB)
📄
45url-lib.tar
(10 KB)
📄
45url-lib.tar.gz
(2.81 KB)
📄
45url-lib.zip
(8.22 KB)
📄
46b856e06bf7f067.css.css.tar.gz
(10.72 KB)
📄
46b856e06bf7f067.css.tar
(87 KB)
📄
472b6dd43bb66dc64e3d22e87edb817bca17bf.tar
(111 KB)
📄
472b6dd43bb66dc64e3d22e87edb817bca17bf.tar.gz
(52.37 KB)
📄
4877121d00b5ecf93a819b7249e83176274664.tar
(13.5 KB)
📄
4877121d00b5ecf93a819b7249e83176274664.tar.gz
(3.9 KB)
📄
4abetter.us-old.tar
(5.42 MB)
📄
4abetter.us-old.tar.gz
(5.22 MB)
📄
4abetter.us-old.zip
(5.39 MB)
📄
4abetter.us.tar
(151.52 MB)
📄
4abetter.us.tar.gz
(7.37 MB)
📄
4abetter.us.zip
(147.17 MB)
📄
4abetterus.tar
(2.5 KB)
📄
4abetterus.tar.gz
(394 B)
📄
4b24b57337441051.css.css.tar.gz
(3.38 KB)
📄
4b24b57337441051.css.tar
(28 KB)
📄
4e5db5b7ec55d571a9f71cbc61c0620450859c.tar
(13.5 KB)
📄
4e5db5b7ec55d571a9f71cbc61c0620450859c.tar.gz
(3.67 KB)
📄
4images.tar
(179 KB)
📄
4images.tar.gz
(93.73 KB)
📄
4images.zip
(151.75 KB)
📄
5.4.tar
(29 KB)
📄
5.4.tar.gz
(8.41 KB)
📄
5.4.zip
(27.57 KB)
📄
5.5.tar
(29 KB)
📄
5.5.tar.gz
(8.4 KB)
📄
5.5.zip
(27.57 KB)
📄
5.6.tar
(29 KB)
📄
5.6.tar.gz
(8.41 KB)
📄
5.6.zip
(27.57 KB)
📄
5.png.png.tar.gz
(51.73 KB)
📄
5.png.tar
(54 KB)
📄
5.tar
(9.5 KB)
📄
5.tar.gz
(285 B)
📄
5.txt.tar
(2 KB)
📄
5.txt.txt.tar.gz
(138 B)
📄
5.zip
(1.06 KB)
📄
50-chronyd.list.list.tar.gz
(132 B)
📄
50-chronyd.list.tar
(2 KB)
📄
50-coredump.conf.conf.tar.gz
(748 B)
📄
50-coredump.conf.tar
(3 KB)
📄
50-default.conf.conf.tar.gz
(1.04 KB)
📄
50-default.conf.tar
(3.5 KB)
📄
50-depmod.install.install.tar.gz
(338 B)
📄
50-depmod.install.tar
(2 KB)
📄
50-dracut.install.install.tar.gz
(763 B)
📄
50-dracut.install.tar
(3.5 KB)
📄
50-pid-max.conf.conf.tar.gz
(499 B)
📄
50-pid-max.conf.tar
(2.5 KB)
📄
500.shtml.shtml.tar.gz
(249 B)
📄
500.shtml.tar
(2 KB)
📄
508d430299302655.css.css.tar.gz
(2 KB)
📄
508d430299302655.css.tar
(16.5 KB)
📄
50drm.tar
(3 KB)
📄
50drm.tar.gz
(705 B)
📄
50drm.zip
(1.48 KB)
📄
50plymouth.tar
(9 KB)
📄
50plymouth.tar.gz
(1.61 KB)
📄
50plymouth.zip
(4.72 KB)
📄
51d958a19ba5463fb21f7e66447862693b1119.tar
(13.5 KB)
📄
51d958a19ba5463fb21f7e66447862693b1119.tar.gz
(3.66 KB)
📄
52acd9bb3af0b4c42900163fc260edf3935a5b.tar
(17.5 KB)
📄
52acd9bb3af0b4c42900163fc260edf3935a5b.tar.gz
(6.51 KB)
📄
54f523bd10a409b84f7ec2597580e450a97c79.tar
(22 KB)
📄
54f523bd10a409b84f7ec2597580e450a97c79.tar.gz
(9.14 KB)
📄
59a2d47d1560b56e2f460ff817c64d96a4e529.tar
(93 KB)
📄
59a2d47d1560b56e2f460ff817c64d96a4e529.tar.gz
(34.1 KB)
📄
5c74c7cdccc81ecc.css.css.tar.gz
(11.56 KB)
📄
5c74c7cdccc81ecc.css.tar
(93.5 KB)
📄
5fdc705607570993f23492a461ce9418293dfb.tar
(54.5 KB)
📄
5fdc705607570993f23492a461ce9418293dfb.tar.gz
(20.46 KB)
📄
6.4.1.tar
(9.99 MB)
📄
6.4.1.tar.gz
(3.83 MB)
📄
6.4.1.zip
(9.8 MB)
📄
6.5.1.tar
(11.95 MB)
📄
6.5.1.tar.gz
(4.68 MB)
📄
6.5.1.zip
(11.74 MB)
📄
6.5.2.tar
(12.59 MB)
📄
6.5.2.tar.gz
(4.98 MB)
📄
6.5.2.zip
(12.38 MB)
📄
6.5.3.tar
(10.65 MB)
📄
6.5.3.tar.gz
(4.13 MB)
📄
6.5.3.zip
(10.45 MB)
📄
6.5.4.tar
(11.32 MB)
📄
6.5.4.tar.gz
(4.45 MB)
📄
6.5.4.zip
(11.12 MB)
📄
6.png.png.tar.gz
(51.97 KB)
📄
6.png.tar
(54 KB)
📄
6.tar
(9 KB)
📄
6.tar.gz
(285 B)
📄
6.txt.tar
(2 KB)
📄
6.txt.txt.tar.gz
(142 B)
📄
6.zip
(1.06 KB)
📄
60-alias-kmsg.rules.rules.tar.gz
(322 B)
📄
60-alias-kmsg.rules.tar
(2 KB)
📄
60-autosuspend.hwdb.hwdb.tar.gz
(778 B)
📄
60-autosuspend.hwdb.tar
(6 KB)
📄
60-block.rules.rules.tar.gz
(478 B)
📄
60-block.rules.tar
(2.5 KB)
📄
60-cdrom_id.rules.rules.tar.gz
(684 B)
📄
60-cdrom_id.rules.tar
(3 KB)
📄
60-drm.rules.rules.tar.gz
(321 B)
📄
60-drm.rules.tar
(2 KB)
📄
60-evdev.hwdb.hwdb.tar.gz
(4.55 KB)
📄
60-evdev.hwdb.tar
(42 KB)
📄
60-evdev.rules.rules.tar.gz
(479 B)
📄
60-evdev.rules.tar
(2.5 KB)
📄
60-fido-id.rules.rules.tar.gz
(244 B)
📄
60-fido-id.rules.tar
(2 KB)
📄
60-input-id.rules.rules.tar.gz
(302 B)
📄
60-input-id.rules.tar
(2 KB)
📄
60-keyboard.hwdb.hwdb.tar.gz
(16.43 KB)
📄
60-keyboard.hwdb.tar
(174 KB)
📄
60-net.rules.rules.tar.gz
(218 B)
📄
60-net.rules.tar
(2 KB)
📄
60-persistent-input.rules.rules.tar.gz
(844 B)
📄
60-persistent-input.rules.tar
(4.5 KB)
📄
60-raw.rules.rules.tar.gz
(294 B)
📄
60-raw.rules.tar
(2 KB)
📄
60-seat.hwdb.hwdb.tar.gz
(589 B)
📄
60-seat.hwdb.tar
(3 KB)
📄
60-sensor.hwdb.hwdb.tar.gz
(7.18 KB)
📄
60-sensor.hwdb.tar
(75 KB)
📄
60-sensor.rules.rules.tar.gz
(415 B)
📄
60-sensor.rules.tar
(2.5 KB)
📄
60-serial.rules.rules.tar.gz
(544 B)
📄
60-serial.rules.tar
(3 KB)
📄
60-tpm-udev.rules.rules.tar.gz
(241 B)
📄
60-tpm-udev.rules.tar
(2 KB)
📄
63-fc-wwpn-id.rules.rules.tar.gz
(360 B)
📄
63-fc-wwpn-id.rules.tar
(2.5 KB)
📄
63-scsi-sg3_symlink.rules.rules.tar.gz
(713 B)
📄
63-scsi-sg3_symlink.rules.tar
(4.5 KB)
📄
64-btrfs.rules.rules.tar.gz
(455 B)
📄
64-btrfs.rules.tar
(2.5 KB)
📄
65-context.rules.rules.tar.gz
(669 B)
📄
65-context.rules.tar
(3.5 KB)
📄
65-libwacom.hwdb.hwdb.tar.gz
(3.35 KB)
📄
65-libwacom.hwdb.tar
(104 KB)
📄
65-libwacom.rules.rules.tar.gz
(680 B)
📄
65-libwacom.rules.tar
(3 KB)
📄
66-kpartx.rules.rules.tar.gz
(657 B)
📄
66-kpartx.rules.tar
(3 KB)
📄
67edb88a9a7fc67552dd3d1bb2845e6d84fe7d.tar
(18.5 KB)
📄
67edb88a9a7fc67552dd3d1bb2845e6d84fe7d.tar.gz
(5.36 KB)
📄
691ad460a27a8d052bf09f2a1654b6183c7575.tar
(13.5 KB)
📄
691ad460a27a8d052bf09f2a1654b6183c7575.tar.gz
(3.6 KB)
📄
6adc6dd0c48bd4d2b190a94c8884fb29559325.tar
(13.5 KB)
📄
6adc6dd0c48bd4d2b190a94c8884fb29559325.tar.gz
(3.7 KB)
📄
6b98b8f369ce8b63512d9236017fbe20acda17.tar
(47.5 KB)
📄
6b98b8f369ce8b63512d9236017fbe20acda17.tar.gz
(20.24 KB)
📄
6fd.tar
(25.5 KB)
📄
6fd.tar.gz
(18.17 KB)
📄
7.0.tar
(29.5 KB)
📄
7.0.tar.gz
(8.6 KB)
📄
7.0.zip
(27.73 KB)
📄
7.1.tar
(7.59 MB)
📄
7.1.tar.gz
(2.77 MB)
📄
7.1.zip
(7.4 MB)
📄
7.2.tar
(7.59 MB)
📄
7.2.tar.gz
(2.75 MB)
📄
7.2.zip
(7.4 MB)
📄
7.3.tar
(29.5 KB)
📄
7.3.tar.gz
(8.59 KB)
📄
7.3.zip
(27.73 KB)
📄
7.4.tar
(7.9 MB)
📄
7.4.tar.gz
(2.85 MB)
📄
7.4.zip
(7.7 MB)
📄
7.6.2.tar
(9.86 MB)
📄
7.6.2.tar.gz
(3.74 MB)
📄
7.6.2.zip
(9.66 MB)
📄
7.7.tar
(8.96 MB)
📄
7.7.tar.gz
(3.33 MB)
📄
7.7.zip
(8.76 MB)
📄
7.png.png.tar.gz
(42.87 KB)
📄
7.png.tar
(45 KB)
📄
7.tar
(9 KB)
📄
7.tar.gz
(286 B)
📄
7.txt.tar
(71 KB)
📄
7.txt.txt.tar.gz
(21.16 KB)
📄
7.zip
(1.06 KB)
📄
70-joystick.hwdb.hwdb.tar.gz
(942 B)
📄
70-joystick.hwdb.tar
(6 KB)
📄
70-joystick.rules.rules.tar.gz
(367 B)
📄
70-joystick.rules.tar
(2 KB)
📄
70-mouse.hwdb.hwdb.tar.gz
(5.75 KB)
📄
70-mouse.hwdb.tar
(50 KB)
📄
70-mouse.rules.rules.tar.gz
(418 B)
📄
70-mouse.rules.tar
(2.5 KB)
📄
70-nvmf-autoconnect.rules.rules.tar.gz
(594 B)
📄
70-nvmf-autoconnect.rules.tar
(3 KB)
📄
70-touchpad.hwdb.hwdb.tar.gz
(957 B)
📄
70-touchpad.hwdb.tar
(7 KB)
📄
70-touchpad.rules.rules.tar.gz
(368 B)
📄
70-touchpad.rules.tar
(2 KB)
📄
70-uaccess.rules.rules.tar.gz
(1.22 KB)
📄
70-uaccess.rules.tar
(4.5 KB)
📄
71-prefixdevname.rules.rules.tar.gz
(326 B)
📄
71-prefixdevname.rules.tar
(2 KB)
📄
71-seat.rules.rules.tar.gz
(1.22 KB)
📄
71-seat.rules.tar
(8 KB)
📄
711624ac560e8d20dfdea2e6a54ce01ae60965.tar
(22.5 KB)
📄
711624ac560e8d20dfdea2e6a54ce01ae60965.tar.gz
(8.01 KB)
📄
71prefixdevname-tools.tar
(2 KB)
📄
71prefixdevname-tools.tar.gz
(232 B)
📄
71prefixdevname-tools.zip
(367 B)
📄
71prefixdevname.tar
(2 KB)
📄
71prefixdevname.tar.gz
(271 B)
📄
71prefixdevname.zip
(409 B)
📄
724.tar
(25.5 KB)
📄
724.tar.gz
(18.17 KB)
📄
73-idrac.rules.rules.tar.gz
(331 B)
📄
73-idrac.rules.tar
(2 KB)
📄
73-seat-late.rules.rules.tar.gz
(480 B)
📄
73-seat-late.rules.tar
(2.5 KB)
📄
7350a583a14eddaea52a09243ee5b8ff150eb8.tar
(133.5 KB)
📄
7350a583a14eddaea52a09243ee5b8ff150eb8.tar.gz
(50.03 KB)
📄
75-probe_mtd.rules.rules.tar.gz
(250 B)
📄
75-probe_mtd.rules.tar
(2 KB)
📄
772799.tar
(243.94 MB)
📄
772799.tar.gz
(44.93 MB)
📄
772799.zip
(423.31 MB)
📄
77d81bafcb99deb3d27590758213eb3b9a033f.tar
(34 KB)
📄
77d81bafcb99deb3d27590758213eb3b9a033f.tar.gz
(12.36 KB)
📄
78-sound-card.rules.rules.tar.gz
(1.83 KB)
📄
78-sound-card.rules.tar
(6.5 KB)
📄
787ebdc5b39d2510f61e8a5e6be38892c89c5c.tar
(4.57 MB)
📄
787ebdc5b39d2510f61e8a5e6be38892c89c5c.tar.gz
(777.64 KB)
📄
793410ebc20fde99.css.css.tar.gz
(7.34 KB)
📄
793410ebc20fde99.css.tar
(63.5 KB)
📄
7ac3931da6de1f3d.css.css.tar.gz
(7.24 KB)
📄
7ac3931da6de1f3d.css.tar
(59 KB)
📄
7b1ab270b281367e06af4683978955b1c55890.tar
(111.5 KB)
📄
7b1ab270b281367e06af4683978955b1c55890.tar.gz
(52.3 KB)
📄
7bef1cfbe6299e8030cd8ff20da7ccb40b4e34.tar
(38.5 KB)
📄
7bef1cfbe6299e8030cd8ff20da7ccb40b4e34.tar.gz
(18.35 KB)
📄
7za.tar
(2 KB)
📄
7za.tar.gz
(133 B)
📄
8.0.tar
(29.5 KB)
📄
8.0.tar.gz
(8.61 KB)
📄
8.0.zip
(27.8 KB)
📄
8.1.tar
(29.5 KB)
📄
8.1.tar.gz
(8.61 KB)
📄
8.1.zip
(27.8 KB)
📄
8.2.tar
(29.5 KB)
📄
8.2.tar.gz
(8.61 KB)
📄
8.2.zip
(27.8 KB)
📄
8.3.tar
(29.5 KB)
📄
8.3.tar.gz
(8.61 KB)
📄
8.3.zip
(27.8 KB)
📄
8.4.tar
(29.5 KB)
📄
8.4.tar.gz
(8.61 KB)
📄
8.4.zip
(27.8 KB)
📄
8.5.tar
(29.5 KB)
📄
8.5.tar.gz
(8.61 KB)
📄
8.5.zip
(27.8 KB)
📄
8.png.png.tar.gz
(39.62 KB)
📄
8.png.tar
(42 KB)
📄
8.tar
(82.25 MB)
📄
8.tar.gz
(286 B)
📄
8.txt.tar
(124 KB)
📄
8.txt.txt.tar.gz
(40.5 KB)
📄
8.zip
(82.23 MB)
📄
80-drivers.rules.rules.tar.gz
(392 B)
📄
80-drivers.rules.tar
(2.5 KB)
📄
80lvmmerge.tar
(9 KB)
📄
80lvmmerge.tar.gz
(2.03 KB)
📄
80lvmmerge.zip
(5.89 KB)
📄
80lvmthinpool-monitor.tar
(5.5 KB)
📄
80lvmthinpool-monitor.tar.gz
(1.12 KB)
📄
80lvmthinpool-monitor.zip
(2.62 KB)
📄
83ED.tar
(30.11 MB)
📄
83ED.tar.gz
(14.02 MB)
📄
83ED.zip
(30.1 MB)
📄
83bed284b0b0f10f4126244a154d20cab925ee.tar
(29.5 KB)
📄
83bed284b0b0f10f4126244a154d20cab925ee.tar.gz
(11.13 KB)
📄
84-nm-drivers.rules.rules.tar.gz
(424 B)
📄
84-nm-drivers.rules.tar
(2.5 KB)
📄
855b53e57aba52c5572d9fe81a2a129fcf1f2a.tar
(34 KB)
📄
855b53e57aba52c5572d9fe81a2a129fcf1f2a.tar.gz
(13.71 KB)
📄
86a19c698ee35863b41d9ab159fefac8ed499a.tar
(13.5 KB)
📄
86a19c698ee35863b41d9ab159fefac8ed499a.tar.gz
(4.43 KB)
📄
8859-1.a0-ff.uni.a0-ff.uni.tar.gz
(1.15 KB)
📄
8859-1.a0-ff.uni.tar
(6 KB)
📄
8859-10.a0-ff.uni.a0-ff.uni.tar.gz
(1.07 KB)
📄
8859-10.a0-ff.uni.tar
(12 KB)
📄
8859-13.a0-ff.uni.a0-ff.uni.tar.gz
(1.15 KB)
📄
8859-13.a0-ff.uni.tar
(11 KB)
📄
8859-14.a0-ff.uni.a0-ff.uni.tar.gz
(1.04 KB)
📄
8859-14.a0-ff.uni.tar
(12 KB)
📄
8859-15.a0-ff.uni.a0-ff.uni.tar.gz
(1.16 KB)
📄
8859-15.a0-ff.uni.tar
(11 KB)
📄
8859-2.a0-ff.uni.a0-ff.uni.tar.gz
(1.07 KB)
📄
8859-2.a0-ff.uni.tar
(6 KB)
📄
8859-3.a0-ff.uni.a0-ff.uni.tar.gz
(1.05 KB)
📄
8859-3.a0-ff.uni.tar
(6 KB)
📄
8859-4.a0-ff.uni.a0-ff.uni.tar.gz
(1.08 KB)
📄
8859-4.a0-ff.uni.tar
(6 KB)
📄
8859-5.a0-ff.uni.a0-ff.uni.tar.gz
(983 B)
📄
8859-5.a0-ff.uni.tar
(6 KB)
📄
8859-6.a0-ff.uni.a0-ff.uni.tar.gz
(708 B)
📄
8859-6.a0-ff.uni.tar
(3.5 KB)
📄
8859-7.a0-ff.uni.a0-ff.uni.tar.gz
(1.07 KB)
📄
8859-7.a0-ff.uni.tar
(5.5 KB)
📄
8859-8.a0-ff.uni.a0-ff.uni.tar.gz
(834 B)
📄
8859-8.a0-ff.uni.tar
(3.5 KB)
📄
8859-9.a0-ff.uni.a0-ff.uni.tar.gz
(1.19 KB)
📄
8859-9.a0-ff.uni.tar
(6 KB)
📄
88W8864.bin.bin.tar.gz
(83.24 KB)
📄
88W8864.bin.tar
(115.5 KB)
📄
88W8897.bin.bin.tar.gz
(328.98 KB)
📄
88W8897.bin.tar
(479.5 KB)
📄
8c3a1e4ec8941e021fa66fbcbc72dd1e753efe.tar
(13.5 KB)
📄
8c3a1e4ec8941e021fa66fbcbc72dd1e753efe.tar.gz
(3.33 KB)
📄
8f0e08ff0c2479137ea9f72938c1aa78a7d99a.tar
(177 KB)
📄
8f0e08ff0c2479137ea9f72938c1aa78a7d99a.tar.gz
(78.4 KB)
📄
8f9f9e5ddd9d9740.css.css.tar.gz
(10.43 KB)
📄
8f9f9e5ddd9d9740.css.tar
(94.5 KB)
📄
9.png.png.tar.gz
(50.99 KB)
📄
9.png.tar
(53 KB)
📄
9.tar
(9 KB)
📄
9.tar.gz
(285 B)
📄
9.txt.tar
(10.5 KB)
📄
9.txt.txt.tar.gz
(3.04 KB)
📄
9.zip
(1.06 KB)
📄
90-iprutils.rules.rules.tar.gz
(177 B)
📄
90-iprutils.rules.tar
(2 KB)
📄
90-vconsole.rules.rules.tar.gz
(449 B)
📄
90-vconsole.rules.tar
(2 KB)
📄
90-wireshark-usbmon.rules.rules.tar.gz
(158 B)
📄
90-wireshark-usbmon.rules.tar
(2 KB)
📄
9017fb4a8b5e1fe9b29401ae30182ceca6568e.tar
(18 KB)
📄
9017fb4a8b5e1fe9b29401ae30182ceca6568e.tar.gz
(5.98 KB)
📄
9032217082b55e96.css.css.tar.gz
(341 B)
📄
9032217082b55e96.css.tar
(2 KB)
📄
90btrfs.tar
(7.5 KB)
📄
90btrfs.tar.gz
(1.17 KB)
📄
90btrfs.zip
(3.38 KB)
📄
90crypt.tar
(33 KB)
📄
90crypt.tar.gz
(7.2 KB)
📄
90crypt.zip
(27.84 KB)
📄
90dm.tar
(8 KB)
📄
90dm.tar.gz
(1.51 KB)
📄
90dm.zip
(3.81 KB)
📄
90dmraid.tar
(9 KB)
📄
90dmraid.tar.gz
(2.04 KB)
📄
90dmraid.zip
(5.52 KB)
📄
90kernel-modules.tar
(8 KB)
📄
90kernel-modules.tar.gz
(1.66 KB)
📄
90kernel-modules.zip
(5.25 KB)
📄
90lvm.tar
(13.5 KB)
📄
90lvm.tar.gz
(3.47 KB)
📄
90lvm.zip
(10.42 KB)
📄
90mdraid.tar
(24.5 KB)
📄
90mdraid.tar.gz
(4.43 KB)
📄
90mdraid.zip
(15.3 KB)
📄
90multipath.tar
(12 KB)
📄
90multipath.tar.gz
(2.11 KB)
📄
90multipath.zip
(6.81 KB)
📄
90qemu-net.tar
(2.5 KB)
📄
90qemu-net.tar.gz
(455 B)
📄
90qemu-net.zip
(966 B)
📄
90qemu.tar
(3 KB)
📄
90qemu.tar.gz
(523 B)
📄
90qemu.zip
(1.17 KB)
📄
91-drm-modeset.rules.rules.tar.gz
(171 B)
📄
91-drm-modeset.rules.tar
(3 KB)
📄
91crypt-gpg.tar
(10 KB)
📄
91crypt-gpg.tar.gz
(2.66 KB)
📄
91crypt-gpg.zip
(6.99 KB)
📄
91crypt-loop.tar
(4 KB)
📄
91crypt-loop.tar.gz
(862 B)
📄
91crypt-loop.zip
(1.92 KB)
📄
92b09a8a2c28f710206b8ea53ec141efa03c4b.tar
(13.5 KB)
📄
92b09a8a2c28f710206b8ea53ec141efa03c4b.tar.gz
(3.75 KB)
📄
930-fpga.bin.bin.tar.gz
(13.74 KB)
📄
930-fpga.bin.tar
(23.5 KB)
📄
94a0f5cdbe2c37d4.css.css.tar.gz
(39.55 KB)
📄
94a0f5cdbe2c37d4.css.tar
(285 KB)
📄
95cifs.tar
(8 KB)
📄
95cifs.tar.gz
(1.86 KB)
📄
95cifs.zip
(4.5 KB)
📄
95debug.tar
(2.5 KB)
📄
95debug.tar.gz
(383 B)
📄
95debug.zip
(714 B)
📄
95fcoe-uefi.tar
(3.5 KB)
📄
95fcoe-uefi.tar.gz
(719 B)
📄
95fcoe-uefi.zip
(1.69 KB)
📄
95fcoe.tar
(18 KB)
📄
95fcoe.tar.gz
(3.91 KB)
📄
95fcoe.zip
(12.31 KB)
📄
95fstab-sys.tar
(4 KB)
📄
95fstab-sys.tar.gz
(784 B)
📄
95fstab-sys.zip
(1.85 KB)
📄
95hwdb.tar
(2.5 KB)
📄
95hwdb.tar.gz
(412 B)
📄
95hwdb.zip
(723 B)
📄
95iscsi.tar
(30.5 KB)
📄
95iscsi.tar.gz
(6.97 KB)
📄
95iscsi.zip
(26.6 KB)
📄
95lunmask.tar
(9 KB)
📄
95lunmask.tar.gz
(1.59 KB)
📄
95lunmask.zip
(5.12 KB)
📄
95nbd.tar
(11.5 KB)
📄
95nbd.tar.gz
(2.74 KB)
📄
95nbd.zip
(8.09 KB)
📄
95nfs.tar
(20 KB)
📄
95nfs.tar.gz
(5.36 KB)
📄
95nfs.zip
(15.3 KB)
📄
95nvmf.tar
(9.5 KB)
📄
95nvmf.tar.gz
(2.15 KB)
📄
95nvmf.zip
(6.79 KB)
📄
95resume.tar
(9.5 KB)
📄
95resume.tar.gz
(1.83 KB)
📄
95resume.zip
(6.39 KB)
📄
95rootfs-block.tar
(13.5 KB)
📄
95rootfs-block.tar.gz
(2.8 KB)
📄
95rootfs-block.zip
(9.85 KB)
📄
95ssh-client.tar
(4 KB)
📄
95ssh-client.tar.gz
(930 B)
📄
95ssh-client.zip
(2.18 KB)
📄
95terminfo.tar
(2.5 KB)
📄
95terminfo.tar.gz
(373 B)
📄
95terminfo.zip
(692 B)
📄
95udev-rules.tar
(8.5 KB)
📄
95udev-rules.tar.gz
(1.74 KB)
📄
95udev-rules.zip
(5.22 KB)
📄
95virtfs.tar
(6 KB)
📄
95virtfs.tar.gz
(1.28 KB)
📄
95virtfs.zip
(3.29 KB)
📄
9600.bin.bin.tar.gz
(2.76 KB)
📄
9600.bin.tar
(7 KB)
📄
97biosdevname.tar
(3 KB)
📄
97biosdevname.tar.gz
(402 B)
📄
97biosdevname.zip
(912 B)
📄
98-kexec.rules.rules.tar.gz
(430 B)
📄
98-kexec.rules.tar
(2.5 KB)
📄
98a21e77d9d88ce1be5e8633fdb77e24ac5009.tar
(18.5 KB)
📄
98a21e77d9d88ce1be5e8633fdb77e24ac5009.tar.gz
(6.89 KB)
📄
98dracut-systemd.tar
(75.5 KB)
📄
98dracut-systemd.tar.gz
(9.16 KB)
📄
98dracut-systemd.zip
(51.31 KB)
📄
98ecryptfs.tar
(8.5 KB)
📄
98ecryptfs.tar.gz
(1.85 KB)
📄
98ecryptfs.zip
(5.66 KB)
📄
98pollcdrom.tar
(3.5 KB)
📄
98pollcdrom.tar.gz
(614 B)
📄
98pollcdrom.zip
(1.11 KB)
📄
98selinux.tar
(5 KB)
📄
98selinux.tar.gz
(991 B)
📄
98selinux.zip
(2.72 KB)
📄
98syslog.tar
(12 KB)
📄
98syslog.tar.gz
(2.27 KB)
📄
98syslog.zip
(6.75 KB)
📄
98usrmount.tar
(6.5 KB)
📄
98usrmount.tar.gz
(1.42 KB)
📄
98usrmount.zip
(4.1 KB)
📄
99-default.link.link.tar.gz
(396 B)
📄
99-default.link.tar
(2 KB)
📄
99-environment.conf.conf.tar.gz
(102 B)
📄
99-environment.conf.tar
(1.5 KB)
📄
99-nfs.rules.rules.tar.gz
(197 B)
📄
99-nfs.rules.tar
(2 KB)
📄
99-qemu-guest-agent.rules.rules.tar.gz
(222 B)
📄
99-qemu-guest-agent.rules.tar
(2 KB)
📄
99-systemd.rules.rules.tar.gz
(1.71 KB)
📄
99-systemd.rules.tar
(6 KB)
📄
99-vmware-scsi-udev.rules.rules.tar.gz
(343 B)
📄
99-vmware-scsi-udev.rules.tar
(2 KB)
📄
99base.tar
(58 KB)
📄
99base.tar.gz
(15.16 KB)
📄
99base.zip
(52.62 KB)
📄
99earlykdump.tar
(6 KB)
📄
99earlykdump.tar.gz
(1.29 KB)
📄
99earlykdump.zip
(3.86 KB)
📄
99fs-lib.tar
(10.5 KB)
📄
99fs-lib.tar.gz
(2.68 KB)
📄
99fs-lib.zip
(8.2 KB)
📄
99kdumpbase.tar
(53 KB)
📄
99kdumpbase.tar.gz
(13.63 KB)
📄
99kdumpbase.zip
(47.87 KB)
📄
99memstrack.tar
(7 KB)
📄
99memstrack.tar.gz
(1.41 KB)
📄
99memstrack.zip
(3.73 KB)
📄
99shutdown.tar
(6.5 KB)
📄
99shutdown.tar.gz
(1.5 KB)
📄
99shutdown.zip
(3.92 KB)
📄
99squash.tar
(6.5 KB)
📄
99squash.tar.gz
(1.45 KB)
📄
99squash.zip
(3.62 KB)
📄
99uefi-lib.tar
(7.5 KB)
📄
99uefi-lib.tar.gz
(1.54 KB)
📄
99uefi-lib.zip
(5.13 KB)
📄
9a3a2c56bcdc5a5af04830fd0c3656b5bc2239.tar
(15.5 KB)
📄
9a3a2c56bcdc5a5af04830fd0c3656b5bc2239.tar.gz
(3.87 KB)
📄
9cb22e3299444ab5.css.css.tar.gz
(1.32 KB)
📄
9cb22e3299444ab5.css.tar
(10 KB)
📄
9d1dc99ccf7c23790369e372ba3bb588abb308.tar
(29.5 KB)
📄
9d1dc99ccf7c23790369e372ba3bb588abb308.tar.gz
(10.18 KB)
📄
9feba1c1cc1ce3fec20aea047ed966c06ff181.tar
(99 KB)
📄
9feba1c1cc1ce3fec20aea047ed966c06ff181.tar.gz
(36.35 KB)
📄
ANSI_X3.110.so.110.so.tar.gz
(8.81 KB)
📄
ANSI_X3.110.so.tar
(25.5 KB)
📄
AR6002.tar
(102.5 KB)
📄
AR6002.tar.gz
(87.54 KB)
📄
AR6002.zip
(98.8 KB)
📄
AR6003.1.tar
(95 KB)
📄
AR6003.1.tar.gz
(73.95 KB)
📄
AR6003.1.zip
(89.58 KB)
📄
AR6003.tar
(536.5 KB)
📄
AR6003.tar.gz
(446.54 KB)
📄
AR6003.zip
(523.37 KB)
📄
AR6004.tar
(116.5 KB)
📄
AR6004.tar.gz
(91.39 KB)
📄
AR6004.zip
(113.92 KB)
📄
ARMSCII-8.so.so.tar.gz
(5.44 KB)
📄
ARMSCII-8.so.tar
(13.5 KB)
📄
ARUBA_me.bin.bin.tar.gz
(3.44 KB)
📄
ARUBA_me.bin.tar
(10 KB)
📄
ARUBA_pfp.bin.bin.tar.gz
(2.62 KB)
📄
ARUBA_pfp.bin.tar
(10 KB)
📄
ARUBA_rlc.bin.bin.tar.gz
(3.01 KB)
📄
ARUBA_rlc.bin.tar
(7.5 KB)
📄
ASMO_449.so.so.tar.gz
(5.58 KB)
📄
ASMO_449.so.tar
(13.5 KB)
📄
AUTHORS.tar
(28 KB)
📄
AUTHORS.tar.gz
(11.88 KB)
📄
ActiefGrotesque-Bold.10832e10.woff2.10832e10.woff2.tar.gz
(26.98 KB)
📄
ActiefGrotesque-Bold.10832e10.woff2.tar
(28.5 KB)
📄
ActiefGrotesque-Bold.7ded28bd.woff.7ded28bd.woff.tar.gz
(34.02 KB)
📄
ActiefGrotesque-Bold.7ded28bd.woff.tar
(35.5 KB)
📄
ActiefGrotesque-Medium.1acd899d.woff2.1acd899d.woff2.tar.gz
(28.16 KB)
📄
ActiefGrotesque-Medium.1acd899d.woff2.tar
(29.5 KB)
📄
ActiefGrotesque-Medium.cab39769.woff.cab39769.woff.tar.gz
(35.47 KB)
📄
ActiefGrotesque-Medium.cab39769.woff.tar
(37 KB)
📄
ActiefGrotesque-Regular.1f5abb93.woff.1f5abb93.woff.tar.gz
(34.59 KB)
📄
ActiefGrotesque-Regular.1f5abb93.woff.tar
(36 KB)
📄
ActiefGrotesque-Regular.f4e76979.woff2.f4e76979.woff2.tar.gz
(27.51 KB)
📄
ActiefGrotesque-Regular.f4e76979.woff2.tar
(29 KB)
📄
ActiefGrotesque_W_Medium.7e37a161.woff.7e37a161.woff.tar.gz
(31.46 KB)
📄
ActiefGrotesque_W_Medium.7e37a161.woff.tar
(33 KB)
📄
ActiefGrotesque_W_Regular.458577e8.woff.458577e8.woff.tar.gz
(30.5 KB)
📄
ActiefGrotesque_W_Regular.458577e8.woff.tar
(32 KB)
📄
Activate.ps1.ps1.tar.gz
(2.97 KB)
📄
Activate.ps1.tar
(20 KB)
📄
AdminGeneral_Help.html.html.tar.gz
(4.84 KB)
📄
AdminGeneral_Help.html.tar
(20 KB)
📄
Alien.tar
(5 KB)
📄
Alien.tar.gz
(1.3 KB)
📄
Alien.zip
(2.79 KB)
📄
App.php.php.tar.gz
(2.5 KB)
📄
App.php.tar
(9.5 KB)
📄
AthrBT_0x01020001.dfu.dfu.tar.gz
(38.55 KB)
📄
AthrBT_0x01020001.dfu.tar
(55.5 KB)
📄
AthrBT_0x01020200.dfu.dfu.tar.gz
(29.05 KB)
📄
AthrBT_0x01020200.dfu.tar
(41.5 KB)
📄
AthrBT_0x01020201.dfu.dfu.tar.gz
(34.02 KB)
📄
AthrBT_0x01020201.dfu.tar
(49 KB)
📄
AthrBT_0x11020000.dfu.dfu.tar.gz
(25.19 KB)
📄
AthrBT_0x11020000.dfu.tar
(37.5 KB)
📄
AthrBT_0x11020100.dfu.dfu.tar.gz
(25.2 KB)
📄
AthrBT_0x11020100.dfu.tar
(47.5 KB)
📄
AthrBT_0x31010000.dfu.dfu.tar.gz
(29.02 KB)
📄
AthrBT_0x31010000.dfu.tar
(82 KB)
📄
AthrBT_0x31010100.dfu.dfu.tar.gz
(19.62 KB)
📄
AthrBT_0x31010100.dfu.tar
(38.5 KB)
📄
AthrBT_0x41020000.dfu.dfu.tar.gz
(20.22 KB)
📄
AthrBT_0x41020000.dfu.tar
(32.5 KB)
📄
AutoComplete.py.py.tar.gz
(2.69 KB)
📄
AutoComplete.py.tar
(10.5 KB)
📄
AutoCompleteWindow.py.py.tar.gz
(4.29 KB)
📄
AutoCompleteWindow.py.tar
(18.5 KB)
📄
B.pm.pm.tar.gz
(10.57 KB)
📄
B.pm.tar
(32.5 KB)
📄
B.so.so.tar.gz
(32.24 KB)
📄
B.so.tar
(90 KB)
📄
B.tar
(173.5 KB)
📄
B.tar.gz
(32.22 KB)
📄
B.zip
(168.82 KB)
📄
BARTS_mc.bin.bin.tar.gz
(9.24 KB)
📄
BARTS_mc.bin.tar
(25.5 KB)
📄
BARTS_me.bin.bin.tar.gz
(2.95 KB)
📄
BARTS_me.bin.tar
(7 KB)
📄
BARTS_pfp.bin.bin.tar.gz
(2.22 KB)
📄
BARTS_pfp.bin.tar
(6 KB)
📄
BARTS_smc.bin.bin.tar.gz
(10.76 KB)
📄
BARTS_smc.bin.tar
(26 KB)
📄
BCM-0a5c-6410.hcd.hcd.tar.gz
(37.12 KB)
📄
BCM-0a5c-6410.hcd.tar
(55 KB)
📄
BCM-0bb4-0306.hcd.hcd.tar.gz
(37.12 KB)
📄
BCM-0bb4-0306.hcd.tar
(55 KB)
📄
BG-White.webp.tar
(9 KB)
📄
BG-White.webp.webp.tar.gz
(7.43 KB)
📄
BIG5.so.so.tar.gz
(65.25 KB)
📄
BIG5.so.tar
(89.5 KB)
📄
BIG5HKSCS.so.so.tar.gz
(90.08 KB)
📄
BIG5HKSCS.so.tar
(233.5 KB)
📄
BONAIRE_ce.bin.bin.tar.gz
(1.32 KB)
📄
BONAIRE_ce.bin.tar
(10 KB)
📄
BONAIRE_mc.bin.bin.tar.gz
(12.92 KB)
📄
BONAIRE_mc.bin.tar
(32.5 KB)
📄
BONAIRE_mc2.bin.bin.tar.gz
(13.05 KB)
📄
BONAIRE_mc2.bin.tar
(33 KB)
📄
BONAIRE_me.bin.bin.tar.gz
(3.84 KB)
📄
BONAIRE_me.bin.tar
(10 KB)
📄
BONAIRE_mec.bin.bin.tar.gz
(8.81 KB)
📄
BONAIRE_mec.bin.tar
(18 KB)
📄
BONAIRE_pfp.bin.bin.tar.gz
(3.46 KB)
📄
BONAIRE_pfp.bin.tar
(10 KB)
📄
BONAIRE_rlc.bin.bin.tar.gz
(2.54 KB)
📄
BONAIRE_rlc.bin.tar
(9.5 KB)
📄
BONAIRE_sdma.bin.bin.tar.gz
(2.21 KB)
📄
BONAIRE_sdma.bin.tar
(6 KB)
📄
BONAIRE_smc.bin.bin.tar.gz
(42.31 KB)
📄
BONAIRE_smc.bin.tar
(129 KB)
📄
BONAIRE_uvd.bin.bin.tar.gz
(154.39 KB)
📄
BONAIRE_uvd.bin.tar
(228.5 KB)
📄
BONAIRE_vce.bin.bin.tar.gz
(57.25 KB)
📄
BONAIRE_vce.bin.tar
(78 KB)
📄
BRF.so.so.tar.gz
(5.45 KB)
📄
BRF.so.tar
(13.5 KB)
📄
BTC_rlc.bin.bin.tar.gz
(924 B)
📄
BTC_rlc.bin.tar
(4.5 KB)
📄
BUILD.6.2.1.6.2.1.tar.gz
(111 B)
📄
BUILD.6.2.1.tar
(2 KB)
📄
BUILD.6.2.2.6.2.2.tar.gz
(111 B)
📄
BUILD.6.2.2.tar
(2 KB)
📄
BUILD.6.3.1.6.3.1.tar.gz
(111 B)
📄
BUILD.6.3.1.tar
(2 KB)
📄
BUILD.6.3.2.6.3.2.tar.gz
(111 B)
📄
BUILD.6.3.2.tar
(2 KB)
📄
BUILD.6.3.3.6.3.3.tar.gz
(111 B)
📄
BUILD.6.3.3.tar
(2 KB)
📄
BUILD.6.3.4.6.3.4.tar.gz
(112 B)
📄
BUILD.6.3.4.tar
(2 KB)
📄
BUILD.tar
(2 KB)
📄
BUILD.tar.gz
(106 B)
📄
Balloon.tcl.tar
(14.5 KB)
📄
Balloon.tcl.tcl.tar.gz
(3.69 KB)
📄
BaseHTTPServer.py.py.tar.gz
(7.61 KB)
📄
BaseHTTPServer.py.tar
(24 KB)
📄
BaseHTTPServer.pyc.pyc.tar.gz
(8.45 KB)
📄
BaseHTTPServer.pyc.tar
(23 KB)
📄
BaseHTTPServer.pyo.pyo.tar.gz
(8.45 KB)
📄
BaseHTTPServer.pyo.tar
(23 KB)
📄
Bastion.py.py.tar.gz
(2.23 KB)
📄
Bastion.py.tar
(7.5 KB)
📄
Bastion.pyc.pyc.tar.gz
(2.7 KB)
📄
Bastion.pyc.tar
(8.5 KB)
📄
Bastion.pyo.pyo.tar.gz
(2.7 KB)
📄
Bastion.pyo.tar
(8.5 KB)
📄
Bindings.pyc.pyc.tar.gz
(1.65 KB)
📄
Bindings.pyc.tar
(6.5 KB)
📄
Bindings.pyo.pyo.tar.gz
(1.65 KB)
📄
Bindings.pyo.tar
(6.5 KB)
📄
Bisque.cs.cs.tar.gz
(394 B)
📄
Bisque.cs.tar
(3 KB)
📄
Blue.cs.cs.tar.gz
(414 B)
📄
Blue.cs.tar
(3 KB)
📄
BtnBox.py.py.tar.gz
(892 B)
📄
BtnBox.py.tar
(3.5 KB)
📄
Button.svg.svg.tar.gz
(3.5 KB)
📄
Button.svg.tar
(10 KB)
📄
Byte.pm.pm.tar.gz
(1.16 KB)
📄
Byte.pm.tar
(4 KB)
📄
C.utf8.tar
(6.96 MB)
📄
C.utf8.tar.gz
(2.14 MB)
📄
C.utf8.zip
(6.95 MB)
📄
CACHEDIR.TAG.TAG.tar.gz
(252 B)
📄
CACHEDIR.TAG.tar
(2 KB)
📄
CAICOS_mc.bin.bin.tar.gz
(9.24 KB)
📄
CAICOS_mc.bin.tar
(25.5 KB)
📄
CAICOS_me.bin.bin.tar.gz
(2.95 KB)
📄
CAICOS_me.bin.tar
(7 KB)
📄
CAICOS_pfp.bin.bin.tar.gz
(2.23 KB)
📄
CAICOS_pfp.bin.tar
(6 KB)
📄
CAICOS_smc.bin.bin.tar.gz
(10.68 KB)
📄
CAICOS_smc.bin.tar
(25.5 KB)
📄
CAYMAN_mc.bin.bin.tar.gz
(9.36 KB)
📄
CAYMAN_mc.bin.tar
(25.5 KB)
📄
CAYMAN_me.bin.bin.tar.gz
(3.27 KB)
📄
CAYMAN_me.bin.tar
(10 KB)
📄
CAYMAN_pfp.bin.bin.tar.gz
(2.46 KB)
📄
CAYMAN_pfp.bin.tar
(10 KB)
📄
CAYMAN_rlc.bin.bin.tar.gz
(2.08 KB)
📄
CAYMAN_rlc.bin.tar
(5.5 KB)
📄
CAYMAN_smc.bin.bin.tar.gz
(13.75 KB)
📄
CAYMAN_smc.bin.tar
(32 KB)
📄
CDROM.py.py.tar.gz
(1.83 KB)
📄
CDROM.py.tar
(6.5 KB)
📄
CEDAR_me.bin.bin.tar.gz
(3.09 KB)
📄
CEDAR_me.bin.tar
(7 KB)
📄
CEDAR_pfp.bin.bin.tar.gz
(2.08 KB)
📄
CEDAR_pfp.bin.tar
(6 KB)
📄
CEDAR_rlc.bin.bin.tar.gz
(870 B)
📄
CEDAR_rlc.bin.tar
(4.5 KB)
📄
CEDAR_smc.bin.bin.tar.gz
(10.49 KB)
📄
CEDAR_smc.bin.tar
(25 KB)
📄
CGIHTTPServer.pyc.pyc.tar.gz
(5.36 KB)
📄
CGIHTTPServer.pyc.tar
(12.5 KB)
📄
CGIHTTPServer.pyo.pyo.tar.gz
(5.36 KB)
📄
CGIHTTPServer.pyo.tar
(12.5 KB)
📄
CGI_Context.html.html.tar.gz
(7.18 KB)
📄
CGI_Context.html.tar
(33 KB)
📄
CHANGELOG.md.md.tar.gz
(50.36 KB)
📄
CHANGELOG.md.tar
(315 KB)
📄
CLGRP.conf.php.conf.php.tar.gz
(551 B)
📄
CLGRP.conf.php.tar
(2.5 KB)
📄
CMV4p.bin.v2.bin.v2.tar.gz
(184 B)
📄
CMV4p.bin.v2.tar
(2 KB)
📄
CMV9i.bin.bin.tar.gz
(160 B)
📄
CMV9i.bin.tar
(2 KB)
📄
CMV9p.bin.bin.tar.gz
(156 B)
📄
CMV9p.bin.tar
(2 KB)
📄
CMVei.bin.bin.tar.gz
(224 B)
📄
CMVei.bin.tar
(2 KB)
📄
CMVeiWO.bin.bin.tar.gz
(230 B)
📄
CMVeiWO.bin.tar
(2 KB)
📄
CMVep.bin.bin.tar.gz
(234 B)
📄
CMVep.bin.tar
(2 KB)
📄
CMVepES.bin.bin.tar.gz
(237 B)
📄
CMVepES.bin.tar
(2 KB)
📄
CMVepFR.bin.bin.tar.gz
(227 B)
📄
CMVepFR.bin.tar
(2 KB)
📄
CMVepIT.bin.bin.tar.gz
(243 B)
📄
CMVepIT.bin.tar
(2 KB)
📄
CMVepWO.bin.bin.tar.gz
(227 B)
📄
CMVepWO.bin.tar
(2 KB)
📄
CN.pm.pm.tar.gz
(1.15 KB)
📄
CN.pm.tar
(3.5 KB)
📄
CN.tar
(7.5 KB)
📄
CN.tar.gz
(1.87 KB)
📄
CN.zip
(6.08 KB)
📄
COMpad2.cis.cis.tar.gz
(203 B)
📄
COMpad2.cis.tar
(2 KB)
📄
COMpad4.cis.cis.tar.gz
(180 B)
📄
COMpad4.cis.tar
(2 KB)
📄
CONTRIBUTING.md.md.tar.gz
(3.75 KB)
📄
CONTRIBUTING.md.tar
(11 KB)
📄
CObjView.tcl.tar
(9.5 KB)
📄
CObjView.tcl.tcl.tar.gz
(2.28 KB)
📄
CP10007.so.so.tar.gz
(6.02 KB)
📄
CP10007.so.tar
(13.5 KB)
📄
CP1125.so.so.tar.gz
(6.02 KB)
📄
CP1125.so.tar
(13.5 KB)
📄
CP1250.so.so.tar.gz
(6.09 KB)
📄
CP1250.so.tar
(13.5 KB)
📄
CP1251.so.so.tar.gz
(6.03 KB)
📄
CP1251.so.tar
(13.5 KB)
📄
CP1252.so.so.tar.gz
(6.03 KB)
📄
CP1252.so.tar
(13.5 KB)
📄
CP1253.so.so.tar.gz
(5.97 KB)
📄
CP1253.so.tar
(13.5 KB)
📄
CP1254.so.so.tar.gz
(6.04 KB)
📄
CP1254.so.tar
(13.5 KB)
📄
CP1255.so.so.tar.gz
(8.17 KB)
📄
CP1255.so.tar
(17.5 KB)
📄
CP1256.so.so.tar.gz
(6.12 KB)
📄
CP1256.so.tar
(13.5 KB)
📄
CP1257.so.so.tar.gz
(6.07 KB)
📄
CP1257.so.tar
(13.5 KB)
📄
CP1258.so.so.tar.gz
(9.12 KB)
📄
CP1258.so.tar
(21.5 KB)
📄
CP737.so.so.tar.gz
(6.08 KB)
📄
CP737.so.tar
(13.5 KB)
📄
CP770.so.so.tar.gz
(6.18 KB)
📄
CP770.so.tar
(13.5 KB)
📄
CP771.so.so.tar.gz
(6.02 KB)
📄
CP771.so.tar
(13.5 KB)
📄
CP772.so.so.tar.gz
(6.1 KB)
📄
CP772.so.tar
(13.5 KB)
📄
CP773.so.so.tar.gz
(6.09 KB)
📄
CP773.so.tar
(13.5 KB)
📄
CP774.so.so.tar.gz
(6.18 KB)
📄
CP774.so.tar
(13.5 KB)
📄
CP775.so.so.tar.gz
(6.15 KB)
📄
CP775.so.tar
(13.5 KB)
📄
CP932.so.so.tar.gz
(42.29 KB)
📄
CP932.so.tar
(97.5 KB)
📄
CSN_369103.so.so.tar.gz
(6.03 KB)
📄
CSN_369103.so.tar
(13.5 KB)
📄
CWI.so.so.tar.gz
(6.13 KB)
📄
CWI.so.tar
(13.5 KB)
📄
CYPRESS_me.bin.bin.tar.gz
(3.08 KB)
📄
CYPRESS_me.bin.tar
(7 KB)
📄
CYPRESS_pfp.bin.bin.tar.gz
(2.27 KB)
📄
CYPRESS_pfp.bin.tar
(6 KB)
📄
CYPRESS_rlc.bin.bin.tar.gz
(878 B)
📄
CYPRESS_rlc.bin.tar
(4.5 KB)
📄
CYPRESS_smc.bin.bin.tar.gz
(10.91 KB)
📄
CYPRESS_smc.bin.tar
(26 KB)
📄
CYPRESS_uvd.bin.bin.tar.gz
(77.11 KB)
📄
CYPRESS_uvd.bin.tar
(115 KB)
📄
CallTips.pyc.pyc.tar.gz
(3.66 KB)
📄
CallTips.pyc.tar
(9.5 KB)
📄
CallTips.pyo.pyo.tar.gz
(3.66 KB)
📄
CallTips.pyo.tar
(9.5 KB)
📄
ChangeLog.tar
(57 KB)
📄
ChangeLog.tar.gz
(18.2 KB)
📄
ChkList.tcl.tar
(6.5 KB)
📄
ChkList.tcl.tcl.tar.gz
(1.54 KB)
📄
ClassBrowser.py.py.tar.gz
(2.15 KB)
📄
ClassBrowser.py.tar
(8.5 KB)
📄
Clone.pm.pm.tar.gz
(1.27 KB)
📄
Clone.pm.tar
(4 KB)
📄
CmpImg.py.py.tar.gz
(1.67 KB)
📄
CmpImg.py.tar
(9 KB)
📄
CodeContext.pyc.pyc.tar.gz
(3.19 KB)
📄
CodeContext.pyc.tar
(8.5 KB)
📄
CodeContext.pyo.pyo.tar.gz
(3.15 KB)
📄
CodeContext.pyo.tar
(8 KB)
📄
CodingStyle.tar
(6 KB)
📄
CodingStyle.tar.gz
(1.73 KB)
📄
ColorDelegator.pyc.pyc.tar.gz
(3.92 KB)
📄
ColorDelegator.pyc.tar
(10.5 KB)
📄
ColorDelegator.pyo.pyo.tar.gz
(3.92 KB)
📄
ColorDelegator.pyo.tar
(10.5 KB)
📄
ComboBox.tcl.tar
(37 KB)
📄
ComboBox.tcl.tcl.tar.gz
(7.62 KB)
📄
Common.pm.pm.tar.gz
(1.34 KB)
📄
Common.pm.tar
(10 KB)
📄
Complex.py.py.tar.gz
(2.77 KB)
📄
Complex.py.tar
(11.5 KB)
📄
Concise.pm.pm.tar.gz
(21.64 KB)
📄
Concise.pm.tar
(61 KB)
📄
Conf.php.php.tar.gz
(922 B)
📄
Conf.php.tar
(4 KB)
📄
Config.php.php.tar.gz
(1.19 KB)
📄
Config.php.tar
(4 KB)
📄
Config.pm.pm.tar.gz
(1.53 KB)
📄
Config.pm.tar
(66.5 KB)
📄
Config.pod.pod.tar.gz
(49.15 KB)
📄
Config.pod.tar
(252.5 KB)
📄
ConfigParser.py.py.tar.gz
(6.89 KB)
📄
ConfigParser.py.tar
(29 KB)
📄
Config_git.pl.pl.tar.gz
(283 B)
📄
Config_git.pl.tar
(2 KB)
📄
Config_heavy.pl.pl.tar.gz
(16.15 KB)
📄
Config_heavy.pl.tar
(57 KB)
📄
Console.tcl.tar
(16.5 KB)
📄
Console.tcl.tcl.tar.gz
(4.57 KB)
📄
Control.tcl.tar
(14 KB)
📄
Control.tcl.tcl.tar.gz
(3.56 KB)
📄
Cookie.py.py.tar.gz
(8.75 KB)
📄
Cookie.py.tar
(27.5 KB)
📄
Cookie.pyc.pyc.tar.gz
(8.95 KB)
📄
Cookie.pyc.tar
(24 KB)
📄
Cookie.pyo.pyo.tar.gz
(8.95 KB)
📄
Cookie.pyo.tar
(24 KB)
📄
Coroutine.pyc.pyc.tar.gz
(1.55 KB)
📄
Coroutine.pyc.tar
(6 KB)
📄
Coroutine.pyo.pyo.tar.gz
(1.55 KB)
📄
Coroutine.pyo.tar
(6 KB)
📄
Crypt.tar
(28 KB)
📄
Crypt.tar.gz
(8.12 KB)
📄
Crypt.zip
(21.99 KB)
📄
DEC-MCS.so.so.tar.gz
(5.95 KB)
📄
DEC-MCS.so.tar
(13.5 KB)
📄
DECkeysym.h.h.tar.gz
(1.27 KB)
📄
DECkeysym.h.tar
(4.5 KB)
📄
DEFAULT.tar
(229 KB)
📄
DEFAULT.tar.gz
(66.02 KB)
📄
DEFAULT.zip
(215.11 KB)
📄
DIR_COLORS.tar
(6 KB)
📄
DIR_COLORS.tar.gz
(2.04 KB)
📄
DLFCN.py.py.tar.gz
(709 B)
📄
DLFCN.py.tar
(3.5 KB)
📄
DP83903.cis.cis.tar.gz
(229 B)
📄
DP83903.cis.tar
(2 KB)
📄
DSP4p.bin.bin.tar.gz
(203.27 KB)
📄
DSP4p.bin.tar
(447.5 KB)
📄
DSP9i.bin.bin.tar.gz
(156.24 KB)
📄
DSP9i.bin.tar
(333.5 KB)
📄
DSP9p.bin.bin.tar.gz
(205.3 KB)
📄
DSP9p.bin.tar
(428.5 KB)
📄
DSPei.bin.bin.tar.gz
(212.74 KB)
📄
DSPei.bin.tar
(438.5 KB)
📄
DSPep.bin.bin.tar.gz
(209.02 KB)
📄
DSPep.bin.tar
(419.5 KB)
📄
Database.php.php.tar.gz
(1.5 KB)
📄
Database.php.tar
(8 KB)
📄
Dates.py.py.tar.gz
(2.92 KB)
📄
Dates.py.tar
(9.5 KB)
📄
Db.php.php.tar.gz
(738 B)
📄
Db.php.tar
(4 KB)
📄
Dbm.pyc.pyc.tar.gz
(1.08 KB)
📄
Dbm.pyc.tar
(4 KB)
📄
Dbm.pyo.pyo.tar.gz
(1.08 KB)
📄
Dbm.pyo.tar
(4 KB)
📄
Debugger.pyc.pyc.tar.gz
(6.53 KB)
📄
Debugger.pyc.tar
(19 KB)
📄
Debugger.pyo.pyo.tar.gz
(6.53 KB)
📄
Debugger.pyo.tar
(19 KB)
📄
DefSchm.tcl.tar
(4.5 KB)
📄
DefSchm.tcl.tcl.tar.gz
(948 B)
📄
Delegator.py.py.tar.gz
(365 B)
📄
Delegator.py.tar
(2.5 KB)
📄
Delegator.pyc.pyc.tar.gz
(629 B)
📄
Delegator.pyc.tar
(3 KB)
📄
Delegator.pyo.pyo.tar.gz
(629 B)
📄
Delegator.pyo.tar
(3 KB)
📄
Demo.tar
(3.12 MB)
📄
Demo.tar.gz
(769.83 KB)
📄
Demo.zip
(2.72 MB)
📄
Devel.tar
(40 KB)
📄
Devel.tar.gz
(6.79 KB)
📄
Devel.zip
(37.56 KB)
📄
DialogS.tcl.tar
(6 KB)
📄
DialogS.tcl.tcl.tar.gz
(1.68 KB)
📄
Dir.pm.pm.tar.gz
(2.23 KB)
📄
Dir.pm.tar
(7 KB)
📄
DirList.tcl.tar
(8.5 KB)
📄
DirList.tcl.tcl.tar.gz
(2.16 KB)
📄
DirTree.tcl.tar
(10.5 KB)
📄
DirTree.tcl.tcl.tar.gz
(2.72 KB)
📄
DocXMLRPCServer.py.py.tar.gz
(3.19 KB)
📄
DocXMLRPCServer.py.tar
(12.5 KB)
📄
Document.pm.pm.tar.gz
(4.95 KB)
📄
Document.pm.tar
(17.5 KB)
📄
Document.pod.pod.tar.gz
(6.43 KB)
📄
Document.pod.tar
(23 KB)
📄
DosGlob.pm.pm.tar.gz
(3.58 KB)
📄
DosGlob.pm.tar
(9.5 KB)
📄
DosGlob.tar
(9.5 KB)
📄
DosGlob.tar.gz
(3.42 KB)
📄
DosGlob.zip
(7.73 KB)
📄
DragDrop.tcl.tar
(5.5 KB)
📄
DragDrop.tcl.tcl.tar.gz
(1.29 KB)
📄
DtlList.tcl.tar
(2.5 KB)
📄
DtlList.tcl.tcl.tar.gz
(675 B)
📄
Dumper.tar
(2 KB)
📄
Dumper.tar.gz
(176 B)
📄
Dumper.zip
(257 B)
📄
DynaLoader.pm.pm.tar.gz
(9.25 KB)
📄
DynaLoader.pm.tar
(26.5 KB)
📄
EBCDIC-AT-DE-A.so.so.tar.gz
(5.58 KB)
📄
EBCDIC-AT-DE-A.so.tar
(13.5 KB)
📄
EBCDIC-AT-DE.so.so.tar.gz
(5.58 KB)
📄
EBCDIC-AT-DE.so.tar
(13.5 KB)
📄
EBCDIC-CA-FR.so.so.tar.gz
(5.65 KB)
📄
EBCDIC-CA-FR.so.tar
(13.5 KB)
📄
EBCDIC-DK-NO-A.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-DK-NO-A.so.tar
(13.5 KB)
📄
EBCDIC-DK-NO.so.so.tar.gz
(5.58 KB)
📄
EBCDIC-DK-NO.so.tar
(13.5 KB)
📄
EBCDIC-ES-A.so.so.tar.gz
(5.69 KB)
📄
EBCDIC-ES-A.so.tar
(13.5 KB)
📄
EBCDIC-ES-S.so.so.tar.gz
(5.58 KB)
📄
EBCDIC-ES-S.so.tar
(13.5 KB)
📄
EBCDIC-ES.so.so.tar.gz
(5.71 KB)
📄
EBCDIC-ES.so.tar
(13.5 KB)
📄
EBCDIC-FI-SE-A.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-FI-SE-A.so.tar
(13.5 KB)
📄
EBCDIC-FI-SE.so.so.tar.gz
(5.58 KB)
📄
EBCDIC-FI-SE.so.tar
(13.5 KB)
📄
EBCDIC-FR.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-FR.so.tar
(13.5 KB)
📄
EBCDIC-IS-FRISS.so.so.tar.gz
(5.71 KB)
📄
EBCDIC-IS-FRISS.so.tar
(13.5 KB)
📄
EBCDIC-IT.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-IT.so.tar
(13.5 KB)
📄
EBCDIC-PT.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-PT.so.tar
(13.5 KB)
📄
EBCDIC-UK.so.so.tar.gz
(5.69 KB)
📄
EBCDIC-UK.so.tar
(13.5 KB)
📄
EBCDIC-US.so.so.tar.gz
(5.57 KB)
📄
EBCDIC-US.so.tar
(13.5 KB)
📄
ECMA-CYRILLIC.so.so.tar.gz
(5.95 KB)
📄
ECMA-CYRILLIC.so.tar
(13.5 KB)
📄
ECMA144.uni.tar
(5 KB)
📄
ECMA144.uni.uni.tar.gz
(733 B)
📄
EFileBox.tcl.tar
(13 KB)
📄
EFileBox.tcl.tcl.tar.gz
(3.11 KB)
📄
EFileDlg.tcl.tar
(3.5 KB)
📄
EFileDlg.tcl.tcl.tar.gz
(860 B)
📄
ENABLE_INSTALL_TOOL.tar
(2 KB)
📄
ENABLE_INSTALL_TOOL.tar.gz
(127 B)
📄
ERRORS.tar
(3 KB)
📄
ERRORS.tar.gz
(233 B)
📄
EUC-CN.so.so.tar.gz
(8.94 KB)
📄
EUC-CN.so.tar
(21.5 KB)
📄
EUC-JISX0213.so.so.tar.gz
(8.49 KB)
📄
EUC-JISX0213.so.tar
(21.5 KB)
📄
EUC-JP-MS.so.so.tar.gz
(40.39 KB)
📄
EUC-JP-MS.so.tar
(89.5 KB)
📄
EUC-JP.so.so.tar.gz
(7.71 KB)
📄
EUC-JP.so.tar
(17.5 KB)
📄
EUC-KR.so.so.tar.gz
(7.1 KB)
📄
EUC-KR.so.tar
(17.5 KB)
📄
EUC-TW.so.so.tar.gz
(11.18 KB)
📄
EUC-TW.so.tar
(25.5 KB)
📄
EXTERN.h.h.tar.gz
(695 B)
📄
EXTERN.h.tar
(3.5 KB)
📄
EditorWindow.py.py.tar.gz
(16.94 KB)
📄
EditorWindow.py.tar
(65.5 KB)
📄
Eiffel.py.py.tar.gz
(1.38 KB)
📄
Eiffel.py.tar
(5 KB)
📄
Encode.pm.pm.tar.gz
(11.46 KB)
📄
Encode.pm.tar
(33 KB)
📄
Encode.tar
(237 KB)
📄
Encode.tar.gz
(63.02 KB)
📄
Encode.zip
(216.05 KB)
📄
Encoder.pm.pm.tar.gz
(2.46 KB)
📄
Encoder.pm.tar
(8 KB)
📄
Encodings.tar
(275 KB)
📄
Encodings.tar.gz
(150.7 KB)
📄
Encodings.zip
(256.31 KB)
📄
English.rb.rb.tar.gz
(2.21 KB)
📄
English.rb.tar
(28.5 KB)
📄
ErrNo.pod.pod.tar.gz
(481 B)
📄
ErrNo.pod.tar
(2.5 KB)
📄
Errno.pm.pm.tar.gz
(3.17 KB)
📄
Errno.pm.tar
(8.5 KB)
📄
Error.pod.pod.tar.gz
(2.4 KB)
📄
Error.pod.tar
(7.5 KB)
📄
EthMD32.DSP.bin.DSP.bin.tar.gz
(51.84 KB)
📄
EthMD32.DSP.bin.tar
(129.5 KB)
📄
EthMD32.dm.bin.dm.bin.tar.gz
(1.04 KB)
📄
EthMD32.dm.bin.tar
(17.5 KB)
📄
Event.tcl.tar
(7 KB)
📄
Event.tcl.tcl.tar.gz
(2.02 KB)
📄
ExtApp_Help.html.html.tar.gz
(3.81 KB)
📄
ExtApp_Help.html.tar
(14 KB)
📄
External_LB.html.html.tar.gz
(1.96 KB)
📄
External_LB.html.tar
(8 KB)
📄
External_LSAPI.html.html.tar.gz
(5.78 KB)
📄
External_LSAPI.html.tar
(26.5 KB)
📄
External_PL.html.html.tar.gz
(3.41 KB)
📄
External_PL.html.tar
(15 KB)
📄
External_WS.html.html.tar.gz
(3.19 KB)
📄
External_WS.html.tar
(13 KB)
📄
FILES.tar
(2 KB)
📄
FILES.tar.gz
(176 B)
📄
FS.h.h.tar.gz
(1.73 KB)
📄
FS.h.tar
(5.5 KB)
📄
FSproto.h.h.tar.gz
(3.91 KB)
📄
FSproto.h.tar
(21 KB)
📄
Fcntl.pm.pm.tar.gz
(1.92 KB)
📄
Fcntl.pm.tar
(5.5 KB)
📄
Fcntl.so.so.tar.gz
(7.71 KB)
📄
Fcntl.so.tar
(25.5 KB)
📄
Fcntl.tar
(25.5 KB)
📄
Fcntl.tar.gz
(7.69 KB)
📄
Fcntl.zip
(23.72 KB)
📄
FieldHash.pm.pm.tar.gz
(9.48 KB)
📄
FieldHash.pm.tar
(31 KB)
📄
FieldHash.tar
(21.5 KB)
📄
FieldHash.tar.gz
(7.95 KB)
📄
FieldHash.zip
(19.93 KB)
📄
File.pm.pm.tar.gz
(2.08 KB)
📄
File.pm.tar
(6.5 KB)
📄
File.tar
(64.5 KB)
📄
File.tar.gz
(8.64 KB)
📄
File.zip
(61.08 KB)
📄
FileBox.tcl.tar
(15.5 KB)
📄
FileBox.tcl.tcl.tar.gz
(3.75 KB)
📄
FileCbx.tcl.tar
(4 KB)
📄
FileCbx.tcl.tcl.tar.gz
(1.07 KB)
📄
FileDlg.tcl.tar
(4 KB)
📄
FileDlg.tcl.tcl.tar.gz
(936 B)
📄
FileEnt.tcl.tar
(9 KB)
📄
FileEnt.tcl.tcl.tar.gz
(2.25 KB)
📄
FileList.pyc.pyc.tar.gz
(1.83 KB)
📄
FileList.pyc.tar
(5.5 KB)
📄
FileList.pyo.pyo.tar.gz
(1.8 KB)
📄
FileList.pyo.tar
(5.5 KB)
📄
Filter.pm.pm.tar.gz
(1.26 KB)
📄
Filter.pm.tar
(4.5 KB)
📄
FindGLIB2.cmake.cmake.tar.gz
(1.22 KB)
📄
FindGLIB2.cmake.tar
(4.5 KB)
📄
FlexLexer.h.h.tar.gz
(2.47 KB)
📄
FlexLexer.h.tar
(8.5 KB)
📄
FloatEnt.tcl.tar
(5 KB)
📄
FloatEnt.tcl.tcl.tar.gz
(1.16 KB)
📄
FormatParagraph.py.py.tar.gz
(2.57 KB)
📄
FormatParagraph.py.tar
(9 KB)
📄
GB18030.so.so.tar.gz
(159.27 KB)
📄
GB18030.so.tar
(177.5 KB)
📄
GBBIG5.so.so.tar.gz
(33.96 KB)
📄
GBBIG5.so.tar
(57.5 KB)
📄
GBGBK.so.so.tar.gz
(5.65 KB)
📄
GBGBK.so.tar
(13.5 KB)
📄
GBK.so.so.tar.gz
(93.52 KB)
📄
GBK.so.tar
(117.5 KB)
📄
GDBM_File.pm.pm.tar.gz
(934 B)
📄
GDBM_File.pm.tar
(3.5 KB)
📄
GDBM_File.so.so.tar.gz
(9.85 KB)
📄
GDBM_File.so.tar
(29.5 KB)
📄
GDBM_File.tar
(29.5 KB)
📄
GDBM_File.tar.gz
(9.84 KB)
📄
GDBM_File.zip
(27.83 KB)
📄
GEORGIAN-ACADEMY.so.so.tar.gz
(6.03 KB)
📄
GEORGIAN-ACADEMY.so.tar
(13.5 KB)
📄
GEORGIAN-PS.so.so.tar.gz
(6.02 KB)
📄
GEORGIAN-PS.so.tar
(13.5 KB)
📄
GET.tar
(17.5 KB)
📄
GET.tar.gz
(5.42 KB)
📄
GL.zip
(101.31 KB)
📄
GLOBALS.php.php.tar.gz
(1.76 KB)
📄
GLOBALS.php.tar
(6.5 KB)
📄
GLib-2.0.typelib.0.typelib.tar.gz
(58.46 KB)
📄
GLib-2.0.typelib.tar
(183.5 KB)
📄
GModule-2.0.typelib.0.typelib.tar.gz
(725 B)
📄
GModule-2.0.typelib.tar
(3 KB)
📄
GOST_19768-74.so.so.tar.gz
(5.9 KB)
📄
GOST_19768-74.so.tar
(13.5 KB)
📄
GObject-2.0.typelib.0.typelib.tar.gz
(16 KB)
📄
GObject-2.0.typelib.tar
(59.5 KB)
📄
GREEK-CCITT.so.so.tar.gz
(5.59 KB)
📄
GREEK-CCITT.so.tar
(13.5 KB)
📄
GREEK7-OLD.so.so.tar.gz
(5.64 KB)
📄
GREEK7-OLD.so.tar
(13.5 KB)
📄
GREEK7.so.so.tar.gz
(5.6 KB)
📄
GREEK7.so.tar
(13.5 KB)
📄
GSM0338.pm.pm.tar.gz
(3.68 KB)
📄
GSM0338.pm.tar
(14.5 KB)
📄
Generator.pyc.pyc.tar.gz
(1.33 KB)
📄
Generator.pyc.tar
(5 KB)
📄
Generator.pyo.pyo.tar.gz
(1.33 KB)
📄
Generator.pyo.tar
(5 KB)
📄
Glob.pm.pm.tar.gz
(5.5 KB)
📄
Glob.pm.tar
(14.5 KB)
📄
Glob.so.so.tar.gz
(13.69 KB)
📄
Glob.so.tar
(34 KB)
📄
Glob.tar
(34 KB)
📄
Glob.tar.gz
(13.66 KB)
📄
Glob.zip
(32.45 KB)
📄
GraphicsMagick-1.3.38.tar
(2.68 MB)
📄
GraphicsMagick-1.3.38.tar.gz
(943.94 KB)
📄
GraphicsMagick-1.3.38.zip
(2.56 MB)
📄
Gray.cs.cs.tar.gz
(405 B)
📄
Gray.cs.tar
(3 KB)
📄
Grid.tcl.tar
(23 KB)
📄
Grid.tcl.tcl.tar.gz
(3.81 KB)
📄
HAINAN_ce.bin.bin.tar.gz
(1.03 KB)
📄
HAINAN_ce.bin.tar
(10 KB)
📄
HAINAN_mc.bin.bin.tar.gz
(12.83 KB)
📄
HAINAN_mc.bin.tar
(32.5 KB)
📄
HAINAN_mc2.bin.bin.tar.gz
(12.83 KB)
📄
HAINAN_mc2.bin.tar
(32.5 KB)
📄
HAINAN_me.bin.bin.tar.gz
(3.52 KB)
📄
HAINAN_me.bin.tar
(10 KB)
📄
HAINAN_pfp.bin.bin.tar.gz
(2.39 KB)
📄
HAINAN_pfp.bin.tar
(10 KB)
📄
HAINAN_rlc.bin.bin.tar.gz
(1.89 KB)
📄
HAINAN_rlc.bin.tar
(9.5 KB)
📄
HAINAN_smc.bin.bin.tar.gz
(25.36 KB)
📄
HAINAN_smc.bin.tar
(118 KB)
📄
HAWAII_ce.bin.bin.tar.gz
(1.54 KB)
📄
HAWAII_ce.bin.tar
(10 KB)
📄
HAWAII_mc.bin.bin.tar.gz
(13.42 KB)
📄
HAWAII_mc.bin.tar
(32.5 KB)
📄
HAWAII_mc2.bin.bin.tar.gz
(13.69 KB)
📄
HAWAII_mc2.bin.tar
(33.5 KB)
📄
HAWAII_me.bin.bin.tar.gz
(3.73 KB)
📄
HAWAII_me.bin.tar
(10 KB)
📄
HAWAII_mec.bin.bin.tar.gz
(8.78 KB)
📄
HAWAII_mec.bin.tar
(18 KB)
📄
HAWAII_pfp.bin.bin.tar.gz
(3.64 KB)
📄
HAWAII_pfp.bin.tar
(10 KB)
📄
HAWAII_rlc.bin.bin.tar.gz
(2.5 KB)
📄
HAWAII_rlc.bin.tar
(9.5 KB)
📄
HAWAII_sdma.bin.bin.tar.gz
(2.22 KB)
📄
HAWAII_sdma.bin.tar
(6 KB)
📄
HAWAII_smc.bin.bin.tar.gz
(44.29 KB)
📄
HAWAII_smc.bin.tar
(129 KB)
📄
HList.tcl.tar
(19.5 KB)
📄
HList.tcl.tcl.tar.gz
(3.55 KB)
📄
HListDD.tcl.tar
(6 KB)
📄
HListDD.tcl.tcl.tar.gz
(1.29 KB)
📄
HP-GREEK8.so.so.tar.gz
(5.87 KB)
📄
HP-GREEK8.so.tar
(13.5 KB)
📄
HP-ROMAN8.so.so.tar.gz
(6.02 KB)
📄
HP-ROMAN8.so.tar
(13.5 KB)
📄
HP-ROMAN9.so.so.tar.gz
(6.02 KB)
📄
HP-ROMAN9.so.tar
(13.5 KB)
📄
HP-THAI8.so.so.tar.gz
(5.94 KB)
📄
HP-THAI8.so.tar
(13.5 KB)
📄
HP-TURKISH8.so.so.tar.gz
(6.01 KB)
📄
HP-TURKISH8.so.tar
(13.5 KB)
📄
HP.tar
(844 KB)
📄
HP.tar.gz
(362.51 KB)
📄
HP.zip
(842.68 KB)
📄
HTML.tar
(90.5 KB)
📄
HTML.tar.gz
(26.69 KB)
📄
HTML.zip
(85.07 KB)
📄
HTMLParser.pyc.pyc.tar.gz
(5.34 KB)
📄
HTMLParser.pyc.tar
(15 KB)
📄
HTMLParser.pyo.pyo.tar.gz
(5.25 KB)
📄
HTMLParser.pyo.tar
(15 KB)
📄
Handle.pm.pm.tar.gz
(5.91 KB)
📄
Handle.pm.tar
(18.5 KB)
📄
Hash.php.php.tar.gz
(2.73 KB)
📄
Hash.php.tar
(9 KB)
📄
Hash.tar
(116.5 KB)
📄
Hash.tar.gz
(16.59 KB)
📄
Hash.zip
(110.96 KB)
📄
HelvNeue55_W1G-1.woff.tar
(48 KB)
📄
HelvNeue55_W1G-1.woff.woff.tar.gz
(23.04 KB)
📄
HelvNeue55_W1G-1.woff2.tar
(39 KB)
📄
HelvNeue55_W1G-1.woff2.woff2.tar.gz
(18.42 KB)
📄
HelvNeue55_W1G.eot.eot.tar.gz
(23.22 KB)
📄
HelvNeue55_W1G.eot.tar
(85 KB)
📄
HelvNeue55_W1G.svg.svg.tar.gz
(19.35 KB)
📄
HelvNeue55_W1G.svg.tar
(180 KB)
📄
HelvNeue55_W1G.ttf.tar
(85 KB)
📄
HelvNeue55_W1G.ttf.ttf.tar.gz
(23.1 KB)
📄
HelvNeue55_W1G.woff.tar
(48 KB)
📄
HelvNeue55_W1G.woff.woff.tar.gz
(23.04 KB)
📄
HelvNeue55_W1G.woff2.tar
(39 KB)
📄
HelvNeue55_W1G.woff2.woff2.tar.gz
(18.42 KB)
📄
HelvNeue75_W1G-1.woff.tar
(48 KB)
📄
HelvNeue75_W1G-1.woff.woff.tar.gz
(22.87 KB)
📄
HelvNeue75_W1G-1.woff2.tar
(39 KB)
📄
HelvNeue75_W1G-1.woff2.woff2.tar.gz
(18.26 KB)
📄
HelvNeue75_W1G.eot.eot.tar.gz
(23.03 KB)
📄
HelvNeue75_W1G.eot.tar
(82 KB)
📄
HelvNeue75_W1G.svg.svg.tar.gz
(19.6 KB)
📄
HelvNeue75_W1G.svg.tar
(183 KB)
📄
HelvNeue75_W1G.ttf.tar
(82 KB)
📄
HelvNeue75_W1G.ttf.ttf.tar.gz
(22.96 KB)
📄
HelvNeue75_W1G.woff.tar
(48 KB)
📄
HelvNeue75_W1G.woff.woff.tar.gz
(22.87 KB)
📄
HelvNeue75_W1G.woff2.tar
(39 KB)
📄
HelvNeue75_W1G.woff2.woff2.tar.gz
(18.26 KB)
📄
Hostname.pm.pm.tar.gz
(1.66 KB)
📄
Hostname.pm.tar
(5 KB)
📄
Hostname.tar
(9 KB)
📄
Hostname.tar.gz
(3.38 KB)
📄
Hostname.zip
(7.64 KB)
📄
HyperParser.pyo.pyo.tar.gz
(3.01 KB)
📄
HyperParser.pyo.tar
(8.5 KB)
📄
I18N.tar
(22 KB)
📄
I18N.tar.gz
(1.92 KB)
📄
I18N.zip
(19.77 KB)
📄
IBM037.so.so.tar.gz
(5.83 KB)
📄
IBM037.so.tar
(13.5 KB)
📄
IBM038.so.so.tar.gz
(5.57 KB)
📄
IBM038.so.tar
(13.5 KB)
📄
IBM1004.so.so.tar.gz
(6 KB)
📄
IBM1004.so.tar
(13.5 KB)
📄
IBM1008.so.so.tar.gz
(6.11 KB)
📄
IBM1008.so.tar
(13.5 KB)
📄
IBM1008_420.so.so.tar.gz
(4.14 KB)
📄
IBM1008_420.so.tar
(13.5 KB)
📄
IBM1025.so.so.tar.gz
(5.95 KB)
📄
IBM1025.so.tar
(13.5 KB)
📄
IBM1026.so.so.tar.gz
(5.99 KB)
📄
IBM1026.so.tar
(13.5 KB)
📄
IBM1046.so.so.tar.gz
(6.18 KB)
📄
IBM1046.so.tar
(13.5 KB)
📄
IBM1047.so.so.tar.gz
(5.83 KB)
📄
IBM1047.so.tar
(13.5 KB)
📄
IBM1097.so.so.tar.gz
(6.12 KB)
📄
IBM1097.so.tar
(13.5 KB)
📄
IBM1112.so.so.tar.gz
(6.01 KB)
📄
IBM1112.so.tar
(13.5 KB)
📄
IBM1122.so.so.tar.gz
(5.94 KB)
📄
IBM1122.so.tar
(13.5 KB)
📄
IBM1123.so.so.tar.gz
(5.95 KB)
📄
IBM1123.so.tar
(13.5 KB)
📄
IBM1124.so.so.tar.gz
(5.94 KB)
📄
IBM1124.so.tar
(13.5 KB)
📄
IBM1129.so.so.tar.gz
(5.99 KB)
📄
IBM1129.so.tar
(13.5 KB)
📄
IBM1130.so.so.tar.gz
(5.99 KB)
📄
IBM1130.so.tar
(13.5 KB)
📄
IBM1132.so.so.tar.gz
(5.92 KB)
📄
IBM1132.so.tar
(13.5 KB)
📄
IBM1133.so.so.tar.gz
(5.91 KB)
📄
IBM1133.so.tar
(13.5 KB)
📄
IBM1137.so.so.tar.gz
(5.97 KB)
📄
IBM1137.so.tar
(13.5 KB)
📄
IBM1140.so.so.tar.gz
(5.93 KB)
📄
IBM1140.so.tar
(13.5 KB)
📄
IBM1141.so.so.tar.gz
(5.93 KB)
📄
IBM1141.so.tar
(13.5 KB)
📄
IBM1142.so.so.tar.gz
(5.93 KB)
📄
IBM1142.so.tar
(13.5 KB)
📄
IBM1143.so.so.tar.gz
(5.93 KB)
📄
IBM1143.so.tar
(13.5 KB)
📄
IBM1144.so.so.tar.gz
(5.93 KB)
📄
IBM1144.so.tar
(13.5 KB)
📄
IBM1145.so.so.tar.gz
(5.93 KB)
📄
IBM1145.so.tar
(13.5 KB)
📄
IBM1146.so.so.tar.gz
(5.93 KB)
📄
IBM1146.so.tar
(13.5 KB)
📄
IBM1147.so.so.tar.gz
(5.94 KB)
📄
IBM1147.so.tar
(13.5 KB)
📄
IBM1148.so.so.tar.gz
(5.93 KB)
📄
IBM1148.so.tar
(13.5 KB)
📄
IBM1149.so.so.tar.gz
(5.94 KB)
📄
IBM1149.so.tar
(13.5 KB)
📄
IBM1153.so.so.tar.gz
(6.02 KB)
📄
IBM1153.so.tar
(13.5 KB)
📄
IBM1154.so.so.tar.gz
(5.95 KB)
📄
IBM1154.so.tar
(13.5 KB)
📄
IBM1155.so.so.tar.gz
(5.95 KB)
📄
IBM1155.so.tar
(13.5 KB)
📄
IBM1156.so.so.tar.gz
(6.03 KB)
📄
IBM1156.so.tar
(13.5 KB)
📄
IBM1157.so.so.tar.gz
(5.95 KB)
📄
IBM1157.so.tar
(13.5 KB)
📄
IBM1158.so.so.tar.gz
(5.95 KB)
📄
IBM1158.so.tar
(13.5 KB)
📄
IBM1160.so.so.tar.gz
(5.93 KB)
📄
IBM1160.so.tar
(13.5 KB)
📄
IBM1161.so.so.tar.gz
(5.86 KB)
📄
IBM1161.so.tar
(13.5 KB)
📄
IBM1162.so.so.tar.gz
(5.96 KB)
📄
IBM1162.so.tar
(13.5 KB)
📄
IBM1163.so.so.tar.gz
(6 KB)
📄
IBM1163.so.tar
(13.5 KB)
📄
IBM1164.so.so.tar.gz
(6 KB)
📄
IBM1164.so.tar
(13.5 KB)
📄
IBM1166.so.so.tar.gz
(6 KB)
📄
IBM1166.so.tar
(13.5 KB)
📄
IBM1167.so.so.tar.gz
(6.07 KB)
📄
IBM1167.so.tar
(13.5 KB)
📄
IBM12712.so.so.tar.gz
(5.94 KB)
📄
IBM12712.so.tar
(13.5 KB)
📄
IBM1364.so.so.tar.gz
(88.33 KB)
📄
IBM1364.so.tar
(149.5 KB)
📄
IBM1371.so.so.tar.gz
(88.67 KB)
📄
IBM1371.so.tar
(129.5 KB)
📄
IBM1388.so.so.tar.gz
(129.2 KB)
📄
IBM1388.so.tar
(173.5 KB)
📄
IBM1390.so.so.tar.gz
(95.58 KB)
📄
IBM1390.so.tar
(229.5 KB)
📄
IBM1399.so.so.tar.gz
(95.59 KB)
📄
IBM1399.so.tar
(229.5 KB)
📄
IBM16804.so.so.tar.gz
(6.13 KB)
📄
IBM16804.so.tar
(13.5 KB)
📄
IBM256.so.so.tar.gz
(5.99 KB)
📄
IBM256.so.tar
(13.5 KB)
📄
IBM273.so.so.tar.gz
(5.81 KB)
📄
IBM273.so.tar
(13.5 KB)
📄
IBM274.so.so.tar.gz
(5.56 KB)
📄
IBM274.so.tar
(13.5 KB)
📄
IBM275.so.so.tar.gz
(5.57 KB)
📄
IBM275.so.tar
(13.5 KB)
📄
IBM277.so.so.tar.gz
(5.82 KB)
📄
IBM277.so.tar
(13.5 KB)
📄
IBM278.so.so.tar.gz
(5.81 KB)
📄
IBM278.so.tar
(13.5 KB)
📄
IBM280.so.so.tar.gz
(5.82 KB)
📄
IBM280.so.tar
(13.5 KB)
📄
IBM281.so.so.tar.gz
(5.69 KB)
📄
IBM281.so.tar
(13.5 KB)
📄
IBM284.so.so.tar.gz
(5.82 KB)
📄
IBM284.so.tar
(13.5 KB)
📄
IBM285.so.so.tar.gz
(5.96 KB)
📄
IBM285.so.tar
(13.5 KB)
📄
IBM290.so.so.tar.gz
(5.87 KB)
📄
IBM290.so.tar
(13.5 KB)
📄
IBM297.so.so.tar.gz
(5.82 KB)
📄
IBM297.so.tar
(13.5 KB)
📄
IBM420.so.so.tar.gz
(6.05 KB)
📄
IBM420.so.tar
(13.5 KB)
📄
IBM423.so.so.tar.gz
(5.85 KB)
📄
IBM423.so.tar
(13.5 KB)
📄
IBM424.so.so.tar.gz
(5.88 KB)
📄
IBM424.so.tar
(13.5 KB)
📄
IBM437.so.so.tar.gz
(6.11 KB)
📄
IBM437.so.tar
(13.5 KB)
📄
IBM4517.so.so.tar.gz
(6.12 KB)
📄
IBM4517.so.tar
(13.5 KB)
📄
IBM4899.so.so.tar.gz
(5.74 KB)
📄
IBM4899.so.tar
(13.5 KB)
📄
IBM4909.so.so.tar.gz
(5.99 KB)
📄
IBM4909.so.tar
(13.5 KB)
📄
IBM4971.so.so.tar.gz
(5.99 KB)
📄
IBM4971.so.tar
(13.5 KB)
📄
IBM500.so.so.tar.gz
(5.83 KB)
📄
IBM500.so.tar
(13.5 KB)
📄
IBM5347.so.so.tar.gz
(5.99 KB)
📄
IBM5347.so.tar
(13.5 KB)
📄
IBM803.so.so.tar.gz
(5.69 KB)
📄
IBM803.so.tar
(13.5 KB)
📄
IBM850.so.so.tar.gz
(6.08 KB)
📄
IBM850.so.tar
(13.5 KB)
📄
IBM851.so.so.tar.gz
(6.1 KB)
📄
IBM851.so.tar
(13.5 KB)
📄
IBM852.so.so.tar.gz
(6.14 KB)
📄
IBM852.so.tar
(13.5 KB)
📄
IBM855.so.so.tar.gz
(6.08 KB)
📄
IBM855.so.tar
(13.5 KB)
📄
IBM856.so.so.tar.gz
(6.22 KB)
📄
IBM856.so.tar
(13.5 KB)
📄
IBM857.so.so.tar.gz
(6.08 KB)
📄
IBM857.so.tar
(13.5 KB)
📄
IBM858.so.so.tar.gz
(6.08 KB)
📄
IBM858.so.tar
(13.5 KB)
📄
IBM860.so.so.tar.gz
(6.14 KB)
📄
IBM860.so.tar
(13.5 KB)
📄
IBM861.so.so.tar.gz
(6.12 KB)
📄
IBM861.so.tar
(13.5 KB)
📄
IBM862.so.so.tar.gz
(6.12 KB)
📄
IBM862.so.tar
(13.5 KB)
📄
IBM863.so.so.tar.gz
(6.11 KB)
📄
IBM863.so.tar
(13.5 KB)
📄
IBM864.so.so.tar.gz
(6.13 KB)
📄
IBM864.so.tar
(13.5 KB)
📄
IBM865.so.so.tar.gz
(6.11 KB)
📄
IBM865.so.tar
(13.5 KB)
📄
IBM866.so.so.tar.gz
(6.03 KB)
📄
IBM866.so.tar
(13.5 KB)
📄
IBM866NAV.so.so.tar.gz
(6.02 KB)
📄
IBM866NAV.so.tar
(13.5 KB)
📄
IBM868.so.so.tar.gz
(6.09 KB)
📄
IBM868.so.tar
(13.5 KB)
📄
IBM869.so.so.tar.gz
(6.05 KB)
📄
IBM869.so.tar
(13.5 KB)
📄
IBM870.so.so.tar.gz
(5.9 KB)
📄
IBM870.so.tar
(13.5 KB)
📄
IBM871.so.so.tar.gz
(5.83 KB)
📄
IBM871.so.tar
(13.5 KB)
📄
IBM874.so.so.tar.gz
(5.89 KB)
📄
IBM874.so.tar
(13.5 KB)
📄
IBM875.so.so.tar.gz
(5.98 KB)
📄
IBM875.so.tar
(13.5 KB)
📄
IBM880.so.so.tar.gz
(5.96 KB)
📄
IBM880.so.tar
(13.5 KB)
📄
IBM891.so.so.tar.gz
(5.44 KB)
📄
IBM891.so.tar
(13.5 KB)
📄
IBM901.so.so.tar.gz
(6.24 KB)
📄
IBM901.so.tar
(13.5 KB)
📄
IBM902.so.so.tar.gz
(6.19 KB)
📄
IBM902.so.tar
(13.5 KB)
📄
IBM903.so.so.tar.gz
(5.44 KB)
📄
IBM903.so.tar
(13.5 KB)
📄
IBM9030.so.so.tar.gz
(5.92 KB)
📄
IBM9030.so.tar
(13.5 KB)
📄
IBM904.so.so.tar.gz
(5.46 KB)
📄
IBM904.so.tar
(13.5 KB)
📄
IBM905.so.so.tar.gz
(5.87 KB)
📄
IBM905.so.tar
(13.5 KB)
📄
IBM9066.so.so.tar.gz
(5.85 KB)
📄
IBM9066.so.tar
(13.5 KB)
📄
IBM918.so.so.tar.gz
(5.99 KB)
📄
IBM918.so.tar
(13.5 KB)
📄
IBM921.so.so.tar.gz
(6.01 KB)
📄
IBM921.so.tar
(13.5 KB)
📄
IBM922.so.so.tar.gz
(6.19 KB)
📄
IBM922.so.tar
(13.5 KB)
📄
IBM930.so.so.tar.gz
(75.89 KB)
📄
IBM930.so.tar
(97.5 KB)
📄
IBM932.so.so.tar.gz
(60.12 KB)
📄
IBM932.so.tar
(73.5 KB)
📄
IBM933.so.so.tar.gz
(90.42 KB)
📄
IBM933.so.tar
(117.5 KB)
📄
IBM935.so.so.tar.gz
(64.75 KB)
📄
IBM935.so.tar
(85.5 KB)
📄
IBM937.so.so.tar.gz
(88.5 KB)
📄
IBM937.so.tar
(113.5 KB)
📄
IBM939.so.so.tar.gz
(75.7 KB)
📄
IBM939.so.tar
(97.5 KB)
📄
IBM943.so.so.tar.gz
(60.59 KB)
📄
IBM943.so.tar
(73.5 KB)
📄
IBM9448.so.so.tar.gz
(6.27 KB)
📄
IBM9448.so.tar
(13.5 KB)
📄
IEC_P27-1.so.so.tar.gz
(6.11 KB)
📄
IEC_P27-1.so.tar
(13.5 KB)
📄
IN.py.py.tar.gz
(3.76 KB)
📄
IN.py.tar
(14.5 KB)
📄
IN.pyc.pyc.tar.gz
(5.86 KB)
📄
IN.pyc.tar
(22 KB)
📄
IN.pyo.pyo.tar.gz
(5.86 KB)
📄
IN.pyo.tar
(22 KB)
📄
INIS-8.so.so.tar.gz
(5.48 KB)
📄
INIS-8.so.tar
(13.5 KB)
📄
INIS-CYRILLIC.so.so.tar.gz
(5.62 KB)
📄
INIS-CYRILLIC.so.tar
(13.5 KB)
📄
INIS.so.so.tar.gz
(5.43 KB)
📄
INIS.so.tar
(13.5 KB)
📄
INSTALL.txt.tar
(5.5 KB)
📄
INSTALL.txt.txt.tar.gz
(1.69 KB)
📄
INT8866RCA2.bin.bin.tar.gz
(403 B)
📄
INT8866RCA2.bin.tar
(3 KB)
📄
INTERN.h.h.tar.gz
(581 B)
📄
INTERN.h.tar
(3 KB)
📄
IO.pm.pm.tar.gz
(876 B)
📄
IO.pm.tar
(3 KB)
📄
IO.so.so.tar.gz
(8.25 KB)
📄
IO.so.tar
(21.5 KB)
📄
IO.tar
(134.5 KB)
📄
IO.tar.gz
(23.03 KB)
📄
IO.zip
(124.9 KB)
📄
IOBinding.py.py.tar.gz
(5.92 KB)
📄
IOBinding.py.tar
(23 KB)
📄
IOBinding.pyc.pyc.tar.gz
(7.27 KB)
📄
IOBinding.pyc.tar
(20 KB)
📄
IOBinding.pyo.pyo.tar.gz
(7.27 KB)
📄
IOBinding.pyo.tar
(20 KB)
📄
IPQ5018.tar
(4.02 MB)
📄
IPQ5018.tar.gz
(2.14 MB)
📄
IPQ5018.zip
(4.01 MB)
📄
IPQ6018.tar
(4.73 MB)
📄
IPQ6018.tar.gz
(2.23 MB)
📄
IPQ6018.zip
(4.72 MB)
📄
IPQ8074.tar
(6.7 MB)
📄
IPQ8074.tar.gz
(2.83 MB)
📄
IPQ8074.zip
(6.69 MB)
📄
ISIRI-3342.so.so.tar.gz
(5.91 KB)
📄
ISIRI-3342.so.tar
(13.5 KB)
📄
ISO-2022-CN-EXT.so.so.tar.gz
(19.25 KB)
📄
ISO-2022-CN-EXT.so.tar
(41.5 KB)
📄
ISO-2022-CN.so.so.tar.gz
(15.92 KB)
📄
ISO-2022-CN.so.tar
(37.5 KB)
📄
ISO-2022-JP-3.so.so.tar.gz
(13.35 KB)
📄
ISO-2022-JP-3.so.tar
(29.5 KB)
📄
ISO-2022-JP.so.so.tar.gz
(21.01 KB)
📄
ISO-2022-JP.so.tar
(45.5 KB)
📄
ISO-2022-KR.so.so.tar.gz
(7.84 KB)
📄
ISO-2022-KR.so.tar
(17.5 KB)
📄
ISO-IR-197.so.so.tar.gz
(6.05 KB)
📄
ISO-IR-197.so.tar
(13.5 KB)
📄
ISO-IR-209.so.so.tar.gz
(6.06 KB)
📄
ISO-IR-209.so.tar
(13.5 KB)
📄
ISO646.so.so.tar.gz
(9.63 KB)
📄
ISO646.so.tar
(21.5 KB)
📄
ISO8859-1.so.so.tar.gz
(4.92 KB)
📄
ISO8859-1.so.tar
(13.5 KB)
📄
ISO8859-10.so.so.tar.gz
(6.02 KB)
📄
ISO8859-10.so.tar
(13.5 KB)
📄
ISO8859-11.so.so.tar.gz
(5.94 KB)
📄
ISO8859-11.so.tar
(13.5 KB)
📄
ISO8859-13.so.so.tar.gz
(6.02 KB)
📄
ISO8859-13.so.tar
(13.5 KB)
📄
ISO8859-14.so.so.tar.gz
(6.02 KB)
📄
ISO8859-14.so.tar
(13.5 KB)
📄
ISO8859-15.so.so.tar.gz
(5.96 KB)
📄
ISO8859-15.so.tar
(13.5 KB)
📄
ISO8859-16.so.so.tar.gz
(6.03 KB)
📄
ISO8859-16.so.tar
(13.5 KB)
📄
ISO8859-2.so.so.tar.gz
(5.9 KB)
📄
ISO8859-2.so.tar
(13.5 KB)
📄
ISO8859-3.so.so.tar.gz
(5.88 KB)
📄
ISO8859-3.so.tar
(13.5 KB)
📄
ISO8859-4.so.so.tar.gz
(5.9 KB)
📄
ISO8859-4.so.tar
(13.5 KB)
📄
ISO8859-5.so.so.tar.gz
(5.95 KB)
📄
ISO8859-5.so.tar
(13.5 KB)
📄
ISO8859-6.so.so.tar.gz
(5.77 KB)
📄
ISO8859-6.so.tar
(17.5 KB)
📄
ISO8859-7.so.so.tar.gz
(5.99 KB)
📄
ISO8859-7.so.tar
(13.5 KB)
📄
ISO8859-8.so.so.tar.gz
(5.89 KB)
📄
ISO8859-8.so.tar
(13.5 KB)
📄
ISO8859-9.so.so.tar.gz
(5.85 KB)
📄
ISO8859-9.so.tar
(13.5 KB)
📄
ISO8859-9E.so.so.tar.gz
(6.04 KB)
📄
ISO8859-9E.so.tar
(13.5 KB)
📄
ISO_10367-BOX.so.so.tar.gz
(5.85 KB)
📄
ISO_10367-BOX.so.tar
(13.5 KB)
📄
ISO_11548-1.so.so.tar.gz
(4.93 KB)
📄
ISO_11548-1.so.tar
(13.5 KB)
📄
ISO_2033.so.so.tar.gz
(5.33 KB)
📄
ISO_2033.so.tar
(13.5 KB)
📄
ISO_5427-EXT.so.so.tar.gz
(5.47 KB)
📄
ISO_5427-EXT.so.tar
(13.5 KB)
📄
ISO_5427.so.so.tar.gz
(5.58 KB)
📄
ISO_5427.so.tar
(13.5 KB)
📄
ISO_5428.so.so.tar.gz
(5.58 KB)
📄
ISO_5428.so.tar
(13.5 KB)
📄
ISO_6937-2.so.so.tar.gz
(8.77 KB)
📄
ISO_6937-2.so.tar
(25.5 KB)
📄
ISO_6937.so.so.tar.gz
(8.78 KB)
📄
ISO_6937.so.tar
(25.5 KB)
📄
IconView.tcl.tar
(7.5 KB)
📄
IconView.tcl.tcl.tar.gz
(1.91 KB)
📄
Icons.tar
(101 KB)
📄
Icons.tar.gz
(41.67 KB)
📄
Icons.zip
(90.4 KB)
📄
IdleHistory.pyc.pyc.tar.gz
(1.88 KB)
📄
IdleHistory.pyc.tar
(5.5 KB)
📄
IdleHistory.pyo.pyo.tar.gz
(1.88 KB)
📄
IdleHistory.pyo.tar
(5.5 KB)
📄
ImUtil.h.h.tar.gz
(318 B)
📄
ImUtil.h.tar
(2 KB)
📄
ImageMagick-6.9.13.tar
(3.75 MB)
📄
ImageMagick-6.9.13.tar.gz
(1.29 MB)
📄
ImageMagick-6.9.13.zip
(3.59 MB)
📄
Init.tcl.tar
(8 KB)
📄
Init.tcl.tcl.tar.gz
(2.52 KB)
📄
IntcSST2.bin.bin.tar.gz
(123.41 KB)
📄
IntcSST2.bin.tar
(256.5 KB)
📄
Iterator.pm.pm.tar.gz
(4.17 KB)
📄
Iterator.pm.tar
(15 KB)
📄
JIS7.pm.pm.tar.gz
(1.65 KB)
📄
JIS7.pm.tar
(6 KB)
📄
JOHAB.so.so.tar.gz
(8.63 KB)
📄
JOHAB.so.tar
(21.5 KB)
📄
JP.pm.pm.tar.gz
(1.33 KB)
📄
JP.pm.tar
(4.5 KB)
📄
JP.tar
(12 KB)
📄
JP.tar.gz
(2.86 KB)
📄
JP.zip
(9.45 KB)
📄
JSON.tar
(79 KB)
📄
JSON.tar.gz
(26.98 KB)
📄
JSON.zip
(75.59 KB)
📄
JUNIPER_me.bin.bin.tar.gz
(3.08 KB)
📄
JUNIPER_me.bin.tar
(7 KB)
📄
JUNIPER_pfp.bin.bin.tar.gz
(2.27 KB)
📄
JUNIPER_pfp.bin.tar
(6 KB)
📄
JUNIPER_rlc.bin.bin.tar.gz
(877 B)
📄
JUNIPER_rlc.bin.tar
(4.5 KB)
📄
JUNIPER_smc.bin.bin.tar.gz
(10.68 KB)
📄
JUNIPER_smc.bin.tar
(25.5 KB)
📄
Java_Web_App_Context.html.html.tar.gz
(7.15 KB)
📄
Java_Web_App_Context.html.tar
(33.5 KB)
📄
KABINI_ce.bin.bin.tar.gz
(1.33 KB)
📄
KABINI_ce.bin.tar
(10 KB)
📄
KABINI_me.bin.bin.tar.gz
(3.84 KB)
📄
KABINI_me.bin.tar
(10 KB)
📄
KABINI_mec.bin.bin.tar.gz
(8.79 KB)
📄
KABINI_mec.bin.tar
(18 KB)
📄
KABINI_pfp.bin.bin.tar.gz
(3.42 KB)
📄
KABINI_pfp.bin.tar
(10 KB)
📄
KABINI_rlc.bin.bin.tar.gz
(5.26 KB)
📄
KABINI_rlc.bin.tar
(11.5 KB)
📄
KABINI_sdma.bin.bin.tar.gz
(2.22 KB)
📄
KABINI_sdma.bin.tar
(6 KB)
📄
KAVERI_ce.bin.bin.tar.gz
(1.33 KB)
📄
KAVERI_ce.bin.tar
(10 KB)
📄
KAVERI_me.bin.bin.tar.gz
(3.84 KB)
📄
KAVERI_me.bin.tar
(10 KB)
📄
KAVERI_mec.bin.bin.tar.gz
(8.8 KB)
📄
KAVERI_mec.bin.tar
(18 KB)
📄
KAVERI_pfp.bin.bin.tar.gz
(3.48 KB)
📄
KAVERI_pfp.bin.tar
(10 KB)
📄
KAVERI_rlc.bin.bin.tar.gz
(5.4 KB)
📄
KAVERI_rlc.bin.tar
(11.5 KB)
📄
KAVERI_sdma.bin.bin.tar.gz
(2.22 KB)
📄
KAVERI_sdma.bin.tar
(6 KB)
📄
KOI-8.so.so.tar.gz
(5.64 KB)
📄
KOI-8.so.tar
(13.5 KB)
📄
KOI8-R.so.so.tar.gz
(6.04 KB)
📄
KOI8-R.so.tar
(13.5 KB)
📄
KOI8-RU.so.so.tar.gz
(6.06 KB)
📄
KOI8-RU.so.tar
(13.5 KB)
📄
KOI8-T.so.so.tar.gz
(6.01 KB)
📄
KOI8-T.so.tar
(13.5 KB)
📄
KOI8-U.so.so.tar.gz
(6.05 KB)
📄
KOI8-U.so.tar
(13.5 KB)
📄
KR.pm.pm.tar.gz
(1.04 KB)
📄
KR.pm.tar
(3.5 KB)
📄
KR.tar
(3.5 KB)
📄
KR.tar.gz
(988 B)
📄
KR.zip
(2.08 KB)
📄
LA-PCM.cis.cis.tar.gz
(290 B)
📄
LA-PCM.cis.tar
(3 KB)
📄
LATIN-GREEK-1.so.so.tar.gz
(5.6 KB)
📄
LATIN-GREEK-1.so.tar
(13.5 KB)
📄
LATIN-GREEK.so.so.tar.gz
(5.59 KB)
📄
LATIN-GREEK.so.tar
(13.5 KB)
📄
LB_Context.html.html.tar.gz
(5.8 KB)
📄
LB_Context.html.tar
(27 KB)
📄
LC_ADDRESS.tar
(54 KB)
📄
LC_ADDRESS.tar.gz
(203 B)
📄
LC_COLLATE.tar
(68.89 MB)
📄
LC_COLLATE.tar.gz
(4.29 KB)
📄
LC_CTYPE.tar
(17.22 MB)
📄
LC_CTYPE.tar.gz
(52.83 KB)
📄
LC_IDENTIFICATION.tar
(38 KB)
📄
LC_IDENTIFICATION.tar.gz
(220 B)
📄
LC_MEASUREMENT.tar
(40 KB)
📄
LC_MEASUREMENT.tar.gz
(135 B)
📄
LC_MESSAGES.tar
(2 KB)
📄
LC_MESSAGES.tar.gz
(140 B)
📄
LC_MESSAGES.zip
(221 B)
📄
LC_MONETARY.tar
(39 KB)
📄
LC_MONETARY.tar.gz
(276 B)
📄
LC_NAME.tar
(58 KB)
📄
LC_NAME.tar.gz
(160 B)
📄
LC_NUMERIC.tar
(54 KB)
📄
LC_NUMERIC.tar.gz
(155 B)
📄
LC_PAPER.tar
(57 KB)
📄
LC_PAPER.tar.gz
(140 B)
📄
LC_TELEPHONE.tar
(42 KB)
📄
LC_TELEPHONE.tar.gz
(159 B)
📄
LC_TIME.tar
(225 KB)
📄
LC_TIME.tar.gz
(925 B)
📄
LENOVO.tar
(57.04 MB)
📄
LENOVO.tar.gz
(267.53 KB)
📄
LENOVO.zip
(57.03 MB)
📄
LICENSE.OpenLDAP.OpenLDAP.tar.gz
(1.22 KB)
📄
LICENSE.OpenLDAP.tar
(4 KB)
📄
LICENSE.OpenSSL.OpenSSL.tar.gz
(2.15 KB)
📄
LICENSE.OpenSSL.tar
(8 KB)
📄
LICENSE.PHP.PHP.tar.gz
(1.51 KB)
📄
LICENSE.PHP.tar
(5 KB)
📄
LICENSE.tar
(21 KB)
📄
LICENSE.tar.gz
(3.63 KB)
📄
LICENSE.txt.tar
(15.5 KB)
📄
LICENSE.txt.txt.tar.gz
(4.35 KB)
📄
LabEntry.tcl.tar
(4 KB)
📄
LabEntry.tcl.tcl.tar.gz
(987 B)
📄
LabFrame.tcl.tar
(3 KB)
📄
LabFrame.tcl.tcl.tar.gz
(678 B)
📄
LabWidg.tcl.tar
(5.5 KB)
📄
LabWidg.tcl.tcl.tar.gz
(1.25 KB)
📄
Langinfo.pm.pm.tar.gz
(1.94 KB)
📄
Langinfo.pm.tar
(5.5 KB)
📄
Langinfo.tar
(17.5 KB)
📄
Langinfo.tar.gz
(4.99 KB)
📄
Langinfo.zip
(15.67 KB)
📄
Layouts.tar
(170 KB)
📄
Layouts.tar.gz
(55.42 KB)
📄
Layouts.zip
(167 KB)
📄
LibXML.pod.pod.tar.gz
(5.58 KB)
📄
LibXML.pod.tar
(16.5 KB)
📄
LinkExtor.pm.pm.tar.gz
(2.07 KB)
📄
LinkExtor.pm.tar
(6 KB)
📄
ListNBk.tcl.tar
(5 KB)
📄
ListNBk.tcl.tcl.tar.gz
(1.31 KB)
📄
Loader.tar
(2 KB)
📄
Loader.tar.gz
(174 B)
📄
Loader.zip
(257 B)
📄
LocalSettings.php.php.tar.gz
(2.04 KB)
📄
LocalSettings.php.tar
(6 KB)
📄
LocalStorage.tar
(65.5 KB)
📄
LocalStorage.tar.gz
(23.98 KB)
📄
LocalStorage.zip
(62.61 KB)
📄
LogEntry.php.php.tar.gz
(728 B)
📄
LogEntry.php.tar
(3.5 KB)
📄
MAC-CENTRALEUROPE.so.so.tar.gz
(6.08 KB)
📄
MAC-CENTRALEUROPE.so.tar
(13.5 KB)
📄
MAC-IS.so.so.tar.gz
(6.14 KB)
📄
MAC-IS.so.tar
(13.5 KB)
📄
MAC-SAMI.so.so.tar.gz
(6.08 KB)
📄
MAC-SAMI.so.tar
(13.5 KB)
📄
MAC-UK.so.so.tar.gz
(6.01 KB)
📄
MAC-UK.so.tar
(13.5 KB)
📄
MACINTOSH.so.so.tar.gz
(6.15 KB)
📄
MACINTOSH.so.tar
(13.5 KB)
📄
MANIFEST.tar
(2 KB)
📄
MANIFEST.tar.gz
(232 B)
📄
MIK.so.so.tar.gz
(6.1 KB)
📄
MIK.so.tar
(13.5 KB)
📄
MIME.tar
(27 KB)
📄
MIME.tar.gz
(6.88 KB)
📄
MIME.zip
(23.9 KB)
📄
MIN_VER.tar
(2 KB)
📄
MIN_VER.tar.gz
(132 B)
📄
MT5634ZLX.cis.cis.tar.gz
(208 B)
📄
MT5634ZLX.cis.tar
(3 KB)
📄
MULLINS_ce.bin.bin.tar.gz
(1.33 KB)
📄
MULLINS_ce.bin.tar
(10 KB)
📄
MULLINS_me.bin.bin.tar.gz
(3.84 KB)
📄
MULLINS_me.bin.tar
(10 KB)
📄
MULLINS_mec.bin.bin.tar.gz
(8.81 KB)
📄
MULLINS_mec.bin.tar
(18 KB)
📄
MULLINS_pfp.bin.bin.tar.gz
(3.44 KB)
📄
MULLINS_pfp.bin.tar
(10 KB)
📄
MULLINS_rlc.bin.bin.tar.gz
(5.36 KB)
📄
MULLINS_rlc.bin.tar
(11.5 KB)
📄
MULLINS_sdma.bin.bin.tar.gz
(2.22 KB)
📄
MULLINS_sdma.bin.tar
(6 KB)
📄
Mail.tar
(410.5 KB)
📄
Mail.tar.gz
(204.45 KB)
📄
Main.php.php.tar.gz
(1.85 KB)
📄
Main.php.tar
(6.5 KB)
📄
Makefile.tar
(81 KB)
📄
Makefile.tar.gz
(813 B)
📄
ManPage.py.py.tar.gz
(2.36 KB)
📄
ManPage.py.tar
(8.5 KB)
📄
Manual.tar
(259.5 KB)
📄
Manual.tar.gz
(76.9 KB)
📄
Manual.zip
(251.72 KB)
📄
Mcrt1.o.o.tar.gz
(1.2 KB)
📄
Mcrt1.o.tar
(8.5 KB)
📄
Meter.tcl.tar
(5 KB)
📄
Meter.tcl.tcl.tar.gz
(1.17 KB)
📄
MimeWriter.pyc.pyc.tar.gz
(2.87 KB)
📄
MimeWriter.pyc.tar
(9 KB)
📄
MimeWriter.pyo.pyo.tar.gz
(2.88 KB)
📄
MimeWriter.pyo.tar
(9 KB)
📄
Models.2.tar
(46.5 KB)
📄
Models.2.tar.gz
(7.8 KB)
📄
Models.2.zip
(43.78 KB)
📄
Modules.pod.pod.tar.gz
(2.14 KB)
📄
Modules.pod.tar
(7 KB)
📄
MultView.tcl.tar
(5.5 KB)
📄
MultView.tcl.tcl.tar.gz
(1.33 KB)
📄
MultiCall.py.py.tar.gz
(4.97 KB)
📄
MultiCall.py.tar
(19 KB)
📄
MultiStatusBar.pyc.pyc.tar.gz
(1.16 KB)
📄
MultiStatusBar.pyc.tar
(4 KB)
📄
MultiStatusBar.pyo.pyo.tar.gz
(1.16 KB)
📄
MultiStatusBar.pyo.tar
(4 KB)
📄
NATS-DANO.so.so.tar.gz
(5.62 KB)
📄
NATS-DANO.so.tar
(13.5 KB)
📄
NATS-SEFI.so.so.tar.gz
(5.61 KB)
📄
NATS-SEFI.so.tar
(13.5 KB)
📄
NDBM_File.pm.pm.tar.gz
(1.31 KB)
📄
NDBM_File.pm.tar
(4 KB)
📄
NDBM_File.so.so.tar.gz
(8.02 KB)
📄
NDBM_File.so.tar
(21.5 KB)
📄
NDBM_File.tar
(21.5 KB)
📄
NDBM_File.tar.gz
(8 KB)
📄
NDBM_File.zip
(19.78 KB)
📄
NE2K.cis.cis.tar.gz
(161 B)
📄
NE2K.cis.tar
(3 KB)
📄
NOTES.TXT.TXT.tar.gz
(319 B)
📄
NOTES.TXT.tar
(5 KB)
📄
NOTES.txt.tar
(68 KB)
📄
NOTES.txt.txt.tar.gz
(1005 B)
📄
NPE-A.tar
(17 KB)
📄
NPE-A.tar.gz
(4.91 KB)
📄
NPE-B.tar
(17 KB)
📄
NPE-B.tar.gz
(4.91 KB)
📄
NPE-C.tar
(16.5 KB)
📄
NPE-C.tar.gz
(5.71 KB)
📄
NamedCapture.pm.pm.tar.gz
(845 B)
📄
NamedCapture.pm.tar
(3.5 KB)
📄
Net.tar
(18 KB)
📄
Net.tar.gz
(5.5 KB)
📄
Net.zip
(16.64 KB)
📄
NetworkManager.service.service.tar.gz
(802 B)
📄
NetworkManager.service.tar
(3 KB)
📄
NetworkManager.tar
(350 KB)
📄
NetworkManager.tar.gz
(140.6 KB)
📄
NetworkManager.zip
(348.29 KB)
📄
NoteBook.tcl.tar
(8 KB)
📄
NoteBook.tcl.tcl.tar.gz
(1.96 KB)
📄
Notes.txt.tar
(41 KB)
📄
Notes.txt.txt.tar.gz
(971 B)
📄
Number.pm.pm.tar.gz
(1017 B)
📄
Number.pm.tar
(3.5 KB)
📄
O.pm.pm.tar.gz
(2.05 KB)
📄
O.pm.tar
(6 KB)
📄
ODBM_File.pm.pm.tar.gz
(1.26 KB)
📄
ODBM_File.pm.tar
(4 KB)
📄
ODBM_File.so.so.tar.gz
(8.39 KB)
📄
ODBM_File.so.tar
(21.5 KB)
📄
ODBM_File.tar
(21.5 KB)
📄
ODBM_File.tar.gz
(8.37 KB)
📄
ODBM_File.zip
(19.83 KB)
📄
OLAND_ce.bin.bin.tar.gz
(1.03 KB)
📄
OLAND_ce.bin.tar
(10 KB)
📄
OLAND_mc.bin.bin.tar.gz
(12.83 KB)
📄
OLAND_mc.bin.tar
(32.5 KB)
📄
OLAND_mc2.bin.bin.tar.gz
(12.83 KB)
📄
OLAND_mc2.bin.tar
(32.5 KB)
📄
OLAND_me.bin.bin.tar.gz
(3.52 KB)
📄
OLAND_me.bin.tar
(10 KB)
📄
OLAND_pfp.bin.bin.tar.gz
(2.4 KB)
📄
OLAND_pfp.bin.tar
(10 KB)
📄
OLAND_rlc.bin.bin.tar.gz
(2.1 KB)
📄
OLAND_rlc.bin.tar
(9.5 KB)
📄
OLAND_smc.bin.bin.tar.gz
(25.56 KB)
📄
OLAND_smc.bin.tar
(59.5 KB)
📄
OldUtil.tcl.tar
(4.5 KB)
📄
OldUtil.tcl.tcl.tar.gz
(1.09 KB)
📄
Opcode.pm.pm.tar.gz
(6.6 KB)
📄
Opcode.pm.tar
(17.5 KB)
📄
Opcode.so.so.tar.gz
(9.93 KB)
📄
Opcode.so.tar
(25.5 KB)
📄
Opcode.tar
(25.5 KB)
📄
Opcode.tar.gz
(9.91 KB)
📄
Opcode.zip
(23.97 KB)
📄
OptMenu.tcl.tar
(11 KB)
📄
OptMenu.tcl.tcl.tar.gz
(2.59 KB)
📄
OutputWindow.py.py.tar.gz
(1.74 KB)
📄
OutputWindow.py.tar
(6 KB)
📄
PALM_me.bin.bin.tar.gz
(3.07 KB)
📄
PALM_me.bin.tar
(7 KB)
📄
PALM_pfp.bin.bin.tar.gz
(2.25 KB)
📄
PALM_pfp.bin.tar
(6 KB)
📄
PCMLM28.cis.cis.tar.gz
(239 B)
📄
PCMLM28.cis.tar
(2 KB)
📄
PE-200.cis.cis.tar.gz
(175 B)
📄
PE-200.cis.tar
(3 KB)
📄
PE520.cis.cis.tar.gz
(178 B)
📄
PE520.cis.tar
(3 KB)
📄
PHP_Help.html.html.tar.gz
(5.83 KB)
📄
PHP_Help.html.tar
(26.5 KB)
📄
PI.pod.pod.tar.gz
(1.14 KB)
📄
PI.pod.tar
(4 KB)
📄
PITCAIRN_ce.bin.bin.tar.gz
(1.04 KB)
📄
PITCAIRN_ce.bin.tar
(10 KB)
📄
PITCAIRN_mc.bin.bin.tar.gz
(12.61 KB)
📄
PITCAIRN_mc.bin.tar
(32 KB)
📄
PITCAIRN_mc2.bin.bin.tar.gz
(12.66 KB)
📄
PITCAIRN_mc2.bin.tar
(32 KB)
📄
PITCAIRN_me.bin.bin.tar.gz
(3.32 KB)
📄
PITCAIRN_me.bin.tar
(10 KB)
📄
PITCAIRN_pfp.bin.bin.tar.gz
(2.2 KB)
📄
PITCAIRN_pfp.bin.tar
(10 KB)
📄
PITCAIRN_rlc.bin.bin.tar.gz
(2.58 KB)
📄
PITCAIRN_rlc.bin.tar
(9.5 KB)
📄
PITCAIRN_smc.bin.bin.tar.gz
(25.85 KB)
📄
PITCAIRN_smc.bin.tar
(60 KB)
📄
POSIX.pm.pm.tar.gz
(7.52 KB)
📄
POSIX.pm.tar
(21.5 KB)
📄
POSIX.pod.pod.tar.gz
(20.24 KB)
📄
POSIX.pod.tar
(73.5 KB)
📄
POSIX.so.so.tar.gz
(38.27 KB)
📄
POSIX.so.tar
(110 KB)
📄
POSIX.tar
(110 KB)
📄
POSIX.tar.gz
(38.25 KB)
📄
POSIX.zip
(108.59 KB)
📄
POSIX_V6_LP64_OFF64.tar
(34 KB)
📄
POSIX_V6_LP64_OFF64.tar.gz
(10.22 KB)
📄
POSIX_V7_LP64_OFF64.tar
(34 KB)
📄
POSIX_V7_LP64_OFF64.tar.gz
(10.22 KB)
📄
PS_ASIC.pst.pst.tar.gz
(962 B)
📄
PS_ASIC.pst.tar
(8 KB)
📄
PT154.so.so.tar.gz
(5.99 KB)
📄
PT154.so.tar
(13.5 KB)
📄
PanedWin.pyc.pyc.tar.gz
(1.87 KB)
📄
PanedWin.pyc.tar
(6 KB)
📄
PanedWin.pyo.pyo.tar.gz
(1.87 KB)
📄
PanedWin.pyo.tar
(6 KB)
📄
PanedWin.tcl.tar
(29.5 KB)
📄
PanedWin.tcl.tcl.tar.gz
(6.45 KB)
📄
Parser.pm.pm.tar.gz
(12.77 KB)
📄
Parser.pm.tar
(40.5 KB)
📄
Particles.2.tar
(61.5 KB)
📄
Particles.2.tar.gz
(9.33 KB)
📄
Particles.2.zip
(58.55 KB)
📄
PasswordHash.php.php.tar.gz
(2.48 KB)
📄
PasswordHash.php.tar
(8.5 KB)
📄
PathBrowser.pyc.pyc.tar.gz
(1.91 KB)
📄
PathBrowser.pyc.tar
(6 KB)
📄
PathBrowser.pyo.pyo.tar.gz
(1.91 KB)
📄
PathBrowser.pyo.tar
(6 KB)
📄
PatternGrammar.txt.tar
(4 KB)
📄
PatternGrammar.txt.txt.tar.gz
(529 B)
📄
Pbkdf2Salt.php.php.tar.gz
(499 B)
📄
Pbkdf2Salt.php.tar
(4 KB)
📄
Peek.pm.pm.tar.gz
(6.8 KB)
📄
Peek.pm.tar
(19.5 KB)
📄
PerlIO.pod.pod.tar.gz
(2.78 KB)
📄
PerlIO.pod.tar
(7.5 KB)
📄
PerlIO.tar
(100 KB)
📄
PerlIO.tar.gz
(3.81 KB)
📄
PerlIO.zip
(93.33 KB)
📄
Piece.pm.pm.tar.gz
(8.09 KB)
📄
Piece.pm.tar
(25 KB)
📄
Piece.so.so.tar.gz
(9.45 KB)
📄
Piece.so.tar
(25.5 KB)
📄
Piece.tar
(25.5 KB)
📄
Piece.tar.gz
(9.43 KB)
📄
Piece.zip
(23.74 KB)
📄
Pipe.pm.pm.tar.gz
(2.08 KB)
📄
Pipe.pm.tar
(7 KB)
📄
Plugin.tar
(144.5 KB)
📄
Plugin.tar.gz
(32.98 KB)
📄
Plugin.zip
(131.95 KB)
📄
Poll.pm.pm.tar.gz
(1.8 KB)
📄
Poll.pm.tar
(6 KB)
📄
PopMenu.tcl.tar
(7 KB)
📄
PopMenu.tcl.tcl.tar.gz
(1.89 KB)
📄
Primitiv.tcl.tar
(12 KB)
📄
Primitiv.tcl.tcl.tar.gz
(3.24 KB)
📄
Provider.pm.pm.tar.gz
(12.9 KB)
📄
Provider.pm.tar
(47 KB)
📄
PsrSimpleCacheCacheException.phpt.phpt.tar.gz
(368 B)
📄
PsrSimpleCacheCacheException.phpt.tar
(2 KB)
📄
Pty.pm.pm.tar.gz
(3.82 KB)
📄
Pty.pm.tar
(11 KB)
📄
PyParse.py.py.tar.gz
(5.65 KB)
📄
PyParse.py.tar
(21 KB)
📄
PyShell.py.py.tar.gz
(15.29 KB)
📄
PyShell.py.tar
(59 KB)
📄
Python-ast.h.h.tar.gz
(3.86 KB)
📄
Python-ast.h.tar
(27.5 KB)
📄
Python.h.h.tar.gz
(1.35 KB)
📄
Python.h.tar
(5.5 KB)
📄
Q.931.xml.931.xml.tar.gz
(209 B)
📄
Q.931.xml.tar
(2 KB)
📄
QCA2066.tar
(6.38 MB)
📄
QCA2066.tar.gz
(121.45 KB)
📄
QCA2066.zip
(6.38 MB)
📄
QCA4019.tar
(2.4 MB)
📄
QCA4019.tar.gz
(544.39 KB)
📄
QCA4019.zip
(2.39 MB)
📄
QCA6174.tar
(3.63 MB)
📄
QCA6174.tar.gz
(1.76 MB)
📄
QCA6174.zip
(3.62 MB)
📄
QCA6390.tar
(4.07 MB)
📄
QCA6390.tar.gz
(1.7 MB)
📄
QCA6390.zip
(4.06 MB)
📄
QCA6698.tar
(181 KB)
📄
QCA6698.tar.gz
(120.49 KB)
📄
QCA6698.zip
(177.93 KB)
📄
QCA6698AQ.tar
(6.19 MB)
📄
QCA6698AQ.tar.gz
(2.45 MB)
📄
QCA6698AQ.zip
(6.19 MB)
📄
QCA9377.tar
(2.5 MB)
📄
QCA9377.tar.gz
(1.42 MB)
📄
QCA9377.zip
(2.49 MB)
📄
QCA9887.tar
(252 KB)
📄
QCA9887.tar.gz
(208.42 KB)
📄
QCA9887.zip
(249.52 KB)
📄
QCA9888.tar
(935.5 KB)
📄
QCA9888.tar.gz
(531.9 KB)
📄
QCA9888.zip
(933.03 KB)
📄
QCA988X.tar
(515.5 KB)
📄
QCA988X.tar.gz
(425.52 KB)
📄
QCA988X.zip
(510.95 KB)
📄
QCA9984.tar
(973.5 KB)
📄
QCA9984.tar.gz
(531.74 KB)
📄
QCA9984.zip
(970.67 KB)
📄
QCA99X0.tar
(665.5 KB)
📄
QCA99X0.tar.gz
(378.13 KB)
📄
QCA99X0.zip
(662.88 KB)
📄
QCN9074.tar
(5.26 MB)
📄
QCN9074.tar.gz
(2.27 MB)
📄
QCN9074.zip
(5.26 MB)
📄
QCN9274.tar
(17.14 MB)
📄
QCN9274.tar.gz
(6.29 MB)
📄
QCN9274.zip
(17.13 MB)
📄
Qt.tar
(463.5 KB)
📄
Qt.tar.gz
(162.03 KB)
📄
Qt.zip
(450 KB)
📄
Qt5Gui.tar
(38.5 KB)
📄
Qt5Gui.tar.gz
(2.15 KB)
📄
Qt5Gui.zip
(20.02 KB)
📄
Qt5Gui_QGifPlugin.cmake.cmake.tar.gz
(320 B)
📄
Qt5Gui_QGifPlugin.cmake.tar
(2 KB)
📄
Qt5Gui_QICOPlugin.cmake.cmake.tar.gz
(319 B)
📄
Qt5Gui_QICOPlugin.cmake.tar
(2 KB)
📄
Qt5Gui_QOffscreenIntegrationPlugin.cmake.cmake.tar.gz
(336 B)
📄
Qt5Gui_QOffscreenIntegrationPlugin.cmake.tar
(2.5 KB)
📄
Qt5Multimedia.tar
(11 KB)
📄
Qt5Multimedia.tar.gz
(824 B)
📄
Qt5Multimedia.zip
(5.62 KB)
📄
Qt5Network.tar
(5.5 KB)
📄
Qt5Network.tar.gz
(462 B)
📄
Qt5Network.zip
(2.31 KB)
📄
Qt5PrintSupport.tar
(2.5 KB)
📄
Qt5PrintSupport.tar.gz
(326 B)
📄
Qt5PrintSupport.zip
(879 B)
📄
Qt5Sql.tar
(2.5 KB)
📄
Qt5Sql.tar.gz
(319 B)
📄
Qt5Sql.zip
(757 B)
📄
QtAudioEngine.tar
(221.5 KB)
📄
QtAudioEngine.tar.gz
(73.44 KB)
📄
QtAudioEngine.zip
(218.5 KB)
📄
QtMultimedia.tar
(472.5 KB)
📄
QtMultimedia.tar.gz
(129.53 KB)
📄
QtMultimedia.zip
(468.79 KB)
📄
QtQml.tar
(185 KB)
📄
QtQml.tar.gz
(50.19 KB)
📄
QtQml.zip
(176.72 KB)
📄
QtQuick.2.tar
(219 KB)
📄
QtQuick.2.tar.gz
(27.82 KB)
📄
QtQuick.2.zip
(216.15 KB)
📄
QtQuick.tar
(389 KB)
📄
QtQuick.tar.gz
(109.51 KB)
📄
QtQuick.zip
(378.65 KB)
📄
QtTest.tar
(183.5 KB)
📄
QtTest.tar.gz
(49 KB)
📄
QtTest.zip
(178.59 KB)
📄
Queue.py.py.tar.gz
(2.26 KB)
📄
Queue.py.tar
(10 KB)
📄
Queue.pyc.pyc.tar.gz
(3.18 KB)
📄
Queue.pyc.tar
(11 KB)
📄
Queue.pyo.pyo.tar.gz
(3.18 KB)
📄
Queue.pyo.tar
(11 KB)
📄
R100_cp.bin.bin.tar.gz
(839 B)
📄
R100_cp.bin.tar
(3.5 KB)
📄
R200_cp.bin.bin.tar.gz
(899 B)
📄
R200_cp.bin.tar
(3.5 KB)
📄
R300_cp.bin.bin.tar.gz
(909 B)
📄
R300_cp.bin.tar
(3.5 KB)
📄
R420_cp.bin.bin.tar.gz
(861 B)
📄
R420_cp.bin.tar
(6 KB)
📄
R520_cp.bin.bin.tar.gz
(879 B)
📄
R520_cp.bin.tar
(3.5 KB)
📄
R600_me.bin.bin.tar.gz
(4.8 KB)
📄
R600_me.bin.tar
(22.5 KB)
📄
R600_pfp.bin.bin.tar.gz
(1.2 KB)
📄
R600_pfp.bin.tar
(4 KB)
📄
R600_rlc.bin.bin.tar.gz
(1.56 KB)
📄
R600_rlc.bin.tar
(4.5 KB)
📄
R600_uvd.bin.bin.tar.gz
(52.85 KB)
📄
R600_uvd.bin.tar
(74 KB)
📄
R700_rlc.bin.bin.tar.gz
(2.2 KB)
📄
R700_rlc.bin.tar
(5.5 KB)
📄
RAS.xml.tar
(2 KB)
📄
RAS.xml.xml.tar.gz
(212 B)
📄
RB5.tar
(7.11 MB)
📄
RB5.tar.gz
(3.17 MB)
📄
README.12x22.12x22.tar.gz
(207 B)
📄
README.12x22.tar
(3 KB)
📄
README.Arabic.Arabic.tar.gz
(301 B)
📄
README.Arabic.tar
(2 KB)
📄
README.Cyrillic.Cyrillic.tar.gz
(1.01 KB)
📄
README.Cyrillic.tar
(3.5 KB)
📄
README.Ethiopic.Ethiopic.tar.gz
(698 B)
📄
README.Ethiopic.tar
(3 KB)
📄
README.Greek.Greek.tar.gz
(581 B)
📄
README.Greek.tar
(4 KB)
📄
README.Hebrew.Hebrew.tar.gz
(220 B)
📄
README.Hebrew.tar
(2 KB)
📄
README.Sun.Sun.tar.gz
(722 B)
📄
README.Sun.tar
(3 KB)
📄
README.cp1250.cp1250.tar.gz
(336 B)
📄
README.cp1250.tar
(2 KB)
📄
README.drdos.drdos.tar.gz
(263 B)
📄
README.drdos.tar
(3 KB)
📄
README.e2x.e2x.tar.gz
(470 B)
📄
README.e2x.tar
(2.5 KB)
📄
README.eurlatgr.eurlatgr.tar.gz
(9.56 KB)
📄
README.eurlatgr.mappings.eurlatgr.mappings.tar.gz
(2.75 KB)
📄
README.eurlatgr.mappings.tar
(9.5 KB)
📄
README.eurlatgr.tar
(54 KB)
📄
README.fish.fish.tar.gz
(2.95 KB)
📄
README.fish.tar
(8 KB)
📄
README.lat0.lat0.tar.gz
(409 B)
📄
README.lat0.tar
(2 KB)
📄
README.lat7.lat7.tar.gz
(348 B)
📄
README.lat7.tar
(2 KB)
📄
README.lat9.lat9.tar.gz
(1.34 KB)
📄
README.lat9.tar
(5 KB)
📄
README.md.md.tar.gz
(2.12 KB)
📄
README.md.tar
(11 KB)
📄
README.psfu.psfu.tar.gz
(304 B)
📄
README.psfu.tar
(2 KB)
📄
README.tar
(23.5 KB)
📄
README.tar.gz
(137 B)
📄
README.txt.tar
(10.5 KB)
📄
README.txt.txt.tar.gz
(281 B)
📄
REDWOOD_me.bin.bin.tar.gz
(3.07 KB)
📄
REDWOOD_me.bin.tar
(7 KB)
📄
REDWOOD_pfp.bin.bin.tar.gz
(2.09 KB)
📄
REDWOOD_pfp.bin.tar
(6 KB)
📄
REDWOOD_rlc.bin.bin.tar.gz
(875 B)
📄
REDWOOD_rlc.bin.tar
(4.5 KB)
📄
REDWOOD_smc.bin.bin.tar.gz
(10.66 KB)
📄
REDWOOD_smc.bin.tar
(25.5 KB)
📄
RH-Satellite-6.xml.tar
(2.5 KB)
📄
RH-Satellite-6.xml.xml.tar.gz
(369 B)
📄
RK1048.so.so.tar.gz
(6.08 KB)
📄
RK1048.so.tar
(13.5 KB)
📄
RS-COM-2P.cis.cis.tar.gz
(192 B)
📄
RS-COM-2P.cis.tar
(3 KB)
📄
RS600_cp.bin.bin.tar.gz
(900 B)
📄
RS600_cp.bin.tar
(3.5 KB)
📄
RS690_cp.bin.bin.tar.gz
(887 B)
📄
RS690_cp.bin.tar
(3.5 KB)
📄
RS780_me.bin.bin.tar.gz
(4.98 KB)
📄
RS780_me.bin.tar
(22.5 KB)
📄
RS780_pfp.bin.bin.tar.gz
(1.26 KB)
📄
RS780_pfp.bin.tar
(4 KB)
📄
RS780_uvd.bin.bin.tar.gz
(64.13 KB)
📄
RS780_uvd.bin.tar
(90 KB)
📄
RV610_me.bin.bin.tar.gz
(5.19 KB)
📄
RV610_me.bin.tar
(22.5 KB)
📄
RV610_pfp.bin.bin.tar.gz
(1.19 KB)
📄
RV610_pfp.bin.tar
(4 KB)
📄
RV620_me.bin.bin.tar.gz
(5.19 KB)
📄
RV620_me.bin.tar
(22.5 KB)
📄
RV620_pfp.bin.bin.tar.gz
(1.19 KB)
📄
RV620_pfp.bin.tar
(4 KB)
📄
RV630_me.bin.bin.tar.gz
(5.17 KB)
📄
RV630_me.bin.tar
(22.5 KB)
📄
RV630_pfp.bin.bin.tar.gz
(1.19 KB)
📄
RV630_pfp.bin.tar
(4 KB)
📄
RV635_me.bin.bin.tar.gz
(5.17 KB)
📄
RV635_me.bin.tar
(22.5 KB)
📄
RV635_pfp.bin.bin.tar.gz
(1.19 KB)
📄
RV635_pfp.bin.tar
(4 KB)
📄
RV670_me.bin.bin.tar.gz
(5.17 KB)
📄
RV670_me.bin.tar
(22.5 KB)
📄
RV670_pfp.bin.bin.tar.gz
(1.19 KB)
📄
RV670_pfp.bin.tar
(4 KB)
📄
RV710_me.bin.bin.tar.gz
(2.29 KB)
📄
RV710_me.bin.tar
(7 KB)
📄
RV710_pfp.bin.bin.tar.gz
(1.56 KB)
📄
RV710_pfp.bin.tar
(5 KB)
📄
RV710_smc.bin.bin.tar.gz
(6.64 KB)
📄
RV710_smc.bin.tar
(17.5 KB)
📄
RV710_uvd.bin.bin.tar.gz
(77.31 KB)
📄
RV710_uvd.bin.tar
(115 KB)
📄
RV730_me.bin.bin.tar.gz
(2.28 KB)
📄
RV730_me.bin.tar
(7 KB)
📄
RV730_pfp.bin.bin.tar.gz
(1.56 KB)
📄
RV730_pfp.bin.tar
(5 KB)
📄
RV730_smc.bin.bin.tar.gz
(6.9 KB)
📄
RV730_smc.bin.tar
(18 KB)
📄
RV740_smc.bin.bin.tar.gz
(6.79 KB)
📄
RV740_smc.bin.tar
(18 KB)
📄
RV770_me.bin.bin.tar.gz
(2.36 KB)
📄
RV770_me.bin.tar
(7 KB)
📄
RV770_pfp.bin.bin.tar.gz
(1.61 KB)
📄
RV770_pfp.bin.tar
(5 KB)
📄
RV770_smc.bin.bin.tar.gz
(6.69 KB)
📄
RV770_smc.bin.tar
(18 KB)
📄
RV770_uvd.bin.bin.tar.gz
(64.3 KB)
📄
RV770_uvd.bin.tar
(90.5 KB)
📄
RailsRunner.rb.2.3.rb.2.3.tar.gz
(700 B)
📄
RailsRunner.rb.2.3.tar
(3 KB)
📄
RamPatch.txt.tar
(18.5 KB)
📄
RamPatch.txt.txt.tar.gz
(7.22 KB)
📄
Reader.pm.pm.tar.gz
(2.08 KB)
📄
Reader.pm.tar
(7.5 KB)
📄
Real_Time_Stats_Help.html.html.tar.gz
(2.17 KB)
📄
Real_Time_Stats_Help.html.tar
(8.5 KB)
📄
RemoteDebugger.pyc.pyc.tar.gz
(4.47 KB)
📄
RemoteDebugger.pyc.tar
(17.5 KB)
📄
RemoteDebugger.pyo.pyo.tar.gz
(4.4 KB)
📄
RemoteDebugger.pyo.tar
(17.5 KB)
📄
ResizeH.tcl.tar
(14.5 KB)
📄
ResizeH.tcl.tcl.tar.gz
(3 KB)
📄
Rev.pyc.pyc.tar.gz
(1.37 KB)
📄
Rev.pyc.tar
(4.5 KB)
📄
Rev.pyo.pyo.tar.gz
(1.37 KB)
📄
Rev.pyo.tar
(4.5 KB)
📄
RstripExtension.py.py.tar.gz
(608 B)
📄
RstripExtension.py.tar
(3 KB)
📄
Rsvg-2.0.typelib.0.typelib.tar.gz
(1.87 KB)
📄
Rsvg-2.0.typelib.tar
(6.5 KB)
📄
SALT.php.php.tar.gz
(125 B)
📄
SALT.php.tar
(2 KB)
📄
SAMI-WS2.so.so.tar.gz
(6.07 KB)
📄
SAMI-WS2.so.tar
(13.5 KB)
📄
SAX.pm.pm.tar.gz
(1.2 KB)
📄
SAX.pm.tar
(5 KB)
📄
SAX.tar
(25 KB)
📄
SAX.tar.gz
(5.09 KB)
📄
SAX.zip
(21.5 KB)
📄
SDBM_File.pm.pm.tar.gz
(1.76 KB)
📄
SDBM_File.pm.tar
(5 KB)
📄
SDBM_File.so.so.tar.gz
(13.32 KB)
📄
SDBM_File.so.tar
(34 KB)
📄
SDBM_File.tar
(34 KB)
📄
SDBM_File.tar.gz
(13.3 KB)
📄
SDBM_File.zip
(32.46 KB)
📄
SGrid.tcl.tar
(7.5 KB)
📄
SGrid.tcl.tcl.tar.gz
(1.63 KB)
📄
SJIS.so.so.tar.gz
(40.21 KB)
📄
SJIS.so.tar
(97.5 KB)
📄
SListBox.tcl.tar
(8.5 KB)
📄
SListBox.tcl.tcl.tar.gz
(1.89 KB)
📄
SM8450-HDK-tplg.bin.bin.tar.gz
(2.07 KB)
📄
SM8450-HDK-tplg.bin.tar
(28 KB)
📄
SNMPv2-TC.txt.tar
(39 KB)
📄
SNMPv2-TC.txt.txt.tar.gz
(9.2 KB)
📄
SSLeay.tar
(10 KB)
📄
SSLeay.tar.gz
(1.8 KB)
📄
SSLeay.zip
(4.66 KB)
📄
SText.tcl.tar
(5 KB)
📄
SText.tcl.tcl.tar.gz
(1.09 KB)
📄
SUMO2_me.bin.bin.tar.gz
(2.97 KB)
📄
SUMO2_me.bin.tar
(7 KB)
📄
SUMO2_pfp.bin.bin.tar.gz
(2.28 KB)
📄
SUMO2_pfp.bin.tar
(6 KB)
📄
SUMO_me.bin.bin.tar.gz
(2.96 KB)
📄
SUMO_me.bin.tar
(7 KB)
📄
SUMO_pfp.bin.bin.tar.gz
(2.28 KB)
📄
SUMO_pfp.bin.tar
(6 KB)
📄
SUMO_rlc.bin.bin.tar.gz
(1.65 KB)
📄
SUMO_rlc.bin.tar
(4.5 KB)
📄
SUMO_uvd.bin.bin.tar.gz
(132.92 KB)
📄
SUMO_uvd.bin.tar
(202 KB)
📄
SW_555_SER.cis.cis.tar.gz
(223 B)
📄
SW_555_SER.cis.tar
(2 KB)
📄
SW_7xx_SER.cis.cis.tar.gz
(241 B)
📄
SW_7xx_SER.cis.tar
(2 KB)
📄
SW_8xx_SER.cis.cis.tar.gz
(237 B)
📄
SW_8xx_SER.cis.tar
(2 KB)
📄
SWidget.tcl.tar
(11.5 KB)
📄
SWidget.tcl.tcl.tar.gz
(2.47 KB)
📄
SWindow.tcl.tar
(8.5 KB)
📄
SWindow.tcl.tcl.tar.gz
(2.23 KB)
📄
SYS_LC_MESSAGES.tar
(3 KB)
📄
SYS_LC_MESSAGES.tar.gz
(169 B)
📄
SampleStream.inc.inc.tar.gz
(431 B)
📄
SampleStream.inc.tar
(3 KB)
📄
ScrolledList.py.py.tar.gz
(1.31 KB)
📄
ScrolledList.py.tar
(6 KB)
📄
Scrt1.o.o.tar.gz
(1.54 KB)
📄
Scrt1.o.tar
(10 KB)
📄
SearchDialog.py.py.tar.gz
(989 B)
📄
SearchDialog.py.tar
(4.5 KB)
📄
SearchEngine.py.py.tar.gz
(2.37 KB)
📄
SearchEngine.py.tar
(9 KB)
📄
Seconds.pm.pm.tar.gz
(2 KB)
📄
Seconds.pm.tar
(7 KB)
📄
Secret-1.typelib.tar
(21 KB)
📄
Secret-1.typelib.typelib.tar.gz
(5.3 KB)
📄
Seekable.pm.pm.tar.gz
(1.42 KB)
📄
Seekable.pm.tar
(4.5 KB)
📄
Select.pm.pm.tar.gz
(3.18 KB)
📄
Select.pm.tar
(10 KB)
📄
ServSecurity_Help.html.html.tar.gz
(14.42 KB)
📄
ServSecurity_Help.html.tar
(74 KB)
📄
Settings.php.php.tar.gz
(2.31 KB)
📄
Settings.php.tar
(11 KB)
📄
Setup.local.local.tar.gz
(153 B)
📄
Setup.local.tar
(2 KB)
📄
Setup.tar
(19.5 KB)
📄
Setup.tar.gz
(7.15 KB)
📄
Shapes.tar
(20.5 KB)
📄
Shapes.tar.gz
(6.14 KB)
📄
Shapes.zip
(17.78 KB)
📄
Shell.tcl.tar
(3 KB)
📄
Shell.tcl.tcl.tar.gz
(657 B)
📄
Showlex.pm.pm.tar.gz
(2.23 KB)
📄
Showlex.pm.tar
(7.5 KB)
📄
SignalSpy.qml.qml.tar.gz
(2.78 KB)
📄
SignalSpy.qml.tar
(10.5 KB)
📄
SimpDlg.tcl.tar
(3 KB)
📄
SimpDlg.tcl.tcl.tar.gz
(708 B)
📄
Simple.py.py.tar.gz
(545 B)
📄
Simple.py.tar
(3 KB)
📄
SimpleHTTPServer.pyc.pyc.tar.gz
(3.69 KB)
📄
SimpleHTTPServer.pyc.tar
(9.5 KB)
📄
SimpleHTTPServer.pyo.pyo.tar.gz
(3.69 KB)
📄
SimpleHTTPServer.pyo.tar
(9.5 KB)
📄
Socket.pm.pm.tar.gz
(5.61 KB)
📄
Socket.pm.tar
(17.5 KB)
📄
Socket.tar
(18 KB)
📄
Socket.tar.gz
(4.52 KB)
📄
Socket.zip
(15.79 KB)
📄
SocketServer.py.py.tar.gz
(6.62 KB)
📄
SocketServer.py.tar
(25 KB)
📄
StackViewer.pyc.pyc.tar.gz
(2.59 KB)
📄
StackViewer.pyc.tar
(8 KB)
📄
StackWin.tcl.tar
(3.5 KB)
📄
StackWin.tcl.tcl.tar.gz
(998 B)
📄
Stash.pm.pm.tar.gz
(8.12 KB)
📄
Stash.pm.tar
(30 KB)
📄
Stash.tar
(31.5 KB)
📄
Stash.tar.gz
(7.84 KB)
📄
Stash.zip
(29.03 KB)
📄
StatBar.tcl.tar
(3 KB)
📄
StatBar.tcl.tcl.tar.gz
(668 B)
📄
Static_Context.html.html.tar.gz
(8.56 KB)
📄
Static_Context.html.tar
(40 KB)
📄
StdBBox.tcl.tar
(3.5 KB)
📄
StdBBox.tcl.tcl.tar.gz
(825 B)
📄
StdShell.tcl.tar
(3 KB)
📄
StdShell.tcl.tcl.tar.gz
(723 B)
📄
StringIO.py.py.tar.gz
(3.27 KB)
📄
StringIO.py.tar
(12 KB)
📄
StringIO.pyc.pyc.tar.gz
(4.53 KB)
📄
StringIO.pyc.tar
(13 KB)
📄
StringIO.pyo.pyo.tar.gz
(4.53 KB)
📄
StringIO.pyo.tar
(13 KB)
📄
Sunkeysym.h.h.tar.gz
(1.53 KB)
📄
Sunkeysym.h.tar
(5.5 KB)
📄
Supported.pod.pod.tar.gz
(10.2 KB)
📄
Supported.pod.tar
(30 KB)
📄
Syck.pm.pm.tar.gz
(4.14 KB)
📄
Syck.pm.tar
(19 KB)
📄
Synch.pyc.pyc.tar.gz
(3.33 KB)
📄
Synch.pyc.tar
(10 KB)
📄
Synch.pyo.pyo.tar.gz
(3.26 KB)
📄
Synch.pyo.tar
(10 KB)
📄
Sys.tar
(13 KB)
📄
Sys.tar.gz
(1.64 KB)
📄
Sys.zip
(11.27 KB)
📄
T.61.so.61.so.tar.gz
(8.15 KB)
📄
T.61.so.tar
(21.5 KB)
📄
T.pyc.pyc.tar.gz
(599 B)
📄
T.pyc.tar
(2.5 KB)
📄
T.pyo.pyo.tar.gz
(599 B)
📄
T.pyo.tar
(2.5 KB)
📄
TAHITI_ce.bin.bin.tar.gz
(1.03 KB)
📄
TAHITI_ce.bin.tar
(10 KB)
📄
TAHITI_mc.bin.bin.tar.gz
(12.6 KB)
📄
TAHITI_mc.bin.tar
(32 KB)
📄
TAHITI_mc2.bin.bin.tar.gz
(12.71 KB)
📄
TAHITI_mc2.bin.tar
(32 KB)
📄
TAHITI_me.bin.bin.tar.gz
(3.32 KB)
📄
TAHITI_me.bin.tar
(10 KB)
📄
TAHITI_pfp.bin.bin.tar.gz
(2.2 KB)
📄
TAHITI_pfp.bin.tar
(10 KB)
📄
TAHITI_rlc.bin.bin.tar.gz
(2.61 KB)
📄
TAHITI_rlc.bin.tar
(9.5 KB)
📄
TAHITI_smc.bin.bin.tar.gz
(26.05 KB)
📄
TAHITI_smc.bin.tar
(63 KB)
📄
TAHITI_uvd.bin.bin.tar.gz
(143.86 KB)
📄
TAHITI_uvd.bin.tar
(216.5 KB)
📄
TAHITI_vce.bin.bin.tar.gz
(37.1 KB)
📄
TAHITI_vce.bin.tar
(49 KB)
📄
TAS2XXX0C94.bin.bin.tar.gz
(4.78 KB)
📄
TAS2XXX0C94.bin.tar
(36 KB)
📄
TAS2XXX0C95.bin.bin.tar.gz
(4.8 KB)
📄
TAS2XXX0C95.bin.tar
(36 KB)
📄
TAS2XXX0C96.bin.bin.tar.gz
(4.75 KB)
📄
TAS2XXX0C96.bin.tar
(36 KB)
📄
TAS2XXX0C97.bin.bin.tar.gz
(4.76 KB)
📄
TAS2XXX0C97.bin.tar
(36 KB)
📄
TAS2XXX103C8DE8-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE8-0.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE8-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE8-1.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE80.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE80.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE81.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE81.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE9-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE9-0.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE9-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE9-1.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE90.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE90.bin.tar
(50.5 KB)
📄
TAS2XXX103C8DE91.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX103C8DE91.bin.tar
(50.5 KB)
📄
TAS2XXX10A40.bin.bin.tar.gz
(7.73 KB)
📄
TAS2XXX10A40.bin.tar
(50 KB)
📄
TAS2XXX10A41.bin.bin.tar.gz
(7.73 KB)
📄
TAS2XXX10A41.bin.tar
(50 KB)
📄
TAS2XXX11540.bin.bin.tar.gz
(7.72 KB)
📄
TAS2XXX11540.bin.tar
(50 KB)
📄
TAS2XXX11541.bin.bin.tar.gz
(7.72 KB)
📄
TAS2XXX11541.bin.tar
(50 KB)
📄
TAS2XXX12040.bin.bin.tar.gz
(8.15 KB)
📄
TAS2XXX12040.bin.tar
(50 KB)
📄
TAS2XXX12041.bin.bin.tar.gz
(8.05 KB)
📄
TAS2XXX12041.bin.tar
(50 KB)
📄
TAS2XXX12140.bin.bin.tar.gz
(8.15 KB)
📄
TAS2XXX12140.bin.tar
(50 KB)
📄
TAS2XXX12141.bin.bin.tar.gz
(8.05 KB)
📄
TAS2XXX12141.bin.tar
(50 KB)
📄
TAS2XXX13840.bin.bin.tar.gz
(8.12 KB)
📄
TAS2XXX13840.bin.tar
(50 KB)
📄
TAS2XXX13841.bin.bin.tar.gz
(8.16 KB)
📄
TAS2XXX13841.bin.tar
(50 KB)
📄
TAS2XXX13940.bin.bin.tar.gz
(8.12 KB)
📄
TAS2XXX13940.bin.tar
(50 KB)
📄
TAS2XXX13941.bin.bin.tar.gz
(8.16 KB)
📄
TAS2XXX13941.bin.tar
(50 KB)
📄
TAS2XXX13A40.bin.bin.tar.gz
(8.12 KB)
📄
TAS2XXX13A40.bin.tar
(50 KB)
📄
TAS2XXX13A41.bin.bin.tar.gz
(8.16 KB)
📄
TAS2XXX13A41.bin.tar
(50 KB)
📄
TAS2XXX1EB3.bin.bin.tar.gz
(4.75 KB)
📄
TAS2XXX1EB3.bin.tar
(36 KB)
📄
TAS2XXX1EB30.bin.bin.tar.gz
(4.76 KB)
📄
TAS2XXX1EB30.bin.tar
(36 KB)
📄
TAS2XXX1EB31.bin.bin.tar.gz
(4.76 KB)
📄
TAS2XXX1EB31.bin.tar
(36 KB)
📄
TAS2XXX2234.bin.bin.tar.gz
(4.76 KB)
📄
TAS2XXX2234.bin.tar
(36 KB)
📄
TAS2XXX2326.bin.bin.tar.gz
(4.76 KB)
📄
TAS2XXX2326.bin.tar
(36 KB)
📄
TAS2XXX3870.bin.bin.tar.gz
(6.05 KB)
📄
TAS2XXX3870.bin.tar
(21.5 KB)
📄
TAS2XXX387D.bin.bin.tar.gz
(5.57 KB)
📄
TAS2XXX387D.bin.tar
(64.5 KB)
📄
TAS2XXX387E.bin.bin.tar.gz
(5.85 KB)
📄
TAS2XXX387E.bin.tar
(65 KB)
📄
TAS2XXX387F.bin.bin.tar.gz
(5.04 KB)
📄
TAS2XXX387F.bin.tar
(37.5 KB)
📄
TAS2XXX3880.bin.bin.tar.gz
(5.02 KB)
📄
TAS2XXX3880.bin.tar
(37.5 KB)
📄
TAS2XXX3881.bin.bin.tar.gz
(5.08 KB)
📄
TAS2XXX3881.bin.tar
(37.5 KB)
📄
TAS2XXX3882.bin.bin.tar.gz
(5.08 KB)
📄
TAS2XXX3882.bin.tar
(37.5 KB)
📄
TAS2XXX3884.bin.bin.tar.gz
(5.23 KB)
📄
TAS2XXX3884.bin.tar
(37.5 KB)
📄
TAS2XXX3886.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX3886.bin.tar
(37.5 KB)
📄
TAS2XXX38A5.bin.bin.tar.gz
(5.25 KB)
📄
TAS2XXX38A5.bin.tar
(37.5 KB)
📄
TAS2XXX38A7.bin.bin.tar.gz
(5.23 KB)
📄
TAS2XXX38A7.bin.tar
(37.5 KB)
📄
TAS2XXX38A8.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38A8.bin.tar
(37.5 KB)
📄
TAS2XXX38B8.bin.bin.tar.gz
(5.03 KB)
📄
TAS2XXX38B8.bin.tar
(37.5 KB)
📄
TAS2XXX38B9.bin.bin.tar.gz
(5.04 KB)
📄
TAS2XXX38B9.bin.tar
(37.5 KB)
📄
TAS2XXX38BA.bin.bin.tar.gz
(5.8 KB)
📄
TAS2XXX38BA.bin.tar
(65 KB)
📄
TAS2XXX38BB.bin.bin.tar.gz
(5.72 KB)
📄
TAS2XXX38BB.bin.tar
(64.5 KB)
📄
TAS2XXX38BE.bin.bin.tar.gz
(4.88 KB)
📄
TAS2XXX38BE.bin.tar
(37 KB)
📄
TAS2XXX38BF.bin.bin.tar.gz
(4.88 KB)
📄
TAS2XXX38BF.bin.tar
(37 KB)
📄
TAS2XXX38C3.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38C3.bin.tar
(37.5 KB)
📄
TAS2XXX38CB.bin.bin.tar.gz
(5.23 KB)
📄
TAS2XXX38CB.bin.tar
(37.5 KB)
📄
TAS2XXX38CD.bin.bin.tar.gz
(5.22 KB)
📄
TAS2XXX38CD.bin.tar
(37.5 KB)
📄
TAS2XXX38D3.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38D3.bin.tar
(37.5 KB)
📄
TAS2XXX38D4.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38D4.bin.tar
(37.5 KB)
📄
TAS2XXX38D5.bin.bin.tar.gz
(5.84 KB)
📄
TAS2XXX38D5.bin.tar
(64 KB)
📄
TAS2XXX38D6.bin.bin.tar.gz
(5.86 KB)
📄
TAS2XXX38D6.bin.tar
(64 KB)
📄
TAS2XXX38DF.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38DF.bin.tar
(37.5 KB)
📄
TAS2XXX38E0.bin.bin.tar.gz
(5.24 KB)
📄
TAS2XXX38E0.bin.tar
(37.5 KB)
📄
TAS2XXX38FD.bin.bin.tar.gz
(4.93 KB)
📄
TAS2XXX38FD.bin.tar
(35.5 KB)
📄
TAS2XXX391F.bin.bin.tar.gz
(8.69 KB)
📄
TAS2XXX391F.bin.tar
(80 KB)
📄
TAS2XXX3920.bin.bin.tar.gz
(8.7 KB)
📄
TAS2XXX3920.bin.tar
(80 KB)
📄
TAS2XXX3E300.bin.bin.tar.gz
(7.72 KB)
📄
TAS2XXX3E300.bin.tar
(50 KB)
📄
TAS2XXX3E301.bin.bin.tar.gz
(7.72 KB)
📄
TAS2XXX3E301.bin.tar
(50 KB)
📄
TAS2XXX3EE00.bin.bin.tar.gz
(8.07 KB)
📄
TAS2XXX3EE00.bin.tar
(50 KB)
📄
TAS2XXX3EE01.bin.bin.tar.gz
(8.08 KB)
📄
TAS2XXX3EE01.bin.tar
(50 KB)
📄
TAS2XXX3EF00.bin.bin.tar.gz
(8.04 KB)
📄
TAS2XXX3EF00.bin.tar
(50 KB)
📄
TAS2XXX3EF01.bin.bin.tar.gz
(8.04 KB)
📄
TAS2XXX3EF01.bin.tar
(50 KB)
📄
TAS2XXX3F000.bin.bin.tar.gz
(8.07 KB)
📄
TAS2XXX3F000.bin.tar
(50 KB)
📄
TAS2XXX3F001.bin.bin.tar.gz
(8.08 KB)
📄
TAS2XXX3F001.bin.tar
(50 KB)
📄
TAS2XXX3F100.bin.bin.tar.gz
(8.07 KB)
📄
TAS2XXX3F100.bin.tar
(50 KB)
📄
TAS2XXX3F101.bin.bin.tar.gz
(8.08 KB)
📄
TAS2XXX3F101.bin.tar
(50 KB)
📄
TAS2XXX3F200.bin.bin.tar.gz
(8.15 KB)
📄
TAS2XXX3F200.bin.tar
(50 KB)
📄
TAS2XXX3F201.bin.bin.tar.gz
(8.05 KB)
📄
TAS2XXX3F201.bin.tar
(50 KB)
📄
TAS2XXX3F300.bin.bin.tar.gz
(8.07 KB)
📄
TAS2XXX3F300.bin.tar
(50 KB)
📄
TAS2XXX3F301.bin.bin.tar.gz
(8.08 KB)
📄
TAS2XXX3F301.bin.tar
(50 KB)
📄
TAS2XXX8C70.bin.bin.tar.gz
(706 B)
📄
TAS2XXX8C70.bin.tar
(3.5 KB)
📄
TAS2XXX8C71.bin.bin.tar.gz
(709 B)
📄
TAS2XXX8C71.bin.tar
(3.5 KB)
📄
TAS2XXX8C72.bin.bin.tar.gz
(708 B)
📄
TAS2XXX8C72.bin.tar
(3.5 KB)
📄
TAS2XXX8D8E.bin.bin.tar.gz
(7.55 KB)
📄
TAS2XXX8D8E.bin.tar
(50.5 KB)
📄
TAS2XXX8DAA.bin.bin.tar.gz
(7.79 KB)
📄
TAS2XXX8DAA.bin.tar
(50 KB)
📄
TAS2XXX8DE8-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE8-0.bin.tar
(100 KB)
📄
TAS2XXX8DE8-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE8-1.bin.tar
(100 KB)
📄
TAS2XXX8DE8.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE8.bin.tar
(50.5 KB)
📄
TAS2XXX8DE80.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE80.bin.tar
(50.5 KB)
📄
TAS2XXX8DE81.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE81.bin.tar
(50.5 KB)
📄
TAS2XXX8DE9-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE9-0.bin.tar
(100 KB)
📄
TAS2XXX8DE9-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE9-1.bin.tar
(100 KB)
📄
TAS2XXX8DE9.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8DE9.bin.tar
(50.5 KB)
📄
TAS2XXX8DE90.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8DE90.bin.tar
(50.5 KB)
📄
TAS2XXX8DE91.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8DE91.bin.tar
(50.5 KB)
📄
TAS2XXX8E17.bin.bin.tar.gz
(732 B)
📄
TAS2XXX8E17.bin.tar
(3.5 KB)
📄
TAS2XXX8E19.bin.bin.tar.gz
(640 B)
📄
TAS2XXX8E19.bin.tar
(3.5 KB)
📄
TAS2XXX8E1C.bin.bin.tar.gz
(731 B)
📄
TAS2XXX8E1C.bin.tar
(3.5 KB)
📄
TAS2XXX8E8A.bin.bin.tar.gz
(7.59 KB)
📄
TAS2XXX8E8A.bin.tar
(50.5 KB)
📄
TAS2XXX8ED5-0.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED5-0.bin.tar
(100 KB)
📄
TAS2XXX8ED5-1.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED5-1.bin.tar
(100 KB)
📄
TAS2XXX8ED5.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED5.bin.tar
(50.5 KB)
📄
TAS2XXX8ED6-0.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED6-0.bin.tar
(100 KB)
📄
TAS2XXX8ED6-1.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED6-1.bin.tar
(100 KB)
📄
TAS2XXX8ED6.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED6.bin.tar
(100 KB)
📄
TAS2XXX8ED7-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED7-0.bin.tar
(100 KB)
📄
TAS2XXX8ED7-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED7-1.bin.tar
(100 KB)
📄
TAS2XXX8ED7.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED7.bin.tar
(50.5 KB)
📄
TAS2XXX8ED8-0.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED8-0.bin.tar
(100 KB)
📄
TAS2XXX8ED8-1.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED8-1.bin.tar
(100 KB)
📄
TAS2XXX8ED8.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8ED8.bin.tar
(50.5 KB)
📄
TAS2XXX8ED9-0.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED9-0.bin.tar
(100 KB)
📄
TAS2XXX8ED9-1.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED9-1.bin.tar
(100 KB)
📄
TAS2XXX8ED9.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8ED9.bin.tar
(50.5 KB)
📄
TAS2XXX8EDA-0.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8EDA-0.bin.tar
(100 KB)
📄
TAS2XXX8EDA-1.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8EDA-1.bin.tar
(100 KB)
📄
TAS2XXX8EDA.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8EDA.bin.tar
(50.5 KB)
📄
TAS2XXX8F40.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8F40.bin.tar
(50.5 KB)
📄
TAS2XXX8F41.bin.bin.tar.gz
(7.56 KB)
📄
TAS2XXX8F41.bin.tar
(50.5 KB)
📄
TAS2XXX8F42.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8F42.bin.tar
(50.5 KB)
📄
TAS2XXX8F62.bin.bin.tar.gz
(7.57 KB)
📄
TAS2XXX8F62.bin.tar
(50.5 KB)
📄
TCVN5712-1.so.so.tar.gz
(8.52 KB)
📄
TCVN5712-1.so.tar
(17.5 KB)
📄
TIAS2781RCA2.bin.bin.tar.gz
(351 B)
📄
TIAS2781RCA2.bin.tar
(2.5 KB)
📄
TIAS2781RCA4.bin.bin.tar.gz
(369 B)
📄
TIAS2781RCA4.bin.tar
(3 KB)
📄
TIS-620.so.so.tar.gz
(5.83 KB)
📄
TIS-620.so.tar
(13.5 KB)
📄
TK.csc.csc.tar.gz
(505 B)
📄
TK.csc.tar
(3.5 KB)
📄
TK.fsc.fsc.tar.gz
(345 B)
📄
TK.fsc.tar
(2.5 KB)
📄
TList.tcl.tar
(19.5 KB)
📄
TList.tcl.tcl.tar.gz
(2.71 KB)
📄
TRANSPORT-ADDRESS-MIB.txt.tar
(18 KB)
📄
TRANSPORT-ADDRESS-MIB.txt.txt.tar.gz
(3.12 KB)
📄
TSCII.so.so.tar.gz
(10.05 KB)
📄
TSCII.so.tar
(25.5 KB)
📄
TURKS_mc.bin.bin.tar.gz
(9.24 KB)
📄
TURKS_mc.bin.tar
(25.5 KB)
📄
TURKS_me.bin.bin.tar.gz
(2.95 KB)
📄
TURKS_me.bin.tar
(7 KB)
📄
TURKS_pfp.bin.bin.tar.gz
(2.23 KB)
📄
TURKS_pfp.bin.tar
(6 KB)
📄
TURKS_smc.bin.bin.tar.gz
(10.72 KB)
📄
TURKS_smc.bin.tar
(26 KB)
📄
TW.pm.pm.tar.gz
(1.22 KB)
📄
TW.pm.tar
(4 KB)
📄
TXNW2781RCA0.bin.bin.tar.gz
(323 B)
📄
TXNW2781RCA0.bin.tar
(2.5 KB)
📄
TXNW2781RCA1.bin.bin.tar.gz
(323 B)
📄
TXNW2781RCA1.bin.tar
(2.5 KB)
📄
TXNW2781RCA2.bin.bin.tar.gz
(351 B)
📄
TXNW2781RCA2.bin.tar
(2.5 KB)
📄
TXNW2781RCA4.bin.bin.tar.gz
(370 B)
📄
TXNW2781RCA4.bin.tar
(3 KB)
📄
TYPES.py.py.tar.gz
(1.22 KB)
📄
TYPES.py.tar
(5 KB)
📄
Template.pm.pm.tar.gz
(8.46 KB)
📄
Template.pm.tar
(27 KB)
📄
Template.tar
(1016.5 KB)
📄
Template.tar.gz
(249.64 KB)
📄
Template.zip
(977.92 KB)
📄
Templates_Help.html.html.tar.gz
(3.67 KB)
📄
Templates_Help.html.tar
(16.5 KB)
📄
Terse.pm.pm.tar.gz
(1.55 KB)
📄
Terse.pm.tar
(5 KB)
📄
TestCase.qml.qml.tar.gz
(15.03 KB)
📄
TestCase.qml.tar
(75.5 KB)
📄
Thundercomm.tar
(7.11 MB)
📄
Thundercomm.tar.gz
(3.17 MB)
📄
Thundercomm.zip
(7.11 MB)
📄
Tie.tar
(20 KB)
📄
Tie.tar.gz
(834 B)
📄
Tie.zip
(17.4 KB)
📄
Time.tar
(55.5 KB)
📄
Time.tar.gz
(9.47 KB)
📄
Time.zip
(52.34 KB)
📄
TkWin.csc.csc.tar.gz
(1.47 KB)
📄
TkWin.csc.tar
(23.5 KB)
📄
TkWin.fsc.fsc.tar.gz
(510 B)
📄
TkWin.fsc.tar
(3.5 KB)
📄
ToolTip.py.py.tar.gz
(1.21 KB)
📄
ToolTip.py.tar
(5 KB)
📄
Tools.tar
(1.03 MB)
📄
Tools.tar.gz
(301.43 KB)
📄
Tools.zip
(935.34 KB)
📄
Trace.pyc.pyc.tar.gz
(2.27 KB)
📄
Trace.pyc.tar
(8 KB)
📄
Trace.pyo.pyo.tar.gz
(2.27 KB)
📄
Trace.pyo.tar
(8 KB)
📄
Tree.tcl.tar
(6.5 KB)
📄
Tree.tcl.tcl.tar.gz
(1.5 KB)
📄
Tty.pm.pm.tar.gz
(3.8 KB)
📄
Tty.pm.tar
(10 KB)
📄
Tty.tar
(9 KB)
📄
Tty.tar.gz
(2.31 KB)
📄
Tty.zip
(7.21 KB)
📄
Tutorial.tar
(43 KB)
📄
Tutorial.tar.gz
(14.04 KB)
📄
Tutorial.zip
(40.61 KB)
📄
UHC.so.so.tar.gz
(41.81 KB)
📄
UHC.so.tar
(73.5 KB)
📄
UNICODE.so.so.tar.gz
(5.43 KB)
📄
UNICODE.so.tar
(13.5 KB)
📄
UTF-16.so.so.tar.gz
(6.83 KB)
📄
UTF-16.so.tar
(17.5 KB)
📄
UTF-32.so.so.tar.gz
(5.68 KB)
📄
UTF-32.so.tar
(13.5 KB)
📄
UTF-7.so.so.tar.gz
(9.58 KB)
📄
UTF-7.so.tar
(21.5 KB)
📄
Ultimate Brand Invert.svg.svg.tar.gz
(4.62 KB)
📄
Ultimate Brand Invert.svg.tar
(12.5 KB)
📄
Unicode.pm.pm.tar.gz
(3.92 KB)
📄
Unicode.pm.tar
(10.5 KB)
📄
Unicode.tar
(5.5 KB)
📄
Unicode.tar.gz
(1.78 KB)
📄
Unicode.zip
(3.93 KB)
📄
UserDict.py.py.tar.gz
(1.8 KB)
📄
UserDict.py.tar
(8.5 KB)
📄
UserDict.pyc.pyc.tar.gz
(3.04 KB)
📄
UserDict.pyc.tar
(11 KB)
📄
UserDict.pyo.pyo.tar.gz
(3.04 KB)
📄
UserDict.pyo.tar
(11 KB)
📄
UserList.py.py.tar.gz
(898 B)
📄
UserList.py.tar
(5.5 KB)
📄
UserList.pyc.pyc.tar.gz
(1.77 KB)
📄
UserList.pyc.tar
(8 KB)
📄
UserList.pyo.pyo.tar.gz
(1.77 KB)
📄
UserList.pyo.tar
(8 KB)
📄
UserString.pyc.pyc.tar.gz
(3.96 KB)
📄
UserString.pyc.tar
(16.5 KB)
📄
UserString.pyo.pyo.tar.gz
(3.96 KB)
📄
UserString.pyo.tar
(16.5 KB)
📄
Util.pm.pm.tar.gz
(7.75 KB)
📄
Util.pm.tar
(26.5 KB)
📄
Util.so.so.tar.gz
(8.42 KB)
📄
Util.so.tar
(21.5 KB)
📄
Util.tar
(72 KB)
📄
Util.tar.gz
(9.47 KB)
📄
Util.zip
(68.94 KB)
📄
Utils.tcl.tar
(12.5 KB)
📄
Utils.tcl.tcl.tar.gz
(3.47 KB)
📄
V2_xml.php.php.tar.gz
(649 B)
📄
V2_xml.php.tar
(2.5 KB)
📄
VERDE_ce.bin.bin.tar.gz
(1.03 KB)
📄
VERDE_ce.bin.tar
(10 KB)
📄
VERDE_mc.bin.bin.tar.gz
(12.6 KB)
📄
VERDE_mc.bin.tar
(32 KB)
📄
VERDE_mc2.bin.bin.tar.gz
(12.83 KB)
📄
VERDE_mc2.bin.tar
(32.5 KB)
📄
VERDE_me.bin.bin.tar.gz
(3.33 KB)
📄
VERDE_me.bin.tar
(10 KB)
📄
VERDE_pfp.bin.bin.tar.gz
(2.23 KB)
📄
VERDE_pfp.bin.tar
(10 KB)
📄
VERDE_rlc.bin.bin.tar.gz
(4.63 KB)
📄
VERDE_rlc.bin.tar
(9.5 KB)
📄
VERDE_smc.bin.bin.tar.gz
(26.07 KB)
📄
VERDE_smc.bin.tar
(60.5 KB)
📄
VERSION.tar
(3 KB)
📄
VERSION.tar.gz
(111 B)
📄
VHGeneral_Help.html.html.tar.gz
(9.12 KB)
📄
VHGeneral_Help.html.tar
(42 KB)
📄
VISCII.so.so.tar.gz
(5.99 KB)
📄
VISCII.so.tar
(13.5 KB)
📄
VMethods.pm.pm.tar.gz
(4.26 KB)
📄
VMethods.pm.tar
(17 KB)
📄
VResize.tcl.tar
(6.5 KB)
📄
VResize.tcl.tcl.tar.gz
(1.63 KB)
📄
VTree.tcl.tar
(6 KB)
📄
VTree.tcl.tcl.tar.gz
(1.34 KB)
📄
Variable.tcl.tar
(4.5 KB)
📄
Variable.tcl.tcl.tar.gz
(1.02 KB)
📄
Vec.pyc.pyc.tar.gz
(1.13 KB)
📄
Vec.pyc.tar
(4.5 KB)
📄
Vec.pyo.pyo.tar.gz
(1.13 KB)
📄
Vec.pyo.tar
(4.5 KB)
📄
Version.php.php.tar.gz
(4.89 KB)
📄
Version.php.tar
(42 KB)
📄
Video.qml.qml.tar.gz
(4.72 KB)
📄
Video.qml.tar
(18.5 KB)
📄
VirtualHosts_Help.html.html.tar.gz
(4.8 KB)
📄
VirtualHosts_Help.html.tar
(23 KB)
📄
WCN3990.tar
(7.94 MB)
📄
WCN3990.tar.gz
(3.79 MB)
📄
WCN3990.zip
(7.94 MB)
📄
WCN6750.tar
(15.69 MB)
📄
WCN6750.tar.gz
(7.09 MB)
📄
WCN6750.zip
(15.68 MB)
📄
WCN6855.tar
(17.09 MB)
📄
WCN6855.tar.gz
(5.39 MB)
📄
WCN6855.zip
(17.08 MB)
📄
WCN7850.tar
(14.63 MB)
📄
WCN7850.tar.gz
(6.53 MB)
📄
WCN7850.zip
(14.62 MB)
📄
WInfo.tcl.tar
(2.5 KB)
📄
WInfo.tcl.tcl.tar.gz
(626 B)
📄
WQA.html.html.tar.gz
(1.33 KB)
📄
WQA.html.tar
(5 KB)
📄
Wiki.gif.gif.tar.gz
(11.59 KB)
📄
Wiki.gif.tar
(13.5 KB)
📄
Window.2.tar
(75.5 KB)
📄
Window.2.tar.gz
(18.21 KB)
📄
Window.2.zip
(72.51 KB)
📄
WmDefault.cs.cs.tar.gz
(590 B)
📄
WmDefault.cs.tar
(3 KB)
📄
WmDefault.fs.fs.tar.gz
(442 B)
📄
WmDefault.fs.tar
(2.5 KB)
📄
WmDefault.py.py.tar.gz
(1.53 KB)
📄
WmDefault.py.tar
(5 KB)
📄
WorkerScript.2.tar
(16 KB)
📄
WorkerScript.2.tar.gz
(5.3 KB)
📄
WorkerScript.2.zip
(13.3 KB)
📄
X.h.h.tar.gz
(6.13 KB)
📄
X.h.tar
(21.5 KB)
📄
X11.tar
(1.33 MB)
📄
X11.tar.gz
(240.06 KB)
📄
X11.zip
(1.25 MB)
📄
X2Config.php.php.tar.gz
(258 B)
📄
X2Config.php.tar
(2 KB)
📄
XF86keysym.h.h.tar.gz
(3.76 KB)
📄
XF86keysym.h.tar
(15 KB)
📄
XKBlib.h.h.tar.gz
(5.91 KB)
📄
XKBlib.h.tar
(32 KB)
📄
XML.tar
(741.5 KB)
📄
XML.tar.gz
(265.49 KB)
📄
XML.zip
(692.71 KB)
📄
XS.tar
(2.5 KB)
📄
XS.tar.gz
(456 B)
📄
XS.zip
(748 B)
📄
XSUB.h.h.tar.gz
(6.62 KB)
📄
XSUB.h.tar
(25.5 KB)
📄
XWDFile.h.h.tar.gz
(1.77 KB)
📄
XWDFile.h.tar
(5.5 KB)
📄
Xalloca.h.h.tar.gz
(1.96 KB)
📄
Xalloca.h.tar
(6 KB)
📄
Xarch.h.h.tar.gz
(1.26 KB)
📄
Xarch.h.tar
(4.5 KB)
📄
Xatom.h.h.tar.gz
(809 B)
📄
Xatom.h.tar
(4 KB)
📄
Xauth.h.h.tar.gz
(1.57 KB)
📄
Xauth.h.tar
(5.5 KB)
📄
Xcms.h.h.tar.gz
(4.09 KB)
📄
Xcms.h.tar
(22.5 KB)
📄
Xdefs.h.h.tar.gz
(1.09 KB)
📄
Xdefs.h.tar
(4 KB)
📄
Xfuncproto.h.h.tar.gz
(2.5 KB)
📄
Xfuncproto.h.tar
(9.5 KB)
📄
Xfuncs.h.h.tar.gz
(1.14 KB)
📄
Xfuncs.h.tar
(4 KB)
📄
Xilinx7OD.bin.bin.tar.gz
(1.44 KB)
📄
Xilinx7OD.bin.tar
(4.5 KB)
📄
Xlib-xcb.h.h.tar.gz
(394 B)
📄
Xlib-xcb.h.tar
(2 KB)
📄
Xlib.h.h.tar.gz
(17.5 KB)
📄
Xlib.h.tar
(99 KB)
📄
XlibConf.h.h.tar.gz
(967 B)
📄
XlibConf.h.tar
(3.5 KB)
📄
Xlibint.h.h.tar.gz
(10.8 KB)
📄
Xlibint.h.tar
(41.5 KB)
📄
Xlocale.h.h.tar.gz
(822 B)
📄
Xlocale.h.tar
(3 KB)
📄
Xmd.h.h.tar.gz
(2.17 KB)
📄
Xmd.h.tar
(7 KB)
📄
Xos.h.h.tar.gz
(1.93 KB)
📄
Xos.h.tar
(6 KB)
📄
Xos_r.h.h.tar.gz
(6.64 KB)
📄
Xos_r.h.tar
(34.5 KB)
📄
Xosdefs.h.h.tar.gz
(1.47 KB)
📄
Xosdefs.h.tar
(5 KB)
📄
Xpoll.h.h.tar.gz
(2.46 KB)
📄
Xpoll.h.tar
(9.5 KB)
📄
Xproto.h.h.tar.gz
(10.5 KB)
📄
Xproto.h.tar
(53 KB)
📄
Xprotostr.h.h.tar.gz
(1.22 KB)
📄
Xprotostr.h.tar
(4.5 KB)
📄
Xref.pm.pm.tar.gz
(4.5 KB)
📄
Xref.pm.tar
(14 KB)
📄
Xregion.h.h.tar.gz
(2.21 KB)
📄
Xregion.h.tar
(7.5 KB)
📄
Xresource.h.h.tar.gz
(2.77 KB)
📄
Xresource.h.tar
(12 KB)
📄
Xthreads.h.h.tar.gz
(3.08 KB)
📄
Xthreads.h.tar
(14 KB)
📄
Xutil.h.h.tar.gz
(5.51 KB)
📄
Xutil.h.tar
(22.5 KB)
📄
Xw32defs.h.h.tar.gz
(743 B)
📄
Xw32defs.h.tar
(3.5 KB)
📄
Xwindows.h.h.tar.gz
(1.59 KB)
📄
Xwindows.h.tar
(5 KB)
📄
Xwinsock.h.h.tar.gz
(1.18 KB)
📄
Xwinsock.h.tar
(4 KB)
📄
YAML.tar
(13.5 KB)
📄
YAML.tar.gz
(4.22 KB)
📄
YAML.zip
(10.25 KB)
📄
[.tar
(55.5 KB)
📄
[.tar.gz
(25.26 KB)
📄
_.gif.gif.tar.gz
(152 B)
📄
_.gif.tar
(2 KB)
📄
_.htaccess.htaccess.tar.gz
(264 B)
📄
_.htaccess.tar
(48.5 KB)
📄
_4.3.0-2023-03-28.sql.3.0-2023-03-28.sql.tar.gz
(188 B)
📄
_4.3.0-2023-03-28.sql.tar
(2 KB)
📄
_LWPCookieJar.pyc.pyc.tar.gz
(2.68 KB)
📄
_LWPCookieJar.pyc.tar
(7 KB)
📄
_LWPCookieJar.pyo.pyo.tar.gz
(2.68 KB)
📄
_LWPCookieJar.pyo.tar
(7 KB)
📄
_MozillaCookieJar.py.py.tar.gz
(1.88 KB)
📄
_MozillaCookieJar.py.tar
(7.5 KB)
📄
_PM.e2x.e2x.tar.gz
(293 B)
📄
_PM.e2x.tar
(2 KB)
📄
__FILE.h.h.tar.gz
(175 B)
📄
__FILE.h.tar
(2 KB)
📄
__MACOSX.tar
(154.5 KB)
📄
__MACOSX.tar.gz
(4.33 KB)
📄
__MACOSX.zip
(84.47 KB)
📄
__api.json.json.tar.gz
(153 B)
📄
__api.json.tar
(2 KB)
📄
__config.php.php.tar.gz
(465 B)
📄
__config.php.tar
(2.5 KB)
📄
__fpos_t.h.h.tar.gz
(326 B)
📄
__fpos_t.h.tar
(2 KB)
📄
__future__.pyc.pyc.tar.gz
(1.82 KB)
📄
__future__.pyc.tar
(6 KB)
📄
__future__.pyo.pyo.tar.gz
(1.83 KB)
📄
__future__.pyo.tar
(6 KB)
📄
__init__.cpython-36.pyc.cpython-36.pyc.tar.gz
(2.04 KB)
📄
__init__.cpython-36.pyc.tar
(5 KB)
📄
__init__.cpython-38.opt-1.pyc.cpython-38.opt-1.pyc.tar.gz
(4.38 KB)
📄
__init__.cpython-38.opt-1.pyc.tar
(14 KB)
📄
__init__.py.py.tar.gz
(2.2 KB)
📄
__init__.py.tar
(596 KB)
📄
__init__.pyc.pyc.tar.gz
(4.36 KB)
📄
__init__.pyc.tar
(97.5 KB)
📄
__init__.pyo.pyo.tar.gz
(4.36 KB)
📄
__init__.pyo.tar
(97.5 KB)
📄
__main__.py.py.tar.gz
(215 B)
📄
__main__.py.tar
(4 KB)
📄
__mbstate_t.h.h.tar.gz
(420 B)
📄
__mbstate_t.h.tar
(2.5 KB)
📄
__phello__.foo.py.foo.py.tar.gz
(166 B)
📄
__phello__.foo.py.tar
(4 KB)
📄
__phello__.foo.pyc.foo.pyc.tar.gz
(177 B)
📄
__phello__.foo.pyc.tar
(2 KB)
📄
__phello__.foo.pyo.foo.pyo.tar.gz
(178 B)
📄
__phello__.foo.pyo.tar
(2 KB)
📄
__pycache__.tar
(20.77 MB)
📄
__pycache__.tar.gz
(480 B)
📄
__pycache__.zip
(20.61 MB)
📄
__upgrade.php.php.tar.gz
(1.01 KB)
📄
__upgrade.php.tar
(8 KB)
📄
__upgrade.xml.tar
(2 KB)
📄
__upgrade.xml.xml.tar.gz
(291 B)
📄
_abcoll.py.py.tar.gz
(4.36 KB)
📄
_abcoll.py.tar
(20 KB)
📄
_abcoll.pyc.pyc.tar.gz
(7.44 KB)
📄
_abcoll.pyc.tar
(27 KB)
📄
_abcoll.pyo.pyo.tar.gz
(7.44 KB)
📄
_abcoll.pyo.tar
(27 KB)
📄
_aix.py.py.tar.gz
(4.72 KB)
📄
_aix.py.tar
(14 KB)
📄
_app.php.php.tar.gz
(305 B)
📄
_app.php.tar
(4.5 KB)
📄
_blesta.php.php.tar.gz
(3.41 KB)
📄
_blesta.php.tar
(14.5 KB)
📄
_bootlocale.py.py.tar.gz
(650 B)
📄
_bootlocale.py.tar
(5.5 KB)
📄
_bootstrap.php.php.tar.gz
(2.02 KB)
📄
_bootstrap.php.tar
(7.5 KB)
📄
_cfg.php.php.tar.gz
(811 B)
📄
_cfg.php.tar
(3.5 KB)
📄
_clone.php.php.tar.gz
(1.12 KB)
📄
_clone.php.tar
(78.5 KB)
📄
_compat_pickle.py.py.tar.gz
(2.49 KB)
📄
_compat_pickle.py.tar
(20 KB)
📄
_compression.py.py.tar.gz
(1.73 KB)
📄
_compression.py.tar
(13 KB)
📄
_config.php.php.tar.gz
(695 B)
📄
_config.php.tar
(19.5 KB)
📄
_constants.php.php.tar.gz
(1.15 KB)
📄
_constants.php.tar
(4.5 KB)
📄
_edit.php.php.tar.gz
(1.01 KB)
📄
_edit.php.tar
(44.5 KB)
📄
_edit.xml.tar
(11 KB)
📄
_edit.xml.xml.tar.gz
(295 B)
📄
_encoded_words.py.py.tar.gz
(3.21 KB)
📄
_encoded_words.py.tar
(19 KB)
📄
_endian.py.py.tar.gz
(850 B)
📄
_endian.py.tar
(8.5 KB)
📄
_endian.pyc.pyc.tar.gz
(1.14 KB)
📄
_endian.pyc.tar
(4 KB)
📄
_endian.pyo.pyo.tar.gz
(1.13 KB)
📄
_endian.pyo.tar
(4 KB)
📄
_h2ph_pre.ph.ph.tar.gz
(4.26 KB)
📄
_h2ph_pre.ph.tar
(30.5 KB)
📄
_hashopenssl.h.h.tar.gz
(720 B)
📄
_hashopenssl.h.tar
(3 KB)
📄
_header_value_parser.py.py.tar.gz
(21.1 KB)
📄
_header_value_parser.py.tar
(204.5 KB)
📄
_htaccess.tar
(34.5 KB)
📄
_htaccess.tar.gz
(225 B)
📄
_index.php.php.tar.gz
(163 B)
📄
_index.php.tar
(100 KB)
📄
_markupbase.py.py.tar.gz
(3.64 KB)
📄
_markupbase.py.tar
(31 KB)
📄
_osx_support.py.py.tar.gz
(6.61 KB)
📄
_osx_support.py.tar
(62 KB)
📄
_pam_compat.h.h.tar.gz
(1.08 KB)
📄
_pam_compat.h.tar
(4.5 KB)
📄
_pam_macros.h.h.tar.gz
(1.74 KB)
📄
_pam_macros.h.tar
(7.5 KB)
📄
_pam_types.h.h.tar.gz
(4.91 KB)
📄
_pam_types.h.tar
(14.5 KB)
📄
_parseaddr.pyc.pyc.tar.gz
(5.54 KB)
📄
_parseaddr.pyc.tar
(15.5 KB)
📄
_parseaddr.pyo.pyo.tar.gz
(5.54 KB)
📄
_parseaddr.pyo.tar
(15.5 KB)
📄
_policybase.py.py.tar.gz
(4.62 KB)
📄
_policybase.py.tar
(32.5 KB)
📄
_py_abc.py.py.tar.gz
(1.93 KB)
📄
_py_abc.py.tar
(8 KB)
📄
_pyio.py.py.tar.gz
(21.22 KB)
📄
_pyio.py.tar
(248 KB)
📄
_pyio.pyc.pyc.tar.gz
(20.54 KB)
📄
_pyio.pyc.tar
(65 KB)
📄
_pyio.pyo.pyo.tar.gz
(20.55 KB)
📄
_pyio.pyo.tar
(65 KB)
📄
_sitebuiltins.py.py.tar.gz
(1.21 KB)
📄
_sitebuiltins.py.tar
(9 KB)
📄
_strptime.py.py.tar.gz
(7.31 KB)
📄
_strptime.py.tar
(72.5 KB)
📄
_sysconfigdata.py.py.tar.gz
(5.3 KB)
📄
_sysconfigdata.py.tar
(21 KB)
📄
_sysconfigdata.pyc.pyc.tar.gz
(7.71 KB)
📄
_sysconfigdata.pyc.tar
(24 KB)
📄
_sysconfigdata.pyo.pyo.tar.gz
(7.71 KB)
📄
_sysconfigdata.pyo.tar
(24 KB)
📄
_theme.css.css.tar.gz
(27.5 KB)
📄
_theme.css.tar
(179.5 KB)
📄
_threading_local.pyc.pyc.tar.gz
(2.57 KB)
📄
_threading_local.pyc.tar
(8 KB)
📄
_threading_local.pyo.pyo.tar.gz
(2.57 KB)
📄
_threading_local.pyo.tar
(8 KB)
📄
_thumb.php.php.tar.gz
(260 B)
📄
_thumb.php.tar
(2 KB)
📄
_update.php.php.tar.gz
(7.91 KB)
📄
_update.php.tar
(34 KB)
📄
_upgrade.php.php.tar.gz
(2.09 KB)
📄
_upgrade.php.tar
(59 KB)
📄
_upgrade.xml.tar
(12 KB)
📄
_upgrade.xml.xml.tar.gz
(293 B)
📄
_weakrefset.py.py.tar.gz
(1.44 KB)
📄
_weakrefset.py.tar
(20.5 KB)
📄
_weakrefset.pyc.pyc.tar.gz
(2.58 KB)
📄
_weakrefset.pyc.tar
(11 KB)
📄
_weakrefset.pyo.pyo.tar.gz
(2.58 KB)
📄
_weakrefset.pyo.tar
(11 KB)
📄
_wildcard_.4abetter.us.tar
(10.41 MB)
📄
_wildcard_.4abetter.us.tar.gz
(10.21 MB)
📄
_wildcard_.4abetter.us.zip
(10.4 MB)
📄
_wildcard_.gfects.com.tar
(111 KB)
📄
_wildcard_.gfects.com.tar.gz
(23.79 KB)
📄
_wildcard_.gfects.com.zip
(102.94 KB)
📄
_wp-config.php.php.tar.gz
(1.37 KB)
📄
_wp-config.php.tar
(76.5 KB)
📄
a.out.h.out.h.tar.gz
(1.58 KB)
📄
a.out.h.tar
(8.5 KB)
📄
a225_pfp.fw.fw.tar.gz
(738 B)
📄
a225_pfp.fw.tar
(3 KB)
📄
a225_pm4.fw.fw.tar.gz
(2.41 KB)
📄
a225_pm4.fw.tar
(21 KB)
📄
a2b16c4279e4fe2c728c80e15b2abff6167780.tar
(34.5 KB)
📄
a2b16c4279e4fe2c728c80e15b2abff6167780.tar.gz
(11.42 KB)
📄
a300_pfp.fw.fw.tar.gz
(698 B)
📄
a300_pfp.fw.tar
(7 KB)
📄
a300_pm4.fw.fw.tar.gz
(2.47 KB)
📄
a300_pm4.fw.tar
(41 KB)
📄
a330_pfp.fw.fw.tar.gz
(878 B)
📄
a330_pfp.fw.tar
(4 KB)
📄
a330_pm4.fw.fw.tar.gz
(2.38 KB)
📄
a330_pm4.fw.tar
(21 KB)
📄
a420_pfp.fw.fw.tar.gz
(2.47 KB)
📄
a420_pfp.fw.tar
(6 KB)
📄
a420_pm4.fw.fw.tar.gz
(2.53 KB)
📄
a420_pm4.fw.tar
(21 KB)
📄
a530_pfp.fw.fw.tar.gz
(6.86 KB)
📄
a530_pfp.fw.tar
(17.5 KB)
📄
a530_pm4.fw.fw.tar.gz
(4.92 KB)
📄
a530_pm4.fw.tar
(41 KB)
📄
a530_zap.mdt.mdt.tar.gz
(4.04 KB)
📄
a530_zap.mdt.tar
(36 KB)
📄
a530v3_gpmu.fw2.fw2.tar.gz
(5.57 KB)
📄
a530v3_gpmu.fw2.tar
(9.5 KB)
📄
a54225590697a85c95d7aec38fa8026fda3dc9.tar
(494.5 KB)
📄
a54225590697a85c95d7aec38fa8026fda3dc9.tar.gz
(196.44 KB)
📄
a612_rgmu.bin.bin.tar.gz
(1.23 KB)
📄
a612_rgmu.bin.tar
(4.5 KB)
📄
a623_gmu.bin.bin.tar.gz
(34.3 KB)
📄
a623_gmu.bin.tar
(107 KB)
📄
a630_gmu.bin.bin.tar.gz
(11.07 KB)
📄
a630_gmu.bin.tar
(66 KB)
📄
a630_sqe.fw.fw.tar.gz
(16.79 KB)
📄
a630_sqe.fw.tar
(69 KB)
📄
a640_gmu.bin.bin.tar.gz
(21.94 KB)
📄
a640_gmu.bin.tar
(76 KB)
📄
a650_gmu.bin.bin.tar.gz
(26.71 KB)
📄
a650_gmu.bin.tar
(84 KB)
📄
a650_sqe.fw.fw.tar.gz
(15.94 KB)
📄
a650_sqe.fw.tar
(65 KB)
📄
a660_gmu.bin.bin.tar.gz
(35.66 KB)
📄
a660_gmu.bin.tar
(110 KB)
📄
a660_sqe.fw.fw.tar.gz
(19.71 KB)
📄
a660_sqe.fw.tar
(87 KB)
📄
a663_gmu.bin.bin.tar.gz
(36.04 KB)
📄
a663_gmu.bin.tar
(112 KB)
📄
a702_sqe.fw.fw.tar.gz
(10.85 KB)
📄
a702_sqe.fw.tar
(42 KB)
📄
a730_sqe.fw.fw.tar.gz
(36.15 KB)
📄
a730_sqe.fw.tar
(151 KB)
📄
a740_sqe.fw.fw.tar.gz
(36.63 KB)
📄
a740_sqe.fw.tar
(152 KB)
📄
a7b5204e6a0d6eb84fcba64adc442e3a9b9386.tar
(281 KB)
📄
a7b5204e6a0d6eb84fcba64adc442e3a9b9386.tar.gz
(112.19 KB)
📄
a93edc049db4ebc2cbcc8150e6ba5cf4f87e54e9.svg.svg.tar.gz
(246 B)
📄
a93edc049db4ebc2cbcc8150e6ba5cf4f87e54e9.svg.tar
(2 KB)
📄
aai.la.la.tar.gz
(676 B)
📄
aai.la.tar
(3 KB)
📄
aarch64-linux.tar
(4.5 KB)
📄
aarch64-linux.tar.gz
(1.19 KB)
📄
aarch64-linux.zip
(3.11 KB)
📄
ab8e17425d50c8f530bc6cacead730a5871834.tar
(13.5 KB)
📄
ab8e17425d50c8f530bc6cacead730a5871834.tar.gz
(3.31 KB)
📄
abante.sql.sql.tar.gz
(272.79 KB)
📄
abante.sql.tar
(1.42 MB)
📄
abante.tar
(49.5 MB)
📄
abante.tar.gz
(45.65 MB)
📄
abante.zip
(49.47 MB)
📄
abc.py.py.tar.gz
(2.49 KB)
📄
abc.py.tar
(23 KB)
📄
abc.pyc.pyc.tar.gz
(2.59 KB)
📄
abc.pyc.tar
(7.5 KB)
📄
abc.pyo.pyo.tar.gz
(2.57 KB)
📄
abc.pyo.tar
(7.5 KB)
📄
abi.h.h.tar.gz
(941 B)
📄
abi.h.tar
(4 KB)
📄
abi.tar
(2 KB)
📄
abi.tar.gz
(93 B)
📄
abi.zip
(156 B)
📄
about.php.php.tar.gz
(692 B)
📄
about.php.tar
(3 KB)
📄
about.xpm.tar
(4 KB)
📄
about.xpm.xpm.tar.gz
(370 B)
📄
aboutDialog.pyc.pyc.tar.gz
(2.72 KB)
📄
aboutDialog.pyc.tar
(8.5 KB)
📄
aboutDialog.pyo.pyo.tar.gz
(2.72 KB)
📄
aboutDialog.pyo.tar
(8.5 KB)
📄
ac.rb.rb.tar.gz
(595 B)
📄
ac.rb.tar
(3 KB)
📄
accelerator-performance.tar
(4 KB)
📄
accelerator-performance.tar.gz
(1.15 KB)
📄
accelerator-performance.zip
(2.26 KB)
📄
accept_dad.tar
(3 KB)
📄
accept_dad.tar.gz
(121 B)
📄
accept_local.tar
(2 KB)
📄
accept_local.tar.gz
(121 B)
📄
accept_ra.tar
(2 KB)
📄
accept_ra.tar.gz
(119 B)
📄
accept_ra_defrtr.tar
(2 KB)
📄
accept_ra_defrtr.tar.gz
(122 B)
📄
accept_ra_mtu.tar
(3 KB)
📄
accept_ra_mtu.tar.gz
(122 B)
📄
accept_ra_pinfo.tar
(3 KB)
📄
accept_ra_pinfo.tar.gz
(124 B)
📄
accept_ra_rtr_pref.tar
(2 KB)
📄
accept_ra_rtr_pref.tar.gz
(125 B)
📄
accept_redirects.tar
(5 KB)
📄
accept_redirects.tar.gz
(124 B)
📄
access-logs.tar
(3.05 MB)
📄
access-logs.tar.gz
(144.37 KB)
📄
access-logs.zip
(3.52 MB)
📄
access.php.php.tar.gz
(581 B)
📄
access.php.tar
(2.5 KB)
📄
acct.h.h.tar.gz
(1.42 KB)
📄
acct.h.tar
(5 KB)
📄
acct.tar
(2 KB)
📄
acct.tar.gz
(110 B)
📄
acenic.tar
(149.5 KB)
📄
acenic.tar.gz
(49.45 KB)
📄
acenic.zip
(147.31 KB)
📄
acl.auth.php.auth.php.tar.gz
(235 B)
📄
acl.auth.php.tar
(2 KB)
📄
acl.rb.rb.tar.gz
(1.71 KB)
📄
acl.rb.tar
(43.5 KB)
📄
aclocal-1.16.16.tar.gz
(12.12 KB)
📄
aclocal-1.16.tar
(37.5 KB)
📄
aclocal.tar
(37.5 KB)
📄
aclocal.tar.gz
(12.11 KB)
📄
acpi.mod.mod.tar.gz
(5.55 KB)
📄
acpi.mod.tar
(15 KB)
📄
acpi.tar
(2 KB)
📄
acpi.tar.gz
(123 B)
📄
acpi.zip
(183 B)
📄
activate.csh.csh.tar.gz
(525 B)
📄
activate.csh.tar
(4 KB)
📄
activate.fish.fish.tar.gz
(918 B)
📄
activate.fish.tar
(4 KB)
📄
activate.tar
(4 KB)
📄
activate.tar.gz
(908 B)
📄
adaptec.tar
(4 KB)
📄
adaptec.tar.gz
(526 B)
📄
adaptec.zip
(1.92 KB)
📄
adb.tar
(25.5 KB)
📄
adb.tar.gz
(18.17 KB)
📄
add-ons.tar
(865.5 KB)
📄
add-ons.tar.gz
(131.6 KB)
📄
add-ons.zip
(805.1 KB)
📄
add_addr_timeout.tar
(2 KB)
📄
add_addr_timeout.tar.gz
(119 B)
📄
add_admin.php.php.tar.gz
(492 B)
📄
add_admin.php.tar
(5.5 KB)
📄
add_user.php.php.tar.gz
(398 B)
📄
add_user.php.tar
(22 KB)
📄
addr2line.tar
(35 KB)
📄
addr2line.tar.gz
(13.81 KB)
📄
addr_gen_mode.tar
(3 KB)
📄
addr_gen_mode.tar.gz
(123 B)
📄
adi930.fw.fw.tar.gz
(5.74 KB)
📄
adi930.fw.tar
(9.5 KB)
📄
adler32.mod.mod.tar.gz
(761 B)
📄
adler32.mod.tar
(3 KB)
📄
adlp_dmc.bin.bin.tar.gz
(19.02 KB)
📄
adlp_dmc.bin.tar
(157 KB)
📄
adlp_dmc_ver2_09.bin.bin.tar.gz
(14.33 KB)
📄
adlp_dmc_ver2_09.bin.tar
(45.5 KB)
📄
adlp_dmc_ver2_10.bin.bin.tar.gz
(14.34 KB)
📄
adlp_dmc_ver2_10.bin.tar
(45.5 KB)
📄
adlp_dmc_ver2_12.bin.bin.tar.gz
(17.67 KB)
📄
adlp_dmc_ver2_12.bin.tar
(72 KB)
📄
adlp_dmc_ver2_14.bin.bin.tar.gz
(18.32 KB)
📄
adlp_dmc_ver2_14.bin.tar
(77 KB)
📄
adlp_dmc_ver2_16.bin.bin.tar.gz
(18.33 KB)
📄
adlp_dmc_ver2_16.bin.tar
(77 KB)
📄
adlp_guc_70.bin.bin.tar.gz
(144.4 KB)
📄
adlp_guc_70.bin.tar
(341.5 KB)
📄
adls_dmc_ver2_01.bin.bin.tar.gz
(6.12 KB)
📄
adls_dmc_ver2_01.bin.tar
(20 KB)
📄
admidio.sql.sql.tar.gz
(16.64 KB)
📄
admidio.sql.tar
(100.5 KB)
📄
admidio.tar
(15.21 MB)
📄
admidio.tar.gz
(14.41 MB)
📄
admidio.zip
(15.18 MB)
📄
admin.h.h.tar.gz
(4.22 KB)
📄
admin.h.tar
(22 KB)
📄
admin.html.html.tar.gz
(2.39 KB)
📄
admin.html.tar
(9.5 KB)
📄
admin.tar
(216 KB)
📄
admin.tar.gz
(196.34 KB)
📄
admin.yaml.tar
(2 KB)
📄
admin.yaml.yaml.tar.gz
(225 B)
📄
admin.zip
(214.44 KB)
📄
admin_counted.tar
(2 KB)
📄
admin_counted.tar.gz
(119 B)
📄
admin_reserve_kbytes.tar
(2 KB)
📄
admin_reserve_kbytes.tar.gz
(120 B)
📄
admincp.inc.inc.tar.gz
(1.3 KB)
📄
admincp.inc.tar
(6 KB)
📄
adminer.tar
(464.5 KB)
📄
adminer.tar.gz
(402.14 KB)
📄
adminer.zip
(442.66 KB)
📄
admpass.sh.sh.tar.gz
(665 B)
📄
admpass.sh.tar
(3 KB)
📄
adsp.mbn.mbn.tar.gz
(11.75 MB)
📄
adsp.mbn.tar
(74.48 MB)
📄
adspr.jsn.jsn.tar.gz
(272 B)
📄
adspr.jsn.tar
(3.5 KB)
📄
adsps.jsn.jsn.tar.gz
(338 B)
📄
adsps.jsn.tar
(2.5 KB)
📄
adspua.jsn.jsn.tar.gz
(365 B)
📄
adspua.jsn.tar
(2.5 KB)
📄
adspuo.jsn.jsn.tar.gz
(340 B)
📄
adspuo.jsn.tar
(2 KB)
📄
advansys.tar
(22.5 KB)
📄
advansys.tar.gz
(13.34 KB)
📄
advansys.zip
(19.1 KB)
📄
advpoll.tar
(173 KB)
📄
advpoll.tar.gz
(91.46 KB)
📄
advpoll.zip
(146.01 KB)
📄
aef.png.png.tar.gz
(9.3 KB)
📄
aef.png.tar
(11 KB)
📄
aef.tar
(238 KB)
📄
aef.tar.gz
(110.06 KB)
📄
aef.zip
(211.15 KB)
📄
aeonsemi.tar
(257 KB)
📄
aeonsemi.tar.gz
(151.29 KB)
📄
aeonsemi.zip
(255.43 KB)
📄
afalg.so.so.tar.gz
(7.9 KB)
📄
afalg.so.tar
(22 KB)
📄
afc87ac7ed4f8b330bf89e69b605aafa26fabc.tar
(21.5 KB)
📄
afc87ac7ed4f8b330bf89e69b605aafa26fabc.tar.gz
(7.23 KB)
📄
affinity_hint.tar
(30 KB)
📄
affinity_hint.tar.gz
(115 B)
📄
affs.mod.mod.tar.gz
(3.44 KB)
📄
affs.mod.tar
(9 KB)
📄
afs.mod.mod.tar.gz
(4.29 KB)
📄
afs.mod.tar
(20 KB)
📄
agere_ap_fw.bin.bin.tar.gz
(27.14 KB)
📄
agere_ap_fw.bin.tar
(51.5 KB)
📄
agere_sta_fw.bin.bin.tar.gz
(31.85 KB)
📄
agere_sta_fw.bin.tar
(65.5 KB)
📄
agora.sql.sql.tar.gz
(4.11 KB)
📄
agora.sql.tar
(32 KB)
📄
agora.tar
(13.33 MB)
📄
agora.tar.gz
(12.72 MB)
📄
agora.zip
(13.3 MB)
📄
ahci.mod.mod.tar.gz
(6.36 KB)
📄
ahci.mod.tar
(23 KB)
📄
aibolit-resident.socket.socket.tar.gz
(276 B)
📄
aibolit-resident.socket.tar
(2 KB)
📄
aic100.tar
(4.87 MB)
📄
aic100.tar.gz
(1.89 MB)
📄
aic100.zip
(4.87 MB)
📄
aifc.py.py.tar.gz
(7.1 KB)
📄
aifc.py.tar
(101 KB)
📄
aifc.pyc.pyc.tar.gz
(9.98 KB)
📄
aifc.pyc.tar
(31.5 KB)
📄
aifc.pyo.pyo.tar.gz
(9.98 KB)
📄
aifc.pyo.tar
(31.5 KB)
📄
aio-max-nr.tar
(2 KB)
📄
aio-max-nr.tar.gz
(110 B)
📄
aio-nr.tar
(2 KB)
📄
aio-nr.tar.gz
(106 B)
📄
aio.h.h.tar.gz
(2.22 KB)
📄
aio.h.tar
(9 KB)
📄
airoha.tar
(429 KB)
📄
airoha.tar.gz
(179.93 KB)
📄
airoha.zip
(425.4 KB)
📄
ajax-actions.php.php.tar.gz
(27.26 KB)
📄
ajax-actions.php.tar
(131.5 KB)
📄
ajaxchat.tar
(148 KB)
📄
ajaxchat.tar.gz
(71.29 KB)
📄
ajaxchat.zip
(123.27 KB)
📄
akaunting.sql.sql.tar.gz
(9.05 KB)
📄
akaunting.sql.tar
(78.5 KB)
📄
akaunting.tar
(72.03 MB)
📄
akaunting.tar.gz
(67.5 MB)
📄
akaunting.zip
(72.01 MB)
📄
aldebaran_mec2.bin.bin.tar.gz
(34.96 KB)
📄
aldebaran_mec2.bin.tar
(264 KB)
📄
aldebaran_sdma.bin.bin.tar.gz
(10.1 KB)
📄
aldebaran_sdma.bin.tar
(35 KB)
📄
aldebaran_sjt_mec.bin.bin.tar.gz
(35.18 KB)
📄
aldebaran_sjt_mec.bin.tar
(264 KB)
📄
aldebaran_sjt_mec2.bin.bin.tar.gz
(35.18 KB)
📄
aldebaran_sjt_mec2.bin.tar
(264 KB)
📄
aldebaran_ta.bin.bin.tar.gz
(43.21 KB)
📄
aldebaran_ta.bin.tar
(138.5 KB)
📄
alegro.tar
(201 KB)
📄
alegro.tar.gz
(111.82 KB)
📄
alegro.zip
(173.84 KB)
📄
alembic.tar
(3 KB)
📄
alembic.tar.gz
(256 B)
📄
alias.rb.rb.tar.gz
(1 KB)
📄
alias.rb.tar
(22 KB)
📄
aliases.h.h.tar.gz
(928 B)
📄
aliases.h.tar
(3.5 KB)
📄
aliases.tar
(3 KB)
📄
aliases.tar.gz
(770 B)
📄
all.tar
(56.5 KB)
📄
all.tar.gz
(12.02 KB)
📄
all.zip
(18.53 KB)
📄
all_video.mod.mod.tar.gz
(301 B)
📄
all_video.mod.tar
(3 KB)
📄
allocated_dquots.tar
(2 KB)
📄
allocated_dquots.tar.gz
(118 B)
📄
allow-host-ipv6.xml.tar
(2.5 KB)
📄
allow-host-ipv6.xml.xml.tar.gz
(383 B)
📄
allow_dio.tar
(2 KB)
📄
allow_dio.tar.gz
(107 B)
📄
alpha-linux.tar
(4.5 KB)
📄
alpha-linux.tar.gz
(1.19 KB)
📄
alpha-linux.zip
(3.11 KB)
📄
alphaev5-linux.tar
(4.5 KB)
📄
alphaev5-linux.tar.gz
(1.2 KB)
📄
alphaev5-linux.zip
(3.12 KB)
📄
alphaev56-linux.tar
(4.5 KB)
📄
alphaev56-linux.tar.gz
(1.2 KB)
📄
alphaev56-linux.zip
(3.12 KB)
📄
alphaev6-linux.tar
(4.5 KB)
📄
alphaev6-linux.tar.gz
(1.2 KB)
📄
alphaev6-linux.zip
(3.12 KB)
📄
alphaev67-linux.tar
(4.5 KB)
📄
alphaev67-linux.tar.gz
(1.2 KB)
📄
alphaev67-linux.zip
(3.12 KB)
📄
alphapca56-linux.tar
(4.5 KB)
📄
alphapca56-linux.tar.gz
(1.2 KB)
📄
alphapca56-linux.zip
(3.12 KB)
📄
already_install.tar
(2 KB)
📄
already_install.tar.gz
(122 B)
📄
alt-ImageMagick.tar
(58.4 MB)
📄
alt-ImageMagick.tar.gz
(23.07 MB)
📄
alt-ImageMagick.zip
(58.23 MB)
📄
alt-nodejs10_native.req.req.tar.gz
(165 B)
📄
alt-nodejs10_native.req.tar
(2 KB)
📄
alt-nodejs11_native.req.req.tar.gz
(165 B)
📄
alt-nodejs11_native.req.tar
(2 KB)
📄
alt-nodejs12_native.req.req.tar.gz
(164 B)
📄
alt-nodejs12_native.req.tar
(2 KB)
📄
alt-nodejs14_native.req.req.tar.gz
(166 B)
📄
alt-nodejs14_native.req.tar
(2 KB)
📄
alt-nodejs16_native.req.req.tar.gz
(151 B)
📄
alt-nodejs16_native.req.tar
(2 KB)
📄
alt-nodejs18_native.req.req.tar.gz
(151 B)
📄
alt-nodejs18_native.req.tar
(2 KB)
📄
alt-nodejs19_native.req.req.tar.gz
(148 B)
📄
alt-nodejs19_native.req.tar
(2 KB)
📄
alt-nodejs20_native.req.req.tar.gz
(151 B)
📄
alt-nodejs20_native.req.tar
(2 KB)
📄
alt-nodejs22_native.req.req.tar.gz
(154 B)
📄
alt-nodejs22_native.req.tar
(3 KB)
📄
alt-nodejs24_native.req.req.tar.gz
(151 B)
📄
alt-nodejs24_native.req.tar
(2 KB)
📄
alt-nodejs6_native.req.req.tar.gz
(161 B)
📄
alt-nodejs6_native.req.tar
(3 KB)
📄
alt-nodejs8_native.req.req.tar.gz
(166 B)
📄
alt-nodejs8_native.req.tar
(3 KB)
📄
alt-nodejs9_native.req.req.tar.gz
(167 B)
📄
alt-nodejs9_native.req.tar
(3 KB)
📄
alt-php-config.tar
(24.5 KB)
📄
alt-php-config.tar.gz
(4.91 KB)
📄
alt-php-config.zip
(19.26 KB)
📄
alt-php72-fpm.service.service.tar.gz
(333 B)
📄
alt-php72-fpm.service.tar
(2 KB)
📄
alt-php80-pecl-amqp_2.1.2-1.el8.tar
(85 KB)
📄
alt-php80-pecl-amqp_2.1.2-1.el8.tar.gz
(7.57 KB)
📄
alt-php80-pecl-amqp_2.1.2-1.el8.zip
(56.03 KB)
📄
alt-php80-pecl-brotli_0.18.3-2.el8.tar
(9.6 MB)
📄
alt-php80-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php80-pecl-gearman_2.1.4-1.el8.tar
(121 KB)
📄
alt-php80-pecl-gearman_2.1.4-1.el8.tar.gz
(10.11 KB)
📄
alt-php80-pecl-http_4.2.6-4.el8.tar
(269.5 KB)
📄
alt-php80-pecl-http_4.2.6-4.el8.tar.gz
(39.06 KB)
📄
alt-php80-pecl-http_4.2.6-4.el8.zip
(175.95 KB)
📄
alt-php80-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php80-pecl-inotify_3.0.0-1.el8.tar.gz
(875 B)
📄
alt-php80-pecl-leveldb_0.3.0-1.el8.tar
(34 KB)
📄
alt-php80-pecl-leveldb_0.3.0-1.el8.tar.gz
(3.92 KB)
📄
alt-php80-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php80-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.82 KB)
📄
alt-php80-pecl-oci8_3.0.1-1.el8.tar
(25 KB)
📄
alt-php80-pecl-oci8_3.0.1-1.el8.tar.gz
(2.48 KB)
📄
alt-php80-pecl-oci8_3.0.1-1.el8.zip
(18.17 KB)
📄
alt-php80-pecl-solr_2.7.0-1.el8.tar
(747 KB)
📄
alt-php80-pecl-solr_2.7.0-1.el8.tar.gz
(468.02 KB)
📄
alt-php80-pecl-solr_2.7.0-1.el8.zip
(653.54 KB)
📄
alt-php80-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php80-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.23 KB)
📄
alt-php80-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php80-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php80-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php80-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php80-pecl-yaml_2.2.3-1.el8.tar
(134.5 KB)
📄
alt-php80-pecl-yaml_2.2.3-1.el8.tar.gz
(17.44 KB)
📄
alt-php80-pecl-yaml_2.2.3-1.el8.zip
(90.11 KB)
📄
alt-php81-pecl-amqp_2.1.2-1.el8.tar
(85 KB)
📄
alt-php81-pecl-amqp_2.1.2-1.el8.tar.gz
(7.56 KB)
📄
alt-php81-pecl-amqp_2.1.2-1.el8.zip
(56.03 KB)
📄
alt-php81-pecl-brotli_0.18.3-2.el8.tar
(9.66 MB)
📄
alt-php81-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php81-pecl-gearman_2.1.4-1.el8.tar
(121 KB)
📄
alt-php81-pecl-gearman_2.1.4-1.el8.tar.gz
(10.12 KB)
📄
alt-php81-pecl-http_4.2.6-4.el8.tar
(269.5 KB)
📄
alt-php81-pecl-http_4.2.6-4.el8.tar.gz
(39.07 KB)
📄
alt-php81-pecl-http_4.2.6-4.el8.zip
(175.95 KB)
📄
alt-php81-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php81-pecl-inotify_3.0.0-1.el8.tar.gz
(875 B)
📄
alt-php81-pecl-leveldb_0.3.0-1.el8.tar
(34 KB)
📄
alt-php81-pecl-leveldb_0.3.0-1.el8.tar.gz
(3.93 KB)
📄
alt-php81-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php81-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.82 KB)
📄
alt-php81-pecl-oci8_3.2.1-1.el8.tar
(25 KB)
📄
alt-php81-pecl-oci8_3.2.1-1.el8.tar.gz
(2.51 KB)
📄
alt-php81-pecl-oci8_3.2.1-1.el8.zip
(17.99 KB)
📄
alt-php81-pecl-solr_2.7.0-1.el8.tar
(747 KB)
📄
alt-php81-pecl-solr_2.7.0-1.el8.tar.gz
(468.02 KB)
📄
alt-php81-pecl-solr_2.7.0-1.el8.zip
(653.54 KB)
📄
alt-php81-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php81-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.23 KB)
📄
alt-php81-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php81-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php81-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php81-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php81-pecl-yaml_2.2.3-1.el8.tar
(134.5 KB)
📄
alt-php81-pecl-yaml_2.2.3-1.el8.tar.gz
(17.44 KB)
📄
alt-php81-pecl-yaml_2.2.3-1.el8.zip
(90.11 KB)
📄
alt-php82-geos_1.0.0-1.dfe1ab17b0.el8.zip
(93.94 KB)
📄
alt-php82-pecl-amqp_2.1.2-1.el8.tar
(85 KB)
📄
alt-php82-pecl-amqp_2.1.2-1.el8.tar.gz
(7.57 KB)
📄
alt-php82-pecl-amqp_2.1.2-1.el8.zip
(56.03 KB)
📄
alt-php82-pecl-brotli_0.18.3-2.el8.tar
(9.66 MB)
📄
alt-php82-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php82-pecl-gearman_2.1.4-1.el8.tar
(121 KB)
📄
alt-php82-pecl-gearman_2.1.4-1.el8.tar.gz
(10.12 KB)
📄
alt-php82-pecl-http_4.2.6-4.el8.tar
(269.5 KB)
📄
alt-php82-pecl-http_4.2.6-4.el8.tar.gz
(39.07 KB)
📄
alt-php82-pecl-http_4.2.6-4.el8.zip
(175.95 KB)
📄
alt-php82-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php82-pecl-inotify_3.0.0-1.el8.tar.gz
(874 B)
📄
alt-php82-pecl-leveldb_0.3.0-1.el8.tar
(34 KB)
📄
alt-php82-pecl-leveldb_0.3.0-1.el8.tar.gz
(3.93 KB)
📄
alt-php82-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php82-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.82 KB)
📄
alt-php82-pecl-oci8_3.4.0-1.el8.tar
(25 KB)
📄
alt-php82-pecl-oci8_3.4.0-1.el8.tar.gz
(2.53 KB)
📄
alt-php82-pecl-oci8_3.4.0-1.el8.zip
(18.42 KB)
📄
alt-php82-pecl-solr_2.7.0-1.el8.tar
(747 KB)
📄
alt-php82-pecl-solr_2.7.0-1.el8.tar.gz
(468.01 KB)
📄
alt-php82-pecl-solr_2.7.0-1.el8.zip
(653.54 KB)
📄
alt-php82-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php82-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.22 KB)
📄
alt-php82-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php82-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php82-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php82-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php82-pecl-yaml_2.2.3-1.el8.tar
(134.5 KB)
📄
alt-php82-pecl-yaml_2.2.3-1.el8.tar.gz
(17.44 KB)
📄
alt-php82-pecl-yaml_2.2.3-1.el8.zip
(90.11 KB)
📄
alt-php83-pecl-amqp_2.1.2-1.el8.tar
(85 KB)
📄
alt-php83-pecl-amqp_2.1.2-1.el8.tar.gz
(7.56 KB)
📄
alt-php83-pecl-amqp_2.1.2-1.el8.zip
(56.03 KB)
📄
alt-php83-pecl-brotli_0.18.3-2.el8.tar
(9.66 MB)
📄
alt-php83-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php83-pecl-gearman_2.1.4-1.el8.tar
(121 KB)
📄
alt-php83-pecl-gearman_2.1.4-1.el8.tar.gz
(10.12 KB)
📄
alt-php83-pecl-http_4.2.6-4.el8.tar
(269.5 KB)
📄
alt-php83-pecl-http_4.2.6-4.el8.tar.gz
(39.08 KB)
📄
alt-php83-pecl-http_4.2.6-4.el8.zip
(175.95 KB)
📄
alt-php83-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php83-pecl-inotify_3.0.0-1.el8.tar.gz
(875 B)
📄
alt-php83-pecl-leveldb_0.3.0-1.el8.tar
(34 KB)
📄
alt-php83-pecl-leveldb_0.3.0-1.el8.tar.gz
(3.92 KB)
📄
alt-php83-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php83-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.82 KB)
📄
alt-php83-pecl-oci8_3.4.0-1.el8.tar
(25 KB)
📄
alt-php83-pecl-oci8_3.4.0-1.el8.tar.gz
(2.53 KB)
📄
alt-php83-pecl-oci8_3.4.0-1.el8.zip
(18.42 KB)
📄
alt-php83-pecl-solr_2.7.0-1.el8.tar
(747 KB)
📄
alt-php83-pecl-solr_2.7.0-1.el8.tar.gz
(468.02 KB)
📄
alt-php83-pecl-solr_2.7.0-1.el8.zip
(653.54 KB)
📄
alt-php83-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php83-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.22 KB)
📄
alt-php83-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php83-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php83-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php83-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php83-pecl-yaml_2.2.3-1.el8.tar
(134.5 KB)
📄
alt-php83-pecl-yaml_2.2.3-1.el8.tar.gz
(17.44 KB)
📄
alt-php83-pecl-yaml_2.2.3-1.el8.zip
(90.11 KB)
📄
alt-php84-pecl-amqp_2.1.2-1.el8.tar
(85 KB)
📄
alt-php84-pecl-amqp_2.1.2-1.el8.tar.gz
(7.56 KB)
📄
alt-php84-pecl-amqp_2.1.2-1.el8.zip
(56.03 KB)
📄
alt-php84-pecl-brotli_0.18.3-2.el8.tar
(9.66 MB)
📄
alt-php84-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php84-pecl-eio_3.1.3-3.el8.tar
(45.5 KB)
📄
alt-php84-pecl-eio_3.1.3-3.el8.tar.gz
(5.39 KB)
📄
alt-php84-pecl-gearman_2.1.4-1.el8.tar
(121 KB)
📄
alt-php84-pecl-gearman_2.1.4-1.el8.tar.gz
(10.11 KB)
📄
alt-php84-pecl-http_4.2.6-4.el8.tar
(266 KB)
📄
alt-php84-pecl-http_4.2.6-4.el8.tar.gz
(38.33 KB)
📄
alt-php84-pecl-http_4.2.6-4.el8.zip
(173.55 KB)
📄
alt-php84-pecl-imap_1.0.3-1.el8.tar
(177 KB)
📄
alt-php84-pecl-imap_1.0.3-1.el8.tar.gz
(23.63 KB)
📄
alt-php84-pecl-imap_1.0.3-1.el8.zip
(116.91 KB)
📄
alt-php84-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php84-pecl-inotify_3.0.0-1.el8.tar.gz
(875 B)
📄
alt-php84-pecl-leveldb_0.3.0-1.el8.tar
(34 KB)
📄
alt-php84-pecl-leveldb_0.3.0-1.el8.tar.gz
(3.92 KB)
📄
alt-php84-pecl-mailparse_3.1.8-1.el8.tar
(973.5 KB)
📄
alt-php84-pecl-mailparse_3.1.8-1.el8.tar.gz
(894.98 KB)
📄
alt-php84-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php84-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.83 KB)
📄
alt-php84-pecl-oci8_3.4.0-1.el8.tar
(25 KB)
📄
alt-php84-pecl-oci8_3.4.0-1.el8.tar.gz
(2.53 KB)
📄
alt-php84-pecl-oci8_3.4.0-1.el8.zip
(18.42 KB)
📄
alt-php84-pecl-pdo_oci_1.2.0-1.el8.tar
(113.5 KB)
📄
alt-php84-pecl-pdo_oci_1.2.0-1.el8.tar.gz
(16.07 KB)
📄
alt-php84-pecl-solr_2.7.0-2.el8.tar
(747 KB)
📄
alt-php84-pecl-solr_2.7.0-2.el8.tar.gz
(468.02 KB)
📄
alt-php84-pecl-solr_2.7.0-2.el8.zip
(653.54 KB)
📄
alt-php84-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php84-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.23 KB)
📄
alt-php84-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php84-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php84-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php84-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php84-pecl-yaml_2.2.3-1.el8.tar
(134.5 KB)
📄
alt-php84-pecl-yaml_2.2.3-1.el8.tar.gz
(17.44 KB)
📄
alt-php84-pecl-yaml_2.2.3-1.el8.zip
(90.11 KB)
📄
alt-php85-pecl-amqp_2.1.2-2.el8.tar
(85 KB)
📄
alt-php85-pecl-amqp_2.1.2-2.el8.tar.gz
(7.61 KB)
📄
alt-php85-pecl-amqp_2.1.2-2.el8.zip
(56.2 KB)
📄
alt-php85-pecl-brotli_0.18.3-2.el8.tar
(9.66 MB)
📄
alt-php85-pecl-brotli_0.18.3-2.el8.tar.gz
(2.1 MB)
📄
alt-php85-pecl-gearman_2.1.4-2.el8.tar
(121 KB)
📄
alt-php85-pecl-gearman_2.1.4-2.el8.tar.gz
(10.12 KB)
📄
alt-php85-pecl-http_4.3.1-5.el8.tar
(269.5 KB)
📄
alt-php85-pecl-http_4.3.1-5.el8.tar.gz
(39.59 KB)
📄
alt-php85-pecl-http_4.3.1-5.el8.zip
(175.95 KB)
📄
alt-php85-pecl-imap_1.0.3-2.el8.tar
(176.5 KB)
📄
alt-php85-pecl-imap_1.0.3-2.el8.tar.gz
(23.6 KB)
📄
alt-php85-pecl-imap_1.0.3-2.el8.zip
(116.75 KB)
📄
alt-php85-pecl-inotify_3.0.0-1.el8.tar
(5 KB)
📄
alt-php85-pecl-inotify_3.0.0-1.el8.tar.gz
(875 B)
📄
alt-php85-pecl-leveldb_0.3.0-2.el8.tar
(34 KB)
📄
alt-php85-pecl-leveldb_0.3.0-2.el8.tar.gz
(3.92 KB)
📄
alt-php85-pecl-mongodb_2.1.4-3.el8.tar
(3.93 MB)
📄
alt-php85-pecl-mongodb_2.1.4-3.el8.tar.gz
(487.63 KB)
📄
alt-php85-pecl-msgpack_2.2.0-1.el8.tar
(1.6 MB)
📄
alt-php85-pecl-msgpack_2.2.0-1.el8.tar.gz
(109.82 KB)
📄
alt-php85-pecl-oci8_3.4.0-3.el8.tar
(25 KB)
📄
alt-php85-pecl-oci8_3.4.0-3.el8.tar.gz
(2.53 KB)
📄
alt-php85-pecl-oci8_3.4.0-3.el8.zip
(18.42 KB)
📄
alt-php85-pecl-pdo_oci_1.2.0-1.el8.tar
(113.5 KB)
📄
alt-php85-pecl-pdo_oci_1.2.0-1.el8.tar.gz
(16.07 KB)
📄
alt-php85-pecl-solr_2.7.0-3.el8.tar
(747 KB)
📄
alt-php85-pecl-solr_2.7.0-3.el8.tar.gz
(468.01 KB)
📄
alt-php85-pecl-solr_2.7.0-3.el8.zip
(653.54 KB)
📄
alt-php85-pecl-ssh2_1.4.1-1.el8.tar
(23.5 KB)
📄
alt-php85-pecl-ssh2_1.4.1-1.el8.tar.gz
(4.23 KB)
📄
alt-php85-pecl-ssh2_1.4.1-1.el8.zip
(13.05 KB)
📄
alt-php85-pecl-uuid_1.2.0-1.el8.tar
(15 KB)
📄
alt-php85-pecl-uuid_1.2.0-1.el8.tar.gz
(1.59 KB)
📄
alt-php85-pecl-uuid_1.2.0-1.el8.zip
(7.8 KB)
📄
alt-php85-pecl-yaml_2.2.3-2.el8.tar
(135 KB)
📄
alt-php85-pecl-yaml_2.2.3-2.el8.tar.gz
(17.57 KB)
📄
alt-php85-pecl-yaml_2.2.3-2.el8.zip
(90.13 KB)
📄
amanda.xml.tar
(2 KB)
📄
amanda.xml.xml.tar.gz
(209 B)
📄
amd-ucode.tar
(303.5 KB)
📄
amd-ucode.tar.gz
(239.63 KB)
📄
amd-ucode.zip
(298.67 KB)
📄
amd.tar
(612.5 KB)
📄
amd.tar.gz
(399.47 KB)
📄
amd.zip
(608.13 KB)
📄
amd64-linux.tar
(4.5 KB)
📄
amd64-linux.tar.gz
(1.19 KB)
📄
amd64-linux.zip
(3.1 KB)
📄
amd_hsmp.h.h.tar.gz
(2.33 KB)
📄
amd_hsmp.h.tar
(10.5 KB)
📄
amd_pmf_v3.bin.bin.tar.gz
(6.12 KB)
📄
amd_pmf_v3.bin.tar
(14.5 KB)
📄
amd_pmf_v3_1.bin.bin.tar.gz
(7.4 KB)
📄
amd_pmf_v3_1.bin.tar
(18.5 KB)
📄
amd_sev_fam17h_model0xh.sbin.sbin.tar.gz
(22.6 KB)
📄
amd_sev_fam17h_model0xh.sbin.tar
(34.5 KB)
📄
amd_sev_fam17h_model3xh.sbin.sbin.tar.gz
(30.99 KB)
📄
amd_sev_fam17h_model3xh.sbin.tar
(46 KB)
📄
amd_sev_fam19h_model0xh.sbin.sbin.tar.gz
(63.92 KB)
📄
amd_sev_fam19h_model0xh.sbin.tar
(97 KB)
📄
amd_sev_fam19h_model1xh.sbin.sbin.tar.gz
(66.61 KB)
📄
amd_sev_fam19h_model1xh.sbin.tar
(105 KB)
📄
amd_sev_fam19h_modelaxh.sbin.sbin.tar.gz
(66.61 KB)
📄
amd_sev_fam19h_modelaxh.sbin.tar
(105 KB)
📄
amd_sev_fam1ah_model0xh.sbin.sbin.tar.gz
(149.37 KB)
📄
amd_sev_fam1ah_model0xh.sbin.tar
(230 KB)
📄
amdgpu.tar
(108.27 MB)
📄
amdgpu.tar.gz
(36.9 MB)
📄
amdgpu.zip
(107.89 MB)
📄
amdgpu_drm.h.h.tar.gz
(10.54 KB)
📄
amdgpu_drm.h.tar
(38.5 KB)
📄
amdnpu.tar
(979.5 KB)
📄
amdnpu.tar.gz
(225.45 KB)
📄
amdnpu.zip
(977.25 KB)
📄
amdtee.tar
(32 KB)
📄
amdtee.tar.gz
(9.83 KB)
📄
amdtee.zip
(29.58 KB)
📄
amiga.tar
(7 KB)
📄
amiga.tar.gz
(4.9 KB)
📄
amiga.zip
(5.04 KB)
📄
amlogic.tar
(1.72 MB)
📄
amlogic.tar.gz
(884.76 KB)
📄
amlogic.zip
(1.72 MB)
📄
ampache.tar
(74.17 MB)
📄
ampache.tar.gz
(64.88 MB)
📄
ampache.zip
(74.15 MB)
📄
amphion.tar
(501 KB)
📄
amphion.tar.gz
(346.78 KB)
📄
amphion.zip
(499 KB)
📄
amqp.xml.tar
(2 KB)
📄
amqp.xml.xml.tar.gz
(295 B)
📄
amqps.xml.tar
(2 KB)
📄
amqps.xml.xml.tar.gz
(307 B)
📄
amss.bin.bin.tar.gz
(2.95 MB)
📄
amss.bin.tar
(27.92 MB)
📄
an8811hb.tar
(162 KB)
📄
an8811hb.tar.gz
(49.1 KB)
📄
an8811hb.zip
(160.31 KB)
📄
analyze_dxp.pyc.pyc.tar.gz
(2.13 KB)
📄
analyze_dxp.pyc.tar
(6.5 KB)
📄
analyze_dxp.pyo.pyo.tar.gz
(2.13 KB)
📄
analyze_dxp.pyo.tar
(6.5 KB)
📄
anchor.tar
(159.5 KB)
📄
anchor.tar.gz
(82.85 KB)
📄
anchor.zip
(136.18 KB)
📄
android-chrome-144x144.png.png.tar.gz
(895 B)
📄
android-chrome-144x144.png.tar
(4 KB)
📄
android-chrome-192x192.png.png.tar.gz
(750 B)
📄
android-chrome-192x192.png.tar
(4 KB)
📄
android-chrome-36x36.png.png.tar.gz
(823 B)
📄
android-chrome-36x36.png.tar
(4 KB)
📄
android-chrome-48x48.png.png.tar.gz
(1001 B)
📄
android-chrome-48x48.png.tar
(4 KB)
📄
android-chrome-72x72.png.png.tar.gz
(945 B)
📄
android-chrome-72x72.png.tar
(4 KB)
📄
android-chrome-96x96.png.png.tar.gz
(913 B)
📄
android-chrome-96x96.png.tar
(4 KB)
📄
angular.tar
(57.5 KB)
📄
angular.tar.gz
(32.78 KB)
📄
angular.zip
(46.38 KB)
📄
animate.tar
(19.76 MB)
📄
animate.tar.gz
(3.67 KB)
📄
animation.tar
(46.5 KB)
📄
animation.tar.gz
(16.92 KB)
📄
animation.zip
(43.46 KB)
📄
antigravity.py.py.tar.gz
(408 B)
📄
antigravity.py.tar
(4 KB)
📄
antigravity.pyc.pyc.tar.gz
(252 B)
📄
antigravity.pyc.tar
(2 KB)
📄
antigravity.pyo.pyo.tar.gz
(253 B)
📄
antigravity.pyo.tar
(2 KB)
📄
anycast_delay.tar
(7 KB)
📄
anycast_delay.tar.gz
(124 B)
📄
anydbm.py.py.tar.gz
(1.18 KB)
📄
anydbm.py.tar
(4.5 KB)
📄
anydbm.pyc.pyc.tar.gz
(1.47 KB)
📄
anydbm.pyc.tar
(4.5 KB)
📄
anydbm.pyo.pyo.tar.gz
(1.47 KB)
📄
anydbm.pyo.tar
(4.5 KB)
📄
aom.tar
(5.45 MB)
📄
aom.tar.gz
(1.99 MB)
📄
aom.zip
(5.45 MB)
📄
aout.mod.mod.tar.gz
(659 B)
📄
aout.mod.tar
(3 KB)
📄
ap_compat.h.h.tar.gz
(708 B)
📄
ap_compat.h.tar
(3 KB)
📄
ap_config.h.h.tar.gz
(2.3 KB)
📄
ap_config.h.tar
(8 KB)
📄
ap_config_auto.h.h.tar.gz
(2.79 KB)
📄
ap_config_auto.h.tar
(11.5 KB)
📄
ap_expr.h.h.tar.gz
(3.64 KB)
📄
ap_expr.h.tar
(15.5 KB)
📄
ap_hooks.h.h.tar.gz
(1.93 KB)
📄
ap_hooks.h.tar
(7.5 KB)
📄
ap_keysym.h.h.tar.gz
(988 B)
📄
ap_keysym.h.tar
(4 KB)
📄
ap_listen.h.h.tar.gz
(2.26 KB)
📄
ap_listen.h.tar
(8 KB)
📄
ap_lsws.sh.in.sh.in.tar.gz
(765 B)
📄
ap_lsws.sh.in.tar
(3.5 KB)
📄
ap_lsws.sh.sh.tar.gz
(762 B)
📄
ap_lsws.sh.tar
(3.5 KB)
📄
ap_mmn.h.h.tar.gz
(11.77 KB)
📄
ap_mmn.h.tar
(41.5 KB)
📄
ap_mpm.h.h.tar.gz
(3.98 KB)
📄
ap_mpm.h.tar
(12.5 KB)
📄
ap_provider.h.h.tar.gz
(1.15 KB)
📄
ap_provider.h.tar
(5 KB)
📄
ap_regex.h.h.tar.gz
(3.89 KB)
📄
ap_regex.h.tar
(13 KB)
📄
ap_regkey.h.h.tar.gz
(2.04 KB)
📄
ap_regkey.h.tar
(10.5 KB)
📄
apache2.conf.conf.tar.gz
(156 B)
📄
apache2.conf.tar
(3 KB)
📄
apache2.tar
(8.21 MB)
📄
apache2.tar.gz
(2.04 MB)
📄
apache2.zip
(8.12 MB)
📄
apbtfw10.tlv.tar
(56.5 KB)
📄
apbtfw10.tlv.tlv.tar.gz
(39.22 KB)
📄
apbtfw11.tlv.tar
(214 KB)
📄
apbtfw11.tlv.tlv.tar.gz
(151.17 KB)
📄
apcupsd.xml.tar
(2 KB)
📄
apcupsd.xml.xml.tar.gz
(304 B)
📄
apl.tar
(495.5 KB)
📄
apl.tar.gz
(188.47 KB)
📄
apl.zip
(493.94 KB)
📄
apnv10.bin.bin.tar.gz
(636 B)
📄
apnv10.bin.tar
(5 KB)
📄
apnv11.bin.bin.tar.gz
(2.27 KB)
📄
apnv11.bin.tar
(12 KB)
📄
app-version-detector.tar
(319.5 KB)
📄
app-version-detector.tar.gz
(54.62 KB)
📄
app-version-detector.zip
(317.42 KB)
📄
app.php.php.tar.gz
(3.43 KB)
📄
app.php.tar
(47 KB)
📄
app_key.php.php.tar.gz
(358 B)
📄
app_key.php.tar
(4 KB)
📄
app_local.php.php.tar.gz
(1.19 KB)
📄
app_local.php.tar
(4.5 KB)
📄
app_solicit.tar
(3 KB)
📄
app_solicit.tar.gz
(122 B)
📄
append.tar
(2 KB)
📄
append.tar.gz
(321 B)
📄
appendedsig.mod.mod.tar.gz
(15.41 KB)
📄
appendedsig.mod.tar
(46 KB)
📄
apple.951afce8.svg.951afce8.svg.tar.gz
(740 B)
📄
apple.951afce8.svg.tar
(3 KB)
📄
apprain.tar
(152 KB)
📄
apprain.tar.gz
(81.72 KB)
📄
apprain.zip
(132.96 KB)
📄
apps.php.php.tar.gz
(216 B)
📄
apps.php.tar
(2 KB)
📄
apq8016.tar
(14.36 MB)
📄
apq8016.tar.gz
(6.91 MB)
📄
apq8016.zip
(14.36 MB)
📄
apq8096.tar
(17.36 MB)
📄
apq8096.tar.gz
(8.27 MB)
📄
apq8096.zip
(17.36 MB)
📄
apr-1.tar
(347 KB)
📄
apr-1.tar.gz
(89.55 KB)
📄
apr-1.zip
(343.19 KB)
📄
apr-util-1.tar
(34 KB)
📄
apr-util-1.tar.gz
(10.11 KB)
📄
apr-util-1.zip
(31.69 KB)
📄
apr_dbm_db.so.so.tar.gz
(4.35 KB)
📄
apr_dbm_db.so.tar
(13.5 KB)
📄
ar.h.h.tar.gz
(986 B)
📄
ar.h.tar
(3.5 KB)
📄
ar.tar
(63.5 KB)
📄
ar.tar.gz
(28.96 KB)
📄
ar3k.tar
(508 KB)
📄
ar3k.tar.gz
(283.05 KB)
📄
ar3k.zip
(486.52 KB)
📄
ar3kbdaddr.pst.pst.tar.gz
(132 B)
📄
ar3kbdaddr.pst.tar
(3 KB)
📄
ar5523.bin.bin.tar.gz
(70.56 KB)
📄
ar5523.bin.tar
(302 KB)
📄
ar7010.fw.fw.tar.gz
(35.81 KB)
📄
ar7010.fw.tar
(140 KB)
📄
ar7010_1_1.fw.fw.tar.gz
(36.17 KB)
📄
ar7010_1_1.fw.tar
(140 KB)
📄
ar9170-1.fw.fw.tar.gz
(43.97 KB)
📄
ar9170-1.fw.tar
(166 KB)
📄
ar9170-2.fw.fw.tar.gz
(2.65 KB)
📄
ar9170-2.fw.tar
(9 KB)
📄
ar9271.fw.fw.tar.gz
(33.07 KB)
📄
ar9271.fw.tar
(103 KB)
📄
ar_ye.json.json.tar.gz
(5.44 KB)
📄
ar_ye.json.tar
(17.5 KB)
📄
arastta.tar
(158.5 KB)
📄
arastta.tar.gz
(84.14 KB)
📄
arastta.zip
(138.45 KB)
📄
arch.php.php.tar.gz
(284 B)
📄
arch.php.tar
(2 KB)
📄
arch.tar
(39 KB)
📄
arch.tar.gz
(15.69 KB)
📄
arch10.10.tar
(277.5 KB)
📄
arch10.10.tar.gz
(61.93 KB)
📄
arch10.10.zip
(276.16 KB)
📄
arch10.12.tar
(277.5 KB)
📄
arch10.12.tar.gz
(61.94 KB)
📄
arch10.12.zip
(276.16 KB)
📄
arch10.8.tar
(277.5 KB)
📄
arch10.8.tar.gz
(61.93 KB)
📄
arch10.8.zip
(276.16 KB)
📄
arch11.8.tar
(293.5 KB)
📄
arch11.8.tar.gz
(68.53 KB)
📄
arch11.8.zip
(292.16 KB)
📄
arch12.8.tar
(301.5 KB)
📄
arch12.8.tar.gz
(70.63 KB)
📄
arch12.8.zip
(300.16 KB)
📄
arch13.8.tar
(305.5 KB)
📄
arch13.8.tar.gz
(71.41 KB)
📄
arch13.8.zip
(304.16 KB)
📄
archelp.mod.mod.tar.gz
(1.98 KB)
📄
archelp.mod.tar
(5.5 KB)
📄
archive.sh.sh.tar.gz
(728 B)
📄
archive.sh.tar
(5.5 KB)
📄
arcturus_asd.bin.bin.tar.gz
(46.16 KB)
📄
arcturus_asd.bin.tar
(166 KB)
📄
arcturus_gpu_info.bin.bin.tar.gz
(178 B)
📄
arcturus_gpu_info.bin.tar
(2 KB)
📄
arcturus_ip_discovery.bin.bin.tar.gz
(562 B)
📄
arcturus_ip_discovery.bin.tar
(2.5 KB)
📄
arcturus_mec.bin.bin.tar.gz
(34.06 KB)
📄
arcturus_mec.bin.tar
(264 KB)
📄
arcturus_rlc.bin.bin.tar.gz
(13.14 KB)
📄
arcturus_rlc.bin.tar
(48.5 KB)
📄
arcturus_smc.bin.bin.tar.gz
(77.31 KB)
📄
arcturus_smc.bin.tar
(266 KB)
📄
arcturus_sos.bin.bin.tar.gz
(111.32 KB)
📄
arcturus_sos.bin.tar
(196.5 KB)
📄
arcturus_ta.bin.bin.tar.gz
(41.07 KB)
📄
arcturus_ta.bin.tar
(126.5 KB)
📄
arcturus_vcn.bin.bin.tar.gz
(291.23 KB)
📄
arcturus_vcn.bin.tar
(412.5 KB)
📄
arfooo.tar
(206.5 KB)
📄
arfooo.tar.gz
(136.24 KB)
📄
arfooo.zip
(184.09 KB)
📄
argp.h.h.tar.gz
(8.31 KB)
📄
argp.h.tar
(26.5 KB)
📄
argparse.py.py.tar.gz
(19.03 KB)
📄
argparse.py.tar
(272.5 KB)
📄
argparse.pyc.pyc.tar.gz
(22.36 KB)
📄
argparse.pyc.tar
(64.5 KB)
📄
argparse.pyo.pyo.tar.gz
(22.26 KB)
📄
argparse.pyo.tar
(64.5 KB)
📄
argz.h.h.tar.gz
(2.01 KB)
📄
argz.h.tar
(7.5 KB)
📄
arm.tar
(1.69 MB)
📄
arm.tar.gz
(394.91 KB)
📄
arm.zip
(1.68 MB)
📄
armada_drm.h.h.tar.gz
(653 B)
📄
armada_drm.h.tar
(3 KB)
📄
armscii8.uni.tar
(3 KB)
📄
armscii8.uni.uni.tar.gz
(658 B)
📄
armv3l-linux.tar
(4.5 KB)
📄
armv3l-linux.tar.gz
(1.19 KB)
📄
armv3l-linux.zip
(3.11 KB)
📄
armv4b-linux.tar
(4.5 KB)
📄
armv4b-linux.tar.gz
(1.19 KB)
📄
armv4b-linux.zip
(3.11 KB)
📄
armv4l-linux.tar
(4.5 KB)
📄
armv4l-linux.tar.gz
(1.19 KB)
📄
armv4l-linux.zip
(3.11 KB)
📄
armv5tejl-linux.tar
(4.5 KB)
📄
armv5tejl-linux.tar.gz
(1.19 KB)
📄
armv5tejl-linux.zip
(3.12 KB)
📄
armv5tel-linux.tar
(4.5 KB)
📄
armv5tel-linux.tar.gz
(1.19 KB)
📄
armv5tel-linux.zip
(3.11 KB)
📄
armv5tl-linux.tar
(4.5 KB)
📄
armv5tl-linux.tar.gz
(1.19 KB)
📄
armv5tl-linux.zip
(3.11 KB)
📄
armv6hl-linux.tar
(4.5 KB)
📄
armv6hl-linux.tar.gz
(1.21 KB)
📄
armv6hl-linux.zip
(3.14 KB)
📄
armv6l-linux.tar
(4.5 KB)
📄
armv6l-linux.tar.gz
(1.19 KB)
📄
armv6l-linux.zip
(3.11 KB)
📄
armv7hl-linux.tar
(5 KB)
📄
armv7hl-linux.tar.gz
(1.22 KB)
📄
armv7hl-linux.zip
(3.15 KB)
📄
armv7hnl-linux.tar
(4.5 KB)
📄
armv7hnl-linux.tar.gz
(1.21 KB)
📄
armv7hnl-linux.zip
(3.14 KB)
📄
armv7l-linux.tar
(4.5 KB)
📄
armv7l-linux.tar.gz
(1.19 KB)
📄
armv7l-linux.zip
(3.11 KB)
📄
arp_accept.tar
(3 KB)
📄
arp_accept.tar.gz
(119 B)
📄
arp_announce.tar
(2 KB)
📄
arp_announce.tar.gz
(121 B)
📄
arp_filter.tar
(3 KB)
📄
arp_filter.tar.gz
(119 B)
📄
arp_ignore.tar
(3 KB)
📄
arp_ignore.tar.gz
(120 B)
📄
arp_notify.tar
(3 KB)
📄
arp_notify.tar.gz
(120 B)
📄
arpa.tar
(46.5 KB)
📄
arpa.tar.gz
(11.66 KB)
📄
arpa.zip
(42.04 KB)
📄
arpaname.tar
(13.5 KB)
📄
arpaname.tar.gz
(3.88 KB)
📄
arraylist.h.h.tar.gz
(761 B)
📄
arraylist.h.tar
(3.5 KB)
📄
arybase.pm.pm.tar.gz
(1.4 KB)
📄
arybase.pm.tar
(4.5 KB)
📄
arybase.tar
(25.5 KB)
📄
arybase.tar.gz
(9.84 KB)
📄
arybase.zip
(23.88 KB)
📄
as.tar
(891.5 KB)
📄
as.tar.gz
(210.16 KB)
📄
as102_data1_st.hex.hex.tar.gz
(36.35 KB)
📄
as102_data1_st.hex.tar
(95 KB)
📄
as102_data2_st.hex.hex.tar.gz
(25.04 KB)
📄
as102_data2_st.hex.tar
(81.5 KB)
📄
as21x1x_fw.bin.bin.tar.gz
(151.32 KB)
📄
as21x1x_fw.bin.tar
(257 KB)
📄
ascii.20-7f.uni.20-7f.uni.tar.gz
(750 B)
📄
ascii.20-7f.uni.tar
(3.5 KB)
📄
ascii.py.py.tar.gz
(968 B)
📄
ascii.py.tar
(10 KB)
📄
ascii_and_mic.so.so.tar.gz
(3.03 KB)
📄
ascii_and_mic.so.tar
(9.5 KB)
📄
asdl.h.h.tar.gz
(640 B)
📄
asdl.h.tar
(3 KB)
📄
asequencer.h.h.tar.gz
(5.82 KB)
📄
asequencer.h.tar
(22.5 KB)
📄
ash.h.h.tar.gz
(836 B)
📄
ash.h.tar
(3 KB)
📄
asm-generic.tar
(158.5 KB)
📄
asm-generic.tar.gz
(4.71 KB)
📄
asm-generic.zip
(130.14 KB)
📄
asm.tar
(304.5 KB)
📄
asm.tar.gz
(11.65 KB)
📄
asm.zip
(250.05 KB)
📄
asn1.h.h.tar.gz
(8.04 KB)
📄
asn1.h.tar
(34.5 KB)
📄
asn1.mod.mod.tar.gz
(15.73 KB)
📄
asn1.mod.tar
(81 KB)
📄
asn1t.h.h.tar.gz
(7.6 KB)
📄
asn1t.h.tar
(68.5 KB)
📄
asound.h.h.tar.gz
(11.91 KB)
📄
asound.h.tar
(52 KB)
📄
aspell-0.60.tar
(1.34 MB)
📄
aspell-0.60.tar.gz
(266.42 KB)
📄
aspell-0.60.zip
(1.29 MB)
📄
aspell.tar
(161 KB)
📄
aspell.tar.gz
(71.45 KB)
📄
asq.so.so.tar.gz
(5.65 KB)
📄
asq.so.tar
(17.5 KB)
📄
assert.h.h.tar.gz
(1.82 KB)
📄
assert.h.tar
(6 KB)
📄
assets.tar
(895.5 KB)
📄
assets.tar.gz
(621.33 KB)
📄
assets.zip
(858.6 KB)
📄
ast.h.h.tar.gz
(546 B)
📄
ast.h.tar
(2.5 KB)
📄
ast.py.py.tar.gz
(3.88 KB)
📄
ast.py.tar
(83 KB)
📄
ast.pyc.pyc.tar.gz
(5.42 KB)
📄
ast.pyc.tar
(14.5 KB)
📄
ast.pyo.pyo.tar.gz
(5.42 KB)
📄
ast.pyo.tar
(14.5 KB)
📄
async.h.h.tar.gz
(950 B)
📄
async.h.tar
(4 KB)
📄
asynchat.py.py.tar.gz
(3.73 KB)
📄
asynchat.py.tar
(37 KB)
📄
asynchat.pyc.pyc.tar.gz
(3.44 KB)
📄
asynchat.pyc.tar
(10.5 KB)
📄
asynchat.pyo.pyo.tar.gz
(3.44 KB)
📄
asynchat.pyo.tar
(10.5 KB)
📄
asyncio.tar
(2.42 MB)
📄
asyncio.tar.gz
(477.24 KB)
📄
asyncio.zip
(2.31 MB)
📄
asyncore.cpython-38.pyc.cpython-38.pyc.tar.gz
(7.18 KB)
📄
asyncore.cpython-38.pyc.tar
(17.5 KB)
📄
asyncore.py.py.tar.gz
(5.93 KB)
📄
asyncore.py.tar
(63 KB)
📄
asyncore.pyc.pyc.tar.gz
(7.25 KB)
📄
asyncore.pyc.tar
(20 KB)
📄
asyncore.pyo.pyo.tar.gz
(7.25 KB)
📄
asyncore.pyo.tar
(20 KB)
📄
at.deny.deny.tar.gz
(94 B)
📄
at.deny.tar
(2 KB)
📄
at.h.h.tar.gz
(653 B)
📄
at.h.tar
(3 KB)
📄
at.tar
(3 KB)
📄
at.tar.gz
(708 B)
📄
at_keyboard.mod.mod.tar.gz
(3.78 KB)
📄
at_keyboard.mod.tar
(10.5 KB)
📄
ata.mod.mod.tar.gz
(3.49 KB)
📄
ata.mod.tar
(18 KB)
📄
ata_id.tar
(84 KB)
📄
ata_id.tar.gz
(15.42 KB)
📄
atari.tar
(15 KB)
📄
atari.tar.gz
(11.21 KB)
📄
atari.zip
(11.74 KB)
📄
atd.pid.pid.tar.gz
(100 B)
📄
atd.pid.tar
(2 KB)
📄
atd.service.service.tar.gz
(274 B)
📄
atd.service.tar
(3 KB)
📄
atexit.py.py.tar.gz
(785 B)
📄
atexit.py.tar
(3.5 KB)
📄
atexit.pyc.pyc.tar.gz
(1.13 KB)
📄
atexit.pyc.tar
(4 KB)
📄
atexit.pyo.pyo.tar.gz
(1.13 KB)
📄
atexit.pyo.tar
(4 KB)
📄
ath10k.tar
(19.72 MB)
📄
ath10k.tar.gz
(9.53 MB)
📄
ath10k.zip
(19.7 MB)
📄
ath11k.tar
(69.95 MB)
📄
ath11k.tar.gz
(28.57 MB)
📄
ath11k.zip
(69.91 MB)
📄
ath12k.tar
(31.77 MB)
📄
ath12k.tar.gz
(12.81 MB)
📄
ath12k.zip
(31.76 MB)
📄
ath3k-1.fw.fw.tar.gz
(162.15 KB)
📄
ath3k-1.fw.tar
(485 KB)
📄
ath6k.tar
(847.5 KB)
📄
ath6k.tar.gz
(699.21 KB)
📄
ath6k.zip
(826.13 KB)
📄
ath9k_htc.tar
(123.5 KB)
📄
ath9k_htc.tar.gz
(60.46 KB)
📄
ath9k_htc.zip
(121.22 KB)
📄
athlon-linux.tar
(4.5 KB)
📄
athlon-linux.tar.gz
(1.2 KB)
📄
athlon-linux.zip
(3.11 KB)
📄
atlantis.tar
(191.5 KB)
📄
atlantis.tar.gz
(111.79 KB)
📄
atlantis.zip
(170.23 KB)
📄
atmel.tar
(786.5 KB)
📄
atmel.tar.gz
(475.8 KB)
📄
atmel.zip
(782.14 KB)
📄
atom.rb.rb.tar.gz
(3.72 KB)
📄
atom.rb.tar
(20.5 KB)
📄
atom.xml.tar
(2 KB)
📄
atom.xml.xml.tar.gz
(375 B)
📄
atop-rotate.service.service.tar.gz
(211 B)
📄
atop-rotate.service.tar
(2 KB)
📄
atop-rotate.timer.tar
(2 KB)
📄
atop-rotate.timer.timer.tar.gz
(195 B)
📄
atop.service.service.tar.gz
(477 B)
📄
atop.service.tar
(2.5 KB)
📄
atopacct.service.service.tar.gz
(298 B)
📄
atopacct.service.tar
(2 KB)
📄
atq.tar
(3 KB)
📄
atq.tar.gz
(708 B)
📄
atrm.tar
(3 KB)
📄
atrm.tar.gz
(709 B)
📄
attendize.tar
(265 KB)
📄
attendize.tar.gz
(157.13 KB)
📄
attendize.zip
(235.73 KB)
📄
attr.tar
(4 KB)
📄
attr.tar.gz
(163 B)
📄
attr.zip
(778 B)
📄
attributes.pm.pm.tar.gz
(6.13 KB)
📄
attributes.pm.tar
(18.5 KB)
📄
attributes.tar
(17.5 KB)
📄
attributes.tar.gz
(5.57 KB)
📄
attributes.zip
(15.7 KB)
📄
atusb-0.2.dfu.2.dfu.tar.gz
(3.83 KB)
📄
atusb-0.2.dfu.tar
(7.5 KB)
📄
atusb-0.3.dfu.3.dfu.tar.gz
(4 KB)
📄
atusb-0.3.dfu.tar
(7.5 KB)
📄
atusb.tar
(20.5 KB)
📄
atusb.tar.gz
(6.17 KB)
📄
atusb.zip
(17.91 KB)
📄
atutor.tar
(192.5 KB)
📄
atutor.tar.gz
(104.47 KB)
📄
atutor.zip
(167.09 KB)
📄
audio.tar
(3.84 MB)
📄
audio.tar.gz
(71.76 KB)
📄
audio.zip
(3.78 MB)
📄
audiodev.py.py.tar.gz
(1.9 KB)
📄
audiodev.py.tar
(9 KB)
📄
audiodev.pyc.pyc.tar.gz
(3.15 KB)
📄
audiodev.pyc.tar
(10 KB)
📄
audiodev.pyo.pyo.tar.gz
(3.15 KB)
📄
audiodev.pyo.tar
(10 KB)
📄
audit.tar
(13.5 KB)
📄
audit.tar.gz
(5.31 KB)
📄
audit.xml.tar
(2 KB)
📄
audit.xml.xml.tar.gz
(311 B)
📄
audit.zip
(12.1 KB)
📄
auditd.service.service.tar.gz
(925 B)
📄
auditd.service.tar
(3.5 KB)
📄
auth.h.h.tar.gz
(2.52 KB)
📄
auth.h.tar
(8 KB)
📄
auth.php.php.tar.gz
(388 B)
📄
auth.php.tar
(2 KB)
📄
auth_ed25519.so.so.tar.gz
(47.91 KB)
📄
auth_ed25519.so.tar
(72 KB)
📄
auth_gss.h.h.tar.gz
(2.04 KB)
📄
auth_gss.h.tar
(6.5 KB)
📄
auth_pam.so.so.tar.gz
(4.85 KB)
📄
auth_pam.so.tar
(13 KB)
📄
auth_pam_v1.so.so.tar.gz
(4.19 KB)
📄
auth_pam_v1.so.tar
(13 KB)
📄
auth_unix.h.h.tar.gz
(1.52 KB)
📄
auth_unix.h.tar
(4.5 KB)
📄
authdata.tar
(26.5 KB)
📄
authdata.tar.gz
(9.93 KB)
📄
authdata.zip
(24.69 KB)
📄
auto.tar
(16.68 MB)
📄
auto.tar.gz
(458.4 KB)
📄
auto.zip
(16.62 MB)
📄
auto_flowlabels.tar
(2 KB)
📄
auto_flowlabels.tar.gz
(117 B)
📄
auto_msgmni.tar
(2 KB)
📄
auto_msgmni.tar.gz
(112 B)
📄
autobot.tar
(20 KB)
📄
autobot.tar.gz
(1.08 KB)
📄
autobot.zip
(4.61 KB)
📄
autobot1.tar
(20 KB)
📄
autobot1.tar.gz
(1.08 KB)
📄
autobot1.zip
(4.61 KB)
📄
autoconf.tar
(21 KB)
📄
autoconf.tar.gz
(5.45 KB)
📄
autogroup.tar
(10 KB)
📄
autogroup.tar.gz
(124 B)
📄
autoheader.tar
(10 KB)
📄
autoheader.tar.gz
(3.5 KB)
📄
autoindex.tar
(53 KB)
📄
autoindex.tar.gz
(9.93 KB)
📄
autoindex.zip
(41.03 KB)
📄
autom4te.tar
(33 KB)
📄
autom4te.tar.gz
(11.68 KB)
📄
automake-1.16.16.tar.gz
(73.88 KB)
📄
automake-1.16.tar
(253.5 KB)
📄
automake.tar
(253.5 KB)
📄
automake.tar.gz
(73.88 KB)
📄
autoreconf.tar
(22.5 KB)
📄
autoreconf.tar.gz
(7.18 KB)
📄
autoscan.tar
(18.5 KB)
📄
autoscan.tar.gz
(6.13 KB)
📄
autosprintf.h.h.tar.gz
(1.15 KB)
📄
autosprintf.h.tar
(4 KB)
📄
autoupdate.tar
(35 KB)
📄
autoupdate.tar.gz
(11.07 KB)
📄
autovt@.service.service.tar.gz
(1.17 KB)
📄
autovt@.service.tar
(3.5 KB)
📄
auxv.h.h.tar.gz
(799 B)
📄
auxv.h.tar
(3 KB)
📄
auxv.tar
(11 KB)
📄
auxv.tar.gz
(209 B)
📄
auxvec.h.h.tar.gz
(453 B)
📄
auxvec.h.tar
(2.5 KB)
📄
av.h.h.tar.gz
(1.54 KB)
📄
av.h.tar
(5 KB)
📄
av7110.tar
(2 KB)
📄
av7110.tar.gz
(271 B)
📄
av7110.zip
(370 B)
📄
av_permissions.h.h.tar.gz
(7.02 KB)
📄
av_permissions.h.tar
(65.5 KB)
📄
avactis.tar
(140.5 KB)
📄
avactis.tar.gz
(75.5 KB)
📄
avactis.zip
(121.53 KB)
📄
avatar.svg.svg.tar.gz
(533 B)
📄
avatar.svg.tar
(4 KB)
📄
avc.h.h.tar.gz
(4.67 KB)
📄
avc.h.tar
(18 KB)
📄
avs.tar
(1.38 MB)
📄
avs.tar.gz
(603.95 KB)
📄
avs.zip
(1.37 MB)
📄
avtab.h.h.tar.gz
(1.88 KB)
📄
avtab.h.tar
(6.5 KB)
📄
awk.tar
(688.5 KB)
📄
awk.tar.gz
(335.69 KB)
📄
awk.zip
(16.17 KB)
📄
aws.tar
(2.5 KB)
📄
aws.tar.gz
(398 B)
📄
aws.zip
(692 B)
📄
awstats.tar
(149.73 MB)
📄
awstats.zip
(149.14 MB)
📄
ax25.h.h.tar.gz
(1.78 KB)
📄
ax25.h.tar
(6.5 KB)
📄
b15cc6eec70a91e1.css.css.tar.gz
(11.8 KB)
📄
b15cc6eec70a91e1.css.tar
(90.5 KB)
📄
b19d6cb39d21a2f608c1271921b204470da0ec.tar
(17 KB)
📄
b19d6cb39d21a2f608c1271921b204470da0ec.tar.gz
(2.02 KB)
📄
b2db.yml.tar
(2 KB)
📄
b2db.yml.yml.tar.gz
(219 B)
📄
b2e.tar
(186 KB)
📄
b2e.tar.gz
(109.15 KB)
📄
b2e.zip
(163.07 KB)
📄
b2sum.tar
(59.5 KB)
📄
b2sum.tar.gz
(25.86 KB)
📄
b7c93053e410450aff5e09ea5a658ea45c67db.tar
(45.5 KB)
📄
b7c93053e410450aff5e09ea5a658ea45c67db.tar.gz
(18.28 KB)
📄
b9ba290068a2b5a2.css.css.tar.gz
(11.47 KB)
📄
b9ba290068a2b5a2.css.tar
(100.5 KB)
📄
backdrop.tar
(22.71 MB)
📄
backdrop.tar.gz
(20.44 MB)
📄
backdrop.zip
(22.68 MB)
📄
backtrace.mod.mod.tar.gz
(764 B)
📄
backtrace.mod.tar
(5 KB)
📄
backup.php.php.tar.gz
(2.25 KB)
📄
backup.php.tar
(88 KB)
📄
backups.tar
(2 KB)
📄
backups.tar.gz
(487 B)
📄
backups.zip
(584 B)
📄
bacula.xml.tar
(2 KB)
📄
bacula.xml.xml.tar.gz
(294 B)
📄
bad-header.xml.tar
(2 KB)
📄
bad-header.xml.xml.tar.gz
(275 B)
📄
bagisto.sql.sql.tar.gz
(32.73 KB)
📄
bagisto.sql.tar
(244.5 KB)
📄
bagisto.tar
(140.47 MB)
📄
bagisto.tar.gz
(135.73 MB)
📄
bagisto.zip
(140.44 MB)
📄
baker.sql.sql.tar.gz
(19.12 KB)
📄
baker.sql.tar
(85 KB)
📄
baker.tar
(26.03 MB)
📄
baker.tar.gz
(24.2 MB)
📄
baker.zip
(26.01 MB)
📄
balanced.tar
(2 KB)
📄
balanced.tar.gz
(367 B)
📄
balanced.zip
(611 B)
📄
baltic.trans.tar
(6 KB)
📄
baltic.trans.trans.tar.gz
(639 B)
📄
base.h.h.tar.gz
(7.74 KB)
📄
base.h.tar
(26 KB)
📄
base32.tar
(43 KB)
📄
base32.tar.gz
(19.38 KB)
📄
base64.py.py.tar.gz
(5.97 KB)
📄
base64.py.tar
(54.5 KB)
📄
base64.pyc.pyc.tar.gz
(4.45 KB)
📄
base64.pyc.tar
(13 KB)
📄
base64.pyo.pyo.tar.gz
(4.45 KB)
📄
base64.pyo.tar
(13 KB)
📄
base64.tar
(43 KB)
📄
base64.tar.gz
(19.34 KB)
📄
base64mime.py.py.tar.gz
(1.65 KB)
📄
base64mime.py.tar
(5 KB)
📄
base64mime.pyc.pyc.tar.gz
(2.56 KB)
📄
base64mime.pyc.tar
(7 KB)
📄
base64mime.pyo.pyo.tar.gz
(2.56 KB)
📄
base64mime.pyo.tar
(7 KB)
📄
base_dir.php.php.tar.gz
(178 B)
📄
base_dir.php.tar
(2 KB)
📄
base_futures.py.py.tar.gz
(1.11 KB)
📄
base_futures.py.tar
(7.5 KB)
📄
base_subprocess.py.py.tar.gz
(2.28 KB)
📄
base_subprocess.py.tar
(20 KB)
📄
basename.tar
(39 KB)
📄
basename.tar.gz
(15.63 KB)
📄
bash.tar
(1.1 MB)
📄
bash.tar.gz
(547.7 KB)
📄
bash_completion.d.tar
(4.5 KB)
📄
bash_completion.d.tar.gz
(765 B)
📄
bash_completion.d.zip
(2.75 KB)
📄
bashbug-64.tar
(9 KB)
📄
bashbug-64.tar.gz
(3.22 KB)
📄
bashrc.tar
(5.5 KB)
📄
bashrc.tar.gz
(1.62 KB)
📄
basic.conf.conf.tar.gz
(554 B)
📄
basic.conf.tar
(3 KB)
📄
basic.target.tar
(2.5 KB)
📄
basic.target.target.tar.gz
(637 B)
📄
batch.tar
(2 KB)
📄
batch.tar.gz
(192 B)
📄
battmgr.jsn.jsn.tar.gz
(347 B)
📄
battmgr.jsn.tar
(2.5 KB)
📄
bb.xml.tar
(2 KB)
📄
bb.xml.xml.tar.gz
(358 B)
📄
bbpress.tar
(22.53 MB)
📄
bbpress.tar.gz
(21.68 MB)
📄
bbpress.zip
(22.49 MB)
📄
bc.tar
(2.5 KB)
📄
bc.tar.gz
(362 B)
📄
bc_forwarding.tar
(3 KB)
📄
bc_forwarding.tar.gz
(123 B)
📄
bcc1d107bf724af11a75c0d740a5676cc9c211.tar
(44 KB)
📄
bcc1d107bf724af11a75c0d740a5676cc9c211.tar.gz
(15.16 KB)
📄
bcj.h.h.tar.gz
(1.19 KB)
📄
bcj.h.tar
(4.5 KB)
📄
bcm4329-fullmac-4.bin.bin.tar.gz
(176.89 KB)
📄
bcm4329-fullmac-4.bin.tar
(265 KB)
📄
bcm43xx-0.fw.fw.tar.gz
(40.91 KB)
📄
bcm43xx-0.fw.tar
(190 KB)
📄
bcm43xx_hdr-0.fw.fw.tar.gz
(219 B)
📄
bcm43xx_hdr-0.fw.tar
(2 KB)
📄
bcm8483.bin.bin.tar.gz
(121.88 KB)
📄
bcm8483.bin.tar
(206 KB)
📄
bdb.py.py.tar.gz
(5.96 KB)
📄
bdb.py.tar
(79 KB)
📄
bdb.pyc.pyc.tar.gz
(7.02 KB)
📄
bdb.pyc.tar
(20.5 KB)
📄
bdb.pyo.pyo.tar.gz
(7.02 KB)
📄
bdb.pyo.tar
(20.5 KB)
📄
bddcba3778314a7f5d08b8f055af4c8fdc5b19.tar
(45.5 KB)
📄
bddcba3778314a7f5d08b8f055af4c8fdc5b19.tar.gz
(19.3 KB)
📄
bdw.tar
(256.5 KB)
📄
bdw.tar.gz
(123.39 KB)
📄
bdw.zip
(254.98 KB)
📄
bdx.bin.bin.tar.gz
(7.69 KB)
📄
bdx.bin.tar
(86 KB)
📄
bearer.tar
(556 KB)
📄
bearer.tar.gz
(208.36 KB)
📄
bearer.zip
(552.95 KB)
📄
beehive.tar
(170 KB)
📄
beehive.tar.gz
(102.61 KB)
📄
beehive.zip
(151.81 KB)
📄
beer.py.py.tar.gz
(353 B)
📄
beer.py.tar
(2 KB)
📄
beige_goby_mec.bin.bin.tar.gz
(41.19 KB)
📄
beige_goby_mec.bin.tar
(263.5 KB)
📄
beige_goby_mec2.bin.bin.tar.gz
(41.19 KB)
📄
beige_goby_mec2.bin.tar
(263.5 KB)
📄
beige_goby_pfp.bin.bin.tar.gz
(16.54 KB)
📄
beige_goby_pfp.bin.tar
(259 KB)
📄
beige_goby_rlc.bin.bin.tar.gz
(45.69 KB)
📄
beige_goby_rlc.bin.tar
(129 KB)
📄
beige_goby_sdma.bin.bin.tar.gz
(12.29 KB)
📄
beige_goby_sdma.bin.tar
(35 KB)
📄
beige_goby_smc.bin.bin.tar.gz
(109.14 KB)
📄
beige_goby_smc.bin.tar
(241 KB)
📄
beige_goby_sos.bin.bin.tar.gz
(113.92 KB)
📄
beige_goby_sos.bin.tar
(203 KB)
📄
beige_goby_ta.bin.bin.tar.gz
(81.97 KB)
📄
beige_goby_ta.bin.tar
(251 KB)
📄
beige_goby_vcn.bin.bin.tar.gz
(406.83 KB)
📄
beige_goby_vcn.bin.tar
(568.5 KB)
📄
bfb0eefb4561c04aadbac1c60b62c0e50bf5ad.tar
(34 KB)
📄
bfb0eefb4561c04aadbac1c60b62c0e50bf5ad.tar.gz
(11.7 KB)
📄
bfs.mod.mod.tar.gz
(4.74 KB)
📄
bfs.mod.tar
(22 KB)
📄
bgp.xml.tar
(3 KB)
📄
bgp.xml.xml.tar.gz
(334 B)
📄
bgplo.tar
(49 KB)
📄
bgplo.tar.gz
(781 B)
📄
bgplo.zip
(6.76 KB)
📄
big5.so.so.tar.gz
(4.11 KB)
📄
big5.so.tar
(585.5 KB)
📄
big_endian.h.h.tar.gz
(1.17 KB)
📄
big_endian.h.tar
(6 KB)
📄
bigdecimal.rb.rb.tar.gz
(228 B)
📄
bigdecimal.rb.tar
(2 KB)
📄
bigdecimal.so.so.tar.gz
(37.38 KB)
📄
bigdecimal.so.tar
(192.5 KB)
📄
bigreq.h.h.tar.gz
(916 B)
📄
bigreq.h.tar
(4 KB)
📄
bin.tar
(142.2 MB)
📄
bin.tar.gz
(8.43 KB)
📄
bin.zip
(140.5 MB)
📄
bind9-export.tar
(2.95 MB)
📄
bind9-export.tar.gz
(1.25 MB)
📄
bind9-export.zip
(2.95 MB)
📄
bind9.tar
(1.67 MB)
📄
bind9.tar.gz
(343.44 KB)
📄
bind9.zip
(1.51 MB)
📄
bindv6only.tar
(2 KB)
📄
bindv6only.tar.gz
(111 B)
📄
binhex.py.py.tar.gz
(3.88 KB)
📄
binhex.py.tar
(45 KB)
📄
binhex.pyc.pyc.tar.gz
(5.45 KB)
📄
binhex.pyc.tar
(17 KB)
📄
binhex.pyo.pyo.tar.gz
(5.45 KB)
📄
binhex.pyo.tar
(17 KB)
📄
bioerr.h.h.tar.gz
(1.52 KB)
📄
bioerr.h.tar
(8 KB)
📄
biosdisk.mod.mod.tar.gz
(3.13 KB)
📄
biosdisk.mod.tar
(8 KB)
📄
bird.conf.conf.tar.gz
(190 B)
📄
bird.conf.tar
(5 KB)
📄
bird.service.service.tar.gz
(283 B)
📄
bird.service.tar
(2 KB)
📄
bisect.py.py.tar.gz
(719 B)
📄
bisect.py.tar
(11 KB)
📄
bisect.pyc.pyc.tar.gz
(969 B)
📄
bisect.pyc.tar
(4.5 KB)
📄
bisect.pyo.pyo.tar.gz
(968 B)
📄
bisect.pyo.tar
(4.5 KB)
📄
bison.tar
(439.5 KB)
📄
bison.tar.gz
(196.4 KB)
📄
bitcoin-rpc.xml.tar
(2 KB)
📄
bitcoin-rpc.xml.xml.tar.gz
(301 B)
📄
bitcoin-testnet.xml.tar
(2 KB)
📄
bitcoin-testnet.xml.xml.tar.gz
(294 B)
📄
bitcoin.xml.tar
(2 KB)
📄
bitcoin.xml.xml.tar.gz
(272 B)
📄
bitcount.h.h.tar.gz
(188 B)
📄
bitcount.h.tar
(2.5 KB)
📄
bitmap.mod.mod.tar.gz
(1.45 KB)
📄
bitmap.mod.tar
(8 KB)
📄
bitmap_scale.mod.mod.tar.gz
(2.39 KB)
📄
bitmap_scale.mod.tar
(7 KB)
📄
bitmaps.tar
(64 KB)
📄
bitmaps.tar.gz
(5.08 KB)
📄
bitmaps.zip
(25.42 KB)
📄
bitops.h.h.tar.gz
(3.3 KB)
📄
bitops.h.tar
(23.5 KB)
📄
bits.h.h.tar.gz
(526 B)
📄
bits.h.tar
(2.5 KB)
📄
bits.tar
(858.5 KB)
📄
bits.tar.gz
(21.35 KB)
📄
bits.zip
(712.46 KB)
📄
bitset.h.h.tar.gz
(339 B)
📄
bitset.h.tar
(2 KB)
📄
bitsperlong.ph.ph.tar.gz
(315 B)
📄
bitsperlong.ph.tar
(2 KB)
📄
bitstream.bin.bin.tar.gz
(7.36 KB)
📄
bitstream.bin.tar
(13.5 KB)
📄
bitstream.fw.fw.tar.gz
(83.85 KB)
📄
bitstream.fw.tar
(248 KB)
📄
bitvec.pyc.pyc.tar.gz
(3.41 KB)
📄
bitvec.pyc.tar
(12 KB)
📄
bitypes.h.h.tar.gz
(168 B)
📄
bitypes.h.tar
(2 KB)
📄
blab.png.png.tar.gz
(6.91 KB)
📄
blab.png.tar
(10 KB)
📄
blab.sql.sql.tar.gz
(9.59 KB)
📄
blab.sql.tar
(41.5 KB)
📄
blab.tar
(2.2 MB)
📄
blab.tar.gz
(2.07 MB)
📄
blab.zip
(2.17 MB)
📄
blesta.tar
(63.06 MB)
📄
blesta.tar.gz
(56.6 MB)
📄
blesta.zip
(63.04 MB)
📄
blesta4.tar
(484.5 KB)
📄
blesta4.tar.gz
(325.18 KB)
📄
blesta4.zip
(461.61 KB)
📄
block.h.h.tar.gz
(5.61 KB)
📄
block.h.tar
(23.5 KB)
📄
block.xml.tar
(2 KB)
📄
block.xml.xml.tar.gz
(295 B)
📄
block_dump.tar
(2 KB)
📄
block_dump.tar.gz
(106 B)
📄
blocklist.mod.mod.tar.gz
(1.35 KB)
📄
blocklist.mod.tar
(7 KB)
📄
blog-icon.png.png.tar.gz
(1.54 KB)
📄
blog-icon.png.tar
(3 KB)
📄
blowfish.h.h.tar.gz
(752 B)
📄
blowfish.h.tar
(3.5 KB)
📄
blscfg.mod.mod.tar.gz
(5.86 KB)
📄
blscfg.mod.tar
(29 KB)
📄
bludit.tar
(2.89 MB)
📄
bludit.tar.gz
(2.67 MB)
📄
bludit.zip
(2.87 MB)
📄
bluetooth.target.tar
(2 KB)
📄
bluetooth.target.target.tar.gz
(382 B)
📄
bmg_dmc.bin.bin.tar.gz
(13.56 KB)
📄
bmg_dmc.bin.tar
(46.5 KB)
📄
bmg_guc_70.bin.bin.tar.gz
(194.92 KB)
📄
bmg_guc_70.bin.tar
(756 KB)
📄
bmg_huc.bin.bin.tar.gz
(200.52 KB)
📄
bmg_huc.bin.tar
(1.12 MB)
📄
bmi260-init-data.fw.fw.tar.gz
(5.52 KB)
📄
bmi260-init-data.fw.tar
(9.5 KB)
📄
bn.h.h.tar.gz
(11.3 KB)
📄
bn.h.tar
(67 KB)
📄
bn.rb.rb.tar.gz
(544 B)
📄
bn.rb.tar
(13 KB)
📄
bnerr.h.h.tar.gz
(1.3 KB)
📄
bnerr.h.tar
(6.5 KB)
📄
bnm.php.php.tar.gz
(24.09 KB)
📄
bnm.php.tar
(79.5 KB)
📄
bnx2-mips-06-6.2.3.fw.2.3.fw.tar.gz
(45.8 KB)
📄
bnx2-mips-06-6.2.3.fw.tar
(92.5 KB)
📄
bnx2-rv2p-09ax-6.0.17.fw.0.17.fw.tar.gz
(2.25 KB)
📄
bnx2-rv2p-09ax-6.0.17.fw.tar
(8 KB)
📄
bnx2.tar
(214.5 KB)
📄
bnx2.tar.gz
(102.42 KB)
📄
bnx2.zip
(210.89 KB)
📄
bnx2x.tar
(2.57 MB)
📄
bnx2x.tar.gz
(2.31 MB)
📄
bnx2x.zip
(2.56 MB)
📄
bnxt_re-abi.h.h.tar.gz
(1.69 KB)
📄
bnxt_re-abi.h.tar
(5 KB)
📄
board-2.bin.bin.tar.gz
(82.78 KB)
📄
board-2.bin.tar
(27.68 MB)
📄
board.conf.php.conf.php.tar.gz
(1.74 KB)
📄
board.conf.php.tar
(5.5 KB)
📄
bolt.png.png.tar.gz
(2.78 KB)
📄
bolt.png.tar
(5 KB)
📄
bolt.tar
(252.5 KB)
📄
bolt.tar.gz
(141.37 KB)
📄
bolt.zip
(228.22 KB)
📄
bonaire_ce.bin.bin.tar.gz
(1.56 KB)
📄
bonaire_ce.bin.tar
(20 KB)
📄
bonaire_mc.bin.bin.tar.gz
(12.99 KB)
📄
bonaire_mc.bin.tar
(66 KB)
📄
bonaire_me.bin.bin.tar.gz
(4.14 KB)
📄
bonaire_me.bin.tar
(20 KB)
📄
bonaire_mec.bin.bin.tar.gz
(8.9 KB)
📄
bonaire_mec.bin.tar
(36 KB)
📄
bonaire_pfp.bin.bin.tar.gz
(3.95 KB)
📄
bonaire_pfp.bin.tar
(20 KB)
📄
bonaire_rlc.bin.bin.tar.gz
(2.57 KB)
📄
bonaire_rlc.bin.tar
(19 KB)
📄
bonaire_sdma.bin.bin.tar.gz
(2.26 KB)
📄
bonaire_sdma.bin.tar
(11 KB)
📄
bonaire_smc.bin.bin.tar.gz
(43.63 KB)
📄
bonaire_smc.bin.tar
(258 KB)
📄
bonaire_uvd.bin.bin.tar.gz
(154.46 KB)
📄
bonaire_uvd.bin.tar
(457 KB)
📄
bonaire_vce.bin.bin.tar.gz
(62.65 KB)
📄
bonaire_vce.bin.tar
(200 KB)
📄
boolean_record.h.h.tar.gz
(515 B)
📄
boolean_record.h.tar
(3.5 KB)
📄
booleans.h.h.tar.gz
(842 B)
📄
booleans.h.tar
(4 KB)
📄
boolobject.h.h.tar.gz
(551 B)
📄
boolobject.h.tar
(2.5 KB)
📄
boot-complete.target.tar
(2 KB)
📄
boot-complete.target.target.tar.gz
(397 B)
📄
boot.fw.fw.tar.gz
(3.99 KB)
📄
boot.fw.tar
(17 KB)
📄
boot.h.h.tar.gz
(309 B)
📄
boot.h.tar
(2 KB)
📄
boot.img.img.tar.gz
(502 B)
📄
boot.img.tar
(2 KB)
📄
boot.mod.mod.tar.gz
(1.46 KB)
📄
boot.mod.tar
(5 KB)
📄
boot.tar
(146 KB)
📄
boot.tar.gz
(59.8 KB)
📄
boot.zip
(144.07 KB)
📄
boot2.fw.fw.tar.gz
(3.68 KB)
📄
boot2.fw.tar
(16 KB)
📄
boot_hybrid.img.img.tar.gz
(518 B)
📄
boot_hybrid.img.tar
(2 KB)
📄
boot_id.tar
(2 KB)
📄
boot_id.tar.gz
(143 B)
📄
bootcode.bin.bin.tar.gz
(296 B)
📄
bootcode.bin.tar
(2 KB)
📄
bootloader_type.tar
(2 KB)
📄
bootloader_type.tar.gz
(116 B)
📄
bootloader_version.tar
(2 KB)
📄
bootloader_version.tar.gz
(118 B)
📄
bootp_relay.tar
(4 KB)
📄
bootp_relay.tar.gz
(121 B)
📄
bootparam.h.h.tar.gz
(3.14 KB)
📄
bootparam.h.tar
(9.5 KB)
📄
bootstrap.bin.bin.tar.gz
(258 B)
📄
bootstrap.bin.tar
(2 KB)
📄
bootstrap.json.json.tar.gz
(412 B)
📄
bootstrap.json.tar
(2.5 KB)
📄
bootstrap.php.php.tar.gz
(1.91 KB)
📄
bootstrap.php.tar
(13.5 KB)
📄
bootstrap.tar
(1.44 MB)
📄
bootstrap.tar.gz
(1.4 MB)
📄
bootstrap.zip
(1.43 MB)
📄
bootstrap_old.tar
(15 KB)
📄
bootstrap_old.tar.gz
(2.16 KB)
📄
bootstrap_old.zip
(12.49 KB)
📄
boottime.mod.mod.tar.gz
(927 B)
📄
boottime.mod.tar
(3.5 KB)
📄
bpf.tar
(26.16 MB)
📄
bpf.tar.gz
(2.55 MB)
📄
bpf.zip
(26.15 MB)
📄
bpf_stats_enabled.tar
(2 KB)
📄
bpf_stats_enabled.tar.gz
(117 B)
📄
br1c110b.tar
(51 KB)
📄
br1c110b.tar.gz
(36.03 KB)
📄
br1c110b.zip
(48.21 KB)
📄
brcmfmac43012-sdio.clm_blob.clm_blob.tar.gz
(2.09 KB)
📄
brcmfmac43012-sdio.clm_blob.tar
(6.5 KB)
📄
brcmfmac43143.bin.bin.tar.gz
(269.21 KB)
📄
brcmfmac43143.bin.tar
(389.5 KB)
📄
brcmfmac43236b.bin.bin.tar.gz
(221.34 KB)
📄
brcmfmac43236b.bin.tar
(341.5 KB)
📄
brcmfmac43241b0-sdio.bin.bin.tar.gz
(295.69 KB)
📄
brcmfmac43241b0-sdio.bin.tar
(451 KB)
📄
brcmfmac43241b4-sdio.bin.bin.tar.gz
(252.51 KB)
📄
brcmfmac43241b4-sdio.bin.tar
(396 KB)
📄
brcmfmac43241b5-sdio.bin.bin.tar.gz
(258.09 KB)
📄
brcmfmac43241b5-sdio.bin.tar
(401 KB)
📄
brcmfmac43242a.bin.bin.tar.gz
(295.01 KB)
📄
brcmfmac43242a.bin.tar
(469.5 KB)
📄
brcmfmac4329-sdio.bin.bin.tar.gz
(172.68 KB)
📄
brcmfmac4329-sdio.bin.tar
(249.5 KB)
📄
brcmfmac4330-sdio.bin.bin.tar.gz
(137.5 KB)
📄
brcmfmac4330-sdio.bin.tar
(220 KB)
📄
brcmfmac4334-sdio.bin.bin.tar.gz
(310.1 KB)
📄
brcmfmac4334-sdio.bin.tar
(442.5 KB)
📄
brcmfmac4335-sdio.bin.bin.tar.gz
(362.65 KB)
📄
brcmfmac4335-sdio.bin.tar
(557.5 KB)
📄
brcmfmac4339-sdio.bin.bin.tar.gz
(334.08 KB)
📄
brcmfmac4339-sdio.bin.tar
(562.5 KB)
📄
brcmfmac43430-sdio.clm_blob.clm_blob.tar.gz
(2 KB)
📄
brcmfmac43430-sdio.clm_blob.tar
(6.5 KB)
📄
brcmfmac43430a0-sdio.bin.bin.tar.gz
(253 KB)
📄
brcmfmac43430a0-sdio.bin.tar
(375 KB)
📄
brcmfmac43455-sdio.clm_blob.clm_blob.tar.gz
(2 KB)
📄
brcmfmac43455-sdio.clm_blob.tar
(6.5 KB)
📄
brcmfmac4350-pcie.bin.bin.tar.gz
(386.43 KB)
📄
brcmfmac4350-pcie.bin.tar
(613 KB)
📄
brcmfmac4354-sdio.bin.bin.tar.gz
(384.79 KB)
📄
brcmfmac4354-sdio.bin.tar
(589.5 KB)
📄
brcmfmac4356-pcie.bin.bin.tar.gz
(387.19 KB)
📄
brcmfmac4356-pcie.bin.tar
(603.5 KB)
📄
brcmfmac4356-pcie.gpd-win-pocket.txt.gpd-win-pocket.txt.tar.gz
(1.02 KB)
📄
brcmfmac4356-pcie.gpd-win-pocket.txt.tar
(4 KB)
📄
brcmfmac4356-sdio.bin.bin.tar.gz
(371.28 KB)
📄
brcmfmac4356-sdio.bin.tar
(568.5 KB)
📄
brcmfmac43569.bin.bin.tar.gz
(345.14 KB)
📄
brcmfmac43569.bin.tar
(545.5 KB)
📄
brcmfmac43570-pcie.clm_blob.clm_blob.tar.gz
(2.24 KB)
📄
brcmfmac43570-pcie.clm_blob.tar
(14 KB)
📄
brcmfmac4358-pcie.bin.bin.tar.gz
(400.8 KB)
📄
brcmfmac4358-pcie.bin.tar
(621 KB)
📄
brcmfmac4371-pcie.bin.bin.tar.gz
(387.63 KB)
📄
brcmfmac4371-pcie.bin.tar
(610.5 KB)
📄
brcmfmac4373-sdio.bin.bin.tar.gz
(355.93 KB)
📄
brcmfmac4373-sdio.bin.tar
(552.5 KB)
📄
brcmfmac4373.bin.bin.tar.gz
(287.68 KB)
📄
brcmfmac4373.bin.tar
(469.5 KB)
📄
brcmfmac54591-pcie.clm_blob.clm_blob.tar.gz
(2.22 KB)
📄
brcmfmac54591-pcie.clm_blob.tar
(7.5 KB)
📄
brd4001a.pds.pds.tar.gz
(313 B)
📄
brd4001a.pds.tar
(2.5 KB)
📄
brd8022a.pds.pds.tar.gz
(324 B)
📄
brd8022a.pds.tar
(2.5 KB)
📄
brd8023a.pds.pds.tar.gz
(314 B)
📄
brd8023a.pds.tar
(2.5 KB)
📄
broadcast.pyc.pyc.tar.gz
(465 B)
📄
broadcast.pyc.tar
(2.5 KB)
📄
broadcast.pyo.pyo.tar.gz
(465 B)
📄
broadcast.pyo.tar
(2.5 KB)
📄
brotli.tar
(3.61 MB)
📄
brotli.tar.gz
(1.81 MB)
📄
brp-ldconfig.tar
(3 KB)
📄
brp-ldconfig.tar.gz
(293 B)
📄
brp-mangle-shebangs.tar
(6 KB)
📄
brp-mangle-shebangs.tar.gz
(1.6 KB)
📄
brp-scl-compress.tar
(6 KB)
📄
brp-scl-compress.tar.gz
(787 B)
📄
brp-scl-python-bytecompile.tar
(5 KB)
📄
brp-scl-python-bytecompile.tar.gz
(1.2 KB)
📄
bsd.mod.mod.tar.gz
(16.28 KB)
📄
bsd.mod.tar
(85 KB)
📄
bsddb.tar
(245.5 KB)
📄
bsddb.tar.gz
(58.02 KB)
📄
bsddb.zip
(230.56 KB)
📄
bsock.tar
(20.5 KB)
📄
bsock.tar.gz
(3.54 KB)
📄
bsock.zip
(16.7 KB)
📄
bsock_addrinfo.h.h.tar.gz
(1.67 KB)
📄
bsock_addrinfo.h.tar
(5.5 KB)
📄
bsock_bind.h.h.tar.gz
(1.09 KB)
📄
bsock_bind.h.tar
(3.5 KB)
📄
bsock_unix.h.h.tar.gz
(2.15 KB)
📄
bsock_unix.h.tar
(7 KB)
📄
bswap_test.mod.mod.tar.gz
(1.43 KB)
📄
bswap_test.mod.tar
(4.5 KB)
📄
btm_utils.py.py.tar.gz
(2.67 KB)
📄
btm_utils.py.tar
(22 KB)
📄
btrfs.mod.mod.tar.gz
(14.06 KB)
📄
btrfs.mod.tar
(67 KB)
📄
bubble_bg.gif.gif.tar.gz
(489 B)
📄
bubble_bg.gif.tar
(2 KB)
📄
bubblebabble.so.so.tar.gz
(4 KB)
📄
bubblebabble.so.tar
(13.5 KB)
📄
buffer.h.h.tar.gz
(803 B)
📄
buffer.h.tar
(42.5 KB)
📄
buffer_compat.h.h.tar.gz
(2.07 KB)
📄
buffer_compat.h.tar
(6.5 KB)
📄
buffererr.h.h.tar.gz
(536 B)
📄
buffererr.h.tar
(2.5 KB)
📄
bufferevent_compat.h.h.tar.gz
(1.95 KB)
📄
bufferevent_compat.h.tar
(6 KB)
📄
bufferevent_ssl.h.h.tar.gz
(1.93 KB)
📄
bufferevent_ssl.h.tar
(6.5 KB)
📄
bufferevent_struct.h.h.tar.gz
(1.87 KB)
📄
bufferevent_struct.h.tar
(6 KB)
📄
bufio.mod.mod.tar.gz
(1.36 KB)
📄
bufio.mod.tar
(8 KB)
📄
buggenie.tar
(246 KB)
📄
buggenie.tar.gz
(154.03 KB)
📄
buggenie.zip
(220.61 KB)
📄
bugs.png.png.tar.gz
(2.99 KB)
📄
bugs.png.tar
(5 KB)
📄
bugs.tar
(156 KB)
📄
bugs.tar.gz
(81.13 KB)
📄
bugs.zip
(134.01 KB)
📄
build.tar
(1.57 MB)
📄
build.tar.gz
(5.45 KB)
📄
build.zip
(1.43 MB)
📄
build_ap_wrapper.sh.sh.tar.gz
(473 B)
📄
build_ap_wrapper.sh.tar
(2.5 KB)
📄
builtins.qmltypes.qmltypes.tar.gz
(10.6 KB)
📄
builtins.qmltypes.tar
(59 KB)
📄
bundle.tar
(11.5 KB)
📄
bundle.tar.gz
(442 B)
📄
bundler.tar
(11.5 KB)
📄
bundler.tar.gz
(433 B)
📄
bundles.php.php.tar.gz
(196 B)
📄
bundles.php.tar
(2 KB)
📄
bunzip2.tar
(38.5 KB)
📄
bunzip2.tar.gz
(16.35 KB)
📄
burden.tar
(125.5 KB)
📄
burden.tar.gz
(61.69 KB)
📄
burden.zip
(106.55 KB)
📄
bus.tar
(18.5 KB)
📄
bus.tar.gz
(1.39 KB)
📄
bus.zip
(6.79 KB)
📄
busy_poll.tar
(2 KB)
📄
busy_poll.tar.gz
(111 B)
📄
busy_read.tar
(2 KB)
📄
busy_read.tar.gz
(112 B)
📄
buy.php.php.tar.gz
(872 B)
📄
buy.php.tar
(3 KB)
📄
bxt_dmc_ver1.bin.bin.tar.gz
(2.47 KB)
📄
bxt_dmc_ver1.bin.tar
(10 KB)
📄
bxt_guc_32.0.3.bin.0.3.bin.tar.gz
(81.46 KB)
📄
bxt_guc_32.0.3.bin.tar
(174 KB)
📄
bxt_guc_33.0.0.bin.0.0.bin.tar.gz
(83.81 KB)
📄
bxt_guc_33.0.0.bin.tar
(179.5 KB)
📄
bxt_guc_49.0.1.bin.0.1.bin.tar.gz
(85.57 KB)
📄
bxt_guc_49.0.1.bin.tar
(193.5 KB)
📄
bxt_guc_62.0.0.bin.0.0.bin.tar.gz
(90.67 KB)
📄
bxt_guc_62.0.0.bin.tar
(196.5 KB)
📄
bxt_guc_69.0.3.bin.0.3.bin.tar.gz
(101.64 KB)
📄
bxt_guc_69.0.3.bin.tar
(213.5 KB)
📄
bxt_guc_70.1.1.bin.1.1.bin.tar.gz
(93 KB)
📄
bxt_guc_70.1.1.bin.tar
(203.5 KB)
📄
bxt_guc_ver8_7.bin.bin.tar.gz
(66.64 KB)
📄
bxt_guc_ver8_7.bin.tar
(139.5 KB)
📄
bxt_huc_2.0.0.bin.0.0.bin.tar.gz
(65.34 KB)
📄
bxt_huc_2.0.0.bin.tar
(148 KB)
📄
bxt_huc_ver01_8_2893.bin.bin.tar.gz
(64.41 KB)
📄
bxt_huc_ver01_8_2893.bin.tar
(145 KB)
📄
byext.pyc.pyc.tar.gz
(2.12 KB)
📄
byext.pyc.tar
(6 KB)
📄
byext.pyo.pyo.tar.gz
(2.12 KB)
📄
byext.pyo.tar
(6 KB)
📄
byte_order_generic.h.h.tar.gz
(1.22 KB)
📄
byte_order_generic.h.tar
(7 KB)
📄
byteorder.h.h.tar.gz
(225 B)
📄
byteorder.h.tar
(2 KB)
📄
byteswap.h.h.tar.gz
(769 B)
📄
byteswap.h.tar
(3 KB)
📄
byteswap.ph.ph.tar.gz
(559 B)
📄
byteswap.ph.tar
(3.5 KB)
📄
bz2.py.py.tar.gz
(3.59 KB)
📄
bz2.py.tar
(27 KB)
📄
bzcat.tar
(38.5 KB)
📄
bzcat.tar.gz
(16.35 KB)
📄
bzcmp.tar
(4 KB)
📄
bzcmp.tar.gz
(974 B)
📄
bzdiff.tar
(4 KB)
📄
bzdiff.tar.gz
(977 B)
📄
bzgrep.tar
(3.5 KB)
📄
bzgrep.tar.gz
(888 B)
📄
bzip2.pc.pc.tar.gz
(239 B)
📄
bzip2.pc.tar
(2 KB)
📄
bzip2.tar
(38.5 KB)
📄
bzip2.tar.gz
(16.35 KB)
📄
bzip2recover.tar
(18 KB)
📄
bzip2recover.tar.gz
(6.23 KB)
📄
bzless.tar
(3 KB)
📄
bzless.tar.gz
(729 B)
📄
bzlib.h.h.tar.gz
(1.72 KB)
📄
bzlib.h.tar
(8 KB)
📄
bzmore.tar
(3 KB)
📄
bzmore.tar.gz
(730 B)
📄
c++.tar
(9.55 MB)
📄
c++.tar.gz
(1.36 MB)
📄
c++.zip
(9.12 MB)
📄
c++filt.tar
(30.5 KB)
📄
c++filt.tar.gz
(12.59 KB)
📄
c09b78b4814ec7ec2137b18b13f8475068e0a9.tar
(13.5 KB)
📄
c09b78b4814ec7ec2137b18b13f8475068e0a9.tar.gz
(4.24 KB)
📄
c0b3e018972343a57fb9450e10fab620a42b4a.tar
(461 KB)
📄
c0b3e018972343a57fb9450e10fab620a42b4a.tar.gz
(263.67 KB)
📄
c148dbd03b1246f721c2e2c851d4325e521bc99b.svg.svg.tar.gz
(234 B)
📄
c148dbd03b1246f721c2e2c851d4325e521bc99b.svg.tar
(2 KB)
📄
c2f0d42f9547a4e3be2890c625c813342c866b.tar
(27 KB)
📄
c2f0d42f9547a4e3be2890c625c813342c866b.tar.gz
(10.97 KB)
📄
c598b8a81bd4d7b59cdd1651e2af3716efe80e.tar
(292.5 KB)
📄
c598b8a81bd4d7b59cdd1651e2af3716efe80e.tar.gz
(130.75 KB)
📄
cProfile.py.py.tar.gz
(1.85 KB)
📄
cProfile.py.tar
(21.5 KB)
📄
cProfile.pyc.pyc.tar.gz
(2.94 KB)
📄
cProfile.pyc.tar
(8 KB)
📄
cProfile.pyo.pyo.tar.gz
(2.94 KB)
📄
cProfile.pyo.tar
(8 KB)
📄
c_rehash.tar
(12.5 KB)
📄
c_rehash.tar.gz
(2.01 KB)
📄
ca.tar
(5.5 KB)
📄
ca.tar.gz
(3.51 KB)
📄
ca.zip
(3.64 KB)
📄
cache.json.json.tar.gz
(399 B)
📄
cache.json.tar
(4 KB)
📄
cache.tar
(148 KB)
📄
cache.tar.gz
(102 B)
📄
cache.zip
(140.37 KB)
📄
cache_common.h.h.tar.gz
(937 B)
📄
cache_common.h.tar
(3.5 KB)
📄
cache_hits.tar
(2 KB)
📄
cache_hits.tar.gz
(121 B)
📄
cadence.tar
(129.5 KB)
📄
cadence.tar.gz
(23.24 KB)
📄
cadence.zip
(128.15 KB)
📄
cagefs.service.service.tar.gz
(399 B)
📄
cagefs.service.tar
(2.5 KB)
📄
cagefs.tar
(4.5 KB)
📄
cagefs.tar.gz
(341 B)
📄
cagefs.zip
(2.76 KB)
📄
cagefs_enter.proxied.proxied.tar.gz
(721 B)
📄
cagefs_enter.proxied.tar
(3 KB)
📄
cagefs_enter_site.tar
(3.5 KB)
📄
cagefs_enter_site.tar.gz
(975 B)
📄
cagefsctl-user.tar
(14.5 KB)
📄
cagefsctl-user.tar.gz
(3.34 KB)
📄
cake.png.png.tar.gz
(5.11 KB)
📄
cake.png.tar
(7 KB)
📄
cake.tar
(12.73 MB)
📄
cake.tar.gz
(11.17 MB)
📄
cake.zip
(12.72 MB)
📄
cal.tar
(67.5 KB)
📄
cal.tar.gz
(29.49 KB)
📄
calendar.h.h.tar.gz
(21.45 KB)
📄
calendar.h.tar
(107 KB)
📄
calendar.py.py.tar.gz
(5.92 KB)
📄
calendar.py.tar
(73 KB)
📄
calendar.pyc.pyc.tar.gz
(9.17 KB)
📄
calendar.pyc.tar
(29 KB)
📄
calendar.pyo.pyo.tar.gz
(9.17 KB)
📄
calendar.pyo.tar
(29 KB)
📄
calling.go.go.tar.gz
(3.6 KB)
📄
calling.go.tar
(13 KB)
📄
camellia.h.h.tar.gz
(944 B)
📄
camellia.h.tar
(5 KB)
📄
cap_last_cap.tar
(2 KB)
📄
cap_last_cap.tar.gz
(113 B)
📄
capability.h.h.tar.gz
(2.39 KB)
📄
capability.h.tar
(9 KB)
📄
capi.so.so.tar.gz
(2.71 KB)
📄
capi.so.tar
(9 KB)
📄
captoinfo.tar
(87 KB)
📄
captoinfo.tar.gz
(38.76 KB)
📄
carbon.tar
(158 KB)
📄
carbon.tar.gz
(99.84 KB)
📄
carbon.zip
(139.14 KB)
📄
carl9170-1.fw.fw.tar.gz
(9.45 KB)
📄
carl9170-1.fw.tar
(29 KB)
📄
carrizo_ce.bin.bin.tar.gz
(2.48 KB)
📄
carrizo_ce.bin.tar
(10.5 KB)
📄
carrizo_me.bin.bin.tar.gz
(6.2 KB)
📄
carrizo_me.bin.tar
(18.5 KB)
📄
carrizo_mec.bin.bin.tar.gz
(26.38 KB)
📄
carrizo_mec.bin.tar
(258.5 KB)
📄
carrizo_mec2.bin.bin.tar.gz
(26.37 KB)
📄
carrizo_mec2.bin.tar
(258.5 KB)
📄
carrizo_pfp.bin.bin.tar.gz
(7.25 KB)
📄
carrizo_pfp.bin.tar
(18.5 KB)
📄
carrizo_rlc.bin.bin.tar.gz
(7.95 KB)
📄
carrizo_rlc.bin.tar
(20 KB)
📄
carrizo_sdma.bin.bin.tar.gz
(4.19 KB)
📄
carrizo_sdma.bin.tar
(12 KB)
📄
carrizo_sdma1.bin.bin.tar.gz
(4.19 KB)
📄
carrizo_sdma1.bin.tar
(12 KB)
📄
carrizo_uvd.bin.bin.tar.gz
(161.27 KB)
📄
carrizo_uvd.bin.tar
(267 KB)
📄
carrizo_vce.bin.bin.tar.gz
(103.75 KB)
📄
carrizo_vce.bin.tar
(173.5 KB)
📄
cassini.bin.bin.tar.gz
(1.61 KB)
📄
cassini.bin.tar
(4 KB)
📄
cast.h.h.tar.gz
(698 B)
📄
cast.h.tar
(3.5 KB)
📄
castopod.tar
(48.3 MB)
📄
castopod.tar.gz
(45.07 MB)
📄
castopod.zip
(48.27 MB)
📄
cat.mod.mod.tar.gz
(1.62 KB)
📄
cat.mod.tar
(9 KB)
📄
cat.tar
(39 KB)
📄
cat.tar.gz
(17.52 KB)
📄
catalog.tar
(139.5 KB)
📄
catalog.tar.gz
(31.18 KB)
📄
catalog.zip
(131.22 KB)
📄
catchsegv.tar
(5 KB)
📄
catchsegv.tar.gz
(1.62 KB)
📄
catlogo.gif.gif.tar.gz
(2.2 KB)
📄
catlogo.gif.tar
(11 KB)
📄
catpt.tar
(256.5 KB)
📄
catpt.tar.gz
(123.39 KB)
📄
catpt.zip
(254.99 KB)
📄
cavium.tar
(52 KB)
📄
cavium.tar.gz
(33.25 KB)
📄
cavium.zip
(49.9 KB)
📄
cb1fca053a681e9d9c7bc158d04e2e3525a96a.tar
(317 KB)
📄
cb1fca053a681e9d9c7bc158d04e2e3525a96a.tar.gz
(136.5 KB)
📄
cb58588c86ecb68689badafab8641ee79f12d5.tar
(96 KB)
📄
cb58588c86ecb68689badafab8641ee79f12d5.tar.gz
(38.5 KB)
📄
cbfs.mod.mod.tar.gz
(2.41 KB)
📄
cbfs.mod.tar
(6.5 KB)
📄
cbfw-3.2.5.1.bin.2.5.1.bin.tar.gz
(247.38 KB)
📄
cbfw-3.2.5.1.bin.tar
(406.5 KB)
📄
cbls.mod.mod.tar.gz
(1.58 KB)
📄
cbls.mod.tar
(5.5 KB)
📄
cbmemc.mod.mod.tar.gz
(1.3 KB)
📄
cbmemc.mod.tar
(8 KB)
📄
cbtable.mod.mod.tar.gz
(665 B)
📄
cbtable.mod.tar
(3 KB)
📄
cbtime.mod.mod.tar.gz
(1.5 KB)
📄
cbtime.mod.tar
(9 KB)
📄
cc1plus.tar
(28.39 MB)
📄
cc1plus.tar.gz
(12.54 MB)
📄
cc33xx_2nd_loader.bin.bin.tar.gz
(68.02 KB)
📄
cc33xx_2nd_loader.bin.tar
(70.5 KB)
📄
cc33xx_fw.bin.bin.tar.gz
(348.02 KB)
📄
cc33xx_fw.bin.tar
(498 KB)
📄
ccache.tar
(5.59 MB)
📄
ccache.tar.gz
(1.78 MB)
📄
ccache.zip
(5.44 MB)
📄
ccpp.amf.amf.tar.gz
(295 B)
📄
ccpp.amf.tar
(2 KB)
📄
ccselect_plugin.h.h.tar.gz
(1.76 KB)
📄
ccselect_plugin.h.tar
(6 KB)
📄
ccu.php.php.tar.gz
(19.73 KB)
📄
ccu.php.tar
(117.5 KB)
📄
cdboot.img.img.tar.gz
(312 B)
📄
cdboot.img.tar
(6 KB)
📄
cdefs.h.h.tar.gz
(6.01 KB)
📄
cdefs.h.tar
(22 KB)
📄
cdefs.ph.ph.tar.gz
(3.35 KB)
📄
cdefs.ph.tar
(23.5 KB)
📄
cdrom_id.tar
(68 KB)
📄
cdrom_id.tar.gz
(13.45 KB)
📄
cdsp.mbn.mbn.tar.gz
(2.74 MB)
📄
cdsp.mbn.tar
(17.09 MB)
📄
cdspr.jsn.jsn.tar.gz
(272 B)
📄
cdspr.jsn.tar
(3.5 KB)
📄
cedf6c3f9d4300c1.css.css.tar.gz
(11.04 KB)
📄
cedf6c3f9d4300c1.css.tar
(100 KB)
📄
cellobject.h.h.tar.gz
(439 B)
📄
cellobject.h.tar
(2.5 KB)
📄
ceph-mon.xml.tar
(2 KB)
📄
ceph-mon.xml.xml.tar.gz
(295 B)
📄
ceph.xml.tar
(2 KB)
📄
ceph.xml.xml.tar.gz
(331 B)
📄
certauth_plugin.h.h.tar.gz
(2.12 KB)
📄
certauth_plugin.h.tar
(6.5 KB)
📄
certs.tar
(18 KB)
📄
certs.tar.gz
(5.68 KB)
📄
certs.zip
(14.94 KB)
📄
cf8381.bin.bin.tar.gz
(65.18 KB)
📄
cf8381.bin.tar
(94.5 KB)
📄
cf8381_helper.bin.bin.tar.gz
(1.52 KB)
📄
cf8381_helper.bin.tar
(4 KB)
📄
cf8385.bin.bin.tar.gz
(66.21 KB)
📄
cf8385.bin.tar
(96.5 KB)
📄
cf8385_helper.bin.bin.tar.gz
(1.52 KB)
📄
cf8385_helper.bin.tar
(4 KB)
📄
cfengine.xml.tar
(2 KB)
📄
cfengine.xml.xml.tar.gz
(226 B)
📄
cff0b8765f56ec961409e8463ccf0bf22a4a4c.tar
(13.5 KB)
📄
cff0b8765f56ec961409e8463ccf0bf22a4a4c.tar.gz
(4 KB)
📄
cfg.db.php.db.php.tar.gz
(487 B)
📄
cfg.db.php.tar
(2.5 KB)
📄
cfg.user.php.tar
(3 KB)
📄
cfg.user.php.user.php.tar.gz
(672 B)
📄
cftp.png.png.tar.gz
(3.49 KB)
📄
cftp.png.tar
(5 KB)
📄
cftp.sql.sql.tar.gz
(7.13 KB)
📄
cftp.sql.tar
(42.5 KB)
📄
cftp.tar
(19.63 MB)
📄
cftp.tar.gz
(18.34 MB)
📄
cftp.zip
(19.6 MB)
📄
cgi-bin.tar
(21 KB)
📄
cgi-bin.tar.gz
(2.97 KB)
📄
cgi-bin.zip
(15.5 KB)
📄
cgi.py.py.tar.gz
(9.26 KB)
📄
cgi.py.tar
(108 KB)
📄
cgi.pyc.pyc.tar.gz
(12.64 KB)
📄
cgi.pyc.tar
(34.5 KB)
📄
cgi.pyo.pyo.tar.gz
(12.64 KB)
📄
cgi.pyo.tar
(34.5 KB)
📄
cgi.tar
(144.5 KB)
📄
cgi.tar.gz
(6.14 KB)
📄
cgi.zip
(134.27 KB)
📄
cgi1.pyc.pyc.tar.gz
(302 B)
📄
cgi1.pyc.tar
(2 KB)
📄
cgi1.pyo.pyo.tar.gz
(302 B)
📄
cgi1.pyo.tar
(2 KB)
📄
cgi2.pyc.pyc.tar.gz
(537 B)
📄
cgi2.pyc.tar
(2.5 KB)
📄
cgi2.pyo.pyo.tar.gz
(537 B)
📄
cgi2.pyo.tar
(2.5 KB)
📄
cgi3.pyc.pyc.tar.gz
(329 B)
📄
cgi3.pyc.tar
(2 KB)
📄
cgi3.pyo.pyo.tar.gz
(327 B)
📄
cgi3.pyo.tar
(2 KB)
📄
cgitb.py.py.tar.gz
(3.51 KB)
📄
cgitb.py.tar
(38.5 KB)
📄
cgitb.pyc.pyc.tar.gz
(5.42 KB)
📄
cgitb.pyc.tar
(13.5 KB)
📄
cgitb.pyo.pyo.tar.gz
(5.42 KB)
📄
cgitb.pyo.tar
(13.5 KB)
📄
cgroup.tar
(5 KB)
📄
cgroup.tar.gz
(245 B)
📄
chain.mod.mod.tar.gz
(2.08 KB)
📄
chain.mod.tar
(11 KB)
📄
chamilo.sql.sql.tar.gz
(38.43 KB)
📄
chamilo.sql.tar
(286 KB)
📄
chamilo.tar
(288.96 MB)
📄
chamilo.tar.gz
(329.86 MB)
📄
chamilo.zip
(363.4 MB)
📄
changelog.js.js.tar.gz
(1.29 KB)
📄
changelog.js.tar
(4.5 KB)
📄
changelog.txt.tar
(955.5 KB)
📄
changelog.txt.txt.tar.gz
(320 B)
📄
changelogs.tar
(789.5 KB)
📄
changelogs.tar.gz
(264.12 KB)
📄
changelogs.zip
(785.5 KB)
📄
channel.go.go.tar.gz
(2.53 KB)
📄
channel.go.tar
(7 KB)
📄
char.tar
(1.66 MB)
📄
char.tar.gz
(454.19 KB)
📄
char.zip
(1.62 MB)
📄
chardetect.tar
(3.5 KB)
📄
chardetect.tar.gz
(571 B)
📄
chariter.h.h.tar.gz
(5.26 KB)
📄
chariter.h.tar
(25.5 KB)
📄
charset.pyc.pyc.tar.gz
(4.91 KB)
📄
charset.pyc.tar
(15 KB)
📄
charset.pyo.pyo.tar.gz
(4.88 KB)
📄
charset.pyo.tar
(15 KB)
📄
check.h.h.tar.gz
(1.69 KB)
📄
check.h.tar
(6 KB)
📄
check_charset.php.php.tar.gz
(863 B)
📄
check_charset.php.tar
(3.5 KB)
📄
check_suphp.php.php.tar.gz
(204 B)
📄
check_suphp.php.tar
(3 KB)
📄
check_utf8.php.php.tar.gz
(988 B)
📄
check_utf8.php.tar
(95.5 KB)
📄
check_webserver.php.php.tar.gz
(266 B)
📄
check_webserver.php.tar
(2 KB)
📄
checkappend.pyc.pyc.tar.gz
(2.39 KB)
📄
checkappend.pyc.tar
(6.5 KB)
📄
checkappend.pyo.pyo.tar.gz
(2.39 KB)
📄
checkappend.pyo.tar
(6.5 KB)
📄
checkpip.pyc.pyc.tar.gz
(715 B)
📄
checkpip.pyc.tar
(3 KB)
📄
checkpip.pyo.pyo.tar.gz
(715 B)
📄
checkpip.pyo.tar
(3 KB)
📄
checkpyc.pyc.pyc.tar.gz
(1.09 KB)
📄
checkpyc.pyc.tar
(3.5 KB)
📄
checkpyc.pyo.pyo.tar.gz
(1.08 KB)
📄
checkpyc.pyo.tar
(3.5 KB)
📄
chevereto.sql.sql.tar.gz
(9.52 KB)
📄
chevereto.sql.tar
(54.5 KB)
📄
chevereto.tar
(35 MB)
📄
chevereto.tar.gz
(31.66 MB)
📄
chevereto.zip
(34.98 MB)
📄
chgrp.tar
(68 KB)
📄
chgrp.tar.gz
(32.05 KB)
📄
chinese.so.so.tar.gz
(87.6 KB)
📄
chinese.so.tar
(185 KB)
📄
chmod.php.php.tar.gz
(194 B)
📄
chmod.php.tar
(2 KB)
📄
chmod.tar
(65 KB)
📄
chmod.tar.gz
(30.81 KB)
📄
choicfmt.h.h.tar.gz
(6.16 KB)
📄
choicfmt.h.tar
(25.5 KB)
📄
chown.tar
(73 KB)
📄
chown.tar.gz
(33.18 KB)
📄
chpass_util_strings.h.h.tar.gz
(619 B)
📄
chpass_util_strings.h.tar
(3.5 KB)
📄
chrony-dnssrv@.service.service.tar.gz
(259 B)
📄
chrony-dnssrv@.service.tar
(2 KB)
📄
chrony-dnssrv@.timer.tar
(2 KB)
📄
chrony-dnssrv@.timer.timer.tar.gz
(228 B)
📄
chrony-wait.service.service.tar.gz
(420 B)
📄
chrony-wait.service.tar
(2 KB)
📄
chronyd.service.service.tar.gz
(427 B)
📄
chronyd.service.tar
(4 KB)
📄
chroot.sh.sh.tar.gz
(1.72 KB)
📄
chroot.sh.tar
(9 KB)
📄
chroot.tar
(43 KB)
📄
chroot.tar.gz
(18.84 KB)
📄
chrt.tar
(39 KB)
📄
chrt.tar.gz
(15.49 KB)
📄
chunk.py.py.tar.gz
(1.76 KB)
📄
chunk.py.tar
(19 KB)
📄
chunk.pyc.pyc.tar.gz
(2.43 KB)
📄
chunk.pyc.tar
(7 KB)
📄
chunk.pyo.pyo.tar.gz
(2.43 KB)
📄
chunk.pyo.tar
(7 KB)
📄
churchcrm.sql.sql.tar.gz
(8.51 KB)
📄
churchcrm.sql.tar
(50 KB)
📄
churchcrm.tar
(25.58 MB)
📄
churchcrm.tar.gz
(24.29 MB)
📄
churchcrm.zip
(25.56 MB)
📄
chyrp.tar
(206 KB)
📄
chyrp.tar.gz
(121.5 KB)
📄
chyrp.zip
(183.38 KB)
📄
cifs-utils.tar
(13 KB)
📄
cifs-utils.tar.gz
(4.75 KB)
📄
cifs-utils.zip
(11.65 KB)
📄
cifs_idmap_sss.so.so.tar.gz
(4.76 KB)
📄
cifs_idmap_sss.so.tar
(13 KB)
📄
cil.h.h.tar.gz
(1.47 KB)
📄
cil.h.tar
(5 KB)
📄
cil.tar
(5 KB)
📄
cil.tar.gz
(1.45 KB)
📄
cil.zip
(3.55 KB)
📄
cipso_cache_enable.tar
(2 KB)
📄
cipso_cache_enable.tar.gz
(120 B)
📄
cipso_rbm_optfmt.tar
(2 KB)
📄
cipso_rbm_optfmt.tar.gz
(118 B)
📄
cipso_rbm_strictvalid.tar
(2 KB)
📄
cipso_rbm_strictvalid.tar.gz
(122 B)
📄
cirrus.tar
(5.06 MB)
📄
cirrus.tar.gz
(1.54 MB)
📄
cirrus.zip
(4.71 MB)
📄
cis.tar
(17 KB)
📄
cis.tar.gz
(1.48 KB)
📄
cis.zip
(4.01 KB)
📄
cjdpoll.tar
(118.5 KB)
📄
cjdpoll.tar.gz
(68.35 KB)
📄
cjdpoll.zip
(102.54 KB)
📄
cksum.tar
(39 KB)
📄
cksum.tar.gz
(17.18 KB)
📄
cl-MariaDB1104.conf.conf.tar.gz
(156 B)
📄
cl-MariaDB1104.conf.tar
(2 KB)
📄
cl.nodejs.tar
(2 KB)
📄
cl.nodejs.tar.gz
(146 B)
📄
cl.nodejs.zip
(221 B)
📄
cl.php.d.tar
(22.5 KB)
📄
cl.php.d.tar.gz
(1.03 KB)
📄
cl.php.d.zip
(13.94 KB)
📄
cl.python.tar
(2 KB)
📄
cl.python.tar.gz
(147 B)
📄
cl.python.zip
(222 B)
📄
cl.selector.conf.d.tar
(41.5 KB)
📄
cl.selector.conf.d.tar.gz
(11.71 KB)
📄
cl.selector.conf.d.zip
(35.7 KB)
📄
cl_edition.tar
(2 KB)
📄
cl_edition.tar.gz
(126 B)
📄
cl_sysctl.tar
(6.5 KB)
📄
cl_sysctl.tar.gz
(1.33 KB)
📄
class_module.rb.rb.tar.gz
(5.64 KB)
📄
class_module.rb.tar
(21.5 KB)
📄
classes.tar
(753 KB)
📄
classes.tar.gz
(145.93 KB)
📄
classes.zip
(719.86 KB)
📄
classfix.pyc.pyc.tar.gz
(2.1 KB)
📄
classfix.pyc.tar
(6 KB)
📄
classfix.pyo.pyo.tar.gz
(2.1 KB)
📄
classfix.pyo.tar
(6 KB)
📄
classicpress.tar
(11.3 MB)
📄
classicpress.tar.gz
(10.82 MB)
📄
classicpress.zip
(11.27 MB)
📄
clcpapi.tar
(5.5 KB)
📄
clcpapi.tar.gz
(1.19 KB)
📄
cldetect.tar
(12 KB)
📄
cldetect.tar.gz
(2.5 KB)
📄
cldr-plurals.tar
(32 KB)
📄
cldr-plurals.tar.gz
(13.51 KB)
📄
clean-old.sh.sh.tar.gz
(1.7 KB)
📄
clean-old.sh.tar
(6 KB)
📄
clean.rb.rb.tar.gz
(628 B)
📄
clean.rb.tar
(9 KB)
📄
cleancache.sh.sh.tar.gz
(587 B)
📄
cleancache.sh.tar
(3 KB)
📄
cleanfuture.pyc.pyc.tar.gz
(3.48 KB)
📄
cleanfuture.pyc.tar
(9 KB)
📄
cleanfuture.pyo.pyo.tar.gz
(3.46 KB)
📄
cleanfuture.pyo.tar
(9 KB)
📄
cleanlitemage.sh.sh.tar.gz
(932 B)
📄
cleanlitemage.sh.tar
(4 KB)
📄
clear.tar
(14.5 KB)
📄
clear.tar.gz
(4.87 KB)
📄
clicshop.tar
(23.73 MB)
📄
clicshop.tar.gz
(19.68 MB)
📄
clicshop.zip
(23.71 MB)
📄
client.go.go.tar.gz
(9.01 KB)
📄
client.go.tar
(35 KB)
📄
client.ini.php.ini.php.tar.gz
(505 B)
📄
client.ini.php.tar
(2.5 KB)
📄
client.py.py.tar.gz
(15.47 KB)
📄
client.py.tar
(112 KB)
📄
client_ed25519.so.so.tar.gz
(46.92 KB)
📄
client_ed25519.so.tar
(68.5 KB)
📄
clientexec.tar
(74.62 MB)
📄
clientexec.tar.gz
(70.48 MB)
📄
clientexec.zip
(74.59 MB)
📄
clip.png.png.tar.gz
(15.92 KB)
📄
clip.png.tar
(17.5 KB)
📄
clip.tar
(236 KB)
📄
clip.tar.gz
(134.74 KB)
📄
clip.zip
(209.09 KB)
📄
clipper.tar
(150 KB)
📄
clipper.tar.gz
(83.75 KB)
📄
clipper.zip
(131.81 KB)
📄
clnt.h.h.tar.gz
(3.53 KB)
📄
clnt.h.tar
(11 KB)
📄
clockid_t.h.h.tar.gz
(212 B)
📄
clockid_t.h.tar
(2 KB)
📄
clone.php.php.tar.gz
(3.41 KB)
📄
clone.php.tar
(2.72 MB)
📄
clone.xml.tar
(28 KB)
📄
clone.xml.xml.tar.gz
(270 B)
📄
clone_bootstrap.php.php.tar.gz
(2.07 KB)
📄
clone_bootstrap.php.tar
(8 KB)
📄
cloudlinux-default-base.tar
(2.5 KB)
📄
cloudlinux-default-base.tar.gz
(593 B)
📄
cloudlinux-default-base.zip
(1.03 KB)
📄
cloudlinux-default-cgv1.tar
(2 KB)
📄
cloudlinux-default-cgv1.tar.gz
(259 B)
📄
cloudlinux-default-cgv1.zip
(391 B)
📄
cloudlinux-default-cgv2.tar
(2 KB)
📄
cloudlinux-default-cgv2.tar.gz
(275 B)
📄
cloudlinux-default-cgv2.zip
(389 B)
📄
cloudlinux-default.tar
(2 KB)
📄
cloudlinux-default.tar.gz
(212 B)
📄
cloudlinux-default.zip
(332 B)
📄
cloudlinux-dummy.tar
(2 KB)
📄
cloudlinux-dummy.tar.gz
(159 B)
📄
cloudlinux-dummy.zip
(227 B)
📄
cloudlinux-latency-performance-base.tar
(3.5 KB)
📄
cloudlinux-latency-performance-base.tar.gz
(1.09 KB)
📄
cloudlinux-latency-performance-base.zip
(2.13 KB)
📄
cloudlinux-latency-performance-cgv1.tar
(2 KB)
📄
cloudlinux-latency-performance-cgv1.tar.gz
(266 B)
📄
cloudlinux-latency-performance-cgv1.zip
(403 B)
📄
cloudlinux-latency-performance-cgv2.tar
(2 KB)
📄
cloudlinux-latency-performance-cgv2.tar.gz
(283 B)
📄
cloudlinux-latency-performance-cgv2.zip
(401 B)
📄
cloudlinux-linksafe.tar
(2 KB)
📄
cloudlinux-linksafe.tar.gz
(226 B)
📄
cloudlinux-linksafe.zip
(345 B)
📄
cloudlinux-selector.tar
(2.5 KB)
📄
cloudlinux-selector.tar.gz
(474 B)
📄
cloudlinux-vz.tar
(2 KB)
📄
cloudlinux-vz.tar.gz
(159 B)
📄
cloudlinux-vz.zip
(227 B)
📄
clshared.tar
(241 KB)
📄
clshared.tar.gz
(16.71 KB)
📄
clshared.zip
(233.19 KB)
📄
clsolo.tar
(241 KB)
📄
clsolo.tar.gz
(16.68 KB)
📄
clusterdb.tar
(72 KB)
📄
clusterdb.tar.gz
(27.7 KB)
📄
cmac.h.h.tar.gz
(627 B)
📄
cmac.h.tar
(3 KB)
📄
cmake.tar
(72.5 KB)
📄
cmake.tar.gz
(7.42 KB)
📄
cmake.zip
(43.71 KB)
📄
cmbtfw12.tlv.tar
(48 KB)
📄
cmbtfw12.tlv.tlv.tar.gz
(33.26 KB)
📄
cmbtfw13.tlv.tar
(23 KB)
📄
cmbtfw13.tlv.tlv.tar.gz
(15.3 KB)
📄
cmd.py.py.tar.gz
(4.47 KB)
📄
cmd.py.tar
(47.5 KB)
📄
cmd.pyc.pyc.tar.gz
(6.01 KB)
📄
cmd.pyc.tar
(15.5 KB)
📄
cmd.pyo.pyo.tar.gz
(6 KB)
📄
cmd.pyo.tar
(15.5 KB)
📄
cmd.tar
(11.5 KB)
📄
cmd.tar.gz
(1.4 KB)
📄
cmd.zip
(5.25 KB)
📄
cmdline.tar
(13 KB)
📄
cmdline.tar.gz
(313 B)
📄
cml_guc_33.0.0.bin.0.0.bin.tar.gz
(84.1 KB)
📄
cml_guc_33.0.0.bin.tar
(180.5 KB)
📄
cml_guc_49.0.1.bin.0.1.bin.tar.gz
(85.79 KB)
📄
cml_guc_49.0.1.bin.tar
(194.5 KB)
📄
cml_guc_62.0.0.bin.0.0.bin.tar.gz
(90.95 KB)
📄
cml_guc_62.0.0.bin.tar
(197.5 KB)
📄
cml_guc_69.0.3.bin.0.3.bin.tar.gz
(101.91 KB)
📄
cml_guc_69.0.3.bin.tar
(214.5 KB)
📄
cml_guc_70.1.1.bin.1.1.bin.tar.gz
(93.23 KB)
📄
cml_guc_70.1.1.bin.tar
(204 KB)
📄
cml_huc_4.0.0.bin.0.0.bin.tar.gz
(80.18 KB)
📄
cml_huc_4.0.0.bin.tar
(222.5 KB)
📄
cmmb_vega_12mhz.inp.inp.tar.gz
(38.54 KB)
📄
cmmb_vega_12mhz.inp.tar
(63 KB)
📄
cmmb_venice_12mhz.inp.inp.tar.gz
(61.92 KB)
📄
cmmb_venice_12mhz.inp.tar
(96.5 KB)
📄
cmnv12.bin.bin.tar.gz
(1.48 KB)
📄
cmnv12.bin.tar
(8 KB)
📄
cmnv13.bin.bin.tar.gz
(967 B)
📄
cmnv13.bin.tar
(6 KB)
📄
cmnv13s.bin.bin.tar.gz
(968 B)
📄
cmnv13s.bin.tar
(3.5 KB)
📄
cmnv13t.bin.bin.tar.gz
(970 B)
📄
cmnv13t.bin.tar
(3.5 KB)
📄
cmosdump.mod.mod.tar.gz
(833 B)
📄
cmosdump.mod.tar
(3 KB)
📄
cmostest.mod.mod.tar.gz
(1.16 KB)
📄
cmostest.mod.tar
(4 KB)
📄
cmp.mod.mod.tar.gz
(1.23 KB)
📄
cmp.mod.tar
(7 KB)
📄
cmp.tar
(105.5 KB)
📄
cmp.tar.gz
(24.7 KB)
📄
cmp_test.mod.mod.tar.gz
(2.17 KB)
📄
cmp_test.mod.tar
(7.5 KB)
📄
cms.h.h.tar.gz
(3.01 KB)
📄
cms.h.tar
(17.5 KB)
📄
cms.php.php.tar.gz
(4.2 KB)
📄
cms.php.tar
(35.5 KB)
📄
cmserr.h.h.tar.gz
(2.28 KB)
📄
cmserr.h.tar
(12.5 KB)
📄
cmsimple.tar
(1.43 MB)
📄
cmsimple.tar.gz
(1.27 MB)
📄
cmsimple.zip
(1.41 MB)
📄
cmssimple.sql.sql.tar.gz
(87.44 KB)
📄
cmssimple.sql.tar
(441 KB)
📄
cmssimple.tar
(18.56 MB)
📄
cmssimple.tar.gz
(15.12 MB)
📄
cmssimple.zip
(18.53 MB)
📄
cnl.tar
(576 KB)
📄
cnl.tar.gz
(256.08 KB)
📄
cnl.zip
(574.42 KB)
📄
cnm.tar
(1.46 MB)
📄
cnm.tar.gz
(462.94 KB)
📄
cnm.zip
(1.45 MB)
📄
cnn55xx_ae.fw.fw.tar.gz
(10.28 KB)
📄
cnn55xx_ae.fw.tar
(17 KB)
📄
cnn55xx_se.fw.fw.tar.gz
(24.65 KB)
📄
cnn55xx_se.fw.tar
(36 KB)
📄
cockpit.xml.tar
(3 KB)
📄
cockpit.xml.xml.tar.gz
(253 B)
📄
code.h.h.tar.gz
(2.8 KB)
📄
code.h.tar
(9 KB)
📄
code.py.py.tar.gz
(3.41 KB)
📄
code.py.tar
(33.5 KB)
📄
code.pyc.pyc.tar.gz
(4.33 KB)
📄
code.pyc.tar
(12 KB)
📄
code.pyo.pyo.tar.gz
(4.34 KB)
📄
code.pyo.tar
(12 KB)
📄
codecs.py.py.tar.gz
(8.49 KB)
📄
codecs.py.tar
(109.5 KB)
📄
codecs.pyc.pyc.tar.gz
(10.39 KB)
📄
codecs.pyc.tar
(37.5 KB)
📄
codecs.pyo.pyo.tar.gz
(10.39 KB)
📄
codecs.pyo.tar
(37.5 KB)
📄
codeop.py.py.tar.gz
(1.98 KB)
📄
codeop.py.tar
(21 KB)
📄
codeop.pyc.pyc.tar.gz
(2.5 KB)
📄
codeop.pyc.tar
(8 KB)
📄
codeop.pyo.pyo.tar.gz
(2.5 KB)
📄
codeop.pyo.tar
(8 KB)
📄
col.tar
(31 KB)
📄
col.tar.gz
(13.45 KB)
📄
colcrt.tar
(18 KB)
📄
colcrt.tar.gz
(6.06 KB)
📄
collab.tar
(197 KB)
📄
collab.tar.gz
(105.17 KB)
📄
collab.zip
(168.64 KB)
📄
collect.tar
(44 KB)
📄
collect.tar.gz
(8.91 KB)
📄
collectd.xml.tar
(2 KB)
📄
collectd.xml.xml.tar.gz
(304 B)
📄
collections.py.py.tar.gz
(7.63 KB)
📄
collections.py.tar
(29 KB)
📄
collections.pyc.pyc.tar.gz
(9.18 KB)
📄
collections.pyc.tar
(27.5 KB)
📄
collections.pyo.pyo.tar.gz
(9.15 KB)
📄
collections.pyo.tar
(27 KB)
📄
collections.tar
(308 KB)
📄
collections.tar.gz
(55.11 KB)
📄
collections.zip
(298.07 KB)
📄
colorchooser.py.py.tar.gz
(1.16 KB)
📄
colorchooser.py.tar
(4.5 KB)
📄
colorsys.py.py.tar.gz
(1.57 KB)
📄
colorsys.py.tar
(14.5 KB)
📄
colorsys.pyc.pyc.tar.gz
(1.81 KB)
📄
colorsys.pyc.tar
(5.5 KB)
📄
colorsys.pyo.pyo.tar.gz
(1.81 KB)
📄
colorsys.pyo.tar
(5.5 KB)
📄
colrm.tar
(26.5 KB)
📄
colrm.tar.gz
(11.27 KB)
📄
column.tar
(51 KB)
📄
column.tar.gz
(22.06 KB)
📄
com_err.h.h.tar.gz
(847 B)
📄
com_err.h.tar
(7 KB)
📄
com_err.pc.pc.tar.gz
(266 B)
📄
com_err.pc.tar
(2 KB)
📄
combinerefs.pyc.pyc.tar.gz
(2.22 KB)
📄
combinerefs.pyc.tar
(6 KB)
📄
combinerefs.pyo.pyo.tar.gz
(2.19 KB)
📄
combinerefs.pyo.tar
(6 KB)
📄
combobox.xbm.tar
(2.5 KB)
📄
combobox.xbm.xbm.tar.gz
(292 B)
📄
combobox.xpm.tar
(4 KB)
📄
combobox.xpm.xpm.tar.gz
(462 B)
📄
comm.tar
(54.5 KB)
📄
comm.tar.gz
(105 B)
📄
command-processor.rb.rb.tar.gz
(4.79 KB)
📄
command-processor.rb.tar
(20.5 KB)
📄
command.lst.lst.tar.gz
(1.52 KB)
📄
command.lst.tar
(6 KB)
📄
commands.py.py.tar.gz
(1.17 KB)
📄
commands.py.tar
(4 KB)
📄
commands.pyc.pyc.tar.gz
(1.22 KB)
📄
commands.pyc.tar
(4 KB)
📄
commands.pyo.pyo.tar.gz
(1.22 KB)
📄
commands.pyo.tar
(4 KB)
📄
commentics.tar
(5.04 MB)
📄
commentics.tar.gz
(4.51 MB)
📄
commentics.zip
(5 MB)
📄
common.php.php.tar.gz
(381 B)
📄
common.php.tar
(2 KB)
📄
common.rb.rb.tar.gz
(9.56 KB)
📄
common.rb.tar
(97 KB)
📄
common.tar
(18.5 KB)
📄
common.tar.gz
(7.24 KB)
📄
common.zip
(16.31 KB)
📄
commondialog.py.py.tar.gz
(649 B)
📄
commondialog.py.tar
(3 KB)
📄
comp.h.h.tar.gz
(678 B)
📄
comp.h.tar
(3 KB)
📄
compact_unevictable_allowed.tar
(2 KB)
📄
compact_unevictable_allowed.tar.gz
(122 B)
📄
compaction_proactiveness.tar
(2 KB)
📄
compaction_proactiveness.tar.gz
(119 B)
📄
compare.tar
(19.76 MB)
📄
compare.tar.gz
(3.86 KB)
📄
compat.py.py.tar.gz
(389 B)
📄
compat.py.tar
(2.5 KB)
📄
compile.h.h.tar.gz
(1.4 KB)
📄
compile.h.tar
(5 KB)
📄
compileall.pyc.pyc.tar.gz
(3.31 KB)
📄
compileall.pyc.tar
(8.5 KB)
📄
compileall.pyo.pyo.tar.gz
(3.31 KB)
📄
compileall.pyo.tar
(8.5 KB)
📄
compiled.tar
(5.23 MB)
📄
compiled.tar.gz
(1.26 MB)
📄
compiled.zip
(5.22 MB)
📄
compiler.tar
(664 KB)
📄
compiler.tar.gz
(153.99 KB)
📄
compiler.zip
(643.22 KB)
📄
complex.h.h.tar.gz
(1.99 KB)
📄
complex.h.tar
(8.5 KB)
📄
complex.rb.rb.tar.gz
(356 B)
📄
complex.rb.tar
(2 KB)
📄
compose.8859_7.8859_7.tar.gz
(291 B)
📄
compose.8859_7.tar
(2.5 KB)
📄
compose.8859_8.8859_8.tar.gz
(147 B)
📄
compose.8859_8.tar
(2 KB)
📄
compose.latin1.latin1.tar.gz
(1.02 KB)
📄
compose.latin1.tar
(5.5 KB)
📄
compose.latin2.latin2.tar.gz
(866 B)
📄
compose.latin2.tar
(5 KB)
📄
compose.latin3.latin3.tar.gz
(565 B)
📄
compose.latin3.tar
(3.5 KB)
📄
compose.latin4.latin4.tar.gz
(797 B)
📄
compose.latin4.tar
(4.5 KB)
📄
composer.json.json.tar.gz
(114 B)
📄
composer.json.tar
(10.5 KB)
📄
composer.lock.lock.tar.gz
(6.98 KB)
📄
composer.lock.tar
(66 KB)
📄
composer.tar
(2.73 MB)
📄
composer.tar.gz
(689.94 KB)
📄
composer.zip
(2.73 MB)
📄
composite.h.h.tar.gz
(1.71 KB)
📄
composite.h.tar
(15.5 KB)
📄
composite.tar
(13.5 KB)
📄
composite.tar.gz
(3.62 KB)
📄
compress_offload.h.h.tar.gz
(1.98 KB)
📄
compress_offload.h.tar
(7.5 KB)
📄
conc.png.png.tar.gz
(8.46 KB)
📄
conc.png.tar
(10 KB)
📄
conc.tar
(204.5 KB)
📄
conc.tar.gz
(117.64 KB)
📄
conc.zip
(181.93 KB)
📄
conc56.tar
(204 KB)
📄
conc56.tar.gz
(116.6 KB)
📄
conc56.zip
(181.17 KB)
📄
conc8.sql.sql.tar.gz
(66.69 KB)
📄
conc8.sql.tar
(484.5 KB)
📄
conc8.tar
(85.09 MB)
📄
conc8.tar.gz
(78.91 MB)
📄
conc8.zip
(85.06 MB)
📄
conc85.sql.sql.tar.gz
(55.01 KB)
📄
conc85.sql.tar
(381 KB)
📄
conc85.tar
(57.18 MB)
📄
conc85.tar.gz
(52.96 MB)
📄
conc85.zip
(57.15 MB)
📄
concrete.php.php.tar.gz
(370 B)
📄
concrete.php.tar
(5 KB)
📄
concurrent.tar
(325.5 KB)
📄
concurrent.tar.gz
(33.39 KB)
📄
concurrent.zip
(289.89 KB)
📄
condor-collector.xml.tar
(2 KB)
📄
condor-collector.xml.xml.tar.gz
(283 B)
📄
conf.h.h.tar.gz
(1.67 KB)
📄
conf.h.tar
(7 KB)
📄
conf.inc.php.inc.php.tar.gz
(505 B)
📄
conf.inc.php.tar
(17.5 KB)
📄
conf.php.php.tar.gz
(730 B)
📄
conf.php.tar
(7 KB)
📄
conf.tar
(259.5 KB)
📄
conf.tar.gz
(218 B)
📄
conf.zip
(77 KB)
📄
conf_api.h.h.tar.gz
(609 B)
📄
conf_api.h.tar
(3 KB)
📄
config-extensions.def.def.tar.gz
(1.25 KB)
📄
config-extensions.def.tar
(4.5 KB)
📄
config-keys.def.def.tar.gz
(1.77 KB)
📄
config-keys.def.tar
(9.5 KB)
📄
config-main.def.def.tar.gz
(1.18 KB)
📄
config-main.def.tar
(4.5 KB)
📄
config.c.c.tar.gz
(955 B)
📄
config.c.in.c.in.tar.gz
(755 B)
📄
config.c.in.tar
(3 KB)
📄
config.c.tar
(4 KB)
📄
config.core.php.core.php.tar.gz
(317 B)
📄
config.core.php.tar
(2 KB)
📄
config.guess.guess.tar.gz
(12.98 KB)
📄
config.guess.tar
(88 KB)
📄
config.h.h.tar.gz
(33.66 KB)
📄
config.h.tar
(187.5 KB)
📄
config.html.html.tar.gz
(3.46 KB)
📄
config.html.tar
(12 KB)
📄
config.inc.php.inc.php.tar.gz
(238 B)
📄
config.inc.php.tar
(180.5 KB)
📄
config.ini.ini.tar.gz
(631 B)
📄
config.ini.php.ini.php.tar.gz
(924 B)
📄
config.ini.php.tar
(5.5 KB)
📄
config.ini.tar
(23.5 KB)
📄
config.json.json.tar.gz
(472 B)
📄
config.json.tar
(5 KB)
📄
config.local.php.local.php.tar.gz
(3.24 KB)
📄
config.local.php.tar
(10 KB)
📄
config.php.php.tar.gz
(309 B)
📄
config.php.tar
(500.5 KB)
📄
config.py.py.tar.gz
(8.36 KB)
📄
config.py.tar
(108 KB)
📄
config.pyc.pyc.tar.gz
(10.31 KB)
📄
config.pyc.tar
(27 KB)
📄
config.pyo.pyo.tar.gz
(10.29 KB)
📄
config.pyo.tar
(27 KB)
📄
config.rb.rb.tar.gz
(2.22 KB)
📄
config.rb.tar
(7.5 KB)
📄
config.sub.sub.tar.gz
(10.27 KB)
📄
config.sub.tar
(37 KB)
📄
config.tar
(44 KB)
📄
config.tar.gz
(5.16 KB)
📄
config.yaml.tar
(5.5 KB)
📄
config.yaml.yaml.tar.gz
(1.58 KB)
📄
config.yml.tar
(26.5 KB)
📄
config.yml.yml.tar.gz
(8.16 KB)
📄
config.zip
(40.1 KB)
📄
config6.tar
(4.5 KB)
📄
config6.tar.gz
(965 B)
📄
configDialog.py.py.tar.gz
(13.88 KB)
📄
configDialog.py.tar
(66 KB)
📄
config_.php.php.tar.gz
(449 B)
📄
config_.php.tar
(5 KB)
📄
config_db.inc.php.inc.php.tar.gz
(286 B)
📄
config_db.inc.php.tar
(2 KB)
📄
config_db.php.php.tar.gz
(255 B)
📄
config_db.php.tar
(4 KB)
📄
config_en.php.php.tar.gz
(840 B)
📄
config_en.php.tar
(3.5 KB)
📄
config_global.php.php.tar.gz
(4.79 KB)
📄
config_global.php.tar
(27 KB)
📄
config_vars.mk.mk.tar.gz
(1.4 KB)
📄
config_vars.mk.tar
(5 KB)
📄
configfile.mod.mod.tar.gz
(1.06 KB)
📄
configfile.mod.tar
(4 KB)
📄
configparser.py.py.tar.gz
(12.16 KB)
📄
configparser.py.tar
(108 KB)
📄
configs.tar
(101 KB)
📄
configs.tar.gz
(11.21 KB)
📄
configs.zip
(97.25 KB)
📄
configuration.php.php.tar.gz
(357 B)
📄
configuration.php.tar
(12.5 KB)
📄
configurations.tar
(2.5 KB)
📄
configurations.tar.gz
(579 B)
📄
configurations.zip
(1.13 KB)
📄
configure.tar
(4 KB)
📄
configure.tar.gz
(439 B)
📄
confname.h.h.tar.gz
(4.43 KB)
📄
confname.h.tar
(25 KB)
📄
conjure.tar
(19.76 MB)
📄
conjure.tar.gz
(3.62 KB)
📄
connect.php.php.tar.gz
(297 B)
📄
connect.php.tar
(2 KB)
📄
connection.py.py.tar.gz
(4.31 KB)
📄
connection.py.tar
(79.5 KB)
📄
cons.saver.saver.tar.gz
(4.69 KB)
📄
cons.saver.tar
(15 KB)
📄
console.so.so.tar.gz
(8.39 KB)
📄
console.so.tar
(21.5 KB)
📄
console.tar
(2 KB)
📄
console.tar.gz
(293 B)
📄
console.zip
(545 B)
📄
consolefonts.tar
(654 KB)
📄
consolefonts.tar.gz
(407.38 KB)
📄
consolefonts.zip
(499.21 KB)
📄
consoletrans.tar
(405 KB)
📄
consoletrans.tar.gz
(54.34 KB)
📄
consoletrans.zip
(374.62 KB)
📄
consoletype.tar
(13.5 KB)
📄
consoletype.tar.gz
(3.87 KB)
📄
constants.py.py.tar.gz
(662 B)
📄
constants.py.tar
(5.5 KB)
📄
constraint.h.h.tar.gz
(1.07 KB)
📄
constraint.h.tar
(4.5 KB)
📄
consts.py.py.tar.gz
(364 B)
📄
consts.py.tar
(2 KB)
📄
container.h.h.tar.gz
(6.15 KB)
📄
container.h.tar
(26 KB)
📄
contao.sql.sql.tar.gz
(7.3 KB)
📄
contao.sql.tar
(68.5 KB)
📄
contao.tar
(83.82 MB)
📄
contao.tar.gz
(79.43 MB)
📄
contao.zip
(83.79 MB)
📄
contentmanager.py.py.tar.gz
(3.13 KB)
📄
contentmanager.py.tar
(23 KB)
📄
contenttypes.yml.tar
(13.5 KB)
📄
contenttypes.yml.yml.tar.gz
(3.7 KB)
📄
context.h.h.tar.gz
(359 B)
📄
context.h.tar
(9 KB)
📄
context.py.py.tar.gz
(2.88 KB)
📄
context.py.tar
(24 KB)
📄
context_record.h.h.tar.gz
(547 B)
📄
context_record.h.tar
(3.5 KB)
📄
contextlib.py.py.tar.gz
(3.98 KB)
📄
contextlib.py.tar
(44.5 KB)
📄
contextlib.pyc.pyc.tar.gz
(1.88 KB)
📄
contextlib.pyc.tar
(6 KB)
📄
contextlib.pyo.pyo.tar.gz
(1.88 KB)
📄
contextlib.pyo.tar
(6 KB)
📄
contextvars.py.py.tar.gz
(187 B)
📄
contextvars.py.tar
(2 KB)
📄
continuation.so.so.tar.gz
(2.78 KB)
📄
continuation.so.tar
(17.5 KB)
📄
control.go.go.tar.gz
(3.25 KB)
📄
control.go.tar
(10 KB)
📄
control.h.h.tar.gz
(5.05 KB)
📄
control.h.tar
(22 KB)
📄
controlpanelname.tar
(2 KB)
📄
controlpanelname.tar.gz
(114 B)
📄
convert.tar
(19.76 MB)
📄
convert.tar.gz
(3.63 KB)
📄
cookie.rb.rb.tar.gz
(1.9 KB)
📄
cookie.rb.tar
(25.5 KB)
📄
cookiejar.py.py.tar.gz
(19.16 KB)
📄
cookiejar.py.tar
(152.5 KB)
📄
cookielib.py.py.tar.gz
(16.92 KB)
📄
cookielib.py.tar
(65.5 KB)
📄
cookies.inc.inc.tar.gz
(3.27 KB)
📄
cookies.inc.tar
(10 KB)
📄
cookies.py.py.tar.gz
(7.15 KB)
📄
cookies.py.tar
(43 KB)
📄
cop.h.h.tar.gz
(11.25 KB)
📄
cop.h.tar
(40.5 KB)
📄
copy.py.py.tar.gz
(2.69 KB)
📄
copy.py.tar
(31.5 KB)
📄
copy.pyc.pyc.tar.gz
(5.04 KB)
📄
copy.pyc.tar
(13.5 KB)
📄
copy.pyo.pyo.tar.gz
(5.01 KB)
📄
copy.pyo.tar
(13.5 KB)
📄
copy1.svg.svg.tar.gz
(14.65 KB)
📄
copy1.svg.tar
(40.5 KB)
📄
copy_reg.py.py.tar.gz
(2.51 KB)
📄
copy_reg.py.tar
(8.5 KB)
📄
copy_reg.pyc.pyc.tar.gz
(2.48 KB)
📄
copy_reg.pyc.tar
(7 KB)
📄
copy_reg.pyo.pyo.tar.gz
(2.46 KB)
📄
copy_reg.pyo.tar
(7 KB)
📄
copyreg.py.py.tar.gz
(2.54 KB)
📄
copyreg.py.tar
(16 KB)
📄
copytime.pyc.pyc.tar.gz
(617 B)
📄
copytime.pyc.tar
(2.5 KB)
📄
copytime.pyo.pyo.tar.gz
(618 B)
📄
copytime.pyo.tar
(2.5 KB)
📄
core.json.json.tar.gz
(203 B)
📄
core.json.tar
(2 KB)
📄
core_pattern.tar
(2 KB)
📄
core_pattern.tar.gz
(159 B)
📄
core_pipe_limit.tar
(2 KB)
📄
core_pipe_limit.tar.gz
(116 B)
📄
coredump_filter.tar
(12 KB)
📄
coredump_filter.tar.gz
(117 B)
📄
coreinfo.php.php.tar.gz
(183 B)
📄
coreinfo.php.tar
(2 KB)
📄
coreutils.tar
(13.5 KB)
📄
coreutils.tar.gz
(3.56 KB)
📄
coreutils.zip
(11.89 KB)
📄
cotonti.sql.sql.tar.gz
(6.91 KB)
📄
cotonti.sql.tar
(37 KB)
📄
cotonti.tar
(3.95 MB)
📄
cotonti.tar.gz
(3.33 MB)
📄
cotonti.zip
(3.93 MB)
📄
coverage.so.so.tar.gz
(5.83 KB)
📄
coverage.so.tar
(17.5 KB)
📄
coverage3.tar
(2 KB)
📄
coverage3.tar.gz
(237 B)
📄
cp.tar
(150 KB)
📄
cp.tar.gz
(71.37 KB)
📄
cp1250.uni.tar
(13 KB)
📄
cp1250.uni.uni.tar.gz
(1.46 KB)
📄
cp437.00-1f.uni.00-1f.uni.tar.gz
(288 B)
📄
cp437.00-1f.uni.tar
(2 KB)
📄
cp437.uni.tar
(11 KB)
📄
cp437.uni.uni.tar.gz
(1.95 KB)
📄
cp437_to_uni.trans.tar
(11 KB)
📄
cp437_to_uni.trans.trans.tar.gz
(2.74 KB)
📄
cp737.uni.tar
(14 KB)
📄
cp737.uni.uni.tar.gz
(1.44 KB)
📄
cp737_to_uni.trans.tar
(11 KB)
📄
cp737_to_uni.trans.trans.tar.gz
(2.62 KB)
📄
cp737a.uni.tar
(15 KB)
📄
cp737a.uni.uni.tar.gz
(1.68 KB)
📄
cp737b.uni.tar
(15 KB)
📄
cp737b.uni.uni.tar.gz
(1.79 KB)
📄
cp737c.uni.tar
(15 KB)
📄
cp737c.uni.uni.tar.gz
(1.75 KB)
📄
cp775_to_uni.trans.tar
(11 KB)
📄
cp775_to_uni.trans.trans.tar.gz
(2.68 KB)
📄
cp850.uni.tar
(13 KB)
📄
cp850.uni.uni.tar.gz
(1.5 KB)
📄
cp850_to_uni.trans.tar
(11 KB)
📄
cp850_to_uni.trans.trans.tar.gz
(2.67 KB)
📄
cp850a.uni.tar
(14 KB)
📄
cp850a.uni.uni.tar.gz
(1.74 KB)
📄
cp850b.uni.tar
(10 KB)
📄
cp850b.uni.uni.tar.gz
(1.76 KB)
📄
cp850z.uni.tar
(10 KB)
📄
cp850z.uni.uni.tar.gz
(1.69 KB)
📄
cp852_to_uni.trans.tar
(11 KB)
📄
cp852_to_uni.trans.trans.tar.gz
(2.58 KB)
📄
cp853_to_uni.trans.tar
(11 KB)
📄
cp853_to_uni.trans.trans.tar.gz
(2.61 KB)
📄
cp855_to_uni.trans.tar
(11 KB)
📄
cp855_to_uni.trans.trans.tar.gz
(2.49 KB)
📄
cp857_to_uni.trans.tar
(11 KB)
📄
cp857_to_uni.trans.trans.tar.gz
(2.67 KB)
📄
cp860_to_uni.trans.tar
(11 KB)
📄
cp860_to_uni.trans.trans.tar.gz
(2.71 KB)
📄
cp861_to_uni.trans.tar
(11 KB)
📄
cp861_to_uni.trans.trans.tar.gz
(2.72 KB)
📄
cp862_to_uni.trans.tar
(10.5 KB)
📄
cp862_to_uni.trans.trans.tar.gz
(2.74 KB)
📄
cp863_to_uni.trans.tar
(11 KB)
📄
cp863_to_uni.trans.trans.tar.gz
(2.73 KB)
📄
cp864_to_uni.trans.tar
(11 KB)
📄
cp864_to_uni.trans.trans.tar.gz
(2.68 KB)
📄
cp865.uni.tar
(13 KB)
📄
cp865.uni.uni.tar.gz
(1.56 KB)
📄
cp865_to_uni.trans.tar
(11 KB)
📄
cp865_to_uni.trans.trans.tar.gz
(2.75 KB)
📄
cp865a.uni.tar
(15 KB)
📄
cp865a.uni.uni.tar.gz
(1.81 KB)
📄
cp866.uni.tar
(13 KB)
📄
cp866.uni.uni.tar.gz
(1.34 KB)
📄
cp866_to_uni.trans.tar
(11 KB)
📄
cp866_to_uni.trans.trans.tar.gz
(2.56 KB)
📄
cp866a.uni.tar
(15 KB)
📄
cp866a.uni.uni.tar.gz
(1.62 KB)
📄
cp869_to_uni.trans.tar
(10.5 KB)
📄
cp869_to_uni.trans.trans.tar.gz
(2.58 KB)
📄
cp874_to_uni.trans.tar
(10 KB)
📄
cp874_to_uni.trans.trans.tar.gz
(2.46 KB)
📄
cp949.so.so.tar.gz
(3.75 KB)
📄
cp949.so.tar
(13.5 KB)
📄
cpan.tar
(10 KB)
📄
cpan.tar.gz
(3.64 KB)
📄
cpanel.tar
(27.5 KB)
📄
cpanel.tar.gz
(5.22 KB)
📄
cpanel.zip
(24.8 KB)
📄
cpapirebuildcache.tar
(2 KB)
📄
cpapirebuildcache.tar.gz
(430 B)
📄
cparse.so.so.tar.gz
(8.94 KB)
📄
cparse.so.tar
(21.5 KB)
📄
cparser.rb.rb.tar.gz
(946 B)
📄
cparser.rb.tar
(13.5 KB)
📄
cpbackup-exclude.conf.conf.tar.gz
(118 B)
📄
cpbackup-exclude.conf.tar
(2 KB)
📄
cpbandwidth.tar
(3.5 KB)
📄
cpbandwidth.tar.gz
(748 B)
📄
cpbandwidth.zip
(2.08 KB)
📄
cpg.png.png.tar.gz
(3.21 KB)
📄
cpg.png.tar
(5 KB)
📄
cpg.sql.sql.tar.gz
(6.25 KB)
📄
cpg.sql.tar
(31 KB)
📄
cpg.tar
(4.34 MB)
📄
cpg.tar.gz
(3.55 MB)
📄
cpg.zip
(4.31 MB)
📄
cpia2.tar
(2.5 KB)
📄
cpia2.tar.gz
(821 B)
📄
cpia2.zip
(988 B)
📄
cpio.h.h.tar.gz
(1.17 KB)
📄
cpio.h.tar
(4 KB)
📄
cpio.mod.mod.tar.gz
(1.97 KB)
📄
cpio.mod.tar
(6 KB)
📄
cpio_be.mod.mod.tar.gz
(2 KB)
📄
cpio_be.mod.tar
(6 KB)
📄
cpp.tar
(3.63 MB)
📄
cpp.tar.gz
(525.78 KB)
📄
cpt01.tar
(117 KB)
📄
cpt01.tar.gz
(63.57 KB)
📄
cpt01.zip
(113.95 KB)
📄
cpt02.tar
(127.5 KB)
📄
cpt02.tar.gz
(70.3 KB)
📄
cpt02.zip
(124.57 KB)
📄
cpt03.tar
(120 KB)
📄
cpt03.tar.gz
(66.09 KB)
📄
cpt03.zip
(117.48 KB)
📄
cpt04.tar
(76.5 KB)
📄
cpt04.tar.gz
(55.53 KB)
📄
cpt04.zip
(73.85 KB)
📄
cptechdomain.shtml.shtml.tar.gz
(5.2 KB)
📄
cptechdomain.shtml.tar
(13 KB)
📄
cpu-set.h.h.tar.gz
(1.5 KB)
📄
cpu-set.h.tar
(6 KB)
📄
cpu0.tar
(9 KB)
📄
cpu0.tar.gz
(310 B)
📄
cpu0.zip
(1.23 KB)
📄
cpu1.tar
(9 KB)
📄
cpu1.tar.gz
(310 B)
📄
cpu1.zip
(1.23 KB)
📄
cpu10.tar
(9 KB)
📄
cpu10.tar.gz
(311 B)
📄
cpu10.zip
(1.23 KB)
📄
cpu11.tar
(9 KB)
📄
cpu11.tar.gz
(309 B)
📄
cpu11.zip
(1.23 KB)
📄
cpu12.tar
(9 KB)
📄
cpu12.tar.gz
(310 B)
📄
cpu12.zip
(1.23 KB)
📄
cpu13.tar
(9 KB)
📄
cpu13.tar.gz
(310 B)
📄
cpu13.zip
(1.23 KB)
📄
cpu14.tar
(9 KB)
📄
cpu14.tar.gz
(311 B)
📄
cpu14.zip
(1.23 KB)
📄
cpu15.tar
(9 KB)
📄
cpu15.tar.gz
(312 B)
📄
cpu15.zip
(1.23 KB)
📄
cpu16.tar
(9 KB)
📄
cpu16.tar.gz
(310 B)
📄
cpu16.zip
(1.23 KB)
📄
cpu17.tar
(9 KB)
📄
cpu17.tar.gz
(311 B)
📄
cpu17.zip
(1.23 KB)
📄
cpu18.tar
(9 KB)
📄
cpu18.tar.gz
(312 B)
📄
cpu18.zip
(1.23 KB)
📄
cpu19.tar
(9 KB)
📄
cpu19.tar.gz
(311 B)
📄
cpu19.zip
(1.23 KB)
📄
cpu2.tar
(9 KB)
📄
cpu2.tar.gz
(311 B)
📄
cpu2.zip
(1.23 KB)
📄
cpu20.tar
(9 KB)
📄
cpu20.tar.gz
(312 B)
📄
cpu20.zip
(1.23 KB)
📄
cpu21.tar
(9 KB)
📄
cpu21.tar.gz
(311 B)
📄
cpu21.zip
(1.23 KB)
📄
cpu22.tar
(9 KB)
📄
cpu22.tar.gz
(313 B)
📄
cpu22.zip
(1.23 KB)
📄
cpu23.tar
(9 KB)
📄
cpu23.tar.gz
(311 B)
📄
cpu23.zip
(1.23 KB)
📄
cpu24.tar
(9 KB)
📄
cpu24.tar.gz
(311 B)
📄
cpu24.zip
(1.23 KB)
📄
cpu25.tar
(9 KB)
📄
cpu25.tar.gz
(311 B)
📄
cpu25.zip
(1.23 KB)
📄
cpu26.tar
(9 KB)
📄
cpu26.tar.gz
(310 B)
📄
cpu26.zip
(1.23 KB)
📄
cpu27.tar
(9 KB)
📄
cpu27.tar.gz
(311 B)
📄
cpu27.zip
(1.23 KB)
📄
cpu28.tar
(9 KB)
📄
cpu28.tar.gz
(313 B)
📄
cpu28.zip
(1.23 KB)
📄
cpu29.tar
(9 KB)
📄
cpu29.tar.gz
(311 B)
📄
cpu29.zip
(1.23 KB)
📄
cpu3.tar
(9 KB)
📄
cpu3.tar.gz
(311 B)
📄
cpu3.zip
(1.23 KB)
📄
cpu30.tar
(9 KB)
📄
cpu30.tar.gz
(311 B)
📄
cpu30.zip
(1.23 KB)
📄
cpu31.tar
(9 KB)
📄
cpu31.tar.gz
(310 B)
📄
cpu31.zip
(1.23 KB)
📄
cpu32.tar
(9 KB)
📄
cpu32.tar.gz
(311 B)
📄
cpu32.zip
(1.23 KB)
📄
cpu33.tar
(9 KB)
📄
cpu33.tar.gz
(312 B)
📄
cpu33.zip
(1.23 KB)
📄
cpu34.tar
(9 KB)
📄
cpu34.tar.gz
(312 B)
📄
cpu34.zip
(1.23 KB)
📄
cpu35.tar
(9 KB)
📄
cpu35.tar.gz
(311 B)
📄
cpu35.zip
(1.23 KB)
📄
cpu36.tar
(9 KB)
📄
cpu36.tar.gz
(311 B)
📄
cpu36.zip
(1.23 KB)
📄
cpu37.tar
(9 KB)
📄
cpu37.tar.gz
(312 B)
📄
cpu37.zip
(1.23 KB)
📄
cpu38.tar
(9 KB)
📄
cpu38.tar.gz
(310 B)
📄
cpu38.zip
(1.23 KB)
📄
cpu39.tar
(9 KB)
📄
cpu39.tar.gz
(310 B)
📄
cpu39.zip
(1.23 KB)
📄
cpu4.tar
(9 KB)
📄
cpu4.tar.gz
(310 B)
📄
cpu4.zip
(1.23 KB)
📄
cpu40.tar
(9 KB)
📄
cpu40.tar.gz
(312 B)
📄
cpu40.zip
(1.23 KB)
📄
cpu41.tar
(9 KB)
📄
cpu41.tar.gz
(311 B)
📄
cpu41.zip
(1.23 KB)
📄
cpu42.tar
(9 KB)
📄
cpu42.tar.gz
(310 B)
📄
cpu42.zip
(1.23 KB)
📄
cpu43.tar
(9 KB)
📄
cpu43.tar.gz
(312 B)
📄
cpu43.zip
(1.23 KB)
📄
cpu44.tar
(9 KB)
📄
cpu44.tar.gz
(310 B)
📄
cpu44.zip
(1.23 KB)
📄
cpu45.tar
(9 KB)
📄
cpu45.tar.gz
(313 B)
📄
cpu45.zip
(1.23 KB)
📄
cpu46.tar
(9 KB)
📄
cpu46.tar.gz
(312 B)
📄
cpu46.zip
(1.23 KB)
📄
cpu47.tar
(9 KB)
📄
cpu47.tar.gz
(311 B)
📄
cpu47.zip
(1.23 KB)
📄
cpu5.tar
(9 KB)
📄
cpu5.tar.gz
(312 B)
📄
cpu5.zip
(1.23 KB)
📄
cpu6.tar
(9 KB)
📄
cpu6.tar.gz
(309 B)
📄
cpu6.zip
(1.23 KB)
📄
cpu7.tar
(9 KB)
📄
cpu7.tar.gz
(310 B)
📄
cpu7.zip
(1.23 KB)
📄
cpu8.tar
(9 KB)
📄
cpu8.tar.gz
(311 B)
📄
cpu8.zip
(1.23 KB)
📄
cpu9.tar
(9 KB)
📄
cpu9.tar.gz
(310 B)
📄
cpu9.zip
(1.23 KB)
📄
cpu_resctrl_groups.tar
(13 KB)
📄
cpu_resctrl_groups.tar.gz
(122 B)
📄
cpuid.mod.mod.tar.gz
(991 B)
📄
cpuid.mod.tar
(6 KB)
📄
cpuidle.h.h.tar.gz
(361 B)
📄
cpuidle.h.tar
(2.5 KB)
📄
cpuinfo.tar
(61 KB)
📄
cpuinfo.tar.gz
(1.74 KB)
📄
cpupower.service.service.tar.gz
(306 B)
📄
cpupower.service.tar
(2 KB)
📄
cpuset.tar
(6 KB)
📄
cpuset.tar.gz
(103 B)
📄
cpython.tar
(131.5 KB)
📄
cpython.tar.gz
(31.04 KB)
📄
cpython.zip
(120.46 KB)
📄
cracklib-check.tar
(15 KB)
📄
cracklib-check.tar.gz
(3.78 KB)
📄
cracklib-format.tar
(2 KB)
📄
cracklib-format.tar.gz
(282 B)
📄
cracklib-packer.tar
(15 KB)
📄
cracklib-packer.tar.gz
(4.17 KB)
📄
cracklib-unpacker.tar
(11 KB)
📄
cracklib-unpacker.tar.gz
(3.56 KB)
📄
crafty.sql.sql.tar.gz
(5.5 KB)
📄
crafty.sql.tar
(35 KB)
📄
crafty.tar
(6.54 MB)
📄
crafty.tar.gz
(6.23 MB)
📄
crafty.zip
(6.51 MB)
📄
crbtfw21.tlv.tar
(174.5 KB)
📄
crbtfw21.tlv.tlv.tar.gz
(122 KB)
📄
crbtfw32.tlv.tar
(116.5 KB)
📄
crbtfw32.tlv.tlv.tar.gz
(80.55 KB)
📄
crc64.mod.mod.tar.gz
(1.1 KB)
📄
crc64.mod.tar
(7 KB)
📄
createdb.tar
(72 KB)
📄
createdb.tar.gz
(27.43 KB)
📄
createuser.tar
(76.5 KB)
📄
createuser.tar.gz
(28.64 KB)
📄
criu-log.h.h.tar.gz
(878 B)
📄
criu-log.h.tar
(3.5 KB)
📄
criu-plugin.h.h.tar.gz
(1.5 KB)
📄
criu-plugin.h.tar
(6 KB)
📄
criu.h.h.tar.gz
(2.72 KB)
📄
criu.h.tar
(11 KB)
📄
criu.pc.pc.tar.gz
(243 B)
📄
criu.pc.tar
(2 KB)
📄
criu.service.service.tar.gz
(284 B)
📄
criu.service.tar
(2 KB)
📄
criu.socket.socket.tar.gz
(232 B)
📄
criu.socket.tar
(3 KB)
📄
criu.tar
(25.5 KB)
📄
criu.tar.gz
(5.87 KB)
📄
criu.zip
(21.17 KB)
📄
crnv21.bin.bin.tar.gz
(2.24 KB)
📄
crnv21.bin.tar
(11 KB)
📄
crnv32.bin.bin.tar.gz
(2.53 KB)
📄
crnv32.bin.tar
(13 KB)
📄
crnv32u.bin.bin.tar.gz
(2.54 KB)
📄
crnv32u.bin.tar
(7 KB)
📄
cron.daily.tar
(2 KB)
📄
cron.daily.tar.gz
(187 B)
📄
cron.daily.zip
(294 B)
📄
cron.php.php.tar.gz
(1.72 KB)
📄
cron.php.tar
(8.5 KB)
📄
cron.sh.sh.tar.gz
(451 B)
📄
cron.sh.tar
(2.5 KB)
📄
cron.tar
(5 KB)
📄
cron.tar.gz
(1.59 KB)
📄
cron.zip
(3.58 KB)
📄
crond.service.service.tar.gz
(349 B)
📄
crond.service.tar
(3 KB)
📄
crontab.cagefs.cagefs.tar.gz
(23.58 KB)
📄
crontab.cagefs.tar
(56 KB)
📄
crontab.tar
(3 KB)
📄
crontab.tar.gz
(745 B)
📄
croogo.tar
(224 KB)
📄
croogo.tar.gz
(120.79 KB)
📄
croogo.zip
(198.79 KB)
📄
crt1.o.o.tar.gz
(2.1 KB)
📄
crt1.o.tar
(16 KB)
📄
crtbeginS.o.o.tar.gz
(1.07 KB)
📄
crtbeginS.o.tar
(5 KB)
📄
crtbeginT.o.o.tar.gz
(1.15 KB)
📄
crtbeginT.o.tar
(5 KB)
📄
crtend.o.o.tar.gz
(577 B)
📄
crtend.o.tar
(5.5 KB)
📄
crtendS.o.o.tar.gz
(577 B)
📄
crtendS.o.tar
(5.5 KB)
📄
crti.o.o.tar.gz
(566 B)
📄
crti.o.tar
(3.5 KB)
📄
crtn.o.o.tar.gz
(454 B)
📄
crtn.o.tar
(3 KB)
📄
crtoffloadend.o.o.tar.gz
(561 B)
📄
crtoffloadend.o.tar
(3.5 KB)
📄
crtprec32.o.o.tar.gz
(1.29 KB)
📄
crtprec32.o.tar
(6 KB)
📄
crtprec64.o.o.tar.gz
(1.31 KB)
📄
crtprec64.o.tar
(6 KB)
📄
crtprec80.o.o.tar.gz
(1.29 KB)
📄
crtprec80.o.tar
(6 KB)
📄
crypt.h.h.tar.gz
(3.11 KB)
📄
crypt.h.tar
(10.5 KB)
📄
crypt.py.py.tar.gz
(952 B)
📄
crypt.py.tar
(11 KB)
📄
crypt.pyc.pyc.tar.gz
(1.52 KB)
📄
crypt.pyc.tar
(4.5 KB)
📄
crypt.pyo.pyo.tar.gz
(1.52 KB)
📄
crypt.pyo.tar
(4.5 KB)
📄
crypto.h.h.tar.gz
(4.7 KB)
📄
crypto.h.tar
(18.5 KB)
📄
crypto.lst.lst.tar.gz
(457 B)
📄
crypto.lst.tar
(4 KB)
📄
crypto.mod.mod.tar.gz
(2.88 KB)
📄
crypto.mod.tar
(15 KB)
📄
crypto.tar
(4 KB)
📄
crypto.tar.gz
(225 B)
📄
crypto.zip
(511 B)
📄
cryptodisk.mod.mod.tar.gz
(6.06 KB)
📄
cryptodisk.mod.tar
(15.5 KB)
📄
cryptoerr.h.h.tar.gz
(847 B)
📄
cryptoerr.h.tar
(4 KB)
📄
cryptsetup.conf.conf.tar.gz
(136 B)
📄
cryptsetup.conf.tar
(3 KB)
📄
cryptsetup.target.tar
(2 KB)
📄
cryptsetup.target.target.tar.gz
(375 B)
📄
cs.tar
(31.5 KB)
📄
cs.tar.gz
(22.68 KB)
📄
cs.zip
(24.01 KB)
📄
cs35l41-dsp1-spk-prot-1025182c.wmfw.tar
(35 KB)
📄
cs35l41-dsp1-spk-prot-1025182c.wmfw.wmfw.tar.gz
(18.52 KB)
📄
cs35l41-dsp1-spk-prot-103c8a2e-spkid1-r0.bin.bin.tar.gz
(2.27 KB)
📄
cs35l41-dsp1-spk-prot-103c8a2e-spkid1-r0.bin.tar
(5.5 KB)
📄
cs35l41-dsp1-spk-prot-103c8bb4-spkid0-l0.bincfg.bincfg.tar.gz
(162 B)
📄
cs35l41-dsp1-spk-prot-103c8bb4-spkid0-l0.bincfg.tar
(2 KB)
📄
cs35l41-dsp1-spk-prot-103c8bdd-spkid0-r0.bin.bin.tar.gz
(2.68 KB)
📄
cs35l41-dsp1-spk-prot-103c8bdd-spkid0-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-103c8be1.wmfw.tar
(35 KB)
📄
cs35l41-dsp1-spk-prot-103c8be1.wmfw.wmfw.tar.gz
(18.48 KB)
📄
cs35l41-dsp1-spk-prot-103c8be8.wmfw.tar
(35 KB)
📄
cs35l41-dsp1-spk-prot-103c8be8.wmfw.wmfw.tar.gz
(18.49 KB)
📄
cs35l41-dsp1-spk-prot-103c8c46.bin.bin.tar.gz
(2.73 KB)
📄
cs35l41-dsp1-spk-prot-103c8c46.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-104312af-spkid0-r0.bin.bin.tar.gz
(2.79 KB)
📄
cs35l41-dsp1-spk-prot-104312af-spkid0-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-10431454-spkid1-r0.bin.bin.tar.gz
(2.96 KB)
📄
cs35l41-dsp1-spk-prot-10431454-spkid1-r0.bin.tar
(7 KB)
📄
cs35l41-dsp1-spk-prot-10431463-spkid1-r0.bin.bin.tar.gz
(2.61 KB)
📄
cs35l41-dsp1-spk-prot-10431463-spkid1-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-10431483-r0.bin.bin.tar.gz
(2.64 KB)
📄
cs35l41-dsp1-spk-prot-10431483-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-104314e3-spkid1-r0.bin.bin.tar.gz
(2.66 KB)
📄
cs35l41-dsp1-spk-prot-104314e3-spkid1-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-104316d3-spkid1-l0.bin.bin.tar.gz
(2.71 KB)
📄
cs35l41-dsp1-spk-prot-104316d3-spkid1-l0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-104316d3-spkid1-r0.bin.bin.tar.gz
(2.73 KB)
📄
cs35l41-dsp1-spk-prot-104316d3-spkid1-r0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-10431fb3-r0.bin.bin.tar.gz
(2.49 KB)
📄
cs35l41-dsp1-spk-prot-10431fb3-r0.bin.tar
(6 KB)
📄
cs35l41-dsp1-spk-prot-10433061-spkid0-r0.bin.bin.tar.gz
(2.91 KB)
📄
cs35l41-dsp1-spk-prot-10433061-spkid0-r0.bin.tar
(7 KB)
📄
cs35l41-dsp1-spk-prot-10433ff0-spkid0-l0.bin.bin.tar.gz
(2.75 KB)
📄
cs35l41-dsp1-spk-prot-10433ff0-spkid0-l0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-17aa2319-l0.bin.bin.tar.gz
(2.82 KB)
📄
cs35l41-dsp1-spk-prot-17aa2319-l0.bin.tar
(6.5 KB)
📄
cs35l41-dsp1-spk-prot-17aa38a9.wmfw.tar
(35 KB)
📄
cs35l41-dsp1-spk-prot-17aa38a9.wmfw.wmfw.tar.gz
(18.49 KB)
📄
cs35l41-dsp1-spk-prot-vlv1776.wmfw.tar
(35 KB)
📄
cs35l41-dsp1-spk-prot-vlv1776.wmfw.wmfw.tar.gz
(18.28 KB)
📄
cs35l41-dsp1-spk-prot.bin.bin.tar.gz
(624 B)
📄
cs35l41-dsp1-spk-prot.bin.tar
(2.5 KB)
📄
cs35l41.tar
(340.5 KB)
📄
cs35l41.tar.gz
(179.15 KB)
📄
cs35l41.zip
(331.96 KB)
📄
cs35l54-b0-dsp1-misc-103c8d85-amp2.bin.bin.tar.gz
(3.52 KB)
📄
cs35l54-b0-dsp1-misc-103c8d85-amp2.bin.tar
(9 KB)
📄
cs35l56-b0-dsp1-misc-10280c62-spkid1.wmfw.tar
(31.5 KB)
📄
cs35l56-b0-dsp1-misc-10280c62-spkid1.wmfw.wmfw.tar.gz
(15.43 KB)
📄
cs35l56-b0-dsp1-misc-10280d13-spkid1-amp2.bin.bin.tar.gz
(4.97 KB)
📄
cs35l56-b0-dsp1-misc-10280d13-spkid1-amp2.bin.tar
(13 KB)
📄
cs35l56-b0-dsp1-misc-10280d32-spkid0-amp2.bin.bin.tar.gz
(4.98 KB)
📄
cs35l56-b0-dsp1-misc-10280d32-spkid0-amp2.bin.tar
(13 KB)
📄
cs35l56-b0-dsp1-misc-103c8c53-amp2.bin.bin.tar.gz
(3.88 KB)
📄
cs35l56-b0-dsp1-misc-103c8c53-amp2.bin.tar
(9.5 KB)
📄
cs35l56-b0-dsp1-misc-10431264-amp4.bin.bin.tar.gz
(3.95 KB)
📄
cs35l56-b0-dsp1-misc-10431264-amp4.bin.tar
(10 KB)
📄
cs35l56-b0-dsp1-misc-17aa3838-spkid0-ampl.bin.bin.tar.gz
(3.17 KB)
📄
cs35l56-b0-dsp1-misc-17aa3838-spkid0-ampl.bin.tar
(8.5 KB)
📄
cs35l56-b0-dsp1-misc-17aa3910-spkid1-amp1.bin.bin.tar.gz
(3.19 KB)
📄
cs35l56-b0-dsp1-misc-17aa3910-spkid1-amp1.bin.tar
(8.5 KB)
📄
cs35l56-b0-dsp1-misc-17aa392c-spkid1-amp1.bin.bin.tar.gz
(3.89 KB)
📄
cs35l56-b0-dsp1-misc-17aa392c-spkid1-amp1.bin.tar
(10 KB)
📄
cs35l56-b0-dsp1-misc-17aa3932-amp3.bin.bin.tar.gz
(4.06 KB)
📄
cs35l56-b0-dsp1-misc-17aa3932-amp3.bin.tar
(11 KB)
📄
cs35l56.tar
(408.5 KB)
📄
cs35l56.tar.gz
(193.95 KB)
📄
cs35l56.zip
(399.76 KB)
📄
cs42l43.bin.bin.tar.gz
(574 B)
📄
cs42l43.bin.tar
(4 KB)
📄
cs5536.mod.mod.tar.gz
(2.32 KB)
📄
cs5536.mod.tar
(12 KB)
📄
cscart.sql.sql.tar.gz
(569.07 KB)
📄
cscart.sql.tar
(3.02 MB)
📄
cscart.tar
(102.21 MB)
📄
cscart.tar.gz
(95.35 MB)
📄
cscart.zip
(102.19 MB)
📄
csf.service.service.tar.gz
(285 B)
📄
csf.service.tar
(3 KB)
📄
csplit.tar
(55.5 KB)
📄
csplit.tar.gz
(24.08 KB)
📄
csrf_secret.php.php.tar.gz
(142 B)
📄
csrf_secret.php.tar
(2 KB)
📄
csrs.tar
(5 KB)
📄
csrs.tar.gz
(1.74 KB)
📄
csrs.zip
(2.74 KB)
📄
css.tar
(2.09 MB)
📄
css.tar.gz
(23.02 KB)
📄
css.zip
(2.05 MB)
📄
csv.py.py.tar.gz
(4.72 KB)
📄
csv.py.tar
(51 KB)
📄
csv.pyc.pyc.tar.gz
(5.76 KB)
📄
csv.pyc.tar
(15 KB)
📄
csv.pyo.pyo.tar.gz
(5.76 KB)
📄
csv.pyo.tar
(15 KB)
📄
cszcms.sql.sql.tar.gz
(8.54 KB)
📄
cszcms.sql.tar
(47 KB)
📄
cszcms.tar
(7.5 MB)
📄
cszcms.tar.gz
(7.06 MB)
📄
cszcms.zip
(7.48 MB)
📄
ct.h.h.tar.gz
(4.14 KB)
📄
ct.h.tar
(17 KB)
📄
ct2fw-3.2.5.1.bin.2.5.1.bin.tar.gz
(353.29 KB)
📄
ct2fw-3.2.5.1.bin.tar
(1.12 MB)
📄
ctdb.xml.tar
(2 KB)
📄
ctdb.xml.xml.tar.gz
(291 B)
📄
cterr.h.h.tar.gz
(1 KB)
📄
cterr.h.tar
(5 KB)
📄
ctfw-3.2.5.1.bin.2.5.1.bin.tar.gz
(323.12 KB)
📄
ctfw-3.2.5.1.bin.tar
(528.5 KB)
📄
ctrl-alt-del.tar
(2 KB)
📄
ctrl-alt-del.tar.gz
(113 B)
📄
ctrl-alt-del.target.tar
(2.5 KB)
📄
ctrl-alt-del.target.target.tar.gz
(468 B)
📄
ctype.h.h.tar.gz
(3.45 KB)
📄
ctype.h.tar
(12.5 KB)
📄
ctypes.tar
(460.5 KB)
📄
ctypes.tar.gz
(35.5 KB)
📄
ctypes.zip
(414.63 KB)
📄
ctz_test.mod.mod.tar.gz
(1009 B)
📄
ctz_test.mod.tar
(3.5 KB)
📄
cube.png.png.tar.gz
(27.03 KB)
📄
cube.png.tar
(28.5 KB)
📄
cube.sql.sql.tar.gz
(23.49 KB)
📄
cube.sql.tar
(122 KB)
📄
cube.tar
(16.35 MB)
📄
cube.tar.gz
(15.01 MB)
📄
cube.zip
(16.33 MB)
📄
cumulus.tar
(161 KB)
📄
cumulus.tar.gz
(86.32 KB)
📄
cumulus.zip
(138.56 KB)
📄
cur.tar
(4.66 MB)
📄
cur.tar.gz
(726.83 KB)
📄
cur.zip
(4.25 MB)
📄
curl.h.h.tar.gz
(29.17 KB)
📄
curl.h.tar
(104 KB)
📄
curl.tar
(722.5 KB)
📄
curl.tar.gz
(131.38 KB)
📄
curl.zip
(193.12 KB)
📄
curlssl11.tar
(1.96 MB)
📄
curlssl11.tar.gz
(776.98 KB)
📄
curlssl11.zip
(1.95 MB)
📄
curlver.h.h.tar.gz
(1.41 KB)
📄
curlver.h.tar
(4.5 KB)
📄
current.tar
(1.5 KB)
📄
current.tar.gz
(101 B)
📄
currpinf.h.h.tar.gz
(2.04 KB)
📄
currpinf.h.tar
(9 KB)
📄
currunit.h.h.tar.gz
(1.47 KB)
📄
currunit.h.tar
(5.5 KB)
📄
curses.h.h.tar.gz
(19.66 KB)
📄
curses.h.tar
(197 KB)
📄
curses.tar
(328 KB)
📄
curses.tar.gz
(15.13 KB)
📄
curses.zip
(287.08 KB)
📄
cursesapp.h.h.tar.gz
(2.34 KB)
📄
cursesapp.h.tar
(16 KB)
📄
cursesf.h.h.tar.gz
(6.45 KB)
📄
cursesf.h.tar
(57 KB)
📄
cursesm.h.h.tar.gz
(5.15 KB)
📄
cursesm.h.tar
(41 KB)
📄
cursesp.h.h.tar.gz
(3.08 KB)
📄
cursesp.h.tar
(28 KB)
📄
cursesw.h.h.tar.gz
(10.89 KB)
📄
cursesw.h.tar
(100 KB)
📄
cursorfont.h.h.tar.gz
(1.36 KB)
📄
cursorfont.h.tar
(5 KB)
📄
cursslk.h.h.tar.gz
(2.47 KB)
📄
cursslk.h.tar
(17 KB)
📄
curve_keygen.tar
(11 KB)
📄
curve_keygen.tar.gz
(3.76 KB)
📄
custom_fields.php.php.tar.gz
(3.19 KB)
📄
custom_fields.php.tar
(31 KB)
📄
cut.tar
(51.5 KB)
📄
cut.tar.gz
(22.55 KB)
📄
cv.h.h.tar.gz
(3.98 KB)
📄
cv.h.tar
(13.5 KB)
📄
cvelist.tar
(3.5 KB)
📄
cvelist.tar.gz
(436 B)
📄
cvsfiles.pyc.pyc.tar.gz
(1.21 KB)
📄
cvsfiles.pyc.tar
(4 KB)
📄
cvsfiles.pyo.pyo.tar.gz
(1.21 KB)
📄
cvsfiles.pyo.tar
(4 KB)
📄
cwp.tar
(7.5 KB)
📄
cwp.tar.gz
(1.96 KB)
📄
cwp.zip
(6.03 KB)
📄
cxgb4-abi.h.h.tar.gz
(1.47 KB)
📄
cxgb4-abi.h.tar
(5 KB)
📄
cxgb4.tar
(4.53 MB)
📄
cxgb4.tar.gz
(2.88 MB)
📄
cxgb4.zip
(4.52 MB)
📄
cxl.h.h.tar.gz
(1.5 KB)
📄
cxl.h.tar
(5.5 KB)
📄
cxlflash_ioctl.h.h.tar.gz
(2.82 KB)
📄
cxlflash_ioctl.h.tar
(11.5 KB)
📄
cxs.tar
(3 KB)
📄
cxs.tar.gz
(713 B)
📄
cxswatch.service.service.tar.gz
(258 B)
📄
cxswatch.service.tar
(2 KB)
📄
cyan_skillfish2_ce.bin.bin.tar.gz
(4.53 KB)
📄
cyan_skillfish2_ce.bin.tar
(259 KB)
📄
cyan_skillfish2_me.bin.bin.tar.gz
(9.28 KB)
📄
cyan_skillfish2_me.bin.tar
(259 KB)
📄
cyan_skillfish2_sdma1.bin.bin.tar.gz
(10.5 KB)
📄
cyan_skillfish2_sdma1.bin.tar
(34.5 KB)
📄
cybercafe.uni.tar
(7 KB)
📄
cybercafe.uni.uni.tar.gz
(1.08 KB)
📄
cyfmac43012-sdio.bin.bin.tar.gz
(291.16 KB)
📄
cyfmac43012-sdio.bin.tar
(481 KB)
📄
cyfmac43340-sdio.bin.bin.tar.gz
(267 KB)
📄
cyfmac43340-sdio.bin.tar
(402 KB)
📄
cyfmac43362-sdio.bin.bin.tar.gz
(126.76 KB)
📄
cyfmac43362-sdio.bin.tar
(199.5 KB)
📄
cyfmac43430-sdio.bin.bin.tar.gz
(275.91 KB)
📄
cyfmac43430-sdio.bin.tar
(411.5 KB)
📄
cyfmac43455-sdio.bin.bin.tar.gz
(416.99 KB)
📄
cyfmac43455-sdio.bin.tar
(630.5 KB)
📄
cyfmac4354-sdio.clm_blob.clm_blob.tar.gz
(2.24 KB)
📄
cyfmac4354-sdio.clm_blob.tar
(7.5 KB)
📄
cyfmac4356-pcie.clm_blob.clm_blob.tar.gz
(2.23 KB)
📄
cyfmac4356-pcie.clm_blob.tar
(7.5 KB)
📄
cyfmac4356-sdio.clm_blob.clm_blob.tar.gz
(2.23 KB)
📄
cyfmac4356-sdio.clm_blob.tar
(7.5 KB)
📄
cyfmac43570-pcie.bin.bin.tar.gz
(351.32 KB)
📄
cyfmac43570-pcie.bin.tar
(547 KB)
📄
cyfmac4373-sdio.clm_blob.clm_blob.tar.gz
(2.09 KB)
📄
cyfmac4373-sdio.clm_blob.tar
(6.5 KB)
📄
cyfmac54591-pcie.bin.bin.tar.gz
(395.86 KB)
📄
cyfmac54591-pcie.bin.tar
(603 KB)
📄
cypress.tar
(6.05 MB)
📄
cypress.tar.gz
(3.88 MB)
📄
cypress.zip
(6.03 MB)
📄
cyralt.uni.tar
(11 KB)
📄
cyralt.uni.uni.tar.gz
(1.78 KB)
📄
cyrillic_and_mic.so.so.tar.gz
(5.13 KB)
📄
cyrillic_and_mic.so.tar
(17.5 KB)
📄
cyrus-sasl.tar
(1.22 MB)
📄
cyrus-sasl.tar.gz
(280.23 KB)
📄
cyrus-sasl.zip
(1.17 MB)
📄
d101m_ucode.bin.bin.tar.gz
(419 B)
📄
d101m_ucode.bin.tar
(2.5 KB)
📄
d101s_ucode.bin.bin.tar.gz
(436 B)
📄
d101s_ucode.bin.tar
(2.5 KB)
📄
d102e_ucode.bin.bin.tar.gz
(226 B)
📄
d102e_ucode.bin.tar
(2.5 KB)
📄
d11763e7ed17def045f3f50ea3e7bfeb8833a1.tar
(29.5 KB)
📄
d11763e7ed17def045f3f50ea3e7bfeb8833a1.tar.gz
(11.35 KB)
📄
d2027e18292e4043b2d32c0f0d931a3d8047ef.tar
(23 KB)
📄
d2027e18292e4043b2d32c0f0d931a3d8047ef.tar.gz
(8.6 KB)
📄
d31d2a225f5aca64e636fc41f5b10fa20e1791.tar
(26.5 KB)
📄
d31d2a225f5aca64e636fc41f5b10fa20e1791.tar.gz
(10.09 KB)
📄
d33b62a705180ec35e6292463e656bb3e11510.tar
(13.5 KB)
📄
d33b62a705180ec35e6292463e656bb3e11510.tar.gz
(5.73 KB)
📄
d368f547e83a8e369d02f39d0a1fbecdd9ddf0.tar
(13 KB)
📄
d368f547e83a8e369d02f39d0a1fbecdd9ddf0.tar.gz
(4.83 KB)
📄
d38294f0e280fa0c38f85a348deac5417b66cc.tar
(17.5 KB)
📄
d38294f0e280fa0c38f85a348deac5417b66cc.tar.gz
(5.92 KB)
📄
d38f190f5a7a78f8a4a6b0a703c60b98ec34d5.tar
(175.5 KB)
📄
d38f190f5a7a78f8a4a6b0a703c60b98ec34d5.tar.gz
(61.76 KB)
📄
d4ae7b0e79e1c6187ca7b018d91bbd161fcb59.tar
(9 KB)
📄
d4ae7b0e79e1c6187ca7b018d91bbd161fcb59.tar.gz
(2.71 KB)
📄
d6128f39f0b344da6eb25722f796ac3a191665.tar
(13.5 KB)
📄
d6128f39f0b344da6eb25722f796ac3a191665.tar.gz
(4.04 KB)
📄
d9b148216dd39148.css.css.tar.gz
(11 KB)
📄
d9b148216dd39148.css.tar
(95.5 KB)
📄
d9eb2f1e6d91d8f5aeba8591b5a551b56a1f3f.tar
(13.5 KB)
📄
d9eb2f1e6d91d8f5aeba8591b5a551b56a1f3f.tar.gz
(4.82 KB)
📄
da.tar
(55 KB)
📄
da.tar.gz
(40.44 KB)
📄
da.zip
(42.24 KB)
📄
da368b10fdbab3ebc44803869bc07fad058adc.tar
(13.5 KB)
📄
da368b10fdbab3ebc44803869bc07fad058adc.tar.gz
(3.65 KB)
📄
da39a3ee5e6b4b0d3255bfef95601890afd80709.ico.ico.tar.gz
(141 B)
📄
da39a3ee5e6b4b0d3255bfef95601890afd80709.ico.tar
(1.5 KB)
📄
da7219-tplg.bin.bin.tar.gz
(771 B)
📄
da7219-tplg.bin.tar
(6 KB)
📄
dabusb.tar
(24 KB)
📄
dabusb.tar.gz
(13.12 KB)
📄
dabusb.zip
(21.64 KB)
📄
dad_transmits.tar
(3 KB)
📄
dad_transmits.tar.gz
(122 B)
📄
dada.png.png.tar.gz
(7.28 KB)
📄
dada.png.tar
(9.5 KB)
📄
damage.h.h.tar.gz
(1.74 KB)
📄
damage.h.tar
(11 KB)
📄
data.php.php.tar.gz
(283 B)
📄
data.php.tar
(2 KB)
📄
database.inc.inc.tar.gz
(234 B)
📄
database.inc.php.inc.php.tar.gz
(296 B)
📄
database.inc.php.tar
(2 KB)
📄
database.inc.tar
(2 KB)
📄
database.ini.ini.tar.gz
(195 B)
📄
database.ini.tar
(2 KB)
📄
database.js.js.tar.gz
(1.14 KB)
📄
database.js.tar
(5 KB)
📄
database.php.php.tar.gz
(228 B)
📄
database.php.tar
(36 KB)
📄
database.xml.tar
(3.5 KB)
📄
database.xml.xml.tar.gz
(796 B)
📄
databases.yml.tar
(2 KB)
📄
databases.yml.yml.tar.gz
(289 B)
📄
dataclasses.py.py.tar.gz
(13.36 KB)
📄
dataclasses.py.tar
(50.5 KB)
📄
date.mod.mod.tar.gz
(1.33 KB)
📄
date.mod.tar
(4 KB)
📄
date.rb.rb.tar.gz
(534 B)
📄
date.rb.tar
(7 KB)
📄
date.tar
(108.5 KB)
📄
date.tar.gz
(50.27 KB)
📄
date.zip
(203 B)
📄
date_core.so.so.tar.gz
(89.56 KB)
📄
date_core.so.tar
(209 KB)
📄
datehook.mod.mod.tar.gz
(928 B)
📄
datehook.mod.tar
(3.5 KB)
📄
datetime.mod.mod.tar.gz
(1.03 KB)
📄
datetime.mod.tar
(4 KB)
📄
datetime.py.py.tar.gz
(20.63 KB)
📄
datetime.py.tar
(169 KB)
📄
dav1d.tar
(895 KB)
📄
dav1d.tar.gz
(406.09 KB)
📄
dav1d.zip
(892 KB)
📄
db-config.php.php.tar.gz
(1011 B)
📄
db-config.php.tar
(3.5 KB)
📄
db.h.h.tar.gz
(29.54 KB)
📄
db.h.tar
(243 KB)
📄
db.ini.ini.tar.gz
(407 B)
📄
db.ini.tar
(2.5 KB)
📄
db.php.php.tar.gz
(261 B)
📄
db.php.tar
(4.5 KB)
📄
db.py.py.tar.gz
(1.32 KB)
📄
db.py.tar
(4.5 KB)
📄
db.pyc.pyc.tar.gz
(428 B)
📄
db.pyc.tar
(2.5 KB)
📄
db.pyo.pyo.tar.gz
(426 B)
📄
db.pyo.tar
(2.5 KB)
📄
db2pickle.py.py.tar.gz
(1.08 KB)
📄
db2pickle.py.tar
(5 KB)
📄
db2pickle.pyo.pyo.tar.gz
(1.64 KB)
📄
db2pickle.pyo.tar
(5 KB)
📄
db3.tar
(16.5 KB)
📄
db3.tar.gz
(7.51 KB)
📄
db3.zip
(11.21 KB)
📄
db9.tar
(16.5 KB)
📄
db9.tar.gz
(7.51 KB)
📄
db9.zip
(11.21 KB)
📄
db_185.h.h.tar.gz
(2.41 KB)
📄
db_185.h.tar
(14 KB)
📄
db_governor.service.service.tar.gz
(439 B)
📄
db_governor.service.tar
(2.5 KB)
📄
db_login.php.php.tar.gz
(1.72 KB)
📄
db_login.php.tar
(7 KB)
📄
dbapi2.py.py.tar.gz
(1.18 KB)
📄
dbapi2.py.tar
(11.5 KB)
📄
dbapi2.pyc.pyc.tar.gz
(1.18 KB)
📄
dbapi2.pyc.tar
(4.5 KB)
📄
dbapi2.pyo.pyo.tar.gz
(1.18 KB)
📄
dbapi2.pyo.tar
(4.5 KB)
📄
dbconnect.php.php.tar.gz
(607 B)
📄
dbconnect.php.tar
(3.5 KB)
📄
dbhash.py.py.tar.gz
(403 B)
📄
dbhash.py.tar
(2 KB)
📄
dbhash.pyc.pyc.tar.gz
(545 B)
📄
dbhash.pyc.tar
(2.5 KB)
📄
dbhash.pyo.pyo.tar.gz
(545 B)
📄
dbhash.pyo.tar
(2.5 KB)
📄
dbm.h.h.tar.gz
(805 B)
📄
dbm.h.tar
(5 KB)
📄
dbm.so.so.tar.gz
(10.32 KB)
📄
dbm.so.tar
(25.5 KB)
📄
dbm.tar
(109.5 KB)
📄
dbm.tar.gz
(12.26 KB)
📄
dbm.zip
(89.46 KB)
📄
dbobj.py.py.tar.gz
(1.83 KB)
📄
dbobj.py.tar
(13 KB)
📄
dbobj.pyc.pyc.tar.gz
(2.73 KB)
📄
dbobj.pyc.tar
(20 KB)
📄
dbobj.pyo.pyo.tar.gz
(2.73 KB)
📄
dbobj.pyo.tar
(20 KB)
📄
dbrecio.pyc.pyc.tar.gz
(2.08 KB)
📄
dbrecio.pyc.tar
(7 KB)
📄
dbrecio.pyo.pyo.tar.gz
(2.08 KB)
📄
dbrecio.pyo.tar
(7 KB)
📄
dbshelve.py.py.tar.gz
(3.24 KB)
📄
dbshelve.py.tar
(13 KB)
📄
dbshelve.pyc.pyc.tar.gz
(4.1 KB)
📄
dbshelve.pyc.tar
(14.5 KB)
📄
dbshelve.pyo.pyo.tar.gz
(4.11 KB)
📄
dbshelve.pyo.tar
(14.5 KB)
📄
dbtables.py.py.tar.gz
(7 KB)
📄
dbtables.py.tar
(32 KB)
📄
dbtables.pyc.pyc.tar.gz
(8.86 KB)
📄
dbtables.pyc.tar
(25.5 KB)
📄
dbtables.pyo.pyo.tar.gz
(8.79 KB)
📄
dbtables.pyo.tar
(25.5 KB)
📄
dbus-org.freedesktop.portable1.service.tar
(2.5 KB)
📄
dbus.conf.conf.tar.gz
(185 B)
📄
dbus.conf.tar
(5 KB)
📄
dbus.service.service.tar.gz
(342 B)
📄
dbus.service.tar
(2 KB)
📄
dbus.socket.socket.tar.gz
(186 B)
📄
dbus.socket.tar
(3 KB)
📄
dbutils.pyc.pyc.tar.gz
(1.02 KB)
📄
dbutils.pyc.tar
(3.5 KB)
📄
dbutils.pyo.pyo.tar.gz
(1.02 KB)
📄
dbutils.pyo.tar
(3.5 KB)
📄
dc8fe8df6150e09d803c55797cffa917658b2c.tar
(9 KB)
📄
dc8fe8df6150e09d803c55797cffa917658b2c.tar.gz
(2.76 KB)
📄
dcfmtsym.h.h.tar.gz
(5.46 KB)
📄
dcfmtsym.h.tar
(22 KB)
📄
dcn_3_1_4_dmcub.bin.bin.tar.gz
(223.98 KB)
📄
dcn_3_1_4_dmcub.bin.tar
(344.5 KB)
📄
dcn_3_1_5_dmcub.bin.bin.tar.gz
(160.18 KB)
📄
dcn_3_1_5_dmcub.bin.tar
(238.5 KB)
📄
dcn_3_1_6_dmcub.bin.bin.tar.gz
(143.48 KB)
📄
dcn_3_1_6_dmcub.bin.tar
(212.5 KB)
📄
dcn_3_2_0_dmcub.bin.bin.tar.gz
(157.71 KB)
📄
dcn_3_2_0_dmcub.bin.tar
(279.5 KB)
📄
dcn_3_2_1_dmcub.bin.bin.tar.gz
(141.71 KB)
📄
dcn_3_2_1_dmcub.bin.tar
(229 KB)
📄
dcn_3_5_1_dmcub.bin.bin.tar.gz
(299.5 KB)
📄
dcn_3_5_1_dmcub.bin.tar
(482.5 KB)
📄
dcn_4_0_1_dmcub.bin.bin.tar.gz
(231.43 KB)
📄
dcn_4_0_1_dmcub.bin.tar
(361 KB)
📄
dd.tar
(79.5 KB)
📄
dd.tar.gz
(37.45 KB)
📄
ddns-confgen.tar
(22 KB)
📄
ddns-confgen.tar.gz
(8.83 KB)
📄
ddp-comms.tar
(1.37 MB)
📄
ddp-comms.tar.gz
(110.05 KB)
📄
ddp-comms.zip
(1.37 MB)
📄
ddp-lag.tar
(678.5 KB)
📄
ddp-lag.tar.gz
(50.43 KB)
📄
ddp-lag.zip
(676.71 KB)
📄
ddp.tar
(1.29 MB)
📄
ddp.tar.gz
(97.02 KB)
📄
ddp.zip
(1.29 MB)
📄
de.tar
(252 KB)
📄
de.tar.gz
(202.32 KB)
📄
de.zip
(209.89 KB)
📄
de079de4ac8df1d6cd55375f1b6efbaee1e818.tar
(35 KB)
📄
de079de4ac8df1d6cd55375f1b6efbaee1e818.tar.gz
(14.92 KB)
📄
de61259d261fd55c.css.css.tar.gz
(5.96 KB)
📄
de61259d261fd55c.css.tar
(46 KB)
📄
debug-shell.service.service.tar.gz
(778 B)
📄
debug-shell.service.tar
(3 KB)
📄
debug.h.h.tar.gz
(545 B)
📄
debug.h.tar
(5 KB)
📄
debug.la.la.tar.gz
(680 B)
📄
debug.la.tar
(3 KB)
📄
debug.php.php.tar.gz
(2.9 KB)
📄
debug.php.tar
(9.5 KB)
📄
debug.tar
(6.5 KB)
📄
debug.tar.gz
(142 B)
📄
debug.zip
(950 B)
📄
debugreg.h.h.tar.gz
(1.56 KB)
📄
debugreg.h.tar
(9 KB)
📄
decimal.h.h.tar.gz
(1.66 KB)
📄
decimal.h.tar
(6.5 KB)
📄
decimal.py.py.tar.gz
(193 B)
📄
decimal.py.tar
(220.5 KB)
📄
decimal.pyc.pyc.tar.gz
(47.71 KB)
📄
decimal.pyc.tar
(170 KB)
📄
decimal.pyo.pyo.tar.gz
(47.71 KB)
📄
decimal.pyo.tar
(170 KB)
📄
decimfmt.h.h.tar.gz
(18.67 KB)
📄
decimfmt.h.tar
(89.5 KB)
📄
decoder.cpython-38.opt-2.pyc.cpython-38.opt-2.pyc.tar.gz
(3.25 KB)
📄
decoder.cpython-38.opt-2.pyc.tar
(7.5 KB)
📄
decoder.py.py.tar.gz
(3.61 KB)
📄
decoder.py.tar
(41 KB)
📄
def.uni.tar
(7 KB)
📄
def.uni.uni.tar.gz
(902 B)
📄
def_reserved_size.tar
(2 KB)
📄
def_reserved_size.tar.gz
(119 B)
📄
default.json.json.tar.gz
(531 B)
📄
default.json.tar
(3.5 KB)
📄
default.tar
(264 KB)
📄
default.tar.gz
(433 B)
📄
default.target.tar
(2.5 KB)
📄
default.target.target.tar.gz
(455 B)
📄
default.zip
(169.66 KB)
📄
default_php_ini.tar
(28.5 KB)
📄
default_php_ini.tar.gz
(1.38 KB)
📄
default_php_ini.zip
(19.73 KB)
📄
default_qdisc.tar
(2 KB)
📄
default_qdisc.tar.gz
(121 B)
📄
dell.tar
(836 KB)
📄
dell.tar.gz
(364.73 KB)
📄
dell.zip
(834.7 KB)
📄
delta.h.h.tar.gz
(986 B)
📄
delta.h.tar
(3.5 KB)
📄
delv.tar
(44 KB)
📄
delv.tar.gz
(17.92 KB)
📄
demo.c.c.tar.gz
(1.07 KB)
📄
demo.c.tar
(4 KB)
📄
dentry-state.tar
(2 KB)
📄
dentry-state.tar.gz
(131 B)
📄
dep-update.tar
(2 KB)
📄
dep-update.tar.gz
(295 B)
📄
deprecated.go.go.tar.gz
(17.87 KB)
📄
deprecated.go.tar
(50.5 KB)
📄
deps.tar
(2.38 MB)
📄
deps.tar.gz
(2.35 MB)
📄
deps.zip
(2.38 MB)
📄
des.h.h.tar.gz
(1.91 KB)
📄
des.h.tar
(9 KB)
📄
desktop.tar
(2 KB)
📄
desktop.tar.gz
(203 B)
📄
desktop.zip
(290 B)
📄
details.so.so.tar.gz
(6.75 KB)
📄
details.so.tar
(17.5 KB)
📄
detectcp.py.py.tar.gz
(387 B)
📄
detectcp.py.tar
(2.5 KB)
📄
dev-hugepages.mount.mount.tar.gz
(566 B)
📄
dev-hugepages.mount.tar
(2.5 KB)
📄
dev-mqueue.mount.mount.tar.gz
(538 B)
📄
dev-mqueue.mount.tar
(4 KB)
📄
dev.tar
(30.5 KB)
📄
dev.tar.gz
(347 B)
📄
dev.zip
(2.37 KB)
📄
dev_weight.tar
(2 KB)
📄
dev_weight.tar.gz
(113 B)
📄
dev_weight_rx_bias.tar
(2 KB)
📄
dev_weight_rx_bias.tar.gz
(120 B)
📄
dev_weight_tx_bias.tar
(2 KB)
📄
dev_weight_tx_bias.tar.gz
(121 B)
📄
device_hdr.tar
(2 KB)
📄
device_hdr.tar.gz
(144 B)
📄
device_info.tar
(6.5 KB)
📄
device_info.tar.gz
(1.85 KB)
📄
device_strs.tar
(2 KB)
📄
device_strs.tar.gz
(145 B)
📄
devices.tar
(7.5 KB)
📄
devices.tar.gz
(128 B)
📄
df.tar
(93 KB)
📄
df.tar.gz
(44.79 KB)
📄
dg1_guc_49.0.1.bin.0.1.bin.tar.gz
(120.82 KB)
📄
dg1_guc_49.0.1.bin.tar
(612 KB)
📄
dg1_guc_62.0.0.bin.0.0.bin.tar.gz
(125.31 KB)
📄
dg1_guc_62.0.0.bin.tar
(310 KB)
📄
dg1_guc_69.0.3.bin.0.3.bin.tar.gz
(135.25 KB)
📄
dg1_guc_69.0.3.bin.tar
(318 KB)
📄
dg1_guc_70.1.1.bin.1.1.bin.tar.gz
(104.67 KB)
📄
dg1_guc_70.1.1.bin.tar
(260.5 KB)
📄
dg1_guc_70.bin.bin.tar.gz
(130.88 KB)
📄
dg1_guc_70.bin.tar
(315.5 KB)
📄
dg1_huc.bin.bin.tar.gz
(198.44 KB)
📄
dg1_huc.bin.tar
(578 KB)
📄
dg2_dmc_ver2_06.bin.bin.tar.gz
(6.18 KB)
📄
dg2_dmc_ver2_06.bin.tar
(23.5 KB)
📄
dg2_guc_70.1.2.bin.1.2.bin.tar.gz
(148.95 KB)
📄
dg2_guc_70.1.2.bin.tar
(358.5 KB)
📄
dg2_guc_70.4.1.bin.4.1.bin.tar.gz
(154.54 KB)
📄
dg2_guc_70.4.1.bin.tar
(362.5 KB)
📄
dg2_guc_70.bin.bin.tar.gz
(175.52 KB)
📄
dg2_guc_70.bin.tar
(374.5 KB)
📄
dg2_huc_gsc.bin.bin.tar.gz
(219.03 KB)
📄
dg2_huc_gsc.bin.tar
(617.5 KB)
📄
dh.h.h.tar.gz
(4.5 KB)
📄
dh.h.tar
(32 KB)
📄
dhcp.xml.tar
(2 KB)
📄
dhcp.xml.xml.tar.gz
(268 B)
📄
dhcpv6.xml.tar
(2 KB)
📄
dhcpv6.xml.xml.tar.gz
(271 B)
📄
dherr.h.h.tar.gz
(1.16 KB)
📄
dherr.h.tar
(6 KB)
📄
dhtmlx.tar
(1.71 MB)
📄
dhtmlx.tar.gz
(1.62 MB)
📄
dhtmlx.zip
(1.7 MB)
📄
di.xml.tar
(648 KB)
📄
di.xml.xml.tar.gz
(12.91 KB)
📄
dialog.py.py.tar.gz
(698 B)
📄
dialog.py.tar
(3 KB)
📄
dialog.so.so.tar.gz
(3.9 KB)
📄
dialog.so.tar
(12.5 KB)
📄
dict_snowball.so.so.tar.gz
(85.2 KB)
📄
dict_snowball.so.tar
(330.5 KB)
📄
dictobject.h.h.tar.gz
(1.16 KB)
📄
dictobject.h.tar
(5.5 KB)
📄
diff.tar
(270 KB)
📄
diff.tar.gz
(78.71 KB)
📄
diff3.tar
(130.5 KB)
📄
diff3.tar.gz
(33.56 KB)
📄
difflib.py.py.tar.gz
(22.69 KB)
📄
difflib.py.tar
(248 KB)
📄
difflib.pyc.pyc.tar.gz
(21.6 KB)
📄
difflib.pyc.tar
(62 KB)
📄
difflib.pyo.pyo.tar.gz
(21.57 KB)
📄
difflib.pyo.tar
(62 KB)
📄
diffuse.tar
(2 KB)
📄
diffuse.tar.gz
(288 B)
📄
dig.tar
(164 KB)
📄
dig.tar.gz
(71.07 KB)
📄
digest.so.so.tar.gz
(7.27 KB)
📄
digest.so.tar
(21.5 KB)
📄
digest.tar
(49.5 KB)
📄
digest.tar.gz
(10.96 KB)
📄
digest.zip
(46.19 KB)
📄
dimgrey_cavefish_mec2.bin.bin.tar.gz
(41.68 KB)
📄
dimgrey_cavefish_mec2.bin.tar
(263.5 KB)
📄
dimgrey_cavefish_sdma.bin.bin.tar.gz
(12.23 KB)
📄
dimgrey_cavefish_sdma.bin.tar
(35 KB)
📄
dir-notify-enable.tar
(2 KB)
📄
dir-notify-enable.tar.gz
(114 B)
📄
dir.h.h.tar.gz
(606 B)
📄
dir.h.tar
(2.5 KB)
📄
dir.tar
(141.5 KB)
📄
dir.tar.gz
(65.84 KB)
📄
dircache.py.py.tar.gz
(635 B)
📄
dircache.py.tar
(3 KB)
📄
dircache.pyc.pyc.tar.gz
(928 B)
📄
dircache.pyc.tar
(3.5 KB)
📄
dircache.pyo.pyo.tar.gz
(927 B)
📄
dircache.pyo.tar
(3.5 KB)
📄
dircolors.tar
(51.5 KB)
📄
dircolors.tar.gz
(21.28 KB)
📄
directadmin.tar
(47.5 KB)
📄
directadmin.tar.gz
(15.51 KB)
📄
directadmin.zip
(45.27 KB)
📄
directus.tar
(227 KB)
📄
directus.tar.gz
(136.76 KB)
📄
directus.zip
(203.16 KB)
📄
dirent.h.h.tar.gz
(3.5 KB)
📄
dirent.h.tar
(16.5 KB)
📄
dirname.tar
(35 KB)
📄
dirname.tar.gz
(15.24 KB)
📄
dirty_background_bytes.tar
(2 KB)
📄
dirty_background_bytes.tar.gz
(119 B)
📄
dirty_background_ratio.tar
(2 KB)
📄
dirty_background_ratio.tar.gz
(119 B)
📄
dirty_bytes.tar
(2 KB)
📄
dirty_bytes.tar.gz
(108 B)
📄
dirty_expire_centisecs.tar
(2 KB)
📄
dirty_expire_centisecs.tar.gz
(121 B)
📄
dirty_ratio.tar
(2 KB)
📄
dirty_ratio.tar.gz
(108 B)
📄
dirtytime_expire_seconds.tar
(2 KB)
📄
dirtytime_expire_seconds.tar.gz
(123 B)
📄
dis.py.py.tar.gz
(5.62 KB)
📄
dis.py.tar
(47.5 KB)
📄
dis.pyc.pyc.tar.gz
(3.02 KB)
📄
dis.pyc.tar
(8 KB)
📄
dis.pyo.pyo.tar.gz
(3.02 KB)
📄
dis.pyo.tar
(8 KB)
📄
disable_ipv6.tar
(2 KB)
📄
disable_ipv6.tar.gz
(122 B)
📄
disable_policy.tar
(7 KB)
📄
disable_policy.tar.gz
(125 B)
📄
disable_xfrm.tar
(2 KB)
📄
disable_xfrm.tar.gz
(123 B)
📄
disabled.tar
(2 KB)
📄
disabled.tar.gz
(123 B)
📄
disk.mod.mod.tar.gz
(1.79 KB)
📄
disk.mod.tar
(5 KB)
📄
diskboot.img.img.tar.gz
(428 B)
📄
diskboot.img.tar
(2 KB)
📄
diskfilter.mod.mod.tar.gz
(6.63 KB)
📄
diskfilter.mod.tar
(17 KB)
📄
disks.so.so.tar.gz
(4.54 KB)
📄
disks.so.tar
(13 KB)
📄
display.tar
(19.76 MB)
📄
display.tar.gz
(3.66 KB)
📄
dist-alsa.conf.conf.tar.gz
(338 B)
📄
dist-alsa.conf.tar
(3 KB)
📄
dist-blacklist.conf.conf.tar.gz
(531 B)
📄
dist-blacklist.conf.tar
(2.5 KB)
📄
dist.sh.sh.tar.gz
(951 B)
📄
dist.sh.tar
(6 KB)
📄
distcc.xml.tar
(2 KB)
📄
distcc.xml.xml.tar.gz
(246 B)
📄
distro.tar
(2 KB)
📄
distro.tar.gz
(253 B)
📄
distutils.tar
(4.26 MB)
📄
distutils.tar.gz
(628.74 KB)
📄
distutils.zip
(4 MB)
📄
div.mod.mod.tar.gz
(685 B)
📄
div.mod.tar
(5 KB)
📄
div_test.mod.mod.tar.gz
(3.21 KB)
📄
div_test.mod.tar
(9 KB)
📄
dl.tar
(40 KB)
📄
dl.tar.gz
(7.28 KB)
📄
dl.zip
(33.89 KB)
📄
dlfcn.h.h.tar.gz
(2.74 KB)
📄
dlfcn.h.tar
(12 KB)
📄
dm_nv.mod.mod.tar.gz
(1.16 KB)
📄
dm_nv.mod.tar
(7 KB)
📄
dmesg_restrict.tar
(2 KB)
📄
dmesg_restrict.tar.gz
(115 B)
📄
dmic-tplg.bin.bin.tar.gz
(1.26 KB)
📄
dmic-tplg.bin.tar
(10.5 KB)
📄
dmz.xml.tar
(3 KB)
📄
dmz.xml.xml.tar.gz
(306 B)
📄
dnd.py.py.tar.gz
(3.5 KB)
📄
dnd.py.tar
(13 KB)
📄
dnf-makecache.timer.tar
(2 KB)
📄
dnf-makecache.timer.timer.tar.gz
(321 B)
📄
dnf-system-upgrade.service.service.tar.gz
(455 B)
📄
dnf-system-upgrade.service.tar
(2.5 KB)
📄
dnf.conf.conf.tar.gz
(205 B)
📄
dnf.conf.tar
(3 KB)
📄
dns-over-tls.xml.tar
(2 KB)
📄
dns-over-tls.xml.xml.tar.gz
(322 B)
📄
dns.h.h.tar.gz
(8.24 KB)
📄
dns.h.tar
(28 KB)
📄
dns.tar
(916 KB)
📄
dns.tar.gz
(188.96 KB)
📄
dns.xml.tar
(3 KB)
📄
dns.xml.xml.tar.gz
(316 B)
📄
dns.zip
(853.79 KB)
📄
dns_compat.h.h.tar.gz
(3.33 KB)
📄
dns_compat.h.tar
(13.5 KB)
📄
dns_struct.h.h.tar.gz
(1.35 KB)
📄
dns_struct.h.tar
(4.5 KB)
📄
dnssec-checkds.tar
(2.5 KB)
📄
dnssec-checkds.tar.gz
(570 B)
📄
dnssec-coverage.tar
(2.5 KB)
📄
dnssec-coverage.tar.gz
(573 B)
📄
dnssec-dsfromkey.tar
(62.5 KB)
📄
dnssec-dsfromkey.tar.gz
(25.75 KB)
📄
dnssec-importkey.tar
(62.5 KB)
📄
dnssec-importkey.tar.gz
(24.69 KB)
📄
dnssec-keyfromlabel.tar
(66.5 KB)
📄
dnssec-keyfromlabel.tar.gz
(27.09 KB)
📄
dnssec-keygen.tar
(74.5 KB)
📄
dnssec-keygen.tar.gz
(29.76 KB)
📄
dnssec-keymgr.tar
(2.5 KB)
📄
dnssec-keymgr.tar.gz
(571 B)
📄
dnssec-revoke.tar
(58.5 KB)
📄
dnssec-revoke.tar.gz
(23.11 KB)
📄
dnssec-settime.tar
(62.5 KB)
📄
dnssec-settime.tar.gz
(26.16 KB)
📄
dnssec-signzone.tar
(119 KB)
📄
dnssec-signzone.tar.gz
(50.75 KB)
📄
dnssec-verify.tar
(54.5 KB)
📄
dnssec-verify.tar.gz
(23.04 KB)
📄
dnstap-read.tar
(22 KB)
📄
dnstap-read.tar.gz
(7.1 KB)
📄
doc.sh.sh.tar.gz
(1.19 KB)
📄
doc.sh.tar
(6.5 KB)
📄
doc.tar
(205 KB)
📄
doc.tar.gz
(20.23 KB)
📄
doc.zip
(201.14 KB)
📄
docker-registry.xml.tar
(2 KB)
📄
docker-registry.xml.xml.tar.gz
(333 B)
📄
docker-swarm.xml.tar
(2 KB)
📄
docker-swarm.xml.xml.tar.gz
(317 B)
📄
docs-build.js.js.tar.gz
(512 B)
📄
docs-build.js.tar
(2.5 KB)
📄
docs.tar
(1.21 MB)
📄
docs.tar.gz
(204.73 KB)
📄
docs.zip
(1.17 MB)
📄
doctest.py.py.tar.gz
(26.36 KB)
📄
doctest.py.tar
(310 KB)
📄
doctest.pyc.pyc.tar.gz
(28 KB)
📄
doctest.pyc.tar
(83.5 KB)
📄
doctest.pyo.pyo.tar.gz
(27.85 KB)
📄
doctest.pyo.tar
(83 KB)
📄
documentation.go.go.tar.gz
(2.89 KB)
📄
documentation.go.tar
(7.5 KB)
📄
documentor.tar
(77 KB)
📄
documentor.tar.gz
(45.89 KB)
📄
documentor.zip
(64.28 KB)
📄
documents.h.h.tar.gz
(1.11 KB)
📄
documents.h.tar
(4.5 KB)
📄
doge.gif.gif.tar.gz
(127 B)
📄
doge.gif.tar
(2.5 KB)
📄
dojo.png.png.tar.gz
(10.82 KB)
📄
dojo.png.tar
(12.5 KB)
📄
dojo.tar
(72.5 KB)
📄
dojo.tar.gz
(44.96 KB)
📄
dojo.zip
(61.04 KB)
📄
doku.png.png.tar.gz
(36.84 KB)
📄
doku.png.tar
(38.5 KB)
📄
doku.tar
(6.16 MB)
📄
doku.tar.gz
(5.13 MB)
📄
doku.zip
(6.13 MB)
📄
dolibarr.tar
(85.6 MB)
📄
dolibarr.tar.gz
(81.91 MB)
📄
dolibarr.zip
(85.57 MB)
📄
dolph.tar
(267.5 KB)
📄
dolph.tar.gz
(158.63 KB)
📄
dolph.zip
(242.09 KB)
📄
domainmod.sql.sql.tar.gz
(13.61 KB)
📄
domainmod.sql.tar
(84 KB)
📄
domainmod.tar
(9 MB)
📄
domainmod.tar.gz
(8.36 MB)
📄
domainmod.zip
(8.97 MB)
📄
domainname.tar
(2 KB)
📄
domainname.tar.gz
(116 B)
📄
dosish.h.h.tar.gz
(2.43 KB)
📄
dosish.h.tar
(7 KB)
📄
dotcl.sql.sql.tar.gz
(6.78 KB)
📄
dotcl.sql.tar
(36.5 KB)
📄
dotcl.tar
(6.25 MB)
📄
dotcl.tar.gz
(5.07 MB)
📄
dotcl.zip
(6.22 MB)
📄
dotproj.tar
(173.5 KB)
📄
dotproj.tar.gz
(94.07 KB)
📄
dotproj.zip
(149.35 KB)
📄
doveadm.tar
(136.5 KB)
📄
doveadm.tar.gz
(34.8 KB)
📄
doveadm.zip
(133.32 KB)
📄
dovecot-acl-list.tar
(1.5 KB)
📄
dovecot-acl-list.tar.gz
(109 B)
📄
dovecot-lda.tar
(3 KB)
📄
dovecot-lda.tar.gz
(730 B)
📄
dovecot-quota.tar
(2 KB)
📄
dovecot-quota.tar.gz
(150 B)
📄
dovecot-uidlist.tar
(81.5 KB)
📄
dovecot-uidlist.tar.gz
(21.37 KB)
📄
dovecot.index.index.tar.gz
(6.45 KB)
📄
dovecot.index.log.index.log.tar.gz
(361 B)
📄
dovecot.index.log.tar
(2.5 KB)
📄
dovecot.index.tar
(29 KB)
📄
dovecot.list.index.list.index.tar.gz
(814 B)
📄
dovecot.list.index.tar
(4 KB)
📄
dovecot.tar
(8.34 MB)
📄
dovecot.tar.gz
(2.79 MB)
📄
dovecot.zip
(8.31 MB)
📄
down.fw.fw.tar.gz
(7.56 KB)
📄
down.fw.tar
(19.5 KB)
📄
down2.fw.fw.tar.gz
(7 KB)
📄
down2.fw.tar
(35 KB)
📄
down3.bin.bin.tar.gz
(8.13 KB)
📄
down3.bin.tar
(14.5 KB)
📄
dpaa2.tar
(14.73 MB)
📄
dpaa2.tar.gz
(6.21 MB)
📄
dpaa2.zip
(14.72 MB)
📄
dpms.h.h.tar.gz
(1.59 KB)
📄
dpms.h.tar
(13.5 KB)
📄
dptx.bin.bin.tar.gz
(33.13 KB)
📄
dptx.bin.tar
(195 KB)
📄
dracut-cmdline.service.service.tar.gz
(610 B)
📄
dracut-cmdline.service.tar
(2.5 KB)
📄
dracut-functions.sh.sh.tar.gz
(5.83 KB)
📄
dracut-functions.sh.tar
(45 KB)
📄
dracut-functions.tar
(45 KB)
📄
dracut-functions.tar.gz
(5.82 KB)
📄
dracut-init.sh.sh.tar.gz
(7.78 KB)
📄
dracut-init.sh.tar
(36 KB)
📄
dracut-initramfs-restore.tar
(3.5 KB)
📄
dracut-initramfs-restore.tar.gz
(812 B)
📄
dracut-install.tar
(76 KB)
📄
dracut-install.tar.gz
(34.46 KB)
📄
dracut-logger.sh.sh.tar.gz
(4.14 KB)
📄
dracut-logger.sh.tar
(28 KB)
📄
dracut-mount.service.service.tar.gz
(586 B)
📄
dracut-mount.service.tar
(2.5 KB)
📄
dracut-pre-trigger.service.service.tar.gz
(607 B)
📄
dracut-pre-trigger.service.tar
(2.5 KB)
📄
dracut-pre-udev.service.service.tar.gz
(627 B)
📄
dracut-pre-udev.service.tar
(2.5 KB)
📄
dracut-shutdown.service.service.tar.gz
(369 B)
📄
dracut-shutdown.service.tar
(2 KB)
📄
dracut-version.sh.sh.tar.gz
(149 B)
📄
dracut-version.sh.tar
(2 KB)
📄
dracut.conf.d.tar
(6.5 KB)
📄
dracut.conf.d.tar.gz
(719 B)
📄
dracut.conf.d.zip
(1.64 KB)
📄
dracut.tar
(916.5 KB)
📄
dracut.tar.gz
(208.55 KB)
📄
dracut.zip
(749.88 KB)
📄
drawmsg.inc.inc.tar.gz
(6.65 KB)
📄
drawmsg.inc.tar
(26 KB)
📄
drb.rb.rb.tar.gz
(16.04 KB)
📄
drb.rb.tar
(453.5 KB)
📄
dri.tar
(15 KB)
📄
dri.tar.gz
(2.56 KB)
📄
dri.zip
(12.42 KB)
📄
dri2.h.h.tar.gz
(3.54 KB)
📄
dri2.h.tar
(36.5 KB)
📄
dri3.h.h.tar.gz
(2.49 KB)
📄
dri3.h.tar
(25.5 KB)
📄
drivemap.mod.mod.tar.gz
(2.91 KB)
📄
drivemap.mod.tar
(8 KB)
📄
driver.tar
(3 KB)
📄
driver.tar.gz
(498 B)
📄
driver.zip
(1004 B)
📄
drivers.tar
(2.5 KB)
📄
drivers.tar.gz
(290 B)
📄
drm.h.h.tar.gz
(10.64 KB)
📄
drm.h.tar
(38.5 KB)
📄
drm.tar
(604 KB)
📄
drm.tar.gz
(154.98 KB)
📄
drm.zip
(587.72 KB)
📄
drm_fourcc.h.h.tar.gz
(17.6 KB)
📄
drm_fourcc.h.tar
(67 KB)
📄
drm_mode.h.h.tar.gz
(11.87 KB)
📄
drm_mode.h.tar
(40.5 KB)
📄
drm_sarea.h.h.tar.gz
(1.36 KB)
📄
drm_sarea.h.tar
(4.5 KB)
📄
drop.xml.tar
(2 KB)
📄
drop.xml.xml.tar.gz
(285 B)
📄
drop_caches.tar
(2 KB)
📄
drop_caches.tar.gz
(108 B)
📄
drop_unicast_in_l2_multicast.tar
(2 KB)
📄
drop_unicast_in_l2_multicast.tar.gz
(136 B)
📄
drop_unsolicited_na.tar
(2 KB)
📄
drop_unsolicited_na.tar.gz
(128 B)
📄
dropbox-lansync.xml.tar
(2 KB)
📄
dropbox-lansync.xml.xml.tar.gz
(242 B)
📄
dropdb.tar
(68 KB)
📄
dropdb.tar.gz
(25.96 KB)
📄
drops.tar
(2 KB)
📄
drops.tar.gz
(115 B)
📄
dropuser.tar
(67.5 KB)
📄
dropuser.tar.gz
(25.92 KB)
📄
dropzone.tar
(51 KB)
📄
dropzone.tar.gz
(27.08 KB)
📄
dropzone.zip
(41.57 KB)
📄
drupal.sql.sql.tar.gz
(58.92 KB)
📄
drupal.sql.tar
(398.5 KB)
📄
drupal.tar
(4.42 MB)
📄
drupal.tar.gz
(3.76 MB)
📄
drupal.zip
(4.39 MB)
📄
drupal10.tar
(34.64 MB)
📄
drupal10.tar.gz
(27.39 MB)
📄
drupal10.zip
(34.61 MB)
📄
drupal6.tar
(246.5 KB)
📄
drupal6.tar.gz
(147.07 KB)
📄
drupal6.zip
(220.17 KB)
📄
drupal8.tar
(35.03 MB)
📄
drupal8.tar.gz
(27.51 MB)
📄
drupal8.zip
(35 MB)
📄
drupal89.tar
(349 KB)
📄
drupal89.tar.gz
(216.93 KB)
📄
drupal89.zip
(325.54 KB)
📄
drupal9.tar
(372.5 KB)
📄
drupal9.tar.gz
(222.83 KB)
📄
drupal9.zip
(345.18 KB)
📄
drupalcms.sql.sql.tar.gz
(426.66 KB)
📄
drupalcms.sql.tar
(4.57 MB)
📄
drupalcms.tar
(120.51 MB)
📄
drupalcms.tar.gz
(103.37 MB)
📄
drupalcms.zip
(120.48 MB)
📄
dsa.h.h.tar.gz
(2.7 KB)
📄
dsa.h.tar
(11.5 KB)
📄
dsaerr.h.h.tar.gz
(1011 B)
📄
dsaerr.h.tar
(5 KB)
📄
dsp56k.tar
(2 KB)
📄
dsp56k.tar.gz
(237 B)
📄
dsp56k.zip
(535 B)
📄
dsp_basefw.bin.bin.tar.gz
(256.11 KB)
📄
dsp_basefw.bin.tar
(1.28 MB)
📄
dsp_fw_bxtn.bin.bin.tar.gz
(188.49 KB)
📄
dsp_fw_bxtn.bin.tar
(495.5 KB)
📄
dsp_fw_cnl.bin.bin.tar.gz
(256.1 KB)
📄
dsp_fw_cnl.bin.tar
(576 KB)
📄
dsp_fw_cnl_v1191.bin.bin.tar.gz
(218.78 KB)
📄
dsp_fw_cnl_v1191.bin.tar
(572 KB)
📄
dsp_fw_cnl_v1858.bin.bin.tar.gz
(222.64 KB)
📄
dsp_fw_cnl_v1858.bin.tar
(572 KB)
📄
dsp_fw_glk.bin.bin.tar.gz
(188.49 KB)
📄
dsp_fw_glk.bin.tar
(495.5 KB)
📄
dsp_fw_glk_v1814.bin.bin.tar.gz
(187.98 KB)
📄
dsp_fw_glk_v1814.bin.tar
(495.5 KB)
📄
dsp_fw_glk_v2768.bin.bin.tar.gz
(185.13 KB)
📄
dsp_fw_glk_v2768.bin.tar
(495.5 KB)
📄
dsp_fw_glk_v2880.bin.bin.tar.gz
(184.84 KB)
📄
dsp_fw_glk_v2880.bin.tar
(495.5 KB)
📄
dsp_fw_glk_v3366.bin.bin.tar.gz
(185.76 KB)
📄
dsp_fw_glk_v3366.bin.tar
(495.5 KB)
📄
dsp_fw_kbl.bin.bin.tar.gz
(147.92 KB)
📄
dsp_fw_kbl.bin.tar
(239 KB)
📄
dsp_fw_kbl_v1037.bin.bin.tar.gz
(145.9 KB)
📄
dsp_fw_kbl_v1037.bin.tar
(235 KB)
📄
dsp_fw_kbl_v2042.bin.bin.tar.gz
(146.29 KB)
📄
dsp_fw_kbl_v2042.bin.tar
(235 KB)
📄
dsp_fw_kbl_v2630.bin.bin.tar.gz
(148.12 KB)
📄
dsp_fw_kbl_v2630.bin.tar
(239 KB)
📄
dsp_fw_kbl_v3266.bin.bin.tar.gz
(147.88 KB)
📄
dsp_fw_kbl_v3266.bin.tar
(239 KB)
📄
dsp_fw_kbl_v3402.bin.bin.tar.gz
(149.05 KB)
📄
dsp_fw_kbl_v3402.bin.tar
(243 KB)
📄
dsp_fw_kbl_v3420.bin.bin.tar.gz
(148.06 KB)
📄
dsp_fw_kbl_v3420.bin.tar
(239 KB)
📄
dsp_fw_kbl_v701.bin.bin.tar.gz
(145.13 KB)
📄
dsp_fw_kbl_v701.bin.tar
(235 KB)
📄
dsp_fw_release_v969.bin.bin.tar.gz
(137.13 KB)
📄
dsp_fw_release_v969.bin.tar
(217.5 KB)
📄
dspbootcode.bin.bin.tar.gz
(6.57 KB)
📄
dspbootcode.bin.tar
(14.5 KB)
📄
dst.tar
(38 KB)
📄
dst.tar.gz
(8.08 KB)
📄
dst.zip
(34.45 KB)
📄
dtfmtsym.h.h.tar.gz
(7.54 KB)
📄
dtfmtsym.h.tar
(39.5 KB)
📄
dtitvfmt.h.h.tar.gz
(9.99 KB)
📄
dtitvfmt.h.tar
(48.5 KB)
📄
dtitvinf.h.h.tar.gz
(4.78 KB)
📄
dtitvinf.h.tar
(20 KB)
📄
dtls1.h.h.tar.gz
(3.27 KB)
📄
dtls1.h.tar
(13 KB)
📄
dtoa.h.h.tar.gz
(332 B)
📄
dtoa.h.tar
(2 KB)
📄
dtptngen.h.h.tar.gz
(5.55 KB)
📄
dtptngen.h.tar
(27 KB)
📄
du.tar
(108.5 KB)
📄
du.tar.gz
(51.58 KB)
📄
dumb.py.py.tar.gz
(3.56 KB)
📄
dumb.py.tar
(25.5 KB)
📄
dumbdbm.py.py.tar.gz
(3.12 KB)
📄
dumbdbm.py.tar
(10.5 KB)
📄
dumbdbm.pyc.pyc.tar.gz
(2.89 KB)
📄
dumbdbm.pyc.tar
(8.5 KB)
📄
dumbdbm.pyo.pyo.tar.gz
(2.89 KB)
📄
dumbdbm.pyo.tar
(8.5 KB)
📄
dummy.tar
(73.5 KB)
📄
dummy.tar.gz
(4.53 KB)
📄
dummy.zip
(63.25 KB)
📄
dummy_thread.py.py.tar.gz
(1.69 KB)
📄
dummy_thread.py.tar
(6 KB)
📄
dummy_threading.py.py.tar.gz
(922 B)
📄
dummy_threading.py.tar
(11.5 KB)
📄
dump.py.py.tar.gz
(1.25 KB)
📄
dump.py.tar
(11.5 KB)
📄
dutree.py.py.tar.gz
(789 B)
📄
dutree.py.tar
(3.5 KB)
📄
dvb-fe-xc4000-1.4.1.fw.4.1.fw.tar.gz
(6.6 KB)
📄
dvb-fe-xc4000-1.4.1.fw.tar
(20 KB)
📄
dvb-fe-xc5000c-4.1.30.7.fw.1.30.7.fw.tar.gz
(12.16 KB)
📄
dvb-fe-xc5000c-4.1.30.7.fw.tar
(18 KB)
📄
dvb-usb-dib0700-1.20.fw.20.fw.tar.gz
(21.28 KB)
📄
dvb-usb-dib0700-1.20.fw.tar
(34.5 KB)
📄
dvb-usb-it9135-01.fw.fw.tar.gz
(5.26 KB)
📄
dvb-usb-it9135-01.fw.tar
(9.5 KB)
📄
dvb-usb-it9135-02.fw.fw.tar.gz
(3.99 KB)
📄
dvb-usb-it9135-02.fw.tar
(7.5 KB)
📄
dvb-usb-terratec-h5-drxk.fw.fw.tar.gz
(28.27 KB)
📄
dvb-usb-terratec-h5-drxk.fw.tar
(51 KB)
📄
dvb_nova_12mhz.inp.inp.tar.gz
(56.63 KB)
📄
dvb_nova_12mhz.inp.tar
(93 KB)
📄
dvb_nova_12mhz_b0.inp.inp.tar.gz
(61.81 KB)
📄
dvb_nova_12mhz_b0.inp.tar
(101 KB)
📄
dvorak.kbd.kbd.tar.gz
(185 B)
📄
dvorak.kbd.tar
(2 KB)
📄
dynamic.php.php.tar.gz
(233 B)
📄
dynamic.php.tar
(2 KB)
📄
e018821693f96c43be7a0427501512f03debff.tar
(581.5 KB)
📄
e018821693f96c43be7a0427501512f03debff.tar.gz
(236.25 KB)
📄
e09155263f2ae740942adabab08f28c6b61439.tar
(26 KB)
📄
e09155263f2ae740942adabab08f28c6b61439.tar.gz
(10.8 KB)
📄
e100.tar
(5.5 KB)
📄
e100.tar.gz
(729 B)
📄
e100.zip
(2.02 KB)
📄
e107.tar
(316.5 KB)
📄
e107.tar.gz
(189.39 KB)
📄
e107.zip
(286.52 KB)
📄
e107_config.php.php.tar.gz
(1019 B)
📄
e107_config.php.tar
(3.5 KB)
📄
e2p.h.h.tar.gz
(1.08 KB)
📄
e2p.h.tar
(5 KB)
📄
e2p.pc.pc.tar.gz
(256 B)
📄
e2p.pc.tar
(2 KB)
📄
e2p.tar
(5 KB)
📄
e2p.tar.gz
(1.08 KB)
📄
e2p.zip
(3.32 KB)
📄
e4c2b9b3a01757b298fbfb2179a1b4feb606e2.tar
(13.5 KB)
📄
e4c2b9b3a01757b298fbfb2179a1b4feb606e2.tar.gz
(3.95 KB)
📄
e6801822679100279fb17a21bfdf7288f056ef.tar
(18.5 KB)
📄
e6801822679100279fb17a21bfdf7288f056ef.tar.gz
(6.65 KB)
📄
e7b3b93221f56c55eb17f596c5d899565a66d5.tar
(9 KB)
📄
e7b3b93221f56c55eb17f596c5d899565a66d5.tar.gz
(3.21 KB)
📄
e820.h.h.tar.gz
(1.35 KB)
📄
e820.h.tar
(4.5 KB)
📄
e8d9e119e8884be399eb01ebbed01e1e692e04.tar
(12.5 KB)
📄
e8d9e119e8884be399eb01ebbed01e1e692e04.tar.gz
(2.95 KB)
📄
e_os2.h.h.tar.gz
(3.3 KB)
📄
e_os2.h.tar
(22 KB)
📄
ea-apr16-util-1.pc.pc.tar.gz
(368 B)
📄
ea-apr16-util-1.pc.tar
(2 KB)
📄
ea-apr16.tar
(2.06 MB)
📄
ea-apr16.tar.gz
(589.4 KB)
📄
ea-apr16.zip
(2 MB)
📄
ea-brotli.tar
(10.97 MB)
📄
ea-brotli.tar.gz
(5.48 MB)
📄
ea-brotli.zip
(10.97 MB)
📄
ea-libicu.tar
(37.71 MB)
📄
ea-libicu.tar.gz
(14.65 MB)
📄
ea-libicu.zip
(37.71 MB)
📄
ea-libxml2.tar
(1.76 MB)
📄
ea-libxml2.tar.gz
(697.91 KB)
📄
ea-libxml2.zip
(1.73 MB)
📄
ea-libzip.tar
(130.5 KB)
📄
ea-libzip.tar.gz
(62.88 KB)
📄
ea-libzip.zip
(128.94 KB)
📄
ea-oniguruma.tar
(1.45 MB)
📄
ea-oniguruma.tar.gz
(448.75 KB)
📄
ea-oniguruma.zip
(1.45 MB)
📄
ea-php70.tar
(6.05 MB)
📄
ea-php70.tar.gz
(1.99 MB)
📄
ea-php71.tar
(6.32 MB)
📄
ea-php71.tar.gz
(2.06 MB)
📄
ea-php72.tar
(6.73 MB)
📄
ea-php72.tar.gz
(2.17 MB)
📄
ea-php73.tar
(4.63 MB)
📄
ea-php73.tar.gz
(1.77 MB)
📄
ea-php74.tar
(6.09 MB)
📄
ea-php74.tar.gz
(1.88 MB)
📄
ea-php80.tar
(29.5 KB)
📄
ea-php80.tar.gz
(8.62 KB)
📄
ea-php80.zip
(27.82 KB)
📄
ea-php81.tar
(10.88 MB)
📄
ea-php81.tar.gz
(3.85 MB)
📄
ea-php82.tar
(29.5 KB)
📄
ea-php82.tar.gz
(8.62 KB)
📄
ea-php82.zip
(27.81 KB)
📄
ea-php83.tar
(29.5 KB)
📄
ea-php83.tar.gz
(8.62 KB)
📄
ea-php83.zip
(27.81 KB)
📄
ea-php84.tar
(29.5 KB)
📄
ea-php84.tar.gz
(8.62 KB)
📄
ea-php84.zip
(27.81 KB)
📄
ea-php85.tar
(29.5 KB)
📄
ea-php85.tar.gz
(8.62 KB)
📄
ea-php85.zip
(27.81 KB)
📄
ea-profiles-cloudlinux.tar
(509 KB)
📄
ea-profiles-cloudlinux.tar.gz
(36.13 KB)
📄
ea-profiles-cloudlinux.zip
(489.13 KB)
📄
ea-profiles-cpanel.tar
(49.5 KB)
📄
ea-profiles-cpanel.tar.gz
(3.74 KB)
📄
ea-profiles-cpanel.zip
(38.15 KB)
📄
ea-ruby27-passenger.conf.conf.tar.gz
(148 B)
📄
ea-ruby27-passenger.conf.tar
(2 KB)
📄
ea-ruby27.tar
(2 KB)
📄
ea-ruby27.tar.gz
(163 B)
📄
ea4.tar
(12.5 KB)
📄
ea4.tar.gz
(3.6 KB)
📄
ea4.zip
(11.08 KB)
📄
ea_php_cli.pm.pm.tar.gz
(3.61 KB)
📄
ea_php_cli.pm.tar
(12.5 KB)
📄
eagleI.fw.fw.tar.gz
(7.92 KB)
📄
eagleI.fw.tar
(12.5 KB)
📄
eagleII.fw.fw.tar.gz
(7.9 KB)
📄
eagleII.fw.tar
(12.5 KB)
📄
eagleIII.fw.fw.tar.gz
(7.98 KB)
📄
eagleIII.fw.tar
(12.5 KB)
📄
eagleIV.fw.fw.tar.gz
(7.47 KB)
📄
eagleIV.fw.tar
(12 KB)
📄
easy.h.h.tar.gz
(1.42 KB)
📄
easy.h.tar
(5 KB)
📄
easy_install.tar
(3 KB)
📄
easy_install.tar.gz
(271 B)
📄
easyapmt.tar
(37.66 MB)
📄
easyapmt.tar.gz
(29.21 MB)
📄
easyapmt.zip
(37.63 MB)
📄
easyp.tar
(136 KB)
📄
easyp.tar.gz
(63.88 KB)
📄
easyp.zip
(110.06 KB)
📄
ebcdic.h.h.tar.gz
(551 B)
📄
ebcdic.h.tar
(2.5 KB)
📄
ebcdic.so.so.tar.gz
(4.04 KB)
📄
ebcdic.so.tar
(13 KB)
📄
ebitmap.h.h.tar.gz
(1.13 KB)
📄
ebitmap.h.tar
(5 KB)
📄
ebtables.service.service.tar.gz
(252 B)
📄
ebtables.service.tar
(2 KB)
📄
ec.h.h.tar.gz
(9.98 KB)
📄
ec.h.tar
(122 KB)
📄
ecdh.h.h.tar.gz
(337 B)
📄
ecdh.h.tar
(2 KB)
📄
ecdsa.h.h.tar.gz
(3.42 KB)
📄
ecdsa.h.tar
(16.5 KB)
📄
ecerr.h.h.tar.gz
(3.1 KB)
📄
ecerr.h.tar
(18 KB)
📄
echo-reply.xml.tar
(2 KB)
📄
echo-reply.xml.xml.tar.gz
(244 B)
📄
echo.mod.mod.tar.gz
(1.14 KB)
📄
echo.mod.tar
(4 KB)
📄
echo.tar
(39 KB)
📄
echo.tar.gz
(15.92 KB)
📄
echosvr.py.py.tar.gz
(539 B)
📄
echosvr.py.tar
(2.5 KB)
📄
ecmerge.tar
(2 KB)
📄
ecmerge.tar.gz
(312 B)
📄
ed08e822497246b5c424fb07b64366b2377cbe.tar
(55 KB)
📄
ed08e822497246b5c424fb07b64366b2377cbe.tar.gz
(20.76 KB)
📄
edgeport.tar
(65.5 KB)
📄
edgeport.tar.gz
(26.55 KB)
📄
edgeport.zip
(61.09 KB)
📄
edit.php.php.tar.gz
(4.3 KB)
📄
edit.php.tar
(3.63 MB)
📄
edit.xml.tar
(385 KB)
📄
edit.xml.xml.tar.gz
(295 B)
📄
editor.tar
(71.49 MB)
📄
editor.tar.gz
(17.66 MB)
📄
editor.zip
(69.56 MB)
📄
edits.h.h.tar.gz
(5.02 KB)
📄
edits.h.tar
(22.5 KB)
📄
eengine.sql.sql.tar.gz
(44.32 KB)
📄
eengine.sql.tar
(263.5 KB)
📄
eengine.tar
(21.65 MB)
📄
eengine.tar.gz
(20.38 MB)
📄
eengine.zip
(21.62 MB)
📄
ef290a9d13371596307585be83ae1f104d2f36.tar
(13.5 KB)
📄
ef290a9d13371596307585be83ae1f104d2f36.tar.gz
(6.04 KB)
📄
efa-abi.h.h.tar.gz
(1.17 KB)
📄
efa-abi.h.tar
(4.5 KB)
📄
efe.tar
(25.5 KB)
📄
efe.tar.gz
(18.17 KB)
📄
effective_affinity.tar
(20 KB)
📄
effective_affinity.tar.gz
(121 B)
📄
effective_affinity_list.tar
(11 KB)
📄
effective_affinity_list.tar.gz
(117 B)
📄
effective_version.tar
(2 KB)
📄
effective_version.tar.gz
(132 B)
📄
efi.tar
(146 KB)
📄
efi.tar.gz
(59.79 KB)
📄
efi.zip
(144.06 KB)
📄
efiemu.mod.mod.tar.gz
(13.34 KB)
📄
efiemu.mod.tar
(71 KB)
📄
egldeviceintegrations.tar
(399 KB)
📄
egldeviceintegrations.tar.gz
(157.54 KB)
📄
egldeviceintegrations.zip
(395.74 KB)
📄
egrep.tar
(2 KB)
📄
egrep.tar.gz
(120 B)
📄
egroup.sql.sql.tar.gz
(39.42 KB)
📄
egroup.sql.tar
(274.5 KB)
📄
egroup.tar
(174.7 MB)
📄
egroup.tar.gz
(160.15 MB)
📄
egroup.zip
(174.67 MB)
📄
ehci.mod.mod.tar.gz
(8.11 KB)
📄
ehci.mod.tar
(22.5 KB)
📄
ehl_guc_33.0.4.bin.0.4.bin.tar.gz
(123.58 KB)
📄
ehl_guc_33.0.4.bin.tar
(388.5 KB)
📄
ehl_guc_49.0.1.bin.0.1.bin.tar.gz
(126.81 KB)
📄
ehl_guc_49.0.1.bin.tar
(318.5 KB)
📄
ehl_guc_62.0.0.bin.0.0.bin.tar.gz
(131.88 KB)
📄
ehl_guc_62.0.0.bin.tar
(321.5 KB)
📄
ehl_guc_69.0.3.bin.0.3.bin.tar.gz
(144.61 KB)
📄
ehl_guc_69.0.3.bin.tar
(337 KB)
📄
ehl_guc_70.1.1.bin.1.1.bin.tar.gz
(108.91 KB)
📄
ehl_guc_70.1.1.bin.tar
(270 KB)
📄
ehl_huc_9.0.0.bin.0.0.bin.tar.gz
(151.87 KB)
📄
ehl_huc_9.0.0.bin.tar
(489 KB)
📄
element.rb.rb.tar.gz
(1.54 KB)
📄
element.rb.tar
(7 KB)
📄
elf.h.h.tar.gz
(39.41 KB)
📄
elf.h.tar
(174 KB)
📄
elf.mod.mod.tar.gz
(2.42 KB)
📄
elf.mod.tar
(14 KB)
📄
elgg.png.png.tar.gz
(14.64 KB)
📄
elgg.png.tar
(16.5 KB)
📄
elgg.tar
(262.5 KB)
📄
elgg.tar.gz
(154.35 KB)
📄
elgg.zip
(236.07 KB)
📄
elgg2.tar
(285 KB)
📄
elgg2.tar.gz
(164.26 KB)
📄
elgg2.zip
(252.76 KB)
📄
elgg3.sql.sql.tar.gz
(5.87 KB)
📄
elgg3.sql.tar
(38.5 KB)
📄
elgg3.tar
(48.24 MB)
📄
elgg3.tar.gz
(43.88 MB)
📄
elgg3.zip
(48.21 MB)
📄
elgg33.tar
(278.5 KB)
📄
elgg33.tar.gz
(156.43 KB)
📄
elgg33.zip
(247.62 KB)
📄
elgg4.sql.sql.tar.gz
(5.29 KB)
📄
elgg4.sql.tar
(33.5 KB)
📄
elgg4.tar
(47.14 MB)
📄
elgg4.tar.gz
(43.23 MB)
📄
elgg4.zip
(47.11 MB)
📄
elkarte.tar
(207.5 KB)
📄
elkarte.tar.gz
(119.24 KB)
📄
elkarte.zip
(186.08 KB)
📄
ely.png.png.tar.gz
(25.79 KB)
📄
ely.png.tar
(27.5 KB)
📄
ely.tar
(74 KB)
📄
ely.tar.gz
(52.96 KB)
📄
ely.zip
(64.8 KB)
📄
emacs_mule.so.so.tar.gz
(4.04 KB)
📄
emacs_mule.so.tar
(13.5 KB)
📄
email-filter.so.so.tar.gz
(6.53 KB)
📄
email-filter.so.tar
(17.5 KB)
📄
email.amf.amf.tar.gz
(201 B)
📄
email.amf.tar
(2 KB)
📄
email.tar
(2.27 MB)
📄
email.tar.gz
(361.05 KB)
📄
email.zip
(2.13 MB)
📄
embed.h.h.tar.gz
(19.02 KB)
📄
embed.h.tar
(97 KB)
📄
embed.tar
(10 KB)
📄
embed.tar.gz
(2.46 KB)
📄
embed.zip
(5.67 KB)
📄
embedvar.h.h.tar.gz
(4.01 KB)
📄
embedvar.h.tar
(20 KB)
📄
emergency.service.service.tar.gz
(586 B)
📄
emergency.service.tar
(2.5 KB)
📄
emergency.target.tar
(3 KB)
📄
emergency.target.target.tar.gz
(400 B)
📄
emi26.tar
(134.5 KB)
📄
emi26.tar.gz
(68.76 KB)
📄
emi26.zip
(132.12 KB)
📄
emi62.tar
(205 KB)
📄
emi62.tar.gz
(99.72 KB)
📄
emi62.zip
(201.51 KB)
📄
emoji_iso2022_kddi.so.so.tar.gz
(54.95 KB)
📄
emoji_iso2022_kddi.so.tar
(113.5 KB)
📄
emoji_sjis_kddi.so.so.tar.gz
(60.58 KB)
📄
emoji_sjis_kddi.so.tar
(125 KB)
📄
empty.uni.tar
(3 KB)
📄
empty.uni.uni.tar.gz
(127 B)
📄
emu10k1.h.h.tar.gz
(5.13 KB)
📄
emu10k1.h.tar
(20 KB)
📄
en7581_npu_data.bin.bin.tar.gz
(792 B)
📄
en7581_npu_data.bin.tar
(5 KB)
📄
en7581_npu_rv32.bin.bin.tar.gz
(77.15 KB)
📄
en7581_npu_rv32.bin.tar
(119 KB)
📄
en_AU.tar
(318.5 KB)
📄
en_AU.tar.gz
(51.82 KB)
📄
en_AU.zip
(309.01 KB)
📄
en_BW.tar
(318.5 KB)
📄
en_BW.tar.gz
(51.76 KB)
📄
en_BW.zip
(308.87 KB)
📄
en_CA.tar
(318.5 KB)
📄
en_CA.tar.gz
(51.83 KB)
📄
en_CA.zip
(309 KB)
📄
en_DK.tar
(318.5 KB)
📄
en_DK.tar.gz
(51.83 KB)
📄
en_DK.zip
(308.94 KB)
📄
en_GB.iso885915.tar
(320 KB)
📄
en_GB.iso885915.tar.gz
(52.08 KB)
📄
en_GB.iso885915.zip
(310.44 KB)
📄
en_GB.tar
(318.5 KB)
📄
en_GB.tar.gz
(51.88 KB)
📄
en_GB.zip
(309.06 KB)
📄
en_HK.tar
(318.5 KB)
📄
en_HK.tar.gz
(51.92 KB)
📄
en_HK.zip
(309.24 KB)
📄
en_IE.tar
(318.5 KB)
📄
en_IE.tar.gz
(51.8 KB)
📄
en_IE.zip
(308.93 KB)
📄
en_IE@euro.tar
(320 KB)
📄
en_IE@euro.tar.gz
(52.01 KB)
📄
en_IE@euro.zip
(310.32 KB)
📄
en_NZ.tar
(318.5 KB)
📄
en_NZ.tar.gz
(51.83 KB)
📄
en_NZ.zip
(309 KB)
📄
en_PH.tar
(318.5 KB)
📄
en_PH.tar.gz
(51.93 KB)
📄
en_PH.zip
(309.25 KB)
📄
en_SG.tar
(318.5 KB)
📄
en_SG.tar.gz
(51.94 KB)
📄
en_SG.zip
(309.08 KB)
📄
en_US.iso885915.tar
(320 KB)
📄
en_US.iso885915.tar.gz
(52.07 KB)
📄
en_US.iso885915.zip
(310.43 KB)
📄
en_US.tar
(318.5 KB)
📄
en_US.tar.gz
(51.88 KB)
📄
en_US.zip
(309.05 KB)
📄
en_ZA.tar
(318.5 KB)
📄
en_ZA.tar.gz
(51.85 KB)
📄
en_ZA.zip
(309.01 KB)
📄
en_ZW.tar
(318.5 KB)
📄
en_ZW.tar.gz
(51.76 KB)
📄
en_ZW.zip
(308.87 KB)
📄
enable.tar
(21.5 KB)
📄
enable.tar.gz
(279 B)
📄
enabled.tar
(2 KB)
📄
enabled.tar.gz
(110 B)
📄
enc.tar
(3.31 MB)
📄
enc.tar.gz
(1.43 MB)
📄
enc.zip
(3.26 MB)
📄
enc2xs.tar
(42.5 KB)
📄
enc2xs.tar.gz
(15.28 KB)
📄
encdb.so.so.tar.gz
(4.69 KB)
📄
encdb.so.tar
(13 KB)
📄
enchant-lsmod.tar
(15 KB)
📄
enchant-lsmod.tar.gz
(4.56 KB)
📄
enchant.tar
(54 KB)
📄
enchant.tar.gz
(11.95 KB)
📄
enchant.zip
(30.31 KB)
📄
encoder.py.py.tar.gz
(4.06 KB)
📄
encoder.py.tar
(51 KB)
📄
encoders.py.py.tar.gz
(801 B)
📄
encoders.py.tar
(8.5 KB)
📄
encoders.pyc.pyc.tar.gz
(1002 B)
📄
encoders.pyc.tar
(4 KB)
📄
encoders.pyo.pyo.tar.gz
(1003 B)
📄
encoders.pyo.tar
(4 KB)
📄
encoding.pm.pm.tar.gz
(760 B)
📄
encoding.pm.tar
(26 KB)
📄
encoding.tar
(29.5 KB)
📄
encoding.tar.gz
(10.25 KB)
📄
encoding.zip
(27.72 KB)
📄
encodings.tar
(5.15 MB)
📄
encodings.tar.gz
(435.78 KB)
📄
encodings.zip
(4.57 MB)
📄
encryption.iv.iv.tar.gz
(124 B)
📄
encryption.iv.tar
(2 KB)
📄
encryption.key.key.tar.gz
(127 B)
📄
encryption.key.tar
(2 KB)
📄
encryption_key.php.php.tar.gz
(130 B)
📄
encryption_key.php.tar
(2 KB)
📄
endian.h.h.tar.gz
(1.22 KB)
📄
endian.h.tar
(6 KB)
📄
endian.ph.ph.tar.gz
(775 B)
📄
endian.ph.tar
(7 KB)
📄
ene-ub6250.tar
(16 KB)
📄
ene-ub6250.tar.gz
(4.06 KB)
📄
ene-ub6250.zip
(12.81 KB)
📄
engine.h.h.tar.gz
(10 KB)
📄
engine.h.tar
(35.5 KB)
📄
engineerr.h.h.tar.gz
(1.43 KB)
📄
engineerr.h.tar
(7 KB)
📄
engines-1.1.tar
(148 KB)
📄
engines-1.1.tar.gz
(55.7 KB)
📄
engines-1.1.zip
(144.44 KB)
📄
engines.tar
(426 KB)
📄
engines.tar.gz
(18.57 KB)
📄
engines.zip
(416.7 KB)
📄
enhanced_dad.tar
(2 KB)
📄
enhanced_dad.tar.gz
(123 B)
📄
ensurepip.tar
(83 KB)
📄
ensurepip.tar.gz
(5.66 KB)
📄
ensurepip.zip
(66.54 KB)
📄
entities.h.h.tar.gz
(1.77 KB)
📄
entities.h.tar
(6.5 KB)
📄
entropy_avail.tar
(2 KB)
📄
entropy_avail.tar.gz
(123 B)
📄
enum.py.py.tar.gz
(9.6 KB)
📄
enum.py.tar
(72.5 KB)
📄
enumobject.h.h.tar.gz
(260 B)
📄
enumobject.h.tar
(2 KB)
📄
env.php.php.tar.gz
(274 B)
📄
env.php.tar
(17.5 KB)
📄
env.tar
(43 KB)
📄
env.tar.gz
(18.32 KB)
📄
environ.tar
(13 KB)
📄
environ.tar.gz
(255 B)
📄
environment-modules.tar
(4.5 KB)
📄
environment-modules.tar.gz
(697 B)
📄
environment-modules.zip
(1.68 KB)
📄
environment.tar
(1.5 KB)
📄
environment.tar.gz
(90 B)
📄
environments.h.h.tar.gz
(1.47 KB)
📄
environments.h.tar
(5.5 KB)
📄
epesi.tar
(206 KB)
📄
epesi.tar.gz
(111.81 KB)
📄
epesi.zip
(179.6 KB)
📄
epoll.h.h.tar.gz
(1.81 KB)
📄
epoll.h.tar
(6 KB)
📄
epoll.tar
(2 KB)
📄
epoll.tar.gz
(109 B)
📄
epoll.zip
(175 B)
📄
eppic_makedumpfile.so.so.tar.gz
(123.84 KB)
📄
eppic_makedumpfile.so.tar
(334.5 KB)
📄
eps2eps.tar
(2.5 KB)
📄
eps2eps.tar.gz
(504 B)
📄
eptags.py.py.tar.gz
(852 B)
📄
eptags.py.tar
(3 KB)
📄
epyc-eda.tar
(2 KB)
📄
epyc-eda.tar.gz
(344 B)
📄
epyc-eda.zip
(538 B)
📄
epylint.tar
(2 KB)
📄
epylint.tar.gz
(230 B)
📄
eqn.tar
(234 KB)
📄
eqn.tar.gz
(80.23 KB)
📄
erb.tar
(73 KB)
📄
erb.tar.gz
(410 B)
📄
erb.zip
(11.63 KB)
📄
erbio.rb.rb.tar.gz
(546 B)
📄
erbio.rb.tar
(13 KB)
📄
err.h.h.tar.gz
(927 B)
📄
err.h.tar
(16 KB)
📄
errcode.h.h.tar.gz
(874 B)
📄
errcode.h.tar
(3.5 KB)
📄
errcodes.h.h.tar.gz
(509 B)
📄
errcodes.h.tar
(2.5 KB)
📄
errmsg.h.h.tar.gz
(1.91 KB)
📄
errmsg.h.tar
(11.5 KB)
📄
errno-base.h.h.tar.gz
(838 B)
📄
errno-base.h.tar
(3.5 KB)
📄
errno.h.h.tar.gz
(986 B)
📄
errno.h.tar
(14 KB)
📄
error.h.h.tar.gz
(1.1 KB)
📄
error.h.tar
(7 KB)
📄
error.rb.rb.tar.gz
(620 B)
📄
error.rb.tar
(3 KB)
📄
error_burst.tar
(2 KB)
📄
error_burst.tar.gz
(121 B)
📄
error_cost.tar
(2 KB)
📄
error_cost.tar.gz
(119 B)
📄
error_level.tar
(2 KB)
📄
error_level.tar.gz
(111 B)
📄
error_log
(6.32 MB)
📄
error_log.tar
(15.5 KB)
📄
error_log.tar.gz
(52.28 KB)
📄
errors.py.py.tar.gz
(1.37 KB)
📄
errors.py.tar
(12.5 KB)
📄
es.tar
(102 KB)
📄
es.tar.gz
(90.17 KB)
📄
es.zip
(91.73 KB)
📄
es_shrinker_info.tar
(7 KB)
📄
es_shrinker_info.tar.gz
(266 B)
📄
escape.so.so.tar.gz
(6.15 KB)
📄
escape.so.tar
(30 KB)
📄
espo.png.png.tar.gz
(2.39 KB)
📄
espo.png.tar
(4.5 KB)
📄
espo.sql.sql.tar.gz
(12.42 KB)
📄
espo.sql.tar
(163 KB)
📄
espo.tar
(33.63 MB)
📄
espo.tar.gz
(29.64 MB)
📄
espo.zip
(33.61 MB)
📄
et.tar
(4 KB)
📄
et.tar.gz
(842 B)
📄
et.zip
(2.22 KB)
📄
etano.tar
(189 KB)
📄
etano.tar.gz
(111.46 KB)
📄
etano.zip
(167.26 KB)
📄
etc.conf.conf.tar.gz
(402 B)
📄
etc.conf.tar
(4 KB)
📄
etc.so.so.tar.gz
(10.71 KB)
📄
etc.so.tar
(29.5 KB)
📄
etc.tar
(26.4 MB)
📄
etc.tar.gz
(472.93 KB)
📄
etc.zip
(25.82 MB)
📄
etcd-client.xml.tar
(2 KB)
📄
etcd-client.xml.xml.tar.gz
(315 B)
📄
etcd-server.xml.tar
(2 KB)
📄
etcd-server.xml.xml.tar.gz
(315 B)
📄
etckeeper.service.service.tar.gz
(302 B)
📄
etckeeper.service.tar
(2 KB)
📄
etckeeper.timer.tar
(2 KB)
📄
etckeeper.timer.timer.tar.gz
(249 B)
📄
eth0.tar
(49 KB)
📄
eth0.tar.gz
(444 B)
📄
eth0.zip
(6.76 KB)
📄
eth1.tar
(49 KB)
📄
eth1.tar.gz
(444 B)
📄
eth1.zip
(6.76 KB)
📄
ether.h.h.tar.gz
(949 B)
📄
ether.h.tar
(3.5 KB)
📄
ethernet.h.h.tar.gz
(1.42 KB)
📄
ethernet.h.tar
(5 KB)
📄
ethiopic.uni.tar
(7.5 KB)
📄
ethiopic.uni.uni.tar.gz
(2.33 KB)
📄
eti.h.h.tar.gz
(1.17 KB)
📄
eti.h.tar
(11.5 KB)
📄
etip.h.h.tar.gz
(2.63 KB)
📄
etip.h.tar
(31 KB)
📄
euc2004_sjis2004.so.so.tar.gz
(4.08 KB)
📄
euc2004_sjis2004.so.tar
(13 KB)
📄
euc_jp.so.so.tar.gz
(5.42 KB)
📄
euc_jp.so.tar
(17.5 KB)
📄
euc_jp_and_sjis.so.so.tar.gz
(7.61 KB)
📄
euc_jp_and_sjis.so.tar
(17.5 KB)
📄
euc_kr.so.so.tar.gz
(3.7 KB)
📄
euc_kr.so.tar
(13.5 KB)
📄
euc_tw.so.so.tar.gz
(3.77 KB)
📄
euc_tw.so.tar
(13.5 KB)
📄
euc_tw_and_big5.so.so.tar.gz
(6.17 KB)
📄
euc_tw_and_big5.so.tar
(18 KB)
📄
eval.go.go.tar.gz
(6.04 KB)
📄
eval.go.tar
(15 KB)
📄
eval.h.h.tar.gz
(467 B)
📄
eval.h.tar
(3 KB)
📄
eval.mod.mod.tar.gz
(878 B)
📄
eval.mod.tar
(3.5 KB)
📄
evdns.h.h.tar.gz
(1.1 KB)
📄
evdns.h.tar
(3.5 KB)
📄
event-config-64.h.h.tar.gz
(3.46 KB)
📄
event-config-64.h.tar
(18 KB)
📄
event-config.h.h.tar.gz
(211 B)
📄
event-config.h.tar
(2 KB)
📄
event.h.h.tar.gz
(1.29 KB)
📄
event.h.tar
(66 KB)
📄
event2.tar
(374 KB)
📄
event2.tar.gz
(85.24 KB)
📄
event2.zip
(355.64 KB)
📄
event_compat.h.h.tar.gz
(2.52 KB)
📄
event_compat.h.tar
(9 KB)
📄
event_struct.h.h.tar.gz
(2.02 KB)
📄
event_struct.h.tar
(6.5 KB)
📄
eventfd.h.h.tar.gz
(702 B)
📄
eventfd.h.tar
(5 KB)
📄
events.conf.php.conf.php.tar.gz
(1017 B)
📄
events.conf.php.tar
(5 KB)
📄
events.py.py.tar.gz
(6.06 KB)
📄
events.py.tar
(51 KB)
📄
eventsch.tar
(321.48 MB)
📄
eventsch.tar.gz
(309.51 MB)
📄
eventsch.zip
(321.46 MB)
📄
eventum.tar
(178.5 KB)
📄
eventum.tar.gz
(97.34 KB)
📄
eventum.zip
(156.05 KB)
📄
evhttp.h.h.tar.gz
(1.1 KB)
📄
evhttp.h.tar
(3.5 KB)
📄
evp.h.h.tar.gz
(11.94 KB)
📄
evp.h.tar
(77 KB)
📄
evperr.h.h.tar.gz
(2.5 KB)
📄
evperr.h.tar
(13.5 KB)
📄
evrpc.h.h.tar.gz
(1.1 KB)
📄
evrpc.h.tar
(3.5 KB)
📄
evtchn.h.h.tar.gz
(1.54 KB)
📄
evtchn.h.tar
(5 KB)
📄
evutil.h.h.tar.gz
(1.01 KB)
📄
evutil.h.tar
(3.5 KB)
📄
ex.tar
(1.13 MB)
📄
ex.tar.gz
(583.55 KB)
📄
exception-trace.tar
(2 KB)
📄
exception-trace.tar.gz
(115 B)
📄
exe.tar
(108.86 MB)
📄
exe.tar.gz
(3.83 MB)
📄
execinfo.h.h.tar.gz
(879 B)
📄
execinfo.h.tar
(3 KB)
📄
exfat.mod.mod.tar.gz
(3.71 KB)
📄
exfat.mod.tar
(17 KB)
📄
exfctest.mod.mod.tar.gz
(681 B)
📄
exfctest.mod.tar
(3 KB)
📄
exim.tar
(3 KB)
📄
exim.tar.gz
(716 B)
📄
exit.target.tar
(4 KB)
📄
exit.target.target.tar.gz
(445 B)
📄
expand.tar
(43.5 KB)
📄
expand.tar.gz
(19.48 KB)
📄
expat-2.5.0.tar
(15 KB)
📄
expat-2.5.0.tar.gz
(3.65 KB)
📄
expat-2.5.0.zip
(11.75 KB)
📄
expat.h.h.tar.gz
(12.22 KB)
📄
expat.h.tar
(45 KB)
📄
expat.pc.pc.tar.gz
(261 B)
📄
expat.pc.tar
(2 KB)
📄
expat_config.h.h.tar.gz
(1.31 KB)
📄
expat_config.h.tar
(5.5 KB)
📄
expat_external.h.h.tar.gz
(2.53 KB)
📄
expat_external.h.tar
(7.5 KB)
📄
expr.tar
(51.5 KB)
📄
expr.tar.gz
(21.88 KB)
📄
exslt.h.h.tar.gz
(727 B)
📄
exslt.h.tar
(4.5 KB)
📄
exsltconfig.h.h.tar.gz
(649 B)
📄
exsltconfig.h.tar
(3 KB)
📄
ext.d.tar
(28 KB)
📄
ext.d.tar.gz
(3.35 KB)
📄
ext.d.zip
(21.02 KB)
📄
ext.tar
(90 KB)
📄
ext.tar.gz
(25.43 KB)
📄
ext.zip
(81.28 KB)
📄
ext2.mod.mod.tar.gz
(4.42 KB)
📄
ext2.mod.tar
(11 KB)
📄
ext2_ext_attr.h.h.tar.gz
(1 KB)
📄
ext2_ext_attr.h.tar
(4.5 KB)
📄
ext2_fs.h.h.tar.gz
(11.46 KB)
📄
ext2_fs.h.tar
(43 KB)
📄
ext2_io.h.h.tar.gz
(1.44 KB)
📄
ext2_io.h.tar
(7 KB)
📄
ext2_types.h.h.tar.gz
(648 B)
📄
ext2_types.h.tar
(3 KB)
📄
ext2fs.h.h.tar.gz
(14.4 KB)
📄
ext2fs.h.tar
(72.5 KB)
📄
ext2fs.pc.pc.tar.gz
(251 B)
📄
ext2fs.pc.tar
(2 KB)
📄
ext2fs.tar
(186 KB)
📄
ext2fs.tar.gz
(38.9 KB)
📄
ext2fs.zip
(176.94 KB)
📄
ext3_extents.h.h.tar.gz
(1.79 KB)
📄
ext3_extents.h.tar
(6 KB)
📄
ext4.tar
(9.17 MB)
📄
ext4.tar.gz
(1.87 MB)
📄
ext4.zip
(9.16 MB)
📄
extcap.tar
(108 KB)
📄
extcap.tar.gz
(40.7 KB)
📄
extcap.zip
(105.26 KB)
📄
extcmd.mod.mod.tar.gz
(3.21 KB)
📄
extcmd.mod.tar
(16 KB)
📄
extend.php.php.tar.gz
(6.27 KB)
📄
extend.php.tar
(3.52 MB)
📄
extend.txt.tar
(5.5 KB)
📄
extend.txt.txt.tar.gz
(1.64 KB)
📄
extensions.tar
(646.5 KB)
📄
extensions.tar.gz
(104.63 KB)
📄
extensions.zip
(590.84 KB)
📄
external.xml.tar
(2 KB)
📄
external.xml.xml.tar.gz
(309 B)
📄
extfs.d.tar
(173.5 KB)
📄
extfs.d.tar.gz
(43.77 KB)
📄
extfs.d.zip
(151.07 KB)
📄
extplorer.tar
(127 KB)
📄
extplorer.tar.gz
(66.66 KB)
📄
extplorer.zip
(108.66 KB)
📄
extra.h.h.tar.gz
(773 B)
📄
extra.h.tar
(3.5 KB)
📄
extra.tar
(466 KB)
📄
extra.tar.gz
(106.84 KB)
📄
exynos_drm.h.h.tar.gz
(3.31 KB)
📄
exynos_drm.h.tar
(12.5 KB)
📄
f0ef10da45dc68b4d9b5b4262014f549134972.tar
(10 KB)
📄
f0ef10da45dc68b4d9b5b4262014f549134972.tar.gz
(3.64 KB)
📄
f1b2201ab97563a2a9c66685ebfbc968e12967.tar
(46 KB)
📄
f1b2201ab97563a2a9c66685ebfbc968e12967.tar.gz
(17.93 KB)
📄
f2255usb.bin.bin.tar.gz
(69.24 KB)
📄
f2255usb.bin.tar
(179 KB)
📄
f2fs.mod.mod.tar.gz
(5.06 KB)
📄
f2fs.mod.tar
(12.5 KB)
📄
f2py.tar
(2 KB)
📄
f2py.tar.gz
(236 B)
📄
f3723ce900603b72870c7b927826385e6cb9d2.tar
(609.5 KB)
📄
f3723ce900603b72870c7b927826385e6cb9d2.tar.gz
(317.94 KB)
📄
f3f63ed37449de7a2e98a4eb5f81b712c12be3.tar
(51.5 KB)
📄
f3f63ed37449de7a2e98a4eb5f81b712c12be3.tar.gz
(23.65 KB)
📄
f6b9ee3770716be49cf7faf480fa7e53856aa9.tar
(9 KB)
📄
f6b9ee3770716be49cf7faf480fa7e53856aa9.tar.gz
(3.16 KB)
📄
f78d9cf4e8c5a9b010e162f16950daa157f058.tar
(190.5 KB)
📄
f78d9cf4e8c5a9b010e162f16950daa157f058.tar.gz
(101.3 KB)
📄
f84866c85765f17aa7e977ec585dae713c059c.tar
(13.5 KB)
📄
f84866c85765f17aa7e977ec585dae713c059c.tar.gz
(3.78 KB)
📄
f9b32bcb33145b46999706dc8595437b61d6e1.tar
(22 KB)
📄
f9b32bcb33145b46999706dc8595437b61d6e1.tar.gz
(8.66 KB)
📄
fa8c42daab96a39b42df014e1f018bc466cf9f.tar
(196 KB)
📄
fa8c42daab96a39b42df014e1f018bc466cf9f.tar.gz
(82.12 KB)
📄
fact.py.py.tar.gz
(646 B)
📄
fact.py.tar
(3 KB)
📄
factor.tar
(87.5 KB)
📄
factor.tar.gz
(46.99 KB)
📄
failed-policy.xml.tar
(2 KB)
📄
failed-policy.xml.xml.tar.gz
(277 B)
📄
faillock.tar
(22.5 KB)
📄
faillock.tar.gz
(8.1 KB)
📄
fakesdio.h.h.tar.gz
(1.15 KB)
📄
fakesdio.h.tar
(5 KB)
📄
false.tar
(35 KB)
📄
false.tar.gz
(14.45 KB)
📄
fanotify.h.h.tar.gz
(788 B)
📄
fanotify.h.tar
(3 KB)
📄
fat.mod.mod.tar.gz
(3.86 KB)
📄
fat.mod.tar
(18 KB)
📄
faultinject.tar
(2 KB)
📄
faultinject.tar.gz
(110 B)
📄
faultinject_call.tar
(2 KB)
📄
faultinject_call.tar.gz
(212 B)
📄
faveo.sql.sql.tar.gz
(19.24 KB)
📄
faveo.sql.tar
(119 KB)
📄
faveo.tar
(111.5 MB)
📄
faveo.tar.gz
(104.18 MB)
📄
faveo.zip
(111.47 MB)
📄
favicon-1.ico.ico.tar.gz
(2.5 KB)
📄
favicon-1.ico.tar
(42.5 KB)
📄
favicon-16x16.png.png.tar.gz
(276 B)
📄
favicon-16x16.png.tar
(3 KB)
📄
favicon-194x194.png.png.tar.gz
(361 B)
📄
favicon-194x194.png.tar
(4 KB)
📄
favicon-32x32.png.png.tar.gz
(278 B)
📄
favicon-32x32.png.tar
(3 KB)
📄
favicon-96x96.png.png.tar.gz
(445 B)
📄
favicon-96x96.png.tar
(3 KB)
📄
favicon.ico.ico.tar.gz
(541 B)
📄
favicon.ico.tar
(56 KB)
📄
fbintl.conf.conf.tar.gz
(1.1 KB)
📄
fbintl.conf.tar
(9 KB)
📄
fbintl.tar
(2.12 MB)
📄
fbintl.tar.gz
(822.09 KB)
📄
fc-cache-64.tar
(22 KB)
📄
fc-cache-64.tar.gz
(7.03 KB)
📄
fc-cache.tar
(2 KB)
📄
fc-cache.tar.gz
(144 B)
📄
fc-cat.tar
(18 KB)
📄
fc-cat.tar.gz
(6.12 KB)
📄
fc-conflist.tar
(14 KB)
📄
fc-conflist.tar.gz
(4.3 KB)
📄
fc-list.tar
(14 KB)
📄
fc-list.tar.gz
(5.15 KB)
📄
fc-match.tar
(18 KB)
📄
fc-match.tar.gz
(5.63 KB)
📄
fc-pattern.tar
(14 KB)
📄
fc-pattern.tar.gz
(4.85 KB)
📄
fc-query.tar
(14 KB)
📄
fc-query.tar.gz
(4.8 KB)
📄
fc-scan.tar
(14 KB)
📄
fc-scan.tar.gz
(4.82 KB)
📄
fc-validate.tar
(18 KB)
📄
fc-validate.tar.gz
(5.48 KB)
📄
fc.tar
(62.5 KB)
📄
fc.tar.gz
(15.83 KB)
📄
fc.zip
(58.95 KB)
📄
fc_els.h.h.tar.gz
(10.62 KB)
📄
fc_els.h.tar
(40.5 KB)
📄
fc_fs.h.h.tar.gz
(4.12 KB)
📄
fc_fs.h.tar
(14 KB)
📄
fc_gs.h.h.tar.gz
(1.38 KB)
📄
fc_gs.h.tar
(4.5 KB)
📄
fc_ns.h.h.tar.gz
(1.78 KB)
📄
fc_ns.h.tar
(6.5 KB)
📄
fc_wwpn_id.tar
(5 KB)
📄
fc_wwpn_id.tar.gz
(668 B)
📄
fcgi-bin.tar
(4.72 MB)
📄
fcgi-bin.tar.gz
(1.7 MB)
📄
fcgi-bin.zip
(4.72 MB)
📄
fcmp.py.py.tar.gz
(745 B)
📄
fcmp.py.tar
(3.5 KB)
📄
fcms.png.png.tar.gz
(9.18 KB)
📄
fcms.png.tar
(11 KB)
📄
fcms.tar
(239.5 KB)
📄
fcms.tar.gz
(143.99 KB)
📄
fcms.zip
(216.31 KB)
📄
fcntl-linux.h.h.tar.gz
(4.37 KB)
📄
fcntl-linux.h.tar
(15 KB)
📄
fcntl.h.h.tar.gz
(3.68 KB)
📄
fcntl.h.tar
(20.5 KB)
📄
fcntl.so.so.tar.gz
(3.05 KB)
📄
fcntl.so.tar
(17 KB)
📄
fcntl2.h.h.tar.gz
(1.36 KB)
📄
fcntl2.h.tar
(7 KB)
📄
fcprivate.h.h.tar.gz
(1.61 KB)
📄
fcprivate.h.tar
(6 KB)
📄
fdinfo.tar
(12 KB)
📄
fdinfo.tar.gz
(211 B)
📄
fdinfo.zip
(1.64 KB)
📄
fdt.lst.lst.tar.gz
(104 B)
📄
fdt.lst.tar
(2 KB)
📄
feature.h.h.tar.gz
(1.15 KB)
📄
feature.h.tar
(6.5 KB)
📄
features.h.h.tar.gz
(5 KB)
📄
features.h.tar
(17.5 KB)
📄
features.ph.ph.tar.gz
(2.18 KB)
📄
features.ph.tar
(15 KB)
📄
features.php.php.tar.gz
(3.29 KB)
📄
features.php.tar
(11 KB)
📄
feed.php.php.tar.gz
(7.93 KB)
📄
feed.php.tar
(34.5 KB)
📄
feedparser.pyc.pyc.tar.gz
(4.58 KB)
📄
feedparser.pyc.tar
(12.5 KB)
📄
feedparser.pyo.pyo.tar.gz
(4.52 KB)
📄
feedparser.pyo.tar
(12.5 KB)
📄
feng.png.png.tar.gz
(6.23 KB)
📄
feng.png.tar
(8 KB)
📄
feng.sql.sql.tar.gz
(28.13 KB)
📄
feng.sql.tar
(172 KB)
📄
feng.tar
(20.64 MB)
📄
feng.tar.gz
(18.43 MB)
📄
feng.zip
(20.62 MB)
📄
fenv.h.h.tar.gz
(1.83 KB)
📄
fenv.h.tar
(6 KB)
📄
fexists.tar
(2 KB)
📄
fexists.tar.gz
(181 B)
📄
fgrep.tar
(2 KB)
📄
fgrep.tar.gz
(119 B)
📄
fiber.so.so.tar.gz
(2.65 KB)
📄
fiber.so.tar
(9 KB)
📄
fiddle.so.so.tar.gz
(17.54 KB)
📄
fiddle.so.tar
(42.5 KB)
📄
fido_id.tar
(35 KB)
📄
fido_id.tar.gz
(6.14 KB)
📄
fieldpos.h.h.tar.gz
(2.72 KB)
📄
fieldpos.h.tar
(10.5 KB)
📄
fiji_ce.bin.bin.tar.gz
(2.96 KB)
📄
fiji_ce.bin.tar
(10.5 KB)
📄
fiji_mc.bin.bin.tar.gz
(6.29 KB)
📄
fiji_mc.bin.tar
(17.5 KB)
📄
fiji_me.bin.bin.tar.gz
(6.38 KB)
📄
fiji_me.bin.tar
(18.5 KB)
📄
fiji_mec.bin.bin.tar.gz
(26.35 KB)
📄
fiji_mec.bin.tar
(258.5 KB)
📄
fiji_mec2.bin.bin.tar.gz
(26.35 KB)
📄
fiji_mec2.bin.tar
(258.5 KB)
📄
fiji_pfp.bin.bin.tar.gz
(8.16 KB)
📄
fiji_pfp.bin.tar
(18.5 KB)
📄
fiji_rlc.bin.bin.tar.gz
(6.14 KB)
📄
fiji_rlc.bin.tar
(18 KB)
📄
fiji_sdma.bin.bin.tar.gz
(4.18 KB)
📄
fiji_sdma.bin.tar
(12 KB)
📄
fiji_sdma1.bin.bin.tar.gz
(4.17 KB)
📄
fiji_sdma1.bin.tar
(12 KB)
📄
fiji_smc.bin.bin.tar.gz
(52.95 KB)
📄
fiji_smc.bin.tar
(128.5 KB)
📄
fiji_uvd.bin.bin.tar.gz
(159.87 KB)
📄
fiji_uvd.bin.tar
(262.5 KB)
📄
fiji_vce.bin.bin.tar.gz
(97.22 KB)
📄
fiji_vce.bin.tar
(159 KB)
📄
file-max.tar
(2 KB)
📄
file-max.tar.gz
(110 B)
📄
file-nr.tar
(2 KB)
📄
file-nr.tar.gz
(118 B)
📄
file.h.h.tar.gz
(1.33 KB)
📄
file.h.tar
(7.5 KB)
📄
file.mod.mod.tar.gz
(7.47 KB)
📄
file.mod.tar
(23 KB)
📄
file.tar
(26.5 KB)
📄
file.tar.gz
(10.04 KB)
📄
file_.htaccess.htaccess.tar.gz
(340 B)
📄
file_.htaccess.tar
(3 KB)
📄
fileattrs.tar
(9 KB)
📄
fileattrs.tar.gz
(877 B)
📄
fileattrs.zip
(2.66 KB)
📄
filecmp.py.py.tar.gz
(3.01 KB)
📄
filecmp.py.tar
(32 KB)
📄
filecmp.pyc.pyc.tar.gz
(3.94 KB)
📄
filecmp.pyc.tar
(11 KB)
📄
filecmp.pyo.pyo.tar.gz
(3.94 KB)
📄
filecmp.pyo.tar
(11 KB)
📄
filefuncs.so.so.tar.gz
(14.67 KB)
📄
filefuncs.so.tar
(34.5 KB)
📄
fileindex.php.php.tar.gz
(326 B)
📄
fileindex.php.tar
(352.5 KB)
📄
fileinput.py.py.tar.gz
(3.95 KB)
📄
fileinput.py.tar
(45 KB)
📄
filemanager.php.php.tar.gz
(1.52 KB)
📄
filemanager.php.tar
(5.5 KB)
📄
fileobject.h.h.tar.gz
(745 B)
📄
fileobject.h.tar
(3.5 KB)
📄
files.tar
(199.52 MB)
📄
files.tar.gz
(38.84 MB)
📄
files.zip
(199.49 MB)
📄
filestream_centisecs.tar
(2 KB)
📄
filestream_centisecs.tar.gz
(122 B)
📄
filesystems.tar
(2 KB)
📄
filesystems.tar.gz
(271 B)
📄
fileutils.h.h.tar.gz
(1.34 KB)
📄
fileutils.h.tar
(6 KB)
📄
filter.h.h.tar.gz
(3.95 KB)
📄
filter.h.tar
(18 KB)
📄
final.target.tar
(2 KB)
📄
final.target.target.tar.gz
(416 B)
📄
find-provides.tar
(3 KB)
📄
find-provides.tar.gz
(702 B)
📄
find-requires.tar
(2.5 KB)
📄
find-requires.tar.gz
(617 B)
📄
find-uname.py.py.tar.gz
(718 B)
📄
find-uname.py.tar
(3 KB)
📄
find.py.py.tar.gz
(1.68 KB)
📄
find.py.tar
(6 KB)
📄
find.rb.rb.tar.gz
(1.14 KB)
📄
find.rb.tar
(13.5 KB)
📄
find.tar
(225 KB)
📄
find.tar.gz
(107.54 KB)
📄
findnocoding.py.py.tar.gz
(1.22 KB)
📄
findnocoding.py.tar
(4.5 KB)
📄
finger.pyc.pyc.tar.gz
(735 B)
📄
finger.pyc.tar
(3 KB)
📄
finger.pyo.pyo.tar.gz
(735 B)
📄
finger.pyo.tar
(3 KB)
📄
finger.xml.tar
(2 KB)
📄
finger.xml.xml.tar.gz
(256 B)
📄
fips.h.h.tar.gz
(2.77 KB)
📄
fips.h.tar
(11.5 KB)
📄
fips_enabled.tar
(2 KB)
📄
fips_enabled.tar.gz
(113 B)
📄
fips_name.tar
(2 KB)
📄
fips_name.tar.gz
(160 B)
📄
fips_rand.h.h.tar.gz
(2.17 KB)
📄
fips_rand.h.tar
(9 KB)
📄
fips_version.tar
(2 KB)
📄
fips_version.tar.gz
(139 B)
📄
fipscheck.tar
(3 KB)
📄
fipscheck.tar.gz
(214 B)
📄
fipscheck.zip
(462 B)
📄
firebird.service.service.tar.gz
(292 B)
📄
firebird.service.tar
(2 KB)
📄
firebird.tar
(22.44 MB)
📄
firebird.tar.gz
(8.68 MB)
📄
firebird.zip
(22.43 MB)
📄
firefly.tar
(41.3 MB)
📄
firefly.tar.gz
(36.45 MB)
📄
firefly.zip
(41.27 MB)
📄
firewalld.service.service.tar.gz
(493 B)
📄
firewalld.service.tar
(2.5 KB)
📄
firewalld.tar
(260 KB)
📄
firewalld.tar.gz
(23.19 KB)
📄
firewalld.zip
(116.12 KB)
📄
firewire.h.h.tar.gz
(3.12 KB)
📄
firewire.h.tar
(12.5 KB)
📄
firmware-5.bin.bin.tar.gz
(203.85 KB)
📄
firmware-5.bin.tar
(234.5 KB)
📄
firmware.fw.fw.tar.gz
(5.44 KB)
📄
firmware.fw.tar
(11.5 KB)
📄
firmware_config.tar
(3 KB)
📄
firmware_config.tar.gz
(128 B)
📄
firmware_config.zip
(332 B)
📄
fish.tar
(30.5 KB)
📄
fish.tar.gz
(5.54 KB)
📄
fish.zip
(18.66 KB)
📄
fix-ALTMODP-166.sh.sh.tar.gz
(439 B)
📄
fix-ALTMODP-166.sh.tar
(2.5 KB)
📄
fix_cagefs.sh.sh.tar.gz
(469 B)
📄
fix_cagefs.sh.tar
(2.5 KB)
📄
fixcid.py.py.tar.gz
(3.34 KB)
📄
fixcid.py.tar
(11.5 KB)
📄
fixdiv.py.py.tar.gz
(4.54 KB)
📄
fixdiv.py.tar
(15.5 KB)
📄
fixer_base.cpython-36.opt-2.pyc.cpython-36.opt-2.pyc.tar.gz
(1.87 KB)
📄
fixer_base.cpython-36.opt-2.pyc.tar
(5 KB)
📄
fixes.tar
(945 KB)
📄
fixes.tar.gz
(119.72 KB)
📄
fixes.zip
(729.46 KB)
📄
fixheader.py.py.tar.gz
(595 B)
📄
fixheader.py.tar
(3 KB)
📄
fixnotice.py.py.tar.gz
(1.31 KB)
📄
fixnotice.py.tar
(4.5 KB)
📄
fixps.pyc.pyc.tar.gz
(631 B)
📄
fixps.pyc.tar
(2.5 KB)
📄
fixps.pyo.pyo.tar.gz
(628 B)
📄
fixps.pyo.tar
(2.5 KB)
📄
fiyo.png.png.tar.gz
(6.13 KB)
📄
fiyo.png.tar
(8 KB)
📄
fiyo.tar
(118.5 KB)
📄
fiyo.tar.gz
(62.28 KB)
📄
fiyo.zip
(100.71 KB)
📄
flake8.tar
(2 KB)
📄
flake8.tar.gz
(234 B)
📄
flarum.sql.sql.tar.gz
(5.75 KB)
📄
flarum.sql.tar
(42 KB)
📄
flarum.tar
(14.25 MB)
📄
flarum.tar.gz
(12.28 MB)
📄
flarum.zip
(14.22 MB)
📄
flask.h.h.tar.gz
(1.26 KB)
📄
flask.h.tar
(13.5 KB)
📄
flat.png.png.tar.gz
(8.11 KB)
📄
flat.png.tar
(10 KB)
📄
flat.tar
(4.71 MB)
📄
flat.tar.gz
(4.27 MB)
📄
flat.zip
(4.68 MB)
📄
flatboard.tar
(1.78 MB)
📄
flatboard.tar.gz
(1.66 MB)
📄
flatboard.zip
(1.76 MB)
📄
flex++.tar
(430 KB)
📄
flex++.tar.gz
(148.25 KB)
📄
flex.tar
(430 KB)
📄
flex.tar.gz
(148.25 KB)
📄
floatn.h.h.tar.gz
(1.72 KB)
📄
floatn.h.tar
(6 KB)
📄
flock.tar
(35 KB)
📄
flock.tar.gz
(14.12 KB)
📄
flow_limit_cpu_bitmap.tar
(2 KB)
📄
flow_limit_cpu_bitmap.tar.gz
(130 B)
📄
flower.tar
(19.19 MB)
📄
flower.tar.gz
(8.01 MB)
📄
flower.zip
(19.18 MB)
📄
flowlabel_consistency.tar
(2 KB)
📄
flowlabel_consistency.tar.gz
(123 B)
📄
flt-eval-method.h.h.tar.gz
(702 B)
📄
flt-eval-method.h.tar
(3 KB)
📄
fluxbb.tar
(203 KB)
📄
fluxbb.tar.gz
(109.52 KB)
📄
fluxbb.zip
(175.71 KB)
📄
fmhash.so.so.tar.gz
(5.38 KB)
📄
fmhash.so.tar
(14 KB)
📄
fmhttp.so.so.tar.gz
(4.82 KB)
📄
fmhttp.so.tar
(13.5 KB)
📄
fmimage_8366.fw.fw.tar.gz
(64.1 KB)
📄
fmimage_8366.fw.tar
(96 KB)
📄
fmimage_8366_ap-1.fw.fw.tar.gz
(70.96 KB)
📄
fmimage_8366_ap-1.fw.tar
(101 KB)
📄
fmimage_8366_ap-2.fw.fw.tar.gz
(71.13 KB)
📄
fmimage_8366_ap-2.fw.tar
(101.5 KB)
📄
fmimage_8366_ap-3.fw.fw.tar.gz
(73.21 KB)
📄
fmimage_8366_ap-3.fw.tar
(105 KB)
📄
fmimage_8687.fw.fw.tar.gz
(49.15 KB)
📄
fmimage_8687.fw.tar
(73.5 KB)
📄
fmimage_8764_ap-1.fw.fw.tar.gz
(79.81 KB)
📄
fmimage_8764_ap-1.fw.tar
(120.5 KB)
📄
fmt.tar
(47 KB)
📄
fmt.tar.gz
(20.41 KB)
📄
fmtmsg.h.h.tar.gz
(1.41 KB)
📄
fmtmsg.h.tar
(5 KB)
📄
fnmatch.h.h.tar.gz
(1.22 KB)
📄
fnmatch.h.tar
(4 KB)
📄
fnmatch.py.py.tar.gz
(1.23 KB)
📄
fnmatch.py.tar
(13.5 KB)
📄
fnmatch.pyc.pyc.tar.gz
(1.8 KB)
📄
fnmatch.pyc.tar
(5.5 KB)
📄
fnmatch.pyo.pyo.tar.gz
(1.8 KB)
📄
fnmatch.pyo.tar
(5.5 KB)
📄
fnmatch.so.so.tar.gz
(4.48 KB)
📄
fnmatch.so.tar
(13.5 KB)
📄
fold.tar
(43 KB)
📄
fold.tar.gz
(18.43 KB)
📄
folderlistmodel.tar
(91 KB)
📄
folderlistmodel.tar.gz
(30.65 KB)
📄
folderlistmodel.zip
(88.28 KB)
📄
font.h.h.tar.gz
(1.74 KB)
📄
font.h.tar
(6 KB)
📄
font.mod.mod.tar.gz
(8.57 KB)
📄
font.mod.tar
(23.5 KB)
📄
font.py.py.tar.gz
(2.13 KB)
📄
font.py.tar
(8.5 KB)
📄
fontconfig-2.0.typelib.0.typelib.tar.gz
(296 B)
📄
fontconfig-2.0.typelib.tar
(2 KB)
📄
fontconfig.pc.pc.tar.gz
(340 B)
📄
fontconfig.pc.tar
(2 KB)
📄
fontconfig.tar
(180.5 KB)
📄
fontconfig.tar.gz
(14.14 KB)
📄
fontconfig.zip
(174.78 KB)
📄
fontproto.h.h.tar.gz
(1.37 KB)
📄
fontproto.h.tar
(5 KB)
📄
fonts.tar
(49 KB)
📄
fonts.tar.gz
(8.94 KB)
📄
fonts.zip
(44.78 KB)
📄
fontstruct.h.h.tar.gz
(3.02 KB)
📄
fontstruct.h.tar
(11 KB)
📄
fontutil.pc.pc.tar.gz
(235 B)
📄
fontutil.pc.tar
(2 KB)
📄
force_igmp_version.tar
(2 KB)
📄
force_igmp_version.tar.gz
(125 B)
📄
force_mld_version.tar
(3 KB)
📄
force_mld_version.tar.gz
(126 B)
📄
force_tllao.tar
(4 KB)
📄
force_tllao.tar.gz
(123 B)
📄
foreman.xml.tar
(2 KB)
📄
foreman.xml.xml.tar.gz
(302 B)
📄
fork.png.png.tar.gz
(18.09 KB)
📄
fork.png.tar
(19.5 KB)
📄
fork.so.so.tar.gz
(4.38 KB)
📄
fork.so.tar
(13.5 KB)
📄
fork.tar
(314 KB)
📄
fork.tar.gz
(196.04 KB)
📄
fork.zip
(286.79 KB)
📄
forking.py.py.tar.gz
(5.32 KB)
📄
forking.py.tar
(18.5 KB)
📄
forkserver.py.py.tar.gz
(2.74 KB)
📄
forkserver.py.tar
(23 KB)
📄
form.h.h.tar.gz
(805 B)
📄
form.h.tar
(60 KB)
📄
form.pc.pc.tar.gz
(362 B)
📄
form.pc.tar
(2 KB)
📄
forma.sql.sql.tar.gz
(115.98 KB)
📄
forma.sql.tar
(856.5 KB)
📄
forma.tar
(36.02 MB)
📄
forma.tar.gz
(33.33 MB)
📄
forma.zip
(36 MB)
📄
format.rb.rb.tar.gz
(166 B)
📄
format.rb.tar
(2 KB)
📄
formatter.py.py.tar.gz
(3.74 KB)
📄
formatter.py.tar
(47.5 KB)
📄
formatters.tar
(12 KB)
📄
formatters.tar.gz
(2.53 KB)
📄
formw.pc.pc.tar.gz
(364 B)
📄
formw.pc.tar
(2 KB)
📄
forwarding.tar
(5 KB)
📄
forwarding.tar.gz
(120 B)
📄
fp-fast.h.h.tar.gz
(730 B)
📄
fp-fast.h.tar
(3 KB)
📄
fp-logb.h.h.tar.gz
(650 B)
📄
fp-logb.h.tar
(2.5 KB)
📄
fp_install.sh.sh.tar.gz
(776 B)
📄
fp_install.sh.tar
(3.5 KB)
📄
fpformat.py.py.tar.gz
(1.66 KB)
📄
fpformat.py.tar
(6.5 KB)
📄
fpformat.pyc.pyc.tar.gz
(2.24 KB)
📄
fpformat.pyc.tar
(6.5 KB)
📄
fpformat.pyo.pyo.tar.gz
(2.24 KB)
📄
fpformat.pyo.tar
(6.5 KB)
📄
fpositer.h.h.tar.gz
(1.26 KB)
📄
fpositer.h.tar
(4.5 KB)
📄
fpu_control.h.h.tar.gz
(1.7 KB)
📄
fpu_control.h.tar
(5 KB)
📄
fr.tar
(270.5 KB)
📄
fr.tar.gz
(220.63 KB)
📄
fr.zip
(228.44 KB)
📄
fractions.py.py.tar.gz
(6.42 KB)
📄
fractions.py.tar
(72 KB)
📄
framadate.tar
(192 KB)
📄
framadate.tar.gz
(104.03 KB)
📄
framadate.zip
(168.53 KB)
📄
free.tar
(22.5 KB)
📄
free.tar.gz
(8.58 KB)
📄
freedos.mod.mod.tar.gz
(1.46 KB)
📄
freedos.mod.tar
(4.5 KB)
📄
freeipa-4.xml.tar
(2.5 KB)
📄
freeipa-4.xml.xml.tar.gz
(448 B)
📄
freeipa-ldap.xml.tar
(2 KB)
📄
freeipa-ldap.xml.xml.tar.gz
(304 B)
📄
freescout.sql.sql.tar.gz
(4.36 KB)
📄
freescout.sql.tar
(29 KB)
📄
freescout.tar
(10.75 MB)
📄
freescout.tar.gz
(9.14 MB)
📄
freescout.zip
(10.72 MB)
📄
freetds.conf.conf.tar.gz
(742 B)
📄
freetds.conf.tar
(3 KB)
📄
freetds11.tar
(1.84 MB)
📄
freetds11.tar.gz
(833.08 KB)
📄
freetds11.zip
(1.82 MB)
📄
freetype-config.tar
(6 KB)
📄
freetype-config.tar.gz
(1.45 KB)
📄
freetype2.pc.pc.tar.gz
(316 B)
📄
freetype2.pc.tar
(2 KB)
📄
freetype2.tar
(1.21 MB)
📄
freetype2.tar.gz
(184.77 KB)
📄
freetype2.zip
(1.18 MB)
📄
freeze_blacklist.tar
(2 KB)
📄
freeze_blacklist.tar.gz
(121 B)
📄
freshrss.tar
(5.3 MB)
📄
freshrss.tar.gz
(5.01 MB)
📄
freshrss.zip
(5.27 MB)
📄
from.py.py.tar.gz
(541 B)
📄
from.py.tar
(2.5 KB)
📄
front.sql.sql.tar.gz
(10.98 KB)
📄
front.sql.tar
(80.5 KB)
📄
front.tar
(2.57 MB)
📄
front.tar.gz
(2.29 MB)
📄
front.zip
(2.54 MB)
📄
frontpage.tar
(2.5 KB)
📄
frontpage.tar.gz
(129 B)
📄
frontpage.zip
(446 B)
📄
fs.lst.lst.tar.gz
(236 B)
📄
fs.lst.tar
(3 KB)
📄
fs.tcl.tar
(5.5 KB)
📄
fs.tcl.tcl.tar.gz
(1.62 KB)
📄
fscache.tar
(4.5 KB)
📄
fscache.tar.gz
(471 B)
📄
fscache.zip
(1.22 KB)
📄
fshelp.mod.mod.tar.gz
(2.16 KB)
📄
fshelp.mod.tar
(10 KB)
📄
fsmasks.h.h.tar.gz
(1.5 KB)
📄
fsmasks.h.tar
(5.5 KB)
📄
fstab.h.h.tar.gz
(1.57 KB)
📄
fstab.h.tar
(5 KB)
📄
fstrim.service.service.tar.gz
(190 B)
📄
fstrim.service.tar
(2 KB)
📄
fstrim.timer.tar
(2 KB)
📄
fstrim.timer.timer.tar.gz
(280 B)
📄
fstrm.h.h.tar.gz
(4.39 KB)
📄
fstrm.h.tar
(14.5 KB)
📄
fstrm.tar
(77 KB)
📄
fstrm.tar.gz
(14.08 KB)
📄
fstrm.zip
(71.05 KB)
📄
fsuid.h.h.tar.gz
(755 B)
📄
fsuid.h.tar
(3 KB)
📄
ftools.tar
(182.5 KB)
📄
ftools.tar.gz
(94.34 KB)
📄
ftools.zip
(156.69 KB)
📄
ftp.h.h.tar.gz
(1.6 KB)
📄
ftp.h.tar
(5 KB)
📄
ftp.pyc.pyc.tar.gz
(1.46 KB)
📄
ftp.pyc.tar
(4.5 KB)
📄
ftp.pyo.pyo.tar.gz
(1.46 KB)
📄
ftp.pyo.tar
(4.5 KB)
📄
ftp.rb.rb.tar.gz
(2.59 KB)
📄
ftp.rb.tar
(189 KB)
📄
ftp.xml.tar
(4 KB)
📄
ftp.xml.xml.tar.gz
(337 B)
📄
ftplib.py.py.tar.gz
(9.73 KB)
📄
ftplib.py.tar
(110 KB)
📄
ftplib.pyc.pyc.tar.gz
(12.82 KB)
📄
ftplib.pyc.tar
(36 KB)
📄
ftplib.pyo.pyo.tar.gz
(12.82 KB)
📄
ftplib.pyo.tar
(36 KB)
📄
ftrace_enabled.tar
(2 KB)
📄
ftrace_enabled.tar.gz
(115 B)
📄
fts.h.h.tar.gz
(2.87 KB)
📄
fts.h.tar
(10 KB)
📄
ftw.h.h.tar.gz
(1.93 KB)
📄
ftw.h.tar
(7 KB)
📄
fud.png.png.tar.gz
(16.06 KB)
📄
fud.png.tar
(17.5 KB)
📄
fud.sql.sql.tar.gz
(8 KB)
📄
fud.sql.tar
(55 KB)
📄
fud.tar
(7.27 MB)
📄
fud.tar.gz
(6.63 MB)
📄
fud.zip
(7.23 MB)
📄
fuel.png.png.tar.gz
(18.21 KB)
📄
fuel.png.tar
(20 KB)
📄
fuel.tar
(75 KB)
📄
fuel.tar.gz
(48.28 KB)
📄
fuel.zip
(65.36 KB)
📄
func.rb.rb.tar.gz
(1.9 KB)
📄
func.rb.tar
(22 KB)
📄
funcobject.h.h.tar.gz
(1.33 KB)
📄
funcobject.h.tar
(6 KB)
📄
functional_test.mod.mod.tar.gz
(11.08 KB)
📄
functional_test.mod.tar
(37 KB)
📄
functions.h.h.tar.gz
(788 B)
📄
functions.h.tar
(3.5 KB)
📄
functions.tar
(33 KB)
📄
functions.tar.gz
(4.75 KB)
📄
functools.py.py.tar.gz
(8.5 KB)
📄
functools.py.tar
(75.5 KB)
📄
funzip.tar
(38.5 KB)
📄
funzip.tar.gz
(17.92 KB)
📄
fusio.sql.sql.tar.gz
(20.84 KB)
📄
fusio.sql.tar
(165 KB)
📄
fusio.tar
(18.1 MB)
📄
fusio.tar.gz
(15.29 MB)
📄
fusio.zip
(18.08 MB)
📄
fusion.tar
(229.5 KB)
📄
fusion.tar.gz
(139.56 KB)
📄
fusion.zip
(209.83 KB)
📄
future.py.py.tar.gz
(810 B)
📄
future.py.tar
(3.5 KB)
📄
futures.go.go.tar.gz
(14.16 KB)
📄
futures.go.tar
(45.5 KB)
📄
futures.py.py.tar.gz
(3.66 KB)
📄
futures.py.tar
(31 KB)
📄
fw.h.h.tar.gz
(1008 B)
📄
fw.h.tar
(4 KB)
📄
fw_sst_0f28.bin.bin.tar.gz
(147.06 KB)
📄
fw_sst_0f28.bin.tar
(687 KB)
📄
fw_sst_0f28_ssp0.bin.bin.tar.gz
(147.07 KB)
📄
fw_sst_0f28_ssp0.bin.tar
(687 KB)
📄
fw_sst_22a8.bin.bin.tar.gz
(147.29 KB)
📄
fw_sst_22a8.bin.tar
(687 KB)
📄
fwmark_reflect.tar
(3 KB)
📄
fwmark_reflect.tar.gz
(117 B)
📄
g12a_hevc_mmu.bin.bin.tar.gz
(8.14 KB)
📄
g12a_hevc_mmu.bin.tar
(17.5 KB)
📄
g12a_vp9.bin.bin.tar.gz
(4.58 KB)
📄
g12a_vp9.bin.tar
(17.5 KB)
📄
g200_warp.fw.fw.tar.gz
(1.71 KB)
📄
g200_warp.fw.tar
(12.5 KB)
📄
g400_warp.fw.fw.tar.gz
(2.31 KB)
📄
g400_warp.fw.tar
(18 KB)
📄
ga102.tar
(97.53 MB)
📄
ga102.tar.gz
(77.78 MB)
📄
ga102.zip
(97.51 MB)
📄
galera-4.tar
(2.43 MB)
📄
galera-4.tar.gz
(1.1 MB)
📄
galera-4.zip
(2.42 MB)
📄
galera.xml.tar
(3 KB)
📄
galera.xml.xml.tar.gz
(250 B)
📄
gallery.tar
(175 KB)
📄
gallery.tar.gz
(88.18 KB)
📄
gallery.zip
(148.29 KB)
📄
gallery2.tar
(176.5 KB)
📄
gallery2.tar.gz
(99.4 KB)
📄
gallery2.zip
(157.15 KB)
📄
ganglia-client.xml.tar
(2 KB)
📄
ganglia-client.xml.xml.tar.gz
(239 B)
📄
ganglia-master.xml.tar
(2 KB)
📄
ganglia-master.xml.xml.tar.gz
(229 B)
📄
gap-buffer.go.go.tar.gz
(4.49 KB)
📄
gap-buffer.go.tar
(12 KB)
📄
garb.service.service.tar.gz
(421 B)
📄
garb.service.tar
(2 KB)
📄
gawk.tar
(850.5 KB)
📄
gawk.tar.gz
(49.94 KB)
📄
gawk.zip
(170.7 KB)
📄
gb18030.so.so.tar.gz
(4.28 KB)
📄
gb18030.so.tar
(190 KB)
📄
gb2312.so.so.tar.gz
(2.75 KB)
📄
gb2312.so.tar
(9 KB)
📄
gbdownload.sys.sys.tar.gz
(24.99 KB)
📄
gbdownload.sys.tar
(98 KB)
📄
gbk.so.so.tar.gz
(3.74 KB)
📄
gbk.so.tar
(205.5 KB)
📄
gbrcvucode.sys.sys.tar.gz
(1.37 KB)
📄
gbrcvucode.sys.tar
(4.5 KB)
📄
gc_10_3_6_ce.bin.bin.tar.gz
(5.2 KB)
📄
gc_10_3_6_ce.bin.tar
(259 KB)
📄
gc_10_3_6_me.bin.bin.tar.gz
(9.38 KB)
📄
gc_10_3_6_me.bin.tar
(259 KB)
📄
gc_10_3_6_mec2.bin.bin.tar.gz
(40.95 KB)
📄
gc_10_3_6_mec2.bin.tar
(264 KB)
📄
gc_10_3_7_ce.bin.bin.tar.gz
(5.2 KB)
📄
gc_10_3_7_ce.bin.tar
(259 KB)
📄
gc_10_3_7_me.bin.bin.tar.gz
(9.38 KB)
📄
gc_10_3_7_me.bin.tar
(259 KB)
📄
gc_10_3_7_mec2.bin.bin.tar.gz
(41.25 KB)
📄
gc_10_3_7_mec2.bin.tar
(263.5 KB)
📄
gc_11_0_0_me.bin.bin.tar.gz
(41.96 KB)
📄
gc_11_0_0_me.bin.tar
(309 KB)
📄
gc_11_0_0_mes1.bin.bin.tar.gz
(39.05 KB)
📄
gc_11_0_0_mes1.bin.tar
(215 KB)
📄
gc_11_0_0_mes_2.bin.bin.tar.gz
(58.48 KB)
📄
gc_11_0_0_mes_2.bin.tar
(253 KB)
📄
gc_11_0_0_rlc_1.bin.bin.tar.gz
(69.07 KB)
📄
gc_11_0_0_rlc_1.bin.tar
(182.5 KB)
📄
gc_11_0_1_me.bin.bin.tar.gz
(10.48 KB)
📄
gc_11_0_1_me.bin.tar
(259 KB)
📄
gc_11_0_1_mes1.bin.bin.tar.gz
(47.86 KB)
📄
gc_11_0_1_mes1.bin.tar
(229 KB)
📄
gc_11_0_1_mes_2.bin.bin.tar.gz
(58.45 KB)
📄
gc_11_0_1_mes_2.bin.tar
(253 KB)
📄
gc_11_0_2_me.bin.bin.tar.gz
(41.94 KB)
📄
gc_11_0_2_me.bin.tar
(309 KB)
📄
gc_11_0_2_mes1.bin.bin.tar.gz
(39.44 KB)
📄
gc_11_0_2_mes1.bin.tar
(215 KB)
📄
gc_11_0_2_mes_2.bin.bin.tar.gz
(58.49 KB)
📄
gc_11_0_2_mes_2.bin.tar
(253 KB)
📄
gc_11_0_3_me.bin.bin.tar.gz
(41.98 KB)
📄
gc_11_0_3_me.bin.tar
(309 KB)
📄
gc_11_0_3_mes1.bin.bin.tar.gz
(39.11 KB)
📄
gc_11_0_3_mes1.bin.tar
(215 KB)
📄
gc_11_0_3_mes_2.bin.bin.tar.gz
(58.54 KB)
📄
gc_11_0_3_mes_2.bin.tar
(505 KB)
📄
gc_11_0_4_me.bin.bin.tar.gz
(10.48 KB)
📄
gc_11_0_4_me.bin.tar
(259 KB)
📄
gc_11_0_4_mes1.bin.bin.tar.gz
(47.56 KB)
📄
gc_11_0_4_mes1.bin.tar
(228.5 KB)
📄
gc_11_0_4_mes_2.bin.bin.tar.gz
(57.88 KB)
📄
gc_11_0_4_mes_2.bin.tar
(252.5 KB)
📄
gc_11_5_0_me.bin.bin.tar.gz
(10.89 KB)
📄
gc_11_5_0_me.bin.tar
(259 KB)
📄
gc_11_5_0_mes1.bin.bin.tar.gz
(50.14 KB)
📄
gc_11_5_0_mes1.bin.tar
(232 KB)
📄
gc_11_5_0_mes_2.bin.bin.tar.gz
(58.43 KB)
📄
gc_11_5_0_mes_2.bin.tar
(253 KB)
📄
gc_11_5_1_me.bin.bin.tar.gz
(11.14 KB)
📄
gc_11_5_1_me.bin.tar
(259 KB)
📄
gc_11_5_1_mes1.bin.bin.tar.gz
(50.42 KB)
📄
gc_11_5_1_mes1.bin.tar
(232 KB)
📄
gc_11_5_1_mes_2.bin.bin.tar.gz
(58.55 KB)
📄
gc_11_5_1_mes_2.bin.tar
(253 KB)
📄
gc_11_5_2_me.bin.bin.tar.gz
(10.89 KB)
📄
gc_11_5_2_me.bin.tar
(259 KB)
📄
gc_11_5_2_mes1.bin.bin.tar.gz
(49.56 KB)
📄
gc_11_5_2_mes1.bin.tar
(231 KB)
📄
gc_11_5_2_mes_2.bin.bin.tar.gz
(58.47 KB)
📄
gc_11_5_2_mes_2.bin.tar
(253 KB)
📄
gc_11_5_3_me.bin.bin.tar.gz
(10.88 KB)
📄
gc_11_5_3_me.bin.tar
(259 KB)
📄
gc_11_5_3_mes1.bin.bin.tar.gz
(49.55 KB)
📄
gc_11_5_3_mes1.bin.tar
(231 KB)
📄
gc_11_5_3_mes_2.bin.bin.tar.gz
(58.47 KB)
📄
gc_11_5_3_mes_2.bin.tar
(253 KB)
📄
gc_12_0_0_me.bin.bin.tar.gz
(61.58 KB)
📄
gc_12_0_0_me.bin.tar
(458.5 KB)
📄
gc_12_0_0_mes1.bin.bin.tar.gz
(38.02 KB)
📄
gc_12_0_0_mes1.bin.tar
(597.5 KB)
📄
gc_12_0_0_uni_mes.bin.bin.tar.gz
(98.41 KB)
📄
gc_12_0_0_uni_mes.bin.tar
(708.5 KB)
📄
gc_12_0_1_me.bin.bin.tar.gz
(61.59 KB)
📄
gc_12_0_1_me.bin.tar
(458.5 KB)
📄
gc_12_0_1_mes1.bin.bin.tar.gz
(38.71 KB)
📄
gc_12_0_1_mes1.bin.tar
(599.5 KB)
📄
gc_12_0_1_uni_mes.bin.bin.tar.gz
(98.41 KB)
📄
gc_12_0_1_uni_mes.bin.tar
(708.5 KB)
📄
gc_9_4_3_mec.bin.bin.tar.gz
(40.95 KB)
📄
gc_9_4_3_mec.bin.tar
(264 KB)
📄
gc_9_4_3_rlc.bin.bin.tar.gz
(13.73 KB)
📄
gc_9_4_3_rlc.bin.tar
(39.5 KB)
📄
gc_9_4_4_mec.bin.bin.tar.gz
(40.95 KB)
📄
gc_9_4_4_mec.bin.tar
(264 KB)
📄
gc_9_4_4_rlc.bin.bin.tar.gz
(14.95 KB)
📄
gc_9_4_4_rlc.bin.tar
(44 KB)
📄
gc_9_5_0_mec.bin.bin.tar.gz
(39.81 KB)
📄
gc_9_5_0_mec.bin.tar
(264 KB)
📄
gc_9_5_0_rlc.bin.bin.tar.gz
(14.79 KB)
📄
gc_9_5_0_rlc.bin.tar
(39.5 KB)
📄
gc_delay.tar
(2 KB)
📄
gc_delay.tar.gz
(113 B)
📄
gc_min_interval.tar
(3 KB)
📄
gc_min_interval.tar.gz
(122 B)
📄
gc_min_interval_ms.tar
(3 KB)
📄
gc_min_interval_ms.tar.gz
(126 B)
📄
gc_stale_time.tar
(7 KB)
📄
gc_stale_time.tar.gz
(126 B)
📄
gc_thresh.tar
(3 KB)
📄
gc_thresh.tar.gz
(118 B)
📄
gc_thresh1.tar
(3 KB)
📄
gc_thresh1.tar.gz
(125 B)
📄
gc_thresh2.tar
(3 KB)
📄
gc_thresh2.tar.gz
(126 B)
📄
gc_thresh3.tar
(3 KB)
📄
gc_thresh3.tar.gz
(127 B)
📄
gc_timeout.tar
(3 KB)
📄
gc_timeout.tar.gz
(119 B)
📄
gcc-ar.tar
(38.5 KB)
📄
gcc-ar.tar.gz
(18.33 KB)
📄
gcc-nm.tar
(38.5 KB)
📄
gcc-nm.tar.gz
(18.31 KB)
📄
gcc-ranlib.tar
(38.5 KB)
📄
gcc-ranlib.tar.gz
(18.3 KB)
📄
gcc.tar
(82.24 MB)
📄
gcc.tar.gz
(35.92 MB)
📄
gcc.zip
(82.23 MB)
📄
gconv-modules.cache.cache.tar.gz
(11.13 KB)
📄
gconv-modules.cache.tar
(28 KB)
📄
gconv-modules.d.tar
(54.5 KB)
📄
gconv-modules.d.tar.gz
(8.83 KB)
📄
gconv-modules.d.zip
(52.89 KB)
📄
gconv-modules.tar
(5.5 KB)
📄
gconv-modules.tar.gz
(1.27 KB)
📄
gconv.h.h.tar.gz
(1.84 KB)
📄
gconv.h.tar
(6 KB)
📄
gconv.tar
(6.45 MB)
📄
gconv.tar.gz
(2.84 MB)
📄
gconv.zip
(6.3 MB)
📄
gcov-dump.tar
(572.5 KB)
📄
gcov-dump.tar.gz
(297.58 KB)
📄
gcov-tool.tar
(609.5 KB)
📄
gcov-tool.tar.gz
(317.91 KB)
📄
gcov.tar
(1.32 MB)
📄
gcov.tar.gz
(594.58 KB)
📄
gcrt1.o.o.tar.gz
(2.82 KB)
📄
gcrt1.o.tar
(22.5 KB)
📄
gcry_arcfour.mod.mod.tar.gz
(1.13 KB)
📄
gcry_arcfour.mod.tar
(4 KB)
📄
gcry_blowfish.mod.mod.tar.gz
(5.78 KB)
📄
gcry_blowfish.mod.tar
(13.5 KB)
📄
gcry_camellia.mod.mod.tar.gz
(10.94 KB)
📄
gcry_camellia.mod.tar
(52.5 KB)
📄
gcry_cast5.mod.mod.tar.gz
(11 KB)
📄
gcry_cast5.mod.tar
(22 KB)
📄
gcry_crc.mod.mod.tar.gz
(8.87 KB)
📄
gcry_crc.mod.tar
(12.5 KB)
📄
gcry_des.mod.mod.tar.gz
(4.34 KB)
📄
gcry_des.mod.tar
(25.5 KB)
📄
gcry_dsa.mod.mod.tar.gz
(1.19 KB)
📄
gcry_dsa.mod.tar
(4.5 KB)
📄
gcry_idea.mod.mod.tar.gz
(1.87 KB)
📄
gcry_idea.mod.tar
(11 KB)
📄
gcry_md4.mod.mod.tar.gz
(1.73 KB)
📄
gcry_md4.mod.tar
(6 KB)
📄
gcry_md5.mod.mod.tar.gz
(2.3 KB)
📄
gcry_md5.mod.tar
(7 KB)
📄
gcry_rfc2268.mod.mod.tar.gz
(1.75 KB)
📄
gcry_rfc2268.mod.tar
(5.5 KB)
📄
gcry_rijndael.mod.mod.tar.gz
(12.15 KB)
📄
gcry_rijndael.mod.tar
(23 KB)
📄
gcry_rmd160.mod.mod.tar.gz
(3.81 KB)
📄
gcry_rmd160.mod.tar
(15 KB)
📄
gcry_rsa.mod.mod.tar.gz
(1.1 KB)
📄
gcry_rsa.mod.tar
(4 KB)
📄
gcry_seed.mod.mod.tar.gz
(5.73 KB)
📄
gcry_seed.mod.tar
(41 KB)
📄
gcry_serpent.mod.mod.tar.gz
(14.11 KB)
📄
gcry_serpent.mod.tar
(63.5 KB)
📄
gcry_sha1.mod.mod.tar.gz
(3.33 KB)
📄
gcry_sha1.mod.tar
(22 KB)
📄
gcry_sha256.mod.mod.tar.gz
(2.42 KB)
📄
gcry_sha256.mod.tar
(7 KB)
📄
gcry_sha512.mod.mod.tar.gz
(3.84 KB)
📄
gcry_sha512.mod.tar
(11 KB)
📄
gcry_tiger.mod.mod.tar.gz
(11.05 KB)
📄
gcry_tiger.mod.tar
(16.5 KB)
📄
gcry_twofish.mod.mod.tar.gz
(12.28 KB)
📄
gcry_twofish.mod.tar
(54 KB)
📄
gcry_whirlpool.mod.mod.tar.gz
(12.67 KB)
📄
gcry_whirlpool.mod.tar
(35 KB)
📄
gcrypt.h.h.tar.gz
(17.53 KB)
📄
gcrypt.h.tar
(70.5 KB)
📄
gcrypt.tar
(2 KB)
📄
gcrypt.tar.gz
(209 B)
📄
gcrypt.zip
(313 B)
📄
gd.h.h.tar.gz
(15.72 KB)
📄
gd.h.tar
(58 KB)
📄
gd_color_map.h.h.tar.gz
(350 B)
📄
gd_color_map.h.tar
(2 KB)
📄
gd_errors.h.h.tar.gz
(691 B)
📄
gd_errors.h.tar
(3 KB)
📄
gd_io.h.h.tar.gz
(1.19 KB)
📄
gd_io.h.tar
(5 KB)
📄
gdb-bt.tar
(2 KB)
📄
gdb-bt.tar.gz
(136 B)
📄
gdb.mod.mod.tar.gz
(5.9 KB)
📄
gdb.mod.tar
(55 KB)
📄
gdb.tar
(13.5 KB)
📄
gdb.tar.gz
(3.77 KB)
📄
gdb.zip
(11.96 KB)
📄
gdb_grub.tar
(3.5 KB)
📄
gdb_grub.tar.gz
(939 B)
📄
gdbm.h.h.tar.gz
(3.52 KB)
📄
gdbm.h.tar
(23 KB)
📄
gdbm.so.so.tar.gz
(11.41 KB)
📄
gdbm.so.tar
(29.5 KB)
📄
gdcache.h.h.tar.gz
(1.07 KB)
📄
gdcache.h.tar
(4.5 KB)
📄
gdfontg.h.h.tar.gz
(478 B)
📄
gdfontg.h.tar
(2.5 KB)
📄
gdfontl.h.h.tar.gz
(476 B)
📄
gdfontl.h.tar
(2.5 KB)
📄
gdfontmb.h.h.tar.gz
(456 B)
📄
gdfontmb.h.tar
(2.5 KB)
📄
gdfonts.h.h.tar.gz
(456 B)
📄
gdfonts.h.tar
(2.5 KB)
📄
gdfontt.h.h.tar.gz
(476 B)
📄
gdfontt.h.tar
(2.5 KB)
📄
gdfx.h.h.tar.gz
(338 B)
📄
gdfx.h.tar
(2 KB)
📄
gdk-pixbuf-2.0.tar
(480.5 KB)
📄
gdk-pixbuf-2.0.tar.gz
(170 KB)
📄
gdk-pixbuf-2.0.zip
(470.43 KB)
📄
gdlib.pc.pc.tar.gz
(293 B)
📄
gdlib.pc.tar
(2 KB)
📄
gdpp.h.h.tar.gz
(7.71 KB)
📄
gdpp.h.tar
(52.5 KB)
📄
ge.h.h.tar.gz
(950 B)
📄
ge.h.tar
(4.5 KB)
📄
gedview.tar
(173.5 KB)
📄
gedview.tar.gz
(95.89 KB)
📄
gedview.zip
(154.29 KB)
📄
geeklog.rss.rss.tar.gz
(920 B)
📄
geeklog.rss.tar
(3.5 KB)
📄
geeklog.tar.gz
(247.21 KB)
📄
geli.mod.mod.tar.gz
(3.45 KB)
📄
geli.mod.tar
(9 KB)
📄
gem.tar
(23.5 KB)
📄
gem.tar.gz
(417 B)
📄
gems.tar
(7.31 MB)
📄
gems.tar.gz
(227.47 KB)
📄
gems.zip
(7.02 MB)
📄
gen-changelog.tar
(2 KB)
📄
gen-changelog.tar.gz
(368 B)
📄
gen-enc-table.tar
(10.5 KB)
📄
gen-enc-table.tar.gz
(4.04 KB)
📄
gen70500_gmu.bin.bin.tar.gz
(53.11 KB)
📄
gen70500_gmu.bin.tar
(81 KB)
📄
gen70500_sqe.fw.fw.tar.gz
(36.83 KB)
📄
gen70500_sqe.fw.tar
(77.5 KB)
📄
gen70900_aqe.fw.fw.tar.gz
(15.37 KB)
📄
gen70900_aqe.fw.tar
(34 KB)
📄
gen70900_sqe.fw.fw.tar.gz
(40.63 KB)
📄
gen70900_sqe.fw.tar
(85 KB)
📄
gen71500_gmu.bin.bin.tar.gz
(52.88 KB)
📄
gen71500_gmu.bin.tar
(80 KB)
📄
gen71500_sqe.fw.fw.tar.gz
(34.11 KB)
📄
gen71500_sqe.fw.tar
(67.5 KB)
📄
gen80000_aqe.fw.fw.tar.gz
(11.76 KB)
📄
gen80000_aqe.fw.tar
(26 KB)
📄
gen80000_gmu.bin.bin.tar.gz
(56.8 KB)
📄
gen80000_gmu.bin.tar
(88.5 KB)
📄
gen80000_sqe.fw.fw.tar.gz
(53.31 KB)
📄
gen80000_sqe.fw.tar
(110.5 KB)
📄
gen80200_aqe.fw.fw.tar.gz
(12.24 KB)
📄
gen80200_aqe.fw.tar
(27 KB)
📄
gen80200_gmu.bin.bin.tar.gz
(69.88 KB)
📄
gen80200_gmu.bin.tar
(107.5 KB)
📄
gen80200_sqe.fw.fw.tar.gz
(57.19 KB)
📄
gen80200_sqe.fw.tar
(117 KB)
📄
gen_app.php.php.tar.gz
(274 B)
📄
gen_app.php.tar
(3 KB)
📄
gen_totp_key.php.php.tar.gz
(668 B)
📄
gen_totp_key.php.tar
(3 KB)
📄
gencat.tar
(26.5 KB)
📄
gencat.tar.gz
(11.77 KB)
📄
gender.h.h.tar.gz
(1.23 KB)
📄
gender.h.tar
(5 KB)
📄
general.php.php.tar.gz
(3.23 KB)
📄
general.php.tar
(12 KB)
📄
generated.yaml.tar
(3 KB)
📄
generated.yaml.yaml.tar.gz
(536 B)
📄
generated.yml.tar
(2.5 KB)
📄
generated.yml.yml.tar.gz
(490 B)
📄
generator.py.py.tar.gz
(6.31 KB)
📄
generator.py.tar
(57.5 KB)
📄
generic.tar
(429.5 KB)
📄
generic.tar.gz
(175.73 KB)
📄
generic.zip
(424.29 KB)
📄
genericpath.py.py.tar.gz
(1.88 KB)
📄
genericpath.py.tar
(16 KB)
📄
genericpath.pyc.pyc.tar.gz
(1.49 KB)
📄
genericpath.pyc.tar
(5 KB)
📄
genericpath.pyo.pyo.tar.gz
(1.49 KB)
📄
genericpath.pyo.tar
(5 KB)
📄
genix.tar
(128 KB)
📄
genix.tar.gz
(75.11 KB)
📄
genix.zip
(111.83 KB)
📄
genobject.h.h.tar.gz
(1.16 KB)
📄
genobject.h.tar
(5.5 KB)
📄
genrandom.tar
(14 KB)
📄
genrandom.tar.gz
(4.72 KB)
📄
geode-linux.tar
(4.5 KB)
📄
geode-linux.tar.gz
(1.2 KB)
📄
geode-linux.zip
(3.11 KB)
📄
geoiplookup.tar
(23.5 KB)
📄
geoiplookup.tar.gz
(6.6 KB)
📄
geoiplookup6.tar
(23.5 KB)
📄
geoiplookup6.tar.gz
(5.4 KB)
📄
geqn.tar
(234 KB)
📄
geqn.tar.gz
(80.23 KB)
📄
get.tar
(4 KB)
📄
get.tar.gz
(754 B)
📄
get_cur_ppage.inc.inc.tar.gz
(719 B)
📄
get_cur_ppage.inc.tar
(3 KB)
📄
get_gprof.tar
(3.5 KB)
📄
get_gprof.tar.gz
(1.04 KB)
📄
get_objgraph.tar
(3.5 KB)
📄
get_objgraph.tar.gz
(937 B)
📄
getconf.tar
(133 KB)
📄
getconf.tar.gz
(30.08 KB)
📄
getconf.zip
(97.84 KB)
📄
getdata.php.php.tar.gz
(502 B)
📄
getdata.php.tar
(3 KB)
📄
getent.tar
(35 KB)
📄
getent.tar.gz
(11.93 KB)
📄
getkey.php.php.tar.gz
(343 B)
📄
getkey.php.tar
(2 KB)
📄
getopt.h.h.tar.gz
(863 B)
📄
getopt.h.tar
(3 KB)
📄
getopt.py.py.tar.gz
(2.63 KB)
📄
getopt.py.tar
(25 KB)
📄
getopt.pyc.pyc.tar.gz
(3.04 KB)
📄
getopt.pyc.tar
(8 KB)
📄
getopt.pyo.pyo.tar.gz
(3.02 KB)
📄
getopt.pyo.tar
(8 KB)
📄
getopt.tar
(22.5 KB)
📄
getopt.tar.gz
(7.54 KB)
📄
getopt_core.h.h.tar.gz
(1.77 KB)
📄
getopt_core.h.tar
(5.5 KB)
📄
getopt_ext.h.h.tar.gz
(1.43 KB)
📄
getopt_ext.h.tar
(4.5 KB)
📄
getopt_posix.h.h.tar.gz
(1022 B)
📄
getopt_posix.h.tar
(3.5 KB)
📄
getoptlong.rb.rb.tar.gz
(4.54 KB)
📄
getoptlong.rb.tar
(17 KB)
📄
getpass.py.py.tar.gz
(2.2 KB)
📄
getpass.py.tar
(20 KB)
📄
getpass.pyc.pyc.tar.gz
(2.37 KB)
📄
getpass.pyc.tar
(6.5 KB)
📄
getpass.pyo.pyo.tar.gz
(2.37 KB)
📄
getpass.pyo.tar
(6.5 KB)
📄
gettest.php.php.tar.gz
(5.04 KB)
📄
gettest.php.tar
(19 KB)
📄
gettext-po.h.h.tar.gz
(3.94 KB)
📄
gettext-po.h.tar
(17 KB)
📄
gettext.mod.mod.tar.gz
(2.68 KB)
📄
gettext.mod.tar
(8 KB)
📄
gettext.py.py.tar.gz
(6.34 KB)
📄
gettext.py.tar
(73.5 KB)
📄
gettext.pyc.pyc.tar.gz
(6.92 KB)
📄
gettext.pyc.tar
(19.5 KB)
📄
gettext.pyo.pyo.tar.gz
(6.92 KB)
📄
gettext.pyo.tar
(19.5 KB)
📄
gettext.tar
(87.5 KB)
📄
gettext.tar.gz
(26.1 KB)
📄
gettext.zip
(82.74 KB)
📄
getty-pre.target.tar
(3 KB)
📄
getty-pre.target.target.tar.gz
(430 B)
📄
getty.target.tar
(3 KB)
📄
getty.target.target.tar.gz
(422 B)
📄
getty@.service.service.tar.gz
(1.17 KB)
📄
getty@.service.tar
(3.5 KB)
📄
getuid.php.php.tar.gz
(357 B)
📄
getuid.php.tar
(2 KB)
📄
gfecatvj.tar
(5 KB)
📄
gfecatvj.tar.gz
(1.6 KB)
📄
gfects.com.tar
(31.98 MB)
📄
gfects.com.tar.gz
(16.13 MB)
📄
gfects.com.zip
(31.58 MB)
📄
gfects.iml.iml.tar.gz
(296 B)
📄
gfects.iml.tar
(2 KB)
📄
gfx.li.tar
(119.5 KB)
📄
gfx.li.tar.gz
(19.44 KB)
📄
gfx.li.zip
(74.94 KB)
📄
gfxmenu.mod.mod.tar.gz
(20.22 KB)
📄
gfxmenu.mod.tar
(57 KB)
📄
gfxterm.mod.mod.tar.gz
(4.99 KB)
📄
gfxterm.mod.tar
(14 KB)
📄
gfxterm_background.mod.mod.tar.gz
(1.39 KB)
📄
gfxterm_background.mod.tar
(5 KB)
📄
gfxterm_menu.mod.mod.tar.gz
(2.29 KB)
📄
gfxterm_menu.mod.tar
(7 KB)
📄
ghostscript.tar
(14 KB)
📄
ghostscript.tar.gz
(3.96 KB)
📄
gibbon.sql.sql.tar.gz
(80.35 KB)
📄
gibbon.sql.tar
(456 KB)
📄
gibbon.tar
(117.42 MB)
📄
gibbon.tar.gz
(105.48 MB)
📄
gibbon.zip
(117.39 MB)
📄
gid_map.tar
(12 KB)
📄
gid_map.tar.gz
(120 B)
📄
girepository-1.0.tar
(2.81 MB)
📄
girepository-1.0.tar.gz
(828.05 KB)
📄
girepository-1.0.zip
(2.77 MB)
📄
git-add.tar
(3.67 MB)
📄
git-add.tar.gz
(1.83 MB)
📄
git-am.tar
(3.67 MB)
📄
git-am.tar.gz
(1.83 MB)
📄
git-annotate.tar
(3.67 MB)
📄
git-annotate.tar.gz
(1.83 MB)
📄
git-apply.tar
(3.67 MB)
📄
git-apply.tar.gz
(1.83 MB)
📄
git-bisect.tar
(3.67 MB)
📄
git-bisect.tar.gz
(1.83 MB)
📄
git-blame.tar
(3.67 MB)
📄
git-blame.tar.gz
(1.83 MB)
📄
git-branch.tar
(3.67 MB)
📄
git-branch.tar.gz
(1.83 MB)
📄
git-bugreport.tar
(3.67 MB)
📄
git-bugreport.tar.gz
(1.83 MB)
📄
git-bundle.tar
(3.67 MB)
📄
git-bundle.tar.gz
(1.83 MB)
📄
git-cat-file.tar
(3.67 MB)
📄
git-cat-file.tar.gz
(1.83 MB)
📄
git-checkout-index.tar
(3.67 MB)
📄
git-checkout-index.tar.gz
(1.83 MB)
📄
git-checkout.tar
(3.67 MB)
📄
git-checkout.tar.gz
(1.83 MB)
📄
git-cherry-pick.tar
(3.67 MB)
📄
git-cherry-pick.tar.gz
(1.83 MB)
📄
git-cherry.tar
(3.67 MB)
📄
git-cherry.tar.gz
(1.83 MB)
📄
git-clone.tar
(3.67 MB)
📄
git-clone.tar.gz
(1.83 MB)
📄
git-column.tar
(3.67 MB)
📄
git-column.tar.gz
(1.83 MB)
📄
git-commit-tree.tar
(3.67 MB)
📄
git-commit-tree.tar.gz
(1.83 MB)
📄
git-commit.tar
(3.67 MB)
📄
git-commit.tar.gz
(1.83 MB)
📄
git-config.tar
(3.67 MB)
📄
git-config.tar.gz
(1.83 MB)
📄
git-contacts.tar
(6 KB)
📄
git-contacts.tar.gz
(1.81 KB)
📄
git-describe.tar
(3.67 MB)
📄
git-describe.tar.gz
(1.83 MB)
📄
git-diagnose.tar
(3.67 MB)
📄
git-diagnose.tar.gz
(1.83 MB)
📄
git-diff-tree.tar
(3.67 MB)
📄
git-diff-tree.tar.gz
(1.83 MB)
📄
git-difftool.tar
(3.67 MB)
📄
git-difftool.tar.gz
(1.83 MB)
📄
git-fast-export.tar
(3.67 MB)
📄
git-fast-export.tar.gz
(1.83 MB)
📄
git-fast-import.tar
(3.67 MB)
📄
git-fast-import.tar.gz
(1.83 MB)
📄
git-fetch.tar
(3.67 MB)
📄
git-fetch.tar.gz
(1.83 MB)
📄
git-gc.tar
(3.67 MB)
📄
git-gc.tar.gz
(1.83 MB)
📄
git-hash-object.tar
(3.67 MB)
📄
git-hash-object.tar.gz
(1.83 MB)
📄
git-http-push.tar
(2.19 MB)
📄
git-http-push.tar.gz
(1.12 MB)
📄
git-imap-send.tar
(2.19 MB)
📄
git-imap-send.tar.gz
(1.12 MB)
📄
git-log.tar
(3.67 MB)
📄
git-log.tar.gz
(1.83 MB)
📄
git-ls-files.tar
(3.67 MB)
📄
git-ls-files.tar.gz
(1.83 MB)
📄
git-ls-remote.tar
(3.67 MB)
📄
git-ls-remote.tar.gz
(1.83 MB)
📄
git-mailinfo.tar
(3.67 MB)
📄
git-mailinfo.tar.gz
(1.83 MB)
📄
git-mailsplit.tar
(3.67 MB)
📄
git-mailsplit.tar.gz
(1.83 MB)
📄
git-maintenance.tar
(3.67 MB)
📄
git-maintenance.tar.gz
(1.83 MB)
📄
git-merge-index.tar
(3.67 MB)
📄
git-merge-index.tar.gz
(1.83 MB)
📄
git-merge.tar
(3.67 MB)
📄
git-merge.tar.gz
(1.83 MB)
📄
git-mergetool.tar
(13 KB)
📄
git-mergetool.tar.gz
(3.56 KB)
📄
git-mktag.tar
(3.67 MB)
📄
git-mktag.tar.gz
(1.83 MB)
📄
git-mktree.tar
(3.67 MB)
📄
git-mktree.tar.gz
(1.83 MB)
📄
git-mv.tar
(3.67 MB)
📄
git-mv.tar.gz
(1.83 MB)
📄
git-name-rev.tar
(3.67 MB)
📄
git-name-rev.tar.gz
(1.83 MB)
📄
git-notes.tar
(3.67 MB)
📄
git-notes.tar.gz
(1.83 MB)
📄
git-pack-refs.tar
(3.67 MB)
📄
git-pack-refs.tar.gz
(1.83 MB)
📄
git-patch-id.tar
(3.67 MB)
📄
git-patch-id.tar.gz
(1.83 MB)
📄
git-prune.tar
(3.67 MB)
📄
git-prune.tar.gz
(1.83 MB)
📄
git-quiltimport.tar
(5.5 KB)
📄
git-quiltimport.tar.gz
(1.46 KB)
📄
git-read-tree.tar
(3.67 MB)
📄
git-read-tree.tar.gz
(1.83 MB)
📄
git-rebase.tar
(3.67 MB)
📄
git-rebase.tar.gz
(1.83 MB)
📄
git-receive-pack.tar
(3.67 MB)
📄
git-receive-pack.tar.gz
(1.83 MB)
📄
git-reflog.tar
(3.67 MB)
📄
git-reflog.tar.gz
(1.83 MB)
📄
git-remote-fd.tar
(3.67 MB)
📄
git-remote-fd.tar.gz
(1.83 MB)
📄
git-remote-ftps.tar
(2.19 MB)
📄
git-remote-ftps.tar.gz
(1.12 MB)
📄
git-remote-http.tar
(2.19 MB)
📄
git-remote-http.tar.gz
(1.12 MB)
📄
git-remote.tar
(3.67 MB)
📄
git-remote.tar.gz
(1.83 MB)
📄
git-repack.tar
(3.67 MB)
📄
git-repack.tar.gz
(1.83 MB)
📄
git-rerere.tar
(3.67 MB)
📄
git-rerere.tar.gz
(1.83 MB)
📄
git-reset.tar
(3.67 MB)
📄
git-reset.tar.gz
(1.83 MB)
📄
git-rev-list.tar
(3.67 MB)
📄
git-rev-list.tar.gz
(1.83 MB)
📄
git-rev-parse.tar
(3.67 MB)
📄
git-rev-parse.tar.gz
(1.83 MB)
📄
git-revert.tar
(3.67 MB)
📄
git-revert.tar.gz
(1.83 MB)
📄
git-rm.tar
(3.67 MB)
📄
git-rm.tar.gz
(1.83 MB)
📄
git-send-pack.tar
(3.67 MB)
📄
git-send-pack.tar.gz
(1.83 MB)
📄
git-sh-setup.tar
(10 KB)
📄
git-sh-setup.tar.gz
(3.49 KB)
📄
git-shell.tar
(4.27 MB)
📄
git-shell.tar.gz
(1.09 MB)
📄
git-shortlog.tar
(3.67 MB)
📄
git-shortlog.tar.gz
(1.83 MB)
📄
git-show-branch.tar
(3.67 MB)
📄
git-show-branch.tar.gz
(1.83 MB)
📄
git-show-ref.tar
(3.67 MB)
📄
git-show-ref.tar.gz
(1.83 MB)
📄
git-stage.tar
(3.67 MB)
📄
git-stage.tar.gz
(1.83 MB)
📄
git-stash.tar
(3.67 MB)
📄
git-stash.tar.gz
(1.83 MB)
📄
git-status.tar
(3.67 MB)
📄
git-status.tar.gz
(1.83 MB)
📄
git-submodule.tar
(12 KB)
📄
git-submodule.tar.gz
(2.85 KB)
📄
git-switch.tar
(3.67 MB)
📄
git-switch.tar.gz
(1.83 MB)
📄
git-tag.tar
(3.67 MB)
📄
git-tag.tar.gz
(1.83 MB)
📄
git-unpack-file.tar
(3.67 MB)
📄
git-unpack-file.tar.gz
(1.83 MB)
📄
git-upload-archive.tar
(3.67 MB)
📄
git-upload-archive.tar.gz
(1.83 MB)
📄
git-upload-pack.tar
(7.34 MB)
📄
git-upload-pack.tar.gz
(1.83 MB)
📄
git-var.tar
(3.67 MB)
📄
git-var.tar.gz
(1.83 MB)
📄
git-verify-pack.tar
(3.67 MB)
📄
git-verify-pack.tar.gz
(1.83 MB)
📄
git-web--browse.tar
(6 KB)
📄
git-web--browse.tar.gz
(1.79 KB)
📄
git-whatchanged.tar
(3.67 MB)
📄
git-whatchanged.tar.gz
(1.83 MB)
📄
git-worktree.tar
(3.67 MB)
📄
git-worktree.tar.gz
(1.83 MB)
📄
git.tar
(7.34 MB)
📄
git.tar.gz
(1.83 MB)
📄
git.xml.tar
(3 KB)
📄
git.xml.xml.tar.gz
(255 B)
📄
git_version.h.h.tar.gz
(274 B)
📄
git_version.h.tar
(2 KB)
📄
gk20a.tar
(55.5 KB)
📄
gk20a.tar.gz
(20.08 KB)
📄
gk20a.zip
(50.01 KB)
📄
glk_guc_32.0.3.bin.0.3.bin.tar.gz
(81.63 KB)
📄
glk_guc_32.0.3.bin.tar
(174 KB)
📄
glk_guc_33.0.0.bin.0.0.bin.tar.gz
(83.98 KB)
📄
glk_guc_33.0.0.bin.tar
(180 KB)
📄
glk_guc_49.0.1.bin.0.1.bin.tar.gz
(85.72 KB)
📄
glk_guc_49.0.1.bin.tar
(194 KB)
📄
glk_guc_62.0.0.bin.0.0.bin.tar.gz
(90.86 KB)
📄
glk_guc_62.0.0.bin.tar
(197 KB)
📄
glk_guc_69.0.3.bin.0.3.bin.tar.gz
(101.82 KB)
📄
glk_guc_69.0.3.bin.tar
(214 KB)
📄
glk_guc_70.1.1.bin.1.1.bin.tar.gz
(93.19 KB)
📄
glk_guc_70.1.1.bin.tar
(203.5 KB)
📄
glk_huc_4.0.0.bin.0.0.bin.tar.gz
(80.18 KB)
📄
glk_huc_4.0.0.bin.tar
(222.5 KB)
📄
glob.h.h.tar.gz
(2.33 KB)
📄
glob.h.tar
(8 KB)
📄
glob.py.py.tar.gz
(1.73 KB)
📄
glob.py.tar
(18 KB)
📄
glob.pyc.pyc.tar.gz
(1.39 KB)
📄
glob.pyc.tar
(4.5 KB)
📄
glob.pyo.pyo.tar.gz
(1.39 KB)
📄
glob.pyo.tar
(4.5 KB)
📄
global.php.php.tar.gz
(229 B)
📄
global.php.tar
(3 KB)
📄
glpi.png.png.tar.gz
(3.97 KB)
📄
glpi.png.tar
(6 KB)
📄
glpi.sql.sql.tar.gz
(95.53 KB)
📄
glpi.sql.tar
(844.5 KB)
📄
glpi.tar
(94.34 MB)
📄
glpi.tar.gz
(90.34 MB)
📄
glpi.zip
(94.31 MB)
📄
glpicrypt.key.key.tar.gz
(122 B)
📄
glpicrypt.key.tar
(2 KB)
📄
glx.h.h.tar.gz
(15.9 KB)
📄
glx.h.tar
(248.5 KB)
📄
gm.tar
(9.5 KB)
📄
gm.tar.gz
(3.2 KB)
📄
gm200.tar
(80 KB)
📄
gm200.tar.gz
(28.41 KB)
📄
gm200.zip
(69.75 KB)
📄
gmake.tar
(237 KB)
📄
gmake.tar.gz
(116.09 KB)
📄
gmodule.pl.pl.tar.gz
(499 B)
📄
gmodule.pl.tar
(4 KB)
📄
gmon.h.h.tar.gz
(2.79 KB)
📄
gmon.h.tar
(8 KB)
📄
gmon_out.h.h.tar.gz
(1.33 KB)
📄
gmon_out.h.tar
(4.5 KB)
📄
gmu_gen70000.bin.bin.tar.gz
(36.85 KB)
📄
gmu_gen70000.bin.tar
(57.5 KB)
📄
gmu_gen70200.bin.bin.tar.gz
(43.28 KB)
📄
gmu_gen70200.bin.tar
(67 KB)
📄
gmu_gen70900.bin.bin.tar.gz
(50.26 KB)
📄
gmu_gen70900.bin.tar
(78.5 KB)
📄
gneqn.tar
(2.5 KB)
📄
gneqn.tar.gz
(651 B)
📄
gnroff.tar
(5 KB)
📄
gnroff.tar.gz
(1.6 KB)
📄
gntalloc.h.h.tar.gz
(1.17 KB)
📄
gntalloc.h.tar
(4.5 KB)
📄
gntdev.h.h.tar.gz
(2.95 KB)
📄
gntdev.h.tar
(9 KB)
📄
gnu-versions.h.h.tar.gz
(1.15 KB)
📄
gnu-versions.h.tar
(4 KB)
📄
gnu.png.png.tar.gz
(2.82 KB)
📄
gnu.png.tar
(5 KB)
📄
gnu.py.py.tar.gz
(167 B)
📄
gnu.py.tar
(3 KB)
📄
gnu.tar
(140.5 KB)
📄
gnu.tar.gz
(67.07 KB)
📄
gnu.zip
(116.92 KB)
📄
gnumake.h.h.tar.gz
(1.43 KB)
📄
gnumake.h.tar
(4.5 KB)
📄
go7007.tar
(193.5 KB)
📄
go7007.tar.gz
(57.56 KB)
📄
go7007.zip
(187.26 KB)
📄
go7007fw.bin.bin.tar.gz
(10.42 KB)
📄
go7007fw.bin.tar
(32 KB)
📄
go7007tv.bin.bin.tar.gz
(27.18 KB)
📄
go7007tv.bin.tar
(123.5 KB)
📄
goffice6.tar
(243 KB)
📄
goffice6.tar.gz
(138.18 KB)
📄
goffice6.zip
(217.1 KB)
📄
goffice62.tar
(177.8 MB)
📄
goffice62.tar.gz
(172.82 MB)
📄
goffice62.zip
(177.77 MB)
📄
goffice67.sql.sql.tar.gz
(26.46 KB)
📄
goffice67.sql.tar
(157 KB)
📄
goffice67.tar
(99.64 MB)
📄
goffice67.tar.gz
(96.13 MB)
📄
goffice67.zip
(99.6 MB)
📄
goods.php.php.tar.gz
(871 B)
📄
goods.php.tar
(3 KB)
📄
google.226bc584.svg.226bc584.svg.tar.gz
(684 B)
📄
google.226bc584.svg.tar
(3 KB)
📄
google.py.py.tar.gz
(390 B)
📄
google.py.tar
(2.5 KB)
📄
goops.tar
(106 KB)
📄
goops.tar.gz
(36.74 KB)
📄
goops.zip
(98.16 KB)
📄
gopher.pyc.pyc.tar.gz
(4.26 KB)
📄
gopher.pyc.tar
(12 KB)
📄
gopher.pyo.pyo.tar.gz
(4.26 KB)
📄
gopher.pyo.tar
(12 KB)
📄
gp10b.tar
(153 KB)
📄
gp10b.tar.gz
(52.72 KB)
📄
gp10b.zip
(140.85 KB)
📄
gpeasy.tar
(86 KB)
📄
gpeasy.tar.gz
(45.42 KB)
📄
gpeasy.zip
(72.09 KB)
📄
gpg-agent.tar
(421 KB)
📄
gpg-agent.tar.gz
(200.83 KB)
📄
gpg-error.h.h.tar.gz
(15.88 KB)
📄
gpg-error.h.tar
(68 KB)
📄
gpg-error.tar
(36 KB)
📄
gpg-error.tar.gz
(11.83 KB)
📄
gpg-zip.tar
(5 KB)
📄
gpg-zip.tar.gz
(1.33 KB)
📄
gpg.tar
(1.04 MB)
📄
gpg.tar.gz
(522.42 KB)
📄
gpgrt.h.h.tar.gz
(15.88 KB)
📄
gpgrt.h.tar
(68 KB)
📄
gpgsplit.tar
(89 KB)
📄
gpgsplit.tar.gz
(41.02 KB)
📄
gpgv.tar
(453.5 KB)
📄
gpgv.tar.gz
(231.53 KB)
📄
gpgverify.tar
(10 KB)
📄
gpgverify.tar.gz
(1.58 KB)
📄
gpic.tar
(295.5 KB)
📄
gpic.tar.gz
(97.49 KB)
📄
gprof.tar
(105 KB)
📄
gprof.tar.gz
(48.59 KB)
📄
gptsync.mod.mod.tar.gz
(2.21 KB)
📄
gptsync.mod.tar
(6 KB)
📄
grafana.xml.tar
(2 KB)
📄
grafana.xml.xml.tar.gz
(258 B)
📄
grammar.h.h.tar.gz
(782 B)
📄
grammar.h.tar
(3.5 KB)
📄
graphical.target.tar
(2.5 KB)
📄
graphical.target.target.tar.gz
(457 B)
📄
graphviz.tar
(1.21 MB)
📄
graphviz.tar.gz
(556.67 KB)
📄
graphviz.zip
(1.2 MB)
📄
grav.png.png.tar.gz
(3.94 KB)
📄
grav.png.tar
(6 KB)
📄
grav.tar
(17.89 MB)
📄
grav.tar.gz
(16.71 MB)
📄
grav.zip
(17.86 MB)
📄
grcat.tar
(9.5 KB)
📄
grcat.tar.gz
(3.39 KB)
📄
grcrt1.o.o.tar.gz
(2.25 KB)
📄
grcrt1.o.tar
(16.5 KB)
📄
gre.xml.tar
(3 KB)
📄
gre.xml.xml.tar.gz
(193 B)
📄
green_sardine_asd.bin.bin.tar.gz
(65.76 KB)
📄
green_sardine_asd.bin.tar
(202 KB)
📄
green_sardine_mec.bin.bin.tar.gz
(33.42 KB)
📄
green_sardine_mec.bin.tar
(263.5 KB)
📄
green_sardine_mec2.bin.bin.tar.gz
(33.42 KB)
📄
green_sardine_mec2.bin.tar
(263.5 KB)
📄
green_sardine_pfp.bin.bin.tar.gz
(41.83 KB)
📄
green_sardine_pfp.bin.tar
(85.5 KB)
📄
green_sardine_rlc.bin.bin.tar.gz
(11.75 KB)
📄
green_sardine_rlc.bin.tar
(40.5 KB)
📄
green_sardine_sdma.bin.bin.tar.gz
(8.6 KB)
📄
green_sardine_sdma.bin.tar
(18.5 KB)
📄
green_sardine_ta.bin.bin.tar.gz
(13.73 KB)
📄
green_sardine_ta.bin.tar
(38.5 KB)
📄
green_sardine_vcn.bin.bin.tar.gz
(279.77 KB)
📄
green_sardine_vcn.bin.tar
(397 KB)
📄
gregocal.h.h.tar.gz
(7.05 KB)
📄
gregocal.h.tar
(33.5 KB)
📄
grep.tar
(195.5 KB)
📄
grep.tar.gz
(86.44 KB)
📄
grepconf.sh.sh.tar.gz
(267 B)
📄
grepconf.sh.tar
(2 KB)
📄
grid.pyc.pyc.tar.gz
(758 B)
📄
grid.pyc.tar
(3 KB)
📄
grid.pyo.pyo.tar.gz
(757 B)
📄
grid.pyo.tar
(3 KB)
📄
groff.tar
(126.5 KB)
📄
groff.tar.gz
(47.6 KB)
📄
grops.tar
(193 KB)
📄
grops.tar.gz
(79.28 KB)
📄
grotty.tar
(143.5 KB)
📄
grotty.tar.gz
(56.23 KB)
📄
group.tar
(2 KB)
📄
group.tar.gz
(365 B)
📄
groups.tar
(39 KB)
📄
groups.tar.gz
(16.21 KB)
📄
grp.h.h.tar.gz
(1.92 KB)
📄
grp.h.tar
(8.5 KB)
📄
grub.tar
(3.16 MB)
📄
grub.tar.gz
(1.11 MB)
📄
grub.zip
(2.98 MB)
📄
gs.tar
(14 KB)
📄
gs.tar.gz
(3.96 KB)
📄
gserver.rb.rb.tar.gz
(3.11 KB)
📄
gserver.rb.tar
(10.5 KB)
📄
gshadow.h.h.tar.gz
(1.28 KB)
📄
gshadow.h.tar
(6 KB)
📄
gsnd.tar
(2 KB)
📄
gsnd.tar.gz
(278 B)
📄
gsoelim.tar
(44.5 KB)
📄
gsoelim.tar.gz
(16.86 KB)
📄
gspi8682.bin.bin.tar.gz
(109.92 KB)
📄
gspi8682.bin.tar
(152.5 KB)
📄
gspi8682_helper.bin.bin.tar.gz
(1.53 KB)
📄
gspi8682_helper.bin.tar
(4 KB)
📄
gspi8688.bin.bin.tar.gz
(185.24 KB)
📄
gspi8688.bin.tar
(257 KB)
📄
gspi8688_helper.bin.bin.tar.gz
(1.53 KB)
📄
gspi8688_helper.bin.tar
(4 KB)
📄
gssapi.h.h.tar.gz
(219 B)
📄
gssapi.h.tar
(32 KB)
📄
gssapi.tar
(73.5 KB)
📄
gssapi.tar.gz
(14.71 KB)
📄
gssapi.zip
(68.39 KB)
📄
gssapi_alloc.h.h.tar.gz
(962 B)
📄
gssapi_alloc.h.tar
(4.5 KB)
📄
gssapi_ext.h.h.tar.gz
(5.28 KB)
📄
gssapi_ext.h.tar
(22 KB)
📄
gssproxy.service.service.tar.gz
(429 B)
📄
gssproxy.service.tar
(3 KB)
📄
gssproxy.tar
(123.5 KB)
📄
gssproxy.tar.gz
(48.23 KB)
📄
gssproxy.zip
(122.05 KB)
📄
gssrpc.pc.pc.tar.gz
(273 B)
📄
gssrpc.pc.tar
(2 KB)
📄
gssrpc.tar
(100.5 KB)
📄
gssrpc.tar.gz
(20.37 KB)
📄
gssrpc.zip
(89.63 KB)
📄
gstreamer-1.0.tar
(7.78 MB)
📄
gstreamer-1.0.tar.gz
(3.14 MB)
📄
gstreamer-1.0.zip
(7.71 MB)
📄
gstreamer1.attr.attr.tar.gz
(178 B)
📄
gstreamer1.attr.tar
(2 KB)
📄
gstreamer1.prov.prov.tar.gz
(655 B)
📄
gstreamer1.prov.tar
(4 KB)
📄
gtar.tar
(450.5 KB)
📄
gtar.tar.gz
(218.2 KB)
📄
gtbl.tar
(156.5 KB)
📄
gtbl.tar.gz
(59.71 KB)
📄
gtk-2.0.tar
(669 KB)
📄
gtk-2.0.tar.gz
(253.44 KB)
📄
gtk-2.0.zip
(664.96 KB)
📄
gtroff.tar
(807 KB)
📄
gtroff.tar.gz
(279.07 KB)
📄
guido.tar
(562 KB)
📄
guido.tar.gz
(157.48 KB)
📄
guido.zip
(511.65 KB)
📄
guile.tar
(5.59 MB)
📄
guile.tar.gz
(1.78 MB)
📄
guile.zip
(5.44 MB)
📄
gunzip.tar
(4 KB)
📄
gunzip.tar.gz
(1.22 KB)
📄
gv.h.h.tar.gz
(3.25 KB)
📄
gv.h.tar
(12 KB)
📄
gv100.tar
(215.5 KB)
📄
gv100.tar.gz
(59.14 KB)
📄
gv100.zip
(201.23 KB)
📄
gw.rb.rb.tar.gz
(1.21 KB)
📄
gw.rb.tar
(4.5 KB)
📄
gxl_h263.bin.bin.tar.gz
(4.95 KB)
📄
gxl_h263.bin.tar
(17.5 KB)
📄
gxl_h264.bin.bin.tar.gz
(13.9 KB)
📄
gxl_h264.bin.tar
(37.5 KB)
📄
gxl_hevc.bin.bin.tar.gz
(8.04 KB)
📄
gxl_hevc.bin.tar
(17.5 KB)
📄
gxl_mpeg12.bin.bin.tar.gz
(4.2 KB)
📄
gxl_mpeg12.bin.tar
(17.5 KB)
📄
gxl_mpeg4_5.bin.bin.tar.gz
(5.19 KB)
📄
gxl_mpeg4_5.bin.tar
(17.5 KB)
📄
gxl_vp9.bin.bin.tar.gz
(4.63 KB)
📄
gxl_vp9.bin.tar
(17.5 KB)
📄
gxm_h264.bin.bin.tar.gz
(13.91 KB)
📄
gxm_h264.bin.tar
(37.5 KB)
📄
gzexe.tar
(8 KB)
📄
gzexe.tar.gz
(2.49 KB)
📄
gzio.mod.mod.tar.gz
(5.38 KB)
📄
gzio.mod.tar
(25 KB)
📄
gzip.py.py.tar.gz
(6.14 KB)
📄
gzip.py.tar
(62.5 KB)
📄
gzip.pyc.pyc.tar.gz
(6.26 KB)
📄
gzip.pyc.tar
(16.5 KB)
📄
gzip.pyo.pyo.tar.gz
(6.27 KB)
📄
gzip.pyo.tar
(16.5 KB)
📄
gzip.tar
(96.5 KB)
📄
gzip.tar.gz
(49.23 KB)
📄
gzipStatic.sh.sh.tar.gz
(270 B)
📄
gzipStatic.sh.tar
(2 KB)
📄
h2ph.tar
(30.5 KB)
📄
h2ph.tar.gz
(9.89 KB)
📄
h2py.py.py.tar.gz
(2.1 KB)
📄
h2py.py.tar
(7.5 KB)
📄
h2xs.tar
(61 KB)
📄
h2xs.tar.gz
(20.48 KB)
📄
h323.xml.tar
(3 KB)
📄
h323.xml.xml.tar.gz
(181 B)
📄
ha_blackhole.so.so.tar.gz
(15.05 KB)
📄
ha_blackhole.so.tar
(49.5 KB)
📄
ha_federated.so.so.tar.gz
(28.49 KB)
📄
ha_federated.so.tar
(74 KB)
📄
ha_federatedx.so.so.tar.gz
(46.4 KB)
📄
ha_federatedx.so.tar
(122.5 KB)
📄
ha_sphinx.so.so.tar.gz
(48.24 KB)
📄
ha_sphinx.so.tar
(122 KB)
📄
ha_spider.so.so.tar.gz
(385.06 KB)
📄
ha_spider.so.tar
(1013 KB)
📄
habanalabs_accel.h.h.tar.gz
(18.73 KB)
📄
habanalabs_accel.h.tar
(76 KB)
📄
hablator.tar
(112 KB)
📄
hablator.tar.gz
(58.03 KB)
📄
hablator.zip
(93.33 KB)
📄
hainan_ce.bin.bin.tar.gz
(1.06 KB)
📄
hainan_ce.bin.tar
(20 KB)
📄
hainan_k_smc.bin.bin.tar.gz
(26.5 KB)
📄
hainan_k_smc.bin.tar
(123 KB)
📄
hainan_mc.bin.bin.tar.gz
(12.81 KB)
📄
hainan_mc.bin.tar
(65 KB)
📄
hainan_me.bin.bin.tar.gz
(3.67 KB)
📄
hainan_me.bin.tar
(20 KB)
📄
hainan_pfp.bin.bin.tar.gz
(2.78 KB)
📄
hainan_pfp.bin.tar
(20 KB)
📄
hainan_rlc.bin.bin.tar.gz
(2.12 KB)
📄
hainan_rlc.bin.tar
(19 KB)
📄
hainan_smc.bin.bin.tar.gz
(26.37 KB)
📄
hainan_smc.bin.tar
(123 KB)
📄
halt.mod.mod.tar.gz
(2.68 KB)
📄
halt.mod.tar
(7.5 KB)
📄
halt.target.tar
(4 KB)
📄
halt.target.target.tar.gz
(436 B)
📄
handesk.tar
(186.5 KB)
📄
handesk.tar.gz
(108.68 KB)
📄
handesk.zip
(166.05 KB)
📄
handle.h.h.tar.gz
(633 B)
📄
handle.h.tar
(3 KB)
📄
handlers.pyc.pyc.tar.gz
(14.6 KB)
📄
handlers.pyc.tar
(57 KB)
📄
handlers.pyo.pyo.tar.gz
(14.6 KB)
📄
handlers.pyo.tar
(56.5 KB)
📄
handlers.tar
(4.5 KB)
📄
handlers.tar.gz
(189 B)
📄
handlers.zip
(1.67 KB)
📄
handlersocket.so.so.tar.gz
(61.99 KB)
📄
handlersocket.so.tar
(148 KB)
📄
handy.h.h.tar.gz
(28.58 KB)
📄
handy.h.tar
(122 KB)
📄
haproxy-int.service.service.tar.gz
(418 B)
📄
haproxy-int.service.tar
(2.5 KB)
📄
haproxy.service.service.tar.gz
(844 B)
📄
haproxy.service.tar
(5 KB)
📄
hardlink.tar
(2 KB)
📄
hardlink.tar.gz
(215 B)
📄
hardware.h.h.tar.gz
(1.15 KB)
📄
hardware.h.tar
(4.5 KB)
📄
has_key.py.py.tar.gz
(1.56 KB)
📄
has_key.py.tar
(20.5 KB)
📄
has_key.pyc.pyc.tar.gz
(2.25 KB)
📄
has_key.pyc.tar
(7.5 KB)
📄
has_key.pyo.pyo.tar.gz
(2.25 KB)
📄
has_key.pyo.tar
(7.5 KB)
📄
hash-table.go.go.tar.gz
(1.63 KB)
📄
hash-table.go.tar
(5.5 KB)
📄
hashlib.py.py.tar.gz
(2.65 KB)
📄
hashlib.py.tar
(28 KB)
📄
hashlib.pyc.pyc.tar.gz
(3.33 KB)
📄
hashlib.pyc.tar
(8.5 KB)
📄
hashlib.pyo.pyo.tar.gz
(3.33 KB)
📄
hashlib.pyo.tar
(8.5 KB)
📄
hashmap.h.h.tar.gz
(602 B)
📄
hashmap.h.tar
(3 KB)
📄
hashsum.mod.mod.tar.gz
(2.72 KB)
📄
hashsum.mod.tar
(8 KB)
📄
hashtab.h.h.tar.gz
(1.38 KB)
📄
hashtab.h.tar
(6 KB)
📄
hawaii_ce.bin.bin.tar.gz
(1.79 KB)
📄
hawaii_ce.bin.tar
(20 KB)
📄
hawaii_k_smc.bin.bin.tar.gz
(46.68 KB)
📄
hawaii_k_smc.bin.tar
(258 KB)
📄
hawaii_mc.bin.bin.tar.gz
(13.56 KB)
📄
hawaii_mc.bin.tar
(67 KB)
📄
hawaii_me.bin.bin.tar.gz
(4.03 KB)
📄
hawaii_me.bin.tar
(20 KB)
📄
hawaii_mec.bin.bin.tar.gz
(8.87 KB)
📄
hawaii_mec.bin.tar
(36 KB)
📄
hawaii_pfp.bin.bin.tar.gz
(4.34 KB)
📄
hawaii_pfp.bin.tar
(20 KB)
📄
hawaii_rlc.bin.bin.tar.gz
(2.61 KB)
📄
hawaii_rlc.bin.tar
(19 KB)
📄
hawaii_sdma.bin.bin.tar.gz
(2.26 KB)
📄
hawaii_sdma.bin.tar
(11 KB)
📄
hawaii_sdma1.bin.bin.tar.gz
(2.26 KB)
📄
hawaii_sdma1.bin.tar
(11 KB)
📄
hawaii_smc.bin.bin.tar.gz
(46.53 KB)
📄
hawaii_smc.bin.tar
(258 KB)
📄
hawaii_uvd.bin.bin.tar.gz
(154.45 KB)
📄
hawaii_uvd.bin.tar
(457 KB)
📄
hawaii_vce.bin.bin.tar.gz
(62.64 KB)
📄
hawaii_vce.bin.tar
(200 KB)
📄
hc_lve_housekeeper.tar
(2.38 MB)
📄
hc_lve_housekeeper.tar.gz
(2.35 MB)
📄
hc_lve_housekeeper.zip
(2.38 MB)
📄
hc_php.tar
(2.5 KB)
📄
hc_php.tar.gz
(462 B)
📄
hc_php.zip
(1.06 KB)
📄
hdparm.mod.mod.tar.gz
(3.58 KB)
📄
hdparm.mod.tar
(18 KB)
📄
hdrcopy.tar
(421.5 KB)
📄
hdrcopy.tar.gz
(197.83 KB)
📄
hdsp.h.h.tar.gz
(917 B)
📄
hdsp.h.tar
(4 KB)
📄
hdspm.h.h.tar.gz
(1.75 KB)
📄
hdspm.h.tar
(6 KB)
📄
head.tar
(47 KB)
📄
head.tar.gz
(20.96 KB)
📄
header.h.h.tar.gz
(1016 B)
📄
header.h.tar
(3.5 KB)
📄
header.inc.php.inc.php.tar.gz
(2.59 KB)
📄
header.inc.php.tar
(11 KB)
📄
header.py.py.tar.gz
(7.08 KB)
📄
header.py.tar
(72.5 KB)
📄
headerregistry.py.py.tar.gz
(5.31 KB)
📄
headerregistry.py.tar
(42.5 KB)
📄
headers.py.py.tar.gz
(2.17 KB)
📄
headers.py.tar
(22.5 KB)
📄
heap.py.py.tar.gz
(3.56 KB)
📄
heap.py.tar
(31 KB)
📄
heapq.py.py.tar.gz
(7.31 KB)
📄
heapq.py.tar
(65.5 KB)
📄
heapq.pyc.pyc.tar.gz
(5.89 KB)
📄
heapq.pyc.tar
(16 KB)
📄
heapq.pyo.pyo.tar.gz
(5.9 KB)
📄
heapq.pyo.tar
(16 KB)
📄
heartbeat.h.h.tar.gz
(968 B)
📄
heartbeat.h.tar
(3.5 KB)
📄
heif-dec.tar
(147.5 KB)
📄
heif-dec.tar.gz
(61.55 KB)
📄
heif-enc.tar
(400.5 KB)
📄
heif-enc.tar.gz
(168.58 KB)
📄
heif-thumbnailer.tar
(44 KB)
📄
heif-thumbnailer.tar.gz
(15.84 KB)
📄
hello.mod.mod.tar.gz
(638 B)
📄
hello.mod.tar
(5 KB)
📄
help.html.html.tar.gz
(11.48 KB)
📄
help.html.tar
(43 KB)
📄
help.mod.mod.tar.gz
(1.52 KB)
📄
help.mod.tar
(4.5 KB)
📄
help.py.py.tar.gz
(3.7 KB)
📄
help.py.tar
(12.5 KB)
📄
helpdeskz.tar
(273 KB)
📄
helpdeskz.tar.gz
(158.03 KB)
📄
helpdeskz.zip
(244.2 KB)
📄
helpdezk.tar
(168.5 KB)
📄
helpdezk.tar.gz
(89.16 KB)
📄
helpdezk.zip
(147.2 KB)
📄
helper_8366.fw.fw.tar.gz
(1.77 KB)
📄
helper_8366.fw.tar
(4 KB)
📄
helper_8687.fw.fw.tar.gz
(1.77 KB)
📄
helper_8687.fw.tar
(4 KB)
📄
helpers.tar
(14 KB)
📄
helpers.tar.gz
(574 B)
📄
helpers.zip
(3.24 KB)
📄
hesk.png.png.tar.gz
(7.74 KB)
📄
hesk.png.tar
(10 KB)
📄
hesk.sql.sql.tar.gz
(6.4 KB)
📄
hesk.sql.tar
(50.5 KB)
📄
hesk.tar
(6.26 MB)
📄
hesk.tar.gz
(5.73 MB)
📄
hesk.zip
(6.21 MB)
📄
hesk_settings.inc.php.inc.php.tar.gz
(2.98 KB)
📄
hesk_settings.inc.php.tar
(11.5 KB)
📄
hexdump.mod.mod.tar.gz
(1.79 KB)
📄
hexdump.mod.tar
(5 KB)
📄
hexdump.tar
(59.5 KB)
📄
hexdump.tar.gz
(25.7 KB)
📄
hfi.tar
(18 KB)
📄
hfi.tar.gz
(5.14 KB)
📄
hfi.zip
(15.83 KB)
📄
hfi1_dc8051.fw.fw.tar.gz
(17.58 KB)
📄
hfi1_dc8051.fw.tar
(66 KB)
📄
hfi1_fabric.fw.fw.tar.gz
(14.12 KB)
📄
hfi1_fabric.fw.tar
(35 KB)
📄
hfi1_ioctl.h.h.tar.gz
(2.79 KB)
📄
hfi1_ioctl.h.tar
(8 KB)
📄
hfi1_pcie.fw.fw.tar.gz
(29.97 KB)
📄
hfi1_pcie.fw.tar
(34.5 KB)
📄
hfi1_sbus.fw.fw.tar.gz
(4.36 KB)
📄
hfi1_sbus.fw.tar
(7 KB)
📄
hfs.mod.mod.tar.gz
(4.99 KB)
📄
hfs.mod.tar
(22 KB)
📄
hfsplus.mod.mod.tar.gz
(5.38 KB)
📄
hfsplus.mod.tar
(13 KB)
📄
hfspluscomp.mod.mod.tar.gz
(2.33 KB)
📄
hfspluscomp.mod.tar
(6.5 KB)
📄
hibernate.target.tar
(2 KB)
📄
hibernate.target.target.tar.gz
(424 B)
📄
history.go.go.tar.gz
(1.35 KB)
📄
history.go.tar
(4.5 KB)
📄
history.rb.rb.tar.gz
(1.03 KB)
📄
history.rb.tar
(4 KB)
📄
hizup.sql.sql.tar.gz
(14.82 KB)
📄
hizup.sql.tar
(86.5 KB)
📄
hizup.tar
(178.93 MB)
📄
hizup.tar.gz
(175.56 MB)
📄
hizup.zip
(178.9 MB)
📄
hmac-md5.h.h.tar.gz
(638 B)
📄
hmac-md5.h.tar
(3 KB)
📄
hmac.h.h.tar.gz
(758 B)
📄
hmac.h.tar
(3.5 KB)
📄
hmac.py.py.tar.gz
(2.12 KB)
📄
hmac.py.tar
(21.5 KB)
📄
hmac.pyc.pyc.tar.gz
(2.06 KB)
📄
hmac.pyc.tar
(6 KB)
📄
hmac.pyo.pyo.tar.gz
(2.06 KB)
📄
hmac.pyo.tar
(6 KB)
📄
hmaccalc.tar
(7 KB)
📄
hmaccalc.tar.gz
(254 B)
📄
hmaccalc.zip
(1.6 KB)
📄
hmtbtfw20.tlv.tar
(530 KB)
📄
hmtbtfw20.tlv.tlv.tar.gz
(191.39 KB)
📄
hmtnv20.b10f.b10f.tar.gz
(4.27 KB)
📄
hmtnv20.b10f.tar
(11 KB)
📄
hmtnv20.b112.b112.tar.gz
(4.26 KB)
📄
hmtnv20.b112.tar
(11 KB)
📄
hmtnv20.bin.bin.tar.gz
(4.13 KB)
📄
hmtnv20.bin.tar
(11 KB)
📄
hns-abi.h.h.tar.gz
(1.12 KB)
📄
hns-abi.h.tar
(4 KB)
📄
home.conf.conf.tar.gz
(330 B)
📄
home.conf.tar
(3 KB)
📄
home.html.html.tar.gz
(2.09 KB)
📄
home.html.tar
(9.5 KB)
📄
home.xml.tar
(2 KB)
📄
home.xml.xml.tar.gz
(323 B)
📄
hop_limit.tar
(3 KB)
📄
hop_limit.tar.gz
(121 B)
📄
host-redirect.xml.tar
(2 KB)
📄
host-redirect.xml.xml.tar.gz
(265 B)
📄
host.conf.conf.tar.gz
(105 B)
📄
host.conf.tar
(2 KB)
📄
host.tar
(144 KB)
📄
host.tar.gz
(61.16 KB)
📄
hostid.tar
(35 KB)
📄
hostid.tar.gz
(14.74 KB)
📄
hostname.tar
(42.5 KB)
📄
hostname.tar.gz
(5.6 KB)
📄
hosts.tar
(2 KB)
📄
hosts.tar.gz
(178 B)
📄
hotaru.tar
(184.5 KB)
📄
hotaru.tar.gz
(110.94 KB)
📄
hotaru.zip
(166.84 KB)
📄
hotshot.tar
(48.5 KB)
📄
hotshot.tar.gz
(8.67 KB)
📄
hotshot.zip
(39.77 KB)
📄
hotshotmain.pyc.pyc.tar.gz
(1.05 KB)
📄
hotshotmain.pyc.tar
(3.5 KB)
📄
hotshotmain.pyo.pyo.tar.gz
(1.05 KB)
📄
hotshotmain.pyo.tar
(3.5 KB)
📄
hp.tar
(33 KB)
📄
hp.tar.gz
(2.26 KB)
📄
hp.zip
(31.37 KB)
📄
hpbtfw21.tlv.tar
(316.5 KB)
📄
hpbtfw21.tlv.tlv.tar.gz
(115.33 KB)
📄
hpc-compute.tar
(3 KB)
📄
hpc-compute.tar.gz
(810 B)
📄
hpc-compute.zip
(1.51 KB)
📄
hpnv21.301.301.tar.gz
(3.15 KB)
📄
hpnv21.301.tar
(16 KB)
📄
hpnv21.302.302.tar.gz
(3.15 KB)
📄
hpnv21.302.tar
(16 KB)
📄
hpnv21.309.309.tar.gz
(3.06 KB)
📄
hpnv21.309.tar
(16 KB)
📄
hpnv21.30a.30a.tar.gz
(3.08 KB)
📄
hpnv21.30a.tar
(16 KB)
📄
hpnv21.b10c.b10c.tar.gz
(3.02 KB)
📄
hpnv21.b10c.tar
(8 KB)
📄
hpnv21.b111.b111.tar.gz
(3.02 KB)
📄
hpnv21.b111.tar
(8 KB)
📄
hpnv21.b206.b206.tar.gz
(3.02 KB)
📄
hpnv21.b206.tar
(8 KB)
📄
hpnv21.b207.b207.tar.gz
(3.09 KB)
📄
hpnv21.b207.tar
(8.5 KB)
📄
hpnv21.b8c.b8c.tar.gz
(3.24 KB)
📄
hpnv21.b8c.tar
(15 KB)
📄
hpnv21.b9f.b9f.tar.gz
(3.24 KB)
📄
hpnv21.b9f.tar
(15 KB)
📄
hpnv21.ba0.ba0.tar.gz
(3.24 KB)
📄
hpnv21.ba0.tar
(15 KB)
📄
hpnv21.ba1.ba1.tar.gz
(3.24 KB)
📄
hpnv21.ba1.tar
(15 KB)
📄
hpnv21.ba2.ba2.tar.gz
(3.24 KB)
📄
hpnv21.ba2.tar
(15 KB)
📄
hpnv21.ba3.ba3.tar.gz
(3.13 KB)
📄
hpnv21.ba3.tar
(15 KB)
📄
hpnv21.ba4.ba4.tar.gz
(3.13 KB)
📄
hpnv21.ba4.tar
(15 KB)
📄
hpnv21.baa.baa.tar.gz
(3.02 KB)
📄
hpnv21.baa.tar
(15 KB)
📄
hpnv21.bb8.bb8.tar.gz
(3.24 KB)
📄
hpnv21.bb8.tar
(15 KB)
📄
hpnv21.bin.bin.tar.gz
(3.24 KB)
📄
hpnv21.bin.tar
(22 KB)
📄
hpnv21g.301.301.tar.gz
(3.15 KB)
📄
hpnv21g.301.tar
(8.5 KB)
📄
hpnv21g.302.302.tar.gz
(3.15 KB)
📄
hpnv21g.302.tar
(8.5 KB)
📄
hpnv21g.309.309.tar.gz
(3.15 KB)
📄
hpnv21g.309.tar
(8.5 KB)
📄
hpnv21g.30a.30a.tar.gz
(3.07 KB)
📄
hpnv21g.30a.tar
(8.5 KB)
📄
hpnv21g.b10c.b10c.tar.gz
(3.02 KB)
📄
hpnv21g.b10c.tar
(8 KB)
📄
hpnv21g.b111.b111.tar.gz
(3.02 KB)
📄
hpnv21g.b111.tar
(8 KB)
📄
hpnv21g.b8c.b8c.tar.gz
(3.24 KB)
📄
hpnv21g.b8c.tar
(8 KB)
📄
hpnv21g.b9f.b9f.tar.gz
(3.24 KB)
📄
hpnv21g.b9f.tar
(8 KB)
📄
hpnv21g.ba0.ba0.tar.gz
(3.24 KB)
📄
hpnv21g.ba0.tar
(8 KB)
📄
hpnv21g.ba1.ba1.tar.gz
(3.24 KB)
📄
hpnv21g.ba1.tar
(8 KB)
📄
hpnv21g.ba2.ba2.tar.gz
(3.24 KB)
📄
hpnv21g.ba2.tar
(8 KB)
📄
hpnv21g.ba3.ba3.tar.gz
(3.13 KB)
📄
hpnv21g.ba3.tar
(8 KB)
📄
hpnv21g.ba4.ba4.tar.gz
(3.13 KB)
📄
hpnv21g.ba4.tar
(8 KB)
📄
hpnv21g.baa.baa.tar.gz
(3.02 KB)
📄
hpnv21g.baa.tar
(8 KB)
📄
hpnv21g.bb8.bb8.tar.gz
(3.24 KB)
📄
hpnv21g.bb8.tar
(8 KB)
📄
hpnv21g.bin.bin.tar.gz
(3.24 KB)
📄
hpnv21g.bin.tar
(8 KB)
📄
hsphere.tar
(7.5 KB)
📄
hsphere.tar.gz
(1.93 KB)
📄
hsphere.zip
(5.83 KB)
📄
htbtfw20.tlv.tar
(207.5 KB)
📄
htbtfw20.tlv.tlv.tar.gz
(143.45 KB)
📄
htc_7010.fw.fw.tar.gz
(32.44 KB)
📄
htc_7010.fw.tar
(144 KB)
📄
htc_9271.fw.fw.tar.gz
(27.81 KB)
📄
htc_9271.fw.tar
(102 KB)
📄
htcacheclean.service.service.tar.gz
(359 B)
📄
htcacheclean.service.tar
(2 KB)
📄
html-filter.info.info.tar.gz
(388 B)
📄
html-filter.info.tar
(2 KB)
📄
html.6.2.1.tar
(2.25 MB)
📄
html.6.2.1.tar.gz
(622.3 KB)
📄
html.6.2.1.zip
(2.18 MB)
📄
html.6.2.2.tar
(2.25 MB)
📄
html.6.2.2.tar.gz
(621.85 KB)
📄
html.6.2.2.zip
(2.18 MB)
📄
html.6.3.1.tar
(2.25 MB)
📄
html.6.3.1.tar.gz
(622.94 KB)
📄
html.6.3.1.zip
(2.18 MB)
📄
html.6.3.2.tar
(2.25 MB)
📄
html.6.3.2.tar.gz
(622.93 KB)
📄
html.6.3.2.zip
(2.18 MB)
📄
html.6.3.3.tar
(2.25 MB)
📄
html.6.3.3.tar.gz
(623.28 KB)
📄
html.6.3.3.zip
(2.18 MB)
📄
html.6.3.4.tar
(2.25 MB)
📄
html.6.3.4.tar.gz
(623.29 KB)
📄
html.6.3.4.zip
(2.18 MB)
📄
html.amf.amf.tar.gz
(282 B)
📄
html.amf.tar
(2 KB)
📄
html.rb.rb.tar.gz
(6.52 KB)
📄
html.rb.tar
(36 KB)
📄
html.tar
(2.94 MB)
📄
html.tar.gz
(98.14 KB)
📄
html.zip
(2.85 MB)
📄
htmlentitydefs.py.py.tar.gz
(4.82 KB)
📄
htmlentitydefs.py.tar
(19.5 KB)
📄
htmlentitydefs.pyc.pyc.tar.gz
(3.05 KB)
📄
htmlentitydefs.pyc.tar
(8 KB)
📄
htmlentitydefs.pyo.pyo.tar.gz
(3.05 KB)
📄
htmlentitydefs.pyo.tar
(8 KB)
📄
htmllib.py.py.tar.gz
(3.05 KB)
📄
htmllib.py.tar
(14.5 KB)
📄
htmllib.pyc.pyc.tar.gz
(5.33 KB)
📄
htmllib.pyc.tar
(21.5 KB)
📄
htmllib.pyo.pyo.tar.gz
(5.33 KB)
📄
htmllib.pyo.tar
(21.5 KB)
📄
htmly.tar
(4.55 MB)
📄
htmly.tar.gz
(4.27 MB)
📄
htmly.zip
(4.52 MB)
📄
htnv20.bin.bin.tar.gz
(2.69 KB)
📄
htnv20.bin.tar
(14 KB)
📄
htpasswd.tar
(2 KB)
📄
htpasswd.tar.gz
(159 B)
📄
http.go.go.tar.gz
(43.78 KB)
📄
http.go.tar
(124 KB)
📄
http.h.h.tar.gz
(10.9 KB)
📄
http.h.tar
(43.5 KB)
📄
http.mod.mod.tar.gz
(3.42 KB)
📄
http.mod.tar
(9.5 KB)
📄
http.tar
(1.02 MB)
📄
http.tar.gz
(212.69 KB)
📄
http.xml.tar
(2 KB)
📄
http.xml.xml.tar.gz
(333 B)
📄
http.zip
(969.17 KB)
📄
http_config.h.h.tar.gz
(12.91 KB)
📄
http_config.h.tar
(58 KB)
📄
http_core.h.h.tar.gz
(10.97 KB)
📄
http_core.h.tar
(38 KB)
📄
http_log.h.h.tar.gz
(6.36 KB)
📄
http_log.h.tar
(38 KB)
📄
http_main.h.h.tar.gz
(1.44 KB)
📄
http_main.h.tar
(5 KB)
📄
http_request.h.h.tar.gz
(6.34 KB)
📄
http_request.h.tar
(27.5 KB)
📄
http_ssl.h.h.tar.gz
(4.21 KB)
📄
http_ssl.h.tar
(16.5 KB)
📄
httpauth.tar
(35 KB)
📄
httpauth.tar.gz
(7.24 KB)
📄
httpd.h.h.tar.gz
(26.13 KB)
📄
httpd.h.tar
(97 KB)
📄
httpd.service.ls_bak.service.ls_bak.tar.gz
(395 B)
📄
httpd.service.ls_bak.tar
(2.5 KB)
📄
httpd.service.service.tar.gz
(468 B)
📄
httpd.service.tar
(2.5 KB)
📄
httpd.tar
(6.7 MB)
📄
httpd.tar.gz
(91.53 KB)
📄
httpd.zip
(6.63 MB)
📄
httpd_config.xml.tar
(8 KB)
📄
httpd_config.xml.xml.tar.gz
(2.17 KB)
📄
httplib.py.py.tar.gz
(15.29 KB)
📄
httplib.py.tar
(54 KB)
📄
httplib.pyc.pyc.tar.gz
(15.05 KB)
📄
httplib.pyc.tar
(39.5 KB)
📄
httplib.pyo.pyo.tar.gz
(14.98 KB)
📄
httplib.pyo.tar
(39.5 KB)
📄
https.xml.tar
(2 KB)
📄
https.xml.xml.tar.gz
(391 B)
📄
hu.tar
(58 KB)
📄
hu.tar.gz
(52.16 KB)
📄
hu.zip
(52.72 KB)
📄
hubzilla.tar
(76.6 MB)
📄
hubzilla.tar.gz
(73.94 MB)
📄
hubzilla.zip
(76.58 MB)
📄
hugetlb_shm_group.tar
(2 KB)
📄
hugetlb_shm_group.tar.gz
(114 B)
📄
humhub.sql.sql.tar.gz
(14.36 KB)
📄
humhub.sql.tar
(94 KB)
📄
humhub.tar
(79.65 MB)
📄
humhub.tar.gz
(70.71 MB)
📄
humhub.zip
(79.61 MB)
📄
humogen.tar
(194.5 KB)
📄
humogen.tar.gz
(103.16 KB)
📄
humogen.zip
(169.34 KB)
📄
hung_task_panic.tar
(2 KB)
📄
hung_task_panic.tar.gz
(116 B)
📄
hung_task_warnings.tar
(2 KB)
📄
hung_task_warnings.tar.gz
(119 B)
📄
hunspell.tar
(146.5 KB)
📄
hunspell.tar.gz
(57.02 KB)
📄
hv.h.h.tar.gz
(8.24 KB)
📄
hv.h.tar
(26.5 KB)
📄
hv_func.h.h.tar.gz
(3.54 KB)
📄
hv_func.h.tar
(15 KB)
📄
hw1.0.tar
(35.61 MB)
📄
hw1.0.tar.gz
(3.79 MB)
📄
hw1.0.zip
(35.59 MB)
📄
hw2.0.tar
(39.72 MB)
📄
hw2.0.tar.gz
(378.11 KB)
📄
hw2.0.zip
(40.56 MB)
📄
hw2.1.tar
(6.74 MB)
📄
hw2.1.tar.gz
(334.91 KB)
📄
hw2.1.zip
(6.74 MB)
📄
hw3.0.tar
(2.85 MB)
📄
hw3.0.tar.gz
(1.43 MB)
📄
hw3.0.zip
(2.85 MB)
📄
hw_breakpoint.h.h.tar.gz
(180 B)
📄
hw_breakpoint.h.tar
(2 KB)
📄
hwcap2.h.h.tar.gz
(286 B)
📄
hwcap2.h.tar
(2 KB)
📄
hwdb.d.tar
(7.35 MB)
📄
hwdb.d.tar.gz
(1.19 MB)
📄
hwdb.d.zip
(7.33 MB)
📄
hybrid-sleep.target.tar
(2.5 KB)
📄
hybrid-sleep.target.target.tar.gz
(440 B)
📄
i-1.gif.gif.tar.gz
(115 B)
📄
i-1.gif.tar
(1.5 KB)
📄
i-2.gif.gif.tar.gz
(115 B)
📄
i-2.gif.tar
(1.5 KB)
📄
i.gif.gif.tar.gz
(113 B)
📄
i.gif.tar
(1.5 KB)
📄
i18n.go.go.tar.gz
(7.41 KB)
📄
i18n.go.tar
(22.5 KB)
📄
i386-linux.tar
(4.5 KB)
📄
i386-linux.tar.gz
(1.2 KB)
📄
i386-linux.zip
(3.12 KB)
📄
i386-pc.tar
(3.16 MB)
📄
i386-pc.tar.gz
(1.11 MB)
📄
i386-pc.zip
(2.98 MB)
📄
i386.tar
(540 KB)
📄
i386.tar.gz
(367.34 KB)
📄
i386.zip
(426.35 KB)
📄
i486-linux.tar
(4.5 KB)
📄
i486-linux.tar.gz
(1.19 KB)
📄
i486-linux.zip
(3.11 KB)
📄
i586-linux.tar
(4.5 KB)
📄
i586-linux.tar.gz
(1.19 KB)
📄
i586-linux.zip
(3.11 KB)
📄
i686-linux.tar
(4.5 KB)
📄
i686-linux.tar.gz
(1.19 KB)
📄
i686-linux.zip
(3.11 KB)
📄
i915.tar
(27.05 MB)
📄
i915.tar.gz
(10.99 MB)
📄
i915.zip
(26.98 MB)
📄
i915_drm.h.h.tar.gz
(34.8 KB)
📄
i915_drm.h.tar
(124 KB)
📄
ia32e-linux.tar
(4.5 KB)
📄
ia32e-linux.tar.gz
(1.19 KB)
📄
ia32e-linux.zip
(3.1 KB)
📄
ia64-linux.tar
(4.5 KB)
📄
ia64-linux.tar.gz
(1.18 KB)
📄
ia64-linux.zip
(3.1 KB)
📄
ib_user_ioctl_cmds.h.h.tar.gz
(2.3 KB)
📄
ib_user_ioctl_cmds.h.tar
(11 KB)
📄
ib_user_mad.h.h.tar.gz
(2.88 KB)
📄
ib_user_mad.h.tar
(10 KB)
📄
ibendport_record.h.h.tar.gz
(538 B)
📄
ibendport_record.h.tar
(4 KB)
📄
ibendports.h.h.tar.gz
(555 B)
📄
ibendports.h.tar
(3 KB)
📄
ibpkey_record.h.h.tar.gz
(603 B)
📄
ibpkey_record.h.tar
(4 KB)
📄
ibpkeys.h.h.tar.gz
(552 B)
📄
ibpkeys.h.tar
(3 KB)
📄
ibt-0040-0041.ddc.ddc.tar.gz
(125 B)
📄
ibt-0040-0041.ddc.tar
(2 KB)
📄
ibt-0040-0041.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-0040-0041.sfi.tar
(706 KB)
📄
ibt-0040-1020.ddc.ddc.tar.gz
(126 B)
📄
ibt-0040-1020.ddc.tar
(2 KB)
📄
ibt-0040-1020.sfi.sfi.tar.gz
(543.13 KB)
📄
ibt-0040-1020.sfi.tar
(748.5 KB)
📄
ibt-0040-1050.ddc.ddc.tar.gz
(128 B)
📄
ibt-0040-1050.ddc.tar
(2 KB)
📄
ibt-0040-1050.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-0040-1050.sfi.tar
(706 KB)
📄
ibt-0040-2120.ddc.ddc.tar.gz
(126 B)
📄
ibt-0040-2120.ddc.tar
(2 KB)
📄
ibt-0040-2120.sfi.sfi.tar.gz
(543.13 KB)
📄
ibt-0040-2120.sfi.tar
(748.5 KB)
📄
ibt-0040-4150.ddc.ddc.tar.gz
(125 B)
📄
ibt-0040-4150.ddc.tar
(2 KB)
📄
ibt-0040-4150.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-0040-4150.sfi.tar
(706 KB)
📄
ibt-0041-0041.ddc.ddc.tar.gz
(125 B)
📄
ibt-0041-0041.ddc.tar
(2 KB)
📄
ibt-0041-0041.sfi.sfi.tar.gz
(509.61 KB)
📄
ibt-0041-0041.sfi.tar
(698.5 KB)
📄
ibt-0093-0041.ddc.ddc.tar.gz
(122 B)
📄
ibt-0093-0041.ddc.tar
(2 KB)
📄
ibt-0093-0041.sfi.sfi.tar.gz
(601.3 KB)
📄
ibt-0093-0041.sfi.tar
(858 KB)
📄
ibt-0093-0291.ddc.ddc.tar.gz
(123 B)
📄
ibt-0093-0291.ddc.tar
(2 KB)
📄
ibt-0093-0291.sfi.sfi.tar.gz
(672.96 KB)
📄
ibt-0093-0291.sfi.tar
(949 KB)
📄
ibt-0093-1050.ddc.ddc.tar.gz
(123 B)
📄
ibt-0093-1050.ddc.tar
(2 KB)
📄
ibt-0093-1050.sfi.sfi.tar.gz
(601.31 KB)
📄
ibt-0093-1050.sfi.tar
(858 KB)
📄
ibt-0093-4150.ddc.ddc.tar.gz
(123 B)
📄
ibt-0093-4150.ddc.tar
(2 KB)
📄
ibt-0093-4150.sfi.sfi.tar.gz
(601.31 KB)
📄
ibt-0093-4150.sfi.tar
(858 KB)
📄
ibt-0180-0041.ddc.ddc.tar.gz
(128 B)
📄
ibt-0180-0041.ddc.tar
(2 KB)
📄
ibt-0180-0041.sfi.sfi.tar.gz
(591.3 KB)
📄
ibt-0180-0041.sfi.tar
(809 KB)
📄
ibt-0180-1050.ddc.ddc.tar.gz
(128 B)
📄
ibt-0180-1050.ddc.tar
(2 KB)
📄
ibt-0180-1050.sfi.sfi.tar.gz
(591.3 KB)
📄
ibt-0180-1050.sfi.tar
(809 KB)
📄
ibt-0180-4150.ddc.ddc.tar.gz
(126 B)
📄
ibt-0180-4150.ddc.tar
(2 KB)
📄
ibt-0180-4150.sfi.sfi.tar.gz
(591.3 KB)
📄
ibt-0180-4150.sfi.tar
(809 KB)
📄
ibt-0190-0041.ddc.ddc.tar.gz
(127 B)
📄
ibt-0190-0041.ddc.tar
(2 KB)
📄
ibt-0190-0041.sfi.sfi.tar.gz
(566.22 KB)
📄
ibt-0190-0041.sfi.tar
(796.5 KB)
📄
ibt-0190-0291.ddc.ddc.tar.gz
(127 B)
📄
ibt-0190-0291.ddc.tar
(2 KB)
📄
ibt-0190-0291.sfi.sfi.tar.gz
(609.92 KB)
📄
ibt-0190-0291.sfi.tar
(848 KB)
📄
ibt-0291-0291.ddc.ddc.tar.gz
(120 B)
📄
ibt-0291-0291.ddc.tar
(2 KB)
📄
ibt-0291-0291.sfi.sfi.tar.gz
(672.96 KB)
📄
ibt-0291-0291.sfi.tar
(949 KB)
📄
ibt-1040-0041.ddc.ddc.tar.gz
(125 B)
📄
ibt-1040-0041.ddc.tar
(2 KB)
📄
ibt-1040-0041.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-1040-0041.sfi.tar
(706 KB)
📄
ibt-1040-1020.ddc.ddc.tar.gz
(127 B)
📄
ibt-1040-1020.ddc.tar
(2 KB)
📄
ibt-1040-1020.sfi.sfi.tar.gz
(543.13 KB)
📄
ibt-1040-1020.sfi.tar
(748.5 KB)
📄
ibt-1040-1050.ddc.ddc.tar.gz
(126 B)
📄
ibt-1040-1050.ddc.tar
(2 KB)
📄
ibt-1040-1050.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-1040-1050.sfi.tar
(706 KB)
📄
ibt-1040-2120.ddc.ddc.tar.gz
(125 B)
📄
ibt-1040-2120.ddc.tar
(2 KB)
📄
ibt-1040-2120.sfi.sfi.tar.gz
(543.13 KB)
📄
ibt-1040-2120.sfi.tar
(748.5 KB)
📄
ibt-1040-4150.ddc.ddc.tar.gz
(128 B)
📄
ibt-1040-4150.ddc.tar
(2 KB)
📄
ibt-1040-4150.sfi.sfi.tar.gz
(512.89 KB)
📄
ibt-1040-4150.sfi.tar
(706 KB)
📄
ibt-11-5.ddc.ddc.tar.gz
(132 B)
📄
ibt-11-5.ddc.tar
(2 KB)
📄
ibt-11-5.sfi.sfi.tar.gz
(387.85 KB)
📄
ibt-11-5.sfi.tar
(575 KB)
📄
ibt-12-16.ddc.ddc.tar.gz
(133 B)
📄
ibt-12-16.ddc.tar
(2 KB)
📄
ibt-12-16.sfi.sfi.tar.gz
(387.62 KB)
📄
ibt-12-16.sfi.tar
(572 KB)
📄
ibt-17-0-1.ddc.ddc.tar.gz
(130 B)
📄
ibt-17-0-1.ddc.tar
(3 KB)
📄
ibt-17-0-1.sfi.sfi.tar.gz
(415.01 KB)
📄
ibt-17-0-1.sfi.tar
(1.2 MB)
📄
ibt-17-1.ddc.ddc.tar.gz
(128 B)
📄
ibt-17-1.ddc.tar
(2 KB)
📄
ibt-17-1.sfi.sfi.tar.gz
(415 KB)
📄
ibt-17-1.sfi.tar
(612.5 KB)
📄
ibt-17-16-1.ddc.ddc.tar.gz
(124 B)
📄
ibt-17-16-1.ddc.tar
(2 KB)
📄
ibt-17-16-1.sfi.sfi.tar.gz
(450.87 KB)
📄
ibt-17-16-1.sfi.tar
(661.5 KB)
📄
ibt-17-2.ddc.ddc.tar.gz
(123 B)
📄
ibt-17-2.ddc.tar
(2 KB)
📄
ibt-17-2.sfi.sfi.tar.gz
(450.87 KB)
📄
ibt-17-2.sfi.tar
(661.5 KB)
📄
ibt-18-0-1.ddc.ddc.tar.gz
(130 B)
📄
ibt-18-0-1.ddc.tar
(3 KB)
📄
ibt-18-0-1.sfi.sfi.tar.gz
(415.01 KB)
📄
ibt-18-0-1.sfi.tar
(1.2 MB)
📄
ibt-18-1.ddc.ddc.tar.gz
(128 B)
📄
ibt-18-1.ddc.tar
(2 KB)
📄
ibt-18-1.sfi.sfi.tar.gz
(415 KB)
📄
ibt-18-1.sfi.tar
(612.5 KB)
📄
ibt-18-16-1.ddc.ddc.tar.gz
(126 B)
📄
ibt-18-16-1.ddc.tar
(2 KB)
📄
ibt-18-16-1.sfi.sfi.tar.gz
(450.87 KB)
📄
ibt-18-16-1.sfi.tar
(661.5 KB)
📄
ibt-18-2.ddc.ddc.tar.gz
(123 B)
📄
ibt-18-2.ddc.tar
(2 KB)
📄
ibt-18-2.sfi.sfi.tar.gz
(450.87 KB)
📄
ibt-18-2.sfi.tar
(661.5 KB)
📄
ibt-19-0-0.ddc.ddc.tar.gz
(125 B)
📄
ibt-19-0-0.ddc.tar
(3 KB)
📄
ibt-19-0-0.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-0-0.sfi.tar
(1.53 MB)
📄
ibt-19-0-1.ddc.ddc.tar.gz
(125 B)
📄
ibt-19-0-1.ddc.tar
(3 KB)
📄
ibt-19-0-1.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-0-1.sfi.tar
(1.53 MB)
📄
ibt-19-0-3.ddc.ddc.tar.gz
(125 B)
📄
ibt-19-0-3.ddc.tar
(3 KB)
📄
ibt-19-0-3.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-0-3.sfi.tar
(1.53 MB)
📄
ibt-19-0-4.ddc.ddc.tar.gz
(125 B)
📄
ibt-19-0-4.ddc.tar
(3 KB)
📄
ibt-19-0-4.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-0-4.sfi.tar
(1.53 MB)
📄
ibt-19-16-4.ddc.ddc.tar.gz
(126 B)
📄
ibt-19-16-4.ddc.tar
(2 KB)
📄
ibt-19-16-4.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-16-4.sfi.tar
(784 KB)
📄
ibt-19-240-1.ddc.ddc.tar.gz
(130 B)
📄
ibt-19-240-1.ddc.tar
(2 KB)
📄
ibt-19-240-1.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-240-1.sfi.tar
(784 KB)
📄
ibt-19-240-4.ddc.ddc.tar.gz
(131 B)
📄
ibt-19-240-4.ddc.tar
(2 KB)
📄
ibt-19-240-4.sfi.sfi.tar.gz
(517.36 KB)
📄
ibt-19-240-4.sfi.tar
(784 KB)
📄
ibt-19-32-0.ddc.ddc.tar.gz
(126 B)
📄
ibt-19-32-0.ddc.tar
(2 KB)
📄
ibt-19-32-0.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-32-0.sfi.tar
(784 KB)
📄
ibt-19-32-1.ddc.ddc.tar.gz
(126 B)
📄
ibt-19-32-1.ddc.tar
(2 KB)
📄
ibt-19-32-1.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-32-1.sfi.tar
(784 KB)
📄
ibt-19-32-4.ddc.ddc.tar.gz
(125 B)
📄
ibt-19-32-4.ddc.tar
(2 KB)
📄
ibt-19-32-4.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-19-32-4.sfi.tar
(784 KB)
📄
ibt-20-0-3.ddc.ddc.tar.gz
(125 B)
📄
ibt-20-0-3.ddc.tar
(3 KB)
📄
ibt-20-0-3.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-20-0-3.sfi.tar
(1.53 MB)
📄
ibt-20-1-3.ddc.ddc.tar.gz
(124 B)
📄
ibt-20-1-3.ddc.tar
(3 KB)
📄
ibt-20-1-3.sfi.sfi.tar.gz
(517.35 KB)
📄
ibt-20-1-3.sfi.tar
(1.53 MB)
📄
ibt-20-1-4.ddc.ddc.tar.gz
(125 B)
📄
ibt-20-1-4.ddc.tar
(3 KB)
📄
ibt-20-1-4.sfi.sfi.tar.gz
(516.76 KB)
📄
ibt-20-1-4.sfi.tar
(1.53 MB)
📄
ibt-hw-37.7.bseq.7.bseq.tar.gz
(209 B)
📄
ibt-hw-37.7.bseq.tar
(2 KB)
📄
ibt-hw-37.8.bseq.8.bseq.tar.gz
(209 B)
📄
ibt-hw-37.8.bseq.tar
(2 KB)
📄
ice-9.tar
(1.35 MB)
📄
ice-9.tar.gz
(462.6 KB)
📄
ice-9.zip
(1.31 MB)
📄
ice.pkg.pkg.tar.gz
(97.03 KB)
📄
ice.pkg.tar
(1.29 MB)
📄
ice.tar
(4.7 MB)
📄
ice.tar.gz
(369.65 KB)
📄
ice.zip
(4.7 MB)
📄
icehrm.sql.sql.tar.gz
(32.3 KB)
📄
icehrm.sql.tar
(164.5 KB)
📄
icehrm.tar
(54.54 MB)
📄
icehrm.tar.gz
(48.08 MB)
📄
icehrm.zip
(54.52 MB)
📄
icl_guc_32.0.3.bin.0.3.bin.tar.gz
(117.64 KB)
📄
icl_guc_32.0.3.bin.tar
(373 KB)
📄
icl_guc_33.0.0.bin.0.0.bin.tar.gz
(119.13 KB)
📄
icl_guc_33.0.0.bin.tar
(378 KB)
📄
icl_guc_49.0.1.bin.0.1.bin.tar.gz
(126.81 KB)
📄
icl_guc_49.0.1.bin.tar
(318.5 KB)
📄
icl_guc_62.0.0.bin.0.0.bin.tar.gz
(131.88 KB)
📄
icl_guc_62.0.0.bin.tar
(321.5 KB)
📄
icl_guc_69.0.3.bin.0.3.bin.tar.gz
(144.61 KB)
📄
icl_guc_69.0.3.bin.tar
(337 KB)
📄
icl_guc_70.1.1.bin.1.1.bin.tar.gz
(108.91 KB)
📄
icl_guc_70.1.1.bin.tar
(270 KB)
📄
icl_huc_9.0.0.bin.0.0.bin.tar.gz
(151.87 KB)
📄
icl_huc_9.0.0.bin.tar
(489 KB)
📄
icl_huc_ver8_4_3238.bin.bin.tar.gz
(148.19 KB)
📄
icl_huc_ver8_4_3238.bin.tar
(479 KB)
📄
icmp.tar
(2 KB)
📄
icmp.tar.gz
(94 B)
📄
icmp.zip
(157 B)
📄
icmp6.h.h.tar.gz
(3.09 KB)
📄
icmp6.h.tar
(13 KB)
📄
icmp_msgs_burst.tar
(2 KB)
📄
icmp_msgs_burst.tar.gz
(118 B)
📄
icmp_ratemask.tar
(2 KB)
📄
icmp_ratemask.tar.gz
(118 B)
📄
icmptypes.tar
(50 KB)
📄
icmptypes.tar.gz
(3.1 KB)
📄
icmptypes.zip
(19.98 KB)
📄
icon-orange-CmGCK62q.woff.tar
(304 KB)
📄
icon-orange-CmGCK62q.woff.woff.tar.gz
(300.58 KB)
📄
icon-orange-DBf8NVIG.woff2.tar
(244.5 KB)
📄
icon-orange-DBf8NVIG.woff2.woff2.tar.gz
(242.48 KB)
📄
icons.tar
(4 KB)
📄
icons.tar.gz
(2.6 KB)
📄
icons.zip
(2.61 KB)
📄
iconv.go.go.tar.gz
(1.85 KB)
📄
iconv.go.tar
(5.5 KB)
📄
iconv.h.h.tar.gz
(993 B)
📄
iconv.h.tar
(3.5 KB)
📄
iconv.tar
(63 KB)
📄
iconv.tar.gz
(27.92 KB)
📄
icu-config-64.tar
(23.5 KB)
📄
icu-config-64.tar.gz
(6.75 KB)
📄
icu-config.tar
(2 KB)
📄
icu-config.tar.gz
(242 B)
📄
icuinfo.tar
(16 KB)
📄
icuinfo.tar.gz
(5.14 KB)
📄
id.tar
(92.5 KB)
📄
id.tar.gz
(19.75 KB)
📄
id.zip
(37.09 KB)
📄
idea.h.h.tar.gz
(772 B)
📄
idea.h.tar
(4 KB)
📄
identify-cli.tar
(2 KB)
📄
identify-cli.tar.gz
(257 B)
📄
identify.tar
(13.5 KB)
📄
identify.tar.gz
(3.77 KB)
📄
idgen_delay.tar
(2 KB)
📄
idgen_delay.tar.gz
(114 B)
📄
idgen_retries.tar
(2 KB)
📄
idgen_retries.tar.gz
(116 B)
📄
idle.icns.icns.tar.gz
(22.34 KB)
📄
idle.icns.tar
(58 KB)
📄
idle.py.py.tar.gz
(375 B)
📄
idle.py.tar
(2 KB)
📄
idle_test.tar
(505.5 KB)
📄
idle_test.tar.gz
(115.29 KB)
📄
idle_test.zip
(457.88 KB)
📄
idlelib.tar
(2.7 MB)
📄
idlelib.tar.gz
(821.98 KB)
📄
idlelib.zip
(2.53 MB)
📄
idlever.py.py.tar.gz
(352 B)
📄
idlever.py.tar
(2 KB)
📄
idn-free.h.h.tar.gz
(1.19 KB)
📄
idn-free.h.tar
(4 KB)
📄
idn-int.h.h.tar.gz
(118 B)
📄
idn-int.h.tar
(2 KB)
📄
idn.tar
(41 KB)
📄
idn.tar.gz
(14.59 KB)
📄
ieee754.h.h.tar.gz
(1.13 KB)
📄
ieee754.h.tar
(6.5 KB)
📄
if.h.h.tar.gz
(2.7 KB)
📄
if.h.tar
(8.5 KB)
📄
if_arp.h.h.tar.gz
(2.74 KB)
📄
if_arp.h.tar
(8.5 KB)
📄
if_ether.h.h.tar.gz
(1.91 KB)
📄
if_ether.h.tar
(5.5 KB)
📄
if_packet.h.h.tar.gz
(794 B)
📄
if_packet.h.tar
(3 KB)
📄
if_ppp.h.h.tar.gz
(2.75 KB)
📄
if_ppp.h.tar
(8.5 KB)
📄
if_shaper.h.h.tar.gz
(954 B)
📄
if_shaper.h.tar
(3.5 KB)
📄
if_slip.h.h.tar.gz
(612 B)
📄
if_slip.h.tar
(2.5 KB)
📄
if_tr.h.h.tar.gz
(1.49 KB)
📄
if_tr.h.tar
(5.5 KB)
📄
ifdef.pyc.pyc.tar.gz
(1.19 KB)
📄
ifdef.pyc.tar
(4 KB)
📄
ifdef.pyo.pyo.tar.gz
(1.19 KB)
📄
ifdef.pyo.tar
(4 KB)
📄
ifnames.tar
(6 KB)
📄
ifnames.tar.gz
(2.05 KB)
📄
igalerie.tar
(1.39 MB)
📄
igalerie.tar.gz
(1.16 MB)
📄
igalerie.zip
(1.37 MB)
📄
igmp.h.h.tar.gz
(2.08 KB)
📄
igmp.h.tar
(6.5 KB)
📄
igmp_max_msf.tar
(2 KB)
📄
igmp_max_msf.tar.gz
(116 B)
📄
igmp_qrv.tar
(2 KB)
📄
igmp_qrv.tar.gz
(111 B)
📄
igniter.tar
(6.87 MB)
📄
igniter.tar.gz
(6.03 MB)
📄
igniter.zip
(6.85 MB)
📄
ihooks.py.py.tar.gz
(4.85 KB)
📄
ihooks.py.tar
(20.5 KB)
📄
ihooks.pyc.pyc.tar.gz
(7.41 KB)
📄
ihooks.pyc.tar
(22.5 KB)
📄
ihooks.pyo.pyo.tar.gz
(7.41 KB)
📄
ihooks.pyo.tar
(22.5 KB)
📄
ilias.sql.sql.tar.gz
(779.41 KB)
📄
ilias.sql.tar
(3.81 MB)
📄
ilias.tar
(148.96 MB)
📄
ilias.tar.gz
(137.51 MB)
📄
ilias.zip
(148.93 MB)
📄
image.sh.sh.tar.gz
(491 B)
📄
image.sh.tar
(3 KB)
📄
imageformats.tar
(118 KB)
📄
imageformats.tar.gz
(47.85 KB)
📄
imageformats.zip
(115.39 KB)
📄
images.tar
(6 MB)
📄
images.tar.gz
(24.62 KB)
📄
images.zip
(5.68 MB)
📄
imap.xml.tar
(2 KB)
📄
imap.xml.xml.tar.gz
(331 B)
📄
imap_xaps_plugin.so.so.tar.gz
(4.12 KB)
📄
imap_xaps_plugin.so.tar
(15 KB)
📄
imaplib.py.py.tar.gz
(14.14 KB)
📄
imaplib.py.tar
(155 KB)
📄
imaplib.pyc.pyc.tar.gz
(15.89 KB)
📄
imaplib.pyc.tar
(45.5 KB)
📄
imaplib.pyo.pyo.tar.gz
(14.86 KB)
📄
imaplib.pyo.tar
(43 KB)
📄
imaps.xml.tar
(2 KB)
📄
imaps.xml.xml.tar.gz
(354 B)
📄
imdiag.so.so.tar.gz
(11.24 KB)
📄
imdiag.so.tar
(31 KB)
📄
imf99575.tar
(52 KB)
📄
imf99575.tar.gz
(18.71 KB)
📄
imf99575.zip
(48.47 KB)
📄
imfile.so.so.tar.gz
(25.5 KB)
📄
imfile.so.tar
(60.5 KB)
📄
img.php.php.tar.gz
(691 B)
📄
img.php.tar
(3 KB)
📄
img.tar
(104.5 KB)
📄
img.tar.gz
(35.22 KB)
📄
img.zip
(93.9 KB)
📄
imghdr.py.py.tar.gz
(1.31 KB)
📄
imghdr.py.tar
(14 KB)
📄
imghdr.pyc.pyc.tar.gz
(1.87 KB)
📄
imghdr.pyc.tar
(6.5 KB)
📄
imghdr.pyo.pyo.tar.gz
(1.87 KB)
📄
imghdr.pyo.tar
(6.5 KB)
📄
imjournal.so.so.tar.gz
(12.95 KB)
📄
imjournal.so.tar
(35 KB)
📄
imklog.so.so.tar.gz
(9.94 KB)
📄
imklog.so.tar
(27.5 KB)
📄
immark.so.so.tar.gz
(6.43 KB)
📄
immark.so.tar
(18.5 KB)
📄
imp.py.py.tar.gz
(3.29 KB)
📄
imp.py.tar
(23 KB)
📄
impleo.tar
(142 KB)
📄
impleo.tar.gz
(73.91 KB)
📄
impleo.zip
(119.6 KB)
📄
import-state.service.service.tar.gz
(371 B)
📄
import-state.service.tar
(2 KB)
📄
import.h.h.tar.gz
(1.1 KB)
📄
import.h.tar
(6.5 KB)
📄
import.php.php.tar.gz
(2.25 KB)
📄
import.php.tar
(2.2 MB)
📄
import.tar
(13.5 KB)
📄
import.tar.gz
(3.66 KB)
📄
importlib.tar
(792 KB)
📄
importlib.tar.gz
(121.45 KB)
📄
importlib.zip
(748.43 KB)
📄
impress.tar
(22.7 MB)
📄
impress.tar.gz
(21.33 MB)
📄
impress.zip
(22.67 MB)
📄
impresspage.tar
(213.5 KB)
📄
impresspage.tar.gz
(112.83 KB)
📄
impresspage.zip
(186.17 KB)
📄
impstats.so.so.tar.gz
(9.06 KB)
📄
impstats.so.tar
(23 KB)
📄
imptcp.so.so.tar.gz
(21.38 KB)
📄
imptcp.so.tar
(51.5 KB)
📄
imputil.py.py.tar.gz
(7.87 KB)
📄
imputil.py.tar
(27 KB)
📄
imputil.pyc.pyc.tar.gz
(6.36 KB)
📄
imputil.pyc.tar
(17 KB)
📄
imputil.pyo.pyo.tar.gz
(6.27 KB)
📄
imputil.pyo.tar
(17 KB)
📄
imtcp.so.so.tar.gz
(9.9 KB)
📄
imtcp.so.tar
(27.5 KB)
📄
imudp.so.so.tar.gz
(13.09 KB)
📄
imudp.so.tar
(31.5 KB)
📄
imunify-notifier.socket.socket.tar.gz
(248 B)
📄
imunify-notifier.socket.tar
(2 KB)
📄
imunify360.tar
(199.29 MB)
📄
imunify360.tar.gz
(320 B)
📄
imunify360.zip
(199.26 MB)
📄
imuxsock.so.so.tar.gz
(16.47 KB)
📄
imuxsock.so.tar
(39.5 KB)
📄
imx.tar
(8.5 KB)
📄
imx.tar.gz
(2.09 KB)
📄
imx.zip
(6.34 KB)
📄
in.h.h.tar.gz
(3.32 KB)
📄
in.h.tar
(33 KB)
📄
in_systm.h.h.tar.gz
(880 B)
📄
in_systm.h.tar
(3 KB)
📄
inc.LogInit.php.LogInit.php.tar.gz
(832 B)
📄
inc.LogInit.php.tar
(3 KB)
📄
include.rb.rb.tar.gz
(527 B)
📄
include.rb.tar
(2.5 KB)
📄
include.tar
(72.85 MB)
📄
include.tar.gz
(201.17 KB)
📄
include.zip
(71.64 MB)
📄
increment.mod.mod.tar.gz
(1.17 KB)
📄
increment.mod.tar
(7 KB)
📄
index-Ca-YVQK7.css.css.tar.gz
(82.98 KB)
📄
index-Ca-YVQK7.css.tar
(744.5 KB)
📄
index-SdUAaSso.css.css.tar.gz
(82.91 KB)
📄
index-SdUAaSso.css.tar
(744 KB)
📄
index.h.h.tar.gz
(5.75 KB)
📄
index.h.tar
(24.5 KB)
📄
index.html.html.tar.gz
(223 B)
📄
index.html.tar
(19.5 KB)
📄
index.php.tar
(1.24 MB)
📄
index.php0.php0.tar.gz
(5.73 KB)
📄
index.php0.tar
(15 KB)
📄
index_1.html.html.tar.gz
(290 B)
📄
index_1.html.tar
(3 KB)
📄
index_10.html.html.tar.gz
(708 B)
📄
index_10.html.tar
(3 KB)
📄
index_11.html.html.tar.gz
(296 B)
📄
index_11.html.tar
(2 KB)
📄
index_2.html.html.tar.gz
(230 B)
📄
index_2.html.tar
(3 KB)
📄
index_3.html.html.tar.gz
(230 B)
📄
index_3.html.tar
(2 KB)
📄
index_4.html.html.tar.gz
(801 B)
📄
index_4.html.tar
(3 KB)
📄
index_5.html.html.tar.gz
(334 B)
📄
index_5.html.tar
(2 KB)
📄
index_6.html.html.tar.gz
(358 B)
📄
index_6.html.tar
(2 KB)
📄
index_7.html.html.tar.gz
(363 B)
📄
index_7.html.tar
(2 KB)
📄
index_8.html.html.tar.gz
(2.56 KB)
📄
index_8.html.tar
(11.5 KB)
📄
index_9.html.html.tar.gz
(558 B)
📄
index_9.html.tar
(2.5 KB)
📄
indirect-return.h.h.tar.gz
(888 B)
📄
indirect-return.h.tar
(3.5 KB)
📄
inet_peer_maxttl.tar
(2 KB)
📄
inet_peer_maxttl.tar.gz
(119 B)
📄
inet_peer_minttl.tar
(2 KB)
📄
inet_peer_minttl.tar.gz
(119 B)
📄
info.svg.svg.tar.gz
(796 B)
📄
info.svg.tar
(3 KB)
📄
info.tar
(8.5 KB)
📄
info.tar.gz
(280 B)
📄
info.txt.tar
(2 KB)
📄
info.txt.txt.tar.gz
(147 B)
📄
info.xml.tar
(1.98 MB)
📄
info.xml.xml.tar.gz
(1.25 KB)
📄
infocmp.tar
(63 KB)
📄
infocmp.tar.gz
(29.35 KB)
📄
infotocap.tar
(87 KB)
📄
infotocap.tar.gz
(38.76 KB)
📄
inftl-user.h.h.tar.gz
(759 B)
📄
inftl-user.h.tar
(3.5 KB)
📄
inherit_noatime.tar
(2 KB)
📄
inherit_noatime.tar.gz
(115 B)
📄
inherit_nodump.tar
(2 KB)
📄
inherit_nodump.tar.gz
(114 B)
📄
inherit_nosymlinks.tar
(2 KB)
📄
inherit_nosymlinks.tar.gz
(117 B)
📄
inherit_sync.tar
(2 KB)
📄
inherit_sync.tar.gz
(112 B)
📄
init.php.php.tar.gz
(1.55 KB)
📄
init.php.tar
(4.5 KB)
📄
initrd-cleanup.service.service.tar.gz
(529 B)
📄
initrd-cleanup.service.tar
(2.5 KB)
📄
initrd-fs.target.tar
(2.5 KB)
📄
initrd-fs.target.target.tar.gz
(488 B)
📄
initrd-switch-root.service.service.tar.gz
(497 B)
📄
initrd-switch-root.service.tar
(2.5 KB)
📄
initrd.target.tar
(4 KB)
📄
initrd.target.target.tar.gz
(516 B)
📄
inline.h.h.tar.gz
(11.19 KB)
📄
inline.h.tar
(47 KB)
📄
inode-nr.tar
(2 KB)
📄
inode-nr.tar.gz
(118 B)
📄
inode-state.tar
(2 KB)
📄
inode-state.tar.gz
(124 B)
📄
inotify.h.h.tar.gz
(695 B)
📄
inotify.h.tar
(3 KB)
📄
inotify.tar
(4 KB)
📄
inotify.tar.gz
(171 B)
📄
inotify.zip
(481 B)
📄
inplace.so.so.tar.gz
(5.82 KB)
📄
inplace.so.tar
(17.5 KB)
📄
input.tar
(4 KB)
📄
input.tar.gz
(628 B)
📄
input.zip
(1.69 KB)
📄
inputrc.tar
(2.5 KB)
📄
inputrc.tar.gz
(513 B)
📄
inside-secure.tar
(3 KB)
📄
inside-secure.tar.gz
(302 B)
📄
inside-secure.zip
(542 B)
📄
inspect.py.py.tar.gz
(27.37 KB)
📄
inspect.py.tar
(275 KB)
📄
inspect.pyc.pyc.tar.gz
(14.17 KB)
📄
inspect.pyc.tar
(41 KB)
📄
inspect.pyo.pyo.tar.gz
(14.17 KB)
📄
inspect.pyo.tar
(41 KB)
📄
install-sh.tar
(8.5 KB)
📄
install-sh.tar.gz
(3.03 KB)
📄
install.d.tar
(28.5 KB)
📄
install.d.tar.gz
(5.3 KB)
📄
install.d.zip
(22.06 KB)
📄
install.dat.dat.tar.gz
(108 B)
📄
install.dat.tar
(1.5 KB)
📄
install.js.js.tar.gz
(495 B)
📄
install.js.tar
(621.5 KB)
📄
install.lock.lock.tar.gz
(132 B)
📄
install.lock.tar
(2 KB)
📄
install.php.php.tar.gz
(5.88 KB)
📄
install.php.tar
(7.22 MB)
📄
install.sh.sh.tar.gz
(2.2 KB)
📄
install.sh.tar
(7 KB)
📄
install.tar
(158 KB)
📄
install.tar.gz
(75.65 KB)
📄
install.xml.tar
(1.01 MB)
📄
install.xml.xml.tar.gz
(1.09 KB)
📄
install_timestamp.tar
(2 KB)
📄
install_timestamp.tar.gz
(124 B)
📄
installed.tar
(2 KB)
📄
installed.tar.gz
(134 B)
📄
installed_languages.inc.inc.tar.gz
(493 B)
📄
installed_languages.inc.tar
(2.5 KB)
📄
installed_version.php.php.tar.gz
(346 B)
📄
installed_version.php.tar
(2 KB)
📄
instance.php.php.tar.gz
(399 B)
📄
instance.php.tar
(2 KB)
📄
instantcms.tar
(12.75 MB)
📄
instantcms.tar.gz
(10.51 MB)
📄
instantcms.zip
(12.72 MB)
📄
instdso.sh.sh.tar.gz
(1.46 KB)
📄
instdso.sh.tar
(5 KB)
📄
instmodsh.tar
(6 KB)
📄
instmodsh.tar.gz
(1.36 KB)
📄
int-l64.h.h.tar.gz
(472 B)
📄
int-l64.h.tar
(2.5 KB)
📄
int-ll64.h.h.tar.gz
(509 B)
📄
int-ll64.h.tar
(2.5 KB)
📄
intdiv.so.so.tar.gz
(5.09 KB)
📄
intdiv.so.tar
(13.5 KB)
📄
intel-sst.tar
(2 KB)
📄
intel-sst.tar.gz
(191 B)
📄
intel-sst.zip
(271 B)
📄
intel.tar
(6 KB)
📄
intel.tar.gz
(1.33 KB)
📄
intel.zip
(4.53 KB)
📄
interfaces.h.h.tar.gz
(558 B)
📄
interfaces.h.tar
(3 KB)
📄
internal.tar
(85.5 KB)
📄
internal.tar.gz
(18.31 KB)
📄
internal.xml.tar
(2 KB)
📄
internal.xml.xml.tar.gz
(331 B)
📄
internal.zip
(70.56 KB)
📄
interworx.tar
(7.5 KB)
📄
interworx.tar.gz
(1.95 KB)
📄
interworx.zip
(6.01 KB)
📄
intl.tar
(2.13 MB)
📄
intl.tar.gz
(823.32 KB)
📄
intl.zip
(2.13 MB)
📄
intrcheck.h.h.tar.gz
(490 B)
📄
intrcheck.h.tar
(2.5 KB)
📄
intro.html.html.tar.gz
(3.13 KB)
📄
intro.html.tar
(11.5 KB)
📄
intrpvar.h.h.tar.gz
(10.26 KB)
📄
intrpvar.h.tar
(30.5 KB)
📄
inttypes.h.h.tar.gz
(2.39 KB)
📄
inttypes.h.tar
(13.5 KB)
📄
invlist_inline.h.h.tar.gz
(1.25 KB)
📄
invlist_inline.h.tar
(4.5 KB)
📄
invoice.sql.sql.tar.gz
(4.24 KB)
📄
invoice.sql.tar
(29.5 KB)
📄
invoice.tar
(26.25 MB)
📄
invoice.tar.gz
(25.4 MB)
📄
invoice.zip
(26.23 MB)
📄
io-console-0.4.6.tar
(21.5 KB)
📄
io-console-0.4.6.tar.gz
(8.38 KB)
📄
io-console-0.4.6.zip
(19.96 KB)
📄
io-wmf.so.so.tar.gz
(4.78 KB)
📄
io-wmf.so.tar
(13.5 KB)
📄
io.cpython-38.pyc.cpython-38.pyc.tar.gz
(1.84 KB)
📄
io.cpython-38.pyc.tar
(5 KB)
📄
io.h.h.tar.gz
(1.34 KB)
📄
io.h.tar
(6.5 KB)
📄
io.py.py.tar.gz
(1.53 KB)
📄
io.py.tar
(13 KB)
📄
io.pyc.pyc.tar.gz
(1.77 KB)
📄
io.pyc.tar
(5.5 KB)
📄
io.pyo.pyo.tar.gz
(1.77 KB)
📄
io.pyo.tar
(5.5 KB)
📄
io.tar
(34.5 KB)
📄
io.tar.gz
(193 B)
📄
io.zip
(20.48 KB)
📄
io_delay_type.tar
(2 KB)
📄
io_delay_type.tar.gz
(114 B)
📄
io_lock.lock.lock.tar.gz
(116 B)
📄
io_lock.lock.tar
(2 KB)
📄
ioctl-types.h.h.tar.gz
(1.17 KB)
📄
ioctl-types.h.tar
(4 KB)
📄
ioctl-types.ph.ph.tar.gz
(583 B)
📄
ioctl-types.ph.tar
(3.5 KB)
📄
ioctl.h.h.tar.gz
(1.28 KB)
📄
ioctl.h.tar
(8.5 KB)
📄
ioctl.ph.ph.tar.gz
(259 B)
📄
ioctl.ph.tar
(4 KB)
📄
ioctls.h.h.tar.gz
(1.71 KB)
📄
ioctls.h.tar
(7 KB)
📄
ioctls.ph.ph.tar.gz
(175 B)
📄
ioctls.ph.tar
(6.5 KB)
📄
ioncube.php.php.tar.gz
(263 B)
📄
ioncube.php.tar
(2 KB)
📄
ionice.tar
(30.5 KB)
📄
ionice.tar.gz
(12.45 KB)
📄
iorw.mod.mod.tar.gz
(1.5 KB)
📄
iorw.mod.tar
(5 KB)
📄
iothr.h.h.tar.gz
(4.19 KB)
📄
iothr.h.tar
(17 KB)
📄
ip-header-bad.xml.tar
(2 KB)
📄
ip-header-bad.xml.xml.tar.gz
(264 B)
📄
ip.h.h.tar.gz
(3.4 KB)
📄
ip.h.tar
(11 KB)
📄
ip.tar
(695 KB)
📄
ip.tar.gz
(306.71 KB)
📄
ip6.h.h.tar.gz
(1.84 KB)
📄
ip6.h.tar
(7 KB)
📄
ip6frag_low_thresh.tar
(2 KB)
📄
ip6frag_low_thresh.tar.gz
(126 B)
📄
ip6frag_time.tar
(2 KB)
📄
ip6frag_time.tar.gz
(115 B)
📄
ip_dynaddr.tar
(2 KB)
📄
ip_dynaddr.tar.gz
(111 B)
📄
ip_early_demux.tar
(2 KB)
📄
ip_early_demux.tar.gz
(116 B)
📄
ip_forward.tar
(2 KB)
📄
ip_forward.tar.gz
(111 B)
📄
ip_no_pmtu_disc.tar
(2 KB)
📄
ip_no_pmtu_disc.tar.gz
(117 B)
📄
ip_nonlocal_bind.tar
(3 KB)
📄
ip_nonlocal_bind.tar.gz
(118 B)
📄
ipaddress.py.py.tar.gz
(14.54 KB)
📄
ipaddress.py.tar
(148 KB)
📄
ipc.h.h.tar.gz
(1.05 KB)
📄
ipc.h.tar
(6 KB)
📄
ipcbuf.h.h.tar.gz
(128 B)
📄
ipcbuf.h.tar
(2 KB)
📄
ipconfig.php.php.tar.gz
(1.81 KB)
📄
ipconfig.php.tar
(5 KB)
📄
ipcrm.tar
(30.5 KB)
📄
ipcrm.tar.gz
(13.08 KB)
📄
ipcs.tar
(55 KB)
📄
ipcs.tar.gz
(23.47 KB)
📄
ipctypes.h.h.tar.gz
(734 B)
📄
ipctypes.h.tar
(3 KB)
📄
iperlsys.h.h.tar.gz
(9.13 KB)
📄
iperlsys.h.tar
(49.5 KB)
📄
ipfrag_high_thresh.tar
(2 KB)
📄
ipfrag_high_thresh.tar.gz
(124 B)
📄
ipfrag_max_dist.tar
(2 KB)
📄
ipfrag_max_dist.tar.gz
(118 B)
📄
ipfrag_time.tar
(2 KB)
📄
ipfrag_time.tar.gz
(114 B)
📄
ipmi.service.service.tar.gz
(257 B)
📄
ipmi.service.tar
(2 KB)
📄
ipp.xml.tar
(3 KB)
📄
ipp.xml.xml.tar.gz
(345 B)
📄
iprdump.service.service.tar.gz
(248 B)
📄
iprdump.service.tar
(2 KB)
📄
iprinit.service.service.tar.gz
(226 B)
📄
iprinit.service.tar
(2 KB)
📄
iprupdate.service.service.tar.gz
(226 B)
📄
iprupdate.service.tar
(2 KB)
📄
iprutils.target.tar
(2 KB)
📄
iprutils.target.target.tar.gz
(224 B)
📄
ipsec.xml.tar
(2.5 KB)
📄
ipsec.xml.xml.tar.gz
(555 B)
📄
ipsets.tar
(2 KB)
📄
ipsets.tar.gz
(118 B)
📄
ipsets.zip
(175 B)
📄
iptraf-ng.conf.conf.tar.gz
(140 B)
📄
iptraf-ng.conf.tar
(2 KB)
📄
ipu.tar
(25.82 MB)
📄
ipu.tar.gz
(5.16 MB)
📄
ipu.zip
(25.81 MB)
📄
ipu3-fw.bin.bin.tar.gz
(381.84 KB)
📄
ipu3-fw.bin.tar
(2.32 MB)
📄
ipu6_fw.bin.bin.tar.gz
(256.08 KB)
📄
ipu6_fw.bin.tar
(461.5 KB)
📄
ipu6ep_fw.bin.bin.tar.gz
(254.85 KB)
📄
ipu6ep_fw.bin.tar
(457.5 KB)
📄
ipu6epmtl_fw.bin.bin.tar.gz
(255.35 KB)
📄
ipu6epmtl_fw.bin.tar
(457.5 KB)
📄
ipu6se_fw.bin.bin.tar.gz
(219.78 KB)
📄
ipu6se_fw.bin.tar
(373.5 KB)
📄
ipu7_fw.bin.bin.tar.gz
(155.94 KB)
📄
ipu7_fw.bin.tar
(261.5 KB)
📄
ipx.h.h.tar.gz
(1.22 KB)
📄
ipx.h.tar
(4.5 KB)
📄
irb.tar
(12 KB)
📄
irb.tar.gz
(341 B)
📄
irc.xml.tar
(4 KB)
📄
irc.xml.xml.tar.gz
(275 B)
📄
ircs.xml.tar
(2 KB)
📄
ircs.xml.xml.tar.gz
(286 B)
📄
irdma-abi.h.h.tar.gz
(924 B)
📄
irdma-abi.h.tar
(4 KB)
📄
irix_sgid_inherit.tar
(2 KB)
📄
irix_sgid_inherit.tar.gz
(117 B)
📄
irix_symlink_mode.tar
(2 KB)
📄
irix_symlink_mode.tar.gz
(117 B)
📄
irq.tar
(205 KB)
📄
irq.tar.gz
(2.75 KB)
📄
irq.zip
(31.51 KB)
📄
irs.tar
(22.5 KB)
📄
irs.tar.gz
(4.41 KB)
📄
irs.zip
(17.29 KB)
📄
isc-hmac-fixup.tar
(13.5 KB)
📄
isc-hmac-fixup.tar.gz
(4.8 KB)
📄
isc.tar
(542 KB)
📄
isc.tar.gz
(111.12 KB)
📄
isc.zip
(474.34 KB)
📄
iscanonical.h.h.tar.gz
(1.25 KB)
📄
iscanonical.h.tar
(4 KB)
📄
isccc.tar
(44 KB)
📄
isccc.tar.gz
(6.48 KB)
📄
isccc.zip
(34.46 KB)
📄
isccfg.tar
(42.5 KB)
📄
isccfg.tar.gz
(8.34 KB)
📄
isccfg.zip
(36.96 KB)
📄
isci.tar
(2 KB)
📄
isci.tar.gz
(149 B)
📄
isci.zip
(400 B)
📄
isci_firmware.bin.bin.tar.gz
(163 B)
📄
isci_firmware.bin.tar
(2 KB)
📄
iscsi-target.xml.tar
(2 KB)
📄
iscsi-target.xml.xml.tar.gz
(268 B)
📄
isdbt_nova_12mhz.inp.inp.tar.gz
(45.27 KB)
📄
isdbt_nova_12mhz.inp.tar
(76 KB)
📄
isdbt_nova_12mhz_b0.inp.inp.tar.gz
(60.73 KB)
📄
isdbt_nova_12mhz_b0.inp.tar
(98 KB)
📄
isdbt_rio.inp.inp.tar.gz
(50.72 KB)
📄
isdbt_rio.inp.tar
(170 KB)
📄
ish.tar
(2.25 MB)
📄
ish.tar.gz
(267.53 KB)
📄
ish.zip
(2.25 MB)
📄
ish_lnlm.bin.bin.tar.gz
(455.89 KB)
📄
ish_lnlm.bin.tar
(976 KB)
📄
ish_lnlm_12128606.bin.bin.tar.gz
(362.53 KB)
📄
ish_lnlm_12128606.bin.tar
(844 KB)
📄
ish_ptl.bin.bin.tar.gz
(459.46 KB)
📄
ish_ptl.bin.tar
(1.76 MB)
📄
isns.xml.tar
(2 KB)
📄
isns.xml.xml.tar.gz
(337 B)
📄
iso-8859-1.cmap.cmap.tar.gz
(6.39 KB)
📄
iso-8859-1.cmap.tar
(32 KB)
📄
iso-8859-1.cset.cset.tar.gz
(3.49 KB)
📄
iso-8859-1.cset.tar
(15.5 KB)
📄
iso-8859-10.cmap.cmap.tar.gz
(6.55 KB)
📄
iso-8859-10.cmap.tar
(32 KB)
📄
iso-8859-10.cset.cset.tar.gz
(3.45 KB)
📄
iso-8859-10.cset.tar
(15.5 KB)
📄
iso-8859-11.cmap.cmap.tar.gz
(5.95 KB)
📄
iso-8859-11.cmap.tar
(28 KB)
📄
iso-8859-11.cset.cset.tar.gz
(3.38 KB)
📄
iso-8859-11.cset.tar
(14.5 KB)
📄
iso-8859-13.cmap.cmap.tar.gz
(6.53 KB)
📄
iso-8859-13.cmap.tar
(32 KB)
📄
iso-8859-13.cset.cset.tar.gz
(3.52 KB)
📄
iso-8859-13.cset.tar
(15.5 KB)
📄
iso-8859-14.cmap.cmap.tar.gz
(6.46 KB)
📄
iso-8859-14.cmap.tar
(32.5 KB)
📄
iso-8859-14.cset.cset.tar.gz
(3.41 KB)
📄
iso-8859-14.cset.tar
(16 KB)
📄
iso-8859-15.cmap.cmap.tar.gz
(6.37 KB)
📄
iso-8859-15.cmap.tar
(32 KB)
📄
iso-8859-15.cset.cset.tar.gz
(3.48 KB)
📄
iso-8859-15.cset.tar
(15.5 KB)
📄
iso-8859-16.cmap.cmap.tar.gz
(6.5 KB)
📄
iso-8859-16.cmap.tar
(32 KB)
📄
iso-8859-16.cset.cset.tar.gz
(3.46 KB)
📄
iso-8859-16.cset.tar
(15.5 KB)
📄
iso-8859-2.cmap.cmap.tar.gz
(6.59 KB)
📄
iso-8859-2.cmap.tar
(32.5 KB)
📄
iso-8859-2.cset.cset.tar.gz
(3.43 KB)
📄
iso-8859-2.cset.tar
(15.5 KB)
📄
iso-8859-3.cmap.cmap.tar.gz
(6.44 KB)
📄
iso-8859-3.cmap.tar
(32 KB)
📄
iso-8859-3.cset.cset.tar.gz
(3.44 KB)
📄
iso-8859-3.cset.tar
(15.5 KB)
📄
iso-8859-4.cmap.cmap.tar.gz
(6.57 KB)
📄
iso-8859-4.cmap.tar
(32 KB)
📄
iso-8859-4.cset.cset.tar.gz
(3.44 KB)
📄
iso-8859-4.cset.tar
(15.5 KB)
📄
iso-8859-5.cmap.cmap.tar.gz
(6.44 KB)
📄
iso-8859-5.cmap.tar
(33 KB)
📄
iso-8859-5.cset.cset.tar.gz
(3.51 KB)
📄
iso-8859-5.cset.tar
(15 KB)
📄
iso-8859-6.cmap.cmap.tar.gz
(9 KB)
📄
iso-8859-6.cmap.tar
(42 KB)
📄
iso-8859-6.cset.cset.tar.gz
(3.22 KB)
📄
iso-8859-6.cset.tar
(14 KB)
📄
iso-8859-7.cmap.cmap.tar.gz
(7.51 KB)
📄
iso-8859-7.cmap.tar
(39.5 KB)
📄
iso-8859-7.cset.cset.tar.gz
(3.56 KB)
📄
iso-8859-7.cset.tar
(15 KB)
📄
iso-8859-8.cmap.cmap.tar.gz
(6.05 KB)
📄
iso-8859-8.cmap.tar
(29 KB)
📄
iso-8859-8.cset.cset.tar.gz
(3.31 KB)
📄
iso-8859-8.cset.tar
(14 KB)
📄
iso-8859-9.cmap.cmap.tar.gz
(6.44 KB)
📄
iso-8859-9.cmap.tar
(32 KB)
📄
iso-8859-9.cset.cset.tar.gz
(3.5 KB)
📄
iso-8859-9.cset.tar
(15.5 KB)
📄
iso01.uni.tar
(4 KB)
📄
iso01.uni.uni.tar.gz
(408 B)
📄
iso02.uni.tar
(6 KB)
📄
iso02.uni.uni.tar.gz
(806 B)
📄
iso02_to_cp1250.trans.tar
(7.5 KB)
📄
iso02_to_cp1250.trans.trans.tar.gz
(1.58 KB)
📄
iso03.uni.tar
(6 KB)
📄
iso03.uni.uni.tar.gz
(810 B)
📄
iso04.uni.tar
(6 KB)
📄
iso04.uni.uni.tar.gz
(810 B)
📄
iso05.uni.tar
(6 KB)
📄
iso05.uni.uni.tar.gz
(790 B)
📄
iso06.uni.tar
(5 KB)
📄
iso06.uni.uni.tar.gz
(623 B)
📄
iso07.uni.tar
(6 KB)
📄
iso07.uni.uni.tar.gz
(773 B)
📄
iso07u.uni.tar
(7 KB)
📄
iso07u.uni.uni.tar.gz
(1.09 KB)
📄
iso08.uni.tar
(5 KB)
📄
iso08.uni.uni.tar.gz
(570 B)
📄
iso09.uni.tar
(4 KB)
📄
iso09.uni.uni.tar.gz
(460 B)
📄
iso10.uni.tar
(5 KB)
📄
iso10.uni.uni.tar.gz
(710 B)
📄
iso15.uni.tar
(4 KB)
📄
iso15.uni.uni.tar.gz
(494 B)
📄
iso2022.so.so.tar.gz
(4.91 KB)
📄
iso2022.so.tar
(17.5 KB)
📄
iso9660.mod.mod.tar.gz
(5.83 KB)
📄
iso9660.mod.tar
(14.5 KB)
📄
iso_8859_1.so.so.tar.gz
(4.16 KB)
📄
iso_8859_1.so.tar
(13.5 KB)
📄
iso_8859_10.so.so.tar.gz
(4.33 KB)
📄
iso_8859_10.so.tar
(13.5 KB)
📄
iso_8859_11.so.so.tar.gz
(3.26 KB)
📄
iso_8859_11.so.tar
(13 KB)
📄
iso_8859_13.so.so.tar.gz
(4.32 KB)
📄
iso_8859_13.so.tar
(13.5 KB)
📄
iso_8859_14.so.so.tar.gz
(4.43 KB)
📄
iso_8859_14.so.tar
(13.5 KB)
📄
iso_8859_15.so.so.tar.gz
(4.38 KB)
📄
iso_8859_15.so.tar
(13.5 KB)
📄
iso_8859_16.so.so.tar.gz
(4.43 KB)
📄
iso_8859_16.so.tar
(13.5 KB)
📄
iso_8859_2.so.so.tar.gz
(4.31 KB)
📄
iso_8859_2.so.tar
(13.5 KB)
📄
iso_8859_3.so.so.tar.gz
(4.44 KB)
📄
iso_8859_3.so.tar
(13.5 KB)
📄
iso_8859_4.so.so.tar.gz
(4.36 KB)
📄
iso_8859_4.so.tar
(13.5 KB)
📄
iso_8859_5.so.so.tar.gz
(4.11 KB)
📄
iso_8859_5.so.tar
(13.5 KB)
📄
iso_8859_6.so.so.tar.gz
(3.27 KB)
📄
iso_8859_6.so.tar
(13 KB)
📄
iso_8859_7.so.so.tar.gz
(4.23 KB)
📄
iso_8859_7.so.tar
(13.5 KB)
📄
iso_8859_8.so.so.tar.gz
(3.28 KB)
📄
iso_8859_8.so.tar
(13 KB)
📄
iso_8859_9.so.so.tar.gz
(4.38 KB)
📄
iso_8859_9.so.tar
(13.5 KB)
📄
isort.tar
(2 KB)
📄
isort.tar.gz
(229 B)
📄
isosize.tar
(26.5 KB)
📄
isosize.tar.gz
(11.69 KB)
📄
isp.conf.php.conf.php.tar.gz
(415 B)
📄
isp.conf.php.tar
(2.5 KB)
📄
isp1000.bin.bin.tar.gz
(11.02 KB)
📄
isp1000.bin.tar
(20 KB)
📄
isp_4_1_1.bin.bin.tar.gz
(1.68 MB)
📄
isp_4_1_1.bin.tar
(3.68 MB)
📄
ispell.tar
(2.5 KB)
📄
ispell.tar.gz
(533 B)
📄
ispmanager.tar
(7.5 KB)
📄
ispmanager.tar.gz
(2 KB)
📄
ispmanager.zip
(6.12 KB)
📄
ist.h.h.tar.gz
(633 B)
📄
ist.h.tar
(2.5 KB)
📄
it.tar
(170 KB)
📄
it.tar.gz
(137.26 KB)
📄
it.zip
(141.9 KB)
📄
iterators.py.py.tar.gz
(1020 B)
📄
iterators.py.tar
(10 KB)
📄
iterobject.h.h.tar.gz
(358 B)
📄
iterobject.h.tar
(2.5 KB)
📄
itunes.rb.rb.tar.gz
(2.27 KB)
📄
itunes.rb.tar
(77 KB)
📄
iucv.h.h.tar.gz
(918 B)
📄
iucv.h.tar
(3.5 KB)
📄
ivpu_accel.h.h.tar.gz
(2.76 KB)
📄
ivpu_accel.h.tar
(10 KB)
📄
ivsc_fw.bin.bin.tar.gz
(312.48 KB)
📄
ivsc_fw.bin.tar
(945.5 KB)
📄
iwlwifi-100-5.ucode.tar
(331.5 KB)
📄
iwlwifi-100-5.ucode.ucode.tar.gz
(172.9 KB)
📄
iwlwifi-1000-5.ucode.tar
(331.5 KB)
📄
iwlwifi-1000-5.ucode.ucode.tar.gz
(172.89 KB)
📄
iwlwifi-105-6.ucode.tar
(675.5 KB)
📄
iwlwifi-105-6.ucode.ucode.tar.gz
(325.19 KB)
📄
iwlwifi-135-6.ucode.tar
(686.5 KB)
📄
iwlwifi-135-6.ucode.ucode.tar.gz
(333.79 KB)
📄
iwlwifi-2000-6.ucode.tar
(681.5 KB)
📄
iwlwifi-2000-6.ucode.ucode.tar.gz
(330.93 KB)
📄
iwlwifi-2030-6.ucode.tar
(692.5 KB)
📄
iwlwifi-2030-6.ucode.ucode.tar.gz
(339.17 KB)
📄
iwlwifi-3160-17.ucode.tar
(898.5 KB)
📄
iwlwifi-3160-17.ucode.ucode.tar.gz
(455.71 KB)
📄
iwlwifi-3168-29.ucode.tar
(1013.5 KB)
📄
iwlwifi-3168-29.ucode.ucode.tar.gz
(441.79 KB)
📄
iwlwifi-5000-5.ucode.tar
(668 KB)
📄
iwlwifi-5000-5.ucode.ucode.tar.gz
(173.01 KB)
📄
iwlwifi-5150-2.ucode.tar
(331 KB)
📄
iwlwifi-5150-2.ucode.ucode.tar.gz
(170.08 KB)
📄
iwlwifi-6000-4.ucode.tar
(445.5 KB)
📄
iwlwifi-6000-4.ucode.ucode.tar.gz
(207.77 KB)
📄
iwlwifi-6000g2a-6.ucode.tar
(663 KB)
📄
iwlwifi-6000g2a-6.ucode.ucode.tar.gz
(316.2 KB)
📄
iwlwifi-6050-5.ucode.tar
(460.5 KB)
📄
iwlwifi-6050-5.ucode.ucode.tar.gz
(214.08 KB)
📄
iwlwifi-7260-17.ucode.tar
(1 MB)
📄
iwlwifi-7260-17.ucode.ucode.tar.gz
(481.93 KB)
📄
iwlwifi-7265-17.ucode.tar
(1.13 MB)
📄
iwlwifi-7265-17.ucode.ucode.tar.gz
(522.19 KB)
📄
iwlwifi-7265D-29.ucode.tar
(1014 KB)
📄
iwlwifi-7265D-29.ucode.ucode.tar.gz
(451.23 KB)
📄
iwlwifi-8000C-34.ucode.tar
(2.34 MB)
📄
iwlwifi-8000C-34.ucode.ucode.tar.gz
(940.66 KB)
📄
iwlwifi-8000C-36.ucode.tar
(2.31 MB)
📄
iwlwifi-8000C-36.ucode.ucode.tar.gz
(936.65 KB)
📄
iwlwifi-8265-34.ucode.tar
(2.33 MB)
📄
iwlwifi-8265-34.ucode.ucode.tar.gz
(938.31 KB)
📄
iwlwifi-8265-36.ucode.tar
(2.32 MB)
📄
iwlwifi-8265-36.ucode.ucode.tar.gz
(948.88 KB)
📄
iwlwifi-Qu-b0-hr-b0-50.ucode.tar
(1.05 MB)
📄
iwlwifi-Qu-b0-hr-b0-50.ucode.ucode.tar.gz
(442.64 KB)
📄
iwlwifi-Qu-b0-hr-b0-59.ucode.tar
(1.24 MB)
📄
iwlwifi-Qu-b0-hr-b0-59.ucode.ucode.tar.gz
(503.37 KB)
📄
iwlwifi-Qu-b0-hr-b0-66.ucode.tar
(1.28 MB)
📄
iwlwifi-Qu-b0-hr-b0-66.ucode.ucode.tar.gz
(517.98 KB)
📄
iwlwifi-Qu-b0-hr-b0-72.ucode.tar
(1.31 MB)
📄
iwlwifi-Qu-b0-hr-b0-72.ucode.ucode.tar.gz
(528.02 KB)
📄
iwlwifi-Qu-b0-hr-b0-73.ucode.tar
(1.31 MB)
📄
iwlwifi-Qu-b0-hr-b0-73.ucode.ucode.tar.gz
(530.75 KB)
📄
iwlwifi-Qu-b0-hr-b0-74.ucode.tar
(1.31 MB)
📄
iwlwifi-Qu-b0-hr-b0-74.ucode.ucode.tar.gz
(535.64 KB)
📄
iwlwifi-Qu-b0-hr-b0-77.ucode.tar
(1.34 MB)
📄
iwlwifi-Qu-b0-hr-b0-77.ucode.ucode.tar.gz
(546.7 KB)
📄
iwlwifi-Qu-b0-jf-b0-50.ucode.tar
(1.01 MB)
📄
iwlwifi-Qu-b0-jf-b0-50.ucode.ucode.tar.gz
(424.75 KB)
📄
iwlwifi-Qu-b0-jf-b0-59.ucode.tar
(1.17 MB)
📄
iwlwifi-Qu-b0-jf-b0-59.ucode.ucode.tar.gz
(478.75 KB)
📄
iwlwifi-Qu-b0-jf-b0-66.ucode.tar
(1.21 MB)
📄
iwlwifi-Qu-b0-jf-b0-66.ucode.ucode.tar.gz
(487.89 KB)
📄
iwlwifi-Qu-b0-jf-b0-72.ucode.tar
(1.23 MB)
📄
iwlwifi-Qu-b0-jf-b0-72.ucode.ucode.tar.gz
(495.95 KB)
📄
iwlwifi-Qu-b0-jf-b0-73.ucode.tar
(1.23 MB)
📄
iwlwifi-Qu-b0-jf-b0-73.ucode.ucode.tar.gz
(497.09 KB)
📄
iwlwifi-Qu-b0-jf-b0-74.ucode.tar
(2.46 MB)
📄
iwlwifi-Qu-b0-jf-b0-74.ucode.ucode.tar.gz
(502 KB)
📄
iwlwifi-Qu-b0-jf-b0-77.ucode.tar
(1.26 MB)
📄
iwlwifi-Qu-b0-jf-b0-77.ucode.ucode.tar.gz
(510.64 KB)
📄
iwlwifi-QuZ-a0-hr-b0-50.ucode.tar
(1.05 MB)
📄
iwlwifi-QuZ-a0-hr-b0-50.ucode.ucode.tar.gz
(442.57 KB)
📄
iwlwifi-QuZ-a0-hr-b0-59.ucode.tar
(1.24 MB)
📄
iwlwifi-QuZ-a0-hr-b0-59.ucode.ucode.tar.gz
(503.21 KB)
📄
iwlwifi-QuZ-a0-hr-b0-66.ucode.tar
(1.28 MB)
📄
iwlwifi-QuZ-a0-hr-b0-66.ucode.ucode.tar.gz
(517.9 KB)
📄
iwlwifi-QuZ-a0-hr-b0-72.ucode.tar
(1.31 MB)
📄
iwlwifi-QuZ-a0-hr-b0-72.ucode.ucode.tar.gz
(528.06 KB)
📄
iwlwifi-QuZ-a0-hr-b0-73.ucode.tar
(1.31 MB)
📄
iwlwifi-QuZ-a0-hr-b0-73.ucode.ucode.tar.gz
(530.73 KB)
📄
iwlwifi-QuZ-a0-hr-b0-74.ucode.tar
(1.31 MB)
📄
iwlwifi-QuZ-a0-hr-b0-74.ucode.ucode.tar.gz
(535.65 KB)
📄
iwlwifi-QuZ-a0-hr-b0-77.ucode.tar
(1.34 MB)
📄
iwlwifi-QuZ-a0-hr-b0-77.ucode.ucode.tar.gz
(546.66 KB)
📄
iwlwifi-QuZ-a0-jf-b0-50.ucode.tar
(1.01 MB)
📄
iwlwifi-QuZ-a0-jf-b0-50.ucode.ucode.tar.gz
(424.67 KB)
📄
iwlwifi-QuZ-a0-jf-b0-59.ucode.tar
(1.17 MB)
📄
iwlwifi-QuZ-a0-jf-b0-59.ucode.ucode.tar.gz
(478.68 KB)
📄
iwlwifi-QuZ-a0-jf-b0-66.ucode.tar
(1.21 MB)
📄
iwlwifi-QuZ-a0-jf-b0-66.ucode.ucode.tar.gz
(487.87 KB)
📄
iwlwifi-QuZ-a0-jf-b0-72.ucode.tar
(1.23 MB)
📄
iwlwifi-QuZ-a0-jf-b0-72.ucode.ucode.tar.gz
(495.94 KB)
📄
iwlwifi-QuZ-a0-jf-b0-73.ucode.tar
(1.23 MB)
📄
iwlwifi-QuZ-a0-jf-b0-73.ucode.ucode.tar.gz
(497.15 KB)
📄
iwlwifi-QuZ-a0-jf-b0-74.ucode.tar
(1.23 MB)
📄
iwlwifi-QuZ-a0-jf-b0-74.ucode.ucode.tar.gz
(502.03 KB)
📄
iwlwifi-QuZ-a0-jf-b0-77.ucode.tar
(1.26 MB)
📄
iwlwifi-QuZ-a0-jf-b0-77.ucode.ucode.tar.gz
(510.73 KB)
📄
iwlwifi-bz-b0-fm-c0-100.ucode.tar
(2.12 MB)
📄
iwlwifi-bz-b0-fm-c0-100.ucode.ucode.tar.gz
(759.88 KB)
📄
iwlwifi-bz-b0-fm-c0-101.ucode.tar
(2.12 MB)
📄
iwlwifi-bz-b0-fm-c0-101.ucode.ucode.tar.gz
(760.24 KB)
📄
iwlwifi-bz-b0-gf-a0-100.ucode.tar
(3.51 MB)
📄
iwlwifi-bz-b0-gf-a0-100.ucode.ucode.tar.gz
(622.14 KB)
📄
iwlwifi-bz-b0-hr-b0-100.ucode.tar
(1.51 MB)
📄
iwlwifi-bz-b0-hr-b0-100.ucode.ucode.tar.gz
(543.56 KB)
📄
iwlwifi-cc-a0-50.ucode.tar
(1.05 MB)
📄
iwlwifi-cc-a0-50.ucode.ucode.tar.gz
(441.26 KB)
📄
iwlwifi-cc-a0-59.ucode.tar
(1.2 MB)
📄
iwlwifi-cc-a0-59.ucode.ucode.tar.gz
(497.29 KB)
📄
iwlwifi-cc-a0-66.ucode.tar
(1.25 MB)
📄
iwlwifi-cc-a0-66.ucode.ucode.tar.gz
(511.22 KB)
📄
iwlwifi-cc-a0-72.ucode.tar
(1.27 MB)
📄
iwlwifi-cc-a0-72.ucode.ucode.tar.gz
(521.01 KB)
📄
iwlwifi-cc-a0-73.ucode.tar
(1.27 MB)
📄
iwlwifi-cc-a0-73.ucode.ucode.tar.gz
(522.24 KB)
📄
iwlwifi-cc-a0-74.ucode.tar
(1.27 MB)
📄
iwlwifi-cc-a0-74.ucode.ucode.tar.gz
(526.81 KB)
📄
iwlwifi-cc-a0-77.ucode.tar
(1.31 MB)
📄
iwlwifi-cc-a0-77.ucode.ucode.tar.gz
(538.1 KB)
📄
iwlwifi-gl-c0-fm-c0-83.ucode.tar
(5.15 MB)
📄
iwlwifi-gl-c0-fm-c0-83.ucode.ucode.tar.gz
(609.5 KB)
📄
iwlwifi-gl-c0-fm-c0-86.ucode.tar
(1.76 MB)
📄
iwlwifi-gl-c0-fm-c0-86.ucode.ucode.tar.gz
(632.6 KB)
📄
iwlwifi-gl-c0-fm-c0-90.ucode.tar
(1.81 MB)
📄
iwlwifi-gl-c0-fm-c0-90.ucode.ucode.tar.gz
(655.59 KB)
📄
iwlwifi-gl-c0-fm-c0-92.ucode.tar
(1.83 MB)
📄
iwlwifi-gl-c0-fm-c0-92.ucode.ucode.tar.gz
(656.77 KB)
📄
iwlwifi-gl-c0-fm-c0-94.ucode.tar
(1.83 MB)
📄
iwlwifi-gl-c0-fm-c0-94.ucode.ucode.tar.gz
(663.16 KB)
📄
iwlwifi-gl-c0-fm-c0-96.ucode.tar
(1.83 MB)
📄
iwlwifi-gl-c0-fm-c0-96.ucode.ucode.tar.gz
(665.73 KB)
📄
iwlwifi-gl-c0-fm-c0-97.ucode.tar
(1.82 MB)
📄
iwlwifi-gl-c0-fm-c0-97.ucode.ucode.tar.gz
(667.72 KB)
📄
iwlwifi-gl-c0-fm-c0-98.ucode.tar
(1.82 MB)
📄
iwlwifi-gl-c0-fm-c0-98.ucode.ucode.tar.gz
(668.47 KB)
📄
iwlwifi-ma-b0-gf4-a0-83.ucode.tar
(1.64 MB)
📄
iwlwifi-ma-b0-gf4-a0-83.ucode.ucode.tar.gz
(626.22 KB)
📄
iwlwifi-ma-b0-gf4-a0-86.ucode.tar
(1.6 MB)
📄
iwlwifi-ma-b0-gf4-a0-86.ucode.ucode.tar.gz
(632.95 KB)
📄
iwlwifi-ma-b0-gf4-a0-89.ucode.tar
(1.53 MB)
📄
iwlwifi-ma-b0-gf4-a0-89.ucode.ucode.tar.gz
(597.92 KB)
📄
iwlwifi-ma-b0-gf4-a0.pnvm.pnvm.tar.gz
(4.9 KB)
📄
iwlwifi-ma-b0-gf4-a0.pnvm.tar
(29 KB)
📄
iwlwifi-ma-b0-hr-b0-83.ucode.tar
(1.5 MB)
📄
iwlwifi-ma-b0-hr-b0-83.ucode.ucode.tar.gz
(580.01 KB)
📄
iwlwifi-ma-b0-hr-b0-86.ucode.tar
(1.45 MB)
📄
iwlwifi-ma-b0-hr-b0-86.ucode.ucode.tar.gz
(583.87 KB)
📄
iwlwifi-ma-b0-hr-b0-89.ucode.tar
(1.47 MB)
📄
iwlwifi-ma-b0-hr-b0-89.ucode.ucode.tar.gz
(590.24 KB)
📄
iwlwifi-sc-a0-wh-b0-101.ucode.tar
(2 MB)
📄
iwlwifi-sc-a0-wh-b0-101.ucode.ucode.tar.gz
(751.75 KB)
📄
iwlwifi-so-a0-gf-a0-72.ucode.tar
(1.49 MB)
📄
iwlwifi-so-a0-gf-a0-72.ucode.ucode.tar.gz
(585.86 KB)
📄
iwlwifi-so-a0-gf-a0-73.ucode.tar
(1.49 MB)
📄
iwlwifi-so-a0-gf-a0-73.ucode.ucode.tar.gz
(586.16 KB)
📄
iwlwifi-so-a0-gf-a0-74.ucode.tar
(1.51 MB)
📄
iwlwifi-so-a0-gf-a0-74.ucode.ucode.tar.gz
(597.33 KB)
📄
iwlwifi-so-a0-gf-a0-77.ucode.tar
(1.57 MB)
📄
iwlwifi-so-a0-gf-a0-77.ucode.ucode.tar.gz
(608.42 KB)
📄
iwlwifi-so-a0-gf-a0-78.ucode.tar
(1.59 MB)
📄
iwlwifi-so-a0-gf-a0-78.ucode.ucode.tar.gz
(617.43 KB)
📄
iwlwifi-so-a0-gf-a0-79.ucode.tar
(1.6 MB)
📄
iwlwifi-so-a0-gf-a0-79.ucode.ucode.tar.gz
(617.58 KB)
📄
iwlwifi-so-a0-gf-a0-81.ucode.tar
(1.61 MB)
📄
iwlwifi-so-a0-gf-a0-81.ucode.ucode.tar.gz
(621.32 KB)
📄
iwlwifi-so-a0-gf-a0-83.ucode.tar
(1.66 MB)
📄
iwlwifi-so-a0-gf-a0-83.ucode.ucode.tar.gz
(626.67 KB)
📄
iwlwifi-so-a0-gf-a0-84.ucode.tar
(1.66 MB)
📄
iwlwifi-so-a0-gf-a0-84.ucode.ucode.tar.gz
(628.45 KB)
📄
iwlwifi-so-a0-gf-a0-86.ucode.tar
(1.6 MB)
📄
iwlwifi-so-a0-gf-a0-86.ucode.ucode.tar.gz
(637.13 KB)
📄
iwlwifi-so-a0-gf-a0-89.ucode.tar
(1.66 MB)
📄
iwlwifi-so-a0-gf-a0-89.ucode.ucode.tar.gz
(653.56 KB)
📄
iwlwifi-so-a0-gf4-a0-72.ucode.tar
(1.51 MB)
📄
iwlwifi-so-a0-gf4-a0-72.ucode.ucode.tar.gz
(593.72 KB)
📄
iwlwifi-so-a0-gf4-a0-73.ucode.tar
(1.52 MB)
📄
iwlwifi-so-a0-gf4-a0-73.ucode.ucode.tar.gz
(595.71 KB)
📄
iwlwifi-so-a0-gf4-a0-74.ucode.tar
(3.06 MB)
📄
iwlwifi-so-a0-gf4-a0-74.ucode.ucode.tar.gz
(606.35 KB)
📄
iwlwifi-so-a0-gf4-a0-77.ucode.tar
(1.59 MB)
📄
iwlwifi-so-a0-gf4-a0-77.ucode.ucode.tar.gz
(617.76 KB)
📄
iwlwifi-so-a0-gf4-a0-78.ucode.tar
(1.63 MB)
📄
iwlwifi-so-a0-gf4-a0-78.ucode.ucode.tar.gz
(625.72 KB)
📄
iwlwifi-so-a0-gf4-a0-79.ucode.tar
(1.64 MB)
📄
iwlwifi-so-a0-gf4-a0-79.ucode.ucode.tar.gz
(625.61 KB)
📄
iwlwifi-so-a0-gf4-a0-81.ucode.tar
(1.62 MB)
📄
iwlwifi-so-a0-gf4-a0-81.ucode.ucode.tar.gz
(616.73 KB)
📄
iwlwifi-so-a0-gf4-a0-83.ucode.tar
(1.63 MB)
📄
iwlwifi-so-a0-gf4-a0-83.ucode.ucode.tar.gz
(619.84 KB)
📄
iwlwifi-so-a0-gf4-a0-84.ucode.tar
(1.63 MB)
📄
iwlwifi-so-a0-gf4-a0-84.ucode.ucode.tar.gz
(621.87 KB)
📄
iwlwifi-so-a0-gf4-a0-86.ucode.tar
(1.58 MB)
📄
iwlwifi-so-a0-gf4-a0-86.ucode.ucode.tar.gz
(626.12 KB)
📄
iwlwifi-so-a0-gf4-a0-89.ucode.tar
(1.52 MB)
📄
iwlwifi-so-a0-gf4-a0-89.ucode.ucode.tar.gz
(590.9 KB)
📄
iwlwifi-so-a0-gf4-a0.pnvm.pnvm.tar.gz
(4.91 KB)
📄
iwlwifi-so-a0-gf4-a0.pnvm.tar
(29 KB)
📄
iwlwifi-so-a0-jf-b0-73.ucode.tar
(1.35 MB)
📄
iwlwifi-so-a0-jf-b0-73.ucode.ucode.tar.gz
(516.19 KB)
📄
iwlwifi-ty-a0-gf-a0-59.ucode.tar
(2.7 MB)
📄
iwlwifi-ty-a0-gf-a0-59.ucode.ucode.tar.gz
(531.7 KB)
📄
iwlwifi-ty-a0-gf-a0-66.ucode.tar
(1.42 MB)
📄
iwlwifi-ty-a0-gf-a0-66.ucode.ucode.tar.gz
(564.65 KB)
📄
iwlwifi-ty-a0-gf-a0-72.ucode.tar
(1.43 MB)
📄
iwlwifi-ty-a0-gf-a0-72.ucode.ucode.tar.gz
(575.16 KB)
📄
iwlwifi-ty-a0-gf-a0-73.ucode.tar
(1.44 MB)
📄
iwlwifi-ty-a0-gf-a0-73.ucode.ucode.tar.gz
(576.83 KB)
📄
iwlwifi-ty-a0-gf-a0-74.ucode.tar
(1.46 MB)
📄
iwlwifi-ty-a0-gf-a0-74.ucode.ucode.tar.gz
(593.93 KB)
📄
iwlwifi-ty-a0-gf-a0-77.ucode.tar
(1.52 MB)
📄
iwlwifi-ty-a0-gf-a0-77.ucode.ucode.tar.gz
(601.66 KB)
📄
iwlwifi-ty-a0-gf-a0-78.ucode.tar
(1.55 MB)
📄
iwlwifi-ty-a0-gf-a0-78.ucode.ucode.tar.gz
(610.31 KB)
📄
iwlwifi-ty-a0-gf-a0-79.ucode.tar
(1.55 MB)
📄
iwlwifi-ty-a0-gf-a0-79.ucode.ucode.tar.gz
(610.17 KB)
📄
iwlwifi-ty-a0-gf-a0-81.ucode.tar
(1.56 MB)
📄
iwlwifi-ty-a0-gf-a0-81.ucode.ucode.tar.gz
(613.1 KB)
📄
iwlwifi-ty-a0-gf-a0-83.ucode.tar
(1.61 MB)
📄
iwlwifi-ty-a0-gf-a0-83.ucode.ucode.tar.gz
(617.99 KB)
📄
iwlwifi-ty-a0-gf-a0-84.ucode.tar
(1.6 MB)
📄
iwlwifi-ty-a0-gf-a0-84.ucode.ucode.tar.gz
(620.2 KB)
📄
iwlwifi-ty-a0-gf-a0-86.ucode.tar
(1.56 MB)
📄
iwlwifi-ty-a0-gf-a0-86.ucode.ucode.tar.gz
(626.2 KB)
📄
iwlwifi-ty-a0-gf-a0-89.ucode.tar
(1.6 MB)
📄
iwlwifi-ty-a0-gf-a0-89.ucode.ucode.tar.gz
(642.22 KB)
📄
iwlwifi.tar
(244.34 MB)
📄
iwlwifi.tar.gz
(94.04 MB)
📄
iwlwifi.zip
(244.24 MB)
📄
iwp.png.png.tar.gz
(7.28 KB)
📄
iwp.png.tar
(9 KB)
📄
iwp.sql.sql.tar.gz
(3.49 KB)
📄
iwp.sql.tar
(22.5 KB)
📄
iwp.tar
(7.15 MB)
📄
iwp.tar.gz
(6.92 MB)
📄
iwp.zip
(7.13 MB)
📄
ixp4xx.tar
(68.5 KB)
📄
ixp4xx.tar.gz
(19.59 KB)
📄
ixp4xx.zip
(65.27 KB)
📄
ja.tar
(173 KB)
📄
ja.tar.gz
(132.44 KB)
📄
ja.zip
(142.52 KB)
📄
jamroom.sql.sql.tar.gz
(41.9 KB)
📄
jamroom.sql.tar
(235.5 KB)
📄
jamroom.tar
(28.7 MB)
📄
jamroom.tar.gz
(27.73 MB)
📄
jamroom.zip
(28.67 MB)
📄
japanese_euc.so.so.tar.gz
(180.65 KB)
📄
japanese_euc.so.tar
(353 KB)
📄
jbd2.tar
(7 KB)
📄
jbd2.tar.gz
(553 B)
📄
jbd2.zip
(3.07 KB)
📄
jconfig-64.h.h.tar.gz
(1.04 KB)
📄
jconfig-64.h.tar
(4 KB)
📄
jconfig.h.h.tar.gz
(252 B)
📄
jconfig.h.tar
(2 KB)
📄
jcow.png.png.tar.gz
(11.98 KB)
📄
jcow.png.tar
(13.5 KB)
📄
jcow.tar
(182 KB)
📄
jcow.tar.gz
(95.43 KB)
📄
jcow.zip
(155.11 KB)
📄
jemalloc.pc.pc.tar.gz
(325 B)
📄
jemalloc.pc.tar
(2 KB)
📄
jemalloc.tar
(16 KB)
📄
jemalloc.tar.gz
(3.4 KB)
📄
jemalloc.zip
(14.35 KB)
📄
jenkins.xml.tar
(2 KB)
📄
jenkins.xml.xml.tar.gz
(254 B)
📄
jerror.h.h.tar.gz
(4.17 KB)
📄
jerror.h.tar
(16.5 KB)
📄
jfs.mod.mod.tar.gz
(4.57 KB)
📄
jfs.mod.tar
(22 KB)
📄
jit-reader.h.h.tar.gz
(3.78 KB)
📄
jit-reader.h.tar
(13.5 KB)
📄
jmorecfg.h.h.tar.gz
(5.38 KB)
📄
jmorecfg.h.tar
(16.5 KB)
📄
join.tar
(55.5 KB)
📄
join.tar.gz
(24.67 KB)
📄
joomla16.tar
(361.5 KB)
📄
joomla16.tar.gz
(221.25 KB)
📄
joomla16.zip
(332.51 KB)
📄
joomla30.tar
(31.61 MB)
📄
joomla30.tar.gz
(28.76 MB)
📄
joomla30.zip
(31.58 MB)
📄
joomla310.tar
(640 KB)
📄
joomla310.tar.gz
(396.36 KB)
📄
joomla310.zip
(590.9 KB)
📄
joomla4.tar
(50.68 MB)
📄
joomla4.tar.gz
(45.33 MB)
📄
joomla4.zip
(50.55 MB)
📄
joomla54.tar
(49.71 MB)
📄
joomla54.tar.gz
(44.11 MB)
📄
joomla54.zip
(49.59 MB)
📄
jorani.tar
(212.5 KB)
📄
jorani.tar.gz
(127.78 KB)
📄
jorani.zip
(193.01 KB)
📄
journal-nocow.conf.conf.tar.gz
(655 B)
📄
journal-nocow.conf.tar
(3 KB)
📄
jpeg.mod.mod.tar.gz
(4.91 KB)
📄
jpeg.mod.tar
(13 KB)
📄
jpeglib.h.h.tar.gz
(13.6 KB)
📄
jpeglib.h.tar
(50.5 KB)
📄
jqplot.tar
(71 KB)
📄
jqplot.tar.gz
(45.26 KB)
📄
jqplot.zip
(62.77 KB)
📄
jquery.tar
(862.5 KB)
📄
jquery.tar.gz
(284.3 KB)
📄
jquery.zip
(849.11 KB)
📄
jquery2.js.js.tar.gz
(74.92 KB)
📄
jquery2.js.tar
(253.5 KB)
📄
jquery3.js.js.tar.gz
(73.58 KB)
📄
jquery3.js.tar
(251.5 KB)
📄
js.tar
(17.71 MB)
📄
js.tar.gz
(4.12 MB)
📄
js.zip
(17.49 MB)
📄
json-2.1.0.tar
(66.5 KB)
📄
json-2.1.0.tar.gz
(25.44 KB)
📄
json-2.1.0.zip
(64.16 KB)
📄
json-c.pc.pc.tar.gz
(259 B)
📄
json-c.pc.tar
(2 KB)
📄
json-c.tar
(96.5 KB)
📄
json-c.tar.gz
(21.73 KB)
📄
json-c.zip
(85.92 KB)
📄
json.h.h.tar.gz
(542 B)
📄
json.h.tar
(2.5 KB)
📄
json.rb.rb.tar.gz
(999 B)
📄
json.rb.tar
(11 KB)
📄
json.tar
(461.5 KB)
📄
json.tar.gz
(25.43 KB)
📄
json.zip
(421.96 KB)
📄
json_inttypes.h.h.tar.gz
(316 B)
📄
json_inttypes.h.tar
(2 KB)
📄
json_lib.h.h.tar.gz
(4.72 KB)
📄
json_lib.h.tar
(15.5 KB)
📄
json_object.h.h.tar.gz
(9.44 KB)
📄
json_object.h.tar
(39 KB)
📄
json_pointer.h.h.tar.gz
(1.54 KB)
📄
json_pointer.h.tar
(6.5 KB)
📄
json_tokener.h.h.tar.gz
(2.51 KB)
📄
json_tokener.h.tar
(8.5 KB)
📄
json_util.h.h.tar.gz
(1.21 KB)
📄
json_util.h.tar
(4.5 KB)
📄
json_visit.h.h.tar.gz
(1.21 KB)
📄
json_visit.h.tar
(5 KB)
📄
jsonschema.tar
(3.5 KB)
📄
jsonschema.tar.gz
(571 B)
📄
jszip.tar
(66.5 KB)
📄
jszip.tar.gz
(38.19 KB)
📄
jszip.zip
(54.62 KB)
📄
jwt_secret.tar
(2 KB)
📄
jwt_secret.tar.gz
(122 B)
📄
kaanapali.tar
(27.06 MB)
📄
kaanapali.tar.gz
(15.51 MB)
📄
kaanapali.zip
(27.05 MB)
📄
kabi.attr.attr.tar.gz
(198 B)
📄
kabi.attr.tar
(3 KB)
📄
kabi.sh.sh.tar.gz
(402 B)
📄
kabi.sh.tar
(3 KB)
📄
kabini_ce.bin.bin.tar.gz
(1.56 KB)
📄
kabini_ce.bin.tar
(20 KB)
📄
kabini_me.bin.bin.tar.gz
(4.14 KB)
📄
kabini_me.bin.tar
(20 KB)
📄
kabini_mec.bin.bin.tar.gz
(8.86 KB)
📄
kabini_mec.bin.tar
(36 KB)
📄
kabini_pfp.bin.bin.tar.gz
(3.88 KB)
📄
kabini_pfp.bin.tar
(20 KB)
📄
kabini_rlc.bin.bin.tar.gz
(5.35 KB)
📄
kabini_rlc.bin.tar
(23 KB)
📄
kabini_sdma.bin.bin.tar.gz
(2.26 KB)
📄
kabini_sdma.bin.tar
(11 KB)
📄
kabini_sdma1.bin.bin.tar.gz
(2.26 KB)
📄
kabini_sdma1.bin.tar
(11 KB)
📄
kabini_uvd.bin.bin.tar.gz
(154.45 KB)
📄
kabini_uvd.bin.tar
(457 KB)
📄
kabini_vce.bin.bin.tar.gz
(62.64 KB)
📄
kabini_vce.bin.tar
(200 KB)
📄
kadm-client.pc.pc.tar.gz
(281 B)
📄
kadm-client.pc.tar
(2 KB)
📄
kadm-server.pc.pc.tar.gz
(279 B)
📄
kadm-server.pc.tar
(2 KB)
📄
kadm5.tar
(29.5 KB)
📄
kadm5.tar.gz
(5.39 KB)
📄
kadm5.zip
(26.27 KB)
📄
kadm5_auth_plugin.h.h.tar.gz
(3.22 KB)
📄
kadm5_auth_plugin.h.tar
(14 KB)
📄
kadm5_hook_plugin.h.h.tar.gz
(2.26 KB)
📄
kadm5_hook_plugin.h.tar
(8 KB)
📄
kadm_err.h.h.tar.gz
(1.06 KB)
📄
kadm_err.h.tar
(6 KB)
📄
kadmin.xml.tar
(2 KB)
📄
kadmin.xml.xml.tar.gz
(234 B)
📄
kanboard.tar
(4.6 MB)
📄
kanboard.tar.gz
(4.05 MB)
📄
kanboard.zip
(4.57 MB)
📄
kaveri_ce.bin.bin.tar.gz
(1.56 KB)
📄
kaveri_ce.bin.tar
(20 KB)
📄
kaveri_me.bin.bin.tar.gz
(4.14 KB)
📄
kaveri_me.bin.tar
(20 KB)
📄
kaveri_mec.bin.bin.tar.gz
(9 KB)
📄
kaveri_mec.bin.tar
(36 KB)
📄
kaveri_mec2.bin.bin.tar.gz
(9.64 KB)
📄
kaveri_mec2.bin.tar
(36 KB)
📄
kaveri_pfp.bin.bin.tar.gz
(3.96 KB)
📄
kaveri_pfp.bin.tar
(20 KB)
📄
kaveri_rlc.bin.bin.tar.gz
(5.34 KB)
📄
kaveri_rlc.bin.tar
(23 KB)
📄
kaveri_sdma.bin.bin.tar.gz
(2.26 KB)
📄
kaveri_sdma.bin.tar
(11 KB)
📄
kaveri_sdma1.bin.bin.tar.gz
(2.26 KB)
📄
kaveri_sdma1.bin.tar
(11 KB)
📄
kaveri_uvd.bin.bin.tar.gz
(154.45 KB)
📄
kaveri_uvd.bin.tar
(457 KB)
📄
kaveri_vce.bin.bin.tar.gz
(62.64 KB)
📄
kaveri_vce.bin.tar
(200 KB)
📄
kaweth.tar
(8.5 KB)
📄
kaweth.tar.gz
(2.88 KB)
📄
kaweth.zip
(4.59 KB)
📄
kbd.tar
(3.61 MB)
📄
kbd.tar.gz
(2.21 MB)
📄
kbd.zip
(3.08 MB)
📄
kbl_dmc_ver1.bin.bin.tar.gz
(3.21 KB)
📄
kbl_dmc_ver1.bin.tar
(10 KB)
📄
kbl_guc_32.0.3.bin.0.3.bin.tar.gz
(81.37 KB)
📄
kbl_guc_32.0.3.bin.tar
(174 KB)
📄
kbl_guc_33.0.0.bin.0.0.bin.tar.gz
(84.09 KB)
📄
kbl_guc_33.0.0.bin.tar
(180.5 KB)
📄
kbl_guc_49.0.1.bin.0.1.bin.tar.gz
(85.79 KB)
📄
kbl_guc_49.0.1.bin.tar
(194.5 KB)
📄
kbl_guc_62.0.0.bin.0.0.bin.tar.gz
(90.95 KB)
📄
kbl_guc_62.0.0.bin.tar
(197.5 KB)
📄
kbl_guc_69.0.3.bin.0.3.bin.tar.gz
(101.91 KB)
📄
kbl_guc_69.0.3.bin.tar
(214.5 KB)
📄
kbl_guc_70.1.1.bin.1.1.bin.tar.gz
(93.23 KB)
📄
kbl_guc_70.1.1.bin.tar
(204 KB)
📄
kbl_huc_4.0.0.bin.0.0.bin.tar.gz
(80.18 KB)
📄
kbl_huc_4.0.0.bin.tar
(222.5 KB)
📄
kcare.service.service.tar.gz
(579 B)
📄
kcare.service.tar
(4 KB)
📄
kcare.tar
(496.5 KB)
📄
kcare.tar.gz
(194.7 KB)
📄
kcare.zip
(485.03 KB)
📄
kd.h.h.tar.gz
(670 B)
📄
kd.h.tar
(3 KB)
📄
kdb.h.h.tar.gz
(15.29 KB)
📄
kdb.h.tar
(69.5 KB)
📄
kdb.pc.pc.tar.gz
(291 B)
📄
kdb.pc.tar
(2 KB)
📄
kdcpreauth_plugin.h.h.tar.gz
(5.02 KB)
📄
kdcpreauth_plugin.h.tar
(19 KB)
📄
kdf.h.h.tar.gz
(1.59 KB)
📄
kdf.h.tar
(9 KB)
📄
kdferr.h.h.tar.gz
(1.16 KB)
📄
kdferr.h.tar
(6.5 KB)
📄
kdump-lib-initramfs.sh.sh.tar.gz
(2.13 KB)
📄
kdump-lib-initramfs.sh.tar
(8.5 KB)
📄
kdump-lib.sh.sh.tar.gz
(9.97 KB)
📄
kdump-lib.sh.tar
(64 KB)
📄
kdump-logger.sh.sh.tar.gz
(3.02 KB)
📄
kdump-logger.sh.tar
(11.5 KB)
📄
kdump-udev-throttler.tar
(3 KB)
📄
kdump-udev-throttler.tar.gz
(779 B)
📄
kdump.service.service.tar.gz
(342 B)
📄
kdump.service.tar
(2 KB)
📄
kdump.tar
(50.5 KB)
📄
kdump.tar.gz
(14.46 KB)
📄
kdump.zip
(47.67 KB)
📄
kerberos.xml.tar
(2 KB)
📄
kerberos.xml.xml.tar.gz
(247 B)
📄
kernel.exec.exec.tar.gz
(117.69 KB)
📄
kernel.exec.tar
(276 KB)
📄
kernel.img.img.tar.gz
(24.63 KB)
📄
kernel.img.tar
(111 KB)
📄
kernel.tar
(28.5 KB)
📄
kernel.tar.gz
(5.34 KB)
📄
kernel.zip
(22.23 KB)
📄
kernel_to_cil.h.h.tar.gz
(188 B)
📄
kernel_to_cil.h.tar
(2 KB)
📄
kernel_to_conf.h.h.tar.gz
(190 B)
📄
kernel_to_conf.h.tar
(2 KB)
📄
kexec.target.tar
(2.5 KB)
📄
kexec.target.target.tar.gz
(446 B)
📄
key.php.php.tar.gz
(157 B)
📄
key.php.tar
(2 KB)
📄
keycreate.tar
(1.5 KB)
📄
keycreate.tar.gz
(103 B)
📄
keylayouts.mod.mod.tar.gz
(2.01 KB)
📄
keylayouts.mod.tar
(7.5 KB)
📄
keymaps.tar
(2.32 MB)
📄
keymaps.tar.gz
(1.71 MB)
📄
keymaps.zip
(1.99 MB)
📄
keys.h.h.tar.gz
(597 B)
📄
keys.h.tar
(3 KB)
📄
keys.tar
(29.5 KB)
📄
keys.tar.gz
(11.22 KB)
📄
keys.zip
(17.43 KB)
📄
keyspan.tar
(91 KB)
📄
keyspan.tar.gz
(23.31 KB)
📄
keyspan.zip
(83.26 KB)
📄
keyspan_pda.tar
(6 KB)
📄
keyspan_pda.tar.gz
(2.01 KB)
📄
keyspan_pda.zip
(4.13 KB)
📄
keystatus.mod.mod.tar.gz
(1023 B)
📄
keystatus.mod.tar
(7 KB)
📄
keysym.h.h.tar.gz
(1.21 KB)
📄
keysym.h.tar
(4.5 KB)
📄
keysymdef.h.h.tar.gz
(31.16 KB)
📄
keysymdef.h.tar
(173 KB)
📄
keyutils.h.h.tar.gz
(2.25 KB)
📄
keyutils.h.tar
(9.5 KB)
📄
keyword.py.py.tar.gz
(527 B)
📄
keyword.py.tar
(8 KB)
📄
keyword.pyc.pyc.tar.gz
(1.26 KB)
📄
keyword.pyc.tar
(4 KB)
📄
keyword.pyo.pyo.tar.gz
(1.26 KB)
📄
keyword.pyo.tar
(4 KB)
📄
keywords.h.h.tar.gz
(2.08 KB)
📄
keywords.h.tar
(8 KB)
📄
kibana.xml.tar
(2 KB)
📄
kibana.xml.xml.tar.gz
(349 B)
📄
kickstart.php.php.tar.gz
(4.8 KB)
📄
kickstart.php.tar
(21.5 KB)
📄
kill.php.php.tar.gz
(541 B)
📄
kill.php.tar
(2.5 KB)
📄
kill.py.py.tar.gz
(1.3 KB)
📄
kill.py.tar
(5.5 KB)
📄
kill.tar
(39 KB)
📄
kill.tar.gz
(16.51 KB)
📄
kimai.sql.sql.tar.gz
(4.85 KB)
📄
kimai.sql.tar
(40.5 KB)
📄
kimai.tar
(107.47 MB)
📄
kimai.tar.gz
(102.51 MB)
📄
kimai.zip
(107.44 MB)
📄
kirby.tar
(12.09 MB)
📄
kirby.tar.gz
(11.79 MB)
📄
kirby.zip
(12.06 MB)
📄
klog.h.h.tar.gz
(778 B)
📄
klog.h.tar
(3 KB)
📄
klogin.xml.tar
(2 KB)
📄
klogin.xml.xml.tar.gz
(281 B)
📄
kmod.attr.attr.tar.gz
(171 B)
📄
kmod.attr.tar
(3 KB)
📄
kmod.prov.prov.tar.gz
(488 B)
📄
kmod.prov.tar
(4 KB)
📄
ko.tar
(27.5 KB)
📄
ko.tar.gz
(21.12 KB)
📄
ko.zip
(21.82 KB)
📄
kohana.tar
(78.5 KB)
📄
kohana.tar.gz
(47.04 KB)
📄
kohana.zip
(68.11 KB)
📄
koi2alt.tar
(4 KB)
📄
koi2alt.tar.gz
(1.04 KB)
📄
koi8_r.so.so.tar.gz
(3.86 KB)
📄
koi8_r.so.tar
(13.5 KB)
📄
koi8_u.so.so.tar.gz
(3.89 KB)
📄
koi8_u.so.tar
(13.5 KB)
📄
koi8r.uni.tar
(10 KB)
📄
koi8r.uni.uni.tar.gz
(1.65 KB)
📄
koi8u.uni.tar
(13 KB)
📄
koi8u.uni.uni.tar.gz
(2.04 KB)
📄
koi8u2ruscii.tar
(5 KB)
📄
koi8u2ruscii.tar.gz
(747 B)
📄
koken.tar
(139.5 KB)
📄
koken.tar.gz
(67.41 KB)
📄
koken.zip
(120.17 KB)
📄
kompare.tar
(2 KB)
📄
kompare.tar.gz
(260 B)
📄
kopage.tar
(34.2 MB)
📄
kopage.tar.gz
(34.15 MB)
📄
kopage.zip
(34.19 MB)
📄
korean.so.so.tar.gz
(129.78 KB)
📄
korean.so.tar
(241 KB)
📄
kpartx_id.tar
(7 KB)
📄
kpartx_id.tar.gz
(1.17 KB)
📄
kpasswd.xml.tar
(2 KB)
📄
kpasswd.xml.xml.tar.gz
(243 B)
📄
kpatch_wait_period.tar
(2 KB)
📄
kpatch_wait_period.tar.gz
(137 B)
📄
kprobes-optimization.tar
(2 KB)
📄
kprobes-optimization.tar.gz
(120 B)
📄
kprop.xml.tar
(2 KB)
📄
kprop.xml.xml.tar.gz
(240 B)
📄
krad.h.h.tar.gz
(2.95 KB)
📄
krad.h.tar
(10.5 KB)
📄
krayin.sql.sql.tar.gz
(17.75 KB)
📄
krayin.sql.tar
(100 KB)
📄
krayin.tar
(122.91 MB)
📄
krayin.tar.gz
(119.37 MB)
📄
krayin.zip
(122.89 MB)
📄
krb5-gssapi.pc.pc.tar.gz
(243 B)
📄
krb5-gssapi.pc.tar
(2 KB)
📄
krb5.conf.conf.tar.gz
(515 B)
📄
krb5.conf.tar
(2.5 KB)
📄
krb5.h.h.tar.gz
(353 B)
📄
krb5.h.tar
(346 KB)
📄
krb5.pc.pc.tar.gz
(310 B)
📄
krb5.pc.tar
(2 KB)
📄
krb5.tar
(2.79 MB)
📄
krb5.tar.gz
(77.89 KB)
📄
krb5.zip
(2.77 MB)
📄
kshell.xml.tar
(2 KB)
📄
kshell.xml.xml.tar.gz
(268 B)
📄
kube-apiserver.xml.tar
(2 KB)
📄
kube-apiserver.xml.xml.tar.gz
(319 B)
📄
kvm.h.h.tar.gz
(3.85 KB)
📄
kvm.h.tar
(13 KB)
📄
kvm_para.h.h.tar.gz
(186 B)
📄
kvm_para.h.tar
(7 KB)
📄
kvm_perf.h.h.tar.gz
(325 B)
📄
kvm_perf.h.tar
(2 KB)
📄
kvm_stat.service.service.tar.gz
(364 B)
📄
kvm_stat.service.tar
(3 KB)
📄
l1_char_class_tab.h.h.tar.gz
(8.52 KB)
📄
l1_char_class_tab.h.tar
(125.5 KB)
📄
label.h.h.tar.gz
(2.13 KB)
📄
label.h.tar
(7.5 KB)
📄
labs.tar
(461 KB)
📄
labs.tar.gz
(161.53 KB)
📄
labs.zip
(448.7 KB)
📄
lanai.bin.bin.tar.gz
(25.32 KB)
📄
lanai.bin.tar
(151 KB)
📄
lang.tar
(88.5 KB)
📄
lang.tar.gz
(13.59 KB)
📄
lang.zip
(85.3 KB)
📄
lang_1.php.php.tar.gz
(43.72 KB)
📄
lang_1.php.tar
(195 KB)
📄
lang_en.php.php.tar.gz
(673 B)
📄
lang_en.php.tar
(3 KB)
📄
langinfo.h.h.tar.gz
(4.38 KB)
📄
langinfo.h.tar
(19 KB)
📄
langpref.php.php.tar.gz
(148 B)
📄
langpref.php.tar
(2 KB)
📄
language.tar
(4.21 MB)
📄
language.tar.gz
(707.93 KB)
📄
language.zip
(4.18 MB)
📄
languages.tar
(63.5 MB)
📄
languages.tar.gz
(6.45 MB)
📄
languages.zip
(137.92 MB)
📄
laptop_mode.tar
(2 KB)
📄
laptop_mode.tar.gz
(108 B)
📄
laravel-blog.tar
(7.73 MB)
📄
laravel-blog.tar.gz
(7.72 MB)
📄
laravel-blog.zip
(7.72 MB)
📄
laravel.tar
(26.53 MB)
📄
laravel.tar.gz
(24.66 MB)
📄
laravel.zip
(26.51 MB)
📄
laravel8.tar
(26.1 MB)
📄
laravel8.tar.gz
(24.24 MB)
📄
laravel8.zip
(26.08 MB)
📄
lastlog.h.h.tar.gz
(197 B)
📄
lastlog.h.tar
(2 KB)
📄
lat1.uni.tar
(5 KB)
📄
lat1.uni.uni.tar.gz
(518 B)
📄
lat1u.uni.tar
(7 KB)
📄
lat1u.uni.uni.tar.gz
(1.07 KB)
📄
lat2.uni.tar
(13 KB)
📄
lat2.uni.uni.tar.gz
(1.39 KB)
📄
lat2u.uni.tar
(10 KB)
📄
lat2u.uni.uni.tar.gz
(1.32 KB)
📄
lat4.uni.tar
(9 KB)
📄
lat4.uni.uni.tar.gz
(1.44 KB)
📄
lat4u.uni.tar
(12 KB)
📄
lat4u.uni.uni.tar.gz
(2.33 KB)
📄
lat7.uni.tar
(17 KB)
📄
lat7.uni.uni.tar.gz
(1.95 KB)
📄
lat9u.uni.tar
(9 KB)
📄
lat9u.uni.uni.tar.gz
(1.26 KB)
📄
lat9v.uni.tar
(10 KB)
📄
lat9v.uni.uni.tar.gz
(1.3 KB)
📄
lat9w.uni.tar
(10 KB)
📄
lat9w.uni.uni.tar.gz
(1.28 KB)
📄
latency-performance.tar
(3.5 KB)
📄
latency-performance.tar.gz
(947 B)
📄
latency-performance.zip
(1.77 KB)
📄
latin2_and_win1250.so.so.tar.gz
(3.69 KB)
📄
latin2_and_win1250.so.tar
(13.5 KB)
📄
latin2u.trans.tar
(2 KB)
📄
latin2u.trans.trans.tar.gz
(381 B)
📄
latin_and_mic.so.so.tar.gz
(3.35 KB)
📄
latin_and_mic.so.tar
(13.5 KB)
📄
layerbb.tar
(226 KB)
📄
layerbb.tar.gz
(126.17 KB)
📄
layerbb.zip
(201.16 KB)
📄
lber.h.h.tar.gz
(4.05 KB)
📄
lber.h.tar
(16.5 KB)
📄
lber_types.h.h.tar.gz
(735 B)
📄
lber_types.h.tar
(3 KB)
📄
lbtf_sdio.bin.bin.tar.gz
(84.6 KB)
📄
lbtf_sdio.bin.tar
(120 KB)
📄
lbtf_usb.bin.bin.tar.gz
(80.79 KB)
📄
lbtf_usb.bin.tar
(118 KB)
📄
lc.tar
(10 KB)
📄
lc.tar.gz
(2.64 KB)
📄
lc.zip
(6 KB)
📄
ld-2.28.so.28.so.tar.gz
(402.26 KB)
📄
ld-2.28.so.tar
(1.05 MB)
📄
ld-linux-x86-64.so.2.so.2.tar.gz
(402.26 KB)
📄
ld-linux-x86-64.so.2.tar
(1.05 MB)
📄
ld.so.cache.so.cache.tar.gz
(10.53 KB)
📄
ld.so.cache.tar
(43 KB)
📄
ld.so.conf.d.tar
(9 KB)
📄
ld.so.conf.d.tar.gz
(378 B)
📄
ld.so.conf.d.zip
(1.67 KB)
📄
ld.so.conf.so.conf.tar.gz
(114 B)
📄
ld.so.conf.tar
(2 KB)
📄
ldap.h.h.tar.gz
(14.91 KB)
📄
ldap.h.tar
(65.5 KB)
📄
ldap.xml.tar
(2 KB)
📄
ldap.xml.xml.tar.gz
(253 B)
📄
ldap_cdefs.h.h.tar.gz
(2.87 KB)
📄
ldap_cdefs.h.tar
(11 KB)
📄
ldap_features.h.h.tar.gz
(938 B)
📄
ldap_features.h.tar
(3.5 KB)
📄
ldap_schema.h.h.tar.gz
(2.21 KB)
📄
ldap_schema.h.tar
(11 KB)
📄
ldap_utf8.h.h.tar.gz
(1.4 KB)
📄
ldap_utf8.h.tar
(5 KB)
📄
ldaps.xml.tar
(2 KB)
📄
ldaps.xml.xml.tar.gz
(278 B)
📄
ldb.so.so.tar.gz
(3.44 KB)
📄
ldb.so.tar
(9.5 KB)
📄
ldb.tar
(603 KB)
📄
ldb.tar.gz
(130.81 KB)
📄
ldb.zip
(586.14 KB)
📄
ldconfig.service.service.tar.gz
(543 B)
📄
ldconfig.service.tar
(2.5 KB)
📄
ldconfig.tar
(988 KB)
📄
ldconfig.tar.gz
(421.46 KB)
📄
ldd.tar
(7 KB)
📄
ldd.tar.gz
(2.4 KB)
📄
ldiscs.tar
(2 KB)
📄
ldiscs.tar.gz
(125 B)
📄
ldm.mod.mod.tar.gz
(4.37 KB)
📄
ldm.mod.tar
(25 KB)
📄
ldt.h.h.tar.gz
(771 B)
📄
ldt.h.tar
(3 KB)
📄
leafpub.tar
(203.5 KB)
📄
leafpub.tar.gz
(117.14 KB)
📄
leafpub.zip
(180.26 KB)
📄
lease-break-time.tar
(2 KB)
📄
lease-break-time.tar.gz
(114 B)
📄
leases-enable.tar
(2 KB)
📄
leases-enable.tar.gz
(110 B)
📄
leftj.xbm.tar
(2 KB)
📄
leftj.xbm.xbm.tar.gz
(234 B)
📄
legacy.conf.conf.tar.gz
(550 B)
📄
legacy.conf.tar
(4 KB)
📄
legacy.tar
(680.5 KB)
📄
legacy.tar.gz
(445.63 KB)
📄
legacy.zip
(538.74 KB)
📄
legacy_va_layout.tar
(2 KB)
📄
legacy_va_layout.tar.gz
(113 B)
📄
legacycfg.mod.mod.tar.gz
(13.62 KB)
📄
legacycfg.mod.tar
(71 KB)
📄
leia_pfp_470.fw.fw.tar.gz
(738 B)
📄
leia_pfp_470.fw.tar
(3 KB)
📄
leia_pm4_470.fw.fw.tar.gz
(2.48 KB)
📄
leia_pm4_470.fw.tar
(11 KB)
📄
lepton.sql.sql.tar.gz
(13.96 KB)
📄
lepton.sql.tar
(54 KB)
📄
lepton.tar
(10.87 MB)
📄
lepton.tar.gz
(9.94 MB)
📄
lepton.zip
(10.84 MB)
📄
less.png.png.tar.gz
(5.12 KB)
📄
less.png.tar
(7 KB)
📄
less.tar
(286.5 KB)
📄
less.tar.gz
(83.98 KB)
📄
less.zip
(100.75 KB)
📄
lessecho.tar
(14 KB)
📄
lessecho.tar.gz
(4.96 KB)
📄
lesskey.tar
(23.5 KB)
📄
lesskey.tar.gz
(8.58 KB)
📄
lesspipe.sh.sh.tar.gz
(1.38 KB)
📄
lesspipe.sh.tar
(5 KB)
📄
leto.png.png.tar.gz
(17.87 KB)
📄
leto.png.tar
(19.5 KB)
📄
leto.tar
(209.5 KB)
📄
leto.tar.gz
(110.69 KB)
📄
leto.zip
(186.91 KB)
📄
lex.tar
(430 KB)
📄
lex.tar.gz
(148.25 KB)
📄
lfcr.py.py.tar.gz
(403 B)
📄
lfcr.py.tar
(2.5 KB)
📄
lfd.service.service.tar.gz
(277 B)
📄
lfd.service.tar
(3 KB)
📄
lgs8g75.fw.fw.tar.gz
(301 B)
📄
lgs8g75.fw.tar
(3 KB)
📄
lhash.h.h.tar.gz
(2.31 KB)
📄
lhash.h.tar
(11 KB)
📄
lib-dynload.tar
(13.18 MB)
📄
lib-dynload.tar.gz
(1.95 MB)
📄
lib-dynload.zip
(13.07 MB)
📄
lib-names-64.h.h.tar.gz
(573 B)
📄
lib-names-64.h.tar
(3.5 KB)
📄
lib-names.h.h.tar.gz
(332 B)
📄
lib-names.h.tar
(2 KB)
📄
lib-tk.tar
(2.4 MB)
📄
lib-tk.tar.gz
(600.37 KB)
📄
lib-tk.zip
(2.34 MB)
📄
lib.pm.pm.tar.gz
(2.48 KB)
📄
lib.pm.tar
(7.5 KB)
📄
lib.sh.sh.tar.gz
(240 B)
📄
lib.sh.tar
(2 KB)
📄
lib.tar
(237.38 MB)
📄
lib.tar.gz
(2.91 MB)
📄
lib.zip
(230.86 MB)
📄
lib01_acl_plugin.so.so.tar.gz
(52.07 KB)
📄
lib01_acl_plugin.so.tar
(153.5 KB)
📄
lib02_lazy_expunge_plugin.so.so.tar.gz
(9.92 KB)
📄
lib02_lazy_expunge_plugin.so.tar
(33.5 KB)
📄
lib15_notify_plugin.so.so.tar.gz
(8.54 KB)
📄
lib15_notify_plugin.so.tar
(32 KB)
📄
lib20_fts_plugin.so.so.tar.gz
(120.46 KB)
📄
lib20_fts_plugin.so.tar
(351.5 KB)
📄
lib20_var_expand_crypt.so.so.tar.gz
(5.89 KB)
📄
lib20_var_expand_crypt.so.tar
(21.5 KB)
📄
lib20_zlib_plugin.so.so.tar.gz
(28.04 KB)
📄
lib20_zlib_plugin.so.tar
(90.5 KB)
📄
lib21_fts_solr_plugin.so.so.tar.gz
(26.67 KB)
📄
lib21_fts_solr_plugin.so.tar
(76 KB)
📄
lib21_fts_squat_plugin.so.so.tar.gz
(37.88 KB)
📄
lib21_fts_squat_plugin.so.tar
(96.5 KB)
📄
lib2to3.tar
(2.69 MB)
📄
lib2to3.tar.gz
(312.8 KB)
📄
lib2to3.zip
(2.32 MB)
📄
lib30_imap_zlib_plugin.so.so.tar.gz
(25.88 KB)
📄
lib30_imap_zlib_plugin.so.tar
(84.5 KB)
📄
lib64.tar
(562.72 MB)
📄
lib64.tar.gz
(872.3 KB)
📄
lib64.zip
(817.88 MB)
📄
lib90_old_stats_plugin.so.so.tar.gz
(14.67 KB)
📄
lib90_old_stats_plugin.so.tar
(48 KB)
📄
libBrokenLocale.so.1.so.1.tar.gz
(2.94 KB)
📄
libBrokenLocale.so.1.tar
(9.5 KB)
📄
libBrokenLocale.so.so.tar.gz
(2.94 KB)
📄
libBrokenLocale.so.tar
(9.5 KB)
📄
libCNS.so.so.tar.gz
(263.63 KB)
📄
libCNS.so.tar
(461 KB)
📄
libDeployPkg.so.0.0.0.so.0.0.0.tar.gz
(19.53 KB)
📄
libDeployPkg.so.0.0.0.tar
(46.5 KB)
📄
libDeployPkg.so.0.so.0.tar.gz
(19.52 KB)
📄
libDeployPkg.so.0.tar
(46.5 KB)
📄
libEGL.so.1.1.0.so.1.1.0.tar.gz
(37.13 KB)
📄
libEGL.so.1.1.0.tar
(84.5 KB)
📄
libEGL.so.1.so.1.tar.gz
(37.13 KB)
📄
libEGL.so.1.tar
(84.5 KB)
📄
libEGL_mesa.so.0.0.0.so.0.0.0.tar.gz
(130.23 KB)
📄
libEGL_mesa.so.0.0.0.tar
(302 KB)
📄
libEGL_mesa.so.0.so.0.tar.gz
(130.22 KB)
📄
libEGL_mesa.so.0.tar
(302 KB)
📄
libFLAC++.so.6.3.0.so.6.3.0.tar.gz
(29.99 KB)
📄
libFLAC++.so.6.3.0.tar
(110.5 KB)
📄
libFLAC++.so.6.so.6.tar.gz
(29.98 KB)
📄
libFLAC++.so.6.tar
(110.5 KB)
📄
libFLAC.so.8.3.0.so.8.3.0.tar.gz
(178.45 KB)
📄
libFLAC.so.8.3.0.tar
(365 KB)
📄
libFLAC.so.8.so.8.tar.gz
(178.44 KB)
📄
libFLAC.so.8.tar
(365 KB)
📄
libGB.so.so.tar.gz
(35.92 KB)
📄
libGB.so.tar
(69 KB)
📄
libGL.so.1.7.0.so.1.7.0.tar.gz
(141.98 KB)
📄
libGL.so.1.7.0.tar
(547.5 KB)
📄
libGL.so.1.so.1.tar.gz
(141.98 KB)
📄
libGL.so.1.tar
(547.5 KB)
📄
libGLESv1_CM.so.1.2.0.so.1.2.0.tar.gz
(12.21 KB)
📄
libGLESv1_CM.so.1.2.0.tar
(43.5 KB)
📄
libGLESv1_CM.so.1.so.1.tar.gz
(12.2 KB)
📄
libGLESv1_CM.so.1.tar
(43.5 KB)
📄
libGLESv2.so.2.1.0.so.2.1.0.tar.gz
(21.34 KB)
📄
libGLESv2.so.2.1.0.tar
(72 KB)
📄
libGLESv2.so.2.so.2.tar.gz
(21.34 KB)
📄
libGLESv2.so.2.tar
(72 KB)
📄
libGLX.so.0.0.0.so.0.0.0.tar.gz
(48.01 KB)
📄
libGLX.so.0.0.0.tar
(139.5 KB)
📄
libGLX.so.0.so.0.tar.gz
(48.01 KB)
📄
libGLX.so.0.tar
(139.5 KB)
📄
libGLX_mesa.so.0.0.0.so.0.0.0.tar.gz
(182.79 KB)
📄
libGLX_mesa.so.0.0.0.tar
(492 KB)
📄
libGLX_mesa.so.0.so.0.tar.gz
(182.79 KB)
📄
libGLX_mesa.so.0.tar
(492 KB)
📄
libGLX_system.so.0.so.0.tar.gz
(182.79 KB)
📄
libGLX_system.so.0.tar
(492 KB)
📄
libGLdispatch.so.0.0.0.so.0.0.0.tar.gz
(150.5 KB)
📄
libGLdispatch.so.0.0.0.tar
(752.5 KB)
📄
libGLdispatch.so.0.so.0.tar.gz
(150.5 KB)
📄
libGLdispatch.so.0.tar
(752.5 KB)
📄
libGeoIP.so.1.6.12.so.1.6.12.tar.gz
(87.09 KB)
📄
libGeoIP.so.1.6.12.tar
(270 KB)
📄
libGeoIP.so.1.so.1.tar.gz
(87.09 KB)
📄
libGeoIP.so.1.tar
(270 KB)
📄
libGraphicsMagickWand-Q16.so.2.so.2.tar.gz
(67.53 KB)
📄
libGraphicsMagickWand-Q16.so.2.tar
(196 KB)
📄
libHalf.so.12.0.0.so.12.0.0.tar.gz
(66.84 KB)
📄
libHalf.so.12.0.0.tar
(269.5 KB)
📄
libHalf.so.12.so.12.tar.gz
(66.84 KB)
📄
libHalf.so.12.tar
(269.5 KB)
📄
libICE.so.6.3.0.so.6.3.0.tar.gz
(46.5 KB)
📄
libICE.so.6.3.0.tar
(115 KB)
📄
libICE.so.6.so.6.tar.gz
(46.5 KB)
📄
libICE.so.6.tar
(115 KB)
📄
libISOIR165.so.so.tar.gz
(41.18 KB)
📄
libISOIR165.so.tar
(61 KB)
📄
libIex-2_2.so.12.0.0.so.12.0.0.tar.gz
(34.58 KB)
📄
libIex-2_2.so.12.0.0.tar
(134.5 KB)
📄
libIex-2_2.so.12.so.12.tar.gz
(34.57 KB)
📄
libIex-2_2.so.12.tar
(134.5 KB)
📄
libIexMath-2_2.so.12.0.0.so.12.0.0.tar.gz
(6.27 KB)
📄
libIexMath-2_2.so.12.0.0.tar
(22 KB)
📄
libIexMath-2_2.so.12.so.12.tar.gz
(6.27 KB)
📄
libIexMath-2_2.so.12.tar
(22 KB)
📄
libIlmImf-2_2.so.22.so.22.tar.gz
(852.45 KB)
📄
libIlmImf-2_2.so.22.tar
(2.94 MB)
📄
libIlmImfUtil-2_2.so.22.0.0.so.22.0.0.tar.gz
(51.11 KB)
📄
libIlmImfUtil-2_2.so.22.0.0.tar
(164 KB)
📄
libIlmThread-2_2.so.12.so.12.tar.gz
(11.38 KB)
📄
libIlmThread-2_2.so.12.tar
(34.5 KB)
📄
libImath-2_2.so.12.0.0.so.12.0.0.tar.gz
(29.34 KB)
📄
libImath-2_2.so.12.0.0.tar
(79 KB)
📄
libImath-2_2.so.12.so.12.tar.gz
(29.34 KB)
📄
libImath-2_2.so.12.tar
(79 KB)
📄
libJIS.so.so.tar.gz
(68.85 KB)
📄
libJIS.so.tar
(101 KB)
📄
libJISX0213.so.so.tar.gz
(52.55 KB)
📄
libJISX0213.so.tar
(121 KB)
📄
libKSC.so.so.tar.gz
(39.71 KB)
📄
libKSC.so.tar
(49 KB)
📄
libMagickCore-6.Q16.so.7.0.0.Q16.so.7.0.0.tar.gz
(1.1 MB)
📄
libMagickCore-6.Q16.so.7.0.0.tar
(2.77 MB)
📄
libMagickCore-6.Q16.so.7.Q16.so.7.tar.gz
(1.1 MB)
📄
libMagickCore-6.Q16.so.7.tar
(2.77 MB)
📄
libMagickWand-6.Q16.so.7.0.0.Q16.so.7.0.0.tar.gz
(389.52 KB)
📄
libMagickWand-6.Q16.so.7.0.0.tar
(1.18 MB)
📄
libMagickWand-6.Q16.so.7.Q16.so.7.tar.gz
(389.52 KB)
📄
libMagickWand-6.Q16.so.7.tar
(1.18 MB)
📄
libOpenIPMI.so.0.0.5.so.0.0.5.tar.gz
(397.06 KB)
📄
libOpenIPMI.so.0.0.5.tar
(1.08 MB)
📄
libOpenIPMI.so.0.so.0.tar.gz
(397.05 KB)
📄
libOpenIPMI.so.0.tar
(1.08 MB)
📄
libOpenIPMIcmdlang.so.0.0.5.so.0.0.5.tar.gz
(90.62 KB)
📄
libOpenIPMIcmdlang.so.0.0.5.tar
(286 KB)
📄
libOpenIPMIglib.so.0.0.1.so.0.0.1.tar.gz
(7.92 KB)
📄
libOpenIPMIglib.so.0.0.1.tar
(22 KB)
📄
libOpenIPMIglib.so.0.so.0.tar.gz
(7.91 KB)
📄
libOpenIPMIglib.so.0.tar
(22 KB)
📄
libOpenIPMIposix.so.0.0.1.so.0.0.1.tar.gz
(14.73 KB)
📄
libOpenIPMIposix.so.0.0.1.tar
(34 KB)
📄
libOpenIPMIposix.so.0.so.0.tar.gz
(14.73 KB)
📄
libOpenIPMIposix.so.0.tar
(34 KB)
📄
libOpenIPMIpthread.so.0.0.1.so.0.0.1.tar.gz
(17.19 KB)
📄
libOpenIPMIpthread.so.0.0.1.tar
(43 KB)
📄
libOpenIPMIui.so.1.0.1.so.1.0.1.tar.gz
(64.07 KB)
📄
libOpenIPMIui.so.1.0.1.tar
(188.5 KB)
📄
libOpenIPMIui.so.1.so.1.tar.gz
(64.07 KB)
📄
libOpenIPMIui.so.1.tar
(188.5 KB)
📄
libOpenIPMIutils.so.0.0.1.so.0.0.1.tar.gz
(18.35 KB)
📄
libOpenIPMIutils.so.0.0.1.tar
(42.5 KB)
📄
libOpenIPMIutils.so.0.so.0.tar.gz
(18.35 KB)
📄
libOpenIPMIutils.so.0.tar
(42.5 KB)
📄
libQt5Concurrent.so.5.15.so.5.15.tar.gz
(12.18 KB)
📄
libQt5Concurrent.so.5.15.tar
(31 KB)
📄
libQt5Concurrent.so.5.so.5.tar.gz
(12.18 KB)
📄
libQt5Concurrent.so.5.tar
(31 KB)
📄
libQt5Core.so.5.15.3.so.5.15.3.tar.gz
(2.49 MB)
📄
libQt5Core.so.5.15.3.tar
(5.65 MB)
📄
libQt5Core.so.5.15.so.5.15.tar.gz
(2.49 MB)
📄
libQt5Core.so.5.15.tar
(5.65 MB)
📄
libQt5Core.so.5.so.5.tar.gz
(2.49 MB)
📄
libQt5Core.so.5.tar
(5.65 MB)
📄
libQt5DBus.so.5.15.3.so.5.15.3.tar.gz
(246.8 KB)
📄
libQt5DBus.so.5.15.3.tar
(641.5 KB)
📄
libQt5DBus.so.5.15.so.5.15.tar.gz
(246.8 KB)
📄
libQt5DBus.so.5.15.tar
(641.5 KB)
📄
libQt5DBus.so.5.so.5.tar.gz
(246.8 KB)
📄
libQt5DBus.so.5.tar
(641.5 KB)
📄
libQt5EglFSDeviceIntegration.so.5.15.so.5.15.tar.gz
(314.06 KB)
📄
libQt5EglFSDeviceIntegration.so.5.15.tar
(825 KB)
📄
libQt5EglFSDeviceIntegration.so.5.so.5.tar.gz
(314.06 KB)
📄
libQt5EglFSDeviceIntegration.so.5.tar
(825 KB)
📄
libQt5Gui.so.5.15.3.so.5.15.3.tar.gz
(2.46 MB)
📄
libQt5Gui.so.5.15.3.tar
(6.02 MB)
📄
libQt5Gui.so.5.15.so.5.15.tar.gz
(2.46 MB)
📄
libQt5Gui.so.5.15.tar
(6.02 MB)
📄
libQt5Gui.so.5.so.5.tar.gz
(2.46 MB)
📄
libQt5Gui.so.5.tar
(6.02 MB)
📄
libQt5Multimedia.so.5.15.so.5.15.tar.gz
(366.35 KB)
📄
libQt5Multimedia.so.5.15.tar
(1.09 MB)
📄
libQt5Multimedia.so.5.so.5.tar.gz
(366.34 KB)
📄
libQt5Multimedia.so.5.tar
(1.09 MB)
📄
libQt5MultimediaWidgets.so.5.so.5.tar.gz
(44.54 KB)
📄
libQt5MultimediaWidgets.so.5.tar
(133 KB)
📄
libQt5Network.so.5.15.so.5.15.tar.gz
(742.86 KB)
📄
libQt5Network.so.5.15.tar
(1.84 MB)
📄
libQt5Network.so.5.so.5.tar.gz
(742.85 KB)
📄
libQt5Network.so.5.tar
(1.84 MB)
📄
libQt5OpenGL.so.5.15.3.so.5.15.3.tar.gz
(143.45 KB)
📄
libQt5OpenGL.so.5.15.3.tar
(384.5 KB)
📄
libQt5OpenGL.so.5.15.so.5.15.tar.gz
(143.45 KB)
📄
libQt5OpenGL.so.5.15.tar
(384.5 KB)
📄
libQt5OpenGL.so.5.so.5.tar.gz
(143.44 KB)
📄
libQt5OpenGL.so.5.tar
(384.5 KB)
📄
libQt5PrintSupport.so.5.15.3.so.5.15.3.tar.gz
(189.7 KB)
📄
libQt5PrintSupport.so.5.15.3.tar
(493.5 KB)
📄
libQt5PrintSupport.so.5.so.5.tar.gz
(189.7 KB)
📄
libQt5PrintSupport.so.5.tar
(493.5 KB)
📄
libQt5Qml.so.5.15.3.so.5.15.3.tar.gz
(1.77 MB)
📄
libQt5Qml.so.5.15.3.tar
(4.79 MB)
📄
libQt5Qml.so.5.15.so.5.15.tar.gz
(1.77 MB)
📄
libQt5Qml.so.5.15.tar
(4.79 MB)
📄
libQt5Qml.so.5.so.5.tar.gz
(1.77 MB)
📄
libQt5Qml.so.5.tar
(4.79 MB)
📄
libQt5QmlModels.so.5.15.3.so.5.15.3.tar.gz
(230.78 KB)
📄
libQt5QmlModels.so.5.15.3.tar
(570 KB)
📄
libQt5QmlModels.so.5.so.5.tar.gz
(230.77 KB)
📄
libQt5QmlModels.so.5.tar
(570 KB)
📄
libQt5Quick.so.5.15.3.so.5.15.3.tar.gz
(2.09 MB)
📄
libQt5Quick.so.5.15.3.tar
(5.7 MB)
📄
libQt5Quick.so.5.15.so.5.15.tar.gz
(2.09 MB)
📄
libQt5Quick.so.5.15.tar
(5.7 MB)
📄
libQt5Quick.so.5.so.5.tar.gz
(2.09 MB)
📄
libQt5Quick.so.5.tar
(5.7 MB)
📄
libQt5QuickParticles.so.5.15.3.so.5.15.3.tar.gz
(246.74 KB)
📄
libQt5QuickParticles.so.5.15.3.tar
(657 KB)
📄
libQt5QuickParticles.so.5.15.so.5.15.tar.gz
(246.74 KB)
📄
libQt5QuickParticles.so.5.15.tar
(657 KB)
📄
libQt5QuickParticles.so.5.so.5.tar.gz
(246.74 KB)
📄
libQt5QuickParticles.so.5.tar
(657 KB)
📄
libQt5QuickShapes.so.5.15.3.so.5.15.3.tar.gz
(100.65 KB)
📄
libQt5QuickShapes.so.5.15.3.tar
(268.5 KB)
📄
libQt5QuickShapes.so.5.15.so.5.15.tar.gz
(100.65 KB)
📄
libQt5QuickShapes.so.5.15.tar
(268.5 KB)
📄
libQt5QuickShapes.so.5.so.5.tar.gz
(100.65 KB)
📄
libQt5QuickShapes.so.5.tar
(268.5 KB)
📄
libQt5QuickTest.so.5.15.3.so.5.15.3.tar.gz
(52.92 KB)
📄
libQt5QuickTest.so.5.15.3.tar
(140 KB)
📄
libQt5QuickTest.so.5.so.5.tar.gz
(52.92 KB)
📄
libQt5QuickTest.so.5.tar
(140 KB)
📄
libQt5QuickWidgets.so.5.15.3.so.5.15.3.tar.gz
(31.11 KB)
📄
libQt5QuickWidgets.so.5.15.3.tar
(87 KB)
📄
libQt5QuickWidgets.so.5.so.5.tar.gz
(31.11 KB)
📄
libQt5QuickWidgets.so.5.tar
(87 KB)
📄
libQt5Sql.so.5.15.3.so.5.15.3.tar.gz
(122.36 KB)
📄
libQt5Sql.so.5.15.3.tar
(321.5 KB)
📄
libQt5Sql.so.5.15.so.5.15.tar.gz
(122.36 KB)
📄
libQt5Sql.so.5.15.tar
(321.5 KB)
📄
libQt5Sql.so.5.so.5.tar.gz
(122.36 KB)
📄
libQt5Sql.so.5.tar
(321.5 KB)
📄
libQt5Test.so.5.15.3.so.5.15.3.tar.gz
(149.07 KB)
📄
libQt5Test.so.5.15.3.tar
(363 KB)
📄
libQt5Test.so.5.15.so.5.15.tar.gz
(149.07 KB)
📄
libQt5Test.so.5.15.tar
(363 KB)
📄
libQt5Test.so.5.so.5.tar.gz
(149.07 KB)
📄
libQt5Test.so.5.tar
(363 KB)
📄
libQt5Widgets.so.5.15.so.5.15.tar.gz
(2.87 MB)
📄
libQt5Widgets.so.5.15.tar
(6.94 MB)
📄
libQt5Widgets.so.5.so.5.tar.gz
(2.87 MB)
📄
libQt5Widgets.so.5.tar
(6.94 MB)
📄
libQt5XcbQpa.so.5.15.3.so.5.15.3.tar.gz
(519.39 KB)
📄
libQt5XcbQpa.so.5.15.3.tar
(1.41 MB)
📄
libQt5XcbQpa.so.5.15.so.5.15.tar.gz
(519.39 KB)
📄
libQt5XcbQpa.so.5.15.tar
(1.41 MB)
📄
libQt5XcbQpa.so.5.so.5.tar.gz
(519.39 KB)
📄
libQt5XcbQpa.so.5.tar
(1.41 MB)
📄
libQt5Xml.so.5.15.3.so.5.15.3.tar.gz
(110.51 KB)
📄
libQt5Xml.so.5.15.3.tar
(280.5 KB)
📄
libQt5Xml.so.5.15.so.5.15.tar.gz
(110.51 KB)
📄
libQt5Xml.so.5.15.tar
(280.5 KB)
📄
libQt5Xml.so.5.so.5.tar.gz
(110.51 KB)
📄
libQt5Xml.so.5.tar
(280.5 KB)
📄
libSM.so.6.0.1.so.6.0.1.tar.gz
(15.71 KB)
📄
libSM.so.6.0.1.tar
(40 KB)
📄
libSM.so.6.so.6.tar.gz
(15.7 KB)
📄
libSM.so.6.tar
(40 KB)
📄
libSegFault.so.so.tar.gz
(7.01 KB)
📄
libSegFault.so.tar
(21.5 KB)
📄
libSoundTouch.so.2.0.0.so.2.0.0.tar.gz
(31.11 KB)
📄
libSoundTouch.so.2.0.0.tar
(83 KB)
📄
libSoundTouch.so.2.so.2.tar.gz
(31.1 KB)
📄
libSoundTouch.so.2.tar
(83 KB)
📄
libSvtAv1Dec.so.0.8.7.so.0.8.7.tar.gz
(839.84 KB)
📄
libSvtAv1Dec.so.0.8.7.tar
(1.96 MB)
📄
libSvtAv1Dec.so.0.so.0.tar.gz
(839.84 KB)
📄
libSvtAv1Dec.so.0.tar
(1.96 MB)
📄
libSvtAv1Enc.so.0.8.7.so.0.8.7.tar.gz
(1.61 MB)
📄
libSvtAv1Enc.so.0.8.7.tar
(3.88 MB)
📄
libSvtAv1Enc.so.0.so.0.tar.gz
(1.61 MB)
📄
libSvtAv1Enc.so.0.tar
(3.88 MB)
📄
libTix.so.so.tar.gz
(136.58 KB)
📄
libTix.so.tar
(685 KB)
📄
libX11-xcb.so.1.0.0.so.1.0.0.tar.gz
(2.69 KB)
📄
libX11-xcb.so.1.0.0.tar
(9 KB)
📄
libX11-xcb.so.1.so.1.tar.gz
(2.69 KB)
📄
libX11-xcb.so.1.tar
(9 KB)
📄
libX11-xcb.so.so.tar.gz
(2.69 KB)
📄
libX11-xcb.so.tar
(9 KB)
📄
libX11.so.6.3.0.so.6.3.0.tar.gz
(776.01 KB)
📄
libX11.so.6.3.0.tar
(1.28 MB)
📄
libX11.so.6.so.6.tar.gz
(776.01 KB)
📄
libX11.so.6.tar
(1.28 MB)
📄
libX11.so.so.tar.gz
(776 KB)
📄
libX11.so.tar
(1.28 MB)
📄
libXau.so.6.0.0.so.6.0.0.tar.gz
(6.1 KB)
📄
libXau.so.6.0.0.tar
(18 KB)
📄
libXau.so.6.so.6.tar.gz
(6.1 KB)
📄
libXau.so.6.tar
(18 KB)
📄
libXau.so.so.tar.gz
(6.1 KB)
📄
libXau.so.tar
(18 KB)
📄
libXaw.so.7.so.7.tar.gz
(183.96 KB)
📄
libXaw.so.7.tar
(439 KB)
📄
libXaw7.so.7.0.0.so.7.0.0.tar.gz
(183.97 KB)
📄
libXaw7.so.7.0.0.tar
(439 KB)
📄
libXaw7.so.7.so.7.tar.gz
(183.96 KB)
📄
libXaw7.so.7.tar
(439 KB)
📄
libXcomposite.so.1.0.0.so.1.0.0.tar.gz
(4.63 KB)
📄
libXcomposite.so.1.0.0.tar
(13.5 KB)
📄
libXcomposite.so.1.so.1.tar.gz
(4.63 KB)
📄
libXcomposite.so.1.tar
(13.5 KB)
📄
libXcursor.so.1.0.2.so.1.0.2.tar.gz
(20.55 KB)
📄
libXcursor.so.1.0.2.tar
(47.5 KB)
📄
libXcursor.so.1.so.1.tar.gz
(20.54 KB)
📄
libXcursor.so.1.tar
(47.5 KB)
📄
libXdamage.so.1.1.0.so.1.1.0.tar.gz
(4.94 KB)
📄
libXdamage.so.1.1.0.tar
(13.5 KB)
📄
libXdamage.so.1.so.1.tar.gz
(4.94 KB)
📄
libXdamage.so.1.tar
(13.5 KB)
📄
libXext.so.6.4.0.so.6.4.0.tar.gz
(30.58 KB)
📄
libXext.so.6.4.0.tar
(80.5 KB)
📄
libXext.so.6.so.6.tar.gz
(30.58 KB)
📄
libXext.so.6.tar
(80.5 KB)
📄
libXfixes.so.3.1.0.so.3.1.0.tar.gz
(9.14 KB)
📄
libXfixes.so.3.1.0.tar
(27.5 KB)
📄
libXfixes.so.3.so.3.tar.gz
(9.14 KB)
📄
libXfixes.so.3.tar
(27.5 KB)
📄
libXft.so.2.3.3.so.2.3.3.tar.gz
(43.42 KB)
📄
libXft.so.2.3.3.tar
(95.5 KB)
📄
libXft.so.2.so.2.tar.gz
(43.41 KB)
📄
libXft.so.2.tar
(95.5 KB)
📄
libXi.so.6.1.0.so.6.1.0.tar.gz
(31.25 KB)
📄
libXi.so.6.1.0.tar
(71 KB)
📄
libXi.so.6.so.6.tar.gz
(31.25 KB)
📄
libXi.so.6.tar
(71 KB)
📄
libXinerama.so.1.0.0.so.1.0.0.tar.gz
(4.67 KB)
📄
libXinerama.so.1.0.0.tar
(13.5 KB)
📄
libXinerama.so.1.so.1.tar.gz
(4.67 KB)
📄
libXinerama.so.1.tar
(13.5 KB)
📄
libXmu.so.6.2.0.so.6.2.0.tar.gz
(51.49 KB)
📄
libXmu.so.6.2.0.tar
(112.5 KB)
📄
libXmu.so.6.so.6.tar.gz
(51.48 KB)
📄
libXmu.so.6.tar
(112.5 KB)
📄
libXmuu.so.1.0.0.so.1.0.0.tar.gz
(7.21 KB)
📄
libXmuu.so.1.0.0.tar
(21.5 KB)
📄
libXmuu.so.1.so.1.tar.gz
(7.21 KB)
📄
libXmuu.so.1.tar
(21.5 KB)
📄
libXpm.so.4.11.0.so.4.11.0.tar.gz
(36.75 KB)
📄
libXpm.so.4.11.0.tar
(79 KB)
📄
libXpm.so.4.so.4.tar.gz
(36.75 KB)
📄
libXpm.so.4.tar
(79 KB)
📄
libXpm.so.so.tar.gz
(36.75 KB)
📄
libXpm.so.tar
(79 KB)
📄
libXrandr.so.2.2.0.so.2.2.0.tar.gz
(18.52 KB)
📄
libXrandr.so.2.2.0.tar
(46.5 KB)
📄
libXrandr.so.2.so.2.tar.gz
(18.52 KB)
📄
libXrandr.so.2.tar
(46.5 KB)
📄
libXrender.so.1.3.0.so.1.3.0.tar.gz
(19.02 KB)
📄
libXrender.so.1.3.0.tar
(51 KB)
📄
libXrender.so.1.so.1.tar.gz
(19.01 KB)
📄
libXrender.so.1.tar
(51 KB)
📄
libXt.so.6.0.0.so.6.0.0.tar.gz
(190.43 KB)
📄
libXt.so.6.0.0.tar
(456 KB)
📄
libXt.so.6.so.6.tar.gz
(190.42 KB)
📄
libXt.so.6.tar
(456 KB)
📄
libXtst.so.6.1.0.so.6.1.0.tar.gz
(10.96 KB)
📄
libXtst.so.6.1.0.tar
(30.5 KB)
📄
libXtst.so.6.so.6.tar.gz
(10.96 KB)
📄
libXtst.so.6.tar
(30.5 KB)
📄
libXv.so.1.0.0.so.1.0.0.tar.gz
(9.16 KB)
📄
libXv.so.1.0.0.tar
(26 KB)
📄
libXv.so.1.so.1.tar.gz
(9.16 KB)
📄
libXv.so.1.tar
(26 KB)
📄
libXxf86misc.so.1.1.0.so.1.1.0.tar.gz
(6.27 KB)
📄
libXxf86misc.so.1.1.0.tar
(17.5 KB)
📄
libXxf86misc.so.1.so.1.tar.gz
(6.27 KB)
📄
libXxf86misc.so.1.tar
(17.5 KB)
📄
libXxf86vm.so.1.0.0.so.1.0.0.tar.gz
(8.63 KB)
📄
libXxf86vm.so.1.0.0.tar
(25.5 KB)
📄
libXxf86vm.so.1.so.1.tar.gz
(8.63 KB)
📄
libXxf86vm.so.1.tar
(25.5 KB)
📄
libacl.so.1.1.2253.so.1.1.2253.tar.gz
(17.12 KB)
📄
libacl.so.1.1.2253.tar
(38.5 KB)
📄
libacl.so.1.so.1.tar.gz
(17.12 KB)
📄
libacl.so.1.tar
(38.5 KB)
📄
libaec.so.0.0.8.so.0.0.8.tar.gz
(15.36 KB)
📄
libaec.so.0.0.8.tar
(34.5 KB)
📄
libaec.so.0.so.0.tar.gz
(15.36 KB)
📄
libaec.so.0.tar
(34.5 KB)
📄
libaio.h.h.tar.gz
(2.3 KB)
📄
libaio.h.tar
(10.5 KB)
📄
libaio.so.1.0.0.so.1.0.0.tar.gz
(4.4 KB)
📄
libaio.so.1.0.0.tar
(18 KB)
📄
libaio.so.1.0.1.so.1.0.1.tar.gz
(4.4 KB)
📄
libaio.so.1.0.1.tar
(18 KB)
📄
libaio.so.1.so.1.tar.gz
(4.4 KB)
📄
libaio.so.1.tar
(18 KB)
📄
libaio.so.so.tar.gz
(4.4 KB)
📄
libaio.so.tar
(18 KB)
📄
libanl-2.28.so.28.so.tar.gz
(7.7 KB)
📄
libanl-2.28.so.tar
(19 KB)
📄
libanl.so.1.so.1.tar.gz
(7.7 KB)
📄
libanl.so.1.tar
(19 KB)
📄
libanl.so.so.tar.gz
(7.7 KB)
📄
libanl.so.tar
(19 KB)
📄
libanonymous.so.3.0.0.so.3.0.0.tar.gz
(9.38 KB)
📄
libanonymous.so.3.0.0.tar
(22 KB)
📄
libanonymous.so.3.so.3.tar.gz
(9.38 KB)
📄
libanonymous.so.3.tar
(22 KB)
📄
libanonymous.so.so.tar.gz
(9.38 KB)
📄
libanonymous.so.tar
(22 KB)
📄
libaom.so.3.1.1.so.3.1.1.tar.gz
(1.99 MB)
📄
libaom.so.3.1.1.tar
(5.44 MB)
📄
libaom.so.3.6.1.so.3.6.1.tar.gz
(2.19 MB)
📄
libaom.so.3.6.1.tar
(5.38 MB)
📄
libaom.so.3.so.3.tar.gz
(2.19 MB)
📄
libaom.so.3.tar
(5.38 MB)
📄
libapr-1.a.a.tar.gz
(123.08 KB)
📄
libapr-1.a.tar
(412.5 KB)
📄
libapr-1.so.0.6.3.so.0.6.3.tar.gz
(108.18 KB)
📄
libapr-1.so.0.6.3.tar
(238.5 KB)
📄
libapr-1.so.0.so.0.tar.gz
(108.17 KB)
📄
libapr-1.so.0.tar
(238.5 KB)
📄
libaprutil-1.so.0.6.1.so.0.6.1.tar.gz
(87.67 KB)
📄
libaprutil-1.so.0.6.1.tar
(193.5 KB)
📄
libaprutil-1.so.0.so.0.tar.gz
(87.66 KB)
📄
libaprutil-1.so.0.tar
(193.5 KB)
📄
libarchive.so.13.3.3.so.13.3.3.tar.gz
(351.97 KB)
📄
libarchive.so.13.3.3.tar
(759 KB)
📄
libarchive.so.13.so.13.tar.gz
(351.96 KB)
📄
libarchive.so.13.tar
(759 KB)
📄
libargon2.so.1.so.1.tar.gz
(15.7 KB)
📄
libargon2.so.1.tar
(36 KB)
📄
libargon2.tar
(52.5 KB)
📄
libargon2.tar.gz
(22.08 KB)
📄
libargon2.zip
(50.78 KB)
📄
libarpt_mangle.so.so.tar.gz
(4.57 KB)
📄
libarpt_mangle.so.tar
(13.5 KB)
📄
libasm-0.190.so.190.so.tar.gz
(15 KB)
📄
libasm-0.190.so.tar
(34.5 KB)
📄
libasm.so.1.so.1.tar.gz
(15 KB)
📄
libasm.so.1.tar
(34.5 KB)
📄
libasound.so.2.0.0.so.2.0.0.tar.gz
(459.92 KB)
📄
libasound.so.2.0.0.tar
(1.09 MB)
📄
libasound.so.2.so.2.tar.gz
(459.92 KB)
📄
libasound.so.2.tar
(1.09 MB)
📄
libaspell.so.15.1.5.so.15.1.5.tar.gz
(288.76 KB)
📄
libaspell.so.15.1.5.tar
(713.5 KB)
📄
libaspell.so.15.so.15.tar.gz
(288.75 KB)
📄
libaspell.so.15.tar
(713.5 KB)
📄
libasprintf.so.0.0.0.so.0.0.0.tar.gz
(4.17 KB)
📄
libasprintf.so.0.0.0.tar
(14.5 KB)
📄
libasprintf.so.0.so.0.tar.gz
(4.17 KB)
📄
libasprintf.so.0.tar
(14.5 KB)
📄
libasprintf.so.so.tar.gz
(4.17 KB)
📄
libasprintf.so.tar
(14.5 KB)
📄
libassuan.so.0.8.1.so.0.8.1.tar.gz
(38.02 KB)
📄
libassuan.so.0.8.1.tar
(92 KB)
📄
libassuan.so.0.so.0.tar.gz
(38.01 KB)
📄
libassuan.so.0.tar
(92 KB)
📄
libasyncns.so.0.3.1.so.0.3.1.tar.gz
(10.79 KB)
📄
libasyncns.so.0.3.1.tar
(25.5 KB)
📄
libasyncns.so.0.so.0.tar.gz
(10.8 KB)
📄
libasyncns.so.0.tar
(25.5 KB)
📄
libatk-1.0.so.0.0.so.0.tar.gz
(53.99 KB)
📄
libatk-1.0.so.0.tar
(176.5 KB)
📄
libatomic.so.1.2.0.so.1.2.0.tar.gz
(11.62 KB)
📄
libatomic.so.1.2.0.tar
(30 KB)
📄
libatomic.so.1.so.1.tar.gz
(11.61 KB)
📄
libatomic.so.1.tar
(30 KB)
📄
libatomic_ops.so.1.1.1.so.1.1.1.tar.gz
(3.74 KB)
📄
libatomic_ops.so.1.1.1.tar
(13.5 KB)
📄
libatomic_ops.so.1.so.1.tar.gz
(3.74 KB)
📄
libatomic_ops.so.1.tar
(13.5 KB)
📄
libatomic_ops_gpl.so.1.so.1.tar.gz
(3.9 KB)
📄
libatomic_ops_gpl.so.1.tar
(14 KB)
📄
libatopology.so.2.0.0.so.2.0.0.tar.gz
(56.4 KB)
📄
libatopology.so.2.0.0.tar
(125 KB)
📄
libatopology.so.2.so.2.tar.gz
(56.4 KB)
📄
libatopology.so.2.tar
(125 KB)
📄
libattr.so.1.1.2448.so.1.1.2448.tar.gz
(9.42 KB)
📄
libattr.so.1.1.2448.tar
(28 KB)
📄
libattr.so.1.so.1.tar.gz
(9.42 KB)
📄
libattr.so.1.tar
(28 KB)
📄
libaudit.so.1.0.0.so.1.0.0.tar.gz
(50.2 KB)
📄
libaudit.so.1.0.0.tar
(134.5 KB)
📄
libaudit.so.1.so.1.tar.gz
(50.2 KB)
📄
libaudit.so.1.tar
(134.5 KB)
📄
libaugeas.so.0.24.2.so.0.24.2.tar.gz
(195 KB)
📄
libaugeas.so.0.24.2.tar
(405.5 KB)
📄
libaugeas.so.0.so.0.tar.gz
(195 KB)
📄
libaugeas.so.0.tar
(405.5 KB)
📄
libauparse.so.0.0.0.so.0.0.0.tar.gz
(64.49 KB)
📄
libauparse.so.0.0.0.tar
(144 KB)
📄
libauparse.so.0.so.0.tar.gz
(64.49 KB)
📄
libauparse.so.0.tar
(144 KB)
📄
libauparse.so.so.tar.gz
(64.49 KB)
📄
libauparse.so.tar
(144 KB)
📄
libauthdb_imap.so.so.tar.gz
(38.16 KB)
📄
libauthdb_imap.so.tar
(113.5 KB)
📄
libauthselect.so.3.1.1.so.3.1.1.tar.gz
(38.71 KB)
📄
libauthselect.so.3.1.1.tar
(92 KB)
📄
libauthselect.so.3.so.3.tar.gz
(38.71 KB)
📄
libauthselect.so.3.tar
(92 KB)
📄
libavahi-client.so.3.2.9.so.3.2.9.tar.gz
(28.43 KB)
📄
libavahi-client.so.3.2.9.tar
(74.5 KB)
📄
libavahi-client.so.3.so.3.tar.gz
(28.42 KB)
📄
libavahi-client.so.3.tar
(74.5 KB)
📄
libavahi-common.so.3.5.3.so.3.5.3.tar.gz
(23.34 KB)
📄
libavahi-common.so.3.5.3.tar
(55 KB)
📄
libavahi-common.so.3.so.3.tar.gz
(23.34 KB)
📄
libavahi-common.so.3.tar
(55 KB)
📄
libavif.so.14.0.1.so.14.0.1.tar.gz
(66.13 KB)
📄
libavif.so.14.0.1.tar
(136 KB)
📄
libavif.so.14.so.14.tar.gz
(66.13 KB)
📄
libavif.so.14.tar
(136 KB)
📄
libbabeltrace-ctf-text.so.1.so.1.tar.gz
(19.65 KB)
📄
libbabeltrace-ctf-text.so.1.tar
(47 KB)
📄
libbabeltrace-ctf.so.1.so.1.tar.gz
(141.75 KB)
📄
libbabeltrace-ctf.so.1.tar
(337 KB)
📄
libbabeltrace-dummy.so.1.0.0.so.1.0.0.tar.gz
(3.27 KB)
📄
libbabeltrace-dummy.so.1.0.0.tar
(9.5 KB)
📄
libbabeltrace-dummy.so.1.so.1.tar.gz
(3.27 KB)
📄
libbabeltrace-dummy.so.1.tar
(9.5 KB)
📄
libbabeltrace.so.1.0.0.so.1.0.0.tar.gz
(24.55 KB)
📄
libbabeltrace.so.1.0.0.tar
(59 KB)
📄
libbabeltrace.so.1.so.1.tar.gz
(24.54 KB)
📄
libbabeltrace.so.1.tar
(59 KB)
📄
libbasicobjects.so.0.1.0.so.0.1.0.tar.gz
(3.78 KB)
📄
libbasicobjects.so.0.1.0.tar
(13.5 KB)
📄
libbasicobjects.so.0.so.0.tar.gz
(3.78 KB)
📄
libbasicobjects.so.0.tar
(13.5 KB)
📄
libbfd-2.30-128.el8_10.so.30-128.el8_10.so.tar.gz
(576.46 KB)
📄
libbfd-2.30-128.el8_10.so.tar
(1.38 MB)
📄
libbind9.so.161.0.4.so.161.0.4.tar.gz
(31.26 KB)
📄
libbind9.so.161.0.4.tar
(74 KB)
📄
libbind9.so.161.so.161.tar.gz
(31.25 KB)
📄
libbind9.so.161.tar
(74 KB)
📄
libbind9.so.so.tar.gz
(31.25 KB)
📄
libbind9.so.tar
(74 KB)
📄
libblkid.so.1.1.0.so.1.1.0.tar.gz
(155.39 KB)
📄
libblkid.so.1.1.0.tar
(337.5 KB)
📄
libblkid.so.1.so.1.tar.gz
(155.38 KB)
📄
libblkid.so.1.tar
(337.5 KB)
📄
libbpf.so.0.5.0.so.0.5.0.tar.gz
(141.34 KB)
📄
libbpf.so.0.5.0.tar
(302.5 KB)
📄
libbpf.so.0.so.0.tar.gz
(141.34 KB)
📄
libbpf.so.0.tar
(302.5 KB)
📄
libbrotlicommon.so.1.0.6.so.1.0.6.tar.gz
(62.08 KB)
📄
libbrotlicommon.so.1.0.6.tar
(133.5 KB)
📄
libbrotlicommon.so.1.so.1.tar.gz
(62.08 KB)
📄
libbrotlicommon.so.1.tar
(133.5 KB)
📄
libbrotlidec.so.1.0.6.so.1.0.6.tar.gz
(24.33 KB)
📄
libbrotlidec.so.1.0.6.tar
(54 KB)
📄
libbrotlidec.so.1.so.1.tar.gz
(24.32 KB)
📄
libbrotlidec.so.1.tar
(182.5 KB)
📄
libbrotlienc.so.1.0.6.so.1.0.6.tar.gz
(256.03 KB)
📄
libbrotlienc.so.1.0.6.tar
(563.5 KB)
📄
libbrotlienc.so.1.so.1.tar.gz
(256.03 KB)
📄
libbrotlienc.so.1.tar
(3.9 MB)
📄
libbsock.so.so.tar.gz
(12.11 KB)
📄
libbsock.so.tar
(30.5 KB)
📄
libbsock_preload.so.so.tar.gz
(3.43 KB)
📄
libbsock_preload.so.tar
(9 KB)
📄
libbz2.so.1.0.6.so.1.0.6.tar.gz
(32.51 KB)
📄
libbz2.so.1.0.6.tar
(73 KB)
📄
libbz2.so.1.so.1.tar.gz
(32.5 KB)
📄
libbz2.so.1.tar
(73 KB)
📄
libbz2.so.so.tar.gz
(32.51 KB)
📄
libbz2.so.tar
(73 KB)
📄
libc-2.28.so.28.so.tar.gz
(875.3 KB)
📄
libc-2.28.so.tar
(2.07 MB)
📄
libc-client11.tar
(1.81 MB)
📄
libc-client11.tar.gz
(728.04 KB)
📄
libc-client11.zip
(1.76 MB)
📄
libc-header-start.h.h.tar.gz
(1.04 KB)
📄
libc-header-start.h.tar
(4.5 KB)
📄
libc-version.h.h.tar.gz
(750 B)
📄
libc-version.h.tar
(3 KB)
📄
libc.so.6.so.6.tar.gz
(875.3 KB)
📄
libc.so.6.tar
(2.07 MB)
📄
libc.so.so.tar.gz
(269 B)
📄
libc.so.tar
(2 KB)
📄
libc_nonshared.a.a.tar.gz
(7.28 KB)
📄
libc_nonshared.a.tar
(126.5 KB)
📄
libcairo.so.2.11512.0.so.2.11512.0.tar.gz
(578.3 KB)
📄
libcairo.so.2.11512.0.tar
(1.15 MB)
📄
libcairo.so.2.so.2.tar.gz
(578.29 KB)
📄
libcairo.so.2.tar
(1.15 MB)
📄
libcap-ng.so.0.0.0.so.0.0.0.tar.gz
(10.47 KB)
📄
libcap-ng.so.0.0.0.tar
(26 KB)
📄
libcap-ng.so.0.so.0.tar.gz
(10.47 KB)
📄
libcap-ng.so.0.tar
(26 KB)
📄
libcap.pc.pc.tar.gz
(246 B)
📄
libcap.pc.tar
(2 KB)
📄
libcap.so.2.48.so.2.48.tar.gz
(15.5 KB)
📄
libcap.so.2.48.tar
(34.5 KB)
📄
libcap.so.2.so.2.tar.gz
(15.49 KB)
📄
libcap.so.2.tar
(34.5 KB)
📄
libcap.so.so.tar.gz
(15.5 KB)
📄
libcap.so.tar
(34.5 KB)
📄
libcare-plugin.so.so.tar.gz
(194.71 KB)
📄
libcare-plugin.so.tar
(940 KB)
📄
libcare.service.service.tar.gz
(269 B)
📄
libcare.service.tar
(2 KB)
📄
libcare.socket.socket.tar.gz
(247 B)
📄
libcare.socket.tar
(2 KB)
📄
libcares.so.2.2.0.so.2.2.0.tar.gz
(38.48 KB)
📄
libcares.so.2.2.0.tar
(79 KB)
📄
libcares.so.2.so.2.tar.gz
(38.47 KB)
📄
libcares.so.2.tar
(79 KB)
📄
libcc1.so.0.0.0.so.0.0.0.tar.gz
(58.12 KB)
📄
libcc1.so.0.0.0.tar
(141.5 KB)
📄
libcc1.so.0.so.0.tar.gz
(58.12 KB)
📄
libcc1.so.0.tar
(141.5 KB)
📄
libcc1.so.so.tar.gz
(58.12 KB)
📄
libcc1.so.tar
(141.5 KB)
📄
libcdt.so.5.0.0.so.5.0.0.tar.gz
(13.46 KB)
📄
libcdt.so.5.0.0.tar
(30 KB)
📄
libcdt.so.5.so.5.tar.gz
(13.47 KB)
📄
libcdt.so.5.tar
(30 KB)
📄
libcfitsio.so.7.3.47.so.7.3.47.tar.gz
(586.1 KB)
📄
libcfitsio.so.7.3.47.tar
(1.5 MB)
📄
libcfitsio.so.7.so.7.tar.gz
(586.1 KB)
📄
libcfitsio.so.7.tar
(1.5 MB)
📄
libcgraph.so.6.0.0.so.6.0.0.tar.gz
(45.33 KB)
📄
libcgraph.so.6.0.0.tar
(101.5 KB)
📄
libcgraph.so.6.so.6.tar.gz
(45.32 KB)
📄
libcgraph.so.6.tar
(101.5 KB)
📄
libcollection.so.4.1.1.so.4.1.1.tar.gz
(22.82 KB)
📄
libcollection.so.4.1.1.tar
(54.5 KB)
📄
libcollection.so.4.so.4.tar.gz
(22.81 KB)
📄
libcollection.so.4.tar
(54.5 KB)
📄
libcom_err.so.2.1.so.2.1.tar.gz
(7.03 KB)
📄
libcom_err.so.2.1.tar
(18 KB)
📄
libcom_err.so.2.so.2.tar.gz
(7.03 KB)
📄
libcom_err.so.2.tar
(18 KB)
📄
libcom_err.so.so.tar.gz
(7.03 KB)
📄
libcom_err.so.tar
(18 KB)
📄
libcomps.so.0.so.0.tar.gz
(69.98 KB)
📄
libcomps.so.0.tar
(194.5 KB)
📄
libcord.so.1.3.0.so.1.3.0.tar.gz
(16 KB)
📄
libcord.so.1.3.0.tar
(35 KB)
📄
libcord.so.1.so.1.tar.gz
(16 KB)
📄
libcord.so.1.tar
(35 KB)
📄
libcpupower.so.0.0.1.so.0.0.1.tar.gz
(8.82 KB)
📄
libcpupower.so.0.0.1.tar
(25 KB)
📄
libcpupower.so.0.so.0.tar.gz
(8.82 KB)
📄
libcpupower.so.0.tar
(25 KB)
📄
libcrack.so.2.9.0.so.2.9.0.tar.gz
(15.72 KB)
📄
libcrack.so.2.9.0.tar
(47 KB)
📄
libcrack.so.2.so.2.tar.gz
(15.72 KB)
📄
libcrack.so.2.tar
(47 KB)
📄
libcriu.a.a.tar.gz
(20.34 KB)
📄
libcriu.a.tar
(95.5 KB)
📄
libcriu.so.1.0.so.1.0.tar.gz
(23.81 KB)
📄
libcriu.so.1.0.tar
(74.5 KB)
📄
libcriu.so.1.so.1.tar.gz
(23.81 KB)
📄
libcriu.so.1.tar
(74.5 KB)
📄
libcriu.so.so.tar.gz
(23.81 KB)
📄
libcriu.so.tar
(74.5 KB)
📄
libcroco-0.6.so.3.0.1.6.so.3.0.1.tar.gz
(92.87 KB)
📄
libcroco-0.6.so.3.0.1.tar
(244 KB)
📄
libcroco-0.6.so.3.6.so.3.tar.gz
(92.87 KB)
📄
libcroco-0.6.so.3.tar
(244 KB)
📄
libcrypt.pc.pc.tar.gz
(299 B)
📄
libcrypt.pc.tar
(2 KB)
📄
libcrypt.so.1.1.0.so.1.1.0.tar.gz
(44.89 KB)
📄
libcrypt.so.1.1.0.tar
(134.5 KB)
📄
libcrypt.so.1.so.1.tar.gz
(44.89 KB)
📄
libcrypt.so.1.tar
(134.5 KB)
📄
libcrypt.so.so.tar.gz
(44.89 KB)
📄
libcrypt.so.tar
(134.5 KB)
📄
libcrypto.pc.pc.tar.gz
(285 B)
📄
libcrypto.pc.tar
(2 KB)
📄
libcrypto.so.1.0.2o.so.1.0.2o.tar.gz
(1.08 MB)
📄
libcrypto.so.1.0.2o.tar
(2.4 MB)
📄
libcrypto.so.1.1.1k.so.1.1.1k.tar.gz
(1.35 MB)
📄
libcrypto.so.1.1.1k.tar
(2.95 MB)
📄
libcrypto.so.1.1.so.1.1.tar.gz
(1.35 MB)
📄
libcrypto.so.1.1.tar
(2.95 MB)
📄
libcrypto.so.10.so.10.tar.gz
(1.08 MB)
📄
libcrypto.so.10.tar
(2.4 MB)
📄
libcrypto.so.11.so.11.tar.gz
(1.28 MB)
📄
libcrypto.so.11.tar
(2.84 MB)
📄
libcrypto.so.so.tar.gz
(1.35 MB)
📄
libcrypto.so.tar
(2.95 MB)
📄
libcryptsetup.so.12.so.12.tar.gz
(242.25 KB)
📄
libcryptsetup.so.12.tar
(516 KB)
📄
libcups.so.2.so.2.tar.gz
(252.62 KB)
📄
libcups.so.2.tar
(616.5 KB)
📄
libcupscgi.so.1.so.1.tar.gz
(30.42 KB)
📄
libcupscgi.so.1.tar
(67 KB)
📄
libcupsimage.so.2.so.2.tar.gz
(18.25 KB)
📄
libcupsimage.so.2.tar
(42 KB)
📄
libcupsmime.so.1.so.1.tar.gz
(13.02 KB)
📄
libcupsmime.so.1.tar
(30 KB)
📄
libcupsppdc.so.1.so.1.tar.gz
(53.21 KB)
📄
libcupsppdc.so.1.tar
(131.5 KB)
📄
libcurl.pc.pc.tar.gz
(1.5 KB)
📄
libcurl.pc.tar
(5 KB)
📄
libcurl.so.4.5.0.so.4.5.0.tar.gz
(277.8 KB)
📄
libcurl.so.4.5.0.tar
(588.5 KB)
📄
libcurl.so.4.so.4.tar.gz
(277.79 KB)
📄
libcurl.so.4.tar
(588.5 KB)
📄
libcurl.so.so.tar.gz
(277.79 KB)
📄
libcurl.so.tar
(588.5 KB)
📄
libcurl.tar
(1.5 MB)
📄
libcurl.tar.gz
(688.1 KB)
📄
libcurl.zip
(1.49 MB)
📄
libcurses.so.so.tar.gz
(114 B)
📄
libcurses.so.tar
(2 KB)
📄
libcursesw.so.so.tar.gz
(117 B)
📄
libcursesw.so.tar
(2 KB)
📄
libcxgb4-rdmav34.so.so.tar.gz
(19.85 KB)
📄
libcxgb4-rdmav34.so.tar
(46.5 KB)
📄
libdaemon.so.0.5.0.so.0.5.0.tar.gz
(12.37 KB)
📄
libdaemon.so.0.5.0.tar
(32 KB)
📄
libdaemon.so.0.so.0.tar.gz
(12.37 KB)
📄
libdaemon.so.0.tar
(32 KB)
📄
libdatrie.so.1.3.2.so.1.3.2.tar.gz
(14.71 KB)
📄
libdatrie.so.1.3.2.tar
(37 KB)
📄
libdatrie.so.1.so.1.tar.gz
(14.71 KB)
📄
libdatrie.so.1.tar
(37 KB)
📄
libdav1d.so.3.1.0.so.3.1.0.tar.gz
(402.81 KB)
📄
libdav1d.so.3.1.0.tar
(886 KB)
📄
libdav1d.so.3.so.3.tar.gz
(402.91 KB)
📄
libdav1d.so.3.tar
(1.73 MB)
📄
libdb-5.3.so.3.so.tar.gz
(825.43 KB)
📄
libdb-5.3.so.tar
(1.78 MB)
📄
libdb-5.so.so.tar.gz
(825.43 KB)
📄
libdb-5.so.tar
(1.78 MB)
📄
libdb.so.so.tar.gz
(825.43 KB)
📄
libdb.so.tar
(1.78 MB)
📄
libdb.tar
(128.5 KB)
📄
libdb.tar.gz
(31.43 KB)
📄
libdb.zip
(126.33 KB)
📄
libdbus-1.so.3.19.7.so.3.19.7.tar.gz
(150.74 KB)
📄
libdbus-1.so.3.19.7.tar
(345 KB)
📄
libdbus-1.so.3.so.3.tar.gz
(150.74 KB)
📄
libdbus-1.so.3.tar
(345 KB)
📄
libdbus-glib-1.so.2.so.2.tar.gz
(73.64 KB)
📄
libdbus-glib-1.so.2.tar
(197 KB)
📄
libdcrypt_openssl.so.so.tar.gz
(35.19 KB)
📄
libdcrypt_openssl.so.tar
(110 KB)
📄
libde265.tar
(601.5 KB)
📄
libde265.tar.gz
(251.73 KB)
📄
libde265.zip
(598.57 KB)
📄
libdebuginfod-0.190.so.190.so.tar.gz
(14.51 KB)
📄
libdebuginfod-0.190.so.tar
(33.5 KB)
📄
libdebuginfod.so.1.so.1.tar.gz
(14.51 KB)
📄
libdebuginfod.so.1.tar
(33.5 KB)
📄
libdevmapper.so.1.02.so.1.02.tar.gz
(166.27 KB)
📄
libdevmapper.so.1.02.tar
(364.5 KB)
📄
libdhash.so.1.1.0.so.1.1.0.tar.gz
(6.93 KB)
📄
libdhash.so.1.1.0.tar
(17.5 KB)
📄
libdhash.so.1.so.1.tar.gz
(6.93 KB)
📄
libdhash.so.1.tar
(17.5 KB)
📄
libdhcpctl.so.0.0.0.so.0.0.0.tar.gz
(9.1 KB)
📄
libdhcpctl.so.0.0.0.tar
(26 KB)
📄
libdhcpctl.so.0.so.0.tar.gz
(9.1 KB)
📄
libdhcpctl.so.0.tar
(26 KB)
📄
libdl-2.28.so.28.so.tar.gz
(5.83 KB)
📄
libdl-2.28.so.tar
(20.5 KB)
📄
libdl.so.2.so.2.tar.gz
(5.83 KB)
📄
libdl.so.2.tar
(20.5 KB)
📄
libdl.so.so.tar.gz
(5.83 KB)
📄
libdl.so.tar
(20.5 KB)
📄
libdnf.so.2.so.2.tar.gz
(748.6 KB)
📄
libdnf.so.2.tar
(1.95 MB)
📄
libdnf.tar
(2 KB)
📄
libdnf.tar.gz
(228 B)
📄
libdnf.zip
(356 B)
📄
libdns.so.1115.0.3.so.1115.0.3.tar.gz
(1 MB)
📄
libdns.so.1115.0.3.tar
(2.34 MB)
📄
libdns.so.1115.so.1115.tar.gz
(1 MB)
📄
libdns.so.1115.tar
(2.34 MB)
📄
libdns.so.so.tar.gz
(1 MB)
📄
libdns.so.tar
(2.34 MB)
📄
libdovecot-compression.so.0.0.0.so.0.0.0.tar.gz
(23.37 KB)
📄
libdovecot-compression.so.0.0.0.tar
(78 KB)
📄
libdovecot-dsync.so.0.0.0.so.0.0.0.tar.gz
(109.35 KB)
📄
libdovecot-dsync.so.0.0.0.tar
(307.5 KB)
📄
libdovecot-fts.so.0.so.0.tar.gz
(74.38 KB)
📄
libdovecot-fts.so.0.tar
(211.5 KB)
📄
libdovecot-lda.so.0.so.0.tar.gz
(17.98 KB)
📄
libdovecot-lda.so.0.tar
(55.5 KB)
📄
libdovecot-login.so.0.0.0.so.0.0.0.tar.gz
(57.94 KB)
📄
libdovecot-login.so.0.0.0.tar
(167.5 KB)
📄
libdovecot-sql.so.0.so.0.tar.gz
(22.72 KB)
📄
libdovecot-sql.so.0.tar
(72.5 KB)
📄
libdovecot.so.0.0.0.so.0.0.0.tar.gz
(1020.08 KB)
📄
libdovecot.so.0.0.0.tar
(2.89 MB)
📄
libdriver_sqlite.so.so.tar.gz
(8.76 KB)
📄
libdriver_sqlite.so.tar
(30 KB)
📄
libdrm.so.2.4.0.so.2.4.0.tar.gz
(39.02 KB)
📄
libdrm.so.2.4.0.tar
(87.5 KB)
📄
libdrm.so.2.so.2.tar.gz
(39.02 KB)
📄
libdrm.so.2.tar
(87.5 KB)
📄
libdrm_amdgpu.so.1.0.0.so.1.0.0.tar.gz
(18.88 KB)
📄
libdrm_amdgpu.so.1.0.0.tar
(46 KB)
📄
libdrm_amdgpu.so.1.so.1.tar.gz
(18.88 KB)
📄
libdrm_amdgpu.so.1.tar
(46 KB)
📄
libdrm_intel.so.1.0.0.so.1.0.0.tar.gz
(66.81 KB)
📄
libdrm_intel.so.1.0.0.tar
(145 KB)
📄
libdrm_intel.so.1.so.1.tar.gz
(66.8 KB)
📄
libdrm_intel.so.1.tar
(145 KB)
📄
libdrm_nouveau.so.2.so.2.tar.gz
(17.04 KB)
📄
libdrm_nouveau.so.2.tar
(38.5 KB)
📄
libdrm_radeon.so.1.0.1.so.1.0.1.tar.gz
(22.88 KB)
📄
libdrm_radeon.so.1.0.1.tar
(50.5 KB)
📄
libdrm_radeon.so.1.so.1.tar.gz
(22.88 KB)
📄
libdrm_radeon.so.1.tar
(50.5 KB)
📄
libdvdnav.so.4.2.0.so.4.2.0.tar.gz
(39.7 KB)
📄
libdvdnav.so.4.2.0.tar
(91 KB)
📄
libdvdnav.so.4.so.4.tar.gz
(39.69 KB)
📄
libdvdnav.so.4.tar
(91 KB)
📄
libdvdread.so.4.2.0.so.4.2.0.tar.gz
(54.88 KB)
📄
libdvdread.so.4.2.0.tar
(130 KB)
📄
libdvdread.so.4.so.4.tar.gz
(54.87 KB)
📄
libdvdread.so.4.tar
(130 KB)
📄
libdw-0.190.so.190.so.tar.gz
(265.51 KB)
📄
libdw-0.190.so.tar
(664.5 KB)
📄
libdw.so.1.so.1.tar.gz
(265.5 KB)
📄
libdw.so.1.tar
(664.5 KB)
📄
libe2p.so.2.3.so.2.3.tar.gz
(16.07 KB)
📄
libe2p.so.2.3.tar
(40 KB)
📄
libe2p.so.2.so.2.tar.gz
(16.07 KB)
📄
libe2p.so.2.tar
(40 KB)
📄
libe2p.so.so.tar.gz
(16.07 KB)
📄
libe2p.so.tar
(40 KB)
📄
libebt_arp.so.so.tar.gz
(5.88 KB)
📄
libebt_arp.so.tar
(17.5 KB)
📄
libebt_dnat.so.so.tar.gz
(4.06 KB)
📄
libebt_dnat.so.tar
(13.5 KB)
📄
libebt_ip.so.so.tar.gz
(8.48 KB)
📄
libebt_ip.so.tar
(21.5 KB)
📄
libebt_ip6.so.so.tar.gz
(7.91 KB)
📄
libebt_ip6.so.tar
(21.5 KB)
📄
libebt_log.so.so.tar.gz
(4.71 KB)
📄
libebt_log.so.tar
(13.5 KB)
📄
libebt_mark.so.so.tar.gz
(4.6 KB)
📄
libebt_mark.so.tar
(13.5 KB)
📄
libebt_mark_m.so.so.tar.gz
(3.94 KB)
📄
libebt_mark_m.so.tar
(13.5 KB)
📄
libebt_pkttype.so.so.tar.gz
(3.97 KB)
📄
libebt_pkttype.so.tar
(13.5 KB)
📄
libebt_snat.so.so.tar.gz
(4.18 KB)
📄
libebt_snat.so.tar
(13.5 KB)
📄
libebt_stp.so.so.tar.gz
(5.96 KB)
📄
libebt_stp.so.tar
(17.5 KB)
📄
libebt_vlan.so.so.tar.gz
(4.13 KB)
📄
libebt_vlan.so.tar
(13.5 KB)
📄
libedit.so.0.0.56.so.0.0.56.tar.gz
(92.92 KB)
📄
libedit.so.0.0.56.tar
(229.5 KB)
📄
libedit.so.0.so.0.tar.gz
(92.92 KB)
📄
libedit.so.0.tar
(229.5 KB)
📄
libefa-rdmav34.so.so.tar.gz
(19.28 KB)
📄
libefa-rdmav34.so.tar
(47 KB)
📄
libefa.so.1.2.48.0.so.1.2.48.0.tar.gz
(19.28 KB)
📄
libefa.so.1.2.48.0.tar
(47 KB)
📄
libefa.so.1.so.1.tar.gz
(19.27 KB)
📄
libefa.so.1.tar
(47 KB)
📄
libelf-0.190.so.190.so.tar.gz
(50.1 KB)
📄
libelf-0.190.so.tar
(108 KB)
📄
libelf.so.1.so.1.tar.gz
(50.09 KB)
📄
libelf.so.1.tar
(108 KB)
📄
libenchant.so.1.6.0.so.1.6.0.tar.gz
(21.13 KB)
📄
libenchant.so.1.6.0.tar
(51 KB)
📄
libenchant.so.1.so.1.tar.gz
(21.12 KB)
📄
libenchant.so.1.tar
(51 KB)
📄
libesoobS.so.2.0.0.so.2.0.0.tar.gz
(3.93 KB)
📄
libesoobS.so.2.0.0.tar
(13.5 KB)
📄
libesoobS.so.2.so.2.tar.gz
(3.93 KB)
📄
libesoobS.so.2.tar
(13.5 KB)
📄
libestr.so.0.0.0.so.0.0.0.tar.gz
(6.76 KB)
📄
libestr.so.0.0.0.tar
(18 KB)
📄
libestr.so.0.so.0.tar.gz
(6.76 KB)
📄
libestr.so.0.tar
(18 KB)
📄
libev.so.4.0.0.so.4.0.0.tar.gz
(29.11 KB)
📄
libev.so.4.0.0.tar
(70 KB)
📄
libev.so.4.so.4.tar.gz
(29.11 KB)
📄
libev.so.4.tar
(70 KB)
📄
libevdev.so.2.3.0.so.2.3.0.tar.gz
(38.31 KB)
📄
libevdev.so.2.3.0.tar
(114.5 KB)
📄
libevdev.so.2.so.2.tar.gz
(38.31 KB)
📄
libevdev.so.2.tar
(114.5 KB)
📄
libevent-2.1.so.6.0.2.1.so.6.0.2.tar.gz
(161.05 KB)
📄
libevent-2.1.so.6.0.2.tar
(372.5 KB)
📄
libevent-2.1.so.6.1.so.6.tar.gz
(161.05 KB)
📄
libevent-2.1.so.6.tar
(372.5 KB)
📄
libevent.pc.pc.tar.gz
(306 B)
📄
libevent.pc.tar
(2 KB)
📄
libevent.so.so.tar.gz
(161.04 KB)
📄
libevent.so.tar
(372.5 KB)
📄
libevent_core-2.1.so.6.1.so.6.tar.gz
(102.28 KB)
📄
libevent_core-2.1.so.6.tar
(240 KB)
📄
libevent_core.so.so.tar.gz
(102.28 KB)
📄
libevent_core.so.tar
(240 KB)
📄
libevent_extra-2.1.so.6.0.2.1.so.6.0.2.tar.gz
(65.83 KB)
📄
libevent_extra-2.1.so.6.0.2.tar
(149 KB)
📄
libevent_extra-2.1.so.6.1.so.6.tar.gz
(65.82 KB)
📄
libevent_extra-2.1.so.6.tar
(149 KB)
📄
libevent_extra.pc.pc.tar.gz
(281 B)
📄
libevent_extra.pc.tar
(2 KB)
📄
libevent_extra.so.so.tar.gz
(65.82 KB)
📄
libevent_extra.so.tar
(149 KB)
📄
libevent_openssl-2.1.so.6.1.so.6.tar.gz
(12.08 KB)
📄
libevent_openssl-2.1.so.6.tar
(30 KB)
📄
libevent_openssl.so.so.tar.gz
(12.08 KB)
📄
libevent_openssl.so.tar
(30 KB)
📄
libevent_pthreads-2.1.so.6.0.2.1.so.6.0.2.tar.gz
(4.09 KB)
📄
libevent_pthreads-2.1.so.6.0.2.tar
(13.5 KB)
📄
libevent_pthreads.pc.pc.tar.gz
(311 B)
📄
libevent_pthreads.pc.tar
(2 KB)
📄
libevent_pthreads.so.so.tar.gz
(4.09 KB)
📄
libevent_pthreads.so.tar
(13.5 KB)
📄
libexif.so.12.3.4.so.12.3.4.tar.gz
(86.94 KB)
📄
libexif.so.12.3.4.tar
(291 KB)
📄
libexif.so.12.so.12.tar.gz
(86.94 KB)
📄
libexif.so.12.tar
(291 KB)
📄
libexpat.so.1.8.10.so.1.8.10.tar.gz
(89.35 KB)
📄
libexpat.so.1.8.10.tar
(256.5 KB)
📄
libexpat.so.1.so.1.tar.gz
(89.35 KB)
📄
libexpat.so.1.tar
(256.5 KB)
📄
libexpat.so.so.tar.gz
(89.35 KB)
📄
libexpat.so.tar
(256.5 KB)
📄
libexslt.pc.pc.tar.gz
(278 B)
📄
libexslt.pc.tar
(2 KB)
📄
libexslt.so.0.8.20.so.0.8.20.tar.gz
(39.71 KB)
📄
libexslt.so.0.8.20.tar
(95 KB)
📄
libexslt.so.0.so.0.tar.gz
(39.7 KB)
📄
libexslt.so.0.tar
(95 KB)
📄
libexslt.so.so.tar.gz
(39.7 KB)
📄
libexslt.so.tar
(95 KB)
📄
libexslt.tar
(10.5 KB)
📄
libexslt.tar.gz
(1.78 KB)
📄
libexslt.zip
(7.86 KB)
📄
libext2fs.so.2.4.so.2.4.tar.gz
(201.63 KB)
📄
libext2fs.so.2.4.tar
(428.5 KB)
📄
libext2fs.so.2.so.2.tar.gz
(201.63 KB)
📄
libext2fs.so.2.tar
(428.5 KB)
📄
libext2fs.so.so.tar.gz
(201.63 KB)
📄
libext2fs.so.tar
(428.5 KB)
📄
libfa.so.1.5.3.so.1.5.3.tar.gz
(82.19 KB)
📄
libfa.so.1.5.3.tar
(157 KB)
📄
libfa.so.1.so.1.tar.gz
(82.19 KB)
📄
libfa.so.1.tar
(157 KB)
📄
libfastjson.so.4.3.0.so.4.3.0.tar.gz
(21.49 KB)
📄
libfastjson.so.4.3.0.tar
(51 KB)
📄
libfastjson.so.4.so.4.tar.gz
(21.49 KB)
📄
libfastjson.so.4.tar
(51 KB)
📄
libfbclient.so.2.so.2.tar.gz
(1.3 MB)
📄
libfbclient.so.2.tar
(3.25 MB)
📄
libfbclient.so.4.0.6.so.4.0.6.tar.gz
(1.3 MB)
📄
libfbclient.so.4.0.6.tar
(3.25 MB)
📄
libfbtrace.so.so.tar.gz
(987.35 KB)
📄
libfbtrace.so.tar
(2.33 MB)
📄
libfdisk.so.1.1.0.so.1.1.0.tar.gz
(184.44 KB)
📄
libfdisk.so.1.1.0.tar
(404 KB)
📄
libfdisk.so.1.so.1.tar.gz
(184.43 KB)
📄
libfdisk.so.1.tar
(404 KB)
📄
libferret.so.so.tar.gz
(25.94 KB)
📄
libferret.so.tar
(66.5 KB)
📄
libffi.so.6.0.2.so.6.0.2.tar.gz
(17.75 KB)
📄
libffi.so.6.0.2.tar
(38 KB)
📄
libffi.so.6.so.6.tar.gz
(17.74 KB)
📄
libffi.so.6.tar
(38 KB)
📄
libfftw3.so.3.5.5.so.3.5.5.tar.gz
(880.64 KB)
📄
libfftw3.so.3.5.5.tar
(2.36 MB)
📄
libfftw3.so.3.so.3.tar.gz
(880.63 KB)
📄
libfftw3.so.3.tar
(2.36 MB)
📄
libfftw3_omp.so.3.5.5.so.3.5.5.tar.gz
(11.07 KB)
📄
libfftw3_omp.so.3.5.5.tar
(33 KB)
📄
libfftw3_omp.so.3.so.3.tar.gz
(11.07 KB)
📄
libfftw3_omp.so.3.tar
(33 KB)
📄
libfftw3_threads.so.3.5.5.so.3.5.5.tar.gz
(11.95 KB)
📄
libfftw3_threads.so.3.5.5.tar
(37 KB)
📄
libfftw3_threads.so.3.so.3.tar.gz
(11.95 KB)
📄
libfftw3_threads.so.3.tar
(37 KB)
📄
libfontconfig.so.1.so.1.tar.gz
(135.65 KB)
📄
libfontconfig.so.1.tar
(284.5 KB)
📄
libfontconfig.so.so.tar.gz
(135.65 KB)
📄
libfontconfig.so.tar
(284.5 KB)
📄
libfontenc.so.1.0.0.so.1.0.0.tar.gz
(12.25 KB)
📄
libfontenc.so.1.0.0.tar
(30 KB)
📄
libfontenc.so.1.so.1.tar.gz
(12.25 KB)
📄
libfontenc.so.1.tar
(30 KB)
📄
libform.so.5.9.so.5.9.tar.gz
(30.07 KB)
📄
libform.so.5.9.tar
(68.5 KB)
📄
libform.so.5.so.5.tar.gz
(30.07 KB)
📄
libform.so.5.tar
(68.5 KB)
📄
libform.so.6.1.so.6.1.tar.gz
(31.39 KB)
📄
libform.so.6.1.tar
(73 KB)
📄
libform.so.6.so.6.tar.gz
(31.39 KB)
📄
libform.so.6.tar
(73 KB)
📄
libform.so.so.tar.gz
(31.39 KB)
📄
libform.so.tar
(73 KB)
📄
libformw.so.5.9.so.5.9.tar.gz
(33.36 KB)
📄
libformw.so.5.9.tar
(77 KB)
📄
libformw.so.5.so.5.tar.gz
(33.36 KB)
📄
libformw.so.5.tar
(77 KB)
📄
libformw.so.6.1.so.6.1.tar.gz
(35.42 KB)
📄
libformw.so.6.1.tar
(81 KB)
📄
libformw.so.6.so.6.tar.gz
(35.42 KB)
📄
libformw.so.6.tar
(81 KB)
📄
libformw.so.so.tar.gz
(35.42 KB)
📄
libformw.so.tar
(81 KB)
📄
libfreebl3.chk.chk.tar.gz
(188 B)
📄
libfreebl3.chk.tar
(2 KB)
📄
libfreebl3.so.so.tar.gz
(4.4 KB)
📄
libfreebl3.so.tar
(13.5 KB)
📄
libfreeblpriv3.chk.chk.tar.gz
(190 B)
📄
libfreeblpriv3.chk.tar
(2 KB)
📄
libfreeblpriv3.so.so.tar.gz
(463.35 KB)
📄
libfreeblpriv3.so.tar
(1.04 MB)
📄
libfreetype.so.6.16.1.so.6.16.1.tar.gz
(392.67 KB)
📄
libfreetype.so.6.16.1.tar
(766.5 KB)
📄
libfreetype.so.6.so.6.tar.gz
(392.66 KB)
📄
libfreetype.so.6.tar
(766.5 KB)
📄
libfreetype.so.so.tar.gz
(392.66 KB)
📄
libfreetype.so.tar
(766.5 KB)
📄
libfribidi.so.0.4.0.so.0.4.0.tar.gz
(23.24 KB)
📄
libfribidi.so.0.4.0.tar
(114 KB)
📄
libfribidi.so.0.so.0.tar.gz
(23.23 KB)
📄
libfribidi.so.0.tar
(114 KB)
📄
libfs_compress.so.so.tar.gz
(6.16 KB)
📄
libfs_compress.so.tar
(22.5 KB)
📄
libfs_crypt.so.so.tar.gz
(11.26 KB)
📄
libfs_crypt.so.tar
(40.5 KB)
📄
libfs_mail_crypt.so.so.tar.gz
(10.88 KB)
📄
libfs_mail_crypt.so.tar
(39.5 KB)
📄
libfstrm.pc.pc.tar.gz
(246 B)
📄
libfstrm.pc.tar
(2 KB)
📄
libfstrm.so.0.1.0.so.0.1.0.tar.gz
(18.87 KB)
📄
libfstrm.so.0.1.0.tar
(46.5 KB)
📄
libfstrm.so.0.so.0.tar.gz
(18.86 KB)
📄
libfstrm.so.0.tar
(46.5 KB)
📄
libfstrm.so.so.tar.gz
(18.86 KB)
📄
libfstrm.so.tar
(46.5 KB)
📄
libfuse.so.2.9.7.so.2.9.7.tar.gz
(82.1 KB)
📄
libfuse.so.2.9.7.tar
(258 KB)
📄
libfuse.so.2.so.2.tar.gz
(82.1 KB)
📄
libfuse.so.2.tar
(258 KB)
📄
libg.a.a.tar.gz
(1.42 KB)
📄
libg.a.tar
(9.5 KB)
📄
libgailutil.so.18.0.1.so.18.0.1.tar.gz
(12.36 KB)
📄
libgailutil.so.18.0.1.tar
(37.5 KB)
📄
libgailutil.so.18.so.18.tar.gz
(12.35 KB)
📄
libgailutil.so.18.tar
(37.5 KB)
📄
libgalera_smm.so.so.tar.gz
(1.1 MB)
📄
libgalera_smm.so.tar
(2.43 MB)
📄
libgbm.so.1.0.0.so.1.0.0.tar.gz
(29.76 KB)
📄
libgbm.so.1.0.0.tar
(63.5 KB)
📄
libgbm.so.1.so.1.tar.gz
(29.76 KB)
📄
libgbm.so.1.tar
(63.5 KB)
📄
libgc.so.1.3.2.so.1.3.2.tar.gz
(84.52 KB)
📄
libgc.so.1.3.2.tar
(184.5 KB)
📄
libgc.so.1.so.1.tar.gz
(84.52 KB)
📄
libgc.so.1.tar
(184.5 KB)
📄
libgcc.a.a.tar.gz
(2.08 MB)
📄
libgcc.a.tar
(3.01 MB)
📄
libgcc_eh.a.a.tar.gz
(19.34 KB)
📄
libgcc_eh.a.tar
(60 KB)
📄
libgcc_s-8-20210514.so.1.so.1.tar.gz
(47.43 KB)
📄
libgcc_s-8-20210514.so.1.tar
(99 KB)
📄
libgcc_s.so.1.so.1.tar.gz
(47.42 KB)
📄
libgcc_s.so.1.tar
(99 KB)
📄
libgcc_s.so.so.tar.gz
(262 B)
📄
libgcc_s.so.tar
(2 KB)
📄
libgccpp.so.1.3.1.so.1.3.1.tar.gz
(3.31 KB)
📄
libgccpp.so.1.3.1.tar
(9.5 KB)
📄
libgccpp.so.1.so.1.tar.gz
(3.31 KB)
📄
libgccpp.so.1.tar
(9.5 KB)
📄
libgcov.a.a.tar.gz
(15.19 KB)
📄
libgcov.a.tar
(143.5 KB)
📄
libgcrypt.so.20.2.5.so.20.2.5.tar.gz
(478.29 KB)
📄
libgcrypt.so.20.2.5.tar
(1.13 MB)
📄
libgcrypt.so.20.so.20.tar.gz
(478.29 KB)
📄
libgcrypt.so.20.tar
(1.13 MB)
📄
libgcrypt.so.so.tar.gz
(478.29 KB)
📄
libgcrypt.so.tar
(1.13 MB)
📄
libgd.so.3.0.5.so.3.0.5.tar.gz
(141.4 KB)
📄
libgd.so.3.0.5.tar
(412 KB)
📄
libgd.so.3.so.3.tar.gz
(141.39 KB)
📄
libgd.so.3.tar
(412 KB)
📄
libgd.so.so.tar.gz
(141.4 KB)
📄
libgd.so.tar
(412 KB)
📄
libgd.tar
(422 KB)
📄
libgd.tar.gz
(142.6 KB)
📄
libgd.zip
(418.74 KB)
📄
libgdbm.so.6.0.0.so.6.0.0.tar.gz
(29.92 KB)
📄
libgdbm.so.6.0.0.tar
(67 KB)
📄
libgdbm.so.6.so.6.tar.gz
(29.92 KB)
📄
libgdbm.so.6.tar
(67 KB)
📄
libgdbm.so.so.tar.gz
(29.92 KB)
📄
libgdbm.so.tar
(67 KB)
📄
libgdbm_compat.so.4.so.4.tar.gz
(5.81 KB)
📄
libgdbm_compat.so.4.tar
(18 KB)
📄
libgdbm_compat.so.so.tar.gz
(5.81 KB)
📄
libgdbm_compat.so.tar
(18 KB)
📄
libgdk-x11-2.0.so.0.0.so.0.tar.gz
(346.54 KB)
📄
libgdk-x11-2.0.so.0.2400.32.0.so.0.2400.32.tar.gz
(346.55 KB)
📄
libgdk-x11-2.0.so.0.2400.32.tar
(816 KB)
📄
libgdk-x11-2.0.so.0.tar
(816 KB)
📄
libgdk_pixbuf-2.0.so.0.0.so.0.tar.gz
(72.55 KB)
📄
libgdk_pixbuf-2.0.so.0.tar
(167.5 KB)
📄
libgearman.so.8.0.0.so.8.0.0.tar.gz
(88.21 KB)
📄
libgearman.so.8.0.0.tar
(338.5 KB)
📄
libgearman.so.8.so.8.tar.gz
(88.21 KB)
📄
libgearman.so.8.tar
(338.5 KB)
📄
libgen.h.h.tar.gz
(826 B)
📄
libgen.h.tar
(3 KB)
📄
libgeos.tar
(4 MB)
📄
libgeos.tar.gz
(987.71 KB)
📄
libgeos.zip
(3.99 MB)
📄
libgeos_c.so.1.so.1.tar.gz
(75.93 KB)
📄
libgeos_c.so.1.tar
(242.5 KB)
📄
libgettextlib-0.19.8.1.so.19.8.1.so.tar.gz
(111.34 KB)
📄
libgettextlib-0.19.8.1.so.tar
(312.5 KB)
📄
libgettextpo.so.0.5.4.so.0.5.4.tar.gz
(148.05 KB)
📄
libgettextpo.so.0.5.4.tar
(404 KB)
📄
libgettextpo.so.0.so.0.tar.gz
(148.04 KB)
📄
libgettextpo.so.0.tar
(404 KB)
📄
libgettextpo.so.so.tar.gz
(148.05 KB)
📄
libgettextpo.so.tar
(404 KB)
📄
libgettextsrc-0.19.8.1.so.19.8.1.so.tar.gz
(142.89 KB)
📄
libgettextsrc-0.19.8.1.so.tar
(350.5 KB)
📄
libgfortran.so.5.0.0.so.5.0.0.tar.gz
(844.16 KB)
📄
libgfortran.so.5.0.0.tar
(2.51 MB)
📄
libgfortran.so.5.so.5.tar.gz
(844.16 KB)
📄
libgfortran.so.5.tar
(2.51 MB)
📄
libgif.so.7.0.0.so.7.0.0.tar.gz
(19.12 KB)
📄
libgif.so.7.0.0.tar
(45 KB)
📄
libgif.so.7.so.7.tar.gz
(19.12 KB)
📄
libgif.so.7.tar
(45 KB)
📄
libgio-2.0.so.0.0.so.0.tar.gz
(696.08 KB)
📄
libgio-2.0.so.0.5600.4.0.so.0.5600.4.tar.gz
(696.08 KB)
📄
libgio-2.0.so.0.5600.4.tar
(1.7 MB)
📄
libgio-2.0.so.0.tar
(1.7 MB)
📄
libgirepository-1.0.so.1.0.0.0.so.1.0.0.tar.gz
(97.84 KB)
📄
libgirepository-1.0.so.1.0.0.tar
(239.5 KB)
📄
libgirepository-1.0.so.1.0.so.1.tar.gz
(97.84 KB)
📄
libgirepository-1.0.so.1.tar
(239.5 KB)
📄
libglapi.so.0.0.0.so.0.0.0.tar.gz
(47.95 KB)
📄
libglapi.so.0.0.0.tar
(235.5 KB)
📄
libglapi.so.0.so.0.tar.gz
(47.95 KB)
📄
libglapi.so.0.tar
(235.5 KB)
📄
libglib-2.0.so.0.0.so.0.tar.gz
(473.93 KB)
📄
libglib-2.0.so.0.tar
(1.12 MB)
📄
libglut.so.3.10.0.so.3.10.0.tar.gz
(110.64 KB)
📄
libglut.so.3.10.0.tar
(342 KB)
📄
libglut.so.3.so.3.tar.gz
(110.63 KB)
📄
libglut.so.3.tar
(342 KB)
📄
libgmodule-2.0.so.0.0.so.0.tar.gz
(6.57 KB)
📄
libgmodule-2.0.so.0.tar
(17.5 KB)
📄
libgmp.so.10.3.2.so.10.3.2.tar.gz
(297.11 KB)
📄
libgmp.so.10.3.2.tar
(616.5 KB)
📄
libgmp.so.10.hmac.so.10.hmac.tar.gz
(160 B)
📄
libgmp.so.10.hmac.tar
(2 KB)
📄
libgmp.so.10.so.10.tar.gz
(297.11 KB)
📄
libgmp.so.10.tar
(616.5 KB)
📄
libgnutls.so.30.28.2.so.30.28.2.tar.gz
(899.9 KB)
📄
libgnutls.so.30.28.2.tar
(1.96 MB)
📄
libgnutls.so.30.so.30.tar.gz
(899.89 KB)
📄
libgnutls.so.30.tar
(1.96 MB)
📄
libgobject-2.0.so.0.0.so.0.tar.gz
(145.24 KB)
📄
libgobject-2.0.so.0.tar
(341 KB)
📄
libgomp.a.a.tar.gz
(124.31 KB)
📄
libgomp.a.tar
(782 KB)
📄
libgomp.so.1.0.0.so.1.0.0.tar.gz
(107.24 KB)
📄
libgomp.so.1.0.0.tar
(231.5 KB)
📄
libgomp.so.1.so.1.tar.gz
(107.23 KB)
📄
libgomp.so.1.tar
(231.5 KB)
📄
libgomp.spec.spec.tar.gz
(243 B)
📄
libgomp.spec.tar
(2 KB)
📄
libgov_test.so.1.2.so.1.2.tar.gz
(24.87 KB)
📄
libgov_test.so.1.2.tar
(58 KB)
📄
libgovernor.so.1.2.so.1.2.tar.gz
(24.06 KB)
📄
libgovernor.so.1.2.tar
(63.5 KB)
📄
libgovernor.so.so.tar.gz
(24.05 KB)
📄
libgovernor.so.tar
(63.5 KB)
📄
libgpg-error.so.0.24.2.so.0.24.2.tar.gz
(61.69 KB)
📄
libgpg-error.so.0.24.2.tar
(144.5 KB)
📄
libgpg-error.so.0.so.0.tar.gz
(61.68 KB)
📄
libgpg-error.so.0.tar
(144.5 KB)
📄
libgpg-error.so.so.tar.gz
(61.68 KB)
📄
libgpg-error.so.tar
(144.5 KB)
📄
libgpgme.so.11.22.1.so.11.22.1.tar.gz
(145.05 KB)
📄
libgpgme.so.11.22.1.tar
(328.5 KB)
📄
libgpgme.so.11.so.11.tar.gz
(145.05 KB)
📄
libgpgme.so.11.tar
(328.5 KB)
📄
libgpm.so.2.1.0.so.2.1.0.tar.gz
(12.26 KB)
📄
libgpm.so.2.1.0.tar
(30 KB)
📄
libgpm.so.2.so.2.tar.gz
(12.27 KB)
📄
libgpm.so.2.tar
(30 KB)
📄
libgraphite2.so.3.0.1.so.3.0.1.tar.gz
(93.32 KB)
📄
libgraphite2.so.3.0.1.tar
(199 KB)
📄
libgraphite2.so.3.so.3.tar.gz
(93.32 KB)
📄
libgraphite2.so.3.tar
(199 KB)
📄
libgs.so.9.27.so.9.27.tar.gz
(2.62 MB)
📄
libgs.so.9.27.tar
(15.65 MB)
📄
libgs.so.9.so.9.tar.gz
(2.62 MB)
📄
libgs.so.9.tar
(15.65 MB)
📄
libgsm.so.1.0.17.so.1.0.17.tar.gz
(21.4 KB)
📄
libgsm.so.1.0.17.tar
(57 KB)
📄
libgsm.so.1.so.1.tar.gz
(21.4 KB)
📄
libgsm.so.1.tar
(57 KB)
📄
libgssapi_krb5.so.2.2.so.2.2.tar.gz
(149.78 KB)
📄
libgssapi_krb5.so.2.2.tar
(349.5 KB)
📄
libgssapi_krb5.so.2.so.2.tar.gz
(149.78 KB)
📄
libgssapi_krb5.so.2.tar
(349.5 KB)
📄
libgssapi_krb5.so.so.tar.gz
(149.78 KB)
📄
libgssapi_krb5.so.tar
(349.5 KB)
📄
libgssrpc.so.4.2.so.4.2.tar.gz
(57.38 KB)
📄
libgssrpc.so.4.2.tar
(137.5 KB)
📄
libgssrpc.so.4.so.4.tar.gz
(57.38 KB)
📄
libgssrpc.so.4.tar
(137.5 KB)
📄
libgssrpc.so.so.tar.gz
(57.38 KB)
📄
libgssrpc.so.tar
(137.5 KB)
📄
libgstaccurip.so.so.tar.gz
(6.43 KB)
📄
libgstaccurip.so.tar
(17.5 KB)
📄
libgstadaptivedemux-1.0.so.0.0.so.0.tar.gz
(45.19 KB)
📄
libgstadaptivedemux-1.0.so.0.tar
(106 KB)
📄
libgstadder.so.so.tar.gz
(23.12 KB)
📄
libgstadder.so.tar
(62.5 KB)
📄
libgstaiff.so.so.tar.gz
(25.04 KB)
📄
libgstaiff.so.tar
(58.5 KB)
📄
libgstallocators-1.0.so.0.0.so.0.tar.gz
(7.34 KB)
📄
libgstallocators-1.0.so.0.tar
(22 KB)
📄
libgstalsa.so.so.tar.gz
(37.34 KB)
📄
libgstalsa.so.tar
(98.5 KB)
📄
libgstapp-1.0.so.0.0.so.0.tar.gz
(26.17 KB)
📄
libgstapp-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(26.17 KB)
📄
libgstapp-1.0.so.0.1601.0.tar
(66.5 KB)
📄
libgstapp-1.0.so.0.tar
(66.5 KB)
📄
libgstaudio-1.0.so.0.0.so.0.tar.gz
(200.24 KB)
📄
libgstaudio-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(200.25 KB)
📄
libgstaudio-1.0.so.0.1601.0.tar
(498.5 KB)
📄
libgstaudio-1.0.so.0.tar
(498.5 KB)
📄
libgstaudiobuffersplit.so.so.tar.gz
(12.36 KB)
📄
libgstaudiobuffersplit.so.tar
(33.5 KB)
📄
libgstaudiofxbad.so.so.tar.gz
(5.91 KB)
📄
libgstaudiofxbad.so.tar
(18 KB)
📄
libgstaudiomixer.so.so.tar.gz
(18.48 KB)
📄
libgstaudiomixer.so.tar
(51 KB)
📄
libgstaudioresample.so.so.tar.gz
(14.2 KB)
📄
libgstaudioresample.so.tar
(37.5 KB)
📄
libgstaudiovisualizers.so.so.tar.gz
(16.02 KB)
📄
libgstaudiovisualizers.so.tar
(38.5 KB)
📄
libgstbadaudio-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(27.18 KB)
📄
libgstbadaudio-1.0.so.0.1601.0.tar
(70.5 KB)
📄
libgstbase-1.0.so.0.0.so.0.tar.gz
(204.25 KB)
📄
libgstbase-1.0.so.0.tar
(504 KB)
📄
libgstbayer.so.so.tar.gz
(12.17 KB)
📄
libgstbayer.so.tar
(34.5 KB)
📄
libgstbluez.so.so.tar.gz
(42.72 KB)
📄
libgstbluez.so.tar
(120.5 KB)
📄
libgstcheck-1.0.so.0.0.so.0.tar.gz
(59.28 KB)
📄
libgstcheck-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(59.28 KB)
📄
libgstcheck-1.0.so.0.1601.0.tar
(147.5 KB)
📄
libgstcheck-1.0.so.0.tar
(147.5 KB)
📄
libgstclosedcaption.so.so.tar.gz
(73.07 KB)
📄
libgstclosedcaption.so.tar
(169 KB)
📄
libgstcodecparsers-1.0.so.0.0.so.0.tar.gz
(130.87 KB)
📄
libgstcodecparsers-1.0.so.0.tar
(283 KB)
📄
libgstcompositor.so.so.tar.gz
(28.78 KB)
📄
libgstcompositor.so.tar
(75 KB)
📄
libgstcontroller-1.0.so.0.0.so.0.tar.gz
(28.5 KB)
📄
libgstcontroller-1.0.so.0.tar
(76 KB)
📄
libgstdebugutilsbad.so.so.tar.gz
(32.19 KB)
📄
libgstdebugutilsbad.so.tar
(79.5 KB)
📄
libgstdtls.so.so.tar.gz
(39.54 KB)
📄
libgstdtls.so.tar
(100 KB)
📄
libgstfft-1.0.so.0.0.so.0.tar.gz
(20.14 KB)
📄
libgstfft-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(20.14 KB)
📄
libgstfft-1.0.so.0.1601.0.tar
(46 KB)
📄
libgstfft-1.0.so.0.tar
(46 KB)
📄
libgstfieldanalysis.so.so.tar.gz
(17.72 KB)
📄
libgstfieldanalysis.so.tar
(42.5 KB)
📄
libgstgl-1.0.so.0.0.so.0.tar.gz
(182.24 KB)
📄
libgstgl-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(182.24 KB)
📄
libgstgl-1.0.so.0.1601.0.tar
(451.5 KB)
📄
libgstgl-1.0.so.0.tar
(451.5 KB)
📄
libgstinsertbin-1.0.so.0.0.so.0.tar.gz
(10.24 KB)
📄
libgstinsertbin-1.0.so.0.tar
(25.5 KB)
📄
libgstinter.so.so.tar.gz
(20.06 KB)
📄
libgstinter.so.tar
(55 KB)
📄
libgstisoff-1.0.so.0.0.so.0.tar.gz
(9.02 KB)
📄
libgstisoff-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(9.02 KB)
📄
libgstisoff-1.0.so.0.1601.0.tar
(21 KB)
📄
libgstisoff-1.0.so.0.tar
(21 KB)
📄
libgstivtc.so.so.tar.gz
(11.83 KB)
📄
libgstivtc.so.tar
(26.5 KB)
📄
libgstjp2kdecimator.so.so.tar.gz
(18.54 KB)
📄
libgstjp2kdecimator.so.tar
(42 KB)
📄
libgstjpegformat.so.so.tar.gz
(16.87 KB)
📄
libgstjpegformat.so.tar
(42 KB)
📄
libgstmidi.so.so.tar.gz
(15.49 KB)
📄
libgstmidi.so.tar
(38 KB)
📄
libgstmpegts-1.0.so.0.0.so.0.tar.gz
(62.09 KB)
📄
libgstmpegts-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(62.1 KB)
📄
libgstmpegts-1.0.so.0.1601.0.tar
(175 KB)
📄
libgstmpegts-1.0.so.0.tar
(175 KB)
📄
libgstnet-1.0.so.0.0.so.0.tar.gz
(42.35 KB)
📄
libgstnet-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(42.35 KB)
📄
libgstnet-1.0.so.0.1601.0.tar
(104 KB)
📄
libgstnet-1.0.so.0.tar
(104 KB)
📄
libgstopus.so.so.tar.gz
(26.67 KB)
📄
libgstopus.so.tar
(66.5 KB)
📄
libgstpango.so.so.tar.gz
(36.35 KB)
📄
libgstpango.so.tar
(95 KB)
📄
libgstpbtypes.so.so.tar.gz
(3.17 KB)
📄
libgstpbtypes.so.tar
(9 KB)
📄
libgstpbutils-1.0.so.0.0.so.0.tar.gz
(94.01 KB)
📄
libgstpbutils-1.0.so.0.tar
(247.5 KB)
📄
libgstphotography-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(10.57 KB)
📄
libgstphotography-1.0.so.0.1601.0.tar
(37.5 KB)
📄
libgstplayer-1.0.so.0.0.so.0.tar.gz
(46.37 KB)
📄
libgstplayer-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(46.38 KB)
📄
libgstplayer-1.0.so.0.1601.0.tar
(123.5 KB)
📄
libgstplayer-1.0.so.0.tar
(123.5 KB)
📄
libgstproxy.so.so.tar.gz
(8.56 KB)
📄
libgstproxy.so.tar
(26 KB)
📄
libgstreamer-1.0.so.0.0.so.0.tar.gz
(545.05 KB)
📄
libgstreamer-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(545.05 KB)
📄
libgstreamer-1.0.so.0.1601.0.tar
(1.29 MB)
📄
libgstreamer-1.0.so.0.tar
(1.29 MB)
📄
libgstremovesilence.so.so.tar.gz
(8.34 KB)
📄
libgstremovesilence.so.tar
(22 KB)
📄
libgstriff-1.0.so.0.0.so.0.tar.gz
(26.14 KB)
📄
libgstriff-1.0.so.0.tar
(62 KB)
📄
libgstrsvg.so.so.tar.gz
(11.83 KB)
📄
libgstrsvg.so.tar
(30.5 KB)
📄
libgstrtp-1.0.so.0.0.so.0.tar.gz
(56.57 KB)
📄
libgstrtp-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(56.58 KB)
📄
libgstrtp-1.0.so.0.1601.0.tar
(150.5 KB)
📄
libgstrtp-1.0.so.0.tar
(150.5 KB)
📄
libgstrtsp-1.0.so.0.0.so.0.tar.gz
(59.17 KB)
📄
libgstrtsp-1.0.so.0.tar
(150.5 KB)
📄
libgstsctp-1.0.so.0.0.so.0.tar.gz
(3.84 KB)
📄
libgstsctp-1.0.so.0.tar
(13.5 KB)
📄
libgstsdp-1.0.so.0.0.so.0.tar.gz
(37.16 KB)
📄
libgstsdp-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(37.16 KB)
📄
libgstsdp-1.0.so.0.1601.0.tar
(98 KB)
📄
libgstsdp-1.0.so.0.tar
(98 KB)
📄
libgstsdpelem.so.so.tar.gz
(17.4 KB)
📄
libgstsdpelem.so.tar
(46.5 KB)
📄
libgstsndfile.so.so.tar.gz
(14.6 KB)
📄
libgstsndfile.so.tar
(38 KB)
📄
libgstsoundtouch.so.so.tar.gz
(14.9 KB)
📄
libgstsoundtouch.so.tar
(38.5 KB)
📄
libgstspeed.so.so.tar.gz
(8.92 KB)
📄
libgstspeed.so.tar
(25.5 KB)
📄
libgstsrtp.so.so.tar.gz
(25.85 KB)
📄
libgstsrtp.so.tar
(67 KB)
📄
libgsttag-1.0.so.0.0.so.0.tar.gz
(103.33 KB)
📄
libgsttag-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(103.34 KB)
📄
libgsttag-1.0.so.0.1601.0.tar
(248 KB)
📄
libgsttag-1.0.so.0.tar
(248 KB)
📄
libgsturidownloader-1.0.so.0.0.so.0.tar.gz
(12.56 KB)
📄
libgsturidownloader-1.0.so.0.tar
(33.5 KB)
📄
libgstuvch264.so.so.tar.gz
(36.4 KB)
📄
libgstuvch264.so.tar
(91 KB)
📄
libgstvideo-1.0.so.0.0.so.0.tar.gz
(262.54 KB)
📄
libgstvideo-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(262.54 KB)
📄
libgstvideo-1.0.so.0.1601.0.tar
(705 KB)
📄
libgstvideo-1.0.so.0.tar
(705 KB)
📄
libgstvideoscale.so.so.tar.gz
(14.63 KB)
📄
libgstvideoscale.so.tar
(37.5 KB)
📄
libgstvmnc.so.so.tar.gz
(11.93 KB)
📄
libgstvmnc.so.tar
(29.5 KB)
📄
libgstwayland-1.0.so.0.0.so.0.tar.gz
(4.21 KB)
📄
libgstwayland-1.0.so.0.tar
(13 KB)
📄
libgstwebp.so.so.tar.gz
(11.07 KB)
📄
libgstwebp.so.tar
(30.5 KB)
📄
libgstwebrtc-1.0.so.0.0.so.0.tar.gz
(12.97 KB)
📄
libgstwebrtc-1.0.so.0.1601.0.0.so.0.1601.0.tar.gz
(12.97 KB)
📄
libgstwebrtc-1.0.so.0.1601.0.tar
(42 KB)
📄
libgstwebrtc-1.0.so.0.tar
(42 KB)
📄
libgstximagesink.so.so.tar.gz
(26.55 KB)
📄
libgstximagesink.so.tar
(66.5 KB)
📄
libgstyadif.so.so.tar.gz
(7.44 KB)
📄
libgstyadif.so.tar
(22 KB)
📄
libgthread-2.0.so.0.0.so.0.tar.gz
(2.96 KB)
📄
libgthread-2.0.so.0.tar
(9 KB)
📄
libgtk-x11-2.0.so.0.0.so.0.tar.gz
(2.01 MB)
📄
libgtk-x11-2.0.so.0.2400.32.0.so.0.2400.32.tar.gz
(2.01 MB)
📄
libgtk-x11-2.0.so.0.2400.32.tar
(4.68 MB)
📄
libgtk-x11-2.0.so.0.tar
(4.68 MB)
📄
libgudev-1.0.so.0.0.so.0.tar.gz
(14.34 KB)
📄
libgudev-1.0.so.0.2.0.0.so.0.2.0.tar.gz
(14.34 KB)
📄
libgudev-1.0.so.0.2.0.tar
(47 KB)
📄
libgudev-1.0.so.0.tar
(47 KB)
📄
libguestStoreClient.so.0.0.0.so.0.0.0.tar.gz
(102.87 KB)
📄
libguestStoreClient.so.0.0.0.tar
(324.5 KB)
📄
libguestStoreClient.so.0.so.0.tar.gz
(102.86 KB)
📄
libguestStoreClient.so.0.tar
(324.5 KB)
📄
libguestlib.so.0.0.0.so.0.0.0.tar.gz
(126.21 KB)
📄
libguestlib.so.0.0.0.tar
(382 KB)
📄
libguestlib.so.0.so.0.tar.gz
(126.21 KB)
📄
libguestlib.so.0.tar
(382 KB)
📄
libguile-2.0.so.22.0.so.22.tar.gz
(582.77 KB)
📄
libguile-2.0.so.22.8.1.0.so.22.8.1.tar.gz
(582.77 KB)
📄
libguile-2.0.so.22.8.1.tar
(1.62 MB)
📄
libguile-2.0.so.22.tar
(1.62 MB)
📄
libguilereadline-v-18.so.18.so.18.tar.gz
(23.15 KB)
📄
libguilereadline-v-18.so.18.tar
(60 KB)
📄
libguilereadline-v-18.so.so.tar.gz
(23.15 KB)
📄
libguilereadline-v-18.so.tar
(60 KB)
📄
libgvc.so.6.0.0.so.6.0.0.tar.gz
(281.25 KB)
📄
libgvc.so.6.0.0.tar
(658 KB)
📄
libgvc.so.6.so.6.tar.gz
(281.25 KB)
📄
libgvc.so.6.tar
(658 KB)
📄
libgvplugin_core.so.6.so.6.tar.gz
(55.88 KB)
📄
libgvplugin_core.so.6.tar
(145.5 KB)
📄
libgvplugin_dot_layout.so.6.so.6.tar.gz
(79.56 KB)
📄
libgvplugin_dot_layout.so.6.tar
(164.5 KB)
📄
libgvplugin_gdk.so.6.0.0.so.6.0.0.tar.gz
(4.45 KB)
📄
libgvplugin_gdk.so.6.0.0.tar
(14.5 KB)
📄
libgvplugin_gs.so.6.so.6.tar.gz
(5.27 KB)
📄
libgvplugin_gs.so.6.tar
(17.5 KB)
📄
libgvplugin_gtk.so.6.0.0.so.6.0.0.tar.gz
(12.95 KB)
📄
libgvplugin_gtk.so.6.0.0.tar
(38.5 KB)
📄
libgvplugin_gtk.so.6.so.6.tar.gz
(12.94 KB)
📄
libgvplugin_gtk.so.6.tar
(38.5 KB)
📄
libgvplugin_rsvg.so.6.so.6.tar.gz
(4.45 KB)
📄
libgvplugin_rsvg.so.6.tar
(13.5 KB)
📄
libgvplugin_xlib.so.6.so.6.tar.gz
(7.5 KB)
📄
libgvplugin_xlib.so.6.tar
(21.5 KB)
📄
libgvpr.so.2.0.0.so.2.0.0.tar.gz
(204.31 KB)
📄
libgvpr.so.2.0.0.tar
(502 KB)
📄
libgvpr.so.2.so.2.tar.gz
(204.31 KB)
📄
libgvpr.so.2.tar
(502 KB)
📄
libhandle.so.1.0.3.so.1.0.3.tar.gz
(6.12 KB)
📄
libhandle.so.1.0.3.tar
(18 KB)
📄
libhandle.so.1.so.1.tar.gz
(6.12 KB)
📄
libhandle.so.1.tar
(18 KB)
📄
libharfbuzz.so.0.10705.0.so.0.10705.0.tar.gz
(305.29 KB)
📄
libharfbuzz.so.0.10705.0.tar
(666.5 KB)
📄
libharfbuzz.so.0.so.0.tar.gz
(305.28 KB)
📄
libharfbuzz.so.0.tar
(666.5 KB)
📄
libharu.tar
(1.68 MB)
📄
libharu.tar.gz
(706.76 KB)
📄
libharu.zip
(1.67 MB)
📄
libhashkit.so.2.0.0.so.2.0.0.tar.gz
(23.37 KB)
📄
libhashkit.so.2.0.0.tar
(42.5 KB)
📄
libhashkit.so.2.so.2.tar.gz
(23.37 KB)
📄
libhashkit.so.2.tar
(42.5 KB)
📄
libhdf5.so.103.1.0.so.103.1.0.tar.gz
(1.43 MB)
📄
libhdf5.so.103.1.0.tar
(3.57 MB)
📄
libhdf5.so.103.so.103.tar.gz
(1.43 MB)
📄
libhdf5.so.103.tar
(3.57 MB)
📄
libhdf5_cpp.so.103.1.0.so.103.1.0.tar.gz
(157.61 KB)
📄
libhdf5_cpp.so.103.1.0.tar
(513.5 KB)
📄
libhdf5_cpp.so.103.so.103.tar.gz
(157.61 KB)
📄
libhdf5_cpp.so.103.tar
(513.5 KB)
📄
libhdf5_fortran.so.102.so.102.tar.gz
(94.38 KB)
📄
libhdf5_fortran.so.102.tar
(325 KB)
📄
libhdf5_hl.so.100.1.2.so.100.1.2.tar.gz
(60.1 KB)
📄
libhdf5_hl.so.100.1.2.tar
(143.5 KB)
📄
libhdf5_hl.so.100.so.100.tar.gz
(60.1 KB)
📄
libhdf5_hl.so.100.tar
(143.5 KB)
📄
libhdf5_hl_cpp.so.100.1.3.so.100.1.3.tar.gz
(5.77 KB)
📄
libhdf5_hl_cpp.so.100.1.3.tar
(17.5 KB)
📄
libhdf5_hl_cpp.so.100.so.100.tar.gz
(5.76 KB)
📄
libhdf5_hl_cpp.so.100.tar
(17.5 KB)
📄
libhdf5hl_fortran.so.100.0.4.so.100.0.4.tar.gz
(30.92 KB)
📄
libhdf5hl_fortran.so.100.0.4.tar
(126.5 KB)
📄
libhdf5hl_fortran.so.100.so.100.tar.gz
(30.91 KB)
📄
libhdf5hl_fortran.so.100.tar
(126.5 KB)
📄
libheif.tar
(2.59 MB)
📄
libheif.tar.gz
(1.04 MB)
📄
libheif.zip
(2.58 MB)
📄
libhgfs.so.0.0.0.so.0.0.0.tar.gz
(78.55 KB)
📄
libhgfs.so.0.0.0.tar
(180.5 KB)
📄
libhgfs.so.0.so.0.tar.gz
(78.55 KB)
📄
libhgfs.so.0.tar
(180.5 KB)
📄
libhiredis.so.0.13.so.0.13.tar.gz
(27.28 KB)
📄
libhiredis.so.0.13.tar
(75.5 KB)
📄
libhiredis.so.0.so.0.tar.gz
(27.28 KB)
📄
libhiredis.so.0.tar
(75.5 KB)
📄
libhistory.so.7.0.so.7.0.tar.gz
(21.03 KB)
📄
libhistory.so.7.0.tar
(49 KB)
📄
libhistory.so.7.so.7.tar.gz
(21.03 KB)
📄
libhistory.so.7.tar
(49 KB)
📄
libhns-rdmav34.so.so.tar.gz
(24.43 KB)
📄
libhns-rdmav34.so.tar
(51 KB)
📄
libhogweed.so.4.5.so.4.5.tar.gz
(117.5 KB)
📄
libhogweed.so.4.5.tar
(195 KB)
📄
libhogweed.so.4.so.4.tar.gz
(117.5 KB)
📄
libhogweed.so.4.tar
(195 KB)
📄
libhunspell-1.6.so.0.0.1.6.so.0.0.1.tar.gz
(265.05 KB)
📄
libhunspell-1.6.so.0.0.1.tar
(609 KB)
📄
libhunspell-1.6.so.0.6.so.0.tar.gz
(265.04 KB)
📄
libhunspell-1.6.so.0.tar
(609 KB)
📄
libhwy.so.1.0.2.so.1.0.2.tar.gz
(18.98 KB)
📄
libhwy.so.1.0.2.tar
(39.5 KB)
📄
libhwy.so.1.so.1.tar.gz
(18.98 KB)
📄
libhwy.so.1.tar
(39.5 KB)
📄
libhwy_contrib.so.1.so.1.tar.gz
(756.74 KB)
📄
libhwy_contrib.so.1.tar
(1.61 MB)
📄
libhwy_test.so.1.0.2.so.1.0.2.tar.gz
(4.15 KB)
📄
libhwy_test.so.1.0.2.tar
(13.5 KB)
📄
libhwy_test.so.1.so.1.tar.gz
(4.15 KB)
📄
libhwy_test.so.1.tar
(13.5 KB)
📄
libib_util.so.so.tar.gz
(2.66 KB)
📄
libib_util.so.tar
(9 KB)
📄
libibverbs.so.1.so.1.tar.gz
(59.53 KB)
📄
libibverbs.so.1.tar
(134 KB)
📄
libicu.tar
(37.71 MB)
📄
libicu.tar.gz
(13.85 MB)
📄
libicu.zip
(37.46 MB)
📄
libicu57.tar
(29.95 MB)
📄
libicu57.tar.gz
(11.84 MB)
📄
libicu57.zip
(29.94 MB)
📄
libicu65.tar
(37.81 MB)
📄
libicu65.tar.gz
(14 MB)
📄
libicu65.zip
(37.56 MB)
📄
libicudata.so.60.3.so.60.3.tar.gz
(10.34 MB)
📄
libicudata.so.60.3.tar
(25.66 MB)
📄
libicudata.so.60.so.60.tar.gz
(10.34 MB)
📄
libicudata.so.60.tar
(25.66 MB)
📄
libicui18n.so.60.3.so.60.3.tar.gz
(1.12 MB)
📄
libicui18n.so.60.3.tar
(3.61 MB)
📄
libicui18n.so.60.so.60.tar.gz
(1.12 MB)
📄
libicui18n.so.60.tar
(3.61 MB)
📄
libicuio.so.60.3.so.60.3.tar.gz
(26 KB)
📄
libicuio.so.60.3.tar
(92 KB)
📄
libicuio.so.60.so.60.tar.gz
(26 KB)
📄
libicuio.so.60.tar
(92 KB)
📄
libicutest.so.60.3.so.60.3.tar.gz
(29.66 KB)
📄
libicutest.so.60.3.tar
(90 KB)
📄
libicutest.so.60.so.60.tar.gz
(29.66 KB)
📄
libicutest.so.60.tar
(90 KB)
📄
libicutu.so.60.3.so.60.3.tar.gz
(92.62 KB)
📄
libicutu.so.60.3.tar
(280 KB)
📄
libicutu.so.60.so.60.tar.gz
(92.62 KB)
📄
libicutu.so.60.tar
(280 KB)
📄
libicuuc.so.60.3.so.60.3.tar.gz
(766.75 KB)
📄
libicuuc.so.60.3.tar
(2.34 MB)
📄
libicuuc.so.60.so.60.tar.gz
(766.74 KB)
📄
libicuuc.so.60.tar
(2.34 MB)
📄
libidn.pc.pc.tar.gz
(613 B)
📄
libidn.pc.tar
(2.5 KB)
📄
libidn.so.11.6.18.so.11.6.18.tar.gz
(67.42 KB)
📄
libidn.so.11.6.18.tar
(220 KB)
📄
libidn.so.11.so.11.tar.gz
(67.42 KB)
📄
libidn.so.11.tar
(220 KB)
📄
libidn.so.so.tar.gz
(67.42 KB)
📄
libidn.so.tar
(220 KB)
📄
libidn2.so.0.3.6.so.0.3.6.tar.gz
(63.97 KB)
📄
libidn2.so.0.3.6.tar
(130 KB)
📄
libidn2.so.0.so.0.tar.gz
(63.96 KB)
📄
libidn2.so.0.tar
(130 KB)
📄
libifp_iface.so.so.tar.gz
(26.67 KB)
📄
libifp_iface.so.tar
(98 KB)
📄
libifp_iface_sync.so.so.tar.gz
(18.02 KB)
📄
libifp_iface_sync.so.tar
(62 KB)
📄
libijs-0.35.so.35.so.tar.gz
(10.07 KB)
📄
libijs-0.35.so.tar
(27.5 KB)
📄
libimaevm.so.2.0.0.so.2.0.0.tar.gz
(11.38 KB)
📄
libimaevm.so.2.0.0.tar
(29.5 KB)
📄
libimaevm.so.2.so.2.tar.gz
(11.38 KB)
📄
libimaevm.so.2.tar
(29.5 KB)
📄
libimagequant.so.0.so.0.tar.gz
(34.25 KB)
📄
libimagequant.so.0.tar
(67 KB)
📄
libini_config.so.5.2.1.so.5.2.1.tar.gz
(47.75 KB)
📄
libini_config.so.5.2.1.tar
(111 KB)
📄
libini_config.so.5.so.5.tar.gz
(47.74 KB)
📄
libini_config.so.5.tar
(111 KB)
📄
libinotifytools.so.0.4.1.so.0.4.1.tar.gz
(16.85 KB)
📄
libinotifytools.so.0.4.1.tar
(38.5 KB)
📄
libinotifytools.so.0.so.0.tar.gz
(16.85 KB)
📄
libinotifytools.so.0.tar
(38.5 KB)
📄
libinput-device-group.tar
(35 KB)
📄
libinput-device-group.tar.gz
(5.46 KB)
📄
libinput-fuzz-extract.tar
(44 KB)
📄
libinput-fuzz-extract.tar.gz
(8.58 KB)
📄
libinput-fuzz-to-zero.tar
(26 KB)
📄
libinput-fuzz-to-zero.tar.gz
(3.93 KB)
📄
libinput.so.10.13.0.so.10.13.0.tar.gz
(140.81 KB)
📄
libinput.so.10.13.0.tar
(322.5 KB)
📄
libinput.so.10.so.10.tar.gz
(140.8 KB)
📄
libinput.so.10.tar
(322.5 KB)
📄
libintl.h.h.tar.gz
(1.59 KB)
📄
libintl.h.tar
(6 KB)
📄
libip4tc.so.2.0.0.so.2.0.0.tar.gz
(14.79 KB)
📄
libip4tc.so.2.0.0.tar
(34.5 KB)
📄
libip4tc.so.2.so.2.tar.gz
(14.79 KB)
📄
libip4tc.so.2.tar
(34.5 KB)
📄
libip6t_HL.so.so.tar.gz
(3.57 KB)
📄
libip6t_HL.so.tar
(13.5 KB)
📄
libip6t_LOG.so.so.tar.gz
(4.76 KB)
📄
libip6t_LOG.so.tar
(13.5 KB)
📄
libip6t_NETMAP.so.so.tar.gz
(3.56 KB)
📄
libip6t_NETMAP.so.tar
(13.5 KB)
📄
libip6t_REDIRECT.so.so.tar.gz
(4.12 KB)
📄
libip6t_REDIRECT.so.tar
(13.5 KB)
📄
libip6t_REJECT.so.so.tar.gz
(4.22 KB)
📄
libip6t_REJECT.so.tar
(13.5 KB)
📄
libip6t_ah.so.so.tar.gz
(4.07 KB)
📄
libip6t_ah.so.tar
(13.5 KB)
📄
libip6t_dst.so.so.tar.gz
(4.46 KB)
📄
libip6t_dst.so.tar
(13.5 KB)
📄
libip6t_eui64.so.so.tar.gz
(2.75 KB)
📄
libip6t_eui64.so.tar
(9.5 KB)
📄
libip6t_hbh.so.so.tar.gz
(4.64 KB)
📄
libip6t_hbh.so.tar
(13.5 KB)
📄
libip6t_hl.so.so.tar.gz
(3.67 KB)
📄
libip6t_hl.so.tar
(13.5 KB)
📄
libip6t_icmp6.so.so.tar.gz
(5.51 KB)
📄
libip6t_icmp6.so.tar
(17.5 KB)
📄
libip6t_mh.so.so.tar.gz
(4.91 KB)
📄
libip6t_mh.so.tar
(13.5 KB)
📄
libip6t_rt.so.so.tar.gz
(5.23 KB)
📄
libip6t_rt.so.tar
(13.5 KB)
📄
libip6t_srh.so.so.tar.gz
(5.64 KB)
📄
libip6t_srh.so.tar
(18 KB)
📄
libip6tc.so.2.0.0.so.2.0.0.tar.gz
(15.13 KB)
📄
libip6tc.so.2.0.0.tar
(34.5 KB)
📄
libip6tc.so.2.so.2.tar.gz
(15.13 KB)
📄
libip6tc.so.2.tar
(34.5 KB)
📄
libipset.so.13.1.0.so.13.1.0.tar.gz
(55.2 KB)
📄
libipset.so.13.1.0.tar
(198.5 KB)
📄
libipset.so.13.so.13.tar.gz
(55.19 KB)
📄
libipset.so.13.tar
(198.5 KB)
📄
libipt.so.1.6.1.so.1.6.1.tar.gz
(42.94 KB)
📄
libipt.so.1.6.1.tar
(161 KB)
📄
libipt.so.1.so.1.tar.gz
(42.94 KB)
📄
libipt.so.1.tar
(161 KB)
📄
libipt_CLUSTERIP.so.so.tar.gz
(4.16 KB)
📄
libipt_CLUSTERIP.so.tar
(13.5 KB)
📄
libipt_DNAT.so.so.tar.gz
(6.5 KB)
📄
libipt_DNAT.so.tar
(18 KB)
📄
libipt_ECN.so.so.tar.gz
(3.7 KB)
📄
libipt_ECN.so.tar
(13.5 KB)
📄
libipt_LOG.so.so.tar.gz
(4.77 KB)
📄
libipt_LOG.so.tar
(13.5 KB)
📄
libipt_MASQUERADE.so.so.tar.gz
(4.15 KB)
📄
libipt_MASQUERADE.so.tar
(13.5 KB)
📄
libipt_NETMAP.so.so.tar.gz
(3.49 KB)
📄
libipt_NETMAP.so.tar
(9.5 KB)
📄
libipt_REJECT.so.so.tar.gz
(4.47 KB)
📄
libipt_REJECT.so.tar
(13.5 KB)
📄
libipt_SNAT.so.so.tar.gz
(5.43 KB)
📄
libipt_SNAT.so.tar
(13.5 KB)
📄
libipt_TTL.so.so.tar.gz
(3.58 KB)
📄
libipt_TTL.so.tar
(13.5 KB)
📄
libipt_ULOG.so.so.tar.gz
(3.9 KB)
📄
libipt_ULOG.so.tar
(13.5 KB)
📄
libipt_ah.so.so.tar.gz
(3.79 KB)
📄
libipt_ah.so.tar
(13.5 KB)
📄
libipt_icmp.so.so.tar.gz
(5.64 KB)
📄
libipt_icmp.so.tar
(17.5 KB)
📄
libipt_ttl.so.so.tar.gz
(3.79 KB)
📄
libipt_ttl.so.tar
(13.5 KB)
📄
libirdma-rdmav34.so.so.tar.gz
(20.24 KB)
📄
libirdma-rdmav34.so.tar
(43 KB)
📄
libirs-export.so.161.so.161.tar.gz
(19.12 KB)
📄
libirs-export.so.161.tar
(50 KB)
📄
libirs.so.161.0.1.so.161.0.1.tar.gz
(19.83 KB)
📄
libirs.so.161.0.1.tar
(50 KB)
📄
libirs.so.161.so.161.tar.gz
(19.82 KB)
📄
libirs.so.161.tar
(50 KB)
📄
libirs.so.so.tar.gz
(19.82 KB)
📄
libirs.so.tar
(50 KB)
📄
libisc.so.1107.0.7.so.1107.0.7.tar.gz
(231.77 KB)
📄
libisc.so.1107.0.7.tar
(544.5 KB)
📄
libisc.so.1107.so.1107.tar.gz
(231.77 KB)
📄
libisc.so.1107.tar
(544.5 KB)
📄
libisc.so.so.tar.gz
(231.76 KB)
📄
libisc.so.tar
(544.5 KB)
📄
libisccc.so.161.0.1.so.161.0.1.tar.gz
(18.9 KB)
📄
libisccc.so.161.0.1.tar
(47 KB)
📄
libisccc.so.161.so.161.tar.gz
(18.89 KB)
📄
libisccc.so.161.tar
(47 KB)
📄
libisccc.so.so.tar.gz
(18.9 KB)
📄
libisccc.so.tar
(47 KB)
📄
libisccfg-export.so.163.so.163.tar.gz
(57.48 KB)
📄
libisccfg-export.so.163.tar
(184.5 KB)
📄
libisccfg.so.163.0.8.so.163.0.8.tar.gz
(59.9 KB)
📄
libisccfg.so.163.0.8.tar
(193 KB)
📄
libisccfg.so.163.so.163.tar.gz
(59.9 KB)
📄
libisccfg.so.163.tar
(193 KB)
📄
libisccfg.so.so.tar.gz
(59.9 KB)
📄
libisccfg.so.tar
(193 KB)
📄
libisl.so.13.1.0.so.13.1.0.tar.gz
(590.87 KB)
📄
libisl.so.13.1.0.tar
(1.41 MB)
📄
libisl.so.13.so.13.tar.gz
(590.86 KB)
📄
libisl.so.13.tar
(1.41 MB)
📄
libisl.so.15.1.1.so.15.1.1.tar.gz
(700.46 KB)
📄
libisl.so.15.1.1.tar
(1.7 MB)
📄
libisl.so.15.so.15.tar.gz
(700.46 KB)
📄
libisl.so.15.tar
(1.7 MB)
📄
libitm.spec.spec.tar.gz
(244 B)
📄
libitm.spec.tar
(2 KB)
📄
libjansson.so.4.14.0.so.4.14.0.tar.gz
(28.37 KB)
📄
libjansson.so.4.14.0.tar
(59.5 KB)
📄
libjansson.so.4.so.4.tar.gz
(28.37 KB)
📄
libjansson.so.4.tar
(59.5 KB)
📄
libjasper.so.4.0.0.so.4.0.0.tar.gz
(166.91 KB)
📄
libjasper.so.4.0.0.tar
(359.5 KB)
📄
libjasper.so.4.so.4.tar.gz
(166.9 KB)
📄
libjasper.so.4.tar
(359.5 KB)
📄
libjasper.so.so.tar.gz
(166.91 KB)
📄
libjasper.so.tar
(359.5 KB)
📄
libjbig.so.2.1.so.2.1.tar.gz
(23.29 KB)
📄
libjbig.so.2.1.tar
(53 KB)
📄
libjbig2dec.so.0.0.0.so.0.0.0.tar.gz
(51.49 KB)
📄
libjbig2dec.so.0.0.0.tar
(118.5 KB)
📄
libjbig2dec.so.0.so.0.tar.gz
(51.49 KB)
📄
libjbig2dec.so.0.tar
(118.5 KB)
📄
libjbig85.so.2.1.so.2.1.tar.gz
(10.15 KB)
📄
libjbig85.so.2.1.tar
(22 KB)
📄
libjemalloc.so.2.so.2.tar.gz
(217.4 KB)
📄
libjemalloc.so.2.tar
(563 KB)
📄
libjemalloc.so.so.tar.gz
(217.4 KB)
📄
libjemalloc.so.tar
(563 KB)
📄
libjpeg.pc.pc.tar.gz
(264 B)
📄
libjpeg.pc.tar
(2 KB)
📄
libjpeg.so.62.2.0.so.62.2.0.tar.gz
(126.79 KB)
📄
libjpeg.so.62.2.0.tar
(425.5 KB)
📄
libjpeg.so.62.so.62.tar.gz
(126.79 KB)
📄
libjpeg.so.62.tar
(425.5 KB)
📄
libjpeg.so.so.tar.gz
(126.79 KB)
📄
libjpeg.so.tar
(425.5 KB)
📄
libjq.so.1.0.4.so.1.0.4.tar.gz
(165.07 KB)
📄
libjq.so.1.0.4.tar
(368 KB)
📄
libjq.so.1.so.1.tar.gz
(165.06 KB)
📄
libjq.so.1.tar
(368 KB)
📄
libjson-c.so.4.0.0.so.4.0.0.tar.gz
(28.97 KB)
📄
libjson-c.so.4.0.0.tar
(67 KB)
📄
libjson-c.so.4.so.4.tar.gz
(28.96 KB)
📄
libjson-c.so.4.tar
(67 KB)
📄
libjson-c.so.so.tar.gz
(28.96 KB)
📄
libjson-c.so.tar
(67 KB)
📄
libjxl.so.0.7.2.so.0.7.2.tar.gz
(1.44 MB)
📄
libjxl.so.0.7.2.tar
(3.66 MB)
📄
libjxl.so.0.7.so.0.7.tar.gz
(1.44 MB)
📄
libjxl.so.0.7.tar
(3.66 MB)
📄
libjxl_threads.so.0.7.so.0.7.tar.gz
(8.97 KB)
📄
libjxl_threads.so.0.7.tar
(22.5 KB)
📄
libk5crypto.so.3.1.so.3.1.tar.gz
(38.46 KB)
📄
libk5crypto.so.3.1.tar
(96 KB)
📄
libk5crypto.so.3.so.3.tar.gz
(38.46 KB)
📄
libk5crypto.so.3.tar
(96 KB)
📄
libk5crypto.so.so.tar.gz
(38.46 KB)
📄
libk5crypto.so.tar
(96 KB)
📄
libkadm5clnt.so.so.tar.gz
(36.31 KB)
📄
libkadm5clnt.so.tar
(99 KB)
📄
libkadm5clnt_mit.so.12.0.so.12.0.tar.gz
(36.31 KB)
📄
libkadm5clnt_mit.so.12.0.tar
(99 KB)
📄
libkadm5clnt_mit.so.12.so.12.tar.gz
(36.31 KB)
📄
libkadm5clnt_mit.so.12.tar
(99 KB)
📄
libkadm5clnt_mit.so.so.tar.gz
(36.31 KB)
📄
libkadm5clnt_mit.so.tar
(99 KB)
📄
libkadm5srv.so.so.tar.gz
(49.78 KB)
📄
libkadm5srv.so.tar
(123.5 KB)
📄
libkadm5srv_mit.so.12.0.so.12.0.tar.gz
(49.78 KB)
📄
libkadm5srv_mit.so.12.0.tar
(123.5 KB)
📄
libkadm5srv_mit.so.12.so.12.tar.gz
(49.78 KB)
📄
libkadm5srv_mit.so.12.tar
(123.5 KB)
📄
libkadm5srv_mit.so.so.tar.gz
(49.78 KB)
📄
libkadm5srv_mit.so.tar
(123.5 KB)
📄
libkcapi.so.1.4.0.so.1.4.0.tar.gz
(26.02 KB)
📄
libkcapi.so.1.4.0.tar
(64 KB)
📄
libkcapi.so.1.hmac.so.1.hmac.tar.gz
(161 B)
📄
libkcapi.so.1.hmac.tar
(2 KB)
📄
libkcapi.so.1.so.1.tar.gz
(26.02 KB)
📄
libkcapi.so.1.tar
(64 KB)
📄
libkdb5.so.10.0.so.10.0.tar.gz
(35.77 KB)
📄
libkdb5.so.10.0.tar
(87 KB)
📄
libkdb5.so.10.so.10.tar.gz
(35.77 KB)
📄
libkdb5.so.10.tar
(87 KB)
📄
libkdb5.so.so.tar.gz
(35.77 KB)
📄
libkdb5.so.tar
(87 KB)
📄
libkeyutils.so.1.6.so.1.6.tar.gz
(7.28 KB)
📄
libkeyutils.so.1.6.tar
(17.5 KB)
📄
libkeyutils.so.1.so.1.tar.gz
(7.27 KB)
📄
libkeyutils.so.1.tar
(17.5 KB)
📄
libkeyutils.so.so.tar.gz
(7.28 KB)
📄
libkeyutils.so.tar
(17.5 KB)
📄
libkmod.so.2.3.3.so.2.3.3.tar.gz
(47.04 KB)
📄
libkmod.so.2.3.3.tar
(99.5 KB)
📄
libkmod.so.2.so.2.tar.gz
(47.04 KB)
📄
libkmod.so.2.tar
(99.5 KB)
📄
libkrad.so.0.0.so.0.0.tar.gz
(16.46 KB)
📄
libkrad.so.0.0.tar
(46.5 KB)
📄
libkrad.so.0.so.0.tar.gz
(16.46 KB)
📄
libkrad.so.0.tar
(46.5 KB)
📄
libkrad.so.so.tar.gz
(16.46 KB)
📄
libkrad.so.tar
(46.5 KB)
📄
libkrb5.so.3.3.so.3.3.tar.gz
(374.46 KB)
📄
libkrb5.so.3.3.tar
(954.5 KB)
📄
libkrb5.so.3.so.3.tar.gz
(374.46 KB)
📄
libkrb5.so.3.tar
(954.5 KB)
📄
libkrb5.so.so.tar.gz
(374.45 KB)
📄
libkrb5.so.tar
(954.5 KB)
📄
libkrb5.tar
(22 KB)
📄
libkrb5.tar.gz
(7.8 KB)
📄
libkrb5.zip
(20.21 KB)
📄
libkrb5support.so.0.1.so.0.1.tar.gz
(28.68 KB)
📄
libkrb5support.so.0.1.tar
(71.5 KB)
📄
libkrb5support.so.0.so.0.tar.gz
(28.68 KB)
📄
libkrb5support.so.0.tar
(71.5 KB)
📄
libkrb5support.so.so.tar.gz
(28.68 KB)
📄
libkrb5support.so.tar
(71.5 KB)
📄
libksba.so.8.11.6.so.8.11.6.tar.gz
(103.79 KB)
📄
libksba.so.8.11.6.tar
(233.5 KB)
📄
libksba.so.8.so.8.tar.gz
(103.78 KB)
📄
libksba.so.8.tar
(233.5 KB)
📄
liblab_gamut.so.1.0.0.so.1.0.0.tar.gz
(1.75 MB)
📄
liblab_gamut.so.1.0.0.tar
(2.38 MB)
📄
liblab_gamut.so.1.so.1.tar.gz
(1.75 MB)
📄
liblab_gamut.so.1.tar
(2.38 MB)
📄
liblber-2.4.so.2.10.9.4.so.2.10.9.tar.gz
(28.22 KB)
📄
liblber-2.4.so.2.10.9.tar
(67.5 KB)
📄
liblber-2.4.so.2.4.so.2.tar.gz
(28.22 KB)
📄
liblber-2.4.so.2.tar
(67.5 KB)
📄
liblber.so.so.tar.gz
(28.22 KB)
📄
liblber.so.tar
(67.5 KB)
📄
liblcms2.so.2.0.8.so.2.0.8.tar.gz
(171.58 KB)
📄
liblcms2.so.2.0.8.tar
(390 KB)
📄
liblcms2.so.2.so.2.tar.gz
(171.58 KB)
📄
liblcms2.so.2.tar
(390 KB)
📄
libldap-2.4.so.2.10.9.4.so.2.10.9.tar.gz
(143.28 KB)
📄
libldap-2.4.so.2.10.9.tar
(323 KB)
📄
libldap-2.4.so.2.4.so.2.tar.gz
(143.27 KB)
📄
libldap-2.4.so.2.tar
(323 KB)
📄
libldap.so.so.tar.gz
(143.27 KB)
📄
libldap.so.tar
(323 KB)
📄
libldap_r-2.4.so.2.4.so.2.tar.gz
(153.59 KB)
📄
libldap_r-2.4.so.2.tar
(351.5 KB)
📄
libldap_r.so.so.tar.gz
(153.58 KB)
📄
libldap_r.so.tar
(351.5 KB)
📄
libldb-key-value.so.so.tar.gz
(38.64 KB)
📄
libldb-key-value.so.tar
(95 KB)
📄
libldb-mdb-int.so.so.tar.gz
(9.78 KB)
📄
libldb-mdb-int.so.tar
(26 KB)
📄
libldb-tdb-err-map.so.so.tar.gz
(4.71 KB)
📄
libldb-tdb-err-map.so.tar
(14 KB)
📄
libldb-tdb-int.so.so.tar.gz
(9.47 KB)
📄
libldb-tdb-int.so.tar
(26 KB)
📄
libldb.so.2.8.0.so.2.8.0.tar.gz
(95.78 KB)
📄
libldb.so.2.8.0.tar
(225 KB)
📄
libldb.so.2.so.2.tar.gz
(95.77 KB)
📄
libldb.so.2.tar
(225 KB)
📄
libleveldb.so.1.22.0.so.1.22.0.tar.gz
(187.87 KB)
📄
libleveldb.so.1.22.0.tar
(564.5 KB)
📄
libleveldb.so.1.so.1.tar.gz
(187.86 KB)
📄
libleveldb.so.1.tar
(564.5 KB)
📄
liblmdb.so.0.0.0.so.0.0.0.tar.gz
(47.77 KB)
📄
liblmdb.so.0.0.0.tar
(91.5 KB)
📄
liblqr-1.tar
(106.5 KB)
📄
liblqr-1.tar.gz
(44.25 KB)
📄
liblqr-1.zip
(103.1 KB)
📄
liblscapi.so.1.1.so.1.1.tar.gz
(54.16 KB)
📄
liblscapi.so.1.1.tar
(122 KB)
📄
liblscapi.so.so.tar.gz
(54.16 KB)
📄
liblscapi.so.tar
(122 KB)
📄
libltdl.so.7.3.1.so.7.3.1.tar.gz
(19.26 KB)
📄
libltdl.so.7.3.1.tar
(45.5 KB)
📄
libltdl.so.7.so.7.tar.gz
(19.26 KB)
📄
libltdl.so.7.tar
(45.5 KB)
📄
libltdl.so.so.tar.gz
(19.26 KB)
📄
libltdl.so.tar
(45.5 KB)
📄
libltdl.tar
(15.5 KB)
📄
libltdl.tar.gz
(3.84 KB)
📄
libltdl.zip
(12.33 KB)
📄
liblua-5.1.so.1.so.tar.gz
(91.18 KB)
📄
liblua-5.1.so.tar
(194.5 KB)
📄
liblua-5.3.so.3.so.tar.gz
(114.88 KB)
📄
liblua-5.3.so.tar
(244 KB)
📄
liblve.so.0.9.0.so.0.9.0.tar.gz
(53.97 KB)
📄
liblve.so.0.9.0.tar
(291 KB)
📄
liblve.so.0.so.0.tar.gz
(53.96 KB)
📄
liblve.so.0.tar
(291 KB)
📄
liblve.so.1.so.1.tar.gz
(53.97 KB)
📄
liblve.so.1.tar
(146 KB)
📄
liblve.so.so.tar.gz
(53.97 KB)
📄
liblve.so.tar
(291 KB)
📄
liblve.tar
(163 KB)
📄
liblve.tar.gz
(59.49 KB)
📄
liblve.zip
(161.02 KB)
📄
liblwres.so.161.0.4.so.161.0.4.tar.gz
(36.82 KB)
📄
liblwres.so.161.0.4.tar
(82.5 KB)
📄
liblwres.so.161.so.161.tar.gz
(36.81 KB)
📄
liblwres.so.161.tar
(82.5 KB)
📄
liblwres.so.so.tar.gz
(36.82 KB)
📄
liblwres.so.tar
(82.5 KB)
📄
liblz4.so.1.8.3.so.1.8.3.tar.gz
(58.28 KB)
📄
liblz4.so.1.8.3.tar
(119 KB)
📄
liblz4.so.1.so.1.tar.gz
(58.28 KB)
📄
liblz4.so.1.tar
(119 KB)
📄
liblzma.pc.pc.tar.gz
(365 B)
📄
liblzma.pc.tar
(2 KB)
📄
liblzma.so.5.2.4.so.5.2.4.tar.gz
(83.21 KB)
📄
liblzma.so.5.2.4.tar
(160 KB)
📄
liblzma.so.5.so.5.tar.gz
(83.2 KB)
📄
liblzma.so.5.tar
(160 KB)
📄
liblzma.so.so.tar.gz
(83.21 KB)
📄
liblzma.so.tar
(160 KB)
📄
liblzo2.so.2.0.0.so.2.0.0.tar.gz
(51.42 KB)
📄
liblzo2.so.2.0.0.tar
(165.5 KB)
📄
liblzo2.so.2.so.2.tar.gz
(51.42 KB)
📄
liblzo2.so.2.tar
(165.5 KB)
📄
libm-2.28.so.28.so.tar.gz
(1.03 MB)
📄
libm-2.28.so.tar
(1.53 MB)
📄
libm-simd-decl-stubs.h.h.tar.gz
(1 KB)
📄
libm-simd-decl-stubs.h.tar
(4.5 KB)
📄
libm.so.6.so.6.tar.gz
(1.03 MB)
📄
libm.so.6.tar
(1.53 MB)
📄
libm.so.so.tar.gz
(199 B)
📄
libm.so.tar
(2 KB)
📄
libmagic.so.1.0.0.so.1.0.0.tar.gz
(75.46 KB)
📄
libmagic.so.1.0.0.tar
(160 KB)
📄
libmagic.so.1.so.1.tar.gz
(75.45 KB)
📄
libmagic.so.1.tar
(160 KB)
📄
libmagic.so.so.tar.gz
(75.46 KB)
📄
libmagic.so.tar
(160 KB)
📄
libman-2.7.6.1.so.7.6.1.so.tar.gz
(68.23 KB)
📄
libman-2.7.6.1.so.tar
(147.5 KB)
📄
libman.so.so.tar.gz
(68.23 KB)
📄
libman.so.tar
(147.5 KB)
📄
libmana.so.1.0.48.0.so.1.0.48.0.tar.gz
(10.05 KB)
📄
libmana.so.1.0.48.0.tar
(26.5 KB)
📄
libmana.so.1.so.1.tar.gz
(10.05 KB)
📄
libmana.so.1.tar
(26.5 KB)
📄
libmandb.so.so.tar.gz
(11.71 KB)
📄
libmandb.so.tar
(30 KB)
📄
libmariadb.a.a.tar.gz
(156.76 KB)
📄
libmariadb.a.tar
(533.5 KB)
📄
libmariadb.so.3.so.3.tar.gz
(140.89 KB)
📄
libmariadb.so.3.tar
(366 KB)
📄
libmariadb.so.so.tar.gz
(140.89 KB)
📄
libmariadb.so.tar
(366 KB)
📄
libmariadbclient.a.a.tar.gz
(156.76 KB)
📄
libmariadbclient.a.tar
(533.5 KB)
📄
libmariadbd.a.a.tar.gz
(10.75 MB)
📄
libmariadbd.a.tar
(48.76 MB)
📄
libmariadbd.so.19.so.19.tar.gz
(7.65 MB)
📄
libmariadbd.so.19.tar
(24.64 MB)
📄
libmariadbd.so.so.tar.gz
(7.65 MB)
📄
libmariadbd.so.tar
(24.64 MB)
📄
libmatio.so.9.1.2.so.9.1.2.tar.gz
(113.45 KB)
📄
libmatio.so.9.1.2.tar
(407.5 KB)
📄
libmatio.so.9.so.9.tar.gz
(113.45 KB)
📄
libmatio.so.9.tar
(407.5 KB)
📄
libmaxminddb.so.0.0.7.so.0.0.7.tar.gz
(11.7 KB)
📄
libmaxminddb.so.0.0.7.tar
(25.5 KB)
📄
libmaxminddb.so.0.so.0.tar.gz
(11.7 KB)
📄
libmaxminddb.so.0.tar
(25.5 KB)
📄
libmcheck.a.a.tar.gz
(4.85 KB)
📄
libmcheck.a.tar
(19 KB)
📄
libmcpp.so.0.3.0.so.0.3.0.tar.gz
(73.44 KB)
📄
libmcpp.so.0.3.0.tar
(150 KB)
📄
libmcpp.so.0.so.0.tar.gz
(73.43 KB)
📄
libmcpp.so.0.tar
(150 KB)
📄
libmcrypt.so.4.4.8.so.4.4.8.tar.gz
(81.72 KB)
📄
libmcrypt.so.4.4.8.tar
(204 KB)
📄
libmcrypt.so.4.so.4.tar.gz
(81.72 KB)
📄
libmcrypt.so.4.tar
(204 KB)
📄
libmcrypt.tar
(230 KB)
📄
libmcrypt.tar.gz
(94.78 KB)
📄
libmcrypt.zip
(224.91 KB)
📄
libmemcached.so.11.0.0.so.11.0.0.tar.gz
(100.11 KB)
📄
libmemcached.so.11.0.0.tar
(210 KB)
📄
libmemcached.so.11.so.11.tar.gz
(100.11 KB)
📄
libmemcached.so.11.tar
(210 KB)
📄
libmemcached.tar
(657.5 KB)
📄
libmemcached.tar.gz
(223.57 KB)
📄
libmemcached.zip
(646.15 KB)
📄
libmemcachedprotocol.so.0.so.0.tar.gz
(15.73 KB)
📄
libmemcachedprotocol.so.0.tar
(42.5 KB)
📄
libmemcachedutil.so.2.0.0.so.2.0.0.tar.gz
(7.77 KB)
📄
libmemcachedutil.so.2.0.0.tar
(22 KB)
📄
libmemcachedutil.so.2.so.2.tar.gz
(7.77 KB)
📄
libmemcachedutil.so.2.tar
(22 KB)
📄
libmemusage.so.so.tar.gz
(7.93 KB)
📄
libmemusage.so.tar
(22 KB)
📄
libmenu.so.5.9.so.5.9.tar.gz
(16.21 KB)
📄
libmenu.so.5.9.tar
(38.5 KB)
📄
libmenu.so.5.so.5.tar.gz
(16.21 KB)
📄
libmenu.so.5.tar
(38.5 KB)
📄
libmenu.so.6.1.so.6.1.tar.gz
(16.34 KB)
📄
libmenu.so.6.1.tar
(38.5 KB)
📄
libmenu.so.6.so.6.tar.gz
(16.33 KB)
📄
libmenu.so.6.tar
(38.5 KB)
📄
libmenu.so.so.tar.gz
(16.33 KB)
📄
libmenu.so.tar
(38.5 KB)
📄
libmenuw.so.5.9.so.5.9.tar.gz
(16.56 KB)
📄
libmenuw.so.5.9.tar
(38.5 KB)
📄
libmenuw.so.5.so.5.tar.gz
(16.56 KB)
📄
libmenuw.so.5.tar
(38.5 KB)
📄
libmenuw.so.6.1.so.6.1.tar.gz
(16.67 KB)
📄
libmenuw.so.6.1.tar
(38.5 KB)
📄
libmenuw.so.6.so.6.tar.gz
(16.66 KB)
📄
libmenuw.so.6.tar
(38.5 KB)
📄
libmenuw.so.so.tar.gz
(16.67 KB)
📄
libmenuw.so.tar
(38.5 KB)
📄
libmetalink.so.3.1.0.so.3.1.0.tar.gz
(23.59 KB)
📄
libmetalink.so.3.1.0.tar
(75 KB)
📄
libmetalink.so.3.so.3.tar.gz
(23.59 KB)
📄
libmetalink.so.3.tar
(75 KB)
📄
libmhash.so.2.0.1.so.2.0.1.tar.gz
(100.49 KB)
📄
libmhash.so.2.0.1.tar
(187.5 KB)
📄
libmhash.so.2.so.2.tar.gz
(100.48 KB)
📄
libmhash.so.2.tar
(187.5 KB)
📄
libmimerS.so.2.0.0.so.2.0.0.tar.gz
(3.45 KB)
📄
libmimerS.so.2.0.0.tar
(13.5 KB)
📄
libmimerS.so.2.so.2.tar.gz
(3.45 KB)
📄
libmimerS.so.2.tar
(13.5 KB)
📄
libmlx4.so.1.0.48.0.so.1.0.48.0.tar.gz
(24.01 KB)
📄
libmlx4.so.1.0.48.0.tar
(55 KB)
📄
libmlx4.so.1.so.1.tar.gz
(24 KB)
📄
libmlx4.so.1.tar
(55 KB)
📄
libmlx5.so.1.24.48.0.so.1.24.48.0.tar.gz
(198.06 KB)
📄
libmlx5.so.1.24.48.0.tar
(469 KB)
📄
libmlx5.so.1.so.1.tar.gz
(198.05 KB)
📄
libmlx5.so.1.tar
(469 KB)
📄
libmnl.so.0.2.0.so.0.2.0.tar.gz
(9.82 KB)
📄
libmnl.so.0.2.0.tar
(27 KB)
📄
libmnl.so.0.so.0.tar.gz
(9.82 KB)
📄
libmnl.so.0.tar
(27 KB)
📄
libmodulemd.so.2.13.0.so.2.13.0.tar.gz
(234.58 KB)
📄
libmodulemd.so.2.13.0.tar
(614 KB)
📄
libmodulemd.so.2.so.2.tar.gz
(234.58 KB)
📄
libmodulemd.so.2.tar
(614 KB)
📄
libmount.so.1.1.0.so.1.1.0.tar.gz
(165.36 KB)
📄
libmount.so.1.1.0.tar
(364.5 KB)
📄
libmount.so.1.so.1.tar.gz
(165.36 KB)
📄
libmount.so.1.tar
(364.5 KB)
📄
libmozjs-60.so.0.0.0.so.0.0.0.tar.gz
(8.57 MB)
📄
libmozjs-60.so.0.0.0.tar
(30.28 MB)
📄
libmozjs-60.so.0.so.0.tar.gz
(8.57 MB)
📄
libmozjs-60.so.0.tar
(30.28 MB)
📄
libmpc.so.3.1.0.so.3.1.0.tar.gz
(48.28 KB)
📄
libmpc.so.3.1.0.tar
(111 KB)
📄
libmpc.so.3.so.3.tar.gz
(48.27 KB)
📄
libmpc.so.3.tar
(111 KB)
📄
libmpdec.so.2.5.1.so.2.5.1.tar.gz
(96.51 KB)
📄
libmpdec.so.2.5.1.tar
(230 KB)
📄
libmpdec.so.3.so.3.tar.gz
(96.5 KB)
📄
libmpdec.so.3.tar
(230 KB)
📄
libmpfr.so.4.1.6.so.4.1.6.tar.gz
(196.39 KB)
📄
libmpfr.so.4.1.6.tar
(494.5 KB)
📄
libmpfr.so.4.so.4.tar.gz
(196.38 KB)
📄
libmpfr.so.4.tar
(494.5 KB)
📄
libmspack.so.0.1.0.so.0.1.0.tar.gz
(41.25 KB)
📄
libmspack.so.0.1.0.tar
(125.5 KB)
📄
libmspack.so.0.so.0.tar.gz
(41.24 KB)
📄
libmspack.so.0.tar
(125.5 KB)
📄
libmtdev.so.1.0.0.so.1.0.0.tar.gz
(11.34 KB)
📄
libmtdev.so.1.0.0.tar
(27.5 KB)
📄
libmtdev.so.1.so.1.tar.gz
(11.34 KB)
📄
libmtdev.so.1.tar
(27.5 KB)
📄
libmvec-2.28.so.28.so.tar.gz
(95.65 KB)
📄
libmvec-2.28.so.tar
(175.5 KB)
📄
libmvec.so.1.so.1.tar.gz
(95.64 KB)
📄
libmvec.so.1.tar
(175.5 KB)
📄
libmvec.so.so.tar.gz
(95.65 KB)
📄
libmvec.so.tar
(175.5 KB)
📄
libmvec_nonshared.a.a.tar.gz
(1.38 KB)
📄
libmvec_nonshared.a.tar
(8 KB)
📄
libmysqlclient.a.a.tar.gz
(156.76 KB)
📄
libmysqlclient.a.tar
(533.5 KB)
📄
libmysqlclient.so.15.0.0.so.15.0.0.tar.gz
(721.78 KB)
📄
libmysqlclient.so.15.0.0.tar
(1.61 MB)
📄
libmysqlclient.so.15.so.15.tar.gz
(721.77 KB)
📄
libmysqlclient.so.15.tar
(1.61 MB)
📄
libmysqlclient.so.16.0.0.so.16.0.0.tar.gz
(1.01 MB)
📄
libmysqlclient.so.16.0.0.tar
(2.71 MB)
📄
libmysqlclient.so.16.so.16.tar.gz
(1.01 MB)
📄
libmysqlclient.so.16.tar
(2.71 MB)
📄
libmysqlclient.so.18.so.18.tar.gz
(140.89 KB)
📄
libmysqlclient.so.18.tar
(366 KB)
📄
libmysqlclient.so.19.so.19.tar.gz
(140.89 KB)
📄
libmysqlclient.so.19.tar
(366 KB)
📄
libmysqlclient.so.so.tar.gz
(140.89 KB)
📄
libmysqlclient.so.tar
(366 KB)
📄
libmysqlclient21.tar
(7.18 MB)
📄
libmysqlclient21.tar.gz
(2.09 MB)
📄
libmysqlclient21.zip
(7.18 MB)
📄
libmysqlclient_r.a.a.tar.gz
(156.76 KB)
📄
libmysqlclient_r.a.tar
(533.5 KB)
📄
libmysqlclient_r.so.15.so.15.tar.gz
(726.05 KB)
📄
libmysqlclient_r.so.15.tar
(1.63 MB)
📄
libmysqlclient_r.so.16.so.16.tar.gz
(1.02 MB)
📄
libmysqlclient_r.so.16.tar
(2.73 MB)
📄
libmysqlclient_r.so.so.tar.gz
(140.89 KB)
📄
libmysqlclient_r.so.tar
(366 KB)
📄
libmysqld.a.a.tar.gz
(10.75 MB)
📄
libmysqld.a.tar
(48.76 MB)
📄
libmysqld.so.so.tar.gz
(7.65 MB)
📄
libmysqld.so.tar
(24.64 MB)
📄
libmysqlservices.a.a.tar.gz
(1.62 KB)
📄
libmysqlservices.a.tar
(32 KB)
📄
libncurses++.so.5.9.so.5.9.tar.gz
(27.05 KB)
📄
libncurses++.so.5.9.tar
(75 KB)
📄
libncurses++.so.5.so.5.tar.gz
(27.04 KB)
📄
libncurses++.so.5.tar
(75 KB)
📄
libncurses++.so.6.1.so.6.1.tar.gz
(27.05 KB)
📄
libncurses++.so.6.1.tar
(75 KB)
📄
libncurses++.so.6.so.6.tar.gz
(27.04 KB)
📄
libncurses++.so.6.tar
(75 KB)
📄
libncurses++.so.so.tar.gz
(27.05 KB)
📄
libncurses++.so.tar
(75 KB)
📄
libncurses++w.so.5.9.so.5.9.tar.gz
(27.06 KB)
📄
libncurses++w.so.5.9.tar
(75 KB)
📄
libncurses++w.so.5.so.5.tar.gz
(27.06 KB)
📄
libncurses++w.so.5.tar
(75 KB)
📄
libncurses++w.so.6.1.so.6.1.tar.gz
(27.04 KB)
📄
libncurses++w.so.6.1.tar
(75 KB)
📄
libncurses++w.so.6.so.6.tar.gz
(27.04 KB)
📄
libncurses++w.so.6.tar
(75 KB)
📄
libncurses++w.so.so.tar.gz
(27.04 KB)
📄
libncurses++w.so.tar
(75 KB)
📄
libncurses.so.5.9.so.5.9.tar.gz
(75.31 KB)
📄
libncurses.so.5.9.tar
(161 KB)
📄
libncurses.so.5.so.5.tar.gz
(75.31 KB)
📄
libncurses.so.5.tar
(161 KB)
📄
libncurses.so.6.1.so.6.1.tar.gz
(82.41 KB)
📄
libncurses.so.6.1.tar
(178 KB)
📄
libncurses.so.6.so.6.tar.gz
(82.41 KB)
📄
libncurses.so.6.tar
(178 KB)
📄
libncurses.so.so.tar.gz
(124 B)
📄
libncurses.so.tar
(2 KB)
📄
libncursesw.so.5.9.so.5.9.tar.gz
(100.63 KB)
📄
libncursesw.so.5.9.tar
(214 KB)
📄
libncursesw.so.5.so.5.tar.gz
(100.62 KB)
📄
libncursesw.so.5.tar
(214 KB)
📄
libncursesw.so.6.1.so.6.1.tar.gz
(117.38 KB)
📄
libncursesw.so.6.1.tar
(255 KB)
📄
libncursesw.so.6.so.6.tar.gz
(117.38 KB)
📄
libncursesw.so.6.tar
(255 KB)
📄
libncursesw.so.so.tar.gz
(123 B)
📄
libncursesw.so.tar
(2 KB)
📄
libndp.so.0.1.1.so.0.1.1.tar.gz
(11.03 KB)
📄
libndp.so.0.1.1.tar
(30 KB)
📄
libndp.so.0.so.0.tar.gz
(11.03 KB)
📄
libndp.so.0.tar
(30 KB)
📄
libnet.so.1.7.0.so.1.7.0.tar.gz
(42.93 KB)
📄
libnet.so.1.7.0.tar
(122 KB)
📄
libnet.so.1.so.1.tar.gz
(42.93 KB)
📄
libnet.so.1.tar
(122 KB)
📄
libnetcfg.tar
(17 KB)
📄
libnetcfg.tar.gz
(4.99 KB)
📄
libnetfilter_conntrack.so.3.so.3.tar.gz
(53.65 KB)
📄
libnetfilter_conntrack.so.3.tar
(145.5 KB)
📄
libnetsnmp.so.35.0.0.so.35.0.0.tar.gz
(414.15 KB)
📄
libnetsnmp.so.35.0.0.tar
(932 KB)
📄
libnetsnmp.so.35.so.35.tar.gz
(414.15 KB)
📄
libnetsnmp.so.35.tar
(932 KB)
📄
libnetsnmp.so.so.tar.gz
(286.97 KB)
📄
libnetsnmp.so.tar
(663.5 KB)
📄
libnettle.so.6.5.so.6.5.tar.gz
(110.27 KB)
📄
libnettle.so.6.5.tar
(235.5 KB)
📄
libnettle.so.6.so.6.tar.gz
(110.27 KB)
📄
libnettle.so.6.tar
(235.5 KB)
📄
libnewt.so.0.52.20.so.0.52.20.tar.gz
(43.55 KB)
📄
libnewt.so.0.52.20.tar
(98.5 KB)
📄
libnewt.so.0.52.so.0.52.tar.gz
(43.55 KB)
📄
libnewt.so.0.52.tar
(98.5 KB)
📄
libnfnetlink.so.0.2.0.so.0.2.0.tar.gz
(14.09 KB)
📄
libnfnetlink.so.0.2.0.tar
(34 KB)
📄
libnfnetlink.so.0.so.0.tar.gz
(14.09 KB)
📄
libnfnetlink.so.0.tar
(34 KB)
📄
libnfsidmap.so.1.0.0.so.1.0.0.tar.gz
(21.43 KB)
📄
libnfsidmap.so.1.0.0.tar
(51 KB)
📄
libnfsidmap.so.1.so.1.tar.gz
(21.43 KB)
📄
libnfsidmap.so.1.tar
(51 KB)
📄
libnfsidmap.tar
(172 KB)
📄
libnfsidmap.tar.gz
(73.46 KB)
📄
libnfsidmap.zip
(168.42 KB)
📄
libnftables.so.1.1.0.so.1.1.0.tar.gz
(330.92 KB)
📄
libnftables.so.1.1.0.tar
(828 KB)
📄
libnftables.so.1.so.1.tar.gz
(330.91 KB)
📄
libnftables.so.1.tar
(828 KB)
📄
libnftnl.so.11.6.0.so.11.6.0.tar.gz
(77.7 KB)
📄
libnftnl.so.11.6.0.tar
(210.5 KB)
📄
libnftnl.so.11.so.11.tar.gz
(77.69 KB)
📄
libnftnl.so.11.tar
(210.5 KB)
📄
libnghttp2.so.14.17.0.so.14.17.0.tar.gz
(76.64 KB)
📄
libnghttp2.so.14.17.0.tar
(165 KB)
📄
libnghttp2.so.14.so.14.tar.gz
(76.64 KB)
📄
libnghttp2.so.14.tar
(165 KB)
📄
libnl-3.so.200.26.0.so.200.26.0.tar.gz
(62.08 KB)
📄
libnl-3.so.200.26.0.tar
(145 KB)
📄
libnl-3.so.200.so.200.tar.gz
(62.07 KB)
📄
libnl-3.so.200.tar
(145 KB)
📄
libnl-cli-3.so.200.so.200.tar.gz
(16.29 KB)
📄
libnl-cli-3.so.200.tar
(50 KB)
📄
libnl-genl-3.so.200.26.0.so.200.26.0.tar.gz
(12.05 KB)
📄
libnl-genl-3.so.200.26.0.tar
(31.5 KB)
📄
libnl-genl-3.so.200.so.200.tar.gz
(12.05 KB)
📄
libnl-genl-3.so.200.tar
(31.5 KB)
📄
libnl-idiag-3.so.200.26.0.so.200.26.0.tar.gz
(14.5 KB)
📄
libnl-idiag-3.so.200.26.0.tar
(43.5 KB)
📄
libnl-idiag-3.so.200.so.200.tar.gz
(14.49 KB)
📄
libnl-idiag-3.so.200.tar
(43.5 KB)
📄
libnl-nf-3.so.200.26.0.so.200.26.0.tar.gz
(39.65 KB)
📄
libnl-nf-3.so.200.26.0.tar
(115 KB)
📄
libnl-nf-3.so.200.so.200.tar.gz
(39.65 KB)
📄
libnl-nf-3.so.200.tar
(115 KB)
📄
libnl-route-3.so.200.26.0.so.200.26.0.tar.gz
(226.32 KB)
📄
libnl-route-3.so.200.26.0.tar
(589 KB)
📄
libnl-route-3.so.200.so.200.tar.gz
(226.32 KB)
📄
libnl-route-3.so.200.tar
(589 KB)
📄
libnl-xfrm-3.so.200.26.0.so.200.26.0.tar.gz
(34.26 KB)
📄
libnl-xfrm-3.so.200.26.0.tar
(92.5 KB)
📄
libnl-xfrm-3.so.200.so.200.tar.gz
(34.26 KB)
📄
libnl-xfrm-3.so.200.tar
(92.5 KB)
📄
libnl.tar
(110.5 KB)
📄
libnl.tar.gz
(23.49 KB)
📄
libnl.zip
(102.56 KB)
📄
libnm.so.0.1.0.so.0.1.0.tar.gz
(571.72 KB)
📄
libnm.so.0.1.0.tar
(1.43 MB)
📄
libnm.so.0.so.0.tar.gz
(571.72 KB)
📄
libnm.so.0.tar
(1.43 MB)
📄
libnn.so.2.0.0.so.2.0.0.tar.gz
(41.05 KB)
📄
libnn.so.2.0.0.tar
(96.5 KB)
📄
libnn.so.2.so.2.tar.gz
(41.05 KB)
📄
libnn.so.2.tar
(96.5 KB)
📄
libnpth.so.0.1.1.so.0.1.1.tar.gz
(7.03 KB)
📄
libnpth.so.0.1.1.tar
(22.5 KB)
📄
libnpth.so.0.so.0.tar.gz
(7.03 KB)
📄
libnpth.so.0.tar
(22.5 KB)
📄
libnsl-2.28.so.28.so.tar.gz
(44.29 KB)
📄
libnsl-2.28.so.tar
(98.5 KB)
📄
libnsl.so.1.so.1.tar.gz
(44.28 KB)
📄
libnsl.so.1.tar
(98.5 KB)
📄
libnsl.so.2.0.0.so.2.0.0.tar.gz
(43.81 KB)
📄
libnsl.so.2.0.0.tar
(119.5 KB)
📄
libnsl.so.2.so.2.tar.gz
(43.8 KB)
📄
libnsl.so.2.tar
(119.5 KB)
📄
libnspr4.so.so.tar.gz
(119.08 KB)
📄
libnspr4.so.tar
(258.5 KB)
📄
libnss3.so.so.tar.gz
(514.06 KB)
📄
libnss3.so.tar
(1.28 MB)
📄
libnss_compat-2.28.so.28.so.tar.gz
(15.91 KB)
📄
libnss_compat-2.28.so.tar
(39.5 KB)
📄
libnss_compat.so.2.so.2.tar.gz
(15.9 KB)
📄
libnss_compat.so.2.tar
(39.5 KB)
📄
libnss_dns-2.28.so.28.so.tar.gz
(12.49 KB)
📄
libnss_dns-2.28.so.tar
(30.5 KB)
📄
libnss_dns.so.2.so.2.tar.gz
(12.49 KB)
📄
libnss_dns.so.2.tar
(30.5 KB)
📄
libnss_files-2.28.so.28.so.tar.gz
(20.43 KB)
📄
libnss_files-2.28.so.tar
(55 KB)
📄
libnss_files.so.2.so.2.tar.gz
(20.43 KB)
📄
libnss_files.so.2.tar
(55 KB)
📄
libnss_myhostname.so.2.so.2.tar.gz
(316.95 KB)
📄
libnss_myhostname.so.2.tar
(709.5 KB)
📄
libnss_resolve.so.2.so.2.tar.gz
(426.59 KB)
📄
libnss_resolve.so.2.tar
(924 KB)
📄
libnss_sss.so.2.so.2.tar.gz
(20.3 KB)
📄
libnss_sss.so.2.tar
(47 KB)
📄
libnss_systemd.so.2.so.2.tar.gz
(427.71 KB)
📄
libnss_systemd.so.2.tar
(928 KB)
📄
libnssckbi.so.so.tar.gz
(95.46 KB)
📄
libnssckbi.so.tar
(251 KB)
📄
libnssdbm3.chk.chk.tar.gz
(187 B)
📄
libnssdbm3.chk.tar
(2 KB)
📄
libnssdbm3.so.so.tar.gz
(69.22 KB)
📄
libnssdbm3.so.tar
(141 KB)
📄
libnsssysinit.so.so.tar.gz
(4.97 KB)
📄
libnsssysinit.so.tar
(13 KB)
📄
libnssutil3.so.so.tar.gz
(80.22 KB)
📄
libnssutil3.so.tar
(211.5 KB)
📄
libnuma.so.1.0.0.so.1.0.0.tar.gz
(23.48 KB)
📄
libnuma.so.1.0.0.tar
(52 KB)
📄
libnuma.so.1.so.1.tar.gz
(23.48 KB)
📄
libnuma.so.1.tar
(52 KB)
📄
libnuron.so.so.tar.gz
(5.77 KB)
📄
libnuron.so.tar
(22 KB)
📄
libodbc.so.2.0.0.so.2.0.0.tar.gz
(184.79 KB)
📄
libodbc.so.2.0.0.tar
(446 KB)
📄
libodbc.so.2.so.2.tar.gz
(184.79 KB)
📄
libodbc.so.2.tar
(446 KB)
📄
libodbc.so.so.tar.gz
(184.79 KB)
📄
libodbc.so.tar
(446 KB)
📄
libodbccr.so.2.0.0.so.2.0.0.tar.gz
(16.73 KB)
📄
libodbccr.so.2.0.0.tar
(46.5 KB)
📄
libodbccr.so.2.so.2.tar.gz
(16.73 KB)
📄
libodbccr.so.2.tar
(46.5 KB)
📄
libodbcdrvcfg1S.so.2.0.0.so.2.0.0.tar.gz
(2.94 KB)
📄
libodbcdrvcfg1S.so.2.0.0.tar
(9 KB)
📄
libodbcdrvcfg1S.so.2.so.2.tar.gz
(2.94 KB)
📄
libodbcdrvcfg1S.so.2.tar
(9 KB)
📄
libodbcdrvcfg2S.so.2.0.0.so.2.0.0.tar.gz
(2.8 KB)
📄
libodbcdrvcfg2S.so.2.0.0.tar
(9 KB)
📄
libodbcdrvcfg2S.so.2.so.2.tar.gz
(2.8 KB)
📄
libodbcdrvcfg2S.so.2.tar
(9 KB)
📄
libodbcinst.so.2.0.0.so.2.0.0.tar.gz
(36.16 KB)
📄
libodbcinst.so.2.0.0.tar
(83.5 KB)
📄
libodbcinst.so.2.so.2.tar.gz
(36.16 KB)
📄
libodbcinst.so.2.tar
(83.5 KB)
📄
libodbcinst.so.so.tar.gz
(36.16 KB)
📄
libodbcinst.so.tar
(83.5 KB)
📄
libodbcminiS.so.2.0.0.so.2.0.0.tar.gz
(3 KB)
📄
libodbcminiS.so.2.0.0.tar
(9 KB)
📄
libodbcminiS.so.2.so.2.tar.gz
(3 KB)
📄
libodbcminiS.so.2.tar
(9 KB)
📄
libodbcmyS.so.2.0.0.so.2.0.0.tar.gz
(4.05 KB)
📄
libodbcmyS.so.2.0.0.tar
(13 KB)
📄
libodbcmyS.so.2.so.2.tar.gz
(4.05 KB)
📄
libodbcmyS.so.2.tar
(13 KB)
📄
libodbcmyS.so.so.tar.gz
(4.05 KB)
📄
libodbcmyS.so.tar
(13 KB)
📄
libodbcnnS.so.2.0.0.so.2.0.0.tar.gz
(2.87 KB)
📄
libodbcnnS.so.2.0.0.tar
(9 KB)
📄
libodbcnnS.so.2.so.2.tar.gz
(2.87 KB)
📄
libodbcnnS.so.2.tar
(9 KB)
📄
libodbcpsqlS.so.2.0.0.so.2.0.0.tar.gz
(3.67 KB)
📄
libodbcpsqlS.so.2.0.0.tar
(13.5 KB)
📄
libodbcpsqlS.so.2.so.2.tar.gz
(3.67 KB)
📄
libodbcpsqlS.so.2.tar
(13.5 KB)
📄
libodbcpsqlS.so.so.tar.gz
(3.67 KB)
📄
libodbcpsqlS.so.tar
(13.5 KB)
📄
libodbctxtS.so.2.0.0.so.2.0.0.tar.gz
(3.44 KB)
📄
libodbctxtS.so.2.0.0.tar
(9 KB)
📄
libodbctxtS.so.2.so.2.tar.gz
(3.44 KB)
📄
libodbctxtS.so.2.tar
(9 KB)
📄
libogg.so.0.8.2.so.0.8.2.tar.gz
(13.24 KB)
📄
libogg.so.0.8.2.tar
(30.5 KB)
📄
libogg.so.0.so.0.tar.gz
(13.23 KB)
📄
libogg.so.0.tar
(30.5 KB)
📄
libomapi.so.0.0.0.so.0.0.0.tar.gz
(56.3 KB)
📄
libomapi.so.0.0.0.tar
(135.5 KB)
📄
libomapi.so.0.so.0.tar.gz
(56.3 KB)
📄
libomapi.so.0.tar
(135.5 KB)
📄
libonig.so.5.0.0.so.5.0.0.tar.gz
(180.97 KB)
📄
libonig.so.5.0.0.tar
(532.5 KB)
📄
libonig.so.5.so.5.tar.gz
(180.97 KB)
📄
libonig.so.5.tar
(532.5 KB)
📄
libopenal.so.1.18.2.so.1.18.2.tar.gz
(325.75 KB)
📄
libopenal.so.1.18.2.tar
(801.5 KB)
📄
libopenal.so.1.so.1.tar.gz
(325.75 KB)
📄
libopenal.so.1.tar
(801.5 KB)
📄
libopenjp2.so.2.4.0.so.2.4.0.tar.gz
(159.25 KB)
📄
libopenjp2.so.2.4.0.tar
(361 KB)
📄
libopenjp2.so.7.so.7.tar.gz
(159.24 KB)
📄
libopenjp2.so.7.tar
(361 KB)
📄
libopenslide.so.0.4.1.so.0.4.1.tar.gz
(93.84 KB)
📄
libopenslide.so.0.4.1.tar
(205 KB)
📄
libopenslide.so.0.so.0.tar.gz
(93.84 KB)
📄
libopenslide.so.0.tar
(205 KB)
📄
liboplodbcS.so.2.0.0.so.2.0.0.tar.gz
(4.05 KB)
📄
liboplodbcS.so.2.0.0.tar
(13.5 KB)
📄
liboplodbcS.so.2.so.2.tar.gz
(4.05 KB)
📄
liboplodbcS.so.2.tar
(13.5 KB)
📄
libopus.so.0.6.1.so.0.6.1.tar.gz
(209.64 KB)
📄
libopus.so.0.6.1.tar
(417.5 KB)
📄
libopus.so.0.so.0.tar.gz
(209.63 KB)
📄
libopus.so.0.tar
(417.5 KB)
📄
liboraodbcS.so.2.0.0.so.2.0.0.tar.gz
(3.14 KB)
📄
liboraodbcS.so.2.0.0.tar
(9 KB)
📄
liboraodbcS.so.2.so.2.tar.gz
(3.14 KB)
📄
liboraodbcS.so.2.tar
(9 KB)
📄
liborc-0.4.so.0.28.0.4.so.0.28.0.tar.gz
(175.72 KB)
📄
liborc-0.4.so.0.28.0.tar
(517.5 KB)
📄
liborc-0.4.so.0.4.so.0.tar.gz
(175.71 KB)
📄
liborc-0.4.so.0.tar
(517.5 KB)
📄
liborc-test-0.4.so.0.28.0.4.so.0.28.0.tar.gz
(13.79 KB)
📄
liborc-test-0.4.so.0.28.0.tar
(34 KB)
📄
liborc-test-0.4.so.0.4.so.0.tar.gz
(13.79 KB)
📄
liborc-test-0.4.so.0.tar
(34 KB)
📄
libp11-kit.so.0.3.0.so.0.3.0.tar.gz
(311.32 KB)
📄
libp11-kit.so.0.3.0.tar
(1.2 MB)
📄
libp11-kit.so.0.so.0.tar.gz
(311.32 KB)
📄
libp11-kit.so.0.tar
(1.2 MB)
📄
libp11.so.3.4.2.so.3.4.2.tar.gz
(29.22 KB)
📄
libp11.so.3.4.2.tar
(73.5 KB)
📄
libp11.so.3.so.3.tar.gz
(29.21 KB)
📄
libp11.so.3.tar
(73.5 KB)
📄
libpam.so.0.84.2.so.0.84.2.tar.gz
(27.79 KB)
📄
libpam.so.0.84.2.tar
(66.5 KB)
📄
libpam.so.0.so.0.tar.gz
(27.78 KB)
📄
libpam.so.0.tar
(66.5 KB)
📄
libpam.so.so.tar.gz
(27.78 KB)
📄
libpam.so.tar
(66.5 KB)
📄
libpam_misc.so.0.82.1.so.0.82.1.tar.gz
(6.38 KB)
📄
libpam_misc.so.0.82.1.tar
(18 KB)
📄
libpam_misc.so.0.so.0.tar.gz
(6.38 KB)
📄
libpam_misc.so.0.tar
(18 KB)
📄
libpam_misc.so.so.tar.gz
(6.39 KB)
📄
libpam_misc.so.tar
(18 KB)
📄
libpamc.so.0.82.1.so.0.82.1.tar.gz
(6.92 KB)
📄
libpamc.so.0.82.1.tar
(18 KB)
📄
libpamc.so.0.so.0.tar.gz
(6.92 KB)
📄
libpamc.so.0.tar
(18 KB)
📄
libpamc.so.so.tar.gz
(6.92 KB)
📄
libpamc.so.tar
(18 KB)
📄
libpanel.so.5.9.so.5.9.tar.gz
(5.94 KB)
📄
libpanel.so.5.9.tar
(17.5 KB)
📄
libpanel.so.5.so.5.tar.gz
(5.94 KB)
📄
libpanel.so.5.tar
(17.5 KB)
📄
libpanel.so.6.1.so.6.1.tar.gz
(5.93 KB)
📄
libpanel.so.6.1.tar
(18 KB)
📄
libpanel.so.6.so.6.tar.gz
(5.92 KB)
📄
libpanel.so.6.tar
(18 KB)
📄
libpanel.so.so.tar.gz
(5.92 KB)
📄
libpanel.so.tar
(18 KB)
📄
libpanelw.so.5.9.so.5.9.tar.gz
(5.94 KB)
📄
libpanelw.so.5.9.tar
(17.5 KB)
📄
libpanelw.so.5.so.5.tar.gz
(5.94 KB)
📄
libpanelw.so.5.tar
(17.5 KB)
📄
libpanelw.so.6.1.so.6.1.tar.gz
(5.93 KB)
📄
libpanelw.so.6.1.tar
(18 KB)
📄
libpanelw.so.6.so.6.tar.gz
(5.93 KB)
📄
libpanelw.so.6.tar
(18 KB)
📄
libpanelw.so.so.tar.gz
(5.93 KB)
📄
libpanelw.so.tar
(18 KB)
📄
libpango-1.0.so.0.0.so.0.tar.gz
(130.71 KB)
📄
libpango-1.0.so.0.4200.3.0.so.0.4200.3.tar.gz
(130.71 KB)
📄
libpango-1.0.so.0.4200.3.tar
(292.5 KB)
📄
libpango-1.0.so.0.tar
(292.5 KB)
📄
libpangocairo-1.0.so.0.0.so.0.tar.gz
(23.73 KB)
📄
libpangocairo-1.0.so.0.tar
(62.5 KB)
📄
libpangoft2-1.0.so.0.0.so.0.tar.gz
(39.13 KB)
📄
libpangoft2-1.0.so.0.4200.3.0.so.0.4200.3.tar.gz
(39.14 KB)
📄
libpangoft2-1.0.so.0.4200.3.tar
(95 KB)
📄
libpangoft2-1.0.so.0.tar
(95 KB)
📄
libpangoxft-1.0.so.0.0.so.0.tar.gz
(16.21 KB)
📄
libpangoxft-1.0.so.0.4200.3.0.so.0.4200.3.tar.gz
(16.22 KB)
📄
libpangoxft-1.0.so.0.4200.3.tar
(42 KB)
📄
libpangoxft-1.0.so.0.tar
(42 KB)
📄
libpaper.so.1.1.2.so.1.1.2.tar.gz
(6.56 KB)
📄
libpaper.so.1.1.2.tar
(19.5 KB)
📄
libpaper.so.1.so.1.tar.gz
(6.56 KB)
📄
libpaper.so.1.tar
(19.5 KB)
📄
libparted-fs-resize.so.0.0.1.so.0.0.1.tar.gz
(47.21 KB)
📄
libparted-fs-resize.so.0.0.1.tar
(99.5 KB)
📄
libparted-fs-resize.so.0.so.0.tar.gz
(47.21 KB)
📄
libparted-fs-resize.so.0.tar
(99.5 KB)
📄
libparted.so.2.0.1.so.2.0.1.tar.gz
(141.69 KB)
📄
libparted.so.2.0.1.tar
(322 KB)
📄
libparted.so.2.so.2.tar.gz
(141.68 KB)
📄
libparted.so.2.tar
(322 KB)
📄
libpath_utils.so.1.0.1.so.1.0.1.tar.gz
(7.06 KB)
📄
libpath_utils.so.1.0.1.tar
(17.5 KB)
📄
libpath_utils.so.1.so.1.tar.gz
(7.06 KB)
📄
libpath_utils.so.1.tar
(17.5 KB)
📄
libpathplan.so.4.0.0.so.4.0.0.tar.gz
(18.26 KB)
📄
libpathplan.so.4.0.0.tar
(38 KB)
📄
libpathplan.so.4.so.4.tar.gz
(18.26 KB)
📄
libpathplan.so.4.tar
(38 KB)
📄
libpcap.so.1.9.1.so.1.9.1.tar.gz
(134.73 KB)
📄
libpcap.so.1.9.1.tar
(307 KB)
📄
libpcap.so.1.so.1.tar.gz
(134.73 KB)
📄
libpcap.so.1.tar
(307 KB)
📄
libpci.so.3.7.0.so.3.7.0.tar.gz
(27.13 KB)
📄
libpci.so.3.7.0.tar
(60 KB)
📄
libpci.so.3.so.3.tar.gz
(27.12 KB)
📄
libpci.so.3.tar
(60 KB)
📄
libpciaccess.so.0.11.1.so.0.11.1.tar.gz
(17.79 KB)
📄
libpciaccess.so.0.11.1.tar
(46 KB)
📄
libpciaccess.so.0.so.0.tar.gz
(17.78 KB)
📄
libpciaccess.so.0.tar
(46 KB)
📄
libpcprofile.so.so.tar.gz
(3.32 KB)
📄
libpcprofile.so.tar
(9.5 KB)
📄
libpcre.pc.pc.tar.gz
(314 B)
📄
libpcre.pc.tar
(2 KB)
📄
libpcre.so.1.2.10.so.1.2.10.tar.gz
(180.82 KB)
📄
libpcre.so.1.2.10.tar
(455.5 KB)
📄
libpcre.so.1.so.1.tar.gz
(180.81 KB)
📄
libpcre.so.1.tar
(455.5 KB)
📄
libpcre.so.so.tar.gz
(180.82 KB)
📄
libpcre.so.tar
(660.5 KB)
📄
libpcre16.pc.pc.tar.gz
(316 B)
📄
libpcre16.pc.tar
(2 KB)
📄
libpcre16.so.0.2.10.so.0.2.10.tar.gz
(167.16 KB)
📄
libpcre16.so.0.2.10.tar
(415.5 KB)
📄
libpcre16.so.0.so.0.tar.gz
(167.16 KB)
📄
libpcre16.so.0.tar
(415.5 KB)
📄
libpcre16.so.so.tar.gz
(167.16 KB)
📄
libpcre16.so.tar
(415.5 KB)
📄
libpcre2-16.pc.pc.tar.gz
(330 B)
📄
libpcre2-16.pc.tar
(2 KB)
📄
libpcre2-16.so.0.7.1.so.0.7.1.tar.gz
(193.76 KB)
📄
libpcre2-16.so.0.7.1.tar
(488.5 KB)
📄
libpcre2-16.so.0.so.0.tar.gz
(193.75 KB)
📄
libpcre2-16.so.0.tar
(488.5 KB)
📄
libpcre2-16.so.so.tar.gz
(193.75 KB)
📄
libpcre2-16.so.tar
(488.5 KB)
📄
libpcre2-32.pc.pc.tar.gz
(330 B)
📄
libpcre2-32.pc.tar
(2 KB)
📄
libpcre2-32.so.0.7.1.so.0.7.1.tar.gz
(184.7 KB)
📄
libpcre2-32.so.0.7.1.tar
(472 KB)
📄
libpcre2-32.so.0.so.0.tar.gz
(184.69 KB)
📄
libpcre2-32.so.0.tar
(472 KB)
📄
libpcre2-32.so.so.tar.gz
(184.69 KB)
📄
libpcre2-32.so.tar
(472 KB)
📄
libpcre2-8.so.0.7.1.so.0.7.1.tar.gz
(209.02 KB)
📄
libpcre2-8.so.0.7.1.tar
(532.5 KB)
📄
libpcre2-8.so.0.so.0.tar.gz
(209.01 KB)
📄
libpcre2-8.so.0.tar
(532.5 KB)
📄
libpcre2-8.so.so.tar.gz
(209.01 KB)
📄
libpcre2-8.so.tar
(532.5 KB)
📄
libpcre2-posix.pc.pc.tar.gz
(286 B)
📄
libpcre2-posix.pc.tar
(2 KB)
📄
libpcre2-posix.so.2.so.2.tar.gz
(4.48 KB)
📄
libpcre2-posix.so.2.tar
(13 KB)
📄
libpcre2-posix.so.so.tar.gz
(4.48 KB)
📄
libpcre2-posix.so.tar
(13 KB)
📄
libpcre32.pc.pc.tar.gz
(317 B)
📄
libpcre32.pc.tar
(2 KB)
📄
libpcre32.so.0.0.10.so.0.0.10.tar.gz
(157.48 KB)
📄
libpcre32.so.0.0.10.tar
(395.5 KB)
📄
libpcre32.so.0.so.0.tar.gz
(157.47 KB)
📄
libpcre32.so.0.tar
(395.5 KB)
📄
libpcre32.so.so.tar.gz
(157.47 KB)
📄
libpcre32.so.tar
(395.5 KB)
📄
libpcrecpp.so.0.0.1.so.0.0.1.tar.gz
(18.24 KB)
📄
libpcrecpp.so.0.0.1.tar
(46.5 KB)
📄
libpcrecpp.so.0.so.0.tar.gz
(18.23 KB)
📄
libpcrecpp.so.0.tar
(46.5 KB)
📄
libpcrecpp.so.so.tar.gz
(18.24 KB)
📄
libpcrecpp.so.tar
(94.5 KB)
📄
libpcreposix.pc.pc.tar.gz
(289 B)
📄
libpcreposix.pc.tar
(2 KB)
📄
libpcreposix.so.0.0.6.so.0.0.6.tar.gz
(4.58 KB)
📄
libpcreposix.so.0.0.6.tar
(13 KB)
📄
libpcreposix.so.0.so.0.tar.gz
(4.58 KB)
📄
libpcreposix.so.0.tar
(13 KB)
📄
libpcreposix.so.so.tar.gz
(4.58 KB)
📄
libpcreposix.so.tar
(13 KB)
📄
libperf-jvmti.so.so.tar.gz
(9.65 KB)
📄
libperf-jvmti.so.tar
(24 KB)
📄
libperl.so.5.26.3.so.5.26.3.tar.gz
(929.91 KB)
📄
libperl.so.5.26.3.tar
(2.08 MB)
📄
libperl.so.5.26.so.5.26.tar.gz
(929.91 KB)
📄
libperl.so.5.26.tar
(2.08 MB)
📄
libperl.so.so.tar.gz
(929.92 KB)
📄
libperl.so.tar
(4.16 MB)
📄
libpipeline.so.1.5.0.so.1.5.0.tar.gz
(28.27 KB)
📄
libpipeline.so.1.5.0.tar
(74 KB)
📄
libpipeline.so.1.so.1.tar.gz
(28.26 KB)
📄
libpipeline.so.1.tar
(74 KB)
📄
libpixman-1.so.0.38.4.so.0.38.4.tar.gz
(285.16 KB)
📄
libpixman-1.so.0.38.4.tar
(681 KB)
📄
libpixman-1.so.0.so.0.tar.gz
(285.15 KB)
📄
libpixman-1.so.0.tar
(681 KB)
📄
libpkcs11.so.so.tar.gz
(38.7 KB)
📄
libpkcs11.so.tar
(94.5 KB)
📄
libpkgconf.so.3.0.0.so.3.0.0.tar.gz
(25.49 KB)
📄
libpkgconf.so.3.0.0.tar
(67.5 KB)
📄
libpkgconf.so.3.so.3.tar.gz
(25.49 KB)
📄
libpkgconf.so.3.tar
(67.5 KB)
📄
libplc4.so.so.tar.gz
(9.47 KB)
📄
libplc4.so.tar
(22.5 KB)
📄
libplds4.so.so.tar.gz
(6.98 KB)
📄
libplds4.so.tar
(18 KB)
📄
libply-boot-client.so.5.0.0.so.5.0.0.tar.gz
(9.25 KB)
📄
libply-boot-client.so.5.0.0.tar
(25.5 KB)
📄
libply-splash-core.so.5.0.0.so.5.0.0.tar.gz
(49.48 KB)
📄
libply-splash-core.so.5.0.0.tar
(142.5 KB)
📄
libply.so.5.0.0.so.5.0.0.tar.gz
(44.95 KB)
📄
libply.so.5.0.0.tar
(115 KB)
📄
libply.so.5.so.5.tar.gz
(44.95 KB)
📄
libply.so.5.tar
(115 KB)
📄
libpmem.so.1.0.0.so.1.0.0.tar.gz
(58.57 KB)
📄
libpmem.so.1.0.0.tar
(224 KB)
📄
libpmem.so.1.so.1.tar.gz
(58.56 KB)
📄
libpmem.so.1.tar
(224 KB)
📄
libpng.pc.pc.tar.gz
(269 B)
📄
libpng.pc.tar
(2 KB)
📄
libpng.so.so.tar.gz
(109.49 KB)
📄
libpng.so.tar
(218 KB)
📄
libpng16.pc.pc.tar.gz
(270 B)
📄
libpng16.pc.tar
(2 KB)
📄
libpng16.so.16.34.0.so.16.34.0.tar.gz
(109.5 KB)
📄
libpng16.so.16.34.0.tar
(218 KB)
📄
libpng16.so.16.so.16.tar.gz
(109.49 KB)
📄
libpng16.so.16.tar
(218 KB)
📄
libpng16.so.so.tar.gz
(109.5 KB)
📄
libpng16.so.tar
(218 KB)
📄
libpng16.tar
(173.5 KB)
📄
libpng16.tar.gz
(47.07 KB)
📄
libpng16.zip
(170.87 KB)
📄
libpolkit-agent-1.so.0.so.0.tar.gz
(17.3 KB)
📄
libpolkit-agent-1.so.0.tar
(46 KB)
📄
libpolkit-gobject-1.so.0.0.0.so.0.0.0.tar.gz
(44.36 KB)
📄
libpolkit-gobject-1.so.0.0.0.tar
(127 KB)
📄
libpolkit-gobject-1.so.0.so.0.tar.gz
(44.36 KB)
📄
libpolkit-gobject-1.so.0.tar
(127 KB)
📄
libpoppler-glib.so.8.19.0.so.8.19.0.tar.gz
(153.97 KB)
📄
libpoppler-glib.so.8.19.0.tar
(426 KB)
📄
libpoppler-glib.so.8.so.8.tar.gz
(153.97 KB)
📄
libpoppler-glib.so.8.tar
(426 KB)
📄
libpoppler.so.104.0.0.so.104.0.0.tar.gz
(1.25 MB)
📄
libpoppler.so.104.0.0.tar
(3.69 MB)
📄
libpoppler.so.104.so.104.tar.gz
(1.25 MB)
📄
libpoppler.so.104.tar
(3.69 MB)
📄
libpopt.so.0.0.1.so.0.0.1.tar.gz
(25.92 KB)
📄
libpopt.so.0.0.1.tar
(55 KB)
📄
libpopt.so.0.so.0.tar.gz
(25.91 KB)
📄
libpopt.so.0.tar
(55 KB)
📄
libpq.so.5.13.so.5.13.tar.gz
(146.81 KB)
📄
libpq.so.5.13.tar
(335 KB)
📄
libpq.so.5.so.5.tar.gz
(146.8 KB)
📄
libpq.so.5.tar
(335 KB)
📄
libpqwalreceiver.so.so.tar.gz
(10.11 KB)
📄
libpqwalreceiver.so.tar
(25.5 KB)
📄
libprocps.so.7.1.0.so.7.1.0.tar.gz
(35.47 KB)
📄
libprocps.so.7.1.0.tar
(83 KB)
📄
libprocps.so.7.so.7.tar.gz
(35.47 KB)
📄
libprocps.so.7.tar
(83 KB)
📄
libprotobuf-c.so.1.0.0.so.1.0.0.tar.gz
(17.72 KB)
📄
libprotobuf-c.so.1.0.0.tar
(37.5 KB)
📄
libprotobuf-c.so.1.so.1.tar.gz
(17.72 KB)
📄
libprotobuf-c.so.1.tar
(37.5 KB)
📄
libprotobuf-c.so.so.tar.gz
(17.72 KB)
📄
libprotobuf-c.so.tar
(37.5 KB)
📄
libprotobuf.so.15.0.0.so.15.0.0.tar.gz
(1.02 MB)
📄
libprotobuf.so.15.0.0.tar
(3.01 MB)
📄
libprotobuf.so.15.so.15.tar.gz
(1.02 MB)
📄
libprotobuf.so.15.tar
(3.01 MB)
📄
libprotoc.so.15.0.0.so.15.0.0.tar.gz
(949.94 KB)
📄
libprotoc.so.15.0.0.tar
(2.78 MB)
📄
libprotoc.so.15.so.15.tar.gz
(949.94 KB)
📄
libprotoc.so.15.tar
(2.78 MB)
📄
libpsl.so.5.3.1.so.5.3.1.tar.gz
(50.94 KB)
📄
libpsl.so.5.3.1.tar
(70 KB)
📄
libpsl.so.5.so.5.tar.gz
(50.94 KB)
📄
libpsl.so.5.tar
(70 KB)
📄
libpspell.so.15.1.5.so.15.1.5.tar.gz
(2.46 KB)
📄
libpspell.so.15.1.5.tar
(9 KB)
📄
libpspell.so.15.so.15.tar.gz
(2.46 KB)
📄
libpspell.so.15.tar
(9 KB)
📄
libpsx.pc.pc.tar.gz
(275 B)
📄
libpsx.pc.tar
(2 KB)
📄
libpsx.so.2.48.so.2.48.tar.gz
(6.45 KB)
📄
libpsx.so.2.48.tar
(18 KB)
📄
libpsx.so.2.so.2.tar.gz
(6.45 KB)
📄
libpsx.so.2.tar
(18 KB)
📄
libpsx.so.so.tar.gz
(6.45 KB)
📄
libpsx.so.tar
(18 KB)
📄
libpthread-2.28.so.28.so.tar.gz
(55.46 KB)
📄
libpthread-2.28.so.tar
(148 KB)
📄
libpthread.so.0.so.0.tar.gz
(55.45 KB)
📄
libpthread.so.0.tar
(148 KB)
📄
libpthread.so.so.tar.gz
(55.45 KB)
📄
libpthread.so.tar
(148 KB)
📄
libpthread_nonshared.a.a.tar.gz
(120 B)
📄
libpthread_nonshared.a.tar
(2 KB)
📄
libpulse-mainloop-glib.so.0.so.0.tar.gz
(7.89 KB)
📄
libpulse-mainloop-glib.so.0.tar
(21.5 KB)
📄
libpulse-simple.so.0.1.1.so.0.1.1.tar.gz
(7.24 KB)
📄
libpulse-simple.so.0.1.1.tar
(21.5 KB)
📄
libpulse-simple.so.0.so.0.tar.gz
(7.23 KB)
📄
libpulse-simple.so.0.tar
(21.5 KB)
📄
libpulse.so.0.23.0.so.0.23.0.tar.gz
(126.84 KB)
📄
libpulse.so.0.23.0.tar
(345.5 KB)
📄
libpulse.so.0.so.0.tar.gz
(126.84 KB)
📄
libpulse.so.0.tar
(345.5 KB)
📄
libpulsecommon-14.0.so.0.so.tar.gz
(217.95 KB)
📄
libpulsecommon-14.0.so.tar
(548 KB)
📄
libpulsedsp.so.so.tar.gz
(20.3 KB)
📄
libpulsedsp.so.tar
(50.5 KB)
📄
libpwquality.so.1.0.2.so.1.0.2.tar.gz
(11.45 KB)
📄
libpwquality.so.1.0.2.tar
(26 KB)
📄
libpwquality.so.1.so.1.tar.gz
(11.45 KB)
📄
libpwquality.so.1.tar
(26 KB)
📄
libpython2.7.so.1.0.7.so.1.0.tar.gz
(732.71 KB)
📄
libpython2.7.so.1.0.tar
(1.8 MB)
📄
libpython2.7.so.7.so.tar.gz
(732.71 KB)
📄
libpython2.7.so.tar
(1.8 MB)
📄
libpython3.6m.so.1.0.6m.so.1.0.tar.gz
(1.42 MB)
📄
libpython3.6m.so.1.0.tar
(3.14 MB)
📄
libpython3.6m.so.6m.so.tar.gz
(1.42 MB)
📄
libpython3.6m.so.tar
(3.14 MB)
📄
libpython3.8.so.1.0.8.so.1.0.tar.gz
(1.61 MB)
📄
libpython3.8.so.1.0.tar
(3.55 MB)
📄
libpython3.8.so.8.so.tar.gz
(1.61 MB)
📄
libpython3.8.so.tar
(3.55 MB)
📄
libpython3.so.so.tar.gz
(2.24 KB)
📄
libpython3.so.tar
(69 KB)
📄
libqjpeg.so.so.tar.gz
(20.32 KB)
📄
libqjpeg.so.tar
(50.5 KB)
📄
libqlinuxfb.so.so.tar.gz
(211.74 KB)
📄
libqlinuxfb.so.tar
(515.5 KB)
📄
libqminimal.so.so.tar.gz
(58.64 KB)
📄
libqminimal.so.tar
(142.5 KB)
📄
libqminimalegl.so.so.tar.gz
(72.92 KB)
📄
libqminimalegl.so.tar
(179.5 KB)
📄
libqquicklayoutsplugin.so.so.tar.gz
(54.33 KB)
📄
libqquicklayoutsplugin.so.tar
(163.5 KB)
📄
libquadmath.so.0.0.0.so.0.0.0.tar.gz
(146.41 KB)
📄
libquadmath.so.0.0.0.tar
(263 KB)
📄
libquadmath.so.0.so.0.tar.gz
(146.41 KB)
📄
libquadmath.so.0.tar
(263 KB)
📄
librabbitmq.so.4.3.0.so.4.3.0.tar.gz
(38.66 KB)
📄
librabbitmq.so.4.3.0.tar
(91.5 KB)
📄
librabbitmq.so.4.so.4.tar.gz
(38.65 KB)
📄
librabbitmq.so.4.tar
(91.5 KB)
📄
libraqm.so.0.700.0.so.0.700.0.tar.gz
(9.8 KB)
📄
libraqm.so.0.700.0.tar
(24.5 KB)
📄
libraqm.so.0.so.0.tar.gz
(9.79 KB)
📄
libraqm.so.0.tar
(45 KB)
📄
libraqm.tar
(23.5 KB)
📄
libraqm.tar.gz
(10.57 KB)
📄
libraqm.zip
(21.21 KB)
📄
library.mk.mk.tar.gz
(700 B)
📄
library.mk.tar
(3 KB)
📄
libraw.so.19.0.2.so.19.0.2.tar.gz
(296.2 KB)
📄
libraw.so.19.0.2.tar
(919.5 KB)
📄
libraw.so.19.so.19.tar.gz
(296.2 KB)
📄
libraw.so.19.tar
(919.5 KB)
📄
libraw_r.so.19.0.2.so.19.0.2.tar.gz
(296.21 KB)
📄
libraw_r.so.19.0.2.tar
(919.5 KB)
📄
libraw_r.so.19.so.19.tar.gz
(296.2 KB)
📄
libraw_r.so.19.tar
(919.5 KB)
📄
libre.tar
(137 KB)
📄
libre.tar.gz
(72.11 KB)
📄
libre.zip
(119.41 KB)
📄
libreadline.so.7.0.so.7.0.tar.gz
(134.98 KB)
📄
libreadline.so.7.0.tar
(332.5 KB)
📄
libreadline.so.7.so.7.tar.gz
(134.98 KB)
📄
libreadline.so.7.tar
(332.5 KB)
📄
librecode.so.0.0.0.so.0.0.0.tar.gz
(770.27 KB)
📄
librecode.so.0.0.0.tar
(1.8 MB)
📄
librecode.so.0.so.0.tar.gz
(770.27 KB)
📄
librecode.so.0.tar
(1.8 MB)
📄
libref_array.so.1.2.1.so.1.2.1.tar.gz
(5.36 KB)
📄
libref_array.so.1.2.1.tar
(13.5 KB)
📄
libref_array.so.1.so.1.tar.gz
(5.35 KB)
📄
libref_array.so.1.tar
(13.5 KB)
📄
librepo.so.0.so.0.tar.gz
(77.29 KB)
📄
librepo.so.0.tar
(184.5 KB)
📄
libresolv-2.28.so.28.so.tar.gz
(44.28 KB)
📄
libresolv-2.28.so.tar
(92.5 KB)
📄
libresolv.so.2.so.2.tar.gz
(44.28 KB)
📄
libresolv.so.2.tar
(92.5 KB)
📄
libresolv.so.so.tar.gz
(44.28 KB)
📄
libresolv.so.tar
(92.5 KB)
📄
librpm.so.8.2.0.so.8.2.0.tar.gz
(229.68 KB)
📄
librpm.so.8.2.0.tar
(525.5 KB)
📄
librpm.so.8.so.8.tar.gz
(229.68 KB)
📄
librpm.so.8.tar
(525.5 KB)
📄
librpmbuild.so.8.2.0.so.8.2.0.tar.gz
(84.64 KB)
📄
librpmbuild.so.8.2.0.tar
(185 KB)
📄
librpmbuild.so.8.so.8.tar.gz
(84.64 KB)
📄
librpmbuild.so.8.tar
(185 KB)
📄
librpmio.so.8.2.0.so.8.2.0.tar.gz
(91.67 KB)
📄
librpmio.so.8.2.0.tar
(204.5 KB)
📄
librpmio.so.8.so.8.tar.gz
(91.67 KB)
📄
librpmio.so.8.tar
(204.5 KB)
📄
librpmsign.so.8.2.0.so.8.2.0.tar.gz
(10.94 KB)
📄
librpmsign.so.8.2.0.tar
(29.5 KB)
📄
librpmsign.so.8.so.8.tar.gz
(10.94 KB)
📄
librpmsign.so.8.tar
(29.5 KB)
📄
librrd.so.8.1.0.so.8.1.0.tar.gz
(165.52 KB)
📄
librrd.so.8.1.0.tar
(375.5 KB)
📄
librrd.so.8.so.8.tar.gz
(165.52 KB)
📄
librrd.so.8.tar
(375.5 KB)
📄
librsvg-2.so.2.42.7.so.2.42.7.tar.gz
(634.79 KB)
📄
librsvg-2.so.2.42.7.tar
(1.53 MB)
📄
librsvg-2.so.2.so.2.tar.gz
(634.79 KB)
📄
librsvg-2.so.2.tar
(1.53 MB)
📄
librt-2.28.so.28.so.tar.gz
(16.89 KB)
📄
librt-2.28.so.tar
(43.5 KB)
📄
librt.so.1.so.1.tar.gz
(16.88 KB)
📄
librt.so.1.tar
(43.5 KB)
📄
librt.so.so.tar.gz
(16.89 KB)
📄
librt.so.tar
(43.5 KB)
📄
libruby.so.2.2.0.so.2.2.0.tar.gz
(1.06 MB)
📄
libruby.so.2.2.0.tar
(2.48 MB)
📄
libruby.so.2.5.9.so.2.5.9.tar.gz
(1.22 MB)
📄
libruby.so.2.5.9.tar
(2.83 MB)
📄
libruby.so.2.5.so.2.5.tar.gz
(1.22 MB)
📄
libruby.so.2.5.tar
(2.83 MB)
📄
libruby.so.so.tar.gz
(1.61 MB)
📄
libruby.so.tar
(44.61 MB)
📄
librxe-rdmav34.so.so.tar.gz
(12.81 KB)
📄
librxe-rdmav34.so.tar
(34 KB)
📄
libsanitizer.spec.spec.tar.gz
(270 B)
📄
libsanitizer.spec.tar
(2 KB)
📄
libsapdbS.so.2.0.0.so.2.0.0.tar.gz
(3.18 KB)
📄
libsapdbS.so.2.0.0.tar
(9.5 KB)
📄
libsapdbS.so.2.so.2.tar.gz
(3.17 KB)
📄
libsapdbS.so.2.tar
(9.5 KB)
📄
libsasl2.pc.pc.tar.gz
(306 B)
📄
libsasl2.pc.tar
(2 KB)
📄
libsasl2.so.3.0.0.so.3.0.0.tar.gz
(57.69 KB)
📄
libsasl2.so.3.0.0.tar
(124 KB)
📄
libsasl2.so.3.so.3.tar.gz
(57.68 KB)
📄
libsasl2.so.3.tar
(124 KB)
📄
libsasl2.so.so.tar.gz
(57.68 KB)
📄
libsasl2.so.tar
(124 KB)
📄
libsasldb.so.3.0.0.so.3.0.0.tar.gz
(12.7 KB)
📄
libsasldb.so.3.0.0.tar
(30 KB)
📄
libsasldb.so.3.so.3.tar.gz
(12.7 KB)
📄
libsasldb.so.3.tar
(30 KB)
📄
libsasldb.so.so.tar.gz
(12.7 KB)
📄
libsasldb.so.tar
(30 KB)
📄
libseccomp.so.2.5.2.so.2.5.2.tar.gz
(51.27 KB)
📄
libseccomp.so.2.5.2.tar
(127.5 KB)
📄
libseccomp.so.2.so.2.tar.gz
(51.26 KB)
📄
libseccomp.so.2.tar
(127.5 KB)
📄
libsecret-1.so.0.0.0.so.0.0.0.tar.gz
(123.69 KB)
📄
libsecret-1.so.0.0.0.tar
(355.5 KB)
📄
libsecret-1.so.0.so.0.tar.gz
(123.69 KB)
📄
libsecret-1.so.0.tar
(355.5 KB)
📄
libsecureio.so.0.9.0.so.0.9.0.tar.gz
(5.68 KB)
📄
libsecureio.so.0.9.0.tar
(35 KB)
📄
libsecureio.so.0.so.0.tar.gz
(5.68 KB)
📄
libsecureio.so.0.tar
(35 KB)
📄
libsecureio.so.1.so.1.tar.gz
(5.68 KB)
📄
libsecureio.so.1.tar
(18 KB)
📄
libsecureio.so.so.tar.gz
(5.68 KB)
📄
libsecureio.so.tar
(35 KB)
📄
libselinux.conf.conf.tar.gz
(137 B)
📄
libselinux.conf.tar
(3 KB)
📄
libselinux.so.1.so.1.tar.gz
(79.08 KB)
📄
libselinux.so.1.tar
(170 KB)
📄
libselinux.so.so.tar.gz
(79.08 KB)
📄
libselinux.so.tar
(170 KB)
📄
libsemanage.so.1.so.1.tar.gz
(108.57 KB)
📄
libsemanage.so.1.tar
(273.5 KB)
📄
libsensors.so.4.4.0.so.4.4.0.tar.gz
(26.83 KB)
📄
libsensors.so.4.4.0.tar
(62.5 KB)
📄
libsensors.so.4.so.4.tar.gz
(26.83 KB)
📄
libsensors.so.4.tar
(62.5 KB)
📄
libsepol.pc.pc.tar.gz
(267 B)
📄
libsepol.pc.tar
(2 KB)
📄
libsepol.so.1.so.1.tar.gz
(315.96 KB)
📄
libsepol.so.1.tar
(719.5 KB)
📄
libsepol.so.so.tar.gz
(315.97 KB)
📄
libsepol.so.tar
(719.5 KB)
📄
libsgutils2.so.2.0.0.so.2.0.0.tar.gz
(96.72 KB)
📄
libsgutils2.so.2.0.0.tar
(255 KB)
📄
libsgutils2.so.2.so.2.tar.gz
(96.72 KB)
📄
libsgutils2.so.2.tar
(255 KB)
📄
libsigsegv.so.2.0.4.so.2.0.4.tar.gz
(6.65 KB)
📄
libsigsegv.so.2.0.4.tar
(19 KB)
📄
libsigsegv.so.2.so.2.tar.gz
(6.65 KB)
📄
libsigsegv.so.2.tar
(19 KB)
📄
libsiw-rdmav34.so.so.tar.gz
(9.45 KB)
📄
libsiw-rdmav34.so.tar
(25.5 KB)
📄
libslang.so.2.3.2.so.2.3.2.tar.gz
(403.3 KB)
📄
libslang.so.2.3.2.tar
(1.25 MB)
📄
libslang.so.2.so.2.tar.gz
(403.29 KB)
📄
libslang.so.2.tar
(1.25 MB)
📄
libslapi-2.4.so.2.10.9.4.so.2.10.9.tar.gz
(55.14 KB)
📄
libslapi-2.4.so.2.10.9.tar
(136 KB)
📄
libslapi-2.4.so.2.4.so.2.tar.gz
(55.13 KB)
📄
libslapi-2.4.so.2.tar
(136 KB)
📄
libslapi.so.so.tar.gz
(55.13 KB)
📄
libslapi.so.tar
(136 KB)
📄
libsmartcols.so.1.1.0.so.1.1.0.tar.gz
(99.68 KB)
📄
libsmartcols.so.1.1.0.tar
(218 KB)
📄
libsmartcols.so.1.so.1.tar.gz
(99.67 KB)
📄
libsmartcols.so.1.tar
(218 KB)
📄
libsmi.so.2.0.27.so.2.0.27.tar.gz
(145.23 KB)
📄
libsmi.so.2.0.27.tar
(493.5 KB)
📄
libsmi.so.2.so.2.tar.gz
(145.22 KB)
📄
libsmi.so.2.tar
(493.5 KB)
📄
libsmime3.so.so.tar.gz
(78.01 KB)
📄
libsmime3.so.tar
(184.5 KB)
📄
libsnappy.so.1.1.8.so.1.1.8.tar.gz
(19.65 KB)
📄
libsnappy.so.1.1.8.tar
(47 KB)
📄
libsnappy.so.1.so.1.tar.gz
(19.65 KB)
📄
libsnappy.so.1.tar
(47 KB)
📄
libsndfile.so.1.0.28.so.1.0.28.tar.gz
(187.74 KB)
📄
libsndfile.so.1.0.28.tar
(461 KB)
📄
libsndfile.so.1.so.1.tar.gz
(187.74 KB)
📄
libsndfile.so.1.tar
(461 KB)
📄
libsnmp.so.35.so.35.tar.gz
(286.99 KB)
📄
libsnmp.so.35.tar
(663.5 KB)
📄
libsnmp.so.so.tar.gz
(286.98 KB)
📄
libsnmp.so.tar
(663.5 KB)
📄
libsodium.so.23.3.0.so.23.3.0.tar.gz
(173.63 KB)
📄
libsodium.so.23.3.0.tar
(358 KB)
📄
libsodium.so.23.so.23.tar.gz
(173.63 KB)
📄
libsodium.so.23.tar
(358 KB)
📄
libsoftokn3.chk.chk.tar.gz
(190 B)
📄
libsoftokn3.chk.tar
(2 KB)
📄
libsoftokn3.so.so.tar.gz
(164.08 KB)
📄
libsoftokn3.so.tar
(378 KB)
📄
libsolv.so.1.so.1.tar.gz
(303.53 KB)
📄
libsolv.so.1.tar
(593.5 KB)
📄
libsolvext.so.1.so.1.tar.gz
(89.43 KB)
📄
libsolvext.so.1.tar
(192.5 KB)
📄
libsqlite3.so.0.8.6.so.0.8.6.tar.gz
(601.03 KB)
📄
libsqlite3.so.0.8.6.tar
(1.1 MB)
📄
libsqlite3.so.0.so.0.tar.gz
(601.02 KB)
📄
libsqlite3.so.0.tar
(1.1 MB)
📄
libsrtp.so.1.0.0.so.1.0.0.tar.gz
(34.66 KB)
📄
libsrtp.so.1.0.0.tar
(90 KB)
📄
libsrtp.so.1.so.1.tar.gz
(34.66 KB)
📄
libsrtp.so.1.tar
(90 KB)
📄
libss.so.2.0.so.2.0.tar.gz
(12.38 KB)
📄
libss.so.2.0.tar
(34 KB)
📄
libss.so.2.so.2.tar.gz
(12.38 KB)
📄
libss.so.2.tar
(34 KB)
📄
libssh.so.4.8.7.so.4.8.7.tar.gz
(204.79 KB)
📄
libssh.so.4.8.7.tar
(459.5 KB)
📄
libssh.so.4.so.4.tar.gz
(204.79 KB)
📄
libssh.so.4.tar
(459.5 KB)
📄
libssh2.so.1.0.1.so.1.0.1.tar.gz
(113.84 KB)
📄
libssh2.so.1.0.1.tar
(261.5 KB)
📄
libssh2.so.1.so.1.tar.gz
(113.84 KB)
📄
libssh2.so.1.tar
(261.5 KB)
📄
libssh2.tar
(382 KB)
📄
libssh2.tar.gz
(144.97 KB)
📄
libssh2.zip
(378.12 KB)
📄
libssh211.tar
(636.5 KB)
📄
libssh211.tar.gz
(248.08 KB)
📄
libssh211.zip
(632.52 KB)
📄
libssh_threads.so.4.so.4.tar.gz
(204.8 KB)
📄
libssh_threads.so.4.tar
(459.5 KB)
📄
libssl.a.a.tar.gz
(219.94 KB)
📄
libssl.a.tar
(731 KB)
📄
libssl.pc.pc.tar.gz
(283 B)
📄
libssl.pc.tar
(2 KB)
📄
libssl.so.1.0.2o.so.1.0.2o.tar.gz
(185.5 KB)
📄
libssl.so.1.0.2o.tar
(450 KB)
📄
libssl.so.1.1.1k.so.1.1.1k.tar.gz
(246.55 KB)
📄
libssl.so.1.1.1k.tar
(607 KB)
📄
libssl.so.1.1.so.1.1.tar.gz
(246.55 KB)
📄
libssl.so.1.1.tar
(607 KB)
📄
libssl.so.10.so.10.tar.gz
(185.49 KB)
📄
libssl.so.10.tar
(450 KB)
📄
libssl.so.11.so.11.tar.gz
(240.16 KB)
📄
libssl.so.11.tar
(595.5 KB)
📄
libssl.so.so.tar.gz
(246.54 KB)
📄
libssl.so.tar
(607 KB)
📄
libssl3.so.so.tar.gz
(199.44 KB)
📄
libssl3.so.tar
(436.5 KB)
📄
libsss_cert.so.so.tar.gz
(6.97 KB)
📄
libsss_cert.so.tar
(21.5 KB)
📄
libsss_certmap.so.0.so.0.tar.gz
(33.55 KB)
📄
libsss_certmap.so.0.tar
(85 KB)
📄
libsss_child.so.so.tar.gz
(10.73 KB)
📄
libsss_child.so.tar
(29.5 KB)
📄
libsss_crypt.so.so.tar.gz
(10.21 KB)
📄
libsss_crypt.so.tar
(26 KB)
📄
libsss_debug.so.so.tar.gz
(10.24 KB)
📄
libsss_debug.so.tar
(26 KB)
📄
libsss_files.so.so.tar.gz
(23.13 KB)
📄
libsss_files.so.tar
(58.5 KB)
📄
libsss_idmap.so.0.5.1.so.0.5.1.tar.gz
(12.14 KB)
📄
libsss_idmap.so.0.5.1.tar
(30 KB)
📄
libsss_idmap.so.0.so.0.tar.gz
(12.13 KB)
📄
libsss_idmap.so.0.tar
(30 KB)
📄
libsss_iface.so.so.tar.gz
(44.38 KB)
📄
libsss_iface.so.tar
(150.5 KB)
📄
libsss_iface_sync.so.so.tar.gz
(22.38 KB)
📄
libsss_iface_sync.so.tar
(66 KB)
📄
libsss_nss_idmap.so.0.6.0.so.0.6.0.tar.gz
(21.09 KB)
📄
libsss_nss_idmap.so.0.6.0.tar
(51.5 KB)
📄
libsss_nss_idmap.so.0.so.0.tar.gz
(21.08 KB)
📄
libsss_nss_idmap.so.0.tar
(51.5 KB)
📄
libsss_sbus.so.so.tar.gz
(97.11 KB)
📄
libsss_sbus.so.tar
(262 KB)
📄
libsss_sbus_sync.so.so.tar.gz
(37.39 KB)
📄
libsss_sbus_sync.so.tar
(100 KB)
📄
libsss_semanage.so.so.tar.gz
(6.15 KB)
📄
libsss_semanage.so.tar
(17.5 KB)
📄
libsss_simple.so.so.tar.gz
(12.05 KB)
📄
libsss_simple.so.tar
(34 KB)
📄
libsss_sudo.so.so.tar.gz
(9.73 KB)
📄
libsss_sudo.so.tar
(22.5 KB)
📄
libsss_util.so.so.tar.gz
(236.22 KB)
📄
libsss_util.so.tar
(581.5 KB)
📄
libstdbuf.so.so.tar.gz
(3.57 KB)
📄
libstdbuf.so.tar
(13.5 KB)
📄
libstdc++.so.6.0.25.so.6.0.25.tar.gz
(510.53 KB)
📄
libstdc++.so.6.0.25.tar
(1.59 MB)
📄
libstdc++.so.6.so.6.tar.gz
(510.52 KB)
📄
libstdc++.so.6.tar
(1.59 MB)
📄
libsubid_sss.so.so.tar.gz
(8.73 KB)
📄
libsubid_sss.so.tar
(22 KB)
📄
libsymlink.attr.attr.tar.gz
(268 B)
📄
libsymlink.attr.tar
(3 KB)
📄
libsysfs.so.2.0.1.so.2.0.1.tar.gz
(18.08 KB)
📄
libsysfs.so.2.0.1.tar
(50.5 KB)
📄
libsysfs.so.2.so.2.tar.gz
(18.08 KB)
📄
libsysfs.so.2.tar
(50.5 KB)
📄
libsystemd-shared-239.so.so.tar.gz
(957.99 KB)
📄
libsystemd-shared-239.so.tar
(2.64 MB)
📄
libsystemd.so.0.23.0.so.0.23.0.tar.gz
(611.54 KB)
📄
libsystemd.so.0.23.0.tar
(1.33 MB)
📄
libsystemd.so.0.so.0.tar.gz
(611.53 KB)
📄
libsystemd.so.0.tar
(1.33 MB)
📄
libsz.so.2.0.1.so.2.0.1.tar.gz
(4.43 KB)
📄
libsz.so.2.0.1.tar
(13.5 KB)
📄
libsz.so.2.so.2.tar.gz
(4.44 KB)
📄
libsz.so.2.tar
(13.5 KB)
📄
libtalloc.so.2.4.1.so.2.4.1.tar.gz
(36.5 KB)
📄
libtalloc.so.2.4.1.tar
(87 KB)
📄
libtalloc.so.2.so.2.tar.gz
(36.49 KB)
📄
libtalloc.so.2.tar
(87 KB)
📄
libtasn1.so.6.5.5.so.6.5.5.tar.gz
(37.82 KB)
📄
libtasn1.so.6.5.5.tar
(78.5 KB)
📄
libtasn1.so.6.so.6.tar.gz
(37.81 KB)
📄
libtasn1.so.6.tar
(78.5 KB)
📄
libtcl8.6.so.6.so.tar.gz
(780.76 KB)
📄
libtcl8.6.so.tar
(1.86 MB)
📄
libtclenvmodules.so.so.tar.gz
(5.18 KB)
📄
libtclenvmodules.so.tar
(13.5 KB)
📄
libtdb.so.1.4.9.so.1.4.9.tar.gz
(45.2 KB)
📄
libtdb.so.1.4.9.tar
(100 KB)
📄
libtdb.so.1.so.1.tar.gz
(45.2 KB)
📄
libtdb.so.1.tar
(100 KB)
📄
libtdsS.so.2.0.0.so.2.0.0.tar.gz
(3.09 KB)
📄
libtdsS.so.2.0.0.tar
(9 KB)
📄
libtdsS.so.2.so.2.tar.gz
(3.09 KB)
📄
libtdsS.so.2.tar
(9 KB)
📄
libtdsS.so.so.tar.gz
(3.09 KB)
📄
libtdsS.so.tar
(9 KB)
📄
libteam.so.5.6.1.so.5.6.1.tar.gz
(23.5 KB)
📄
libteam.so.5.6.1.tar
(58 KB)
📄
libteam.so.5.so.5.tar.gz
(23.5 KB)
📄
libteam.so.5.tar
(58 KB)
📄
libteamdctl.so.0.1.5.so.0.1.5.tar.gz
(10.14 KB)
📄
libteamdctl.so.0.1.5.tar
(25.5 KB)
📄
libteamdctl.so.0.so.0.tar.gz
(10.14 KB)
📄
libteamdctl.so.0.tar
(25.5 KB)
📄
libtemplate.so.2.0.0.so.2.0.0.tar.gz
(53.1 KB)
📄
libtemplate.so.2.0.0.tar
(124 KB)
📄
libtemplate.so.2.so.2.tar.gz
(53.1 KB)
📄
libtemplate.so.2.tar
(124 KB)
📄
libtermcap.so.so.tar.gz
(117 B)
📄
libtermcap.so.tar
(2 KB)
📄
libtevent.so.0.16.0.so.0.16.0.tar.gz
(40.79 KB)
📄
libtevent.so.0.16.0.tar
(95.5 KB)
📄
libtevent.so.0.so.0.tar.gz
(40.78 KB)
📄
libtevent.so.0.tar
(95.5 KB)
📄
libthai.so.0.3.0.so.0.3.0.tar.gz
(18.14 KB)
📄
libthai.so.0.3.0.tar
(51.5 KB)
📄
libthai.so.0.so.0.tar.gz
(18.13 KB)
📄
libthai.so.0.tar
(51.5 KB)
📄
libtheora.so.0.3.10.so.0.3.10.tar.gz
(168.32 KB)
📄
libtheora.so.0.3.10.tar
(313 KB)
📄
libtheora.so.0.so.0.tar.gz
(168.31 KB)
📄
libtheora.so.0.tar
(313 KB)
📄
libtheoradec.so.1.1.4.so.1.1.4.tar.gz
(52.89 KB)
📄
libtheoradec.so.1.1.4.tar
(117 KB)
📄
libtheoradec.so.1.so.1.tar.gz
(52.89 KB)
📄
libtheoradec.so.1.tar
(117 KB)
📄
libtheoraenc.so.1.1.2.so.1.1.2.tar.gz
(135.14 KB)
📄
libtheoraenc.so.1.1.2.tar
(249.5 KB)
📄
libtheoraenc.so.1.so.1.tar.gz
(135.13 KB)
📄
libtheoraenc.so.1.tar
(249.5 KB)
📄
libthread_db-1.0.so.0.so.tar.gz
(15.33 KB)
📄
libthread_db-1.0.so.tar
(39.5 KB)
📄
libthread_db.so.1.so.1.tar.gz
(15.33 KB)
📄
libthread_db.so.1.tar
(39.5 KB)
📄
libthread_db.so.so.tar.gz
(15.33 KB)
📄
libthread_db.so.tar
(39.5 KB)
📄
libtic.so.5.9.so.5.9.tar.gz
(31.39 KB)
📄
libtic.so.5.9.tar
(66.5 KB)
📄
libtic.so.5.so.5.tar.gz
(31.39 KB)
📄
libtic.so.5.tar
(66.5 KB)
📄
libtic.so.6.1.so.6.1.tar.gz
(31.6 KB)
📄
libtic.so.6.1.tar
(66.5 KB)
📄
libtic.so.6.so.6.tar.gz
(31.59 KB)
📄
libtic.so.6.tar
(66.5 KB)
📄
libtic.so.so.tar.gz
(31.59 KB)
📄
libtic.so.tar
(66.5 KB)
📄
libtidy.so.5.6.0.so.5.6.0.tar.gz
(261.81 KB)
📄
libtidy.so.5.6.0.tar
(997 KB)
📄
libtidy.so.5.so.5.tar.gz
(261.8 KB)
📄
libtidy.so.5.tar
(997 KB)
📄
libtidy.tar
(3.18 MB)
📄
libtidy.tar.gz
(873.09 KB)
📄
libtidy.zip
(3.18 MB)
📄
libtiff-4.pc.pc.tar.gz
(274 B)
📄
libtiff-4.pc.tar
(2 KB)
📄
libtiff.so.5.3.0.so.5.3.0.tar.gz
(180.52 KB)
📄
libtiff.so.5.3.0.tar
(496 KB)
📄
libtiff.so.5.so.5.tar.gz
(180.51 KB)
📄
libtiff.so.5.tar
(496 KB)
📄
libtiff.so.so.tar.gz
(180.52 KB)
📄
libtiff.so.tar
(496 KB)
📄
libtiffxx.so.5.3.0.so.5.3.0.tar.gz
(5.03 KB)
📄
libtiffxx.so.5.3.0.tar
(14 KB)
📄
libtiffxx.so.5.so.5.tar.gz
(5.03 KB)
📄
libtiffxx.so.5.tar
(14 KB)
📄
libtiffxx.so.so.tar.gz
(5.03 KB)
📄
libtiffxx.so.tar
(14 KB)
📄
libtinfo.so.5.9.so.5.9.tar.gz
(67.2 KB)
📄
libtinfo.so.5.9.tar
(176.5 KB)
📄
libtinfo.so.5.so.5.tar.gz
(67.19 KB)
📄
libtinfo.so.5.tar
(176.5 KB)
📄
libtinfo.so.6.1.so.6.1.tar.gz
(71.78 KB)
📄
libtinfo.so.6.1.tar
(185 KB)
📄
libtinfo.so.6.so.6.tar.gz
(71.78 KB)
📄
libtinfo.so.6.tar
(185 KB)
📄
libtinfo.so.so.tar.gz
(71.78 KB)
📄
libtinfo.so.tar
(185 KB)
📄
libtirpc.so.3.0.0.so.3.0.0.tar.gz
(97.99 KB)
📄
libtirpc.so.3.0.0.tar
(214.5 KB)
📄
libtirpc.so.3.so.3.tar.gz
(97.99 KB)
📄
libtirpc.so.3.tar
(214.5 KB)
📄
libtk8.6.so.6.so.tar.gz
(629.2 KB)
📄
libtk8.6.so.tar
(1.46 MB)
📄
libtokyocabinet.so.9.11.0.so.9.11.0.tar.gz
(253.17 KB)
📄
libtokyocabinet.so.9.11.0.tar
(553.5 KB)
📄
libtokyocabinet.so.9.so.9.tar.gz
(253.17 KB)
📄
libtokyocabinet.so.9.tar
(553.5 KB)
📄
libtomcrypt.so.1.0.1.so.1.0.1.tar.gz
(437.96 KB)
📄
libtomcrypt.so.1.0.1.tar
(892.5 KB)
📄
libtomcrypt.so.1.so.1.tar.gz
(437.96 KB)
📄
libtomcrypt.so.1.tar
(892.5 KB)
📄
libtommath.so.1.1.0.so.1.1.0.tar.gz
(39.67 KB)
📄
libtommath.so.1.1.0.tar
(87 KB)
📄
libtommath.so.1.so.1.tar.gz
(39.66 KB)
📄
libtommath.so.1.tar
(87 KB)
📄
libtool.tar
(361 KB)
📄
libtool.tar.gz
(88 KB)
📄
libtoolize.tar
(128 KB)
📄
libtoolize.tar.gz
(33.46 KB)
📄
libtraceevent.so.1.5.3.so.1.5.3.tar.gz
(60.06 KB)
📄
libtraceevent.so.1.5.3.tar
(132 KB)
📄
libtraceevent.so.1.so.1.tar.gz
(60.05 KB)
📄
libtraceevent.so.1.tar
(132 KB)
📄
libtspi.so.1.2.0.so.1.2.0.tar.gz
(181.08 KB)
📄
libtspi.so.1.2.0.tar
(475.5 KB)
📄
libtspi.so.1.so.1.tar.gz
(181.08 KB)
📄
libtspi.so.1.tar
(475.5 KB)
📄
libtss2-esys.so.0.0.0.so.0.0.0.tar.gz
(192.5 KB)
📄
libtss2-esys.so.0.0.0.tar
(598 KB)
📄
libtss2-esys.so.0.so.0.tar.gz
(192.5 KB)
📄
libtss2-esys.so.0.tar
(598 KB)
📄
libtss2-mu.so.0.0.0.so.0.0.0.tar.gz
(70.27 KB)
📄
libtss2-mu.so.0.0.0.tar
(286 KB)
📄
libtss2-mu.so.0.so.0.tar.gz
(70.26 KB)
📄
libtss2-mu.so.0.tar
(286 KB)
📄
libtss2-rc.so.0.0.0.so.0.0.0.tar.gz
(7.69 KB)
📄
libtss2-rc.so.0.0.0.tar
(30.5 KB)
📄
libtss2-rc.so.0.so.0.tar.gz
(7.69 KB)
📄
libtss2-rc.so.0.tar
(30.5 KB)
📄
libtss2-sys.so.0.0.0.so.0.0.0.tar.gz
(42.75 KB)
📄
libtss2-sys.so.0.0.0.tar
(142.5 KB)
📄
libtss2-sys.so.0.so.0.tar.gz
(42.75 KB)
📄
libtss2-sys.so.0.tar
(142.5 KB)
📄
libtss2-tcti-device.so.0.0.0.so.0.0.0.tar.gz
(10.76 KB)
📄
libtss2-tcti-device.so.0.0.0.tar
(26 KB)
📄
libtss2-tcti-device.so.0.so.0.tar.gz
(10.76 KB)
📄
libtss2-tcti-device.so.0.tar
(26 KB)
📄
libtss2-tcti-mssim.so.0.0.0.so.0.0.0.tar.gz
(12.17 KB)
📄
libtss2-tcti-mssim.so.0.0.0.tar
(30.5 KB)
📄
libtss2-tctildr.so.0.0.0.so.0.0.0.tar.gz
(13.14 KB)
📄
libtss2-tctildr.so.0.0.0.tar
(30.5 KB)
📄
libtss2-tctildr.so.0.so.0.tar.gz
(13.14 KB)
📄
libtss2-tctildr.so.0.tar
(30.5 KB)
📄
libubsan.so.so.tar.gz
(153 B)
📄
libubsan.so.tar
(2 KB)
📄
libubsec.so.so.tar.gz
(9.75 KB)
📄
libubsec.so.tar
(31 KB)
📄
libudev.so.1.6.11.so.1.6.11.tar.gz
(296.41 KB)
📄
libudev.so.1.6.11.tar
(648.5 KB)
📄
libudev.so.1.so.1.tar.gz
(296.41 KB)
📄
libudev.so.1.tar
(648.5 KB)
📄
libudr_engine.so.so.tar.gz
(595.68 KB)
📄
libudr_engine.so.tar
(1.5 MB)
📄
libulockmgr.so.1.0.1.so.1.0.1.tar.gz
(5.67 KB)
📄
libulockmgr.so.1.0.1.tar
(17.5 KB)
📄
libulockmgr.so.1.so.1.tar.gz
(5.67 KB)
📄
libulockmgr.so.1.tar
(17.5 KB)
📄
libunbound.so.2.7.18.so.2.7.18.tar.gz
(607.35 KB)
📄
libunbound.so.2.7.18.tar
(1.43 MB)
📄
libunbound.so.2.so.2.tar.gz
(607.34 KB)
📄
libunbound.so.2.tar
(1.43 MB)
📄
libunistring.so.2.1.0.so.2.1.0.tar.gz
(619.17 KB)
📄
libunistring.so.2.1.0.tar
(1.72 MB)
📄
libunistring.so.2.so.2.tar.gz
(619.17 KB)
📄
libunistring.so.2.tar
(1.72 MB)
📄
libusb-1.0.so.0.0.so.0.tar.gz
(50.21 KB)
📄
libusb-1.0.so.0.2.0.0.so.0.2.0.tar.gz
(50.22 KB)
📄
libusb-1.0.so.0.2.0.tar
(111 KB)
📄
libusb-1.0.so.0.tar
(111 KB)
📄
libuser.so.1.5.2.so.1.5.2.tar.gz
(55.13 KB)
📄
libuser.so.1.5.2.tar
(135.5 KB)
📄
libuser.so.1.so.1.tar.gz
(55.13 KB)
📄
libuser.so.1.tar
(135.5 KB)
📄
libuser.tar
(148 KB)
📄
libuser.tar.gz
(58.81 KB)
📄
libuser.zip
(145.2 KB)
📄
libuser_files.so.so.tar.gz
(19.42 KB)
📄
libuser_files.so.tar
(50 KB)
📄
libuser_shadow.so.so.tar.gz
(19.42 KB)
📄
libuser_shadow.so.tar
(50 KB)
📄
libutempter.so.0.so.0.tar.gz
(3.97 KB)
📄
libutempter.so.0.tar
(13.5 KB)
📄
libutempter.so.1.1.6.so.1.1.6.tar.gz
(3.97 KB)
📄
libutempter.so.1.1.6.tar
(13.5 KB)
📄
libutil-2.28.so.28.so.tar.gz
(5.61 KB)
📄
libutil-2.28.so.tar
(18.5 KB)
📄
libutil.so.1.so.1.tar.gz
(5.61 KB)
📄
libutil.so.1.tar
(18.5 KB)
📄
libutil.so.so.tar.gz
(5.61 KB)
📄
libutil.so.tar
(18.5 KB)
📄
libuuid.so.1.3.0.so.1.3.0.tar.gz
(15.9 KB)
📄
libuuid.so.1.3.0.tar
(34.5 KB)
📄
libuuid.so.1.so.1.tar.gz
(15.91 KB)
📄
libuuid.so.1.tar
(34.5 KB)
📄
libuuid.so.so.tar.gz
(15.91 KB)
📄
libuuid.so.tar
(34.5 KB)
📄
libverto-libev.so.1.so.1.tar.gz
(4.67 KB)
📄
libverto-libev.so.1.tar
(13.5 KB)
📄
libverto.pc.pc.tar.gz
(255 B)
📄
libverto.pc.tar
(2 KB)
📄
libverto.so.1.0.0.so.1.0.0.tar.gz
(10.57 KB)
📄
libverto.so.1.0.0.tar
(26 KB)
📄
libverto.so.1.so.1.tar.gz
(10.57 KB)
📄
libverto.so.1.tar
(26 KB)
📄
libverto.so.so.tar.gz
(10.57 KB)
📄
libverto.so.tar
(26 KB)
📄
libvgauth.so.0.0.0.so.0.0.0.tar.gz
(36.25 KB)
📄
libvgauth.so.0.0.0.tar
(98.5 KB)
📄
libvgauth.so.0.so.0.tar.gz
(36.25 KB)
📄
libvgauth.so.0.tar
(98.5 KB)
📄
libvips-cpp.so.42.so.42.tar.gz
(84.29 KB)
📄
libvips-cpp.so.42.tar
(275 KB)
📄
libvips.so.42.18.1.so.42.18.1.tar.gz
(1.54 MB)
📄
libvips.so.42.18.1.tar
(3.32 MB)
📄
libvirt-tls.xml.tar
(2 KB)
📄
libvirt-tls.xml.xml.tar.gz
(359 B)
📄
libvirt.xml.tar
(2 KB)
📄
libvirt.xml.xml.tar.gz
(363 B)
📄
libvisual-0.4.so.0.0.0.4.so.0.0.0.tar.gz
(112.16 KB)
📄
libvisual-0.4.so.0.0.0.tar
(281 KB)
📄
libvisual-0.4.so.0.4.so.0.tar.gz
(112.16 KB)
📄
libvisual-0.4.so.0.tar
(281 KB)
📄
libvmtools.so.0.0.0.so.0.0.0.tar.gz
(265.24 KB)
📄
libvmtools.so.0.0.0.tar
(706.5 KB)
📄
libvmtools.so.0.so.0.tar.gz
(265.24 KB)
📄
libvmtools.so.0.tar
(706.5 KB)
📄
libvorbis.so.0.4.8.so.0.4.8.tar.gz
(101.25 KB)
📄
libvorbis.so.0.4.8.tar
(190.5 KB)
📄
libvorbis.so.0.so.0.tar.gz
(101.25 KB)
📄
libvorbis.so.0.tar
(190.5 KB)
📄
libvorbisenc.so.2.0.11.so.2.0.11.tar.gz
(104.02 KB)
📄
libvorbisenc.so.2.0.11.tar
(677.5 KB)
📄
libvorbisenc.so.2.so.2.tar.gz
(104.02 KB)
📄
libvorbisenc.so.2.tar
(677.5 KB)
📄
libvorbisfile.so.3.3.7.so.3.3.7.tar.gz
(17.01 KB)
📄
libvorbisfile.so.3.3.7.tar
(38 KB)
📄
libvorbisfile.so.3.so.3.tar.gz
(17 KB)
📄
libvorbisfile.so.3.tar
(38 KB)
📄
libvpx.so.5.0.0.so.5.0.0.tar.gz
(935.14 KB)
📄
libvpx.so.5.0.0.tar
(2.21 MB)
📄
libvpx.so.5.0.so.5.0.tar.gz
(935.24 KB)
📄
libvpx.so.5.0.tar
(2.21 MB)
📄
libvpx.so.5.so.5.tar.gz
(935.14 KB)
📄
libvpx.so.5.tar
(2.21 MB)
📄
libwacom.so.2.6.1.so.2.6.1.tar.gz
(21.68 KB)
📄
libwacom.so.2.6.1.tar
(54.5 KB)
📄
libwacom.so.2.so.2.tar.gz
(21.67 KB)
📄
libwacom.so.2.tar
(54.5 KB)
📄
libwayland-client.so.0.21.0.so.0.21.0.tar.gz
(27.34 KB)
📄
libwayland-client.so.0.21.0.tar
(71.5 KB)
📄
libwayland-client.so.0.so.0.tar.gz
(27.34 KB)
📄
libwayland-client.so.0.tar
(71.5 KB)
📄
libwayland-cursor.so.0.21.0.so.0.21.0.tar.gz
(9.89 KB)
📄
libwayland-cursor.so.0.21.0.tar
(34 KB)
📄
libwayland-cursor.so.0.so.0.tar.gz
(9.89 KB)
📄
libwayland-cursor.so.0.tar
(34 KB)
📄
libwayland-egl.so.1.21.0.so.1.21.0.tar.gz
(2.93 KB)
📄
libwayland-egl.so.1.21.0.tar
(9 KB)
📄
libwayland-egl.so.1.so.1.tar.gz
(2.93 KB)
📄
libwayland-egl.so.1.tar
(9 KB)
📄
libwayland-server.so.0.21.0.so.0.21.0.tar.gz
(36.3 KB)
📄
libwayland-server.so.0.21.0.tar
(92 KB)
📄
libwayland-server.so.0.so.0.tar.gz
(36.29 KB)
📄
libwayland-server.so.0.tar
(92 KB)
📄
libwebp.pc.pc.tar.gz
(260 B)
📄
libwebp.pc.tar
(2 KB)
📄
libwebp.so.7.0.2.so.7.0.2.tar.gz
(225.74 KB)
📄
libwebp.so.7.0.2.tar
(442 KB)
📄
libwebp.so.7.so.7.tar.gz
(225.74 KB)
📄
libwebp.so.7.tar
(442 KB)
📄
libwebp.so.so.tar.gz
(225.74 KB)
📄
libwebp.so.tar
(442 KB)
📄
libwebp.tar
(1.04 MB)
📄
libwebp.tar.gz
(490.73 KB)
📄
libwebp.zip
(1.03 MB)
📄
libwebpdecoder.pc.pc.tar.gz
(279 B)
📄
libwebpdecoder.pc.tar
(2 KB)
📄
libwebpdecoder.so.3.so.3.tar.gz
(109.75 KB)
📄
libwebpdecoder.so.3.tar
(234.5 KB)
📄
libwebpdecoder.so.so.tar.gz
(109.76 KB)
📄
libwebpdecoder.so.tar
(234.5 KB)
📄
libwebpdemux.pc.pc.tar.gz
(277 B)
📄
libwebpdemux.pc.tar
(2 KB)
📄
libwebpdemux.so.2.0.4.so.2.0.4.tar.gz
(9.26 KB)
📄
libwebpdemux.so.2.0.4.tar
(22 KB)
📄
libwebpdemux.so.2.so.2.tar.gz
(9.26 KB)
📄
libwebpdemux.so.2.tar
(22 KB)
📄
libwebpdemux.so.so.tar.gz
(9.27 KB)
📄
libwebpdemux.so.tar
(22 KB)
📄
libwebpmux.so.3.0.2.so.3.0.2.tar.gz
(21.27 KB)
📄
libwebpmux.so.3.0.2.tar
(42.5 KB)
📄
libwebpmux.so.3.so.3.tar.gz
(21.27 KB)
📄
libwebpmux.so.3.tar
(42.5 KB)
📄
libwebpmux.so.so.tar.gz
(21.27 KB)
📄
libwebpmux.so.tar
(42.5 KB)
📄
libwireshark.so.11.1.2.so.11.1.2.tar.gz
(18.53 MB)
📄
libwireshark.so.11.1.2.tar
(78.63 MB)
📄
libwireshark.so.11.so.11.tar.gz
(18.53 MB)
📄
libwireshark.so.11.tar
(78.63 MB)
📄
libwiretap.so.8.0.2.so.8.0.2.tar.gz
(206 KB)
📄
libwiretap.so.8.0.2.tar
(467.5 KB)
📄
libwiretap.so.8.so.8.tar.gz
(205.99 KB)
📄
libwiretap.so.8.tar
(467.5 KB)
📄
libwmf-0.2.so.7.1.1.2.so.7.1.1.tar.gz
(110.31 KB)
📄
libwmf-0.2.so.7.1.1.tar
(354.5 KB)
📄
libwmf-0.2.so.7.2.so.7.tar.gz
(110.3 KB)
📄
libwmf-0.2.so.7.tar
(354.5 KB)
📄
libwmflite-0.2.so.7.2.so.7.tar.gz
(55.59 KB)
📄
libwmflite-0.2.so.7.tar
(129 KB)
📄
libwscodecs.so.2.0.0.so.2.0.0.tar.gz
(13.71 KB)
📄
libwscodecs.so.2.0.0.tar
(31 KB)
📄
libwscodecs.so.2.so.2.tar.gz
(13.71 KB)
📄
libwscodecs.so.2.tar
(31 KB)
📄
libwsutil.so.9.0.0.so.9.0.0.tar.gz
(60.93 KB)
📄
libwsutil.so.9.0.0.tar
(136 KB)
📄
libwsutil.so.9.so.9.tar.gz
(60.93 KB)
📄
libwsutil.so.9.tar
(136 KB)
📄
libx265.so.176.so.176.tar.gz
(777.61 KB)
📄
libx265.so.176.tar
(4.57 MB)
📄
libx265_main10.so.176.so.176.tar.gz
(774.15 KB)
📄
libx265_main10.so.176.tar
(5.51 MB)
📄
libx265_main12.so.176.so.176.tar.gz
(763.06 KB)
📄
libx265_main12.so.176.tar
(5.44 MB)
📄
libxcb-composite.so.0.0.0.so.0.0.0.tar.gz
(4.07 KB)
📄
libxcb-composite.so.0.0.0.tar
(20 KB)
📄
libxcb-composite.so.0.so.0.tar.gz
(4.07 KB)
📄
libxcb-composite.so.0.tar
(20 KB)
📄
libxcb-composite.so.so.tar.gz
(4.07 KB)
📄
libxcb-composite.so.tar
(20 KB)
📄
libxcb-damage.so.0.0.0.so.0.0.0.tar.gz
(3.8 KB)
📄
libxcb-damage.so.0.0.0.tar
(15.5 KB)
📄
libxcb-damage.so.0.so.0.tar.gz
(3.79 KB)
📄
libxcb-damage.so.0.tar
(15.5 KB)
📄
libxcb-damage.so.so.tar.gz
(3.8 KB)
📄
libxcb-damage.so.tar
(15.5 KB)
📄
libxcb-dpms.so.0.0.0.so.0.0.0.tar.gz
(4.06 KB)
📄
libxcb-dpms.so.0.0.0.tar
(16 KB)
📄
libxcb-dpms.so.0.so.0.tar.gz
(4.06 KB)
📄
libxcb-dpms.so.0.tar
(16 KB)
📄
libxcb-dpms.so.so.tar.gz
(4.06 KB)
📄
libxcb-dpms.so.tar
(16 KB)
📄
libxcb-dri2.so.0.0.0.so.0.0.0.tar.gz
(6.09 KB)
📄
libxcb-dri2.so.0.0.0.tar
(26.5 KB)
📄
libxcb-dri2.so.0.so.0.tar.gz
(6.09 KB)
📄
libxcb-dri2.so.0.tar
(26.5 KB)
📄
libxcb-dri2.so.so.tar.gz
(6.09 KB)
📄
libxcb-dri2.so.tar
(26.5 KB)
📄
libxcb-dri3.so.0.0.0.so.0.0.0.tar.gz
(5.76 KB)
📄
libxcb-dri3.so.0.0.0.tar
(25.5 KB)
📄
libxcb-dri3.so.0.so.0.tar.gz
(5.76 KB)
📄
libxcb-dri3.so.0.tar
(25.5 KB)
📄
libxcb-dri3.so.so.tar.gz
(5.77 KB)
📄
libxcb-dri3.so.tar
(25.5 KB)
📄
libxcb-ewmh.so.2.0.0.so.2.0.0.tar.gz
(16.28 KB)
📄
libxcb-ewmh.so.2.0.0.tar
(53.5 KB)
📄
libxcb-ewmh.so.2.so.2.tar.gz
(16.28 KB)
📄
libxcb-ewmh.so.2.tar
(53.5 KB)
📄
libxcb-glx.so.0.0.0.so.0.0.0.tar.gz
(26.42 KB)
📄
libxcb-glx.so.0.0.0.tar
(147 KB)
📄
libxcb-glx.so.0.so.0.tar.gz
(26.42 KB)
📄
libxcb-glx.so.0.tar
(147 KB)
📄
libxcb-glx.so.so.tar.gz
(26.42 KB)
📄
libxcb-glx.so.tar
(147 KB)
📄
libxcb-icccm.so.4.0.0.so.4.0.0.tar.gz
(7.45 KB)
📄
libxcb-icccm.so.4.0.0.tar
(25 KB)
📄
libxcb-icccm.so.4.so.4.tar.gz
(7.45 KB)
📄
libxcb-icccm.so.4.tar
(25 KB)
📄
libxcb-image.so.0.0.0.so.0.0.0.tar.gz
(8.75 KB)
📄
libxcb-image.so.0.0.0.tar
(21.5 KB)
📄
libxcb-image.so.0.so.0.tar.gz
(8.75 KB)
📄
libxcb-image.so.0.tar
(21.5 KB)
📄
libxcb-keysyms.so.1.so.1.tar.gz
(4.87 KB)
📄
libxcb-keysyms.so.1.tar
(13.5 KB)
📄
libxcb-present.so.0.so.0.tar.gz
(4.49 KB)
📄
libxcb-present.so.0.tar
(16.5 KB)
📄
libxcb-present.so.so.tar.gz
(4.5 KB)
📄
libxcb-present.so.tar
(16.5 KB)
📄
libxcb-randr.so.0.1.0.so.0.1.0.tar.gz
(18.15 KB)
📄
libxcb-randr.so.0.1.0.tar
(91 KB)
📄
libxcb-randr.so.0.so.0.tar.gz
(18.14 KB)
📄
libxcb-randr.so.0.tar
(91 KB)
📄
libxcb-randr.so.so.tar.gz
(18.15 KB)
📄
libxcb-randr.so.tar
(91 KB)
📄
libxcb-record.so.0.0.0.so.0.0.0.tar.gz
(6.22 KB)
📄
libxcb-record.so.0.0.0.tar
(27 KB)
📄
libxcb-record.so.0.so.0.tar.gz
(6.22 KB)
📄
libxcb-record.so.0.tar
(27 KB)
📄
libxcb-record.so.so.tar.gz
(6.22 KB)
📄
libxcb-record.so.tar
(27 KB)
📄
libxcb-render-util.so.0.0.0.so.0.0.0.tar.gz
(6.64 KB)
📄
libxcb-render-util.so.0.0.0.tar
(18.5 KB)
📄
libxcb-render.so.0.0.0.so.0.0.0.tar.gz
(15.93 KB)
📄
libxcb-render.so.0.0.0.tar
(73.5 KB)
📄
libxcb-render.so.0.so.0.tar.gz
(15.93 KB)
📄
libxcb-render.so.0.tar
(73.5 KB)
📄
libxcb-render.so.so.tar.gz
(15.93 KB)
📄
libxcb-render.so.tar
(73.5 KB)
📄
libxcb-res.so.0.0.0.so.0.0.0.tar.gz
(5.56 KB)
📄
libxcb-res.so.0.0.0.tar
(22.5 KB)
📄
libxcb-res.so.0.so.0.tar.gz
(5.56 KB)
📄
libxcb-res.so.0.tar
(22.5 KB)
📄
libxcb-res.so.so.tar.gz
(5.56 KB)
📄
libxcb-res.so.tar
(22.5 KB)
📄
libxcb-screensaver.so.0.0.0.so.0.0.0.tar.gz
(5.21 KB)
📄
libxcb-screensaver.so.0.0.0.tar
(20 KB)
📄
libxcb-screensaver.so.so.tar.gz
(5.21 KB)
📄
libxcb-screensaver.so.tar
(20 KB)
📄
libxcb-shape.so.0.0.0.so.0.0.0.tar.gz
(5.02 KB)
📄
libxcb-shape.so.0.0.0.tar
(21 KB)
📄
libxcb-shape.so.0.so.0.tar.gz
(5.02 KB)
📄
libxcb-shape.so.0.tar
(21 KB)
📄
libxcb-shape.so.so.tar.gz
(5.02 KB)
📄
libxcb-shape.so.tar
(21 KB)
📄
libxcb-shm.so.0.0.0.so.0.0.0.tar.gz
(4.69 KB)
📄
libxcb-shm.so.0.0.0.tar
(20.5 KB)
📄
libxcb-shm.so.0.so.0.tar.gz
(4.69 KB)
📄
libxcb-shm.so.0.tar
(20.5 KB)
📄
libxcb-shm.so.so.tar.gz
(4.69 KB)
📄
libxcb-shm.so.tar
(20.5 KB)
📄
libxcb-sync.so.1.0.0.so.1.0.0.tar.gz
(8.5 KB)
📄
libxcb-sync.so.1.0.0.tar
(36.5 KB)
📄
libxcb-sync.so.1.so.1.tar.gz
(8.5 KB)
📄
libxcb-sync.so.1.tar
(36.5 KB)
📄
libxcb-sync.so.so.tar.gz
(8.5 KB)
📄
libxcb-sync.so.tar
(36.5 KB)
📄
libxcb-util.so.1.0.0.so.1.0.0.tar.gz
(8.53 KB)
📄
libxcb-util.so.1.0.0.tar
(26.5 KB)
📄
libxcb-util.so.1.so.1.tar.gz
(8.53 KB)
📄
libxcb-util.so.1.tar
(26.5 KB)
📄
libxcb-xf86dri.so.0.so.0.tar.gz
(5.59 KB)
📄
libxcb-xf86dri.so.0.tar
(26 KB)
📄
libxcb-xf86dri.so.so.tar.gz
(5.59 KB)
📄
libxcb-xf86dri.so.tar
(26 KB)
📄
libxcb-xfixes.so.0.0.0.so.0.0.0.tar.gz
(8.87 KB)
📄
libxcb-xfixes.so.0.0.0.tar
(42 KB)
📄
libxcb-xfixes.so.0.so.0.tar.gz
(8.87 KB)
📄
libxcb-xfixes.so.0.tar
(42 KB)
📄
libxcb-xfixes.so.so.tar.gz
(8.87 KB)
📄
libxcb-xfixes.so.tar
(42 KB)
📄
libxcb-xinerama.so.0.0.0.so.0.0.0.tar.gz
(4.14 KB)
📄
libxcb-xinerama.so.0.0.0.tar
(16.5 KB)
📄
libxcb-xinerama.so.0.so.0.tar.gz
(4.14 KB)
📄
libxcb-xinerama.so.0.tar
(16.5 KB)
📄
libxcb-xinerama.so.so.tar.gz
(4.14 KB)
📄
libxcb-xinerama.so.tar
(16.5 KB)
📄
libxcb-xinput.so.0.1.0.so.0.1.0.tar.gz
(39.32 KB)
📄
libxcb-xinput.so.0.1.0.tar
(185.5 KB)
📄
libxcb-xinput.so.0.so.0.tar.gz
(39.32 KB)
📄
libxcb-xinput.so.0.tar
(185.5 KB)
📄
libxcb-xinput.so.so.tar.gz
(39.32 KB)
📄
libxcb-xinput.so.tar
(185.5 KB)
📄
libxcb-xkb.so.1.0.0.so.1.0.0.tar.gz
(34.18 KB)
📄
libxcb-xkb.so.1.0.0.tar
(150.5 KB)
📄
libxcb-xkb.so.1.so.1.tar.gz
(34.17 KB)
📄
libxcb-xkb.so.1.tar
(150.5 KB)
📄
libxcb-xkb.so.so.tar.gz
(34.17 KB)
📄
libxcb-xkb.so.tar
(150.5 KB)
📄
libxcb-xselinux.so.0.0.0.so.0.0.0.tar.gz
(9.32 KB)
📄
libxcb-xselinux.so.0.0.0.tar
(48.5 KB)
📄
libxcb-xselinux.so.0.so.0.tar.gz
(9.32 KB)
📄
libxcb-xselinux.so.0.tar
(48.5 KB)
📄
libxcb-xselinux.so.so.tar.gz
(9.32 KB)
📄
libxcb-xselinux.so.tar
(48.5 KB)
📄
libxcb-xtest.so.0.0.0.so.0.0.0.tar.gz
(3.69 KB)
📄
libxcb-xtest.so.0.0.0.tar
(15.5 KB)
📄
libxcb-xtest.so.0.so.0.tar.gz
(3.69 KB)
📄
libxcb-xtest.so.0.tar
(15.5 KB)
📄
libxcb-xtest.so.so.tar.gz
(3.69 KB)
📄
libxcb-xtest.so.tar
(15.5 KB)
📄
libxcb-xv.so.0.0.0.so.0.0.0.tar.gz
(9.18 KB)
📄
libxcb-xv.so.0.0.0.tar
(42.5 KB)
📄
libxcb-xv.so.0.so.0.tar.gz
(9.18 KB)
📄
libxcb-xv.so.0.tar
(42.5 KB)
📄
libxcb-xv.so.so.tar.gz
(9.19 KB)
📄
libxcb-xv.so.tar
(42.5 KB)
📄
libxcb-xvmc.so.0.0.0.so.0.0.0.tar.gz
(5.32 KB)
📄
libxcb-xvmc.so.0.0.0.tar
(22 KB)
📄
libxcb-xvmc.so.0.so.0.tar.gz
(5.32 KB)
📄
libxcb-xvmc.so.0.tar
(22 KB)
📄
libxcb-xvmc.so.so.tar.gz
(5.32 KB)
📄
libxcb-xvmc.so.tar
(22 KB)
📄
libxcb.so.1.1.0.so.1.1.0.tar.gz
(53.28 KB)
📄
libxcb.so.1.1.0.tar
(232 KB)
📄
libxcb.so.1.so.1.tar.gz
(53.27 KB)
📄
libxcb.so.1.tar
(232 KB)
📄
libxcb.so.so.tar.gz
(53.28 KB)
📄
libxcb.so.tar
(232 KB)
📄
libxcrypt.pc.pc.tar.gz
(298 B)
📄
libxcrypt.pc.tar
(2 KB)
📄
libxdot.so.4.0.0.so.4.0.0.tar.gz
(10.02 KB)
📄
libxdot.so.4.0.0.tar
(25.5 KB)
📄
libxdot.so.4.so.4.tar.gz
(10.02 KB)
📄
libxdot.so.4.tar
(25.5 KB)
📄
libxkbcommon-x11.so.0.0.0.so.0.0.0.tar.gz
(14.24 KB)
📄
libxkbcommon-x11.so.0.0.0.tar
(46.5 KB)
📄
libxkbcommon-x11.so.0.so.0.tar.gz
(14.24 KB)
📄
libxkbcommon-x11.so.0.tar
(46.5 KB)
📄
libxkbcommon.so.0.0.0.so.0.0.0.tar.gz
(120.57 KB)
📄
libxkbcommon.so.0.0.0.tar
(336.5 KB)
📄
libxkbcommon.so.0.so.0.tar.gz
(120.57 KB)
📄
libxkbcommon.so.0.tar
(336.5 KB)
📄
libxml.tar
(455.5 KB)
📄
libxml.tar.gz
(80.83 KB)
📄
libxml.zip
(425.65 KB)
📄
libxml2-2.0.typelib.0.typelib.tar.gz
(389 B)
📄
libxml2-2.0.typelib.tar
(2.5 KB)
📄
libxml2.so.2.9.7.so.2.9.7.tar.gz
(672.54 KB)
📄
libxml2.so.2.9.7.tar
(1.44 MB)
📄
libxml2.so.2.so.2.tar.gz
(672.53 KB)
📄
libxml2.so.2.tar
(1.44 MB)
📄
libxml2.so.so.tar.gz
(672.53 KB)
📄
libxml2.so.tar
(1.44 MB)
📄
libxml2.tar
(6.78 MB)
📄
libxml2.tar.gz
(684 B)
📄
libxml2.zip
(6.62 MB)
📄
libxmlrpc.so.3.51.so.3.51.tar.gz
(47.56 KB)
📄
libxmlrpc.so.3.51.tar
(111 KB)
📄
libxmlrpc.so.3.so.3.tar.gz
(47.55 KB)
📄
libxmlrpc.so.3.tar
(111 KB)
📄
libxmlrpc_abyss.so.3.so.3.tar.gz
(55.24 KB)
📄
libxmlrpc_abyss.so.3.tar
(128.5 KB)
📄
libxmlrpc_openssl.so.1.51.so.1.51.tar.gz
(3.07 KB)
📄
libxmlrpc_openssl.so.1.51.tar
(9 KB)
📄
libxmlrpc_openssl.so.1.so.1.tar.gz
(3.07 KB)
📄
libxmlrpc_openssl.so.1.tar
(9 KB)
📄
libxmlrpc_server.so.3.51.so.3.51.tar.gz
(12.91 KB)
📄
libxmlrpc_server.so.3.51.tar
(34 KB)
📄
libxmlrpc_server.so.3.so.3.tar.gz
(12.91 KB)
📄
libxmlrpc_server.so.3.tar
(34 KB)
📄
libxmlrpc_server_abyss.so.3.51.so.3.51.tar.gz
(12.78 KB)
📄
libxmlrpc_server_abyss.so.3.51.tar
(34 KB)
📄
libxmlrpc_server_abyss.so.3.so.3.tar.gz
(12.77 KB)
📄
libxmlrpc_server_abyss.so.3.tar
(34 KB)
📄
libxmlrpc_server_cgi.so.3.51.so.3.51.tar.gz
(5.53 KB)
📄
libxmlrpc_server_cgi.so.3.51.tar
(17.5 KB)
📄
libxmlrpc_server_cgi.so.3.so.3.tar.gz
(5.53 KB)
📄
libxmlrpc_server_cgi.so.3.tar
(17.5 KB)
📄
libxmlrpc_util.so.4.51.so.4.51.tar.gz
(12.66 KB)
📄
libxmlrpc_util.so.4.51.tar
(30 KB)
📄
libxmlrpc_util.so.4.so.4.tar.gz
(12.65 KB)
📄
libxmlrpc_util.so.4.tar
(30 KB)
📄
libxmlrpc_xmltok.so.3.51.so.3.51.tar.gz
(51.85 KB)
📄
libxmlrpc_xmltok.so.3.51.tar
(179.5 KB)
📄
libxmlrpc_xmltok.so.3.so.3.tar.gz
(51.85 KB)
📄
libxmlrpc_xmltok.so.3.tar
(179.5 KB)
📄
libxmlsec1-openssl.so.1.2.25.so.1.2.25.tar.gz
(99.02 KB)
📄
libxmlsec1-openssl.so.1.2.25.tar
(283.5 KB)
📄
libxmlsec1-openssl.so.so.tar.gz
(99.02 KB)
📄
libxmlsec1-openssl.so.tar
(283.5 KB)
📄
libxmlsec1.so.1.2.25.so.1.2.25.tar.gz
(162.3 KB)
📄
libxmlsec1.so.1.2.25.tar
(444 KB)
📄
libxmlsec1.so.1.so.1.tar.gz
(162.3 KB)
📄
libxmlsec1.so.1.tar
(444 KB)
📄
libxshmfence.so.1.0.0.so.1.0.0.tar.gz
(3.66 KB)
📄
libxshmfence.so.1.0.0.tar
(14 KB)
📄
libxshmfence.so.1.so.1.tar.gz
(3.65 KB)
📄
libxshmfence.so.1.tar
(14 KB)
📄
libxslt.pc.pc.tar.gz
(258 B)
📄
libxslt.pc.tar
(2 KB)
📄
libxslt.so.1.1.32.so.1.1.32.tar.gz
(116.35 KB)
📄
libxslt.so.1.1.32.tar
(268.5 KB)
📄
libxslt.so.1.so.1.tar.gz
(116.35 KB)
📄
libxslt.so.1.tar
(268.5 KB)
📄
libxslt.so.so.tar.gz
(116.34 KB)
📄
libxslt.so.tar
(268.5 KB)
📄
libxslt.tar
(129 KB)
📄
libxslt.tar.gz
(24.19 KB)
📄
libxslt.zip
(114.92 KB)
📄
libxt_AUDIT.so.so.tar.gz
(3.57 KB)
📄
libxt_AUDIT.so.tar
(13.5 KB)
📄
libxt_CHECKSUM.so.so.tar.gz
(3.2 KB)
📄
libxt_CHECKSUM.so.tar
(9.5 KB)
📄
libxt_CLASSIFY.so.so.tar.gz
(3.83 KB)
📄
libxt_CLASSIFY.so.tar
(14 KB)
📄
libxt_CONNMARK.so.so.tar.gz
(6.2 KB)
📄
libxt_CONNMARK.so.tar
(18 KB)
📄
libxt_CONNSECMARK.so.so.tar.gz
(3.54 KB)
📄
libxt_CONNSECMARK.so.tar
(13.5 KB)
📄
libxt_CT.so.so.tar.gz
(6.11 KB)
📄
libxt_CT.so.tar
(19 KB)
📄
libxt_DSCP.so.so.tar.gz
(4.26 KB)
📄
libxt_DSCP.so.tar
(14 KB)
📄
libxt_HMARK.so.so.tar.gz
(5.91 KB)
📄
libxt_HMARK.so.tar
(18 KB)
📄
libxt_LED.so.so.tar.gz
(3.91 KB)
📄
libxt_LED.so.tar
(13.5 KB)
📄
libxt_MARK.so.so.tar.gz
(5.33 KB)
📄
libxt_MARK.so.tar
(18.5 KB)
📄
libxt_NFLOG.so.so.tar.gz
(4.23 KB)
📄
libxt_NFLOG.so.tar
(13.5 KB)
📄
libxt_NFQUEUE.so.so.tar.gz
(4.96 KB)
📄
libxt_NFQUEUE.so.tar
(18 KB)
📄
libxt_NOTRACK.so.so.tar.gz
(6.11 KB)
📄
libxt_NOTRACK.so.tar
(19 KB)
📄
libxt_RATEEST.so.so.tar.gz
(4.44 KB)
📄
libxt_RATEEST.so.tar
(13.5 KB)
📄
libxt_SECMARK.so.so.tar.gz
(3.52 KB)
📄
libxt_SECMARK.so.tar
(14 KB)
📄
libxt_SET.so.so.tar.gz
(7.87 KB)
📄
libxt_SET.so.tar
(22.5 KB)
📄
libxt_SYNPROXY.so.so.tar.gz
(3.86 KB)
📄
libxt_SYNPROXY.so.tar
(13.5 KB)
📄
libxt_TCPOPTSTRIP.so.so.tar.gz
(4.48 KB)
📄
libxt_TCPOPTSTRIP.so.tar
(13.5 KB)
📄
libxt_TEE.so.so.tar.gz
(3.81 KB)
📄
libxt_TEE.so.tar
(14 KB)
📄
libxt_TOS.so.so.tar.gz
(4.88 KB)
📄
libxt_TOS.so.tar
(14 KB)
📄
libxt_TRACE.so.so.tar.gz
(2.86 KB)
📄
libxt_TRACE.so.tar
(9.5 KB)
📄
libxt_addrtype.so.so.tar.gz
(5.58 KB)
📄
libxt_addrtype.so.tar
(18 KB)
📄
libxt_bpf.so.so.tar.gz
(5.14 KB)
📄
libxt_bpf.so.tar
(14 KB)
📄
libxt_cluster.so.so.tar.gz
(4.21 KB)
📄
libxt_cluster.so.tar
(13.5 KB)
📄
libxt_comment.so.so.tar.gz
(3.48 KB)
📄
libxt_comment.so.tar
(13.5 KB)
📄
libxt_connbytes.so.so.tar.gz
(4.49 KB)
📄
libxt_connbytes.so.tar
(13.5 KB)
📄
libxt_connmark.so.so.tar.gz
(3.94 KB)
📄
libxt_connmark.so.tar
(14 KB)
📄
libxt_cpu.so.so.tar.gz
(3.29 KB)
📄
libxt_cpu.so.tar
(9.5 KB)
📄
libxt_dccp.so.so.tar.gz
(5.66 KB)
📄
libxt_dccp.so.tar
(17.5 KB)
📄
libxt_devgroup.so.so.tar.gz
(4.53 KB)
📄
libxt_devgroup.so.tar
(13.5 KB)
📄
libxt_dscp.so.so.tar.gz
(4.31 KB)
📄
libxt_dscp.so.tar
(13.5 KB)
📄
libxt_ecn.so.so.tar.gz
(3.99 KB)
📄
libxt_ecn.so.tar
(13.5 KB)
📄
libxt_esp.so.so.tar.gz
(3.66 KB)
📄
libxt_esp.so.tar
(13.5 KB)
📄
libxt_iprange.so.so.tar.gz
(5.94 KB)
📄
libxt_iprange.so.tar
(18 KB)
📄
libxt_ipvs.so.so.tar.gz
(5.02 KB)
📄
libxt_ipvs.so.tar
(14 KB)
📄
libxt_limit.so.so.tar.gz
(5 KB)
📄
libxt_limit.so.tar
(14 KB)
📄
libxt_mac.so.so.tar.gz
(3.6 KB)
📄
libxt_mac.so.tar
(13.5 KB)
📄
libxt_mark.so.so.tar.gz
(3.86 KB)
📄
libxt_mark.so.tar
(13.5 KB)
📄
libxt_nfacct.so.so.tar.gz
(3.41 KB)
📄
libxt_nfacct.so.tar
(13.5 KB)
📄
libxt_osf.so.so.tar.gz
(3.77 KB)
📄
libxt_osf.so.tar
(13.5 KB)
📄
libxt_owner.so.so.tar.gz
(6.33 KB)
📄
libxt_owner.so.tar
(18 KB)
📄
libxt_physdev.so.so.tar.gz
(3.88 KB)
📄
libxt_physdev.so.tar
(13.5 KB)
📄
libxt_pkttype.so.so.tar.gz
(4.04 KB)
📄
libxt_pkttype.so.tar
(13.5 KB)
📄
libxt_quota.so.so.tar.gz
(3.33 KB)
📄
libxt_quota.so.tar
(9.5 KB)
📄
libxt_rateest.so.so.tar.gz
(6 KB)
📄
libxt_rateest.so.tar
(17.5 KB)
📄
libxt_rpfilter.so.so.tar.gz
(3.87 KB)
📄
libxt_rpfilter.so.tar
(13.5 KB)
📄
libxt_sctp.so.so.tar.gz
(7.82 KB)
📄
libxt_sctp.so.tar
(21.5 KB)
📄
libxt_set.so.so.tar.gz
(8.6 KB)
📄
libxt_set.so.tar
(26.5 KB)
📄
libxt_standard.so.so.tar.gz
(2.89 KB)
📄
libxt_standard.so.tar
(9.5 KB)
📄
libxt_state.so.so.tar.gz
(12.42 KB)
📄
libxt_state.so.tar
(36 KB)
📄
libxt_tcp.so.so.tar.gz
(6.54 KB)
📄
libxt_tcp.so.tar
(17.5 KB)
📄
libxt_time.so.so.tar.gz
(7.43 KB)
📄
libxt_time.so.tar
(21.5 KB)
📄
libxt_tos.so.so.tar.gz
(4.17 KB)
📄
libxt_tos.so.tar
(14 KB)
📄
libxt_u32.so.so.tar.gz
(4.98 KB)
📄
libxt_u32.so.tar
(13.5 KB)
📄
libxt_udp.so.so.tar.gz
(4.34 KB)
📄
libxt_udp.so.tar
(13.5 KB)
📄
libxtables.so.12.3.0.so.12.3.0.tar.gz
(27.19 KB)
📄
libxtables.so.12.3.0.tar
(62.5 KB)
📄
libxtables.so.12.so.12.tar.gz
(27.19 KB)
📄
libxtables.so.12.tar
(62.5 KB)
📄
libyajl.so.2.1.0.so.2.1.0.tar.gz
(18.39 KB)
📄
libyajl.so.2.1.0.tar
(42.5 KB)
📄
libyajl.so.2.so.2.tar.gz
(18.39 KB)
📄
libyajl.so.2.tar
(42.5 KB)
📄
libyaml-0.so.2.0.5.so.2.0.5.tar.gz
(53.62 KB)
📄
libyaml-0.so.2.0.5.tar
(133 KB)
📄
libyaml-0.so.2.so.2.tar.gz
(53.61 KB)
📄
libyaml-0.so.2.tar
(133 KB)
📄
libyara.so.9.0.1.so.9.0.1.tar.gz
(198.4 KB)
📄
libyara.so.9.0.1.tar
(447 KB)
📄
libyara.so.9.so.9.tar.gz
(198.4 KB)
📄
libyara.so.9.tar
(447 KB)
📄
libyaz.so.5.0.0.so.5.0.0.tar.gz
(515.33 KB)
📄
libyaz.so.5.0.0.tar
(2.13 MB)
📄
libyaz.so.5.so.5.tar.gz
(515.33 KB)
📄
libyaz.so.5.tar
(2.13 MB)
📄
libyaz_icu.so.5.0.0.so.5.0.0.tar.gz
(25.02 KB)
📄
libyaz_icu.so.5.0.0.tar
(92.5 KB)
📄
libyaz_icu.so.5.so.5.tar.gz
(25.02 KB)
📄
libyaz_icu.so.5.tar
(92.5 KB)
📄
libyaz_server.so.5.0.0.so.5.0.0.tar.gz
(35.92 KB)
📄
libyaz_server.so.5.0.0.tar
(100 KB)
📄
libyaz_server.so.5.so.5.tar.gz
(35.91 KB)
📄
libyaz_server.so.5.tar
(100 KB)
📄
libz.so.1.2.11.so.1.2.11.tar.gz
(51.39 KB)
📄
libz.so.1.2.11.tar
(99 KB)
📄
libz.so.1.so.1.tar.gz
(51.39 KB)
📄
libz.so.1.tar
(99 KB)
📄
libz.so.so.tar.gz
(51.39 KB)
📄
libz.so.tar
(99 KB)
📄
libzip.so.5.0.so.5.0.tar.gz
(51.45 KB)
📄
libzip.so.5.0.tar
(108.5 KB)
📄
libzip.so.5.so.5.tar.gz
(51.45 KB)
📄
libzip.so.5.tar
(108.5 KB)
📄
libzip.tar
(137 KB)
📄
libzip.tar.gz
(64.14 KB)
📄
libzip.zip
(135.04 KB)
📄
libzstd.so.1.4.4.so.1.4.4.tar.gz
(288.81 KB)
📄
libzstd.so.1.4.4.tar
(664.5 KB)
📄
libzstd.so.1.so.1.tar.gz
(288.8 KB)
📄
libzstd.so.1.tar
(664.5 KB)
📄
license.html.html.tar.gz
(520 B)
📄
license.html.tar
(2.5 KB)
📄
license.txt.tar
(5 KB)
📄
license.txt.txt.tar.gz
(130 B)
📄
licenses.tar
(45 KB)
📄
licenses.tar.gz
(13.99 KB)
📄
licenses.zip
(42.95 KB)
📄
life.pyc.pyc.tar.gz
(2.97 KB)
📄
life.pyc.tar
(8.5 KB)
📄
life.pyo.pyo.tar.gz
(2.97 KB)
📄
life.pyo.tar
(8.5 KB)
📄
lightning-bolt.svg.svg.tar.gz
(755 B)
📄
lightning-bolt.svg.tar
(3 KB)
📄
lima_drm.h.h.tar.gz
(1.65 KB)
📄
lima_drm.h.tar
(6.5 KB)
📄
lime.png.png.tar.gz
(13.93 KB)
📄
lime.png.tar
(16 KB)
📄
lime.sql.sql.tar.gz
(11.71 KB)
📄
lime.sql.tar
(93.5 KB)
📄
lime.tar
(110.92 MB)
📄
lime.tar.gz
(104.59 MB)
📄
lime.zip
(110.89 MB)
📄
lime3.tar
(287 KB)
📄
lime3.tar.gz
(155.21 KB)
📄
lime3.zip
(258.56 KB)
📄
lime5.sql.sql.tar.gz
(11.4 KB)
📄
lime5.sql.tar
(92.5 KB)
📄
lime5.tar
(88.12 MB)
📄
lime5.tar.gz
(82.75 MB)
📄
lime5.zip
(88.09 MB)
📄
limits.h.h.tar.gz
(2.01 KB)
📄
limits.h.tar
(7 KB)
📄
limits.tar
(11 KB)
📄
limits.tar.gz
(398 B)
📄
linecache.py.py.tar.gz
(1.75 KB)
📄
linecache.py.tar
(17.5 KB)
📄
link.h.h.tar.gz
(2.94 KB)
📄
link.h.tar
(15.5 KB)
📄
link.tar
(35 KB)
📄
link.tar.gz
(14.93 KB)
📄
link_lavcurrent.h.h.tar.gz
(726 B)
📄
link_lavcurrent.h.tar
(3 KB)
📄
linktree.pyc.pyc.tar.gz
(1.08 KB)
📄
linktree.pyc.tar
(3.5 KB)
📄
linktree.pyo.pyo.tar.gz
(1.08 KB)
📄
linktree.pyo.tar
(3.5 KB)
📄
linux.mod.mod.tar.gz
(5.85 KB)
📄
linux.mod.tar
(28 KB)
📄
linux.tar
(4.58 MB)
📄
linux.tar.gz
(585 B)
📄
linux.zip
(4.14 MB)
📄
linuxx64.efi.stub.efi.stub.tar.gz
(25.03 KB)
📄
linuxx64.efi.stub.tar
(60 KB)
📄
lio_210nv_nic.bin.bin.tar.gz
(482.38 KB)
📄
lio_210nv_nic.bin.tar
(1.22 MB)
📄
lio_210sv_nic.bin.bin.tar.gz
(457.96 KB)
📄
lio_210sv_nic.bin.tar
(1.13 MB)
📄
lio_23xx_nic.bin.bin.tar.gz
(486.34 KB)
📄
lio_23xx_nic.bin.tar
(1.23 MB)
📄
lio_410nv_nic.bin.bin.tar.gz
(482.38 KB)
📄
lio_410nv_nic.bin.tar
(1.22 MB)
📄
liquidio.tar
(4.8 MB)
📄
liquidio.tar.gz
(1.86 MB)
📄
liquidio.zip
(4.8 MB)
📄
list.go.go.tar.gz
(783 B)
📄
list.go.tar
(3 KB)
📄
listener.h.h.tar.gz
(2.62 KB)
📄
listener.h.tar
(9 KB)
📄
listobject.h.h.tar.gz
(1.18 KB)
📄
listobject.h.tar
(4.5 KB)
📄
litecart.tar
(2.24 MB)
📄
litecart.tar.gz
(1.87 MB)
📄
litecart.zip
(2.21 MB)
📄
litespeed-wp-plugin.tar
(145.31 MB)
📄
litespeed-wp-plugin.tar.gz
(55.29 MB)
📄
litespeed-wp-plugin.zip
(142.43 MB)
📄
litespeed.tar
(7.33 MB)
📄
litespeed.tar.gz
(7.33 MB)
📄
litespeed_status.tar
(2 KB)
📄
litespeed_status.tar.gz
(114 B)
📄
litforum.tar
(1.61 MB)
📄
litforum.tar.gz
(1.41 MB)
📄
litforum.zip
(1.59 MB)
📄
little.tar
(97 KB)
📄
little.tar.gz
(55.06 KB)
📄
little.zip
(83 KB)
📄
livehelper.tar
(70.77 MB)
📄
livehelper.tar.gz
(66.56 MB)
📄
livehelper.zip
(70.74 MB)
📄
livesite.tar
(140.5 KB)
📄
livesite.tar.gz
(75.36 KB)
📄
livesite.zip
(120.01 KB)
📄
lll.py.py.tar.gz
(496 B)
📄
lll.py.tar
(2.5 KB)
📄
lll.pyc.pyc.tar.gz
(591 B)
📄
lll.pyc.tar
(2.5 KB)
📄
lll.pyo.pyo.tar.gz
(591 B)
📄
lll.pyo.tar
(2.5 KB)
📄
llmnr.xml.tar
(2 KB)
📄
llmnr.xml.xml.tar.gz
(311 B)
📄
lmnet.so.so.tar.gz
(12.77 KB)
📄
lmnet.so.tar
(30.5 KB)
📄
lmnetstrms.so.so.tar.gz
(8.09 KB)
📄
lmnetstrms.so.tar
(25 KB)
📄
lmnsd_ptcp.so.so.tar.gz
(12.46 KB)
📄
lmnsd_ptcp.so.tar
(33 KB)
📄
lmregexp.so.so.tar.gz
(5.94 KB)
📄
lmregexp.so.tar
(17.5 KB)
📄
lmtcpclt.so.so.tar.gz
(5.5 KB)
📄
lmtcpclt.so.tar
(13.5 KB)
📄
lmtcpsrv.so.so.tar.gz
(16.91 KB)
📄
lmtcpsrv.so.tar
(42 KB)
📄
lmzlibw.so.so.tar.gz
(3.81 KB)
📄
lmzlibw.so.tar
(13.5 KB)
📄
ln.tar
(73 KB)
📄
ln.tar.gz
(33.84 KB)
📄
lnl_gsc_1.bin.bin.tar.gz
(1.08 MB)
📄
lnl_gsc_1.bin.tar
(2.22 MB)
📄
lnl_guc_70.bin.bin.tar.gz
(195.1 KB)
📄
lnl_guc_70.bin.tar
(668 KB)
📄
lnl_huc.bin.bin.tar.gz
(218.25 KB)
📄
lnl_huc.bin.tar
(1.23 MB)
📄
lnxboot.image.image.tar.gz
(1.11 KB)
📄
lnxboot.image.tar
(8 KB)
📄
lnxboot.img.img.tar.gz
(476 B)
📄
lnxboot.img.tar
(2.5 KB)
📄
lo.tar
(49 KB)
📄
lo.tar.gz
(782 B)
📄
lo.zip
(6.76 KB)
📄
loadavg.tar
(2 KB)
📄
loadavg.tar.gz
(122 B)
📄
loaded7.tar
(160.5 KB)
📄
loaded7.tar.gz
(89.17 KB)
📄
loaded7.zip
(141.3 KB)
📄
loadenv.mod.mod.tar.gz
(3.55 KB)
📄
loadenv.mod.tar
(9.5 KB)
📄
loader.fw.fw.tar.gz
(1.26 KB)
📄
loader.fw.tar
(6 KB)
📄
loader.py.py.tar.gz
(5.82 KB)
📄
loader.py.tar
(24 KB)
📄
loaders.tar
(2.5 KB)
📄
loaders.tar.gz
(522 B)
📄
loadmodules.service.service.tar.gz
(336 B)
📄
loadmodules.service.tar
(2 KB)
📄
local-eval.go.go.tar.gz
(13.33 KB)
📄
local-eval.go.tar
(41.5 KB)
📄
local-fs-pre.target.tar
(2 KB)
📄
local-fs-pre.target.target.tar.gz
(395 B)
📄
local-fs.target.tar
(2.5 KB)
📄
local-fs.target.target.tar.gz
(453 B)
📄
local.php.php.tar.gz
(535 B)
📄
local.php.tar
(3.5 KB)
📄
local.xml.tar
(4 KB)
📄
local.xml.xml.tar.gz
(999 B)
📄
local_lim.h.h.tar.gz
(1.41 KB)
📄
local_lim.h.tar
(5 KB)
📄
localconf.php.php.tar.gz
(794 B)
📄
localconf.php.tar
(3.5 KB)
📄
locale-archive.tar
(207.72 MB)
📄
locale-archive.tar.gz
(49.1 MB)
📄
locale-archive.tmpl.tar
(2 KB)
📄
locale-archive.tmpl.tmpl.tar.gz
(102 B)
📄
locale.h.h.tar.gz
(2.64 KB)
📄
locale.h.tar
(11 KB)
📄
locale.py.py.tar.gz
(16.37 KB)
📄
locale.py.tar
(255 KB)
📄
locale.pyc.pyc.tar.gz
(20.85 KB)
📄
locale.pyc.tar
(57 KB)
📄
locale.pyo.pyo.tar.gz
(20.85 KB)
📄
locale.pyo.tar
(57 KB)
📄
locale.rb.rb.tar.gz
(1.72 KB)
📄
locale.rb.tar
(38 KB)
📄
locale.tar
(271.79 MB)
📄
locale.tar.gz
(64.8 MB)
📄
locale.zip
(271.44 MB)
📄
locale_t.h.h.tar.gz
(628 B)
📄
locale_t.h.tar
(2.5 KB)
📄
localedef.tar
(309 KB)
📄
localedef.tar.gz
(133.88 KB)
📄
locales.conf.conf.tar.gz
(259 B)
📄
locales.conf.tar
(2 KB)
📄
localrentandbuy.com.tar
(11.22 MB)
📄
localrentandbuy.com.tar.gz
(1.51 MB)
📄
localrentandbuy.com.zip
(10.98 MB)
📄
localtime.tar
(5 KB)
📄
localtime.tar.gz
(1.74 KB)
📄
locdspnm.h.h.tar.gz
(1.55 KB)
📄
locdspnm.h.tar
(9 KB)
📄
locid.h.h.tar.gz
(9.45 KB)
📄
locid.h.tar
(46.5 KB)
📄
lockd.tar
(2 KB)
📄
lockd.tar.gz
(96 B)
📄
lockd.zip
(163 B)
📄
locked_extensions.ini.ini.tar.gz
(158 B)
📄
locked_extensions.ini.tar
(9 KB)
📄
locktime.tar
(7 KB)
📄
locktime.tar.gz
(117 B)
📄
log.py.py.tar.gz
(197 B)
📄
log.py.tar
(10 KB)
📄
log.pyc.pyc.tar.gz
(2.47 KB)
📄
log.pyc.tar
(7 KB)
📄
log.pyo.pyo.tar.gz
(2.47 KB)
📄
log.pyo.tar
(7 KB)
📄
log_martians.tar
(2 KB)
📄
log_martians.tar.gz
(121 B)
📄
logaholic.tar
(167.5 KB)
📄
logaholic.tar.gz
(87.13 KB)
📄
logaholic.zip
(142.5 KB)
📄
logedin.inc.inc.tar.gz
(2.09 KB)
📄
logedin.inc.tar
(7.5 KB)
📄
logger.tar
(51.5 KB)
📄
logger.tar.gz
(21.98 KB)
📄
logging.tar
(1.04 MB)
📄
logging.tar.gz
(169.43 KB)
📄
logging.zip
(1.02 MB)
📄
logic.tar
(187.5 KB)
📄
logic.tar.gz
(109.86 KB)
📄
logic.zip
(166.87 KB)
📄
login.tar
(42.5 KB)
📄
login.tar.gz
(18.06 KB)
📄
loginuid.tar
(8 KB)
📄
loginuid.tar.gz
(111 B)
📄
logmerge.pyc.pyc.tar.gz
(2.66 KB)
📄
logmerge.pyc.tar
(6.5 KB)
📄
logmerge.pyo.pyo.tar.gz
(2.66 KB)
📄
logmerge.pyo.tar
(6.5 KB)
📄
logname.tar
(35 KB)
📄
logname.tar.gz
(14.77 KB)
📄
logo-orange.png.png.tar.gz
(3.39 KB)
📄
logo-orange.png.tar
(9 KB)
📄
logo.82bd2bb6.svg.82bd2bb6.svg.tar.gz
(2.65 KB)
📄
logo.82bd2bb6.svg.tar
(7.5 KB)
📄
logo.gif.gif.tar.gz
(3.4 KB)
📄
logo.gif.tar
(986.5 KB)
📄
logo.jpg.jpg.tar.gz
(4.24 KB)
📄
logo.jpg.tar
(57 KB)
📄
logo.png.png.tar.gz
(10.45 KB)
📄
logo.png.tar
(147 KB)
📄
logs.tar
(47.91 MB)
📄
logs.tar.gz
(47.07 MB)
📄
logs.zip
(47.84 MB)
📄
long-double.h.h.tar.gz
(606 B)
📄
long-double.h.tar
(2.5 KB)
📄
long-double.ph.ph.tar.gz
(164 B)
📄
long-double.ph.tar
(2 KB)
📄
longobject.h.h.tar.gz
(3.02 KB)
📄
longobject.h.tar
(11 KB)
📄
look.tar
(18 KB)
📄
look.tar.gz
(6.3 KB)
📄
lookups.tar
(2 KB)
📄
lookups.tar.gz
(119 B)
📄
loop.c.c.tar.gz
(523 B)
📄
loop.c.tar
(2.5 KB)
📄
loopback.mod.mod.tar.gz
(1.89 KB)
📄
loopback.mod.tar
(5.5 KB)
📄
lpwatch.py.py.tar.gz
(1.14 KB)
📄
lpwatch.py.tar
(4.5 KB)
📄
lr192.fw.fw.tar.gz
(3.91 KB)
📄
lr192.fw.tar
(7.5 KB)
📄
ls.go.go.tar.gz
(1.31 KB)
📄
ls.go.tar
(4.5 KB)
📄
ls.mod.mod.tar.gz
(2.09 KB)
📄
ls.mod.tar
(11 KB)
📄
ls.tar
(147 KB)
📄
ls.tar.gz
(65.84 KB)
📄
lsacpi.mod.mod.tar.gz
(2.57 KB)
📄
lsacpi.mod.tar
(14 KB)
📄
lsapi-cache.service.service.tar.gz
(314 B)
📄
lsapi-cache.service.tar
(2 KB)
📄
lsapm.mod.mod.tar.gz
(1.29 KB)
📄
lsapm.mod.tar
(8 KB)
📄
lscgid.6.2.1.6.2.1.tar.gz
(34.18 KB)
📄
lscgid.6.2.1.tar
(80 KB)
📄
lscgid.6.2.2.6.2.2.tar.gz
(34.25 KB)
📄
lscgid.6.2.2.tar
(80 KB)
📄
lscgid.6.3.1.6.3.1.tar.gz
(77.21 KB)
📄
lscgid.6.3.1.tar
(208 KB)
📄
lscgid.6.3.2.6.3.2.tar.gz
(90.97 KB)
📄
lscgid.6.3.2.tar
(243 KB)
📄
lscgid.6.3.3.6.3.3.tar.gz
(91.15 KB)
📄
lscgid.6.3.3.tar
(243 KB)
📄
lscgid.6.3.4.6.3.4.tar.gz
(91.53 KB)
📄
lscgid.6.3.4.tar
(243 KB)
📄
lscgid.tar
(243 KB)
📄
lscgid.tar.gz
(91.52 KB)
📄
lscmctl.tar
(17 KB)
📄
lscmctl.tar.gz
(4.43 KB)
📄
lscwp_versions_v2.tar
(3 KB)
📄
lscwp_versions_v2.tar.gz
(471 B)
📄
lshttpd.6.3.4.6.3.4.tar.gz
(7.33 MB)
📄
lshttpd.6.3.4.tar
(7.33 MB)
📄
lshttpd.service.service.tar.gz
(464 B)
📄
lshttpd.service.tar
(2.5 KB)
📄
lshttpd.tar
(7.33 MB)
📄
lshttpd.tar.gz
(7.33 MB)
📄
lsmmap.mod.mod.tar.gz
(1006 B)
📄
lsmmap.mod.tar
(6 KB)
📄
lsnode.js.js.tar.gz
(1.16 KB)
📄
lsnode.js.tar
(4.5 KB)
📄
lspci.mod.mod.tar.gz
(2.36 KB)
📄
lspci.mod.tar
(13 KB)
📄
lsphp.cagefs.cagefs.tar.gz
(2.39 MB)
📄
lsphp.cagefs.tar
(7.74 MB)
📄
lsphp.tar
(41.42 MB)
📄
lsphp.tar.gz
(94 B)
📄
lsphp4.tar
(4.72 MB)
📄
lsphp4.tar.gz
(1.7 MB)
📄
lsphp7.tar
(5.92 MB)
📄
lsphp7.tar.gz
(1.96 MB)
📄
lsrecaptcha.tar
(11.96 MB)
📄
lsrecaptcha.tar.gz
(6.33 MB)
📄
lsrecaptcha.zip
(11.96 MB)
📄
lss.png.png.tar.gz
(4.22 KB)
📄
lss.png.tar
(6 KB)
📄
lss.tar
(263.5 KB)
📄
lss.tar.gz
(159.48 KB)
📄
lss.zip
(239.21 KB)
📄
lsup.sh.sh.tar.gz
(1.8 KB)
📄
lsup.sh.tar
(7.5 KB)
📄
lsup6.sh.sh.tar.gz
(1.8 KB)
📄
lsup6.sh.tar
(7.5 KB)
📄
lsws.rc.rc.tar.gz
(722 B)
📄
lsws.rc.tar
(3.5 KB)
📄
lsws.service.service.tar.gz
(466 B)
📄
lsws.service.tar
(2.5 KB)
📄
lsws_logo.png.png.tar.gz
(16.36 KB)
📄
lsws_logo.png.tar
(18.5 KB)
📄
lsws_whm_plugin.tar
(14 KB)
📄
lsws_whm_plugin.tar.gz
(3.12 KB)
📄
lsws_whm_plugin.zip
(12.5 KB)
📄
lswsctrl.6.2.1.6.2.1.tar.gz
(1.86 KB)
📄
lswsctrl.6.2.1.tar
(8 KB)
📄
lswsctrl.6.2.2.6.2.2.tar.gz
(1.86 KB)
📄
lswsctrl.6.2.2.tar
(8 KB)
📄
lswsctrl.6.3.1.6.3.1.tar.gz
(1.86 KB)
📄
lswsctrl.6.3.1.tar
(8 KB)
📄
lswsctrl.6.3.2.6.3.2.tar.gz
(1.88 KB)
📄
lswsctrl.6.3.2.tar
(8 KB)
📄
lswsctrl.6.3.3.6.3.3.tar.gz
(1.88 KB)
📄
lswsctrl.6.3.3.tar
(8 KB)
📄
lswsctrl.6.3.4.6.3.4.tar.gz
(1.88 KB)
📄
lswsctrl.6.3.4.tar
(8 KB)
📄
lswsctrl.tar
(8 KB)
📄
lswsctrl.tar.gz
(1.87 KB)
📄
lswsgi.tar
(877 KB)
📄
lswsgi.tar.gz
(40.58 KB)
📄
lt9611uxc_fw.bin.bin.tar.gz
(9.62 KB)
📄
lt9611uxc_fw.bin.tar
(19.5 KB)
📄
lt_dlloader.h.h.tar.gz
(1.42 KB)
📄
lt_dlloader.h.tar
(5 KB)
📄
lt_error.h.h.tar.gz
(1.75 KB)
📄
lt_error.h.tar
(5.5 KB)
📄
lt_system.h.h.tar.gz
(2.32 KB)
📄
lt_system.h.tar
(7 KB)
📄
ltdl.h.h.tar.gz
(2.12 KB)
📄
ltdl.h.tar
(7.5 KB)
📄
ltlib.mk.mk.tar.gz
(660 B)
📄
ltlib.mk.tar
(2.5 KB)
📄
lto1.tar
(25.55 MB)
📄
lto1.tar.gz
(11.05 MB)
📄
lua-5.1.pc.1.pc.tar.gz
(266 B)
📄
lua-5.1.pc.tar
(2 KB)
📄
lua-5.1.tar
(45 KB)
📄
lua-5.1.tar.gz
(12.02 KB)
📄
lua-5.1.zip
(40.53 KB)
📄
lua.h.h.tar.gz
(3.44 KB)
📄
lua.h.tar
(13 KB)
📄
lua.hpp.hpp.tar.gz
(222 B)
📄
lua.hpp.tar
(2 KB)
📄
lualib.h.h.tar.gz
(502 B)
📄
lualib.h.tar
(3 KB)
📄
luks.mod.mod.tar.gz
(3.83 KB)
📄
luks.mod.tar
(19 KB)
📄
luxcal.sql.sql.tar.gz
(5.04 KB)
📄
luxcal.sql.tar
(21 KB)
📄
luxcal.tar
(4.22 MB)
📄
luxcal.tar.gz
(4.08 MB)
📄
luxcal.zip
(4.2 MB)
📄
lve.service.service.tar.gz
(346 B)
📄
lve.service.tar
(3 KB)
📄
lve.tar
(2.58 MB)
📄
lve.tar.gz
(883.2 KB)
📄
lve.zip
(2.57 MB)
📄
lve_namespaces.service.service.tar.gz
(325 B)
📄
lve_namespaces.service.tar
(2 KB)
📄
lvectl.service.service.tar.gz
(337 B)
📄
lvectl.service.tar
(2 KB)
📄
lveinfo.ver.cagefs.tar
(2 KB)
📄
lveinfo.ver.cagefs.tar.gz
(97 B)
📄
lveinfo.ver.cagefs.zip
(160 B)
📄
lveinfo.ver.tar
(2 KB)
📄
lveinfo.ver.ver.tar.gz
(103 B)
📄
lvestats.service.service.tar.gz
(375 B)
📄
lvestats.service.tar
(2 KB)
📄
lvm.mod.mod.tar.gz
(4.12 KB)
📄
lvm.mod.tar
(22 KB)
📄
lwres.tar
(72 KB)
📄
lwres.tar.gz
(13.8 KB)
📄
lwres.zip
(61.31 KB)
📄
lxadmin.tar
(7.5 KB)
📄
lxadmin.tar.gz
(1.94 KB)
📄
lxadmin.zip
(5.87 KB)
📄
lychee.sql.sql.tar.gz
(29.22 KB)
📄
lychee.sql.tar
(129.5 KB)
📄
lychee.tar
(41.14 MB)
📄
lychee.tar.gz
(36.98 MB)
📄
lychee.zip
(41.12 MB)
📄
lynx-site.cfg.cfg.tar.gz
(158 B)
📄
lynx-site.cfg.tar
(2 KB)
📄
lynx.cfg.cfg.tar.gz
(52.63 KB)
📄
lynx.cfg.tar
(160.5 KB)
📄
lynx.lss.lss.tar.gz
(1.39 KB)
📄
lynx.lss.tar
(5 KB)
📄
lynx.tar
(1.84 MB)
📄
lynx.tar.gz
(772.89 KB)
📄
lzma.h.h.tar.gz
(3.59 KB)
📄
lzma.h.tar
(11.5 KB)
📄
lzma.py.py.tar.gz
(3.92 KB)
📄
lzma.py.tar
(28 KB)
📄
lzma.tar
(168 KB)
📄
lzma.tar.gz
(36.26 KB)
📄
lzma.zip
(158.07 KB)
📄
lzma12.h.h.tar.gz
(5.14 KB)
📄
lzma12.h.tar
(16 KB)
📄
lzma_decompress.img.img.tar.gz
(2.26 KB)
📄
lzma_decompress.img.tar
(4.5 KB)
📄
lzopio.mod.mod.tar.gz
(3.15 KB)
📄
lzopio.mod.tar
(17 KB)
📄
m0.tar
(4.37 MB)
📄
m0.tar.gz
(2.28 MB)
📄
m0.zip
(4.29 MB)
📄
m1.tar
(3.84 MB)
📄
m1.tar.gz
(1.42 MB)
📄
m1.zip
(3.77 MB)
📄
m3.bin.bin.tar.gz
(121.74 KB)
📄
m3.bin.tar
(262 KB)
📄
m3_fw.flist.flist.tar.gz
(178 B)
📄
m3_fw.flist.tar
(4 KB)
📄
m3_fw.mdt.mdt.tar.gz
(2.68 KB)
📄
m3_fw.mdt.tar
(8.5 KB)
📄
m4.tar
(187.5 KB)
📄
m4.tar.gz
(80.77 KB)
📄
m68k-linux.tar
(5 KB)
📄
m68k-linux.tar.gz
(1.2 KB)
📄
m68k-linux.zip
(3.15 KB)
📄
m_ctype.h.h.tar.gz
(15.63 KB)
📄
m_ctype.h.tar
(71.5 KB)
📄
m_string.h.h.tar.gz
(3.61 KB)
📄
m_string.h.tar
(12 KB)
📄
ma_dyncol.h.h.tar.gz
(2.34 KB)
📄
ma_dyncol.h.tar
(9.5 KB)
📄
ma_io.h.h.tar.gz
(889 B)
📄
ma_io.h.tar
(3.5 KB)
📄
ma_list.h.h.tar.gz
(904 B)
📄
ma_list.h.tar
(3.5 KB)
📄
ma_pvio.h.h.tar.gz
(1.38 KB)
📄
ma_pvio.h.tar
(6 KB)
📄
ma_tls.h.h.tar.gz
(1.46 KB)
📄
ma_tls.h.tar
(6.5 KB)
📄
mac.tar
(35 KB)
📄
mac.tar.gz
(14.73 KB)
📄
mac.zip
(21.63 KB)
📄
macbless.mod.mod.tar.gz
(2.08 KB)
📄
macbless.mod.tar
(6 KB)
📄
macho.mod.mod.tar.gz
(4.34 KB)
📄
macho.mod.tar
(25 KB)
📄
macholib.tar
(103.5 KB)
📄
macholib.tar.gz
(5.9 KB)
📄
macholib.zip
(79.92 KB)
📄
macpath.py.py.tar.gz
(2.28 KB)
📄
macpath.py.tar
(14.5 KB)
📄
macpath.pyc.pyc.tar.gz
(3.42 KB)
📄
macpath.pyc.tar
(9.5 KB)
📄
macpath.pyo.pyo.tar.gz
(3.42 KB)
📄
macpath.pyo.tar
(9.5 KB)
📄
macros.d.tar
(122.5 KB)
📄
macros.d.tar.gz
(25.33 KB)
📄
macros.d.zip
(95.27 KB)
📄
macros.dwz.dwz.tar.gz
(992 B)
📄
macros.dwz.tar
(3.5 KB)
📄
macros.efi-srpm.efi-srpm.tar.gz
(1.12 KB)
📄
macros.efi-srpm.tar
(5 KB)
📄
macros.forge.forge.tar.gz
(3.24 KB)
📄
macros.forge.tar
(14 KB)
📄
macros.ghc-srpm.ghc-srpm.tar.gz
(320 B)
📄
macros.ghc-srpm.tar
(2 KB)
📄
macros.ldc-srpm.ldc-srpm.tar.gz
(172 B)
📄
macros.ldc-srpm.tar
(2 KB)
📄
macros.ldconfig.ldconfig.tar.gz
(210 B)
📄
macros.ldconfig.tar
(2 KB)
📄
macros.python.python.tar.gz
(1.16 KB)
📄
macros.python.tar
(5 KB)
📄
macros.scl.scl.tar.gz
(3.96 KB)
📄
macros.scl.tar
(15.5 KB)
📄
macros.tar
(146 KB)
📄
macros.tar.gz
(13.5 KB)
📄
macros.vim.tar
(2 KB)
📄
macros.vim.vim.tar.gz
(141 B)
📄
macros.vpath.tar
(2 KB)
📄
macros.vpath.vpath.tar.gz
(262 B)
📄
macurl2path.py.py.tar.gz
(1.07 KB)
📄
macurl2path.py.tar
(8 KB)
📄
macurl2path.pyc.pyc.tar.gz
(1.17 KB)
📄
macurl2path.pyc.tar
(4 KB)
📄
macurl2path.pyo.pyo.tar.gz
(1.17 KB)
📄
macurl2path.pyo.tar
(4 KB)
📄
magento.tar
(238.5 KB)
📄
magento.tar.gz
(142 KB)
📄
magento.zip
(212.23 KB)
📄
magento17.tar
(210 KB)
📄
magento17.tar.gz
(121.61 KB)
📄
magento17.zip
(185.12 KB)
📄
magento18.tar
(362 KB)
📄
magento18.tar.gz
(164.68 KB)
📄
magento18.zip
(339.08 KB)
📄
magento2.tar
(510.5 KB)
📄
magento2.tar.gz
(222.6 KB)
📄
magento2.zip
(480.38 KB)
📄
magento24.tar
(563.3 MB)
📄
magento24.tar.gz
(0 B)
📄
magento24.zip
(563.27 MB)
📄
magento241.tar
(556.5 KB)
📄
magento241.tar.gz
(244.78 KB)
📄
magento241.zip
(533 KB)
📄
magento242.tar
(515.5 KB)
📄
magento242.tar.gz
(207.68 KB)
📄
magento242.zip
(487.3 KB)
📄
magento246.tar
(567.97 MB)
📄
magento246.tar.gz
(0 B)
📄
magento246.zip
(567.93 MB)
📄
magento247.tar
(584.04 MB)
📄
magento247.tar.gz
(0 B)
📄
magento247.zip
(584.01 MB)
📄
magic.h.h.tar.gz
(2.13 KB)
📄
magic.h.tar
(7 KB)
📄
mahara.tar
(393 KB)
📄
mahara.tar.gz
(185.42 KB)
📄
mahara.zip
(365.04 KB)
📄
maian.sql.sql.tar.gz
(4.37 KB)
📄
maian.sql.tar
(31.5 KB)
📄
maian.tar
(53.57 MB)
📄
maian.tar.gz
(53.17 MB)
📄
maian.zip
(53.53 MB)
📄
mail.php.php.tar.gz
(177 B)
📄
mail.php.tar
(2 KB)
📄
mail.rc.rc.tar.gz
(1.07 KB)
📄
mail.rc.tar
(3.5 KB)
📄
mail.tar
(69.99 MB)
📄
mail.tar.gz
(25.84 MB)
📄
mail.zip
(68.09 MB)
📄
mailbox.py.py.tar.gz
(13.89 KB)
📄
mailbox.py.tar
(236 KB)
📄
mailbox.pyc.pyc.tar.gz
(22.76 KB)
📄
mailbox.pyc.tar
(76.5 KB)
📄
mailbox.pyo.pyo.tar.gz
(22.72 KB)
📄
mailbox.pyo.tar
(76.5 KB)
📄
mailcap.py.py.tar.gz
(2.94 KB)
📄
mailcap.py.tar
(29 KB)
📄
mailcap.pyc.pyc.tar.gz
(3.7 KB)
📄
mailcap.pyc.tar
(9.5 KB)
📄
mailcap.pyo.pyo.tar.gz
(3.7 KB)
📄
mailcap.pyo.tar
(9.5 KB)
📄
mailcap.tar
(2 KB)
📄
mailcap.tar.gz
(214 B)
📄
maildirsize.tar
(2.5 KB)
📄
maildirsize.tar.gz
(364 B)
📄
mailto.rb.rb.tar.gz
(2.55 KB)
📄
mailto.rb.tar
(50.5 KB)
📄
mailx.tar
(410.5 KB)
📄
mailx.tar.gz
(204.46 KB)
📄
main.cache.cache.tar.gz
(271 B)
📄
main.cache.tar
(2 KB)
📄
main.log.log.tar.gz
(103 B)
📄
main.log.tar
(1.5 KB)
📄
main.php.php.tar.gz
(1.31 KB)
📄
main.php.tar
(6 KB)
📄
main.py.py.tar.gz
(3.51 KB)
📄
main.py.tar
(25 KB)
📄
main.tar
(2 KB)
📄
main.tar.gz
(274 B)
📄
mainfile.php.php.tar.gz
(1.53 KB)
📄
mainfile.php.tar
(10.5 KB)
📄
make-dummy-cert.tar
(2.5 KB)
📄
make-dummy-cert.tar.gz
(439 B)
📄
make.bat.bat.tar.gz
(227 B)
📄
make.bat.tar
(2 KB)
📄
make.tar
(237 KB)
📄
make.tar.gz
(116.09 KB)
📄
makedir.py.py.tar.gz
(410 B)
📄
makedir.py.tar
(2 KB)
📄
maketest.tar
(3.5 KB)
📄
maketest.tar.gz
(888 B)
📄
mako-render.tar
(2 KB)
📄
mako-render.tar.gz
(260 B)
📄
mali.tar
(1.69 MB)
📄
mali.tar.gz
(394.9 KB)
📄
mali.zip
(1.68 MB)
📄
malloc.h.h.tar.gz
(2.13 KB)
📄
malloc.h.tar
(7.5 KB)
📄
man-db.conf.conf.tar.gz
(139 B)
📄
man-db.conf.tar
(3 KB)
📄
man-db.tar
(176.5 KB)
📄
man-db.tar.gz
(79.81 KB)
📄
man-db.zip
(174.57 KB)
📄
man.tar
(40.66 MB)
📄
man.tar.gz
(30.21 MB)
📄
man.zip
(31.97 MB)
📄
man0p.tar
(239.5 KB)
📄
man0p.tar.gz
(177.74 KB)
📄
man0p.zip
(187.08 KB)
📄
man1.tar
(10.19 MB)
📄
man1.tar.gz
(5.93 KB)
📄
man1.zip
(9.06 MB)
📄
man1p.zip
(871.38 KB)
📄
man2.tar
(1.35 MB)
📄
man2.tar.gz
(978.56 KB)
📄
man2.zip
(1.01 MB)
📄
man3.tar
(16.4 MB)
📄
man3.tar.gz
(8.15 KB)
📄
man3.zip
(11.2 MB)
📄
man3p.tar
(2.2 MB)
📄
man3p.tar.gz
(1.58 MB)
📄
man3p.zip
(1.68 MB)
📄
man4.tar
(161.5 KB)
📄
man4.tar.gz
(123.71 KB)
📄
man4.zip
(128.55 KB)
📄
man5.tar
(1.63 MB)
📄
man5.tar.gz
(1.4 MB)
📄
man5.zip
(1.43 MB)
📄
man6.tar
(2.5 KB)
📄
man6.tar.gz
(1.11 KB)
📄
man6.zip
(1.13 KB)
📄
man7.tar
(1.78 MB)
📄
man7.tar.gz
(1.47 MB)
📄
man7.zip
(1.51 MB)
📄
man8.tar
(2.48 MB)
📄
man8.tar.gz
(1.87 MB)
📄
man8.zip
(1.96 MB)
📄
mana-abi.h.h.tar.gz
(647 B)
📄
mana-abi.h.tar
(3 KB)
📄
manager.json.json.tar.gz
(192 B)
📄
manager.json.tar
(2 KB)
📄
managesieve.xml.tar
(2 KB)
📄
managesieve.xml.xml.tar.gz
(337 B)
📄
mann.tar
(697.5 KB)
📄
mann.tar.gz
(612.47 KB)
📄
mann.zip
(636.61 KB)
📄
mantis.sql.sql.tar.gz
(2.83 KB)
📄
mantis.sql.tar
(24.5 KB)
📄
mantis.tar
(16.84 MB)
📄
mantis.tar.gz
(16.2 MB)
📄
mantis.zip
(16.81 MB)
📄
mapping.go.go.tar.gz
(2.72 KB)
📄
mapping.go.tar
(9.5 KB)
📄
mapping.rb.rb.tar.gz
(357 B)
📄
mapping.rb.tar
(2 KB)
📄
maps.tar
(289 KB)
📄
maps.tar.gz
(3.21 KB)
📄
mar.php.php.tar.gz
(19.01 KB)
📄
mar.php.tar
(35 KB)
📄
mariadb-access.tar
(111 KB)
📄
mariadb-access.tar.gz
(25.16 KB)
📄
mariadb-admin.tar
(4.89 MB)
📄
mariadb-admin.tar.gz
(1.11 MB)
📄
mariadb-binlog.tar
(5.17 MB)
📄
mariadb-binlog.tar.gz
(1.25 MB)
📄
mariadb-check.tar
(4.89 MB)
📄
mariadb-check.tar.gz
(1.11 MB)
📄
mariadb-conv.tar
(4.6 MB)
📄
mariadb-conv.tar.gz
(1.01 MB)
📄
mariadb-convert-table-format.tar
(6 KB)
📄
mariadb-convert-table-format.tar.gz
(2.07 KB)
📄
mariadb-dump.tar
(4.99 MB)
📄
mariadb-dump.tar.gz
(1.15 MB)
📄
mariadb-dumpslow.tar
(10 KB)
📄
mariadb-dumpslow.tar.gz
(3.44 KB)
📄
mariadb-embedded.tar
(24.61 MB)
📄
mariadb-embedded.tar.gz
(7.93 MB)
📄
mariadb-extra.socket.socket.tar.gz
(410 B)
📄
mariadb-extra.socket.tar
(2.5 KB)
📄
mariadb-find-rows.tar
(5 KB)
📄
mariadb-find-rows.tar.gz
(1.62 KB)
📄
mariadb-hotcopy.tar
(36.5 KB)
📄
mariadb-hotcopy.tar.gz
(11.92 KB)
📄
mariadb-import.tar
(4.88 MB)
📄
mariadb-import.tar.gz
(1.11 MB)
📄
mariadb-plugin.tar
(4.57 MB)
📄
mariadb-plugin.tar.gz
(1019.04 KB)
📄
mariadb-show.tar
(4.88 MB)
📄
mariadb-show.tar.gz
(1.11 MB)
📄
mariadb-slap.tar
(4.9 MB)
📄
mariadb-slap.tar.gz
(1.12 MB)
📄
mariadb-waitpid.tar
(4.56 MB)
📄
mariadb-waitpid.tar.gz
(1013.16 KB)
📄
mariadb.conf.conf.tar.gz
(141 B)
📄
mariadb.conf.tar
(5 KB)
📄
mariadb.pc.pc.tar.gz
(475 B)
📄
mariadb.pc.tar
(2.5 KB)
📄
mariadb.service.service.tar.gz
(2.57 KB)
📄
mariadb.service.tar
(7.5 KB)
📄
mariadb.socket.socket.tar.gz
(426 B)
📄
mariadb.socket.tar
(2.5 KB)
📄
mariadb.tar
(5.35 MB)
📄
mariadb.tar.gz
(1.29 MB)
📄
mariadb.zip
(1.73 KB)
📄
mariadb10.tar
(579 KB)
📄
mariadb10.tar.gz
(71.52 KB)
📄
mariadb10.zip
(595.15 KB)
📄
mariadb101.tar
(598 KB)
📄
mariadb101.tar.gz
(73.16 KB)
📄
mariadb101.zip
(574.2 KB)
📄
mariadb1011.tar
(496 KB)
📄
mariadb1011.tar.gz
(68.98 KB)
📄
mariadb1011.zip
(472.41 KB)
📄
mariadb102.tar
(510.5 KB)
📄
mariadb102.tar.gz
(69.6 KB)
📄
mariadb102.zip
(543.52 KB)
📄
mariadb103.tar
(548 KB)
📄
mariadb103.tar.gz
(68.98 KB)
📄
mariadb103.zip
(577.13 KB)
📄
mariadb104.tar
(565.5 KB)
📄
mariadb104.tar.gz
(68.92 KB)
📄
mariadb104.zip
(541.98 KB)
📄
mariadb105.tar
(564.5 KB)
📄
mariadb105.tar.gz
(68.98 KB)
📄
mariadb105.zip
(560.81 KB)
📄
mariadb106.tar
(546.5 KB)
📄
mariadb106.tar.gz
(69.08 KB)
📄
mariadb106.zip
(543.52 KB)
📄
mariadb1104.tar
(457.5 KB)
📄
mariadb1104.tar.gz
(68.87 KB)
📄
mariadb1104.zip
(476.29 KB)
📄
mariadb@.service.service.tar.gz
(3.97 KB)
📄
mariadb@.service.tar
(11.5 KB)
📄
mariadb@.socket.socket.tar.gz
(444 B)
📄
mariadb@.socket.tar
(2.5 KB)
📄
mariadb_com.h.h.tar.gz
(5.84 KB)
📄
mariadb_com.h.tar
(20.5 KB)
📄
mariadb_ctype.h.h.tar.gz
(1.17 KB)
📄
mariadb_ctype.h.tar
(4.5 KB)
📄
mariadb_dyncol.h.h.tar.gz
(2.4 KB)
📄
mariadb_dyncol.h.tar
(10 KB)
📄
mariadb_rpl.h.h.tar.gz
(5.66 KB)
📄
mariadb_rpl.h.tar
(20.5 KB)
📄
markdown.tar
(76 KB)
📄
markdown.tar.gz
(14.82 KB)
📄
markdown.zip
(72.61 KB)
📄
markov.pyc.pyc.tar.gz
(2.11 KB)
📄
markov.pyc.tar
(5.5 KB)
📄
markov.pyo.pyo.tar.gz
(2.11 KB)
📄
markov.pyo.tar
(5.5 KB)
📄
markup.rb.rb.tar.gz
(9.67 KB)
📄
markup.rb.tar
(30 KB)
📄
markupbase.pyc.pyc.tar.gz
(3.8 KB)
📄
markupbase.pyc.tar
(11 KB)
📄
markupbase.pyo.pyo.tar.gz
(3.73 KB)
📄
markupbase.pyo.tar
(10.5 KB)
📄
marshal.h.h.tar.gz
(396 B)
📄
marshal.h.tar
(2.5 KB)
📄
math-finite.h.h.tar.gz
(1.56 KB)
📄
math-finite.h.tar
(7 KB)
📄
math-vector.h.h.tar.gz
(948 B)
📄
math-vector.h.tar
(4 KB)
📄
math.h.h.tar.gz
(9.91 KB)
📄
math.h.tar
(54 KB)
📄
mathcalls-helper-functions.h.h.tar.gz
(823 B)
📄
mathcalls-helper-functions.h.tar
(3.5 KB)
📄
mathcalls.h.h.tar.gz
(3.45 KB)
📄
mathcalls.h.tar
(14.5 KB)
📄
mathdef.h.h.tar.gz
(602 B)
📄
mathdef.h.tar
(2.5 KB)
📄
mathinline.h.h.tar.gz
(2.87 KB)
📄
mathinline.h.tar
(14.5 KB)
📄
matrix.tar
(29.5 KB)
📄
matrix.tar.gz
(6.71 KB)
📄
matrix.xml.tar
(2 KB)
📄
matrix.xml.xml.tar.gz
(377 B)
📄
matrix.zip
(27.35 KB)
📄
matrox.tar
(29.5 KB)
📄
matrox.tar.gz
(3.84 KB)
📄
matrox.zip
(27.63 KB)
📄
matt.tar
(267.5 KB)
📄
matt.tar.gz
(41.59 KB)
📄
matt.zip
(204.73 KB)
📄
mautic.sql.sql.tar.gz
(19 KB)
📄
mautic.sql.tar
(175 KB)
📄
mautic.tar
(89.54 MB)
📄
mautic.tar.gz
(82.86 MB)
📄
mautic.zip
(89.51 MB)
📄
max.tar
(2 KB)
📄
max.tar.gz
(111 B)
📄
max98357a-tplg.bin.bin.tar.gz
(686 B)
📄
max98357a-tplg.bin.tar
(5 KB)
📄
max_addresses.tar
(3 KB)
📄
max_addresses.tar.gz
(122 B)
📄
max_desync_factor.tar
(3 KB)
📄
max_desync_factor.tar.gz
(129 B)
📄
max_dgram_qlen.tar
(2 KB)
📄
max_dgram_qlen.tar.gz
(118 B)
📄
max_hbh_length.tar
(2 KB)
📄
max_hbh_length.tar.gz
(125 B)
📄
max_lock_depth.tar
(2 KB)
📄
max_lock_depth.tar.gz
(118 B)
📄
max_map_count.tar
(2 KB)
📄
max_map_count.tar.gz
(112 B)
📄
max_queued_events.tar
(2 KB)
📄
max_queued_events.tar.gz
(126 B)
📄
max_resvport.tar
(2 KB)
📄
max_resvport.tar.gz
(114 B)
📄
max_size.tar
(3 KB)
📄
max_size.tar.gz
(125 B)
📄
max_skb_frags.tar
(2 KB)
📄
max_skb_frags.tar.gz
(115 B)
📄
max_user_watches.tar
(3 KB)
📄
max_user_watches.tar.gz
(123 B)
📄
maxbytes.tar
(2 KB)
📄
maxbytes.tar.gz
(112 B)
📄
maxkeys.tar
(2 KB)
📄
maxkeys.tar.gz
(108 B)
📄
mb_groups.tar
(9.16 MB)
📄
mb_groups.tar.gz
(1.69 MB)
📄
mbox.py.py.tar.gz
(2.15 KB)
📄
mbox.py.tar
(9 KB)
📄
mbstate_t.h.h.tar.gz
(177 B)
📄
mbstate_t.h.tar
(2 KB)
📄
mc-wrapper.sh.sh.tar.gz
(300 B)
📄
mc-wrapper.sh.tar
(2 KB)
📄
mc.csh.csh.tar.gz
(136 B)
📄
mc.csh.tar
(2 KB)
📄
mc.sh.sh.tar.gz
(214 B)
📄
mc.sh.tar
(2 KB)
📄
mc.tar
(16.34 MB)
📄
mc.tar.gz
(15.11 KB)
📄
mc.zip
(14.98 MB)
📄
mc_forwarding.tar
(5 KB)
📄
mc_forwarding.tar.gz
(122 B)
📄
mcast_resolicit.tar
(5 KB)
📄
mcast_resolicit.tar.gz
(124 B)
📄
mcast_solicit.tar
(7 KB)
📄
mcast_solicit.tar.gz
(126 B)
📄
mcdiff.tar
(1.3 MB)
📄
mcdiff.tar.gz
(581.38 KB)
📄
mce.h.h.tar.gz
(915 B)
📄
mce.h.tar
(3.5 KB)
📄
mcedit.tar
(1.3 MB)
📄
mcedit.tar.gz
(581.38 KB)
📄
mcheck.h.h.tar.gz
(1.19 KB)
📄
mcheck.h.tar
(4 KB)
📄
mcode.bin.bin.tar.gz
(1.72 KB)
📄
mcode.bin.tar
(4 KB)
📄
mcookie.tar
(35 KB)
📄
mcookie.tar.gz
(15.4 KB)
📄
mcview.tar
(1.3 MB)
📄
mcview.tar.gz
(581.38 KB)
📄
md4.h.h.tar.gz
(696 B)
📄
md4.h.tar
(3 KB)
📄
md5.h.h.tar.gz
(773 B)
📄
md5.h.tar
(5 KB)
📄
md5.py.py.tar.gz
(342 B)
📄
md5.py.tar
(2 KB)
📄
md5.pyc.pyc.tar.gz
(354 B)
📄
md5.pyc.tar
(2 KB)
📄
md5.pyo.pyo.tar.gz
(352 B)
📄
md5.pyo.tar
(2 KB)
📄
md5.so.so.tar.gz
(3.12 KB)
📄
md5.so.tar
(9 KB)
📄
md5.tar
(2.45 MB)
📄
md5.tar.gz
(630 B)
📄
md5driver.pyc.pyc.tar.gz
(1.53 KB)
📄
md5driver.pyc.tar
(5 KB)
📄
md5driver.pyo.pyo.tar.gz
(1.53 KB)
📄
md5driver.pyo.tar
(5 KB)
📄
md5global.h.h.tar.gz
(564 B)
📄
md5global.h.tar
(3 KB)
📄
md5sum.py.py.tar.gz
(999 B)
📄
md5sum.py.tar
(4 KB)
📄
md5sum.tar
(47.5 KB)
📄
md5sum.tar.gz
(20.17 KB)
📄
md5test.tar
(14 KB)
📄
md5test.tar.gz
(2.71 KB)
📄
md5test.zip
(10.04 KB)
📄
mda_text.mod.mod.tar.gz
(1.29 KB)
📄
mda_text.mod.tar
(4.5 KB)
📄
mdb.so.so.tar.gz
(3.08 KB)
📄
mdb.so.tar
(9 KB)
📄
mdc2.h.h.tar.gz
(642 B)
📄
mdc2.h.tar
(3 KB)
📄
mdns.xml.tar
(2 KB)
📄
mdns.xml.xml.tar.gz
(388 B)
📄
mdraid09.mod.mod.tar.gz
(1.21 KB)
📄
mdraid09.mod.tar
(4 KB)
📄
mdraid09_be.mod.mod.tar.gz
(1.26 KB)
📄
mdraid09_be.mod.tar
(4 KB)
📄
mdraid1x.mod.mod.tar.gz
(1.25 KB)
📄
mdraid1x.mod.tar
(4 KB)
📄
measunit.h.h.tar.gz
(7.51 KB)
📄
measunit.h.tar
(90 KB)
📄
mediaservice.tar
(765 KB)
📄
mediaservice.tar.gz
(264.99 KB)
📄
mediaservice.zip
(761.79 KB)
📄
mediatek.tar
(58.27 MB)
📄
mediatek.tar.gz
(26.56 MB)
📄
mediatek.zip
(58.21 MB)
📄
medium_id.tar
(2 KB)
📄
medium_id.tar.gz
(120 B)
📄
meld.tar
(4 KB)
📄
meld.tar.gz
(877 B)
📄
mellanox.tar
(106.45 MB)
📄
mellanox.tar.gz
(101.72 MB)
📄
mellanox.zip
(106.41 MB)
📄
mem.tar
(6 KB)
📄
mem.tar.gz
(88 B)
📄
memberof.so.so.tar.gz
(32.06 KB)
📄
memberof.so.tar
(75 KB)
📄
memcache.xml.tar
(2 KB)
📄
memcache.xml.xml.tar.gz
(256 B)
📄
memcp.tar
(28.5 KB)
📄
memcp.tar.gz
(9.51 KB)
📄
memdisk.mod.mod.tar.gz
(1.25 KB)
📄
memdisk.mod.tar
(4 KB)
📄
memdump.tar
(24 KB)
📄
memdump.tar.gz
(7.67 KB)
📄
memerror.tar
(20 KB)
📄
memerror.tar.gz
(6.9 KB)
📄
memexist.tar
(24 KB)
📄
memexist.tar.gz
(7.46 KB)
📄
memflush.tar
(24 KB)
📄
memflush.tar.gz
(7.6 KB)
📄
meminfo.tar
(3 KB)
📄
meminfo.tar.gz
(646 B)
📄
memory.h.h.tar.gz
(621 B)
📄
memory.h.tar
(2.5 KB)
📄
memory_failure_recovery.tar
(2 KB)
📄
memory_failure_recovery.tar.gz
(118 B)
📄
memoryobject.h.h.tar.gz
(1.1 KB)
📄
memoryobject.h.tar
(4.5 KB)
📄
memparse.tar
(15 KB)
📄
memparse.tar.gz
(4.14 KB)
📄
memping.tar
(24 KB)
📄
memping.tar.gz
(7.66 KB)
📄
memrm.tar
(24 KB)
📄
memrm.tar.gz
(7.74 KB)
📄
memrw.mod.mod.tar.gz
(1.39 KB)
📄
memrw.mod.tar
(9 KB)
📄
memslap.tar
(34 KB)
📄
memslap.tar.gz
(12 KB)
📄
memstat.tar
(28.5 KB)
📄
memstat.tar.gz
(9.75 KB)
📄
memtouch.tar
(24 KB)
📄
memtouch.tar.gz
(7.69 KB)
📄
menu.h.h.tar.gz
(3.13 KB)
📄
menu.h.tar
(38.5 KB)
📄
menu.pc.pc.tar.gz
(361 B)
📄
menu.pc.tar
(2 KB)
📄
menu.yml.tar
(2.5 KB)
📄
menu.yml.yml.tar.gz
(364 B)
📄
menuw.pc.pc.tar.gz
(363 B)
📄
menuw.pc.tar
(2 KB)
📄
mergetools.tar
(45.5 KB)
📄
mergetools.tar.gz
(7.13 KB)
📄
mergetools.zip
(31.53 KB)
📄
mesg.tar
(18 KB)
📄
mesg.tar.gz
(5.33 KB)
📄
meson.tar
(328.5 KB)
📄
meson.tar.gz
(102.21 KB)
📄
meson.zip
(322.21 KB)
📄
message.pyc.pyc.tar.gz
(9.92 KB)
📄
message.pyc.tar
(30 KB)
📄
message.pyo.pyo.tar.gz
(9.92 KB)
📄
message.pyo.tar
(30 KB)
📄
message_burst.tar
(2 KB)
📄
message_burst.tar.gz
(115 B)
📄
message_cost.tar
(2 KB)
📄
message_cost.tar.gz
(114 B)
📄
methodobject.h.h.tar.gz
(1.54 KB)
📄
methodobject.h.tar
(6 KB)
📄
mg.h.h.tar.gz
(1.28 KB)
📄
mg.h.tar
(4.5 KB)
📄
mg_data.h.h.tar.gz
(1.16 KB)
📄
mg_data.h.tar
(6.5 KB)
📄
mg_raw.h.h.tar.gz
(1.31 KB)
📄
mg_raw.h.tar
(6 KB)
📄
mg_vtable.h.h.tar.gz
(2.44 KB)
📄
mg_vtable.h.tar
(11 KB)
📄
mgr_ver.sh.sh.tar.gz
(838 B)
📄
mgr_ver.sh.tar
(3.5 KB)
📄
mhdp8546.bin.bin.tar.gz
(23.26 KB)
📄
mhdp8546.bin.tar
(129.5 KB)
📄
mhlib.py.py.tar.gz
(8.23 KB)
📄
mhlib.py.tar
(34.5 KB)
📄
mhlib.pyc.pyc.tar.gz
(12.4 KB)
📄
mhlib.pyc.tar
(34.5 KB)
📄
mhlib.pyo.pyo.tar.gz
(12.4 KB)
📄
mhlib.pyo.tar
(34.5 KB)
📄
mibs.tar
(1.75 MB)
📄
mibs.tar.gz
(322.12 KB)
📄
mibs.zip
(1.7 MB)
📄
microchip.tar
(4.5 KB)
📄
microchip.tar.gz
(1.45 KB)
📄
microchip.zip
(2.08 KB)
📄
microcode.service.service.tar.gz
(295 B)
📄
microcode.service.tar
(2 KB)
📄
microweber.tar
(297.63 MB)
📄
microweber.tar.gz
(288.88 MB)
📄
microweber.zip
(297.59 MB)
📄
midi.fw.fw.tar.gz
(12.42 KB)
📄
midi.fw.tar
(30 KB)
📄
migrate.php.php.tar.gz
(680 B)
📄
migrate.php.tar
(3 KB)
📄
mime.tar
(159.5 KB)
📄
mime.tar.gz
(8.05 KB)
📄
mime.types.tar
(60.5 KB)
📄
mime.types.types.tar.gz
(16.16 KB)
📄
mime.zip
(109.54 KB)
📄
mimetools.py.py.tar.gz
(2.2 KB)
📄
mimetools.py.tar
(8.5 KB)
📄
mimetypes.py.py.tar.gz
(5.23 KB)
📄
mimetypes.py.tar
(66 KB)
📄
mimify.py.py.tar.gz
(3.57 KB)
📄
mimify.py.tar
(16.5 KB)
📄
mimify.pyc.pyc.tar.gz
(5.12 KB)
📄
mimify.pyc.tar
(13.5 KB)
📄
mimify.pyo.pyo.tar.gz
(5.12 KB)
📄
mimify.pyo.tar
(13.5 KB)
📄
min_free_kbytes.tar
(2 KB)
📄
min_free_kbytes.tar.gz
(116 B)
📄
min_pmtu.tar
(2 KB)
📄
min_pmtu.tar.gz
(118 B)
📄
min_resvport.tar
(2 KB)
📄
min_resvport.tar.gz
(115 B)
📄
min_slab_ratio.tar
(2 KB)
📄
min_slab_ratio.tar.gz
(110 B)
📄
min_unmapped_ratio.tar
(2 KB)
📄
min_unmapped_ratio.tar.gz
(115 B)
📄
minibb.png.png.tar.gz
(2.65 KB)
📄
minibb.png.tar
(4.5 KB)
📄
minibb.sql.sql.tar.gz
(1.27 KB)
📄
minibb.sql.tar
(8 KB)
📄
minibb.tar
(635.5 KB)
📄
minibb.tar.gz
(549.32 KB)
📄
minibb.zip
(616.44 KB)
📄
minicmd.mod.mod.tar.gz
(2.06 KB)
📄
minicmd.mod.tar
(6 KB)
📄
minidlna.xml.tar
(2 KB)
📄
minidlna.xml.xml.tar.gz
(325 B)
📄
miniflux.tar
(133 KB)
📄
miniflux.tar.gz
(70.03 KB)
📄
miniflux.zip
(115.09 KB)
📄
minix.mod.mod.tar.gz
(2.65 KB)
📄
minix.mod.tar
(13 KB)
📄
minix2.mod.mod.tar.gz
(2.71 KB)
📄
minix2.mod.tar
(13 KB)
📄
minix2_be.mod.mod.tar.gz
(2.89 KB)
📄
minix2_be.mod.tar
(14 KB)
📄
minix3.mod.mod.tar.gz
(2.7 KB)
📄
minix3.mod.tar
(13 KB)
📄
minix3_be.mod.mod.tar.gz
(2.87 KB)
📄
minix3_be.mod.tar
(14 KB)
📄
minix_be.mod.mod.tar.gz
(2.8 KB)
📄
minix_be.mod.tar
(7 KB)
📄
mips-linux.tar
(4.5 KB)
📄
mips-linux.tar.gz
(1.18 KB)
📄
mips-linux.zip
(3.1 KB)
📄
mips64-linux.tar
(4.5 KB)
📄
mips64-linux.tar.gz
(1.19 KB)
📄
mips64-linux.zip
(3.11 KB)
📄
mips64el-linux.tar
(4.5 KB)
📄
mips64el-linux.tar.gz
(1.19 KB)
📄
mips64el-linux.zip
(3.11 KB)
📄
mips64r6-linux.tar
(4.5 KB)
📄
mips64r6-linux.tar.gz
(1.19 KB)
📄
mips64r6-linux.zip
(3.11 KB)
📄
mips64r6el-linux.tar
(4.5 KB)
📄
mips64r6el-linux.tar.gz
(1.19 KB)
📄
mips64r6el-linux.zip
(3.12 KB)
📄
mipsel-linux.tar
(4.5 KB)
📄
mipsel-linux.tar.gz
(1.19 KB)
📄
mipsel-linux.zip
(3.1 KB)
📄
mipsr6-linux.tar
(4.5 KB)
📄
mipsr6-linux.tar.gz
(1.19 KB)
📄
mipsr6-linux.zip
(3.1 KB)
📄
mipsr6el-linux.tar
(4.5 KB)
📄
mipsr6el-linux.tar.gz
(1.19 KB)
📄
mipsr6el-linux.zip
(3.11 KB)
📄
misc.pyc.pyc.tar.gz
(1.32 KB)
📄
misc.pyc.tar
(5.5 KB)
📄
misc.pyo.pyo.tar.gz
(1.32 KB)
📄
misc.pyo.tar
(5.5 KB)
📄
misc.sh.sh.tar.gz
(699 B)
📄
misc.sh.tar
(4 KB)
📄
misc.tar
(159 KB)
📄
misc.tar.gz
(37.38 KB)
📄
misc.zip
(146.08 KB)
📄
mit-krb5-gssapi.pc.pc.tar.gz
(272 B)
📄
mit-krb5-gssapi.pc.tar
(2 KB)
📄
mit-krb5.pc.pc.tar.gz
(348 B)
📄
mit-krb5.pc.tar
(2 KB)
📄
mixin.rb.rb.tar.gz
(1.2 KB)
📄
mixin.rb.tar
(22 KB)
📄
mkdir.sh.sh.tar.gz
(986 B)
📄
mkdir.sh.tar
(3.5 KB)
📄
mkdir.tar
(85.5 KB)
📄
mkdir.tar.gz
(41.13 KB)
📄
mkfifo.tar
(68 KB)
📄
mkfifo.tar.gz
(32.81 KB)
📄
mkhomedir_helper.tar
(26 KB)
📄
mkhomedir_helper.tar.gz
(5.72 KB)
📄
mkmf.rb.rb.tar.gz
(23.93 KB)
📄
mkmf.rb.tar
(324 KB)
📄
mkreal.py.py.tar.gz
(756 B)
📄
mkreal.py.tar
(3.5 KB)
📄
mktemp.tar
(47.5 KB)
📄
mktemp.tar.gz
(20.77 KB)
📄
mld-listener-done.xml.tar
(2 KB)
📄
mld-listener-done.xml.xml.tar.gz
(328 B)
📄
mld_max_msf.tar
(2 KB)
📄
mld_max_msf.tar.gz
(114 B)
📄
mld_qrv.tar
(2 KB)
📄
mld_qrv.tar.gz
(109 B)
📄
mlx4-abi.h.h.tar.gz
(2.06 KB)
📄
mlx4-abi.h.tar
(6.5 KB)
📄
mlx5_user_ioctl_cmds.h.h.tar.gz
(2.37 KB)
📄
mlx5_user_ioctl_cmds.h.tar
(12 KB)
📄
mlxsw_spectrum2-29.2010.3020.mfa2.2010.3020.mfa2.tar.gz
(1.28 MB)
📄
mlxsw_spectrum2-29.2010.3020.mfa2.tar
(1.44 MB)
📄
mlxsw_spectrum3-30.2007.1168.mfa2.2007.1168.mfa2.tar.gz
(792.54 KB)
📄
mlxsw_spectrum3-30.2007.1168.mfa2.tar
(799.5 KB)
📄
mlxsw_spectrum3-30.2010.3146.mfa2.2010.3146.mfa2.tar.gz
(1.19 MB)
📄
mlxsw_spectrum3-30.2010.3146.mfa2.tar
(1.23 MB)
📄
mman-shared.h.h.tar.gz
(1.25 KB)
📄
mman-shared.h.tar
(4.5 KB)
📄
mman.h.h.tar.gz
(1.1 KB)
📄
mman.h.tar
(13 KB)
📄
mmanon.so.so.tar.gz
(12.02 KB)
📄
mmanon.so.tar
(26 KB)
📄
mmap.mod.mod.tar.gz
(5.1 KB)
📄
mmap.mod.tar
(13.5 KB)
📄
mmap.pm.pm.tar.gz
(487 B)
📄
mmap.pm.tar
(2.5 KB)
📄
mmap.tar
(17.5 KB)
📄
mmap.tar.gz
(5.22 KB)
📄
mmap.zip
(15.71 KB)
📄
mmap_min_addr.tar
(2 KB)
📄
mmap_min_addr.tar.gz
(113 B)
📄
mmcount.so.so.tar.gz
(6.33 KB)
📄
mmcount.so.tar
(18 KB)
📄
mmexternal.so.so.tar.gz
(8.25 KB)
📄
mmexternal.so.tar
(22 KB)
📄
mmutf8fix.so.so.tar.gz
(5.81 KB)
📄
mmutf8fix.so.tar
(17.5 KB)
📄
mntent.h.h.tar.gz
(1.54 KB)
📄
mntent.h.tar
(5 KB)
📄
mod_access_compat.so.so.tar.gz
(5.4 KB)
📄
mod_access_compat.so.tar
(13.5 KB)
📄
mod_actions.so.so.tar.gz
(4.69 KB)
📄
mod_actions.so.tar
(13.5 KB)
📄
mod_alias.so.so.tar.gz
(8.65 KB)
📄
mod_alias.so.tar
(21.5 KB)
📄
mod_auth.h.h.tar.gz
(1.74 KB)
📄
mod_auth.h.tar
(6 KB)
📄
mod_auth_basic.so.so.tar.gz
(7.07 KB)
📄
mod_auth_basic.so.tar
(17.5 KB)
📄
mod_authn_anon.so.so.tar.gz
(4.05 KB)
📄
mod_authn_anon.so.tar
(13.5 KB)
📄
mod_authn_core.so.so.tar.gz
(6 KB)
📄
mod_authn_core.so.tar
(17.5 KB)
📄
mod_authn_file.so.so.tar.gz
(4.35 KB)
📄
mod_authn_file.so.tar
(13.5 KB)
📄
mod_authz_core.so.so.tar.gz
(10.54 KB)
📄
mod_authz_core.so.tar
(26 KB)
📄
mod_authz_host.so.so.tar.gz
(5.91 KB)
📄
mod_authz_host.so.tar
(17.5 KB)
📄
mod_authz_user.so.so.tar.gz
(4.02 KB)
📄
mod_authz_user.so.tar
(13.5 KB)
📄
mod_bw.so.so.tar.gz
(11.63 KB)
📄
mod_bw.so.tar
(35.5 KB)
📄
mod_cache.h.h.tar.gz
(2.37 KB)
📄
mod_cache.h.tar
(9 KB)
📄
mod_cache.so.so.tar.gz
(32.65 KB)
📄
mod_cache.so.tar
(78.5 KB)
📄
mod_cgid.so.so.tar.gz
(18.59 KB)
📄
mod_cgid.so.tar
(46 KB)
📄
mod_cloudflare.so.so.tar.gz
(6.46 KB)
📄
mod_cloudflare.so.tar
(21 KB)
📄
mod_core.h.h.tar.gz
(1.44 KB)
📄
mod_core.h.tar
(5 KB)
📄
mod_deflate.so.so.tar.gz
(16.27 KB)
📄
mod_deflate.so.tar
(37.5 KB)
📄
mod_expires.so.so.tar.gz
(5.96 KB)
📄
mod_expires.so.tar
(17.5 KB)
📄
mod_headers.so.so.tar.gz
(10.11 KB)
📄
mod_headers.so.tar
(26 KB)
📄
mod_hostinglimits.so.so.tar.gz
(15.83 KB)
📄
mod_hostinglimits.so.tar
(43.5 KB)
📄
mod_http2.h.h.tar.gz
(1.67 KB)
📄
mod_http2.h.tar
(6.5 KB)
📄
mod_include.h.h.tar.gz
(1.75 KB)
📄
mod_include.h.tar
(5.5 KB)
📄
mod_include.so.so.tar.gz
(24.56 KB)
📄
mod_include.so.tar
(54 KB)
📄
mod_log_config.h.h.tar.gz
(1.14 KB)
📄
mod_log_config.h.tar
(4 KB)
📄
mod_log_config.so.so.tar.gz
(14.5 KB)
📄
mod_log_config.so.tar
(34 KB)
📄
mod_logio.so.so.tar.gz
(4.72 KB)
📄
mod_logio.so.tar
(13.5 KB)
📄
mod_lsapi.so.so.tar.gz
(55.74 KB)
📄
mod_lsapi.so.tar
(147.5 KB)
📄
mod_mime.so.so.tar.gz
(9.32 KB)
📄
mod_mime.so.tar
(25.5 KB)
📄
mod_mime_magic.so.so.tar.gz
(12.92 KB)
📄
mod_mime_magic.so.tar
(29.5 KB)
📄
mod_proxy.h.h.tar.gz
(15.35 KB)
📄
mod_proxy.h.tar
(67.5 KB)
📄
mod_proxy.so.so.tar.gz
(73.08 KB)
📄
mod_proxy.so.tar
(167.5 KB)
📄
mod_proxy_connect.so.so.tar.gz
(7.19 KB)
📄
mod_proxy_connect.so.tar
(21.5 KB)
📄
mod_proxy_express.so.so.tar.gz
(5.47 KB)
📄
mod_proxy_express.so.tar
(17.5 KB)
📄
mod_proxy_fcgi.so.so.tar.gz
(14.91 KB)
📄
mod_proxy_fcgi.so.tar
(37.5 KB)
📄
mod_proxy_http.so.so.tar.gz
(18.36 KB)
📄
mod_proxy_http.so.tar
(45.5 KB)
📄
mod_proxy_scgi.so.so.tar.gz
(8.75 KB)
📄
mod_proxy_scgi.so.tar
(21.5 KB)
📄
mod_request.h.h.tar.gz
(933 B)
📄
mod_request.h.tar
(3.5 KB)
📄
mod_rewrite.h.h.tar.gz
(860 B)
📄
mod_rewrite.h.tar
(3 KB)
📄
mod_rewrite.so.so.tar.gz
(35.99 KB)
📄
mod_rewrite.so.tar
(82 KB)
📄
mod_session.h.h.tar.gz
(2.03 KB)
📄
mod_session.h.tar
(8.5 KB)
📄
mod_so.h.h.tar.gz
(794 B)
📄
mod_so.h.tar
(3 KB)
📄
mod_socache_shmcb.so.so.tar.gz
(11.96 KB)
📄
mod_socache_shmcb.so.tar
(29.5 KB)
📄
mod_systemd.so.so.tar.gz
(4.77 KB)
📄
mod_systemd.so.tar
(13.5 KB)
📄
mod_unixd.h.h.tar.gz
(749 B)
📄
mod_unixd.h.tar
(3 KB)
📄
mod_unixd.so.so.tar.gz
(6.46 KB)
📄
mod_unixd.so.tar
(17.5 KB)
📄
mod_upgrade.php.php.tar.gz
(8.65 KB)
📄
mod_upgrade.php.tar
(37 KB)
📄
mod_userdir.so.so.tar.gz
(5.12 KB)
📄
mod_userdir.so.tar
(13.5 KB)
📄
mod_version.so.so.tar.gz
(4.59 KB)
📄
mod_version.so.tar
(13.5 KB)
📄
mod_watchdog.h.h.tar.gz
(2.18 KB)
📄
mod_watchdog.h.tar
(9 KB)
📄
mod_xml2enc.h.h.tar.gz
(994 B)
📄
mod_xml2enc.h.tar
(4 KB)
📄
moddep.lst.lst.tar.gz
(2.06 KB)
📄
moddep.lst.tar
(14 KB)
📄
modernizr.tar
(67 KB)
📄
modernizr.tar.gz
(41.11 KB)
📄
modernizr.zip
(56.8 KB)
📄
modes.h.h.tar.gz
(1.05 KB)
📄
modes.h.tar
(21 KB)
📄
modinfo.sh.sh.tar.gz
(1.3 KB)
📄
modinfo.sh.tar
(8 KB)
📄
modprobe.d.tar
(5 KB)
📄
modprobe.d.tar.gz
(1.15 KB)
📄
modprobe.d.zip
(2.42 KB)
📄
modprobe.tar
(2 KB)
📄
modprobe.tar.gz
(117 B)
📄
modsec.tar
(2 KB)
📄
modsec.tar.gz
(210 B)
📄
modsec.zip
(318 B)
📄
modsupport.h.h.tar.gz
(2.72 KB)
📄
modsupport.h.tar
(11 KB)
📄
module-setup.sh.sh.tar.gz
(693 B)
📄
module-setup.sh.tar
(3.5 KB)
📄
module.h.h.tar.gz
(642 B)
📄
module.h.tar
(4.5 KB)
📄
module_to_cil.h.h.tar.gz
(236 B)
📄
module_to_cil.h.tar
(2 KB)
📄
modulefinder.py.py.tar.gz
(6.28 KB)
📄
modulefinder.py.tar
(73 KB)
📄
moduleobject.h.h.tar.gz
(855 B)
📄
moduleobject.h.tar
(4 KB)
📄
modules-Q16.tar
(3.54 MB)
📄
modules-Q16.tar.gz
(1.29 MB)
📄
modules-Q16.zip
(3.37 MB)
📄
modules-load.d.tar
(2 KB)
📄
modules-load.d.tar.gz
(106 B)
📄
modules-load.d.zip
(175 B)
📄
modules.6.2.1.tar
(15.44 MB)
📄
modules.6.2.1.tar.gz
(5.5 MB)
📄
modules.6.2.1.zip
(15.44 MB)
📄
modules.6.2.2.tar
(15.44 MB)
📄
modules.6.2.2.tar.gz
(5.5 MB)
📄
modules.6.2.2.zip
(15.44 MB)
📄
modules.6.3.1.tar
(15.44 MB)
📄
modules.6.3.1.tar.gz
(5.5 MB)
📄
modules.6.3.1.zip
(15.44 MB)
📄
modules.6.3.2.tar
(15.44 MB)
📄
modules.6.3.2.tar.gz
(5.5 MB)
📄
modules.6.3.2.zip
(15.44 MB)
📄
modules.6.3.3.tar
(15.44 MB)
📄
modules.6.3.3.tar.gz
(5.5 MB)
📄
modules.6.3.3.zip
(15.44 MB)
📄
modules.6.3.4.tar
(15.44 MB)
📄
modules.6.3.4.tar.gz
(5.5 MB)
📄
modules.6.3.4.zip
(15.44 MB)
📄
modules.d.tar
(749.5 KB)
📄
modules.d.tar.gz
(150.51 KB)
📄
modules.d.zip
(585.53 KB)
📄
modules.tar
(23.47 MB)
📄
modules.tar.gz
(72.18 KB)
📄
modules.xml.tar
(2 KB)
📄
modules.xml.xml.tar.gz
(271 B)
📄
modules.zip
(23.42 MB)
📄
modx.png.png.tar.gz
(5.24 KB)
📄
modx.png.tar
(7 KB)
📄
modx.sql.sql.tar.gz
(47.26 KB)
📄
modx.sql.tar
(165 KB)
📄
modx.tar
(23.85 MB)
📄
modx.tar.gz
(21.76 MB)
📄
modx.zip
(23.81 MB)
📄
mogrify.tar
(19.76 MB)
📄
mogrify.tar.gz
(3.62 KB)
📄
monetary.h.h.tar.gz
(935 B)
📄
monetary.h.tar
(3.5 KB)
📄
mongodb.xml.tar
(2 KB)
📄
mongodb.xml.xml.tar.gz
(273 B)
📄
monitor.rb.rb.tar.gz
(2.8 KB)
📄
monitor.rb.tar
(32.5 KB)
📄
monitor.so.so.tar.gz
(4.98 KB)
📄
monitor.so.tar
(13.5 KB)
📄
monsta.tar
(289.5 KB)
📄
monsta.tar.gz
(115.3 KB)
📄
monsta.zip
(259.93 KB)
📄
monstra.tar
(150 KB)
📄
monstra.tar.gz
(77.74 KB)
📄
monstra.zip
(128.58 KB)
📄
montage.tar
(19.76 MB)
📄
montage.tar.gz
(3.63 KB)
📄
moodle.tar
(294 KB)
📄
moodle.tar.gz
(175.78 KB)
📄
moodle.zip
(264.35 KB)
📄
moodle20.tar
(254.5 KB)
📄
moodle20.tar.gz
(149.61 KB)
📄
moodle20.zip
(227.53 KB)
📄
moodle27.tar
(285.5 KB)
📄
moodle27.tar.gz
(172.37 KB)
📄
moodle27.zip
(261.56 KB)
📄
moodle28.tar
(326.5 KB)
📄
moodle28.tar.gz
(198.22 KB)
📄
moodle28.zip
(298.56 KB)
📄
moodle29.tar
(344 KB)
📄
moodle29.tar.gz
(211.63 KB)
📄
moodle29.zip
(315.88 KB)
📄
moodle30.tar
(177.83 MB)
📄
moodle30.tar.gz
(165.11 MB)
📄
moodle30.zip
(177.78 MB)
📄
moodle310.tar
(322 KB)
📄
moodle310.tar.gz
(192.83 KB)
📄
moodle310.zip
(293.13 KB)
📄
moodle311.tar
(391 KB)
📄
moodle311.tar.gz
(238.04 KB)
📄
moodle311.zip
(357.38 KB)
📄
moodle38.tar
(298.5 KB)
📄
moodle38.tar.gz
(182.37 KB)
📄
moodle38.zip
(273.81 KB)
📄
moodle39.tar
(389 KB)
📄
moodle39.tar.gz
(238.16 KB)
📄
moodle39.zip
(357.34 KB)
📄
moodle40.tar
(399 KB)
📄
moodle40.tar.gz
(242.49 KB)
📄
moodle40.zip
(366.07 KB)
📄
moodle41.tar
(155.32 MB)
📄
moodle41.tar.gz
(143.63 MB)
📄
moodle41.zip
(155.27 MB)
📄
moodle42.tar
(152.03 MB)
📄
moodle42.tar.gz
(140.72 MB)
📄
moodle42.zip
(151.98 MB)
📄
moodle43.tar
(164.47 MB)
📄
moodle43.tar.gz
(152.03 MB)
📄
moodle43.zip
(164.42 MB)
📄
moodle44.sql.sql.tar.gz
(161.47 KB)
📄
moodle44.sql.tar
(1.19 MB)
📄
moodle44.tar
(172.08 MB)
📄
moodle44.tar.gz
(158.86 MB)
📄
moodle44.zip
(172.03 MB)
📄
moodle45.tar
(176.43 MB)
📄
moodle45.tar.gz
(163.33 MB)
📄
moodle45.zip
(176.38 MB)
📄
moodle50.tar
(176.29 MB)
📄
moodle50.tar.gz
(163.38 MB)
📄
moodle50.zip
(176.24 MB)
📄
mootools.png.png.tar.gz
(24.15 KB)
📄
mootools.png.tar
(26 KB)
📄
mootools.tar
(68.5 KB)
📄
mootools.tar.gz
(46.61 KB)
📄
mootools.zip
(59.2 KB)
📄
more.tar
(46.5 KB)
📄
more.tar.gz
(20.77 KB)
📄
morph.tar
(87.5 KB)
📄
morph.tar.gz
(57.78 KB)
📄
morph.zip
(79.24 KB)
📄
morse.mod.mod.tar.gz
(1.05 KB)
📄
morse.mod.tar
(8 KB)
📄
mosh.xml.tar
(2 KB)
📄
mosh.xml.xml.tar.gz
(383 B)
📄
mount-max.tar
(2 KB)
📄
mount-max.tar.gz
(109 B)
📄
mount.h.h.tar.gz
(2.26 KB)
📄
mount.h.tar
(7 KB)
📄
mountclient.py.py.tar.gz
(2.36 KB)
📄
mountclient.py.tar
(8 KB)
📄
mountd.xml.tar
(2 KB)
📄
mountd.xml.xml.tar.gz
(243 B)
📄
mountinfo.tar
(221.5 KB)
📄
mountinfo.tar.gz
(2.56 KB)
📄
mounts.tar
(81 KB)
📄
mounts.tar.gz
(1.36 KB)
📄
mountstats.tar
(139 KB)
📄
mountstats.tar.gz
(1.21 KB)
📄
moxa-1110.fw.fw.tar.gz
(7.09 KB)
📄
moxa-1110.fw.tar
(27 KB)
📄
moxa-1130.fw.fw.tar.gz
(7.1 KB)
📄
moxa-1130.fw.tar
(27 KB)
📄
moxa-1131.fw.fw.tar.gz
(7.09 KB)
📄
moxa-1131.fw.tar
(27 KB)
📄
moxa-1150.fw.fw.tar.gz
(7.09 KB)
📄
moxa-1150.fw.tar
(27 KB)
📄
moxa-1151.fw.fw.tar.gz
(7.09 KB)
📄
moxa-1151.fw.tar
(27 KB)
📄
moxa-1250.fw.fw.tar.gz
(16.63 KB)
📄
moxa-1250.fw.tar
(68 KB)
📄
moxa-1251.fw.fw.tar.gz
(16.63 KB)
📄
moxa-1251.fw.tar
(68 KB)
📄
moxa-1410.fw.fw.tar.gz
(16.52 KB)
📄
moxa-1410.fw.tar
(68 KB)
📄
moxa-1450.fw.fw.tar.gz
(16.52 KB)
📄
moxa-1450.fw.tar
(68 KB)
📄
moxa-1451.fw.fw.tar.gz
(16.52 KB)
📄
moxa-1451.fw.tar
(68 KB)
📄
moxa-1613.fw.fw.tar.gz
(16.57 KB)
📄
moxa-1613.fw.tar
(68 KB)
📄
moxa-1618.fw.fw.tar.gz
(16.55 KB)
📄
moxa-1618.fw.tar
(68 KB)
📄
moxa-1653.fw.fw.tar.gz
(16.57 KB)
📄
moxa-1653.fw.tar
(68 KB)
📄
moxa-1658.fw.fw.tar.gz
(16.55 KB)
📄
moxa-1658.fw.tar
(68 KB)
📄
moxa.tar
(367.5 KB)
📄
moxa.tar.gz
(167.63 KB)
📄
moxa.zip
(357.69 KB)
📄
mpi.mod.mod.tar.gz
(14.85 KB)
📄
mpi.mod.tar
(83 KB)
📄
mpm_itk.json.json.tar.gz
(646 B)
📄
mpm_itk.json.tar
(3.5 KB)
📄
mpr.fw.fw.tar.gz
(2.9 KB)
📄
mpr.fw.tar
(12 KB)
📄
mprintf.h.h.tar.gz
(805 B)
📄
mprintf.h.tar
(4 KB)
📄
mptcp.tar
(4 KB)
📄
mptcp.tar.gz
(155 B)
📄
mptcp.zip
(440 B)
📄
mqtt-tls.xml.tar
(2 KB)
📄
mqtt-tls.xml.xml.tar.gz
(311 B)
📄
mqtt.xml.tar
(2 KB)
📄
mqtt.xml.xml.tar.gz
(302 B)
📄
mqueue.h.h.tar.gz
(1.52 KB)
📄
mqueue.h.tar
(7.5 KB)
📄
mqueue.tar
(6 KB)
📄
mqueue.tar.gz
(191 B)
📄
mqueue.zip
(710 B)
📄
mqueue2.h.h.tar.gz
(1.01 KB)
📄
mqueue2.h.tar
(4 KB)
📄
mro.pm.pm.tar.gz
(4.33 KB)
📄
mro.pm.tar
(11.5 KB)
📄
mro.so.so.tar.gz
(9.3 KB)
📄
mro.so.tar
(25.5 KB)
📄
mro.tar
(25.5 KB)
📄
mro.tar.gz
(9.28 KB)
📄
mro.zip
(23.75 KB)
📄
mrvl.tar
(80.51 MB)
📄
mrvl.tar.gz
(77.56 MB)
📄
mrvl.zip
(80.49 MB)
📄
ms-wbt.xml.tar
(2 KB)
📄
ms-wbt.xml.xml.tar.gz
(248 B)
📄
msbtfw11.mbn.mbn.tar.gz
(138.69 KB)
📄
msbtfw11.mbn.tar
(199.5 KB)
📄
msbtfw11.tlv.tar
(187.5 KB)
📄
msbtfw11.tlv.tlv.tar.gz
(136.69 KB)
📄
msdospart.mod.mod.tar.gz
(1.29 KB)
📄
msdospart.mod.tar
(8 KB)
📄
msg.h.h.tar.gz
(1.13 KB)
📄
msg.h.tar
(4 KB)
📄
msg.tar
(2 KB)
📄
msg.tar.gz
(158 B)
📄
msg_default.tar
(2 KB)
📄
msg_default.tar.gz
(116 B)
📄
msg_max.tar
(2 KB)
📄
msg_max.tar.gz
(112 B)
📄
msg_next_id.tar
(2 KB)
📄
msg_next_id.tar.gz
(112 B)
📄
msgbuf.h.h.tar.gz
(597 B)
📄
msgbuf.h.tar
(3 KB)
📄
msgfmt3.8.py.8.py.tar.gz
(2.61 KB)
📄
msgfmt3.8.py.tar
(9 KB)
📄
msgfmt3.9.py.9.py.tar.gz
(2.61 KB)
📄
msgfmt3.9.py.tar
(9 KB)
📄
msgfmt3.py.py.tar.gz
(2.61 KB)
📄
msgfmt3.py.tar
(17 KB)
📄
msgmax.tar
(2 KB)
📄
msgmax.tar.gz
(110 B)
📄
msgmnb.tar
(2 KB)
📄
msgmnb.tar.gz
(111 B)
📄
msgmni.tar
(2 KB)
📄
msgmni.tar.gz
(111 B)
📄
msgsize_default.tar
(2 KB)
📄
msgsize_default.tar.gz
(122 B)
📄
msgsize_max.tar
(2 KB)
📄
msgsize_max.tar.gz
(118 B)
📄
msm_drm.h.h.tar.gz
(5.38 KB)
📄
msm_drm.h.tar
(17.5 KB)
📄
msnv11.b09.b09.tar.gz
(2.72 KB)
📄
msnv11.b09.tar
(14 KB)
📄
msnv11.b0a.b0a.tar.gz
(2.73 KB)
📄
msnv11.b0a.tar
(14 KB)
📄
msnv11.bin.bin.tar.gz
(2.73 KB)
📄
msnv11.bin.tar
(14 KB)
📄
msp_rdwr.bin.bin.tar.gz
(532 B)
📄
msp_rdwr.bin.tar
(3.5 KB)
📄
msq.h.h.tar.gz
(1.21 KB)
📄
msq.h.tar
(4.5 KB)
📄
msql2mysql.tar
(3 KB)
📄
msql2mysql.tar.gz
(821 B)
📄
msr.h.h.tar.gz
(301 B)
📄
msr.h.tar
(2 KB)
📄
mssql.xml.tar
(2 KB)
📄
mssql.xml.xml.tar.gz
(236 B)
📄
mt-config.cgi.cgi.tar.gz
(524 B)
📄
mt-config.cgi.tar
(2.5 KB)
📄
mt-ftsearch.cgi.cgi.tar.gz
(359 B)
📄
mt-ftsearch.cgi.tar
(2 KB)
📄
mt-search.cgi.cgi.tar.gz
(351 B)
📄
mt-search.cgi.tar
(2 KB)
📄
mt-upgrade.cgi.cgi.tar.gz
(351 B)
📄
mt-upgrade.cgi.tar
(2 KB)
📄
mt-xmlrpc.cgi.cgi.tar.gz
(681 B)
📄
mt-xmlrpc.cgi.tar
(3 KB)
📄
mt.cgi.cgi.tar.gz
(343 B)
📄
mt.cgi.tar
(2 KB)
📄
mt.js.js.tar.gz
(9.41 KB)
📄
mt.js.tar
(36.5 KB)
📄
mt.tar
(234 KB)
📄
mt.tar.gz
(126.13 KB)
📄
mt.zip
(208.64 KB)
📄
mt7601u.bin.bin.tar.gz
(25.7 KB)
📄
mt7601u.bin.tar
(136 KB)
📄
mt7610e.bin.bin.tar.gz
(45.1 KB)
📄
mt7610e.bin.tar
(80.5 KB)
📄
mt7610u.bin.bin.tar.gz
(44.85 KB)
📄
mt7610u.bin.tar
(80 KB)
📄
mt7615_cr4.bin.bin.tar.gz
(119.28 KB)
📄
mt7615_cr4.bin.tar
(121.5 KB)
📄
mt7615_n9.bin.bin.tar.gz
(412.96 KB)
📄
mt7615_n9.bin.tar
(449 KB)
📄
mt7615_rom_patch.bin.bin.tar.gz
(6.08 KB)
📄
mt7615_rom_patch.bin.tar
(12.5 KB)
📄
mt7622_n9.bin.bin.tar.gz
(267.92 KB)
📄
mt7622_n9.bin.tar
(295 KB)
📄
mt7622_rom_patch.bin.bin.tar.gz
(55.83 KB)
📄
mt7622_rom_patch.bin.tar
(82 KB)
📄
mt7622pr2h.bin.bin.tar.gz
(52.51 KB)
📄
mt7622pr2h.bin.tar
(78 KB)
📄
mt7650.bin.bin.tar.gz
(221.48 KB)
📄
mt7650.bin.tar
(1.06 MB)
📄
mt7650e.bin.bin.tar.gz
(233.94 KB)
📄
mt7650e.bin.tar
(375 KB)
📄
mt7662.bin.bin.tar.gz
(52.09 KB)
📄
mt7662.bin.tar
(242.5 KB)
📄
mt7662_rom_patch.bin.bin.tar.gz
(18.07 KB)
📄
mt7662_rom_patch.bin.tar
(54 KB)
📄
mt7662u.bin.bin.tar.gz
(52.02 KB)
📄
mt7662u.bin.tar
(91 KB)
📄
mt7663_n9_v3.bin.bin.tar.gz
(399.28 KB)
📄
mt7663_n9_v3.bin.tar
(433 KB)
📄
mt7663pr2h.bin.bin.tar.gz
(152.6 KB)
📄
mt7663pr2h.bin.tar
(274 KB)
📄
mt7663pr2h_rebb.bin.bin.tar.gz
(143.36 KB)
📄
mt7663pr2h_rebb.bin.tar
(206 KB)
📄
mt7668pr2h.bin.bin.tar.gz
(112.08 KB)
📄
mt7668pr2h.bin.tar
(168.5 KB)
📄
mt7915_eeprom.bin.bin.tar.gz
(868 B)
📄
mt7915_eeprom.bin.tar
(5 KB)
📄
mt7915_rom_patch.bin.bin.tar.gz
(62.46 KB)
📄
mt7915_rom_patch.bin.tar
(143 KB)
📄
mt7915_wa.bin.bin.tar.gz
(69.73 KB)
📄
mt7915_wa.bin.tar
(115 KB)
📄
mt7915_wm.bin.bin.tar.gz
(373.11 KB)
📄
mt7915_wm.bin.tar
(1.2 MB)
📄
mt7916_eeprom.bin.bin.tar.gz
(527 B)
📄
mt7916_eeprom.bin.tar
(5.5 KB)
📄
mt7916_rom_patch.bin.bin.tar.gz
(5.29 KB)
📄
mt7916_rom_patch.bin.tar
(10.5 KB)
📄
mt7916_wa.bin.bin.tar.gz
(199.55 KB)
📄
mt7916_wa.bin.tar
(494 KB)
📄
mt7916_wm.bin.bin.tar.gz
(494.05 KB)
📄
mt7916_wm.bin.tar
(1.69 MB)
📄
mt7925.tar
(1.82 MB)
📄
mt7925.tar.gz
(1.76 MB)
📄
mt7925.zip
(1.82 MB)
📄
mt7981_rom_patch.bin.bin.tar.gz
(5.88 KB)
📄
mt7981_rom_patch.bin.tar
(11.5 KB)
📄
mt7981_wa.bin.bin.tar.gz
(191.02 KB)
📄
mt7981_wa.bin.tar
(484.5 KB)
📄
mt7981_wm.bin.bin.tar.gz
(504.54 KB)
📄
mt7981_wm.bin.tar
(1.96 MB)
📄
mt7981_wo.bin.bin.tar.gz
(51.68 KB)
📄
mt7981_wo.bin.tar
(2.34 MB)
📄
mt7986_rom_patch.bin.bin.tar.gz
(7.93 KB)
📄
mt7986_rom_patch.bin.tar
(14.5 KB)
📄
mt7986_wa.bin.bin.tar.gz
(207.3 KB)
📄
mt7986_wa.bin.tar
(512 KB)
📄
mt7986_wm.bin.bin.tar.gz
(512.72 KB)
📄
mt7986_wm.bin.tar
(2.13 MB)
📄
mt7986_wm_mt7975.bin.bin.tar.gz
(491.23 KB)
📄
mt7986_wm_mt7975.bin.tar
(2.13 MB)
📄
mt7987.tar
(126 KB)
📄
mt7987.tar.gz
(34.78 KB)
📄
mt7987.zip
(124.32 KB)
📄
mt7988.tar
(341.5 KB)
📄
mt7988.tar.gz
(131.59 KB)
📄
mt7988.zip
(338.96 KB)
📄
mt7996.tar
(12.13 MB)
📄
mt7996.tar.gz
(12.04 MB)
📄
mt7996.zip
(12.11 MB)
📄
mt8173.tar
(2.97 MB)
📄
mt8173.tar.gz
(110.5 KB)
📄
mt8173.zip
(2.96 MB)
📄
mt8183.tar
(1008.5 KB)
📄
mt8183.tar.gz
(733.33 KB)
📄
mt8183.zip
(1006.76 KB)
📄
mt8186.tar
(411.5 KB)
📄
mt8186.tar.gz
(154.21 KB)
📄
mt8186.zip
(409.66 KB)
📄
mt8188.tar
(623.5 KB)
📄
mt8188.tar.gz
(324.75 KB)
📄
mt8188.zip
(621.77 KB)
📄
mt8189.tar
(6.28 MB)
📄
mt8189.tar.gz
(1.19 MB)
📄
mt8189.zip
(6.28 MB)
📄
mt8192.tar
(303.5 KB)
📄
mt8192.tar.gz
(173.42 KB)
📄
mt8192.zip
(302.06 KB)
📄
mt8195.tar
(622.5 KB)
📄
mt8195.tar.gz
(317.08 KB)
📄
mt8195.zip
(620.78 KB)
📄
mt8196.tar
(5.49 MB)
📄
mt8196.tar.gz
(372.83 KB)
📄
mt8196.zip
(5.49 MB)
📄
mtd-abi.h.h.tar.gz
(3.67 KB)
📄
mtd-abi.h.tar
(11 KB)
📄
mtd-user.h.h.tar.gz
(768 B)
📄
mtd-user.h.tar
(3 KB)
📄
mtd.tar
(36.5 KB)
📄
mtd.tar.gz
(9.52 KB)
📄
mtd.zip
(32.3 KB)
📄
mtd_probe.tar
(27 KB)
📄
mtd_probe.tar.gz
(4.82 KB)
📄
mthca-abi.h.h.tar.gz
(1.44 KB)
📄
mthca-abi.h.tar
(4.5 KB)
📄
mtio.h.h.tar.gz
(3.91 KB)
📄
mtio.h.tar
(12.5 KB)
📄
mtl_dmc.bin.bin.tar.gz
(15.65 KB)
📄
mtl_dmc.bin.tar
(53 KB)
📄
mtl_gsc_1.bin.bin.tar.gz
(740.56 KB)
📄
mtl_gsc_1.bin.tar
(1.09 MB)
📄
mtl_guc_70.bin.bin.tar.gz
(185.9 KB)
📄
mtl_guc_70.bin.tar
(314.5 KB)
📄
mtl_huc_gsc.bin.bin.tar.gz
(188.9 KB)
📄
mtl_huc_gsc.bin.tar
(549.5 KB)
📄
mts_cdma.fw.fw.tar.gz
(7.6 KB)
📄
mts_cdma.fw.tar
(30 KB)
📄
mts_edge.fw.fw.tar.gz
(7.69 KB)
📄
mts_edge.fw.tar
(30 KB)
📄
mts_gsm.fw.fw.tar.gz
(7.6 KB)
📄
mts_gsm.fw.tar
(30 KB)
📄
mts_mt9234mu.fw.fw.tar.gz
(7.55 KB)
📄
mts_mt9234mu.fw.tar
(15 KB)
📄
mts_mt9234zba.fw.fw.tar.gz
(7.56 KB)
📄
mts_mt9234zba.fw.tar
(15 KB)
📄
mtu.tar
(6 KB)
📄
mtu.tar.gz
(117 B)
📄
mtu_expires.tar
(3 KB)
📄
mtu_expires.tar.gz
(120 B)
📄
mul_test.mod.mod.tar.gz
(1.2 KB)
📄
mul_test.mod.tar
(4 KB)
📄
mullins_ce.bin.bin.tar.gz
(1.56 KB)
📄
mullins_ce.bin.tar
(20 KB)
📄
mullins_me.bin.bin.tar.gz
(4.14 KB)
📄
mullins_me.bin.tar
(20 KB)
📄
mullins_mec.bin.bin.tar.gz
(8.87 KB)
📄
mullins_mec.bin.tar
(36 KB)
📄
mullins_pfp.bin.bin.tar.gz
(3.89 KB)
📄
mullins_pfp.bin.tar
(20 KB)
📄
mullins_rlc.bin.bin.tar.gz
(5.42 KB)
📄
mullins_rlc.bin.tar
(23 KB)
📄
mullins_sdma.bin.bin.tar.gz
(2.26 KB)
📄
mullins_sdma.bin.tar
(11 KB)
📄
mullins_uvd.bin.bin.tar.gz
(154.46 KB)
📄
mullins_uvd.bin.tar
(457 KB)
📄
mullins_vce.bin.bin.tar.gz
(62.65 KB)
📄
mullins_vce.bin.tar
(200 KB)
📄
multi-user.target.tar
(2.5 KB)
📄
multi-user.target.target.tar.gz
(432 B)
📄
multi.h.h.tar.gz
(4.96 KB)
📄
multi.h.tar
(17.5 KB)
📄
multiboot.mod.mod.tar.gz
(8.63 KB)
📄
multiboot.mod.tar
(45 KB)
📄
multiboot2.mod.mod.tar.gz
(9.29 KB)
📄
multiboot2.mod.tar
(24 KB)
📄
multifile.py.py.tar.gz
(1.62 KB)
📄
multifile.py.tar
(6.5 KB)
📄
multifile.pyc.pyc.tar.gz
(2.34 KB)
📄
multifile.pyc.tar
(7 KB)
📄
multiprocessing.tar
(1.86 MB)
📄
multiprocessing.tar.gz
(255.09 KB)
📄
multiprocessing.zip
(1.75 MB)
📄
multisite.sql.sql.tar.gz
(8.43 KB)
📄
multisite.sql.tar
(783.5 KB)
📄
murmur.xml.tar
(3 KB)
📄
murmur.xml.xml.tar.gz
(257 B)
📄
mutex.py.py.tar.gz
(834 B)
📄
mutex.py.tar
(3.5 KB)
📄
mutex.pyc.pyc.tar.gz
(1.21 KB)
📄
mutex.pyc.tar
(4 KB)
📄
mutex.pyo.pyo.tar.gz
(1.21 KB)
📄
mutex.pyo.tar
(4 KB)
📄
mutex_m.rb.rb.tar.gz
(886 B)
📄
mutex_m.rb.tar
(12.5 KB)
📄
mv.tar
(146.5 KB)
📄
mv.tar.gz
(70.44 KB)
📄
mw.tar
(313.5 KB)
📄
mw.tar.gz
(188.03 KB)
📄
mw.zip
(284.6 KB)
📄
mw14.sql.sql.tar.gz
(7.27 KB)
📄
mw14.sql.tar
(48.5 KB)
📄
mw14.tar
(95.12 MB)
📄
mw14.tar.gz
(88.1 MB)
📄
mw14.zip
(95.09 MB)
📄
mw19.sql.sql.tar.gz
(7.4 KB)
📄
mw19.sql.tar
(48 KB)
📄
mw19.tar
(68.09 MB)
📄
mw19.tar.gz
(63.5 MB)
📄
mw19.zip
(68.06 MB)
📄
mw28.tar
(263.5 KB)
📄
mw28.tar.gz
(158.73 KB)
📄
mw28.zip
(239.21 KB)
📄
mw35.tar
(295 KB)
📄
mw35.tar.gz
(178.42 KB)
📄
mw35.zip
(269.61 KB)
📄
mwl8k.tar
(598.5 KB)
📄
mwl8k.tar.gz
(410.03 KB)
📄
mwl8k.zip
(592.53 KB)
📄
mwlwifi.tar
(594 KB)
📄
mwlwifi.tar.gz
(412.23 KB)
📄
mwlwifi.zip
(591.53 KB)
📄
my.cnf.cnf.tar.gz
(524 B)
📄
my.cnf.d.tar
(7.5 KB)
📄
my.cnf.d.tar.gz
(1.25 KB)
📄
my.cnf.d.zip
(3.24 KB)
📄
my.cnf.tar
(2.5 KB)
📄
my.php.php.tar.gz
(333 B)
📄
my.php.tar
(2.5 KB)
📄
my_alloca.h.h.tar.gz
(212 B)
📄
my_alloca.h.tar
(4 KB)
📄
my_attribute.h.h.tar.gz
(1.43 KB)
📄
my_attribute.h.tar
(5 KB)
📄
my_byteorder.h.h.tar.gz
(1.06 KB)
📄
my_byteorder.h.tar
(4 KB)
📄
my_cmp.h.h.tar.gz
(623 B)
📄
my_cmp.h.tar
(2.5 KB)
📄
my_compiler.h.h.tar.gz
(2.22 KB)
📄
my_compiler.h.tar
(7 KB)
📄
my_config.h.h.tar.gz
(215 B)
📄
my_config.h.tar
(17 KB)
📄
my_config.php.php.tar.gz
(6.29 KB)
📄
my_config.php.tar
(20 KB)
📄
my_dbug.h.h.tar.gz
(3.05 KB)
📄
my_dbug.h.tar
(11.5 KB)
📄
my_dir.h.h.tar.gz
(1.67 KB)
📄
my_dir.h.tar
(5.5 KB)
📄
my_getopt.h.h.tar.gz
(2 KB)
📄
my_getopt.h.tar
(7 KB)
📄
my_global.h.h.tar.gz
(213 B)
📄
my_global.h.tar
(35 KB)
📄
my_list.h.h.tar.gz
(845 B)
📄
my_list.h.tar
(3 KB)
📄
my_net.h.h.tar.gz
(1.08 KB)
📄
my_net.h.tar
(3.5 KB)
📄
my_print_defaults.tar
(4.57 MB)
📄
my_print_defaults.tar.gz
(1013.71 KB)
📄
my_pthread.h.h.tar.gz
(8.1 KB)
📄
my_pthread.h.tar
(28.5 KB)
📄
my_sys.h.h.tar.gz
(211 B)
📄
my_sys.h.tar
(52 KB)
📄
my_xml.h.h.tar.gz
(1.22 KB)
📄
my_xml.h.tar
(4.5 KB)
📄
myadmin.tar
(16.17 MB)
📄
myadmin.tar.gz
(14.99 MB)
📄
myadmin.zip
(16.15 MB)
📄
myadmin49.tar
(177.5 KB)
📄
myadmin49.tar.gz
(100.45 KB)
📄
myadmin49.zip
(155.74 KB)
📄
mybb.png.png.tar.gz
(6.02 KB)
📄
mybb.png.tar
(8 KB)
📄
mybb.sql.sql.tar.gz
(130.85 KB)
📄
mybb.sql.tar
(828.5 KB)
📄
mybb.tar
(3.85 MB)
📄
mybb.tar.gz
(2.82 MB)
📄
mybb.zip
(3.82 MB)
📄
mydtrace.h.h.tar.gz
(647 B)
📄
mydtrace.h.tar
(3.5 KB)
📄
myfaq.tar
(18.46 MB)
📄
myfaq.tar.gz
(16.66 MB)
📄
myfaq.zip
(18.44 MB)
📄
myri10ge_eth_z8e.dat.dat.tar.gz
(118.72 KB)
📄
myri10ge_eth_z8e.dat.tar
(371.5 KB)
📄
myri10ge_ethp_big_z8e.dat.dat.tar.gz
(119.42 KB)
📄
myri10ge_ethp_big_z8e.dat.tar
(382 KB)
📄
myri10ge_ethp_z8e.dat.dat.tar.gz
(119.27 KB)
📄
myri10ge_ethp_z8e.dat.tar
(381.5 KB)
📄
myri10ge_rss_eth_big_z8e.dat.dat.tar.gz
(149.71 KB)
📄
myri10ge_rss_eth_big_z8e.dat.tar
(525.5 KB)
📄
myri10ge_rss_ethp_big_z8e.dat.dat.tar.gz
(150.63 KB)
📄
myri10ge_rss_ethp_big_z8e.dat.tar
(535 KB)
📄
myri10ge_rss_ethp_z8e.dat.dat.tar.gz
(150.59 KB)
📄
myri10ge_rss_ethp_z8e.dat.tar
(535 KB)
📄
myricom.tar
(76 KB)
📄
myricom.tar.gz
(25.29 KB)
📄
myricom.zip
(74.62 KB)
📄
mysql.h.h.tar.gz
(8.81 KB)
📄
mysql.h.tar
(43.5 KB)
📄
mysql.service.service.tar.gz
(2.58 KB)
📄
mysql.service.tar
(7.5 KB)
📄
mysql.tar
(12.47 MB)
📄
mysql.tar.gz
(1.29 MB)
📄
mysql.xml.tar
(2 KB)
📄
mysql.xml.xml.tar.gz
(238 B)
📄
mysql.zip
(6.82 MB)
📄
mysql5.5.tar
(600.5 KB)
📄
mysql5.5.tar.gz
(70.7 KB)
📄
mysql5.5.zip
(590.45 KB)
📄
mysql5.6.tar
(569.5 KB)
📄
mysql5.6.tar.gz
(68.85 KB)
📄
mysql5.6.zip
(572.06 KB)
📄
mysql5.7.tar
(345 KB)
📄
mysql5.7.tar.gz
(69.51 KB)
📄
mysql5.7.zip
(364.56 KB)
📄
mysql8.0.tar
(565.5 KB)
📄
mysql8.0.tar.gz
(68.89 KB)
📄
mysql8.0.zip
(542.06 KB)
📄
mysql8.4.tar
(476.5 KB)
📄
mysql8.4.tar.gz
(68.79 KB)
📄
mysql8.4.zip
(472.38 KB)
📄
mysql_clear_password.so.so.tar.gz
(2.6 KB)
📄
mysql_clear_password.so.tar
(8.5 KB)
📄
mysql_com.h.h.tar.gz
(9.54 KB)
📄
mysql_com.h.tar
(32 KB)
📄
mysql_config.tar
(6 KB)
📄
mysql_config.tar.gz
(1.85 KB)
📄
mysql_find_rows.tar
(5 KB)
📄
mysql_find_rows.tar.gz
(1.61 KB)
📄
mysql_ps.h.h.tar.gz
(1.3 KB)
📄
mysql_ps.h.tar
(5.5 KB)
📄
mysql_sp.h.h.tar.gz
(1.2 KB)
📄
mysql_sp.h.tar
(5 KB)
📄
mysql_time.h.h.tar.gz
(1.33 KB)
📄
mysql_time.h.tar
(4 KB)
📄
mysql_version.h.h.tar.gz
(278 B)
📄
mysql_version.h.tar
(2 KB)
📄
mysql_waitpid.tar
(4.56 MB)
📄
mysql_waitpid.tar.gz
(1013.16 KB)
📄
mysqlaccess.tar
(111 KB)
📄
mysqlaccess.tar.gz
(25.16 KB)
📄
mysqladmin.tar
(4.89 MB)
📄
mysqladmin.tar.gz
(1.11 MB)
📄
mysqlbinlog.tar
(5.17 MB)
📄
mysqlbinlog.tar.gz
(1.25 MB)
📄
mysqlcheck.tar
(4.89 MB)
📄
mysqlcheck.tar.gz
(1.11 MB)
📄
mysqld.service.service.tar.gz
(2.58 KB)
📄
mysqld.service.tar
(7.5 KB)
📄
mysqld_error.h.h.tar.gz
(13.57 KB)
📄
mysqld_error.h.tar
(52 KB)
📄
mysqldump.tar
(4.99 MB)
📄
mysqldump.tar.gz
(1.15 MB)
📄
mysqlimport.tar
(4.88 MB)
📄
mysqlimport.tar.gz
(1.11 MB)
📄
mysqlshow.tar
(4.88 MB)
📄
mysqlshow.tar.gz
(1.11 MB)
📄
myt.png.png.tar.gz
(7.03 KB)
📄
myt.png.tar
(9 KB)
📄
myt.tar
(183.5 KB)
📄
myt.tar.gz
(107.98 KB)
📄
myt.zip
(165.34 KB)
📄
mytop.tar
(74 KB)
📄
mytop.tar.gz
(20.98 KB)
📄
myweb.tar
(113 KB)
📄
myweb.tar.gz
(61.62 KB)
📄
myweb.zip
(94.54 KB)
📄
named-checkzone.tar
(38.5 KB)
📄
named-checkzone.tar.gz
(13.42 KB)
📄
named-compilezone.tar
(38.5 KB)
📄
named-compilezone.tar.gz
(13.42 KB)
📄
named.conf.conf.tar.gz
(128 B)
📄
named.conf.tar
(2 KB)
📄
named.service.service.tar.gz
(579 B)
📄
named.service.tar
(4 KB)
📄
namei.tar
(35 KB)
📄
namei.tar.gz
(13.98 KB)
📄
nameser.h.h.tar.gz
(4.77 KB)
📄
nameser.h.tar
(15.5 KB)
📄
nameser_compat.h.h.tar.gz
(2.68 KB)
📄
nameser_compat.h.tar
(8.5 KB)
📄
namespaceobject.h.h.tar.gz
(307 B)
📄
namespaceobject.h.tar
(2 KB)
📄
nano.tar
(249.5 KB)
📄
nano.tar.gz
(121.42 KB)
📄
nativedisk.mod.mod.tar.gz
(2.44 KB)
📄
nativedisk.mod.tar
(7 KB)
📄
nau8825-tplg.bin.bin.tar.gz
(766 B)
📄
nau8825-tplg.bin.tar
(6 KB)
📄
navi10_asd.bin.bin.tar.gz
(65.75 KB)
📄
navi10_asd.bin.tar
(202 KB)
📄
navi10_ce.bin.bin.tar.gz
(4.55 KB)
📄
navi10_ce.bin.tar
(259 KB)
📄
navi10_gpu_info.bin.bin.tar.gz
(327 B)
📄
navi10_gpu_info.bin.tar
(2.5 KB)
📄
navi10_me.bin.bin.tar.gz
(9.29 KB)
📄
navi10_me.bin.tar
(259 KB)
📄
navi10_mec.bin.bin.tar.gz
(36.14 KB)
📄
navi10_mec.bin.tar
(263.5 KB)
📄
navi10_mec2.bin.bin.tar.gz
(36.14 KB)
📄
navi10_mec2.bin.tar
(263.5 KB)
📄
navi10_pfp.bin.bin.tar.gz
(16.57 KB)
📄
navi10_pfp.bin.tar
(259 KB)
📄
navi10_rlc.bin.bin.tar.gz
(16.19 KB)
📄
navi10_rlc.bin.tar
(44.5 KB)
📄
navi10_sdma.bin.bin.tar.gz
(10.26 KB)
📄
navi10_sdma.bin.tar
(34.5 KB)
📄
navi10_sdma1.bin.bin.tar.gz
(10.26 KB)
📄
navi10_sdma1.bin.tar
(34.5 KB)
📄
navi10_smc.bin.bin.tar.gz
(93.58 KB)
📄
navi10_smc.bin.tar
(263.5 KB)
📄
navi10_sos.bin.bin.tar.gz
(105.06 KB)
📄
navi10_sos.bin.tar
(182 KB)
📄
navi10_ta.bin.bin.tar.gz
(13.72 KB)
📄
navi10_ta.bin.tar
(38.5 KB)
📄
navi10_vcn.bin.bin.tar.gz
(279.76 KB)
📄
navi10_vcn.bin.tar
(397 KB)
📄
navi12_asd.bin.bin.tar.gz
(65.75 KB)
📄
navi12_asd.bin.tar
(202 KB)
📄
navi12_ce.bin.bin.tar.gz
(4.55 KB)
📄
navi12_ce.bin.tar
(259 KB)
📄
navi12_dmcu.bin.bin.tar.gz
(12.18 KB)
📄
navi12_dmcu.bin.tar
(25 KB)
📄
navi12_gpu_info.bin.bin.tar.gz
(338 B)
📄
navi12_gpu_info.bin.tar
(2.5 KB)
📄
navi12_me.bin.bin.tar.gz
(9.3 KB)
📄
navi12_me.bin.tar
(259 KB)
📄
navi12_mec.bin.bin.tar.gz
(36.02 KB)
📄
navi12_mec.bin.tar
(263.5 KB)
📄
navi12_mec2.bin.bin.tar.gz
(36.03 KB)
📄
navi12_mec2.bin.tar
(263.5 KB)
📄
navi12_pfp.bin.bin.tar.gz
(16.65 KB)
📄
navi12_pfp.bin.tar
(259 KB)
📄
navi12_rlc.bin.bin.tar.gz
(16.76 KB)
📄
navi12_rlc.bin.tar
(44.5 KB)
📄
navi12_sdma.bin.bin.tar.gz
(10.33 KB)
📄
navi12_sdma.bin.tar
(34.5 KB)
📄
navi12_sdma1.bin.bin.tar.gz
(10.32 KB)
📄
navi12_sdma1.bin.tar
(34.5 KB)
📄
navi12_smc.bin.bin.tar.gz
(92.7 KB)
📄
navi12_smc.bin.tar
(260 KB)
📄
navi12_sos.bin.bin.tar.gz
(120.61 KB)
📄
navi12_sos.bin.tar
(201.5 KB)
📄
navi12_ta.bin.bin.tar.gz
(13.72 KB)
📄
navi12_ta.bin.tar
(38.5 KB)
📄
navi12_vcn.bin.bin.tar.gz
(279.76 KB)
📄
navi12_vcn.bin.tar
(397 KB)
📄
navi14_asd.bin.bin.tar.gz
(65.75 KB)
📄
navi14_asd.bin.tar
(202 KB)
📄
navi14_ce.bin.bin.tar.gz
(4.55 KB)
📄
navi14_ce.bin.tar
(259 KB)
📄
navi14_gpu_info.bin.bin.tar.gz
(326 B)
📄
navi14_gpu_info.bin.tar
(2.5 KB)
📄
navi14_me.bin.bin.tar.gz
(9.29 KB)
📄
navi14_me.bin.tar
(259 KB)
📄
navi14_mec.bin.bin.tar.gz
(36.03 KB)
📄
navi14_mec.bin.tar
(263.5 KB)
📄
navi14_mec2.bin.bin.tar.gz
(36.04 KB)
📄
navi14_mec2.bin.tar
(263.5 KB)
📄
navi14_mec2_wks.bin.bin.tar.gz
(34.13 KB)
📄
navi14_mec2_wks.bin.tar
(264 KB)
📄
navi14_mec_wks.bin.bin.tar.gz
(34.13 KB)
📄
navi14_mec_wks.bin.tar
(264 KB)
📄
navi14_pfp.bin.bin.tar.gz
(16.65 KB)
📄
navi14_pfp.bin.tar
(259 KB)
📄
navi14_pfp_wks.bin.bin.tar.gz
(15.06 KB)
📄
navi14_pfp_wks.bin.tar
(259 KB)
📄
navi14_rlc.bin.bin.tar.gz
(15.75 KB)
📄
navi14_rlc.bin.tar
(43.5 KB)
📄
navi14_sdma.bin.bin.tar.gz
(10.23 KB)
📄
navi14_sdma.bin.tar
(34.5 KB)
📄
navi14_sdma1.bin.bin.tar.gz
(10.23 KB)
📄
navi14_sdma1.bin.tar
(34.5 KB)
📄
navi14_smc.bin.bin.tar.gz
(92.36 KB)
📄
navi14_smc.bin.tar
(260 KB)
📄
navi14_sos.bin.bin.tar.gz
(104.6 KB)
📄
navi14_sos.bin.tar
(181.5 KB)
📄
navi14_ta.bin.bin.tar.gz
(13.72 KB)
📄
navi14_ta.bin.tar
(38.5 KB)
📄
navi14_vcn.bin.bin.tar.gz
(279.76 KB)
📄
navi14_vcn.bin.tar
(397 KB)
📄
navy_flounder_mec.bin.bin.tar.gz
(41.71 KB)
📄
navy_flounder_mec.bin.tar
(263.5 KB)
📄
navy_flounder_mec2.bin.bin.tar.gz
(41.71 KB)
📄
navy_flounder_mec2.bin.tar
(263.5 KB)
📄
navy_flounder_pfp.bin.bin.tar.gz
(16.54 KB)
📄
navy_flounder_pfp.bin.tar
(259 KB)
📄
navy_flounder_rlc.bin.bin.tar.gz
(52.4 KB)
📄
navy_flounder_rlc.bin.tar
(136 KB)
📄
navy_flounder_sdma.bin.bin.tar.gz
(12.22 KB)
📄
navy_flounder_sdma.bin.tar
(35 KB)
📄
navy_flounder_smc.bin.bin.tar.gz
(112.48 KB)
📄
navy_flounder_smc.bin.tar
(241 KB)
📄
navy_flounder_sos.bin.bin.tar.gz
(125.37 KB)
📄
navy_flounder_sos.bin.tar
(215 KB)
📄
navy_flounder_ta.bin.bin.tar.gz
(81.97 KB)
📄
navy_flounder_ta.bin.tar
(251 KB)
📄
navy_flounder_vcn.bin.bin.tar.gz
(406.83 KB)
📄
navy_flounder_vcn.bin.tar
(568.5 KB)
📄
nbd.xml.tar
(3 KB)
📄
nbd.xml.xml.tar.gz
(281 B)
📄
nc_tparm.h.h.tar.gz
(1.34 KB)
📄
nc_tparm.h.tar
(16 KB)
📄
ncm865.tar
(6.25 MB)
📄
ncm865.tar.gz
(3.14 MB)
📄
ncurses++.pc.pc.tar.gz
(377 B)
📄
ncurses++.pc.tar
(2 KB)
📄
ncurses.h.h.tar.gz
(19.66 KB)
📄
ncurses.h.tar
(197 KB)
📄
ncurses.pc.pc.tar.gz
(359 B)
📄
ncurses.pc.tar
(2 KB)
📄
ncurses_dll.h.h.tar.gz
(1.7 KB)
📄
ncurses_dll.h.tar
(11 KB)
📄
ncursesw.pc.pc.tar.gz
(359 B)
📄
ncursesw.pc.tar
(2 KB)
📄
ndbm.h.h.tar.gz
(1.19 KB)
📄
ndbm.h.tar
(7 KB)
📄
ndbm.py.py.tar.gz
(165 B)
📄
ndbm.py.tar
(3 KB)
📄
ndiff.pyc.pyc.tar.gz
(1.98 KB)
📄
ndiff.pyc.tar
(5.5 KB)
📄
ndiff.pyo.pyo.tar.gz
(1.98 KB)
📄
ndiff.pyo.tar
(5.5 KB)
📄
ndisc_notify.tar
(2 KB)
📄
ndisc_notify.tar.gz
(122 B)
📄
ndisc_tclass.tar
(2 KB)
📄
ndisc_tclass.tar.gz
(120 B)
📄
neigh.tar
(85 KB)
📄
neigh.tar.gz
(1.53 KB)
📄
neigh.zip
(12.66 KB)
📄
neqn.tar
(2.5 KB)
📄
neqn.tar.gz
(649 B)
📄
net-snmp-config.tar
(34 KB)
📄
net-snmp-config.tar.gz
(7.62 KB)
📄
net-snmp11.tar
(10.02 MB)
📄
net-snmp11.tar.gz
(2.73 MB)
📄
net-snmp11.zip
(9.96 MB)
📄
net.mod.mod.tar.gz
(40.33 KB)
📄
net.mod.tar
(200 KB)
📄
net.tar
(419 KB)
📄
net.tar.gz
(78.5 KB)
📄
net.zip
(400.58 KB)
📄
net2ftp.tar
(87 KB)
📄
net2ftp.tar.gz
(41.29 KB)
📄
net2ftp.zip
(73.15 KB)
📄
netash.tar
(3 KB)
📄
netash.tar.gz
(833 B)
📄
netash.zip
(1.47 KB)
📄
netatalk.tar
(3 KB)
📄
netatalk.tar.gz
(645 B)
📄
netatalk.zip
(1.14 KB)
📄
netax25.tar
(6.5 KB)
📄
netax25.tar.gz
(1.77 KB)
📄
netax25.zip
(4.84 KB)
📄
netbios-ns.xml.tar
(2 KB)
📄
netbios-ns.xml.xml.tar.gz
(223 B)
📄
netdb.h.h.tar.gz
(5.82 KB)
📄
netdb.h.tar
(37.5 KB)
📄
netdev_budget.tar
(2 KB)
📄
netdev_budget.tar.gz
(116 B)
📄
netdev_max_backlog.tar
(2 KB)
📄
netdev_max_backlog.tar.gz
(121 B)
📄
netdev_rss_key.tar
(2 KB)
📄
netdev_rss_key.tar.gz
(120 B)
📄
neteconet.tar
(3.5 KB)
📄
neteconet.tar.gz
(899 B)
📄
neteconet.zip
(1.77 KB)
📄
netfilter.tar
(65 KB)
📄
netfilter.tar.gz
(1.45 KB)
📄
netfilter.zip
(10.44 KB)
📄
netinet.tar
(97.5 KB)
📄
netinet.tar.gz
(20.86 KB)
📄
netinet.zip
(88.42 KB)
📄
netipx.tar
(4.5 KB)
📄
netipx.tar.gz
(1.21 KB)
📄
netipx.zip
(2.97 KB)
📄
netiucv.tar
(3.5 KB)
📄
netiucv.tar.gz
(907 B)
📄
netiucv.zip
(1.7 KB)
📄
netpacket.tar
(4 KB)
📄
netpacket.tar.gz
(1.09 KB)
📄
netpacket.zip
(2.49 KB)
📄
netrc.py.py.tar.gz
(1.75 KB)
📄
netrc.py.tar
(20 KB)
📄
netrc.pyc.pyc.tar.gz
(2.4 KB)
📄
netrc.pyc.tar
(6.5 KB)
📄
netrc.pyo.pyo.tar.gz
(2.4 KB)
📄
netrc.pyo.tar
(6.5 KB)
📄
netrom.h.h.tar.gz
(1.04 KB)
📄
netrom.h.tar
(4 KB)
📄
netrom.tar
(4 KB)
📄
netrom.tar.gz
(1.03 KB)
📄
netrom.zip
(2.32 KB)
📄
netronome.tar
(140.17 MB)
📄
netronome.tar.gz
(16.72 MB)
📄
netronome.zip
(140.14 MB)
📄
netrose.tar
(5 KB)
📄
netrose.tar.gz
(1.34 KB)
📄
netrose.zip
(3.25 KB)
📄
network-latency.tar
(2.5 KB)
📄
network-latency.tar.gz
(426 B)
📄
network-latency.zip
(702 B)
📄
network-throughput.tar
(2 KB)
📄
network-throughput.tar.gz
(409 B)
📄
network-throughput.zip
(653 B)
📄
network.tar
(2 KB)
📄
network.tar.gz
(381 B)
📄
network.target.tar
(2.5 KB)
📄
network.target.target.tar.gz
(435 B)
📄
network.zip
(626 B)
📄
networking.go.go.tar.gz
(2.15 KB)
📄
networking.go.tar
(10.5 KB)
📄
new.py.py.tar.gz
(404 B)
📄
new.py.tar
(2.5 KB)
📄
new.pyc.pyc.tar.gz
(600 B)
📄
new.pyc.tar
(2.5 KB)
📄
new.pyo.pyo.tar.gz
(600 B)
📄
new.pyo.tar
(2.5 KB)
📄
new.tar
(50 KB)
📄
new.tar.gz
(9.74 KB)
📄
new.zip
(43.02 KB)
📄
new_code.bin.bin.tar.gz
(2.14 KB)
📄
new_code.bin.tar
(5 KB)
📄
new_code_fix.bin.bin.tar.gz
(697 B)
📄
new_code_fix.bin.tar
(2.5 KB)
📄
new_order.html.html.tar.gz
(4.12 KB)
📄
new_order.html.tar
(58.5 KB)
📄
newc.mod.mod.tar.gz
(2.13 KB)
📄
newc.mod.tar
(11 KB)
📄
newmetaclasses.tar
(39 KB)
📄
newmetaclasses.tar.gz
(6.27 KB)
📄
newmetaclasses.zip
(34.24 KB)
📄
newrelic-daemon.tar
(14.11 MB)
📄
newrelic-daemon.tar.gz
(5.17 MB)
📄
newrelic.tar
(11 KB)
📄
newrelic.tar.gz
(3.24 KB)
📄
newrelic.xml.tar
(23 KB)
📄
newrelic.xml.xml.tar.gz
(583 B)
📄
newrelic.zip
(9.4 KB)
📄
newsletter.zip
(106.74 KB)
📄
nextcloud.sql.sql.tar.gz
(30.04 KB)
📄
nextcloud.sql.tar
(220 KB)
📄
nextcloud.tar
(738.31 MB)
📄
nextcloud.tar.gz
(0 B)
📄
nextcloud.zip
(738.28 MB)
📄
nf_conntrack_events.tar
(2 KB)
📄
nf_conntrack_events.tar.gz
(123 B)
📄
nf_conntrack_helper.tar
(2 KB)
📄
nf_conntrack_helper.tar.gz
(124 B)
📄
nf_conntrack_max.tar
(3 KB)
📄
nf_conntrack_max.tar.gz
(125 B)
📄
nf_conntrack_timestamp.tar
(2 KB)
📄
nf_conntrack_timestamp.tar.gz
(127 B)
📄
nf_log.tar
(14 KB)
📄
nf_log.tar.gz
(297 B)
📄
nf_log.zip
(1.58 KB)
📄
nf_log_all_netns.tar
(2 KB)
📄
nf_log_all_netns.tar.gz
(119 B)
📄
nfs-client.target.tar
(2 KB)
📄
nfs-client.target.target.tar.gz
(344 B)
📄
nfs-convert.service.service.tar.gz
(376 B)
📄
nfs-convert.service.tar
(2.5 KB)
📄
nfs-utils.service.service.tar.gz
(428 B)
📄
nfs-utils.service.tar
(2.5 KB)
📄
nfs.h.h.tar.gz
(117 B)
📄
nfs.h.tar
(2 KB)
📄
nfs.tar
(10 KB)
📄
nfs.tar.gz
(281 B)
📄
nfs.xml.tar
(3 KB)
📄
nfs.xml.xml.tar.gz
(322 B)
📄
nfs.zip
(1.29 KB)
📄
nfs3.xml.tar
(2 KB)
📄
nfs3.xml.xml.tar.gz
(313 B)
📄
nfs_congestion_kb.tar
(2 KB)
📄
nfs_congestion_kb.tar.gz
(118 B)
📄
nfs_debug.tar
(2 KB)
📄
nfs_debug.tar.gz
(114 B)
📄
nfsd_debug.tar
(2 KB)
📄
nfsd_debug.tar.gz
(115 B)
📄
nfsdcld.service.service.tar.gz
(264 B)
📄
nfsdcld.service.tar
(2 KB)
📄
nftables.service.service.tar.gz
(347 B)
📄
nftables.service.tar
(2 KB)
📄
nftl-user.h.h.tar.gz
(1.1 KB)
📄
nftl-user.h.tar
(4 KB)
📄
nghttp2.tar
(888 KB)
📄
nghttp2.tar.gz
(259.25 KB)
📄
nghttp2.zip
(880.82 KB)
📄
nginx_status.tar
(2 KB)
📄
nginx_status.tar.gz
(111 B)
📄
ngroups_max.tar
(2 KB)
📄
ngroups_max.tar.gz
(116 B)
📄
nibble.tar
(102 KB)
📄
nibble.tar.gz
(51.3 KB)
📄
nibble.zip
(84.12 KB)
📄
nic-sriov.tar
(57.62 MB)
📄
nic-sriov.tar.gz
(3.14 MB)
📄
nic-sriov.zip
(57.61 MB)
📄
nic.tar
(37.2 MB)
📄
nic.tar.gz
(3.02 MB)
📄
nic.zip
(37.19 MB)
📄
nic_AMDA0058-0011_2x40.nffw.nffw.tar.gz
(2.73 MB)
📄
nic_AMDA0058-0011_2x40.nffw.tar
(6.54 MB)
📄
nic_AMDA0078-0011_8x10.nffw.nffw.tar.gz
(2.73 MB)
📄
nic_AMDA0078-0011_8x10.nffw.tar
(6.54 MB)
📄
nic_AMDA0097.nffw.nffw.tar.gz
(1.76 MB)
📄
nic_AMDA0097.nffw.tar
(4.21 MB)
📄
nice.tar
(39 KB)
📄
nice.tar.gz
(16.43 KB)
📄
nilfs2.mod.mod.tar.gz
(4.48 KB)
📄
nilfs2.mod.tar
(22 KB)
📄
ninja.sql.sql.tar.gz
(70.49 KB)
📄
ninja.sql.tar
(460 KB)
📄
ninja.tar
(253.26 MB)
📄
ninja.tar.gz
(230.48 MB)
📄
ninja.zip
(253.22 MB)
📄
ninja4.tar
(317 KB)
📄
ninja4.tar.gz
(176.83 KB)
📄
ninja4.zip
(281.22 KB)
📄
nis-domainname.service.service.tar.gz
(338 B)
📄
nis-domainname.service.tar
(2 KB)
📄
nkf.so.so.tar.gz
(136.21 KB)
📄
nkf.so.tar
(313 KB)
📄
nl.tar
(177 KB)
📄
nl.tar.gz
(19.41 KB)
📄
nl.zip
(113.66 KB)
📄
nl_types.h.h.tar.gz
(1004 B)
📄
nl_types.h.tar
(3.5 KB)
📄
nlm_debug.tar
(2 KB)
📄
nlm_debug.tar.gz
(112 B)
📄
nlm_end_grace.tar
(2 KB)
📄
nlm_end_grace.tar.gz
(112 B)
📄
nlm_grace_period.tar
(2 KB)
📄
nlm_grace_period.tar.gz
(115 B)
📄
nlm_tcpport.tar
(2 KB)
📄
nlm_tcpport.tar.gz
(110 B)
📄
nlm_timeout.tar
(2 KB)
📄
nlm_timeout.tar.gz
(111 B)
📄
nlm_udpport.tar
(2 KB)
📄
nlm_udpport.tar.gz
(110 B)
📄
nm-shared.xml.tar
(2.5 KB)
📄
nm-shared.xml.xml.tar.gz
(530 B)
📄
nm.tar
(52 KB)
📄
nm.tar.gz
(22.19 KB)
📄
nm2def.py.py.tar.gz
(1.21 KB)
📄
nm2def.py.tar
(4 KB)
📄
nmea-0183.xml.tar
(2 KB)
📄
nmea-0183.xml.xml.tar.gz
(290 B)
📄
nmi_watchdog.tar
(2 KB)
📄
nmi_watchdog.tar.gz
(113 B)
📄
nntplib.py.py.tar.gz
(11.39 KB)
📄
nntplib.py.tar
(108.5 KB)
📄
nntplib.pyc.pyc.tar.gz
(7.4 KB)
📄
nntplib.pyc.tar
(22.5 KB)
📄
nntplib.pyo.pyo.tar.gz
(7.4 KB)
📄
nntplib.pyo.tar
(22.5 KB)
📄
no-route.xml.tar
(2 KB)
📄
no-route.xml.xml.tar.gz
(259 B)
📄
noarch-linux.tar
(4.5 KB)
📄
noarch-linux.tar.gz
(1.15 KB)
📄
noarch-linux.zip
(3.01 KB)
📄
node-gyp-bin.tar
(3 KB)
📄
node-gyp-bin.tar.gz
(290 B)
📄
node-gyp-bin.zip
(598 B)
📄
node.h.h.tar.gz
(643 B)
📄
node.h.tar
(3 KB)
📄
node.rb.rb.tar.gz
(933 B)
📄
node.rb.tar
(19 KB)
📄
node.tar
(30 KB)
📄
node.tar.gz
(99 B)
📄
node_modules.tar
(15.85 MB)
📄
node_modules.tar.gz
(3.67 MB)
📄
node_modules.zip
(13.85 MB)
📄
node_record.h.h.tar.gz
(687 B)
📄
node_record.h.tar
(4.5 KB)
📄
nodeenv.tar
(2 KB)
📄
nodeenv.tar.gz
(251 B)
📄
nodejs_native.attr.attr.tar.gz
(187 B)
📄
nodejs_native.attr.tar
(2 KB)
📄
nodejs_native.req.req.tar.gz
(159 B)
📄
nodejs_native.req.tar
(2 KB)
📄
nodes.h.h.tar.gz
(547 B)
📄
nodes.h.tar
(3 KB)
📄
nodes.tar
(15 KB)
📄
nodes.tar.gz
(2.58 KB)
📄
nohup.tar
(39 KB)
📄
nohup.tar.gz
(16.93 KB)
📄
nom.txt.tar
(2 KB)
📄
nom.txt.txt.tar.gz
(204 B)
📄
nonblock.so.so.tar.gz
(3.73 KB)
📄
nonblock.so.tar
(13.5 KB)
📄
none.amf.amf.tar.gz
(174 B)
📄
none.amf.tar
(2 KB)
📄
normal.mod.mod.tar.gz
(59.53 KB)
📄
normal.mod.tar
(314 KB)
📄
normalizer.tar
(3 KB)
📄
normalizer.tar.gz
(264 B)
📄
nosetests-3.4.4.tar.gz
(256 B)
📄
nosetests-3.4.tar
(2 KB)
📄
nosetests.tar
(2 KB)
📄
nosetests.tar.gz
(254 B)
📄
nostdio.h.h.tar.gz
(1.18 KB)
📄
nostdio.h.tar
(5 KB)
📄
notes.txt.tar
(685.5 KB)
📄
notes.txt.txt.tar.gz
(453 B)
📄
npm.tar
(2.5 KB)
📄
npm.tar.gz
(399 B)
📄
nproc.tar
(39 KB)
📄
nproc.tar.gz
(16.59 KB)
📄
npu.sbin.1.0.0.63.sbin.1.0.0.63.tar.gz
(74.89 KB)
📄
npu.sbin.1.0.0.63.tar
(369.5 KB)
📄
npu.sbin.sbin.tar.gz
(74.89 KB)
📄
npu.sbin.tar
(611 KB)
📄
npx.tar
(2.5 KB)
📄
npx.tar.gz
(404 B)
📄
nr.tar
(2 KB)
📄
nr.tar.gz
(107 B)
📄
nr_hugepages.tar
(2 KB)
📄
nr_hugepages.tar.gz
(109 B)
📄
nr_hugepages_mempolicy.tar
(2 KB)
📄
nr_hugepages_mempolicy.tar.gz
(119 B)
📄
nr_open.tar
(2 KB)
📄
nr_open.tar.gz
(110 B)
📄
nr_overcommit_hugepages.tar
(2 KB)
📄
nr_overcommit_hugepages.tar.gz
(120 B)
📄
nroff-filter.info.info.tar.gz
(281 B)
📄
nroff-filter.info.tar
(2 KB)
📄
nroff-filter.so.so.tar.gz
(4.74 KB)
📄
nroff-filter.so.tar
(13.5 KB)
📄
nroff.amf.amf.tar.gz
(234 B)
📄
nroff.amf.tar
(2 KB)
📄
nroff.tar
(5 KB)
📄
nroff.tar.gz
(1.59 KB)
📄
nrpe.conf.conf.tar.gz
(128 B)
📄
nrpe.conf.tar
(3 KB)
📄
nrpe.service.service.tar.gz
(531 B)
📄
nrpe.service.tar
(2.5 KB)
📄
nrpe.xml.tar
(2 KB)
📄
nrpe.xml.xml.tar.gz
(279 B)
📄
ns_last_pid.tar
(2 KB)
📄
ns_last_pid.tar.gz
(117 B)
📄
nscd.conf.conf.tar.gz
(126 B)
📄
nscd.conf.tar
(3 KB)
📄
nscd.pid.pid.tar.gz
(105 B)
📄
nscd.pid.tar
(2 KB)
📄
nscd.service.service.tar.gz
(361 B)
📄
nscd.service.tar
(2 KB)
📄
nscd.socket.socket.tar.gz
(211 B)
📄
nscd.socket.tar
(3 KB)
📄
nsec3hash.tar
(14 KB)
📄
nsec3hash.tar.gz
(4.8 KB)
📄
nslookup.tar
(148 KB)
📄
nslookup.tar.gz
(62.75 KB)
📄
nsm_local_state.tar
(2 KB)
📄
nsm_local_state.tar.gz
(113 B)
📄
nsm_use_hostnames.tar
(2 KB)
📄
nsm_use_hostnames.tar.gz
(116 B)
📄
nss-lookup.target.tar
(2.5 KB)
📄
nss-lookup.target.target.tar.gz
(471 B)
📄
nss-user-lookup.target.tar
(2.5 KB)
📄
nss-user-lookup.target.target.tar.gz
(448 B)
📄
nss.h.h.tar.gz
(1.07 KB)
📄
nss.h.tar
(3.5 KB)
📄
nss.tar
(3.02 MB)
📄
nss.tar.gz
(1.28 MB)
📄
nss.zip
(3.01 MB)
📄
nsswitch.conf.conf.tar.gz
(1.08 KB)
📄
nsswitch.conf.tar
(4 KB)
📄
nsupdate.tar
(75 KB)
📄
nsupdate.tar.gz
(30.67 KB)
📄
ntfs.mod.mod.tar.gz
(7.65 KB)
📄
ntfs.mod.tar
(36 KB)
📄
ntfscomp.mod.mod.tar.gz
(3.05 KB)
📄
ntfscomp.mod.tar
(8 KB)
📄
ntldr.mod.mod.tar.gz
(1.38 KB)
📄
ntldr.mod.tar
(8 KB)
📄
ntp-units.d.tar
(2 KB)
📄
ntp-units.d.tar.gz
(108 B)
📄
ntp-units.d.zip
(180 B)
📄
ntp.xml.tar
(3 KB)
📄
ntp.xml.xml.tar.gz
(343 B)
📄
ntpath.py.py.tar.gz
(7.86 KB)
📄
ntpath.py.tar
(72 KB)
📄
ntpath.pyc.pyc.tar.gz
(5.69 KB)
📄
ntpath.pyc.tar
(14.5 KB)
📄
ntpath.pyo.pyo.tar.gz
(5.69 KB)
📄
ntpath.pyo.tar
(14.5 KB)
📄
nturl2path.pyc.pyc.tar.gz
(1 KB)
📄
nturl2path.pyc.tar
(3.5 KB)
📄
nturl2path.pyo.pyo.tar.gz
(1023 B)
📄
nturl2path.pyo.tar
(3.5 KB)
📄
nucleus.tar
(164.5 KB)
📄
nucleus.tar.gz
(85.74 KB)
📄
nucleus.zip
(139.81 KB)
📄
nuked.tar
(139 KB)
📄
nuked.tar.gz
(81.42 KB)
📄
nuked.zip
(122.25 KB)
📄
nukeviet.tar
(12.16 MB)
📄
nukeviet.tar.gz
(11.22 MB)
📄
nukeviet.zip
(12.13 MB)
📄
null.go.go.tar.gz
(553 B)
📄
null.go.tar
(2.5 KB)
📄
null.tar
(4 KB)
📄
null.tar.gz
(320 B)
📄
num.tar
(1.64 MB)
📄
num.tar.gz
(452.7 KB)
📄
num.zip
(1.61 MB)
📄
numa_balancing.tar
(2 KB)
📄
numa_balancing.tar.gz
(115 B)
📄
numa_maps.tar
(204 KB)
📄
numa_maps.tar.gz
(2.91 KB)
📄
numa_stat.tar
(2 KB)
📄
numa_stat.tar.gz
(106 B)
📄
numa_zonelist_order.tar
(2 KB)
📄
numa_zonelist_order.tar.gz
(119 B)
📄
numbers.py.py.tar.gz
(2.55 KB)
📄
numbers.py.tar
(34 KB)
📄
numbers.pyc.pyc.tar.gz
(3.67 KB)
📄
numbers.pyc.tar
(15.5 KB)
📄
numbers.pyo.pyo.tar.gz
(3.67 KB)
📄
numbers.pyo.tar
(15.5 KB)
📄
numfmt.tar
(67.5 KB)
📄
numfmt.tar.gz
(29.43 KB)
📄
nut.xml.tar
(3 KB)
📄
nut.xml.xml.tar.gz
(338 B)
📄
nvidia.tar
(152.67 MB)
📄
nvidia.tar.gz
(109.56 MB)
📄
nvidia.zip
(152.48 MB)
📄
nvm_00130300.bin.bin.tar.gz
(1.23 KB)
📄
nvm_00130300.bin.tar
(3.5 KB)
📄
nvm_00130302.bin.bin.tar.gz
(1.27 KB)
📄
nvm_00130302.bin.tar
(3.5 KB)
📄
nvm_00230302.bin.bin.tar.gz
(1.29 KB)
📄
nvm_00230302.bin.tar
(3.5 KB)
📄
nvm_00440302.bin.bin.tar.gz
(1.31 KB)
📄
nvm_00440302.bin.tar
(3.5 KB)
📄
nvm_00440302_eu.bin.bin.tar.gz
(1.31 KB)
📄
nvm_00440302_eu.bin.tar
(3.5 KB)
📄
nvm_usb_00000200.bin.bin.tar.gz
(1.19 KB)
📄
nvm_usb_00000200.bin.tar
(3.5 KB)
📄
nvm_usb_00000201.bin.bin.tar.gz
(1.19 KB)
📄
nvm_usb_00000201.bin.tar
(3.5 KB)
📄
nvm_usb_00000300.bin.bin.tar.gz
(1.19 KB)
📄
nvm_usb_00000300.bin.tar
(3.5 KB)
📄
nvm_usb_00000302.bin.bin.tar.gz
(1.29 KB)
📄
nvm_usb_00000302.bin.tar
(3.5 KB)
📄
nvm_usb_00130200_0104.bin.bin.tar.gz
(2.86 KB)
📄
nvm_usb_00130200_0104.bin.tar
(8 KB)
📄
nvm_usb_00130200_0105.bin.bin.tar.gz
(2.87 KB)
📄
nvm_usb_00130200_0105.bin.tar
(8 KB)
📄
nvm_usb_00130200_0106.bin.bin.tar.gz
(2.87 KB)
📄
nvm_usb_00130200_0106.bin.tar
(8 KB)
📄
nvm_usb_00130200_0107.bin.bin.tar.gz
(2.88 KB)
📄
nvm_usb_00130200_0107.bin.tar
(8 KB)
📄
nvm_usb_00130200_0109.bin.bin.tar.gz
(2.87 KB)
📄
nvm_usb_00130200_0109.bin.tar
(8 KB)
📄
nvm_usb_00130200_0110.bin.bin.tar.gz
(2.87 KB)
📄
nvm_usb_00130200_0110.bin.tar
(8 KB)
📄
nvm_usb_00130201_010a.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_010a.bin.tar
(8.5 KB)
📄
nvm_usb_00130201_010b.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_010b.bin.tar
(8.5 KB)
📄
nvm_usb_00130201_0303.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_0303.bin.tar
(8.5 KB)
📄
nvm_usb_00130201_gf_010a.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_gf_010a.bin.tar
(8 KB)
📄
nvm_usb_00130201_gf_010b.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_gf_010b.bin.tar
(8 KB)
📄
nvm_usb_00130201_gf_0303.bin.bin.tar.gz
(3.05 KB)
📄
nvm_usb_00130201_gf_0303.bin.tar
(8 KB)
📄
nvm_usb_00190200_0104.bin.bin.tar.gz
(4.22 KB)
📄
nvm_usb_00190200_0104.bin.tar
(11 KB)
📄
nvm_usb_00190200_0106.bin.bin.tar.gz
(4.22 KB)
📄
nvm_usb_00190200_0106.bin.tar
(11 KB)
📄
nvm_usb_00190200_0108.bin.bin.tar.gz
(4.2 KB)
📄
nvm_usb_00190200_0108.bin.tar
(11 KB)
📄
nvm_usb_00190200_0109.bin.bin.tar.gz
(4.22 KB)
📄
nvm_usb_00190200_0109.bin.tar
(11 KB)
📄
nvm_usb_00190200_010a.bin.bin.tar.gz
(4.22 KB)
📄
nvm_usb_00190200_010a.bin.tar
(11 KB)
📄
nvm_usb_00190200_010c.bin.bin.tar.gz
(4.22 KB)
📄
nvm_usb_00190200_010c.bin.tar
(11 KB)
📄
nvm_usb_00190200_010e.bin.bin.tar.gz
(4.23 KB)
📄
nvm_usb_00190200_010e.bin.tar
(11 KB)
📄
nvm_usb_00190200_0110.bin.bin.tar.gz
(4.23 KB)
📄
nvm_usb_00190200_0110.bin.tar
(11 KB)
📄
nvm_usb_00190200_0111.bin.bin.tar.gz
(4.47 KB)
📄
nvm_usb_00190200_0111.bin.tar
(11 KB)
📄
nvm_usb_00190200_0112.bin.bin.tar.gz
(4.23 KB)
📄
nvm_usb_00190200_0112.bin.tar
(11 KB)
📄
nvmf-connect.target.tar
(2 KB)
📄
nvmf-connect.target.target.tar.gz
(170 B)
📄
nvram.tar
(2 KB)
📄
nvram.tar.gz
(312 B)
📄
nxp.tar
(1.16 MB)
📄
nxp.tar.gz
(955.16 KB)
📄
nxp.zip
(1.15 MB)
📄
oasisdbgdownload.sys.sys.tar.gz
(26.36 KB)
📄
oasisdbgdownload.sys.tar
(82 KB)
📄
oasisdownload.sys.sys.tar.gz
(24.42 KB)
📄
oasisdownload.sys.tar
(82 KB)
📄
oasisrcvucode.sys.sys.tar.gz
(1.35 KB)
📄
oasisrcvucode.sys.tar
(4.5 KB)
📄
oauth.pem.pem.tar.gz
(126 B)
📄
oauth.pem.tar
(2 KB)
📄
oauth.pub.pub.tar.gz
(126 B)
📄
oauth.pub.tar
(2 KB)
📄
obcard.tar
(144.5 KB)
📄
obcard.tar.gz
(72.81 KB)
📄
obcard.zip
(120.57 KB)
📄
obj_mac.h.h.tar.gz
(31.96 KB)
📄
obj_mac.h.tar
(215 KB)
📄
objcopy.tar
(242 KB)
📄
objcopy.tar.gz
(109.95 KB)
📄
objdump.tar
(421.5 KB)
📄
objdump.tar.gz
(189.14 KB)
📄
object.h.h.tar.gz
(9.5 KB)
📄
object.h.tar
(30.5 KB)
📄
object_max_active.tar
(2 KB)
📄
object_max_active.tar.gz
(120 B)
📄
objgraph.pyc.pyc.tar.gz
(2.36 KB)
📄
objgraph.pyc.tar
(6.5 KB)
📄
objgraph.pyo.pyo.tar.gz
(2.36 KB)
📄
objgraph.pyo.tar
(6.5 KB)
📄
objimpl.h.h.tar.gz
(3.69 KB)
📄
objimpl.h.tar
(12 KB)
📄
objspace.so.so.tar.gz
(18.78 KB)
📄
objspace.so.tar
(46.5 KB)
📄
obstack.h.h.tar.gz
(5.9 KB)
📄
obstack.h.tar
(22.5 KB)
📄
ocart.tar
(195.5 KB)
📄
ocart.tar.gz
(100.63 KB)
📄
ocart.zip
(167.71 KB)
📄
ocart2.tar
(20.03 MB)
📄
ocart2.tar.gz
(18.36 MB)
📄
ocart2.zip
(20 MB)
📄
ocart23.tar
(145.5 KB)
📄
ocart23.tar.gz
(74.85 KB)
📄
ocart23.zip
(124.16 KB)
📄
ocart4.tar
(24.76 MB)
📄
ocart4.tar.gz
(22.62 MB)
📄
ocart4.zip
(24.73 MB)
📄
occam-channel.go.go.tar.gz
(9.02 KB)
📄
occam-channel.go.tar
(30.5 KB)
📄
ocportal.tar
(21.21 MB)
📄
ocportal.tar.gz
(19.1 MB)
📄
ocportal.zip
(21.18 MB)
📄
ocsp.h.h.tar.gz
(3.46 KB)
📄
ocsp.h.tar
(16.5 KB)
📄
october.tar
(265 KB)
📄
october.tar.gz
(143.54 KB)
📄
october.zip
(236.26 KB)
📄
ocxl.h.h.tar.gz
(913 B)
📄
ocxl.h.tar
(3.5 KB)
📄
od.tar
(75.5 KB)
📄
od.tar.gz
(33.08 KB)
📄
odc.mod.mod.tar.gz
(1.97 KB)
📄
odc.mod.tar
(11 KB)
📄
odm.png.png.tar.gz
(10 KB)
📄
odm.png.tar
(11.5 KB)
📄
odm.tar
(178.5 KB)
📄
odm.tar.gz
(96.98 KB)
📄
odm.zip
(154.76 KB)
📄
offsetio.mod.mod.tar.gz
(869 B)
📄
offsetio.mod.tar
(3.5 KB)
📄
ohci.mod.mod.tar.gz
(5.83 KB)
📄
ohci.mod.tar
(30 KB)
📄
ojs.png.png.tar.gz
(9.13 KB)
📄
ojs.png.tar
(11 KB)
📄
ojs.sql.sql.tar.gz
(7.22 MB)
📄
ojs.sql.tar
(25.27 MB)
📄
ojs.tar
(232.9 MB)
📄
ojs.tar.gz
(204.34 MB)
📄
ojs.zip
(232.87 MB)
📄
ojs33.sql.sql.tar.gz
(570.57 KB)
📄
ojs33.sql.tar
(1.9 MB)
📄
ojs33.tar
(73.21 MB)
📄
ojs33.tar.gz
(66.6 MB)
📄
ojs33.zip
(73.19 MB)
📄
oland_ce.bin.bin.tar.gz
(1.06 KB)
📄
oland_ce.bin.tar
(20 KB)
📄
oland_k_smc.bin.bin.tar.gz
(26.91 KB)
📄
oland_k_smc.bin.tar
(125 KB)
📄
oland_mc.bin.bin.tar.gz
(12.81 KB)
📄
oland_mc.bin.tar
(65 KB)
📄
oland_me.bin.bin.tar.gz
(3.68 KB)
📄
oland_me.bin.tar
(20 KB)
📄
oland_pfp.bin.bin.tar.gz
(2.78 KB)
📄
oland_pfp.bin.tar
(20 KB)
📄
oland_rlc.bin.bin.tar.gz
(2.11 KB)
📄
oland_rlc.bin.tar
(19 KB)
📄
oland_smc.bin.bin.tar.gz
(26.77 KB)
📄
oland_smc.bin.tar
(124 KB)
📄
oland_uvd.bin.bin.tar.gz
(144.34 KB)
📄
oland_uvd.bin.tar
(216.5 KB)
📄
old-stats.tar
(33.5 KB)
📄
old-stats.tar.gz
(6.41 KB)
📄
old-stats.zip
(31.25 KB)
📄
ols_logo.svg.svg.tar.gz
(1.82 KB)
📄
ols_logo.svg.tar
(5 KB)
📄
omap.rb.rb.tar.gz
(162 B)
📄
omap.rb.tar
(9 KB)
📄
omap_drm.h.h.tar.gz
(1.67 KB)
📄
omap_drm.h.tar
(5.5 KB)
📄
omeka.sql.sql.tar.gz
(6.42 KB)
📄
omeka.sql.tar
(27 KB)
📄
omeka.tar
(13.63 MB)
📄
omeka.tar.gz
(12.43 MB)
📄
omeka.zip
(13.6 MB)
📄
omekas.sql.sql.tar.gz
(14.09 KB)
📄
omekas.sql.tar
(63 KB)
📄
omekas.tar
(17.99 MB)
📄
omekas.tar.gz
(15.93 MB)
📄
omekas.zip
(17.96 MB)
📄
omhttp.so.so.tar.gz
(18.9 KB)
📄
omhttp.so.tar
(47 KB)
📄
omjournal.so.so.tar.gz
(6.29 KB)
📄
omjournal.so.tar
(17.5 KB)
📄
ommail.so.so.tar.gz
(9.42 KB)
📄
ommail.so.tar
(22.5 KB)
📄
omp.png.png.tar.gz
(3.84 KB)
📄
omp.png.tar
(6 KB)
📄
omp.sql.sql.tar.gz
(7.22 MB)
📄
omp.sql.tar
(25.27 MB)
📄
omp.tar
(224.69 MB)
📄
omp.tar.gz
(196.7 MB)
📄
omp.zip
(224.66 MB)
📄
omprog.so.so.tar.gz
(12.58 KB)
📄
omprog.so.tar
(30 KB)
📄
omstdout.so.so.tar.gz
(6.53 KB)
📄
omstdout.so.tar
(18 KB)
📄
omtesting.so.so.tar.gz
(6.28 KB)
📄
omtesting.so.tar
(17.5 KB)
📄
omuxsock.so.so.tar.gz
(7.01 KB)
📄
omuxsock.so.tar
(18.5 KB)
📄
one-context-online.service.service.tar.gz
(352 B)
📄
one-context-online.service.tar
(2 KB)
📄
one-context.service.service.tar.gz
(321 B)
📄
one-context.service.tar
(2 KB)
📄
oom_adj.tar
(12 KB)
📄
oom_adj.tar.gz
(104 B)
📄
oom_dump_tasks.tar
(2 KB)
📄
oom_dump_tasks.tar.gz
(111 B)
📄
oom_kill_allocating_task.tar
(2 KB)
📄
oom_kill_allocating_task.tar.gz
(120 B)
📄
oom_score.tar
(10 KB)
📄
oom_score.tar.gz
(108 B)
📄
oop.tar
(209 KB)
📄
oop.tar.gz
(72.09 KB)
📄
oop.zip
(200.9 KB)
📄
op.h.h.tar.gz
(12.01 KB)
📄
op.h.tar
(37.5 KB)
📄
opcode.h.h.tar.gz
(18.4 KB)
📄
opcode.h.tar
(97.5 KB)
📄
opcode.py.py.tar.gz
(2.12 KB)
📄
opcode.py.tar
(20 KB)
📄
opcode.pyc.pyc.tar.gz
(2.52 KB)
📄
opcode.pyc.tar
(8 KB)
📄
opcode.pyo.pyo.tar.gz
(2.53 KB)
📄
opcode.pyo.tar
(8 KB)
📄
open-vm-tools.tar
(440.5 KB)
📄
open-vm-tools.tar.gz
(170.11 KB)
📄
open-vm-tools.zip
(432.77 KB)
📄
openb.tar
(218.5 KB)
📄
openb.tar.gz
(124.42 KB)
📄
openb.zip
(196.96 KB)
📄
openeshop.tar
(215 KB)
📄
openeshop.tar.gz
(120.2 KB)
📄
openeshop.zip
(189.28 KB)
📄
openldap.tar
(2.5 KB)
📄
openldap.tar.gz
(649 B)
📄
openldap.zip
(1.03 KB)
📄
openldap11.tar
(5.53 MB)
📄
openldap11.tar.gz
(1.41 MB)
📄
openldap11.zip
(5.37 MB)
📄
opensis.tar
(124.5 KB)
📄
opensis.tar.gz
(65.64 KB)
📄
opensis.zip
(105.02 KB)
📄
openssh.conf.conf.tar.gz
(140 B)
📄
openssh.conf.tar
(3 KB)
📄
openssh.tar
(117 KB)
📄
openssh.tar.gz
(53.95 KB)
📄
openssh.zip
(115.38 KB)
📄
openssl-2.1.2.tar
(378 KB)
📄
openssl-2.1.2.tar.gz
(144.3 KB)
📄
openssl-2.1.2.zip
(376.24 KB)
📄
openssl.pc.pc.tar.gz
(255 B)
📄
openssl.pc.tar
(2 KB)
📄
openssl.rb.rb.tar.gz
(361 B)
📄
openssl.rb.tar
(6 KB)
📄
openssl.so.so.tar.gz
(144.32 KB)
📄
openssl.so.tar
(788.5 KB)
📄
openssl.tar
(3.68 MB)
📄
openssl.tar.gz
(298.51 KB)
📄
openssl.zip
(1.52 MB)
📄
opensslconf.h.h.tar.gz
(657 B)
📄
opensslconf.h.tar
(3.5 KB)
📄
opensslv.h.h.tar.gz
(1.88 KB)
📄
opensslv.h.tar
(6 KB)
📄
openvpn.xml.tar
(2 KB)
📄
openvpn.xml.xml.tar.gz
(330 B)
📄
operator.py.py.tar.gz
(2.96 KB)
📄
operator.py.tar
(23.5 KB)
📄
opnames.h.h.tar.gz
(3.11 KB)
📄
opnames.h.tar
(10.5 KB)
📄
ops.pm.pm.tar.gz
(658 B)
📄
ops.pm.tar
(2.5 KB)
📄
ops.png.png.tar.gz
(17.99 KB)
📄
ops.png.tar
(19.5 KB)
📄
ops.sql.sql.tar.gz
(7.21 MB)
📄
ops.sql.tar
(25.22 MB)
📄
ops.tar
(223.44 MB)
📄
ops.tar.gz
(195.94 MB)
📄
ops.zip
(223.41 MB)
📄
opt.tar
(7 KB)
📄
opt.tar.gz
(369 B)
📄
opt.zip
(1.01 KB)
📄
optargs.go.go.tar.gz
(7.25 KB)
📄
optargs.go.tar
(21 KB)
📄
optimistic_dad.tar
(4 KB)
📄
optimistic_dad.tar.gz
(126 B)
📄
optimize-serial-console.tar
(2 KB)
📄
optimize-serial-console.tar.gz
(238 B)
📄
optimize-serial-console.zip
(393 B)
📄
options.php.php.tar.gz
(170 B)
📄
options.php.tar
(2 KB)
📄
options.tar
(7 KB)
📄
options.tar.gz
(318 B)
📄
optmem_max.tar
(2 KB)
📄
optmem_max.tar.gz
(116 B)
📄
optparse.py.py.tar.gz
(15.28 KB)
📄
optparse.py.tar
(180.5 KB)
📄
optparse.pyc.pyc.tar.gz
(18.17 KB)
📄
optparse.pyc.tar
(54.5 KB)
📄
optparse.pyo.pyo.tar.gz
(18.13 KB)
📄
optparse.pyo.tar
(54.5 KB)
📄
orange 04 2025.tar
(72.5 KB)
📄
orange 04 2025.tar.gz
(5.59 KB)
📄
orange 04 2025.zip
(41.56 KB)
📄
orange-icons-D0YzO_qq.css.css.tar.gz
(9.43 KB)
📄
orange-icons-D0YzO_qq.css.tar
(42 KB)
📄
orange-icons-beEFzM3r.css.css.tar.gz
(9.4 KB)
📄
orange-icons-beEFzM3r.css.tar
(42 KB)
📄
orange.sql.sql.tar.gz
(232.77 KB)
📄
orange.sql.tar
(1.02 MB)
📄
orange.tar
(22.01 MB)
📄
orange.tar.gz
(19.43 MB)
📄
orange.zip
(21.98 MB)
📄
ordchr.so.so.tar.gz
(3.84 KB)
📄
ordchr.so.tar
(13.5 KB)
📄
org_upgrade.php.php.tar.gz
(8.61 KB)
📄
org_upgrade.php.tar
(36.5 KB)
📄
orig_upgrade.php.php.tar.gz
(4.52 KB)
📄
orig_upgrade.php.tar
(22 KB)
📄
ornbtfw11.tlv.tar
(425 KB)
📄
ornbtfw11.tlv.tlv.tar.gz
(145.48 KB)
📄
ornnv11.bin.bin.tar.gz
(4.04 KB)
📄
ornnv11.bin.tar
(12.5 KB)
📄
os-release.tar
(3 KB)
📄
os-release.tar.gz
(323 B)
📄
os.cpython-38.pyc.cpython-38.pyc.tar.gz
(12.51 KB)
📄
os.cpython-38.pyc.tar
(32.5 KB)
📄
os.h.h.tar.gz
(1015 B)
📄
os.h.tar
(3.5 KB)
📄
os.py.py.tar.gz
(10.57 KB)
📄
os.py.tar
(103.5 KB)
📄
os.pyc.pyc.tar.gz
(8.27 KB)
📄
os.pyc.tar
(27 KB)
📄
os.pyo.pyo.tar.gz
(8.27 KB)
📄
os.pyo.tar
(27 KB)
📄
os2emxpath.pyc.pyc.tar.gz
(2.18 KB)
📄
os2emxpath.pyc.tar
(6 KB)
📄
os2emxpath.pyo.pyo.tar.gz
(2.18 KB)
📄
os2emxpath.pyo.tar
(6 KB)
📄
osclassified.sql.sql.tar.gz
(905.05 KB)
📄
osclassified.sql.tar
(3.89 MB)
📄
osclassified.tar
(11.08 MB)
📄
osclassified.tar.gz
(7.47 MB)
📄
osclassified.zip
(11.06 MB)
📄
oscom.sql.sql.tar.gz
(5.31 MB)
📄
oscom.sql.tar
(40.64 MB)
📄
oscom.tar
(348.56 MB)
📄
oscom.tar.gz
(288.53 MB)
📄
oscom.zip
(348.53 MB)
📄
osdefs.h.h.tar.gz
(442 B)
📄
osdefs.h.tar
(2.5 KB)
📄
ositech.tar
(4.5 KB)
📄
ositech.tar.gz
(1.41 KB)
📄
ositech.zip
(2.87 KB)
📄
ospos.sql.sql.tar.gz
(7.12 KB)
📄
ospos.sql.tar
(47.5 KB)
📄
ospos.tar
(31.38 MB)
📄
ospos.tar.gz
(28.36 MB)
📄
ospos.zip
(31.35 MB)
📄
osrelease.tar
(2 KB)
📄
osrelease.tar.gz
(134 B)
📄
ossl_typ.h.h.tar.gz
(1.92 KB)
📄
ossl_typ.h.tar
(8 KB)
📄
ossn.png.png.tar.gz
(8.63 KB)
📄
ossn.png.tar
(10.5 KB)
📄
ossn.tar
(3.19 MB)
📄
ossn.tar.gz
(2.78 MB)
📄
ossn.zip
(3.16 MB)
📄
ost-config.php.php.tar.gz
(2.82 KB)
📄
ost-config.php.tar
(8 KB)
📄
ostic.sql.sql.tar.gz
(27.63 KB)
📄
ostic.sql.tar
(112.5 KB)
📄
ostic.tar
(50.96 MB)
📄
ostic.tar.gz
(48.17 MB)
📄
ostic.zip
(50.93 MB)
📄
ostic14.tar
(2.21 MB)
📄
ostic14.tar.gz
(664.36 KB)
📄
ostic14.zip
(2.19 MB)
📄
ostic17.sql.sql.tar.gz
(27.62 KB)
📄
ostic17.sql.tar
(112.5 KB)
📄
ostic17.tar
(50.96 MB)
📄
ostic17.tar.gz
(48.17 MB)
📄
ostic17.zip
(50.92 MB)
📄
ostic2.tar
(1.91 MB)
📄
ostic2.tar.gz
(600.33 KB)
📄
ostic2.zip
(1.88 MB)
📄
ostruct.rb.rb.tar.gz
(3.42 KB)
📄
ostruct.rb.tar
(39.5 KB)
📄
ostype.tar
(2 KB)
📄
ostype.tar.gz
(111 B)
📄
osupport.tar
(231 KB)
📄
osupport.tar.gz
(134.2 KB)
📄
osupport.zip
(205.43 KB)
📄
overcommit_kbytes.tar
(2 KB)
📄
overcommit_kbytes.tar.gz
(114 B)
📄
overcommit_memory.tar
(2 KB)
📄
overcommit_memory.tar.gz
(114 B)
📄
overcommit_ratio.tar
(2 KB)
📄
overcommit_ratio.tar.gz
(114 B)
📄
overflowgid.tar
(3 KB)
📄
overflowgid.tar.gz
(112 B)
📄
overflowuid.tar
(3 KB)
📄
overflowuid.tar.gz
(112 B)
📄
overload.h.h.tar.gz
(1.07 KB)
📄
overload.h.tar
(5 KB)
📄
overrides.tar
(78.5 KB)
📄
overrides.tar.gz
(65.02 KB)
📄
overrides.zip
(66.85 KB)
📄
ovirt-vmconsole.xml.tar
(2 KB)
📄
ovirt-vmconsole.xml.xml.tar.gz
(267 B)
📄
owa-config.php.php.tar.gz
(1.28 KB)
📄
owa-config.php.tar
(4.5 KB)
📄
owa.png.png.tar.gz
(4.05 KB)
📄
owa.png.tar
(5.5 KB)
📄
owa.sql.sql.tar.gz
(2.75 KB)
📄
owa.sql.tar
(32 KB)
📄
owa.tar
(3.89 MB)
📄
owa.tar.gz
(3.57 MB)
📄
owa.zip
(3.86 MB)
📄
owm.png.png.tar.gz
(4.62 KB)
📄
owm.png.tar
(6.5 KB)
📄
owm.tar
(199.5 KB)
📄
owm.tar.gz
(112.34 KB)
📄
owm.zip
(175.74 KB)
📄
owncloud.tar
(98.8 MB)
📄
owncloud.tar.gz
(92.38 MB)
📄
owncloud.zip
(98.76 MB)
📄
oxwall.tar
(407.5 KB)
📄
oxwall.tar.gz
(167.17 KB)
📄
oxwall.zip
(381.29 KB)
📄
p11-kit-proxy.so.so.tar.gz
(311.32 KB)
📄
p11-kit-proxy.so.tar
(1.2 MB)
📄
p11-kit-trust.so.so.tar.gz
(95.45 KB)
📄
p11-kit-trust.so.tar
(251 KB)
📄
pack.h.h.tar.gz
(667 B)
📄
pack.h.tar
(3 KB)
📄
pack.rb.rb.tar.gz
(878 B)
📄
pack.rb.tar
(11.5 KB)
📄
package.json.json.tar.gz
(2.47 KB)
📄
package.json.tar
(9.5 KB)
📄
package.sh.sh.tar.gz
(538 B)
📄
package.sh.tar
(3 KB)
📄
packageindex.php.php.tar.gz
(168 B)
📄
packageindex.php.tar
(4 KB)
📄
packet-too-big.xml.tar
(2 KB)
📄
packet-too-big.xml.xml.tar.gz
(320 B)
📄
packet.h.h.tar.gz
(1.09 KB)
📄
packet.h.tar
(4 KB)
📄
pad.h.h.tar.gz
(5.42 KB)
📄
pad.h.tar
(18.5 KB)
📄
padlock.so.so.tar.gz
(9.56 KB)
📄
padlock.so.tar
(25.5 KB)
📄
page-cluster.tar
(2 KB)
📄
page-cluster.tar.gz
(109 B)
📄
pagekit.tar
(191 KB)
📄
pagekit.tar.gz
(103.43 KB)
📄
pagekit.zip
(167.34 KB)
📄
paintbrushjs.tar
(70 KB)
📄
paintbrushjs.tar.gz
(48.57 KB)
📄
paintbrushjs.zip
(60.59 KB)
📄
pam.conf.conf.tar.gz
(157 B)
📄
pam.conf.tar
(3 KB)
📄
pam.d.tar
(19 KB)
📄
pam.d.tar.gz
(1.53 KB)
📄
pam.d.zip
(8.07 KB)
📄
pam_access.so.so.tar.gz
(9.47 KB)
📄
pam_access.so.tar
(21.5 KB)
📄
pam_appl.h.h.tar.gz
(1.56 KB)
📄
pam_appl.h.tar
(5 KB)
📄
pam_cap.so.so.tar.gz
(5.14 KB)
📄
pam_cap.so.tar
(13 KB)
📄
pam_chroot.so.so.tar.gz
(4.18 KB)
📄
pam_chroot.so.tar
(13 KB)
📄
pam_client.h.h.tar.gz
(2.06 KB)
📄
pam_client.h.tar
(9 KB)
📄
pam_console.so.so.tar.gz
(10.62 KB)
📄
pam_console.so.tar
(30 KB)
📄
pam_console_apply.tar
(47 KB)
📄
pam_console_apply.tar.gz
(16.92 KB)
📄
pam_cpses.so.so.tar.gz
(4.04 KB)
📄
pam_cpses.so.tar
(12 KB)
📄
pam_cracklib.so.so.tar.gz
(7.7 KB)
📄
pam_cracklib.so.tar
(21.5 KB)
📄
pam_debug.so.so.tar.gz
(4.17 KB)
📄
pam_debug.so.tar
(13.5 KB)
📄
pam_deny.so.so.tar.gz
(2.83 KB)
📄
pam_deny.so.tar
(9 KB)
📄
pam_echo.so.so.tar.gz
(4.58 KB)
📄
pam_echo.so.tar
(13.5 KB)
📄
pam_env.so.so.tar.gz
(7.84 KB)
📄
pam_env.so.tar
(21.5 KB)
📄
pam_exec.so.so.tar.gz
(6.97 KB)
📄
pam_exec.so.tar
(17.5 KB)
📄
pam_ext.h.h.tar.gz
(1.6 KB)
📄
pam_ext.h.tar
(5.5 KB)
📄
pam_faildelay.so.so.tar.gz
(4.01 KB)
📄
pam_faildelay.so.tar
(13 KB)
📄
pam_faillock.so.so.tar.gz
(9.61 KB)
📄
pam_faillock.so.tar
(26 KB)
📄
pam_filter.h.h.tar.gz
(611 B)
📄
pam_filter.h.tar
(3 KB)
📄
pam_filter.so.so.tar.gz
(7.01 KB)
📄
pam_filter.so.tar
(17.5 KB)
📄
pam_filter.tar
(14 KB)
📄
pam_filter.tar.gz
(4.02 KB)
📄
pam_filter.zip
(12.41 KB)
📄
pam_ftp.so.so.tar.gz
(3.92 KB)
📄
pam_ftp.so.tar
(13 KB)
📄
pam_group.so.so.tar.gz
(7.24 KB)
📄
pam_group.so.tar
(17.5 KB)
📄
pam_hulk.so.so.tar.gz
(13.82 KB)
📄
pam_hulk.so.tar
(39.5 KB)
📄
pam_issue.so.so.tar.gz
(5.27 KB)
📄
pam_issue.so.tar
(13.5 KB)
📄
pam_limits.so.so.tar.gz
(10.19 KB)
📄
pam_limits.so.tar
(25.5 KB)
📄
pam_listfile.so.so.tar.gz
(5.46 KB)
📄
pam_listfile.so.tar
(13.5 KB)
📄
pam_localuser.so.so.tar.gz
(3.88 KB)
📄
pam_localuser.so.tar
(13.5 KB)
📄
pam_loginuid.so.so.tar.gz
(4.64 KB)
📄
pam_loginuid.so.tar
(13.5 KB)
📄
pam_lve.so.so.tar.gz
(4.63 KB)
📄
pam_lve.so.tar
(13 KB)
📄
pam_mail.so.so.tar.gz
(5.8 KB)
📄
pam_mail.so.tar
(17.5 KB)
📄
pam_misc.h.h.tar.gz
(729 B)
📄
pam_misc.h.tar
(3 KB)
📄
pam_mkhomedir.so.so.tar.gz
(4.31 KB)
📄
pam_mkhomedir.so.tar
(13 KB)
📄
pam_modules.h.h.tar.gz
(2.1 KB)
📄
pam_modules.h.tar
(6.5 KB)
📄
pam_modutil.h.h.tar.gz
(1.98 KB)
📄
pam_modutil.h.tar
(7 KB)
📄
pam_motd.so.so.tar.gz
(5.42 KB)
📄
pam_motd.so.tar
(13.5 KB)
📄
pam_namespace.so.so.tar.gz
(21.01 KB)
📄
pam_namespace.so.tar
(50 KB)
📄
pam_permit.so.so.tar.gz
(3.13 KB)
📄
pam_permit.so.tar
(9 KB)
📄
pam_postgresok.so.so.tar.gz
(3.19 KB)
📄
pam_postgresok.so.tar
(9 KB)
📄
pam_pwhistory.so.so.tar.gz
(9.09 KB)
📄
pam_pwhistory.so.tar
(26 KB)
📄
pam_pwquality.so.so.tar.gz
(5.22 KB)
📄
pam_pwquality.so.tar
(13 KB)
📄
pam_rhosts.so.so.tar.gz
(3.8 KB)
📄
pam_rhosts.so.tar
(13 KB)
📄
pam_rootok.so.so.tar.gz
(4.12 KB)
📄
pam_rootok.so.tar
(13.5 KB)
📄
pam_securetty.so.so.tar.gz
(4.87 KB)
📄
pam_securetty.so.tar
(13.5 KB)
📄
pam_selinux_permit.so.so.tar.gz
(6.57 KB)
📄
pam_selinux_permit.so.tar
(17.5 KB)
📄
pam_sepermit.so.so.tar.gz
(6.57 KB)
📄
pam_sepermit.so.tar
(17.5 KB)
📄
pam_shells.so.so.tar.gz
(3.66 KB)
📄
pam_shells.so.tar
(13 KB)
📄
pam_sss.so.so.tar.gz
(28.24 KB)
📄
pam_sss.so.tar
(62.5 KB)
📄
pam_stress.so.so.tar.gz
(6.92 KB)
📄
pam_stress.so.tar
(17.5 KB)
📄
pam_sulve.so.so.tar.gz
(3.62 KB)
📄
pam_sulve.so.tar
(12.5 KB)
📄
pam_time.so.so.tar.gz
(6.75 KB)
📄
pam_time.so.tar
(17.5 KB)
📄
pam_timestamp.so.so.tar.gz
(9.77 KB)
📄
pam_timestamp.so.tar
(26 KB)
📄
pam_timestamp_check.tar
(13.5 KB)
📄
pam_timestamp_check.tar.gz
(5.34 KB)
📄
pam_tty_audit.so.so.tar.gz
(5.63 KB)
📄
pam_tty_audit.so.tar
(17.5 KB)
📄
pam_umask.so.so.tar.gz
(4.81 KB)
📄
pam_umask.so.tar
(13 KB)
📄
pam_unix.so.so.tar.gz
(24.95 KB)
📄
pam_unix.so.tar
(58.5 KB)
📄
pam_unix_acct.so.so.tar.gz
(24.96 KB)
📄
pam_unix_acct.so.tar
(58.5 KB)
📄
pam_unix_auth.so.so.tar.gz
(24.96 KB)
📄
pam_unix_auth.so.tar
(58.5 KB)
📄
pam_unix_passwd.so.so.tar.gz
(24.95 KB)
📄
pam_unix_passwd.so.tar
(58.5 KB)
📄
pam_unix_session.so.so.tar.gz
(24.96 KB)
📄
pam_unix_session.so.tar
(58.5 KB)
📄
pam_user_map.so.so.tar.gz
(4.38 KB)
📄
pam_user_map.so.tar
(12.5 KB)
📄
pam_userdb.so.so.tar.gz
(6.49 KB)
📄
pam_userdb.so.tar
(17.5 KB)
📄
pam_usertype.so.so.tar.gz
(5.09 KB)
📄
pam_usertype.so.tar
(13.5 KB)
📄
pam_warn.so.so.tar.gz
(3.43 KB)
📄
pam_warn.so.tar
(9.5 KB)
📄
pam_wheel.so.so.tar.gz
(4.41 KB)
📄
pam_wheel.so.tar
(13.5 KB)
📄
pam_xauth.so.so.tar.gz
(9.08 KB)
📄
pam_xauth.so.tar
(25.5 KB)
📄
panel.h.h.tar.gz
(1.49 KB)
📄
panel.h.tar
(16 KB)
📄
panel.pc.pc.tar.gz
(362 B)
📄
panel.pc.tar
(2 KB)
📄
panel.py.py.tar.gz
(173 B)
📄
panel.py.tar
(4 KB)
📄
panelw.pc.pc.tar.gz
(364 B)
📄
panelw.pc.tar
(2 KB)
📄
panfrost_drm.h.h.tar.gz
(2.78 KB)
📄
panfrost_drm.h.tar
(10 KB)
📄
pango-list.tar
(13.5 KB)
📄
pango-list.tar.gz
(3.96 KB)
📄
pango-view.tar
(59 KB)
📄
pango-view.tar.gz
(21.62 KB)
📄
panic.tar
(2 KB)
📄
panic.tar.gz
(106 B)
📄
panic_mask.tar
(2 KB)
📄
panic_mask.tar.gz
(110 B)
📄
panic_on_io_nmi.tar
(2 KB)
📄
panic_on_io_nmi.tar.gz
(116 B)
📄
panic_on_oom.tar
(2 KB)
📄
panic_on_oom.tar.gz
(109 B)
📄
panic_on_oops.tar
(2 KB)
📄
panic_on_oops.tar.gz
(114 B)
📄
panic_on_rcu_stall.tar
(2 KB)
📄
panic_on_rcu_stall.tar.gz
(118 B)
📄
panic_on_warn.tar
(2 KB)
📄
panic_on_warn.tar.gz
(114 B)
📄
panic_print.tar
(2 KB)
📄
panic_print.tar.gz
(112 B)
📄
parallel.rb.rb.tar.gz
(1.64 KB)
📄
parallel.rb.tar
(6.5 KB)
📄
param.h.h.tar.gz
(856 B)
📄
param.h.tar
(9 KB)
📄
parameters.php.php.tar.gz
(426 B)
📄
parameters.php.tar
(2.5 KB)
📄
parameters.yml.tar
(4 KB)
📄
parameters.yml.yml.tar.gz
(545 B)
📄
params.inc.inc.tar.gz
(119 B)
📄
params.inc.tar
(2 KB)
📄
parse-bridge.sh.sh.tar.gz
(600 B)
📄
parse-bridge.sh.tar
(3 KB)
📄
parseerr.h.h.tar.gz
(1.3 KB)
📄
parseerr.h.tar
(5 KB)
📄
parsepos.h.h.tar.gz
(1.89 KB)
📄
parsepos.h.tar
(7 KB)
📄
parser.cpython-36.opt-1.pyc.cpython-36.opt-1.pyc.tar.gz
(4.89 KB)
📄
parser.cpython-36.opt-1.pyc.tar
(12 KB)
📄
parser.h.h.tar.gz
(2.82 KB)
📄
parser.h.tar
(8.5 KB)
📄
parser.py.py.tar.gz
(4.69 KB)
📄
parser.py.tar
(52 KB)
📄
parser.rb.rb.tar.gz
(4.16 KB)
📄
parser.rb.tar
(116 KB)
📄
parser.tar
(134.5 KB)
📄
parser.tar.gz
(27.43 KB)
📄
parser.zip
(118.53 KB)
📄
parsers.tar
(66.5 KB)
📄
parsers.tar.gz
(14.76 KB)
📄
parsers.zip
(60.97 KB)
📄
part_acorn.mod.mod.tar.gz
(1.09 KB)
📄
part_acorn.mod.tar
(3.5 KB)
📄
part_amiga.mod.mod.tar.gz
(1.1 KB)
📄
part_amiga.mod.tar
(4 KB)
📄
part_apple.mod.mod.tar.gz
(1.24 KB)
📄
part_apple.mod.tar
(4 KB)
📄
part_bsd.mod.mod.tar.gz
(1.6 KB)
📄
part_bsd.mod.tar
(5 KB)
📄
part_dfly.mod.mod.tar.gz
(1.06 KB)
📄
part_dfly.mod.tar
(6 KB)
📄
part_dvh.mod.mod.tar.gz
(983 B)
📄
part_dvh.mod.tar
(3.5 KB)
📄
part_gpt.mod.mod.tar.gz
(1.35 KB)
📄
part_gpt.mod.tar
(7 KB)
📄
part_msdos.mod.mod.tar.gz
(1.47 KB)
📄
part_msdos.mod.tar
(4.5 KB)
📄
part_plan.mod.mod.tar.gz
(1.06 KB)
📄
part_plan.mod.tar
(7 KB)
📄
part_sun.mod.mod.tar.gz
(1.08 KB)
📄
part_sun.mod.tar
(3.5 KB)
📄
part_sunpc.mod.mod.tar.gz
(1.04 KB)
📄
part_sunpc.mod.tar
(3.5 KB)
📄
partialfonts.tar
(54.5 KB)
📄
partialfonts.tar.gz
(24.64 KB)
📄
partialfonts.zip
(29.9 KB)
📄
partmap.lst.lst.tar.gz
(165 B)
📄
partmap.lst.tar
(2 KB)
📄
parttool.lst.lst.tar.gz
(129 B)
📄
parttool.lst.tar
(2 KB)
📄
parttool.mod.mod.tar.gz
(2.55 KB)
📄
parttool.mod.tar
(7.5 KB)
📄
pass.php.php.tar.gz
(144 B)
📄
pass.php.tar
(2 KB)
📄
passwd.tar
(5 KB)
📄
passwd.tar.gz
(671 B)
📄
password.mod.mod.tar.gz
(1.05 KB)
📄
password.mod.tar
(4 KB)
📄
password_pbkdf2.mod.mod.tar.gz
(1.66 KB)
📄
password_pbkdf2.mod.tar
(5 KB)
📄
password_reuse_check.so.so.tar.gz
(4.02 KB)
📄
password_reuse_check.so.tar
(13 KB)
📄
paste.sql.sql.tar.gz
(2.84 KB)
📄
paste.sql.tar
(18.5 KB)
📄
paste.tar
(47.34 MB)
📄
paste.tar.gz
(38.37 MB)
📄
paste.zip
(47.28 MB)
📄
pasteurize.tar
(3.5 KB)
📄
pasteurize.tar.gz
(574 B)
📄
pata.mod.mod.tar.gz
(3.07 KB)
📄
pata.mod.tar
(8 KB)
📄
patch.tar
(208 KB)
📄
patch.tar.gz
(98.32 KB)
📄
patchlevel.h.h.tar.gz
(640 B)
📄
patchlevel.h.tar
(3 KB)
📄
patcomp.py.py.tar.gz
(2.2 KB)
📄
patcomp.py.tar
(16 KB)
📄
pathchk.tar
(39 KB)
📄
pathchk.tar.gz
(15.82 KB)
📄
pathfix.py.py.tar.gz
(2.4 KB)
📄
pathfix.py.tar
(16 KB)
📄
pathlib.py.py.tar.gz
(11.03 KB)
📄
pathlib.py.tar
(99 KB)
📄
pathname.so.so.tar.gz
(12.12 KB)
📄
pathname.so.tar
(34 KB)
📄
paths.h.h.tar.gz
(1.41 KB)
📄
paths.h.tar
(4.5 KB)
📄
paths.target.tar
(2 KB)
📄
paths.target.target.tar.gz
(361 B)
📄
pbkdf2.mod.mod.tar.gz
(904 B)
📄
pbkdf2.mod.tar
(6 KB)
📄
pbkdf2_test.mod.mod.tar.gz
(1.14 KB)
📄
pbkdf2_test.mod.tar
(4 KB)
📄
pci.h.h.tar.gz
(614 B)
📄
pci.h.tar
(2.5 KB)
📄
pci.mod.mod.tar.gz
(1.02 KB)
📄
pci.mod.tar
(6 KB)
📄
pci.tar
(15.5 KB)
📄
pci.tar.gz
(827 B)
📄
pci.zip
(5.01 KB)
📄
pcidump.mod.mod.tar.gz
(1.42 KB)
📄
pcidump.mod.tar
(4.5 KB)
📄
pcie8997_wlan_v4.bin.bin.tar.gz
(324.04 KB)
📄
pcie8997_wlan_v4.bin.tar
(455.5 KB)
📄
pcieusb8997_combo_v4.bin.bin.tar.gz
(439.19 KB)
📄
pcieusb8997_combo_v4.bin.tar
(626 KB)
📄
pcre.h.h.tar.gz
(6.56 KB)
📄
pcre.h.tar
(32.5 KB)
📄
pcre.tar
(1.8 MB)
📄
pcre.tar.gz
(638.05 KB)
📄
pcre.zip
(1.79 MB)
📄
pcre2.h.h.tar.gz
(9.65 KB)
📄
pcre2.h.tar
(45.5 KB)
📄
pcre2.tar
(710 KB)
📄
pcre2.tar.gz
(271.53 KB)
📄
pcre2.zip
(704.8 KB)
📄
pcre2posix.h.h.tar.gz
(2.39 KB)
📄
pcre2posix.h.tar
(7.5 KB)
📄
pcre802.tar
(2.34 MB)
📄
pcre802.tar.gz
(717.85 KB)
📄
pcre802.zip
(2.28 MB)
📄
pcre_scanner.h.h.tar.gz
(2.86 KB)
📄
pcre_scanner.h.tar
(8 KB)
📄
pcre_stringpiece.h.h.tar.gz
(2.47 KB)
📄
pcre_stringpiece.h.tar
(8 KB)
📄
pcrecpp.h.h.tar.gz
(8.2 KB)
📄
pcrecpp.h.tar
(27.5 KB)
📄
pcrecpparg.h.h.tar.gz
(2.16 KB)
📄
pcrecpparg.h.tar
(8.5 KB)
📄
pcregrep.tar
(45 KB)
📄
pcregrep.tar.gz
(19.6 KB)
📄
pcreposix.h.h.tar.gz
(2.27 KB)
📄
pcreposix.h.tar
(7 KB)
📄
pdb.doc.doc.tar.gz
(3.02 KB)
📄
pdb.doc.tar
(9.5 KB)
📄
pdb.py.py.tar.gz
(16.93 KB)
📄
pdb.py.tar
(169.5 KB)
📄
pdb.pyc.pyc.tar.gz
(15.5 KB)
📄
pdb.pyc.tar
(44.5 KB)
📄
pdb.pyo.pyo.tar.gz
(15.5 KB)
📄
pdb.pyo.tar
(44.5 KB)
📄
pdeps.pyc.pyc.tar.gz
(1.62 KB)
📄
pdeps.pyc.tar
(5 KB)
📄
pdeps.pyo.pyo.tar.gz
(1.62 KB)
📄
pdeps.pyo.tar
(5 KB)
📄
pdf.php.php.tar.gz
(14.46 KB)
📄
pdf.php.tar
(52.5 KB)
📄
pdf2dsc.tar
(2.5 KB)
📄
pdf2dsc.tar.gz
(540 B)
📄
pdf2ps.tar
(2.5 KB)
📄
pdf2ps.tar.gz
(654 B)
📄
pdflib-lite.tar
(11.49 MB)
📄
pdflib-lite.tar.gz
(3.59 MB)
📄
pdflib-lite.zip
(11.46 MB)
📄
pdist.tar
(336 KB)
📄
pdist.tar.gz
(93.39 KB)
📄
pdist.zip
(301.4 KB)
📄
pear.conf.conf.tar.gz
(533 B)
📄
pear.conf.tar
(31 KB)
📄
pear.tar
(36 KB)
📄
pear.tar.gz
(295 B)
📄
pear.zip
(13.88 KB)
📄
pecl.tar
(10 KB)
📄
pecl.tar.gz
(273 B)
📄
peel.png.png.tar.gz
(9.57 KB)
📄
peel.png.tar
(11.5 KB)
📄
peel.tar
(191.5 KB)
📄
peel.tar.gz
(112.89 KB)
📄
peel.zip
(172.19 KB)
📄
pem.h.h.tar.gz
(2.7 KB)
📄
pem.h.tar
(17 KB)
📄
pem2.h.h.tar.gz
(371 B)
📄
pem2.h.tar
(2 KB)
📄
pemerr.h.h.tar.gz
(1.33 KB)
📄
pemerr.h.tar
(7 KB)
📄
pentium3-linux.tar
(4.5 KB)
📄
pentium3-linux.tar.gz
(1.2 KB)
📄
pentium3-linux.zip
(3.11 KB)
📄
pentium4-linux.tar
(4.5 KB)
📄
pentium4-linux.tar.gz
(1.2 KB)
📄
pentium4-linux.zip
(3.11 KB)
📄
perInstance.php.php.tar.gz
(1.74 KB)
📄
perInstance.php.tar
(5.5 KB)
📄
percona5.6.tar
(374.5 KB)
📄
percona5.6.tar.gz
(72.05 KB)
📄
percona5.6.zip
(370.48 KB)
📄
percpu_pagelist_fraction.tar
(2 KB)
📄
percpu_pagelist_fraction.tar.gz
(121 B)
📄
perf.tar
(7.5 KB)
📄
perf.tar.gz
(1.89 KB)
📄
perf.zip
(5.76 KB)
📄
perf_event_max_sample_rate.tar
(2 KB)
📄
perf_event_max_sample_rate.tar.gz
(127 B)
📄
perf_event_max_stack.tar
(2 KB)
📄
perf_event_max_stack.tar.gz
(122 B)
📄
perf_event_paranoid.tar
(2 KB)
📄
perf_event_paranoid.tar.gz
(120 B)
📄
perf_regs.h.h.tar.gz
(554 B)
📄
perf_regs.h.tar
(3 KB)
📄
perl.amf.amf.tar.gz
(315 B)
📄
perl.amf.tar
(2 KB)
📄
perl.h.h.tar.gz
(64.99 KB)
📄
perl.h.tar
(239.5 KB)
📄
perl.tar
(27 KB)
📄
perl.tar.gz
(4.14 KB)
📄
perl5.26.3.26.3.tar.gz
(4.14 KB)
📄
perl5.26.3.tar
(14 KB)
📄
perl5.tar
(17.82 MB)
📄
perl5.tar.gz
(5.16 MB)
📄
perl5.zip
(17.65 MB)
📄
perlapi.h.h.tar.gz
(1.82 KB)
📄
perlapi.h.tar
(7.5 KB)
📄
perlbug.tar
(46 KB)
📄
perlbug.tar.gz
(15.56 KB)
📄
perldoc.tar
(2 KB)
📄
perldoc.tar.gz
(191 B)
📄
perlio.h.h.tar.gz
(2.71 KB)
📄
perlio.h.tar
(11 KB)
📄
perliol.h.h.tar.gz
(2.7 KB)
📄
perliol.h.tar
(15 KB)
📄
perlivp.tar
(12.5 KB)
📄
perlivp.tar.gz
(3.58 KB)
📄
perllocal.pod.pod.tar.gz
(1.34 KB)
📄
perllocal.pod.tar
(13 KB)
📄
perlml.tar
(8.5 KB)
📄
perlml.tar.gz
(2.19 KB)
📄
perlsdio.h.h.tar.gz
(438 B)
📄
perlsdio.h.tar
(2.5 KB)
📄
perlthanks.tar
(46 KB)
📄
perlthanks.tar.gz
(15.57 KB)
📄
perlvars.h.h.tar.gz
(4.13 KB)
📄
perlvars.h.tar
(11 KB)
📄
perly.h.h.tar.gz
(2.04 KB)
📄
perly.h.tar
(6 KB)
📄
perm.h.h.tar.gz
(717 B)
📄
perm.h.tar
(3 KB)
📄
permissions.yml.tar
(10 KB)
📄
permissions.yml.yml.tar.gz
(2.98 KB)
📄
pg_dump.tar
(401 KB)
📄
pg_dump.tar.gz
(162.19 KB)
📄
pg_dumpall.tar
(109 KB)
📄
pg_dumpall.tar.gz
(41.47 KB)
📄
pg_prewarm.so.so.tar.gz
(4.5 KB)
📄
pg_prewarm.so.tar
(13.5 KB)
📄
pg_restore.tar
(175 KB)
📄
pg_restore.tar.gz
(75.83 KB)
📄
pgen2.tar
(395 KB)
📄
pgen2.tar.gz
(59.45 KB)
📄
pgen2.zip
(358.96 KB)
📄
pgoutput.so.so.tar.gz
(6.66 KB)
📄
pgoutput.so.tar
(17.5 KB)
📄
pgp.mod.mod.tar.gz
(6.14 KB)
📄
pgp.mod.tar
(32 KB)
📄
pgrep.tar
(30.5 KB)
📄
pgrep.tar.gz
(12.19 KB)
📄
pgsql.tar
(2.58 MB)
📄
pgsql.tar.gz
(1.01 MB)
📄
pgsql.zip
(2.56 MB)
📄
phanfw.bin.bin.tar.gz
(1.35 MB)
📄
phanfw.bin.tar
(3.52 MB)
📄
phar.tar
(137.5 KB)
📄
phar.tar.gz
(14.52 KB)
📄
phoenix.sql.sql.tar.gz
(37.43 KB)
📄
phoenix.sql.tar
(219 KB)
📄
phoenix.tar
(2.8 MB)
📄
phoenix.tar.gz
(2.19 MB)
📄
phoenix.zip
(2.79 MB)
📄
phony.rb.rb.tar.gz
(342 B)
📄
phony.rb.tar
(4 KB)
📄
phorum.tar
(178.5 KB)
📄
phorum.tar.gz
(91.93 KB)
📄
phorum.zip
(152.92 KB)
📄
php-cli.tar
(1.5 KB)
📄
php-cli.tar.gz
(95 B)
📄
php-fpm.conf.conf.tar.gz
(1.77 KB)
📄
php-fpm.conf.plesk.conf.plesk.tar.gz
(1.78 KB)
📄
php-fpm.conf.plesk.tar
(14.5 KB)
📄
php-fpm.conf.tar
(63.5 KB)
📄
php-fpm.d.tar
(23.5 KB)
📄
php-fpm.d.tar.gz
(5.98 KB)
📄
php-fpm.d.zip
(20.98 KB)
📄
php-fpm.tar
(4.83 MB)
📄
php-fpm.tar.gz
(1.88 MB)
📄
php.d.all.def.tar
(115 KB)
📄
php.d.all.def.tar.gz
(3.69 KB)
📄
php.d.all.def.zip
(21.77 KB)
📄
php.d.all.tar
(400.5 KB)
📄
php.d.all.tar.gz
(135.78 KB)
📄
php.d.all.zip
(268.96 KB)
📄
php.d.all.zts.tar
(43 KB)
📄
php.d.all.zts.tar.gz
(1.38 KB)
📄
php.d.all.zts.zip
(43 KB)
📄
php.ini.ini.tar.gz
(100 B)
📄
php.ini.rpmsave.ini.rpmsave.tar.gz
(15.3 KB)
📄
php.ini.rpmsave.tar
(45.5 KB)
📄
php.ini.tar
(885.5 KB)
📄
php.tar
(57.54 MB)
📄
php.tar.gz
(91 B)
📄
php.zip
(4.93 MB)
📄
php52.ini.ini.tar.gz
(511 B)
📄
php52.ini.tar
(3 KB)
📄
php53.ini.ini.tar.gz
(526 B)
📄
php53.ini.tar
(3 KB)
📄
php53.tar
(85 KB)
📄
php53.tar.gz
(4.02 KB)
📄
php53.zip
(88.86 KB)
📄
php54.ini.ini.tar.gz
(574 B)
📄
php54.ini.tar
(3 KB)
📄
php55.ini.ini.tar.gz
(518 B)
📄
php55.ini.tar
(3 KB)
📄
php56.ini.ini.tar.gz
(519 B)
📄
php56.ini.tar
(3 KB)
📄
php56.tar
(43.29 MB)
📄
php56.tar.gz
(26.24 KB)
📄
php56.zip
(97.79 KB)
📄
php70.ini.ini.tar.gz
(500 B)
📄
php70.ini.tar
(3 KB)
📄
php70.tar
(107.17 MB)
📄
php70.tar.gz
(36.45 MB)
📄
php70.zip
(106.58 MB)
📄
php71.ini.ini.tar.gz
(548 B)
📄
php71.ini.tar
(3 KB)
📄
php71.tar
(69.14 MB)
📄
php71.tar.gz
(5.25 KB)
📄
php71.zip
(84.95 KB)
📄
php72.ini.ini.tar.gz
(350 B)
📄
php72.ini.tar
(2.5 KB)
📄
php72.tar
(151.49 MB)
📄
php72.tar.gz
(50.61 MB)
📄
php72.zip
(150.81 MB)
📄
php73.ini.ini.tar.gz
(331 B)
📄
php73.ini.tar
(2.5 KB)
📄
php73.tar
(129.88 MB)
📄
php73.tar.gz
(44.12 MB)
📄
php73.zip
(129.28 MB)
📄
php74.ini.ini.tar.gz
(339 B)
📄
php74.ini.tar
(2.5 KB)
📄
php80.ini.ini.tar.gz
(377 B)
📄
php80.ini.tar
(2.5 KB)
📄
php80.tar
(137.91 MB)
📄
php80.tar.gz
(45.59 MB)
📄
php80.zip
(137.26 MB)
📄
php81.ini.ini.tar.gz
(377 B)
📄
php81.ini.tar
(2.5 KB)
📄
php81.tar
(102.22 MB)
📄
php81.tar.gz
(4.5 KB)
📄
php81.zip
(140.66 MB)
📄
php82.ini.ini.tar.gz
(377 B)
📄
php82.ini.tar
(2.5 KB)
📄
php82.tar
(101.92 MB)
📄
php82.tar.gz
(4.52 KB)
📄
php82.zip
(133.64 MB)
📄
php83.ini.ini.tar.gz
(377 B)
📄
php83.ini.tar
(2.5 KB)
📄
php83.tar
(137.59 MB)
📄
php83.tar.gz
(44.81 MB)
📄
php83.zip
(137.05 MB)
📄
php84.ini.ini.tar.gz
(377 B)
📄
php84.ini.tar
(2.5 KB)
📄
php85.ini.ini.tar.gz
(340 B)
📄
php85.ini.tar
(2.5 KB)
📄
phpaddr.tar
(100.5 KB)
📄
phpaddr.tar.gz
(49.49 KB)
📄
phpaddr.zip
(85.8 KB)
📄
phpbb.sql.sql.tar.gz
(28.73 KB)
📄
phpbb.sql.tar
(208 KB)
📄
phpbb.tar
(9.99 MB)
📄
phpbb.tar.gz
(8.78 MB)
📄
phpbb.zip
(9.95 MB)
📄
phpcol.tar
(241 KB)
📄
phpcol.tar.gz
(133.45 KB)
📄
phpcol.zip
(209.42 KB)
📄
phpdbg.tar
(36.1 MB)
📄
phpdbg.tar.gz
(2.14 MB)
📄
phpinfo.php.php.tar.gz
(158 B)
📄
phpinfo.php.tar
(2 KB)
📄
phpize.tar
(47 KB)
📄
phpize.tar.gz
(1.73 KB)
📄
phpjs.tar
(88.5 KB)
📄
phpjs.tar.gz
(62.34 KB)
📄
phpjs.zip
(79.19 KB)
📄
phplist.sql.sql.tar.gz
(37.68 KB)
📄
phplist.sql.tar
(178 KB)
📄
phplist.tar
(27.23 MB)
📄
phplist.tar.gz
(23.43 MB)
📄
phplist.zip
(27.21 MB)
📄
phplite.tar
(322 KB)
📄
phplite.tar.gz
(100.93 KB)
📄
phplite.zip
(307.94 KB)
📄
phplot.tar
(49 KB)
📄
phplot.tar.gz
(31.09 KB)
📄
phplot.zip
(40.04 KB)
📄
phppoll.tar
(135.5 KB)
📄
phppoll.tar.gz
(70.76 KB)
📄
phppoll.zip
(116.35 KB)
📄
phproj.tar
(201 KB)
📄
phproj.tar.gz
(108.61 KB)
📄
phproj.zip
(172.79 KB)
📄
phpsch.tar
(203 KB)
📄
phpsch.tar.gz
(101.56 KB)
📄
phpsch.zip
(175.36 KB)
📄
phpwcms.sql.sql.tar.gz
(16.74 KB)
📄
phpwcms.sql.tar
(86 KB)
📄
phpwcms.tar
(8.87 MB)
📄
phpwcms.tar.gz
(7.75 MB)
📄
phpwcms.zip
(8.84 MB)
📄
pi.py.py.tar.gz
(608 B)
📄
pi.py.tar
(2.5 KB)
📄
pic.tar
(295.5 KB)
📄
pic.tar.gz
(97.49 KB)
📄
picasso_asd.bin.bin.tar.gz
(62.92 KB)
📄
picasso_asd.bin.tar
(194 KB)
📄
picasso_ce.bin.bin.tar.gz
(3.47 KB)
📄
picasso_ce.bin.tar
(11 KB)
📄
picasso_me.bin.bin.tar.gz
(6.9 KB)
📄
picasso_me.bin.tar
(19 KB)
📄
picasso_mec.bin.bin.tar.gz
(32.67 KB)
📄
picasso_mec.bin.tar
(263.5 KB)
📄
picasso_mec2.bin.bin.tar.gz
(32.66 KB)
📄
picasso_mec2.bin.tar
(263.5 KB)
📄
picasso_pfp.bin.bin.tar.gz
(10.14 KB)
📄
picasso_pfp.bin.tar
(23 KB)
📄
picasso_rlc.bin.bin.tar.gz
(11.95 KB)
📄
picasso_rlc.bin.tar
(40 KB)
📄
picasso_rlc_am4.bin.bin.tar.gz
(11.72 KB)
📄
picasso_rlc_am4.bin.tar
(40 KB)
📄
picasso_sdma.bin.bin.tar.gz
(8.38 KB)
📄
picasso_sdma.bin.tar
(18.5 KB)
📄
picasso_ta.bin.bin.tar.gz
(14.61 KB)
📄
picasso_ta.bin.tar
(46.5 KB)
📄
picasso_vcn.bin.bin.tar.gz
(251.28 KB)
📄
picasso_vcn.bin.tar
(359.5 KB)
📄
pickle.cpython-38.opt-2.pyc.cpython-38.opt-2.pyc.tar.gz
(16.51 KB)
📄
pickle.cpython-38.opt-2.pyc.tar
(41.5 KB)
📄
pickle.py.py.tar.gz
(15.52 KB)
📄
pickle.py.tar
(164.5 KB)
📄
pickle.pyc.pyc.tar.gz
(13.37 KB)
📄
pickle.pyc.tar
(39.5 KB)
📄
pickle.pyo.pyo.tar.gz
(13.27 KB)
📄
pickle.pyo.tar
(39 KB)
📄
pickle2db.py.py.tar.gz
(1.24 KB)
📄
pickle2db.py.tar
(5.5 KB)
📄
pickletools.py.py.tar.gz
(21.44 KB)
📄
pickletools.py.tar
(257 KB)
📄
pickletools.pyc.pyc.tar.gz
(17.8 KB)
📄
pickletools.pyc.tar
(57.5 KB)
📄
pickletools.pyo.pyo.tar.gz
(17.42 KB)
📄
pickletools.pyo.tar
(56.5 KB)
📄
piconv.tar
(10 KB)
📄
piconv.tar.gz
(3.01 KB)
📄
pid_max.tar
(2 KB)
📄
pid_max.tar.gz
(114 B)
📄
pie.png.png.tar.gz
(8.73 KB)
📄
pie.png.tar
(10.5 KB)
📄
pie.tar
(913 KB)
📄
pie.tar.gz
(801.76 KB)
📄
pie.zip
(900.19 KB)
📄
pier.png.png.tar.gz
(9.21 KB)
📄
pier.png.tar
(11 KB)
📄
pier.tar
(173.5 KB)
📄
pier.tar.gz
(92.82 KB)
📄
pier.zip
(151.28 KB)
📄
pimcore.sql.sql.tar.gz
(6.96 KB)
📄
pimcore.sql.tar
(54 KB)
📄
pimcore.tar
(103.14 MB)
📄
pimcore.tar.gz
(84.46 MB)
📄
pimcore.zip
(103.12 MB)
📄
pinentry-curses.tar
(79.5 KB)
📄
pinentry-curses.tar.gz
(34.95 KB)
📄
pinentry.tar
(4 KB)
📄
pinentry.tar.gz
(1.02 KB)
📄
ping.tar
(68 KB)
📄
ping.tar.gz
(32.17 KB)
📄
ping_group_range.tar
(2 KB)
📄
ping_group_range.tar.gz
(129 B)
📄
pinky.tar
(43 KB)
📄
pinky.tar.gz
(18.6 KB)
📄
pip-2.7.7.tar.gz
(408 B)
📄
pip-2.7.tar
(2.5 KB)
📄
pip-2.tar
(2.5 KB)
📄
pip-2.tar.gz
(406 B)
📄
pip-3.5.5.tar.gz
(407 B)
📄
pip-3.5.tar
(2.5 KB)
📄
pip-3.6.6.tar.gz
(408 B)
📄
pip-3.6.tar
(2.5 KB)
📄
pip-3.7.7.tar.gz
(408 B)
📄
pip-3.7.tar
(2.5 KB)
📄
pip-3.8.8.tar.gz
(408 B)
📄
pip-3.8.tar
(2.5 KB)
📄
pip-3.9.9.tar.gz
(408 B)
📄
pip-3.9.tar
(2.5 KB)
📄
pip-3.tar
(8.5 KB)
📄
pip-3.tar.gz
(406 B)
📄
pip.tar
(14 KB)
📄
pip.tar.gz
(405 B)
📄
pip2.7.7.tar.gz
(406 B)
📄
pip2.7.tar
(2.5 KB)
📄
pip2.tar
(2.5 KB)
📄
pip2.tar.gz
(404 B)
📄
pip3.11.11.tar.gz
(268 B)
📄
pip3.11.tar
(2 KB)
📄
pip3.12.12.tar.gz
(262 B)
📄
pip3.12.tar
(2 KB)
📄
pip3.3.3.tar.gz
(253 B)
📄
pip3.3.tar
(2 KB)
📄
pip3.4.4.tar.gz
(254 B)
📄
pip3.4.tar
(2 KB)
📄
pip3.5.5.tar.gz
(407 B)
📄
pip3.5.tar
(2.5 KB)
📄
pip3.6.6.tar.gz
(407 B)
📄
pip3.6.tar
(2.5 KB)
📄
pip3.7.7.tar.gz
(407 B)
📄
pip3.7.tar
(2.5 KB)
📄
pip3.8.8.tar.gz
(407 B)
📄
pip3.8.tar
(2.5 KB)
📄
pip3.9.9.tar.gz
(407 B)
📄
pip3.9.tar
(2.5 KB)
📄
pip3.tar
(12.5 KB)
📄
pip3.tar.gz
(405 B)
📄
pipe-max-size.tar
(2 KB)
📄
pipe-max-size.tar.gz
(116 B)
📄
pipe.php.php.tar.gz
(159 B)
📄
pipe.php.tar
(2 KB)
📄
pipes.py.py.tar.gz
(2.76 KB)
📄
pipes.py.tar
(30 KB)
📄
pipes.pyc.pyc.tar.gz
(3.82 KB)
📄
pipes.pyc.tar
(11 KB)
📄
pipes.pyo.pyo.tar.gz
(3.82 KB)
📄
pipes.pyo.tar
(11 KB)
📄
pitcairn_ce.bin.bin.tar.gz
(1.07 KB)
📄
pitcairn_ce.bin.tar
(20 KB)
📄
pitcairn_k_smc.bin.bin.tar.gz
(26.47 KB)
📄
pitcairn_k_smc.bin.tar
(123 KB)
📄
pitcairn_mc.bin.bin.tar.gz
(12.6 KB)
📄
pitcairn_mc.bin.tar
(64 KB)
📄
pitcairn_me.bin.bin.tar.gz
(3.68 KB)
📄
pitcairn_me.bin.tar
(20 KB)
📄
pitcairn_pfp.bin.bin.tar.gz
(2.79 KB)
📄
pitcairn_pfp.bin.tar
(20 KB)
📄
pitcairn_rlc.bin.bin.tar.gz
(2.59 KB)
📄
pitcairn_rlc.bin.tar
(19 KB)
📄
pitcairn_smc.bin.bin.tar.gz
(26.32 KB)
📄
pitcairn_smc.bin.tar
(122 KB)
📄
pitcairn_uvd.bin.bin.tar.gz
(144.34 KB)
📄
pitcairn_uvd.bin.tar
(216.5 KB)
📄
pivotx.tar
(167.5 KB)
📄
pivotx.tar.gz
(90.21 KB)
📄
pivotx.zip
(143.14 KB)
📄
piwigo.sql.sql.tar.gz
(6.7 KB)
📄
piwigo.sql.tar
(38 KB)
📄
piwigo.tar
(18.61 MB)
📄
piwigo.tar.gz
(17.47 MB)
📄
piwigo.zip
(18.58 MB)
📄
piwik.sql.sql.tar.gz
(5.82 KB)
📄
piwik.sql.tar
(39 KB)
📄
piwik.tar
(26.32 MB)
📄
piwik.tar.gz
(24.01 MB)
📄
piwik.zip
(26.29 MB)
📄
pk11.tar
(4.5 KB)
📄
pk11.tar.gz
(1.03 KB)
📄
pk11.zip
(2.97 KB)
📄
pkcs11.so.so.tar.gz
(38.7 KB)
📄
pkcs11.so.tar
(94.5 KB)
📄
pkcs11.tar
(251 KB)
📄
pkcs11.tar.gz
(95.44 KB)
📄
pkcs11.zip
(249.4 KB)
📄
pkcs12.h.h.tar.gz
(2.2 KB)
📄
pkcs12.h.tar
(11.5 KB)
📄
pkcs12err.h.h.tar.gz
(1.1 KB)
📄
pkcs12err.h.tar
(5.5 KB)
📄
pkcs1_v15.mod.mod.tar.gz
(720 B)
📄
pkcs1_v15.mod.tar
(5 KB)
📄
pkcs7.h.h.tar.gz
(5.36 KB)
📄
pkcs7.h.tar
(34 KB)
📄
pkcs7err.h.h.tar.gz
(1.35 KB)
📄
pkcs7err.h.tar
(6.5 KB)
📄
pkg-config.tar
(42 KB)
📄
pkg-config.tar.gz
(16.05 KB)
📄
pkgIndex.tcl.tar
(4 KB)
📄
pkgIndex.tcl.tcl.tar.gz
(210 B)
📄
pkgconf.tar
(42 KB)
📄
pkgconf.tar.gz
(16.04 KB)
📄
pkgconfig.tar
(144 KB)
📄
pkgconfig.tar.gz
(9.39 KB)
📄
pkgconfig.zip
(64.58 KB)
📄
pkgutil.py.py.tar.gz
(6.09 KB)
📄
pkgutil.py.tar
(64.5 KB)
📄
pkgutil.pyc.pyc.tar.gz
(7.76 KB)
📄
pkgutil.pyc.tar
(20.5 KB)
📄
pkgutil.pyo.pyo.tar.gz
(7.76 KB)
📄
pkgutil.pyo.tar
(20.5 KB)
📄
pkill.tar
(30.5 KB)
📄
pkill.tar.gz
(12.19 KB)
📄
pl.tar
(164 KB)
📄
pl.tar.gz
(136.23 KB)
📄
pl.zip
(140.23 KB)
📄
pl2pm.tar
(6 KB)
📄
pl2pm.tar.gz
(2.16 KB)
📄
pla4e2b1.tar
(51 KB)
📄
pla4e2b1.tar.gz
(18.54 KB)
📄
pla4e2b1.zip
(48.2 KB)
📄
plan9.mod.mod.tar.gz
(3.9 KB)
📄
plan9.mod.tar
(19 KB)
📄
plat-linux2.tar
(104.5 KB)
📄
plat-linux2.tar.gz
(22.17 KB)
📄
plat-linux2.zip
(94.95 KB)
📄
platform-python3.6.6.tar.gz
(4.03 KB)
📄
platform-python3.6.tar
(13.5 KB)
📄
platform-python3.6m.6m.tar.gz
(4.03 KB)
📄
platform-python3.6m.tar
(13.5 KB)
📄
platform.h.h.tar.gz
(8.01 KB)
📄
platform.h.tar
(29 KB)
📄
platform.py.py.tar.gz
(13.58 KB)
📄
platform.py.tar
(140.5 KB)
📄
platform.pyc.pyc.tar.gz
(15.25 KB)
📄
platform.pyc.tar
(39 KB)
📄
platform.pyo.pyo.tar.gz
(15.25 KB)
📄
platform.pyo.tar
(39 KB)
📄
platform.tar
(283.5 KB)
📄
platform.tar.gz
(11.01 KB)
📄
platform.zip
(242.53 KB)
📄
platforminputcontexts.tar
(170.5 KB)
📄
platforminputcontexts.tar.gz
(65.34 KB)
📄
platforminputcontexts.zip
(168.44 KB)
📄
platforms.tar
(1.29 MB)
📄
platforms.tar.gz
(535.75 KB)
📄
platforms.zip
(1.29 MB)
📄
play.mod.mod.tar.gz
(1.64 KB)
📄
play.mod.tar
(5 KB)
📄
playlistformats.tar
(30.5 KB)
📄
playlistformats.tar.gz
(10.39 KB)
📄
playlistformats.zip
(28.88 KB)
📄
plesk.tar
(413 KB)
📄
plesk.tar.gz
(44.42 KB)
📄
plesk.zip
(401.36 KB)
📄
plex.xml.tar
(2.5 KB)
📄
plex.xml.xml.tar.gz
(525 B)
📄
plikli.tar
(373.5 KB)
📄
plikli.tar.gz
(221.36 KB)
📄
plikli.zip
(345.19 KB)
📄
plistlib.py.py.tar.gz
(8.04 KB)
📄
plistlib.py.tar
(81.5 KB)
📄
plistlib.pyc.pyc.tar.gz
(7.11 KB)
📄
plistlib.pyc.tar
(21 KB)
📄
plistlib.pyo.pyo.tar.gz
(7.07 KB)
📄
plistlib.pyo.tar
(21 KB)
📄
plpgsql.so.so.tar.gz
(81.08 KB)
📄
plpgsql.so.tar
(187 KB)
📄
pluck.tar
(1.8 MB)
📄
pluck.tar.gz
(1.63 MB)
📄
pluck.zip
(1.77 MB)
📄
plugin.h.h.tar.gz
(1.07 KB)
📄
plugin.h.tar
(34 KB)
📄
plugin.tar
(293 KB)
📄
plugin.tar.gz
(123.16 KB)
📄
plugin.zip
(288.56 KB)
📄
plugin_audit.h.h.tar.gz
(2.01 KB)
📄
plugin_audit.h.tar
(7 KB)
📄
plugin_deactivate.php.php.tar.gz
(431 B)
📄
plugin_deactivate.php.tar
(31 KB)
📄
plugin_hrtimer.so.so.tar.gz
(2.56 KB)
📄
plugin_hrtimer.so.tar
(8.5 KB)
📄
plugin_jbd2.so.so.tar.gz
(2.3 KB)
📄
plugin_jbd2.so.tar
(8.5 KB)
📄
plugin_kmem.so.so.tar.gz
(2.74 KB)
📄
plugin_kmem.so.tar
(8.5 KB)
📄
plugin_scsi.so.so.tar.gz
(3.23 KB)
📄
plugin_scsi.so.tar
(8.5 KB)
📄
plugins.php.php.tar.gz
(183 B)
📄
plugins.php.tar
(2 KB)
📄
plugins.qmltypes.qmltypes.tar.gz
(1.8 KB)
📄
plugins.qmltypes.tar
(31 KB)
📄
plugins.tar
(29.63 MB)
📄
plugins.tar.gz
(77.88 KB)
📄
plugins.zip
(29.57 MB)
📄
pluginviewer.tar
(44 KB)
📄
pluginviewer.tar.gz
(7.27 KB)
📄
plurrule.h.h.tar.gz
(4.95 KB)
📄
plurrule.h.tar
(20 KB)
📄
plusnode.gif.gif.tar.gz
(204 B)
📄
plusnode.gif.tar
(2 KB)
📄
pluxml.tar
(1.38 MB)
📄
pluxml.tar.gz
(1.22 MB)
📄
pluxml.zip
(1.36 MB)
📄
plymouth-kexec.service.service.tar.gz
(371 B)
📄
plymouth-kexec.service.tar
(2 KB)
📄
plymouth-reboot.service.service.tar.gz
(366 B)
📄
plymouth-reboot.service.tar
(2 KB)
📄
plymouth-start.service.service.tar.gz
(426 B)
📄
plymouth-start.service.tar
(2.5 KB)
📄
plymouth.tar
(59.5 KB)
📄
plymouth.tar.gz
(15.44 KB)
📄
plymouth.zip
(56.38 KB)
📄
pm-utils.tar
(3.5 KB)
📄
pm-utils.tar.gz
(812 B)
📄
pm-utils.zip
(1.93 KB)
📄
pma_template_compiles_gfecatvj.tar
(2.35 MB)
📄
pma_template_compiles_gfecatvj.tar.gz
(321.25 KB)
📄
pma_template_compiles_gfecatvj.zip
(2.18 MB)
📄
pmap.tar
(34.5 KB)
📄
pmap.tar.gz
(13.86 KB)
📄
pmap_clnt.h.h.tar.gz
(1.57 KB)
📄
pmap_clnt.h.tar
(5 KB)
📄
pmap_prot.h.h.tar.gz
(1.76 KB)
📄
pmap_prot.h.tar
(5.5 KB)
📄
pmap_rmt.h.h.tar.gz
(1.21 KB)
📄
pmap_rmt.h.tar
(4 KB)
📄
pmcd.xml.tar
(2 KB)
📄
pmcd.xml.xml.tar.gz
(375 B)
📄
pmlastmsg.so.so.tar.gz
(4.33 KB)
📄
pmlastmsg.so.tar
(14.5 KB)
📄
pmproxy.xml.tar
(2 KB)
📄
pmproxy.xml.xml.tar.gz
(394 B)
📄
pmsnare.so.so.tar.gz
(6.64 KB)
📄
pmsnare.so.tar
(18.5 KB)
📄
pmwebapi.xml.tar
(2 KB)
📄
pmwebapi.xml.xml.tar.gz
(385 B)
📄
pmwebapis.xml.tar
(2.5 KB)
📄
pmwebapis.xml.xml.tar.gz
(429 B)
📄
pmwiki.tar
(3.58 MB)
📄
pmwiki.tar.gz
(3.31 MB)
📄
pmwiki.zip
(3.54 MB)
📄
png.h.h.tar.gz
(39.35 KB)
📄
png.h.tar
(284 KB)
📄
png.mod.mod.tar.gz
(4.91 KB)
📄
png.mod.tar
(24 KB)
📄
pngconf.h.h.tar.gz
(7.01 KB)
📄
pngconf.h.tar
(47 KB)
📄
pnglibconf.h.h.tar.gz
(1.63 KB)
📄
pnglibconf.h.tar
(17 KB)
📄
pod2html.tar
(6 KB)
📄
pod2html.tar.gz
(1.61 KB)
📄
pod2man.tar
(16.5 KB)
📄
pod2man.tar.gz
(5.96 KB)
📄
pod2text.tar
(12.5 KB)
📄
pod2text.tar.gz
(4.48 KB)
📄
pod2usage.tar
(5.5 KB)
📄
pod2usage.tar.gz
(1.76 KB)
📄
podcast.tar
(248.5 KB)
📄
podcast.tar.gz
(142.21 KB)
📄
podcast.zip
(216.3 KB)
📄
podchecker.tar
(5.5 KB)
📄
podchecker.tar.gz
(1.69 KB)
📄
podselect.tar
(4 KB)
📄
podselect.tar.gz
(1.24 KB)
📄
polaris10_ce.bin.bin.tar.gz
(3.03 KB)
📄
polaris10_ce.bin.tar
(10.5 KB)
📄
polaris10_ce_2.bin.bin.tar.gz
(3.06 KB)
📄
polaris10_ce_2.bin.tar
(10.5 KB)
📄
polaris10_k_mc.bin.bin.tar.gz
(13.88 KB)
📄
polaris10_k_mc.bin.tar
(34 KB)
📄
polaris10_k_smc.bin.bin.tar.gz
(55.5 KB)
📄
polaris10_k_smc.bin.tar
(129 KB)
📄
polaris10_mc.bin.bin.tar.gz
(13.83 KB)
📄
polaris10_mc.bin.tar
(33.5 KB)
📄
polaris10_me.bin.bin.tar.gz
(6.25 KB)
📄
polaris10_me.bin.tar
(18.5 KB)
📄
polaris10_me_2.bin.bin.tar.gz
(6.37 KB)
📄
polaris10_me_2.bin.tar
(18.5 KB)
📄
polaris10_mec2.bin.bin.tar.gz
(27.32 KB)
📄
polaris10_mec2.bin.tar
(258.5 KB)
📄
polaris10_mec_2.bin.bin.tar.gz
(27.89 KB)
📄
polaris10_mec_2.bin.tar
(258.5 KB)
📄
polaris10_pfp.bin.bin.tar.gz
(8.36 KB)
📄
polaris10_pfp.bin.tar
(18.5 KB)
📄
polaris10_pfp_2.bin.bin.tar.gz
(8.48 KB)
📄
polaris10_pfp_2.bin.tar
(18.5 KB)
📄
polaris10_sdma.bin.bin.tar.gz
(5 KB)
📄
polaris10_sdma.bin.tar
(14 KB)
📄
polaris10_sdma1.bin.bin.tar.gz
(5 KB)
📄
polaris10_sdma1.bin.tar
(14 KB)
📄
polaris11_ce.bin.bin.tar.gz
(3.03 KB)
📄
polaris11_ce.bin.tar
(10.5 KB)
📄
polaris11_ce_2.bin.bin.tar.gz
(3.06 KB)
📄
polaris11_ce_2.bin.tar
(10.5 KB)
📄
polaris11_k_mc.bin.bin.tar.gz
(13.88 KB)
📄
polaris11_k_mc.bin.tar
(34 KB)
📄
polaris11_k_smc.bin.bin.tar.gz
(54.09 KB)
📄
polaris11_k_smc.bin.tar
(129 KB)
📄
polaris11_mc.bin.bin.tar.gz
(14.08 KB)
📄
polaris11_mc.bin.tar
(34 KB)
📄
polaris11_me.bin.bin.tar.gz
(6.25 KB)
📄
polaris11_me.bin.tar
(18.5 KB)
📄
polaris11_me_2.bin.bin.tar.gz
(6.35 KB)
📄
polaris11_me_2.bin.tar
(18.5 KB)
📄
polaris11_mec2.bin.bin.tar.gz
(27.28 KB)
📄
polaris11_mec2.bin.tar
(258.5 KB)
📄
polaris11_mec_2.bin.bin.tar.gz
(27.84 KB)
📄
polaris11_mec_2.bin.tar
(258.5 KB)
📄
polaris11_pfp_2.bin.bin.tar.gz
(8.47 KB)
📄
polaris11_pfp_2.bin.tar
(18.5 KB)
📄
polaris11_sdma.bin.bin.tar.gz
(5 KB)
📄
polaris11_sdma.bin.tar
(14 KB)
📄
polaris11_sdma1.bin.bin.tar.gz
(5 KB)
📄
polaris11_sdma1.bin.tar
(14 KB)
📄
polaris12_32_mc.bin.bin.tar.gz
(13.89 KB)
📄
polaris12_32_mc.bin.tar
(34 KB)
📄
polaris12_ce.bin.bin.tar.gz
(3.03 KB)
📄
polaris12_ce.bin.tar
(10.5 KB)
📄
polaris12_ce_2.bin.bin.tar.gz
(3.06 KB)
📄
polaris12_ce_2.bin.tar
(10.5 KB)
📄
polaris12_k_mc.bin.bin.tar.gz
(13.88 KB)
📄
polaris12_k_mc.bin.tar
(34 KB)
📄
polaris12_k_smc.bin.bin.tar.gz
(54.96 KB)
📄
polaris12_k_smc.bin.tar
(129 KB)
📄
polaris12_mc.bin.bin.tar.gz
(13.79 KB)
📄
polaris12_mc.bin.tar
(33.5 KB)
📄
polaris12_me.bin.bin.tar.gz
(6.25 KB)
📄
polaris12_me.bin.tar
(18.5 KB)
📄
polaris12_me_2.bin.bin.tar.gz
(6.35 KB)
📄
polaris12_me_2.bin.tar
(18.5 KB)
📄
polaris12_mec2.bin.bin.tar.gz
(27.21 KB)
📄
polaris12_mec2.bin.tar
(258.5 KB)
📄
polaris12_mec_2.bin.bin.tar.gz
(27.79 KB)
📄
polaris12_mec_2.bin.tar
(258.5 KB)
📄
polaris12_pfp_2.bin.bin.tar.gz
(8.47 KB)
📄
polaris12_pfp_2.bin.tar
(18.5 KB)
📄
polaris12_sdma.bin.bin.tar.gz
(5 KB)
📄
polaris12_sdma.bin.tar
(14 KB)
📄
polaris12_sdma1.bin.bin.tar.gz
(5 KB)
📄
polaris12_sdma1.bin.tar
(14 KB)
📄
polcaps.h.h.tar.gz
(425 B)
📄
polcaps.h.tar
(2.5 KB)
📄
policies.tar
(2.5 KB)
📄
policies.tar.gz
(370 B)
📄
policies.zip
(821 B)
📄
policy.py.py.tar.gz
(3.52 KB)
📄
policy.py.tar
(23 KB)
📄
policydb.h.h.tar.gz
(1.52 KB)
📄
policydb.h.tar
(6.5 KB)
📄
policydb.tar
(97.5 KB)
📄
policydb.tar.gz
(19.76 KB)
📄
policydb.zip
(83.7 KB)
📄
polkit-1.tar
(158.5 KB)
📄
polkit-1.tar.gz
(61.55 KB)
📄
polkit-1.zip
(155.97 KB)
📄
polkit.service.service.tar.gz
(248 B)
📄
polkit.service.tar
(3 KB)
📄
polkitd.tar
(281 KB)
📄
polkitd.tar.gz
(55 KB)
📄
poll.go.go.tar.gz
(10.87 KB)
📄
poll.go.tar
(34.5 KB)
📄
poll.h.h.tar.gz
(115 B)
📄
poll.h.tar
(10.5 KB)
📄
poll2.h.h.tar.gz
(992 B)
📄
poll2.h.tar
(4 KB)
📄
poll_config.php.php.tar.gz
(620 B)
📄
poll_config.php.tar
(3 KB)
📄
pool.conf.conf.tar.gz
(230 B)
📄
pool.conf.tar
(2 KB)
📄
pool.py.py.tar.gz
(7.26 KB)
📄
pool.py.tar
(84 KB)
📄
poolsize.tar
(2 KB)
📄
poolsize.tar.gz
(119 B)
📄
pop.rb.rb.tar.gz
(6.92 KB)
📄
pop.rb.tar
(110.5 KB)
📄
pop3.xml.tar
(2 KB)
📄
pop3.xml.xml.tar.gz
(336 B)
📄
pop3s.xml.tar
(2 KB)
📄
pop3s.xml.xml.tar.gz
(348 B)
📄
popen2.py.py.tar.gz
(2.03 KB)
📄
popen2.py.tar
(10 KB)
📄
popen2.pyc.pyc.tar.gz
(2.85 KB)
📄
popen2.pyc.tar
(10.5 KB)
📄
popen2.pyo.pyo.tar.gz
(2.83 KB)
📄
popen2.pyo.tar
(10.5 KB)
📄
popen_fork.py.py.tar.gz
(908 B)
📄
popen_fork.py.tar
(7.5 KB)
📄
poplib.py.py.tar.gz
(4.87 KB)
📄
poplib.py.tar
(45.5 KB)
📄
poplib.pyc.pyc.tar.gz
(5.2 KB)
📄
poplib.pyc.tar
(15 KB)
📄
poplib.pyo.pyo.tar.gz
(5.2 KB)
📄
poplib.pyo.tar
(15 KB)
📄
popoji.tar
(180.5 KB)
📄
popoji.tar.gz
(104.42 KB)
📄
popoji.zip
(158.63 KB)
📄
port_record.h.h.tar.gz
(604 B)
📄
port_record.h.tar
(3.5 KB)
📄
portable.tar
(7.5 KB)
📄
portable.tar.gz
(908 B)
📄
portable.zip
(3.7 KB)
📄
portablectl.tar
(76 KB)
📄
portablectl.tar.gz
(16.16 KB)
📄
portables.conf.conf.tar.gz
(190 B)
📄
portables.conf.tar
(2 KB)
📄
portofolio.tar
(2 KB)
📄
portofolio.tar.gz
(186 B)
📄
portofolio.zip
(260 B)
📄
ports.h.h.tar.gz
(545 B)
📄
ports.h.tar
(3 KB)
📄
posix_opt.h.h.tar.gz
(2.06 KB)
📄
posix_opt.h.tar
(7.5 KB)
📄
posix_types.ph.ph.tar.gz
(223 B)
📄
posix_types.ph.tar
(3 KB)
📄
posix_types_32.ph.ph.tar.gz
(261 B)
📄
posix_types_32.ph.tar
(2 KB)
📄
posix_types_64.h.h.tar.gz
(427 B)
📄
posix_types_64.h.tar
(2.5 KB)
📄
posix_types_64.ph.ph.tar.gz
(261 B)
📄
posix_types_64.ph.tar
(2 KB)
📄
posix_types_x32.h.h.tar.gz
(445 B)
📄
posix_types_x32.h.tar
(2.5 KB)
📄
posix_types_x32.ph.ph.tar.gz
(279 B)
📄
posix_types_x32.ph.tar
(2 KB)
📄
posixfile.py.py.tar.gz
(2.36 KB)
📄
posixfile.py.tar
(9.5 KB)
📄
posixpath.py.py.tar.gz
(4.9 KB)
📄
posixpath.py.tar
(48 KB)
📄
post-grohtml.tar
(240.5 KB)
📄
post-grohtml.tar.gz
(102.74 KB)
📄
post_download.json.json.tar.gz
(186 B)
📄
post_download.json.tar
(2 KB)
📄
postfix.sql.sql.tar.gz
(2.15 KB)
📄
postfix.sql.tar
(15.5 KB)
📄
postfix.tar
(32.96 MB)
📄
postfix.tar.gz
(31.35 MB)
📄
postfix.zip
(32.94 MB)
📄
postgresql.conf.conf.tar.gz
(134 B)
📄
postgresql.conf.tar
(3 KB)
📄
postgresql.service.service.tar.gz
(971 B)
📄
postgresql.service.tar
(3 KB)
📄
postgresql11.tar
(306.5 KB)
📄
postgresql11.tar.gz
(134.39 KB)
📄
postgresql11.zip
(304.18 KB)
📄
postgresql@.service.service.tar.gz
(959 B)
📄
postgresql@.service.tar
(3 KB)
📄
poweroff.target.tar
(2.5 KB)
📄
poweroff.target.target.tar.gz
(472 B)
📄
poweroff_cmd.tar
(2 KB)
📄
poweroff_cmd.tar.gz
(121 B)
📄
powersave.tar
(3.5 KB)
📄
powersave.tar.gz
(615 B)
📄
powersave.zip
(1.16 KB)
📄
powervr.tar
(266 KB)
📄
powervr.tar.gz
(125.81 KB)
📄
powervr.zip
(264.33 KB)
📄
pp.h.h.tar.gz
(6.4 KB)
📄
pp.h.tar
(28.5 KB)
📄
pp.py.py.tar.gz
(1.52 KB)
📄
pp.py.tar
(5.5 KB)
📄
pp_proto.h.h.tar.gz
(1.58 KB)
📄
pp_proto.h.tar
(13.5 KB)
📄
ppc-linux.tar
(4.5 KB)
📄
ppc-linux.tar.gz
(1.18 KB)
📄
ppc-linux.zip
(3.09 KB)
📄
ppc.tar
(35 KB)
📄
ppc.tar.gz
(14.74 KB)
📄
ppc.zip
(21.63 KB)
📄
ppc32dy4-linux.tar
(4.5 KB)
📄
ppc32dy4-linux.tar.gz
(1.18 KB)
📄
ppc32dy4-linux.zip
(3.09 KB)
📄
ppc64-linux.tar
(4.5 KB)
📄
ppc64-linux.tar.gz
(1.19 KB)
📄
ppc64-linux.zip
(3.1 KB)
📄
ppc64iseries-linux.tar
(4.5 KB)
📄
ppc64iseries-linux.tar.gz
(1.18 KB)
📄
ppc64iseries-linux.zip
(3.09 KB)
📄
ppc64le-linux.tar
(4.5 KB)
📄
ppc64le-linux.tar.gz
(1.19 KB)
📄
ppc64le-linux.zip
(3.11 KB)
📄
ppc64p7-linux.tar
(4.5 KB)
📄
ppc64p7-linux.tar.gz
(1.2 KB)
📄
ppc64p7-linux.zip
(3.13 KB)
📄
ppc64pseries-linux.tar
(4.5 KB)
📄
ppc64pseries-linux.tar.gz
(1.18 KB)
📄
ppc64pseries-linux.zip
(3.09 KB)
📄
ppc8260-linux.tar
(4.5 KB)
📄
ppc8260-linux.tar.gz
(1.18 KB)
📄
ppc8260-linux.zip
(3.09 KB)
📄
ppc8560-linux.tar
(4.5 KB)
📄
ppc8560-linux.tar.gz
(1.18 KB)
📄
ppc8560-linux.zip
(3.09 KB)
📄
ppciseries-linux.tar
(4.5 KB)
📄
ppciseries-linux.tar.gz
(1.18 KB)
📄
ppciseries-linux.zip
(3.09 KB)
📄
ppcpseries-linux.tar
(4.5 KB)
📄
ppcpseries-linux.tar.gz
(1.18 KB)
📄
ppcpseries-linux.zip
(3.09 KB)
📄
ppp-comp.h.h.tar.gz
(125 B)
📄
ppp-comp.h.tar
(2 KB)
📄
ppp_defs.h.h.tar.gz
(202 B)
📄
ppp_defs.h.tar
(2 KB)
📄
pprint.py.py.tar.gz
(4.71 KB)
📄
pprint.py.tar
(56 KB)
📄
pprint.pyc.pyc.tar.gz
(4.32 KB)
📄
pprint.pyc.tar
(11.5 KB)
📄
pprint.pyo.pyo.tar.gz
(4.24 KB)
📄
pprint.pyo.tar
(11.5 KB)
📄
pptp.xml.tar
(3 KB)
📄
pptp.xml.xml.tar.gz
(214 B)
📄
pr.tar
(88.5 KB)
📄
pr.tar.gz
(37.89 KB)
📄
pr29.h.h.tar.gz
(1.03 KB)
📄
pr29.h.tar
(4 KB)
📄
pr_2jcdn4o7cdfd8bJ58cf.tar
(16.5 KB)
📄
pr_2jcdn4o7cdfd8bJ58cf.tar.gz
(3.58 KB)
📄
prado.tar
(2.31 MB)
📄
prado.tar.gz
(1.97 MB)
📄
prado.zip
(2.3 MB)
📄
prctl.h.h.tar.gz
(694 B)
📄
prctl.h.tar
(4.5 KB)
📄
pre-commit.tar
(2 KB)
📄
pre-commit.tar.gz
(227 B)
📄
pre-grohtml.tar
(132.5 KB)
📄
pre-grohtml.tar.gz
(50.79 KB)
📄
preauth.tar
(87.5 KB)
📄
preauth.tar.gz
(55.49 KB)
📄
preauth.zip
(85.75 KB)
📄
preauth_plugin.h.h.tar.gz
(1.01 KB)
📄
preauth_plugin.h.tar
(3.5 KB)
📄
precat.tar
(7.5 KB)
📄
precat.tar.gz
(1.93 KB)
📄
precedence-cutoff.xml.tar
(2 KB)
📄
precedence-cutoff.xml.xml.tar.gz
(273 B)
📄
precurio.tar
(123 KB)
📄
precurio.tar.gz
(59.18 KB)
📄
precurio.zip
(103.59 KB)
📄
pref.tar
(242 KB)
📄
pref.tar.gz
(21.4 KB)
📄
pref.zip
(217.93 KB)
📄
prefixdevname.tar
(2.92 MB)
📄
prefixdevname.tar.gz
(560.04 KB)
📄
preloadable_libintl.so.so.tar.gz
(22.55 KB)
📄
preloadable_libintl.so.tar
(58 KB)
📄
preproc.h.h.tar.gz
(541 B)
📄
preproc.h.tar
(2.5 KB)
📄
present.h.h.tar.gz
(2.73 KB)
📄
present.h.tar
(20.5 KB)
📄
presta.tar
(332.5 KB)
📄
presta.tar.gz
(211.63 KB)
📄
presta.zip
(306.66 KB)
📄
presta14.tar
(286.5 KB)
📄
presta14.tar.gz
(178.43 KB)
📄
presta14.zip
(259.19 KB)
📄
presta17.tar
(136.15 MB)
📄
presta17.tar.gz
(122.94 MB)
📄
presta17.zip
(136.11 MB)
📄
presta178.tar
(571.5 KB)
📄
presta178.tar.gz
(288.19 KB)
📄
presta178.zip
(541.52 KB)
📄
presta8.tar
(95.22 MB)
📄
presta8.tar.gz
(85.46 MB)
📄
presta8.zip
(95.19 MB)
📄
prestera.tar
(71.77 MB)
📄
prestera.tar.gz
(71.42 MB)
📄
prestera.zip
(71.76 MB)
📄
preunzip.tar
(7.5 KB)
📄
preunzip.tar.gz
(1.93 KB)
📄
prezip-bin.tar
(13.5 KB)
📄
prezip-bin.tar.gz
(4.89 KB)
📄
prezip.tar
(7.5 KB)
📄
prezip.tar.gz
(1.93 KB)
📄
primes.pyc.pyc.tar.gz
(586 B)
📄
primes.pyc.tar
(2.5 KB)
📄
primes.pyo.pyo.tar.gz
(587 B)
📄
primes.pyo.tar
(2.5 KB)
📄
printbackends.tar
(164.5 KB)
📄
printbackends.tar.gz
(62.26 KB)
📄
printbackends.zip
(161.73 KB)
📄
printenv.tar
(35 KB)
📄
printenv.tar.gz
(14.96 KB)
📄
printer.target.tar
(2 KB)
📄
printer.target.target.tar.gz
(377 B)
📄
printf-ldbl.h.h.tar.gz
(665 B)
📄
printf-ldbl.h.tar
(2.5 KB)
📄
printf.h.h.tar.gz
(2.61 KB)
📄
printf.h.tar
(8.5 KB)
📄
printf.tar
(55.5 KB)
📄
printf.tar.gz
(25.1 KB)
📄
printk.tar
(2 KB)
📄
printk.tar.gz
(112 B)
📄
printk_delay.tar
(2 KB)
📄
printk_delay.tar.gz
(113 B)
📄
printk_devkmsg.tar
(2 KB)
📄
printk_devkmsg.tar.gz
(122 B)
📄
printsupport.tar
(92 KB)
📄
printsupport.tar.gz
(33.95 KB)
📄
printsupport.zip
(90.37 KB)
📄
priority_queue.mod.mod.tar.gz
(1.06 KB)
📄
priority_queue.mod.tar
(4 KB)
📄
private.inc.inc.tar.gz
(2.31 KB)
📄
private.inc.tar
(9 KB)
📄
private.tar
(5.4 MB)
📄
private.tar.gz
(1.18 MB)
📄
private.zip
(5.18 MB)
📄
private_key.php.php.tar.gz
(145 B)
📄
private_key.php.tar
(2 KB)
📄
privatekey.php.php.tar.gz
(559 B)
📄
privatekey.php.tar
(17.5 KB)
📄
privcmd.h.h.tar.gz
(1.83 KB)
📄
privcmd.h.tar
(6 KB)
📄
privoxy.xml.tar
(2 KB)
📄
privoxy.xml.xml.tar.gz
(415 B)
📄
proactor_events.py.py.tar.gz
(6.9 KB)
📄
proactor_events.py.tar
(53.5 KB)
📄
probe.mod.mod.tar.gz
(1.52 KB)
📄
probe.mod.tar
(9 KB)
📄
process.py.py.tar.gz
(2.89 KB)
📄
process.py.tar
(33 KB)
📄
processor-flags.h.h.tar.gz
(1.88 KB)
📄
processor-flags.h.tar
(8 KB)
📄
procfs.h.h.tar.gz
(2.04 KB)
📄
procfs.h.tar
(6.5 KB)
📄
procfs.mod.mod.tar.gz
(1.23 KB)
📄
procfs.mod.tar
(8 KB)
📄
procwire.tar
(14.32 MB)
📄
procwire.tar.gz
(13.53 MB)
📄
procwire.zip
(14.29 MB)
📄
profil.h.h.tar.gz
(1.07 KB)
📄
profil.h.tar
(3.5 KB)
📄
profile.h.h.tar.gz
(3.12 KB)
📄
profile.h.tar
(13.5 KB)
📄
profile.py.py.tar.gz
(7.22 KB)
📄
profile.py.tar
(70 KB)
📄
profile.pyc.pyc.tar.gz
(6.45 KB)
📄
profile.pyc.tar
(18 KB)
📄
profile.pyo.pyo.tar.gz
(6.33 KB)
📄
profile.pyo.tar
(17.5 KB)
📄
profile.rb.rb.tar.gz
(272 B)
📄
profile.rb.tar
(5 KB)
📄
profile.tar
(11 KB)
📄
profile.tar.gz
(1.34 KB)
📄
profile.zip
(3.64 KB)
📄
program.mk.mk.tar.gz
(693 B)
📄
program.mk.tar
(3 KB)
📄
progress.mod.mod.tar.gz
(1.42 KB)
📄
progress.mod.tar
(4.5 KB)
📄
project-id.tar
(4.5 KB)
📄
project-id.tar.gz
(1.2 KB)
📄
projeqtor.sql.sql.tar.gz
(93.06 KB)
📄
projeqtor.sql.tar
(641 KB)
📄
projeqtor.tar
(72.36 MB)
📄
projeqtor.tar.gz
(68.08 MB)
📄
projeqtor.zip
(72.33 MB)
📄
promote_secondaries.tar
(2 KB)
📄
promote_secondaries.tar.gz
(127 B)
📄
prop.h.h.tar.gz
(2.42 KB)
📄
prop.h.tar
(9 KB)
📄
prospector.tar
(2 KB)
📄
prospector.tar.gz
(231 B)
📄
protected.tar
(2 KB)
📄
protected.tar.gz
(329 B)
📄
protected.zip
(483 B)
📄
proto-gre.xml.tar
(2 KB)
📄
proto-gre.xml.xml.tar.gz
(192 B)
📄
proto.h.h.tar.gz
(41.25 KB)
📄
proto.h.tar
(242.5 KB)
📄
protobuf-c.h.h.tar.gz
(8.82 KB)
📄
protobuf-c.h.tar
(34.5 KB)
📄
protobuf-c.tar
(34.5 KB)
📄
protobuf-c.tar.gz
(8.81 KB)
📄
protobuf-c.zip
(32.92 KB)
📄
protocol.rb.rb.tar.gz
(2.91 KB)
📄
protocol.rb.tar
(11 KB)
📄
protocols.py.py.tar.gz
(2.35 KB)
📄
protocols.py.tar
(13.5 KB)
📄
protocols.tar
(26 KB)
📄
protocols.tar.gz
(3.17 KB)
📄
protocols.zip
(15.28 KB)
📄
prototype.tar
(73 KB)
📄
prototype.tar.gz
(46.47 KB)
📄
prototype.zip
(64.55 KB)
📄
prove.tar
(15 KB)
📄
prove.tar.gz
(5.27 KB)
📄
proxy_arp.tar
(2 KB)
📄
proxy_arp.tar.gz
(119 B)
📄
proxy_ndp.tar
(2 KB)
📄
proxy_ndp.tar.gz
(120 B)
📄
proxy_qlen.tar
(7 KB)
📄
proxy_qlen.tar.gz
(120 B)
📄
proxyexec.tar
(23 KB)
📄
proxyexec.tar.gz
(9.5 KB)
📄
proxymech.so.so.tar.gz
(48.24 KB)
📄
proxymech.so.tar
(123.5 KB)
📄
ps.tar
(136.5 KB)
📄
ps.tar.gz
(50.93 KB)
📄
ps2ascii.tar
(2.5 KB)
📄
ps2ascii.tar.gz
(456 B)
📄
ps2epsi.tar
(4.5 KB)
📄
ps2epsi.tar.gz
(1.26 KB)
📄
ps2pdf.tar
(2 KB)
📄
ps2pdf.tar.gz
(280 B)
📄
ps2pdf12.tar
(2 KB)
📄
ps2pdf12.tar.gz
(251 B)
📄
ps2pdf13.tar
(2 KB)
📄
ps2pdf13.tar.gz
(250 B)
📄
ps2pdf14.tar
(2 KB)
📄
ps2pdf14.tar.gz
(250 B)
📄
ps2pdfwr.tar
(3 KB)
📄
ps2pdfwr.tar.gz
(690 B)
📄
ps2ps.tar
(2.5 KB)
📄
ps2ps.tar.gz
(487 B)
📄
ps2ps2.tar
(2.5 KB)
📄
ps2ps2.tar.gz
(526 B)
📄
psi.tar
(261.5 KB)
📄
psi.tar.gz
(37.68 KB)
📄
psi.zip
(250.39 KB)
📄
psi_base.h.h.tar.gz
(1.95 KB)
📄
psi_base.h.tar
(6.5 KB)
📄
psp_13_0_0_sos.bin.bin.tar.gz
(152.57 KB)
📄
psp_13_0_0_sos.bin.tar
(264 KB)
📄
psp_13_0_0_sos_kicker.bin.bin.tar.gz
(153.16 KB)
📄
psp_13_0_0_sos_kicker.bin.tar
(264.5 KB)
📄
psp_13_0_10_sos.bin.bin.tar.gz
(175.24 KB)
📄
psp_13_0_10_sos.bin.tar
(353.5 KB)
📄
psp_13_0_10_ta.bin.bin.tar.gz
(88.38 KB)
📄
psp_13_0_10_ta.bin.tar
(259 KB)
📄
psp_13_0_11_ta.bin.bin.tar.gz
(84.19 KB)
📄
psp_13_0_11_ta.bin.tar
(246.5 KB)
📄
psp_13_0_11_toc.bin.bin.tar.gz
(1.01 KB)
📄
psp_13_0_11_toc.bin.tar
(4 KB)
📄
psp_13_0_12_sos.bin.bin.tar.gz
(427.48 KB)
📄
psp_13_0_12_sos.bin.tar
(430.5 KB)
📄
psp_13_0_12_ta.bin.bin.tar.gz
(69.17 KB)
📄
psp_13_0_12_ta.bin.tar
(71 KB)
📄
psp_13_0_14_sos.bin.bin.tar.gz
(387.93 KB)
📄
psp_13_0_14_sos.bin.tar
(390 KB)
📄
psp_13_0_14_ta.bin.bin.tar.gz
(66.18 KB)
📄
psp_13_0_14_ta.bin.tar
(68 KB)
📄
psp_13_0_4_toc.bin.bin.tar.gz
(1.02 KB)
📄
psp_13_0_4_toc.bin.tar
(4 KB)
📄
psp_13_0_5_asd.bin.bin.tar.gz
(65.76 KB)
📄
psp_13_0_5_asd.bin.tar
(202 KB)
📄
psp_13_0_5_toc.bin.bin.tar.gz
(1.05 KB)
📄
psp_13_0_5_toc.bin.tar
(3.5 KB)
📄
psp_13_0_6_sos.bin.bin.tar.gz
(765.77 KB)
📄
psp_13_0_6_sos.bin.tar
(770.5 KB)
📄
psp_13_0_7_sos.bin.bin.tar.gz
(140.28 KB)
📄
psp_13_0_7_sos.bin.tar
(244.5 KB)
📄
psp_13_0_8_asd.bin.bin.tar.gz
(46.27 KB)
📄
psp_13_0_8_asd.bin.tar
(166 KB)
📄
psp_13_0_8_toc.bin.bin.tar.gz
(1.05 KB)
📄
psp_13_0_8_toc.bin.tar
(3.5 KB)
📄
psp_14_0_0_toc.bin.bin.tar.gz
(1.37 KB)
📄
psp_14_0_0_toc.bin.tar
(4 KB)
📄
psp_14_0_1_toc.bin.bin.tar.gz
(1.37 KB)
📄
psp_14_0_1_toc.bin.tar
(4 KB)
📄
psp_14_0_2_sos.bin.bin.tar.gz
(199.87 KB)
📄
psp_14_0_2_sos.bin.tar
(413 KB)
📄
psp_14_0_3_sos.bin.bin.tar.gz
(205.76 KB)
📄
psp_14_0_3_sos.bin.tar
(427 KB)
📄
psp_14_0_3_sos_kicker.bin.bin.tar.gz
(206.05 KB)
📄
psp_14_0_3_sos_kicker.bin.tar
(427.5 KB)
📄
psp_14_0_4_ta.bin.bin.tar.gz
(84.18 KB)
📄
psp_14_0_4_ta.bin.tar
(492 KB)
📄
psp_14_0_4_toc.bin.bin.tar.gz
(1.37 KB)
📄
psp_14_0_4_toc.bin.tar
(4 KB)
📄
psp_14_0_5_toc.bin.bin.tar.gz
(1.36 KB)
📄
psp_14_0_5_toc.bin.tar
(4 KB)
📄
psql.tar
(646 KB)
📄
psql.tar.gz
(231.03 KB)
📄
pstats.py.py.tar.gz
(7.03 KB)
📄
pstats.py.tar
(82 KB)
📄
pstats.pyc.pyc.tar.gz
(9.44 KB)
📄
pstats.pyc.tar
(26 KB)
📄
pstats.pyo.pyo.tar.gz
(9.44 KB)
📄
pstats.pyo.tar
(26 KB)
📄
psych-3.0.2.tar
(34 KB)
📄
psych-3.0.2.tar.gz
(12.61 KB)
📄
psych-3.0.2.zip
(32.49 KB)
📄
psych.so.so.tar.gz
(12.62 KB)
📄
psych.so.tar
(100 KB)
📄
psych.tar
(98 KB)
📄
psych.tar.gz
(17.32 KB)
📄
psych.zip
(74.55 KB)
📄
psych_jars.rb.rb.tar.gz
(253 B)
📄
psych_jars.rb.tar
(2 KB)
📄
psyntax-pp.go.go.tar.gz
(67.85 KB)
📄
psyntax-pp.go.tar
(193 KB)
📄
pt.tar
(85.5 KB)
📄
pt.tar.gz
(73.69 KB)
📄
pt.zip
(75.36 KB)
📄
pt_BR.tar
(12 KB)
📄
pt_BR.tar.gz
(7.48 KB)
📄
ptags.pyc.pyc.tar.gz
(865 B)
📄
ptags.pyc.tar
(3 KB)
📄
ptags.pyo.pyo.tar.gz
(865 B)
📄
ptags.pyo.tar
(3 KB)
📄
pthread.h.h.tar.gz
(8.31 KB)
📄
pthread.h.tar
(42 KB)
📄
pthreadtypes-arch.h.h.tar.gz
(1.21 KB)
📄
pthreadtypes-arch.h.tar
(5 KB)
📄
pthreadtypes.h.h.tar.gz
(1.17 KB)
📄
pthreadtypes.h.tar
(4.5 KB)
📄
ptl_guc_70.bin.bin.tar.gz
(203.88 KB)
📄
ptl_guc_70.bin.tar
(708 KB)
📄
ptl_huc.bin.bin.tar.gz
(225.28 KB)
📄
ptl_huc.bin.tar
(1.24 MB)
📄
ptp.xml.tar
(3 KB)
📄
ptp.xml.xml.tar.gz
(348 B)
📄
ptrace-abi.h.h.tar.gz
(1000 B)
📄
ptrace-abi.h.tar
(3.5 KB)
📄
ptrace.h.h.tar.gz
(1.92 KB)
📄
ptrace.h.tar
(9.5 KB)
📄
ptrace_scope.tar
(2 KB)
📄
ptrace_scope.tar.gz
(117 B)
📄
ptx.tar
(79.5 KB)
📄
ptx.tar.gz
(36.26 KB)
📄
pty.h.h.tar.gz
(884 B)
📄
pty.h.tar
(3.5 KB)
📄
pty.py.py.tar.gz
(1.67 KB)
📄
pty.py.tar
(17.5 KB)
📄
pty.pyc.pyc.tar.gz
(2.38 KB)
📄
pty.pyc.tar
(6.5 KB)
📄
pty.pyo.pyo.tar.gz
(2.38 KB)
📄
pty.pyo.tar
(6.5 KB)
📄
pty.so.so.tar.gz
(6.8 KB)
📄
pty.so.tar
(21.5 KB)
📄
pty.tar
(4 KB)
📄
pty.tar.gz
(141 B)
📄
pty.zip
(394 B)
📄
pub_.htaccess.htaccess.tar.gz
(237 B)
📄
pub_.htaccess.tar
(2 KB)
📄
pub_htaccess.tar
(2 KB)
📄
pub_htaccess.tar.gz
(257 B)
📄
public.xml.tar
(3 KB)
📄
public.xml.xml.tar.gz
(314 B)
📄
public_html.tar
(9.89 GB)
📄
public_html.tar.gz
(387.07 MB)
📄
public_html.zip
(9.64 GB)
📄
pulseaudio.tar
(597.5 KB)
📄
pulseaudio.tar.gz
(238.43 KB)
📄
pulseaudio.xml.tar
(2 KB)
📄
pulseaudio.xml.xml.tar.gz
(350 B)
📄
pulseaudio.zip
(595.26 KB)
📄
punbb.tar
(202.5 KB)
📄
punbb.tar.gz
(114.15 KB)
📄
punbb.zip
(177.34 KB)
📄
puppet-agent.conf.conf.tar.gz
(141 B)
📄
puppet-agent.conf.tar
(3 KB)
📄
puppet.service.service.tar.gz
(589 B)
📄
puppet.service.tar
(2.5 KB)
📄
puppetmaster.xml.tar
(2 KB)
📄
puppetmaster.xml.xml.tar.gz
(304 B)
📄
purge-nobody-user.tar
(7 KB)
📄
purge-nobody-user.tar.gz
(1.03 KB)
📄
purifier.tar
(490 KB)
📄
purifier.tar.gz
(394.89 KB)
📄
purifier.zip
(477.14 KB)
📄
putil.h.h.tar.gz
(2.15 KB)
📄
putil.h.tar
(8 KB)
📄
pvpanic.h.h.tar.gz
(248 B)
📄
pvpanic.h.tar
(2 KB)
📄
pwcat.tar
(9.5 KB)
📄
pwcat.tar.gz
(3.24 KB)
📄
pwd.h.h.tar.gz
(1.84 KB)
📄
pwd.h.tar
(8 KB)
📄
pwd.tar
(39 KB)
📄
pwd.tar.gz
(16.72 KB)
📄
pwdx.tar
(14.5 KB)
📄
pwdx.tar.gz
(5.37 KB)
📄
pwhistory_helper.tar
(22 KB)
📄
pwhistory_helper.tar.gz
(7.34 KB)
📄
px-m402u.fw.fw.tar.gz
(3.92 KB)
📄
px-m402u.fw.tar
(14 KB)
📄
px-tv402u.fw.fw.tar.gz
(4.44 KB)
📄
px-tv402u.fw.tar
(8 KB)
📄
pxe.mod.mod.tar.gz
(1.99 KB)
📄
pxe.mod.tar
(12 KB)
📄
pxeboot.img.img.tar.gz
(121 B)
📄
pxeboot.img.tar
(2.5 KB)
📄
pxechain.mod.mod.tar.gz
(1.5 KB)
📄
pxechain.mod.tar
(5 KB)
📄
pxp-agent.service.service.tar.gz
(551 B)
📄
pxp-agent.service.tar
(2.5 KB)
📄
py.test.tar
(2 KB)
📄
py.test.test.tar.gz
(233 B)
📄
py_compile.pyc.pyc.tar.gz
(2.92 KB)
📄
py_compile.pyc.tar
(8 KB)
📄
py_compile.pyo.pyo.tar.gz
(2.92 KB)
📄
py_compile.pyo.tar
(8 KB)
📄
py_curses.h.h.tar.gz
(1.11 KB)
📄
py_curses.h.tar
(4 KB)
📄
pyarena.h.h.tar.gz
(1.27 KB)
📄
pyarena.h.tar
(4.5 KB)
📄
pyassem.pyc.pyc.tar.gz
(9.39 KB)
📄
pyassem.pyc.tar
(27 KB)
📄
pyassem.pyo.pyo.tar.gz
(9.15 KB)
📄
pyassem.pyo.tar
(26.5 KB)
📄
pycapsule.h.h.tar.gz
(746 B)
📄
pycapsule.h.tar
(3.5 KB)
📄
pyclbr.py.py.tar.gz
(3.75 KB)
📄
pyclbr.py.tar
(44.5 KB)
📄
pyclbr.pyc.pyc.tar.gz
(4.28 KB)
📄
pyclbr.pyc.tar
(11 KB)
📄
pyclbr.pyo.pyo.tar.gz
(4.28 KB)
📄
pyclbr.pyo.tar
(11 KB)
📄
pycodestyle.tar
(2 KB)
📄
pycodestyle.tar.gz
(229 B)
📄
pyctype.h.h.tar.gz
(587 B)
📄
pyctype.h.tar
(3 KB)
📄
pydebug.h.h.tar.gz
(620 B)
📄
pydebug.h.tar
(3 KB)
📄
pydio.tar
(155 KB)
📄
pydio.tar.gz
(85.71 KB)
📄
pydio.zip
(133.15 KB)
📄
pydoc.py.py.tar.gz
(26.11 KB)
📄
pydoc.py.tar
(302 KB)
📄
pydoc.pyc.pyc.tar.gz
(34.7 KB)
📄
pydoc.pyc.tar
(92 KB)
📄
pydoc.pyo.pyo.tar.gz
(34.67 KB)
📄
pydoc.pyo.tar
(92 KB)
📄
pydoc.tar
(2 KB)
📄
pydoc.tar.gz
(167 B)
📄
pydoc3.4.4.tar.gz
(169 B)
📄
pydoc3.4.tar
(2 KB)
📄
pydoc3.5.5.tar.gz
(169 B)
📄
pydoc3.5.tar
(2 KB)
📄
pydoc3.6.6.tar.gz
(169 B)
📄
pydoc3.6.tar
(2 KB)
📄
pydoc3.7.7.tar.gz
(169 B)
📄
pydoc3.7.tar
(2 KB)
📄
pydoc3.8.8.tar.gz
(170 B)
📄
pydoc3.8.tar
(2 KB)
📄
pydoc3.9.9.tar.gz
(168 B)
📄
pydoc3.9.tar
(2 KB)
📄
pydoc3.tar
(9 KB)
📄
pydoc3.tar.gz
(168 B)
📄
pydoc_data.tar
(3.83 MB)
📄
pydoc_data.tar.gz
(477.41 KB)
📄
pydoc_data.zip
(3.81 MB)
📄
pydocstyle.tar
(2 KB)
📄
pydocstyle.tar.gz
(231 B)
📄
pyexpat.h.h.tar.gz
(901 B)
📄
pyexpat.h.tar
(4 KB)
📄
pygettext3.8.py.8.py.tar.gz
(7.06 KB)
📄
pygettext3.8.py.tar
(23 KB)
📄
pygettext3.9.py.9.py.tar.gz
(7.06 KB)
📄
pygettext3.9.py.tar
(23 KB)
📄
pygettext3.py.py.tar.gz
(7.06 KB)
📄
pygettext3.py.tar
(45 KB)
📄
pygram.cpython-38.pyc.cpython-38.pyc.tar.gz
(899 B)
📄
pygram.cpython-38.pyc.tar
(3 KB)
📄
pygram.py.py.tar.gz
(620 B)
📄
pygram.py.tar
(5 KB)
📄
pyhash.h.h.tar.gz
(1.65 KB)
📄
pyhash.h.tar
(6 KB)
📄
pylint.tar
(2 KB)
📄
pylint.tar.gz
(227 B)
📄
pymacro.h.h.tar.gz
(1.65 KB)
📄
pymacro.h.tar
(5.5 KB)
📄
pymath.h.h.tar.gz
(3.1 KB)
📄
pymath.h.tar
(10 KB)
📄
pyport.h.h.tar.gz
(9.5 KB)
📄
pyport.h.tar
(31.5 KB)
📄
pyproject-build.tar
(2 KB)
📄
pyproject-build.tar.gz
(235 B)
📄
pyreverse.tar
(2 KB)
📄
pyreverse.tar.gz
(235 B)
📄
pyro.png.png.tar.gz
(8.63 KB)
📄
pyro.png.tar
(10.5 KB)
📄
pyro.tar
(897.5 KB)
📄
pyro.tar.gz
(197.39 KB)
📄
pyro.zip
(879.2 KB)
📄
pysource.pyc.pyc.tar.gz
(1.93 KB)
📄
pysource.pyc.tar
(5.5 KB)
📄
pystate.h.h.tar.gz
(1.71 KB)
📄
pystate.h.tar
(6.5 KB)
📄
pysvr.c.c.tar.gz
(2.75 KB)
📄
pysvr.c.tar
(10 KB)
📄
pysvr.pyc.pyc.tar.gz
(2.05 KB)
📄
pysvr.pyc.tar
(5.5 KB)
📄
pysvr.pyo.pyo.tar.gz
(2.05 KB)
📄
pysvr.pyo.tar
(5.5 KB)
📄
pysvr.tar
(26 KB)
📄
pysvr.tar.gz
(6.33 KB)
📄
pysvr.zip
(21.56 KB)
📄
pytest.tar
(2 KB)
📄
pytest.tar.gz
(229 B)
📄
python-3.6m.pc.6m.pc.tar.gz
(278 B)
📄
python-3.6m.pc.tar
(2 KB)
📄
python-config.tar
(3.5 KB)
📄
python-config.tar.gz
(826 B)
📄
python-internal.tar
(58.5 MB)
📄
python-internal.tar.gz
(20.87 MB)
📄
python-internal.zip
(57.13 MB)
📄
python-macro-helper.tar
(4 KB)
📄
python-macro-helper.tar.gz
(353 B)
📄
python.attr.attr.tar.gz
(337 B)
📄
python.attr.tar
(2 KB)
📄
python.o.o.tar.gz
(11.32 KB)
📄
python.o.tar
(38.5 KB)
📄
python.pc.pc.tar.gz
(263 B)
📄
python.pc.tar
(2 KB)
📄
python.tar
(42.5 KB)
📄
python.tar.gz
(3.24 KB)
📄
python2.7.7.tar.gz
(5.14 MB)
📄
python2.7.tar
(22.14 MB)
📄
python2.7.tar.gz
(5.14 MB)
📄
python2.7.zip
(21.21 MB)
📄
python2.pc.pc.tar.gz
(264 B)
📄
python2.pc.tar
(2 KB)
📄
python2.tar
(18 KB)
📄
python2.tar.gz
(3.27 KB)
📄
python3.10.tar
(77.37 MB)
📄
python3.10.tar.gz
(38.93 MB)
📄
python3.10.zip
(75.96 MB)
📄
python3.11.11.tar.gz
(3.23 KB)
📄
python3.11.tar
(17.5 KB)
📄
python3.12.12.tar.gz
(3.24 KB)
📄
python3.12.tar
(57.28 MB)
📄
python3.12.tar.gz
(4.65 KB)
📄
python3.12.zip
(55.91 MB)
📄
python3.3.3.tar.gz
(2 MB)
📄
python3.3.tar
(6.78 MB)
📄
python3.3.tar.gz
(2 MB)
📄
python3.3.zip
(6.52 MB)
📄
python3.3m-x86_64-config.3m-x86_64-config.tar.gz
(842 B)
📄
python3.3m-x86_64-config.tar
(3.5 KB)
📄
python3.3m.3m.tar.gz
(3.99 KB)
📄
python3.3m.tar
(13.5 KB)
📄
python3.4.4.tar.gz
(1.98 MB)
📄
python3.4.tar
(6.09 MB)
📄
python3.4.tar.gz
(1.98 MB)
📄
python3.4.zip
(5.84 MB)
📄
python3.4m-x86_64-config.4m-x86_64-config.tar.gz
(1.33 KB)
📄
python3.4m-x86_64-config.tar
(5.5 KB)
📄
python3.4m.4m.tar.gz
(3.97 KB)
📄
python3.4m.tar
(13.5 KB)
📄
python3.5.5.tar.gz
(2.94 MB)
📄
python3.5.tar
(10.12 MB)
📄
python3.5.tar.gz
(2.93 MB)
📄
python3.5.zip
(9.65 MB)
📄
python3.5m-x86_64-config.5m-x86_64-config.tar.gz
(1.35 KB)
📄
python3.5m-x86_64-config.tar
(5.5 KB)
📄
python3.5m.5m.tar.gz
(3.96 KB)
📄
python3.5m.tar
(13.5 KB)
📄
python3.6.6.tar.gz
(4.03 KB)
📄
python3.6.tar
(86.78 MB)
📄
python3.6.tar.gz
(8.4 MB)
📄
python3.6.zip
(83.17 MB)
📄
python3.6m-x86_64-config.6m-x86_64-config.tar.gz
(1.42 KB)
📄
python3.6m-x86_64-config.tar
(5.5 KB)
📄
python3.6m.6m.tar.gz
(4.02 KB)
📄
python3.6m.tar
(684.5 KB)
📄
python3.6m.tar.gz
(156.55 KB)
📄
python3.6m.zip
(597.93 KB)
📄
python3.7.7.tar.gz
(3.27 KB)
📄
python3.7.tar
(61.9 MB)
📄
python3.7.tar.gz
(25.11 MB)
📄
python3.7.zip
(59.95 MB)
📄
python3.7m-x86_64-config.7m-x86_64-config.tar.gz
(1.37 KB)
📄
python3.7m-x86_64-config.tar
(5.5 KB)
📄
python3.7m.7m.tar.gz
(3.27 KB)
📄
python3.7m.tar
(9.5 KB)
📄
python3.8.8.tar.gz
(15.58 MB)
📄
python3.8.tar
(51.79 MB)
📄
python3.8.tar.gz
(3.8 MB)
📄
python3.8.zip
(49.6 MB)
📄
python3.9.9.tar.gz
(3.24 KB)
📄
python3.9.tar
(12.23 MB)
📄
python3.9.tar.gz
(3.37 MB)
📄
python3.9.zip
(11.64 MB)
📄
python3.pc.pc.tar.gz
(276 B)
📄
python3.pc.tar
(2 KB)
📄
python3.tar
(130 KB)
📄
python3.tar.gz
(4.02 KB)
📄
python310.tar
(97.28 MB)
📄
python310.tar.gz
(46.36 MB)
📄
python310.zip
(95.28 MB)
📄
python311.tar
(138.09 MB)
📄
python311.tar.gz
(63.89 MB)
📄
python311.zip
(135.96 MB)
📄
python312.tar
(87.67 MB)
📄
python312.tar.gz
(29.06 MB)
📄
python312.zip
(85.53 MB)
📄
python313.tar
(85.19 MB)
📄
python313.tar.gz
(28.9 MB)
📄
python313.zip
(83.12 MB)
📄
python33.tar
(42.44 MB)
📄
python33.tar.gz
(12.17 MB)
📄
python33.zip
(41.07 MB)
📄
python34.tar
(41.09 MB)
📄
python34.tar.gz
(12.96 MB)
📄
python34.zip
(39.61 MB)
📄
python35.tar
(53.52 MB)
📄
python35.tar.gz
(16.74 MB)
📄
python35.zip
(51.48 MB)
📄
python36.tar
(53.75 MB)
📄
python36.tar.gz
(17.05 MB)
📄
python36.zip
(51.65 MB)
📄
python37.tar
(119.97 MB)
📄
python37.tar.gz
(44.98 MB)
📄
python37.zip
(116.12 MB)
📄
python39.tar
(55.81 MB)
📄
python39.tar.gz
(18.71 MB)
📄
python39.zip
(53.83 MB)
📄
pythondeps.sh.sh.tar.gz
(495 B)
📄
pythondeps.sh.tar
(4 KB)
📄
pythondistdeps.py.py.tar.gz
(2.89 KB)
📄
pythondistdeps.py.tar
(12.5 KB)
📄
pythonrun.h.h.tar.gz
(1.69 KB)
📄
pythonrun.h.tar
(9 KB)
📄
pytime.h.h.tar.gz
(2.29 KB)
📄
pytime.h.tar
(10.5 KB)
📄
pytree.py.py.tar.gz
(6.41 KB)
📄
pytree.py.tar
(57 KB)
📄
pyvenv-3.3.3.tar.gz
(249 B)
📄
pyvenv-3.3.tar
(2 KB)
📄
pyvenv-3.4.4.tar.gz
(250 B)
📄
pyvenv-3.4.tar
(2 KB)
📄
pyvenv-3.5.5.tar.gz
(251 B)
📄
pyvenv-3.5.tar
(2 KB)
📄
pyvenv-3.6.6.tar.gz
(353 B)
📄
pyvenv-3.6.tar
(2 KB)
📄
pyvenv-3.7.7.tar.gz
(354 B)
📄
pyvenv-3.7.tar
(2 KB)
📄
pyvenv.cfg.cfg.tar.gz
(222 B)
📄
pyvenv.cfg.tar
(4 KB)
📄
pyvenv.tar
(6 KB)
📄
pyvenv.tar.gz
(350 B)
📄
q.go.go.tar.gz
(1.5 KB)
📄
q.go.tar
(5 KB)
📄
q6_fw.b05.b05.tar.gz
(5.02 KB)
📄
q6_fw.b05.tar
(19 KB)
📄
q6_fw.flist.flist.tar.gz
(190 B)
📄
q6_fw.flist.tar
(4.5 KB)
📄
qa-config.php.php.tar.gz
(3.76 KB)
📄
qa-config.php.tar
(10.5 KB)
📄
qat.tar
(3.66 MB)
📄
qat.tar.gz
(1.1 MB)
📄
qat.zip
(3.65 MB)
📄
qat_402xx.bin.bin.tar.gz
(133.7 KB)
📄
qat_402xx.bin.tar
(1.91 MB)
📄
qat_402xx_mmp.bin.bin.tar.gz
(72.91 KB)
📄
qat_402xx_mmp.bin.tar
(296 KB)
📄
qat_420xx.bin.bin.tar.gz
(131.28 KB)
📄
qat_420xx.bin.tar
(1.91 MB)
📄
qat_420xx_mmp.bin.bin.tar.gz
(72.91 KB)
📄
qat_420xx_mmp.bin.tar
(296 KB)
📄
qat_4xxx.bin.bin.tar.gz
(155.99 KB)
📄
qat_4xxx.bin.tar
(1.27 MB)
📄
qat_4xxx_mmp.bin.bin.tar.gz
(72.92 KB)
📄
qat_4xxx_mmp.bin.tar
(296 KB)
📄
qat_895xcc.bin.bin.tar.gz
(100.24 KB)
📄
qat_895xcc.bin.tar
(699 KB)
📄
qat_895xcc_mmp.bin.bin.tar.gz
(52.31 KB)
📄
qat_895xcc_mmp.bin.tar
(236 KB)
📄
qat_c3xxx.bin.bin.tar.gz
(92.08 KB)
📄
qat_c3xxx.bin.tar
(781 KB)
📄
qat_c3xxx_mmp.bin.bin.tar.gz
(52.91 KB)
📄
qat_c3xxx_mmp.bin.tar
(238 KB)
📄
qat_c62x.bin.bin.tar.gz
(139.54 KB)
📄
qat_c62x.bin.tar
(780 KB)
📄
qat_c62x_mmp.bin.bin.tar.gz
(52.91 KB)
📄
qat_c62x_mmp.bin.tar
(238 KB)
📄
qat_mmp.bin.bin.tar.gz
(52.3 KB)
📄
qat_mmp.bin.tar
(353.5 KB)
📄
qca.tar
(4.04 MB)
📄
qca.tar.gz
(2.49 MB)
📄
qca.zip
(3.96 MB)
📄
qcart.tar
(151.5 KB)
📄
qcart.tar.gz
(76.37 KB)
📄
qcart.zip
(129.35 KB)
📄
qcms.png.png.tar.gz
(13.48 KB)
📄
qcms.png.tar
(15 KB)
📄
qcms.tar
(1.02 MB)
📄
qcms.tar.gz
(952.89 KB)
📄
qcms.zip
(1018.38 KB)
📄
qcow2.h.h.tar.gz
(1.19 KB)
📄
qcow2.h.tar
(4.5 KB)
📄
qcs615.tar
(10.82 MB)
📄
qcs615.tar.gz
(4.57 MB)
📄
qcs615.zip
(10.81 MB)
📄
qcs8300.tar
(16.29 MB)
📄
qcs8300.tar.gz
(7.42 MB)
📄
qcs8300.zip
(16.28 MB)
📄
qdpm.png.png.tar.gz
(7.05 KB)
📄
qdpm.png.tar
(9 KB)
📄
qdpm.tar
(211 KB)
📄
qdpm.tar.gz
(106.34 KB)
📄
qdpm.zip
(179.46 KB)
📄
qdu100.tar
(15.56 MB)
📄
qdu100.tar.gz
(10.42 MB)
📄
qdu100.zip
(15.55 MB)
📄
qed.tar
(20.41 MB)
📄
qed.tar.gz
(11.02 MB)
📄
qed.zip
(20.4 MB)
📄
qed_init_values-8.10.9.0.bin.10.9.0.bin.tar.gz
(532.5 KB)
📄
qed_init_values-8.10.9.0.bin.tar
(1.37 MB)
📄
qed_init_values-8.14.6.0.bin.14.6.0.bin.tar.gz
(541.13 KB)
📄
qed_init_values-8.14.6.0.bin.tar
(1.39 MB)
📄
qed_init_values-8.18.9.0.bin.18.9.0.bin.tar.gz
(567.2 KB)
📄
qed_init_values-8.18.9.0.bin.tar
(1.47 MB)
📄
qed_init_values-8.37.7.0.bin.37.7.0.bin.tar.gz
(584.57 KB)
📄
qed_init_values-8.37.7.0.bin.tar
(1.49 MB)
📄
qedr-abi.h.h.tar.gz
(1.76 KB)
📄
qedr-abi.h.tar
(6 KB)
📄
ql2100_fw.bin.bin.tar.gz
(40.2 KB)
📄
ql2100_fw.bin.tar
(153 KB)
📄
ql2200_fw.bin.bin.tar.gz
(43.35 KB)
📄
ql2200_fw.bin.tar
(168 KB)
📄
ql2300_fw.bin.bin.tar.gz
(66.08 KB)
📄
ql2300_fw.bin.tar
(247 KB)
📄
ql2322_fw.bin.bin.tar.gz
(70.79 KB)
📄
ql2322_fw.bin.tar
(268 KB)
📄
ql2400_fw.bin.bin.tar.gz
(106.1 KB)
📄
ql2400_fw.bin.tar
(521 KB)
📄
ql2500_fw.bin.bin.tar.gz
(136.49 KB)
📄
ql2500_fw.bin.tar
(541 KB)
📄
qloapps.sql.sql.tar.gz
(71.2 KB)
📄
qloapps.sql.tar
(420.5 KB)
📄
qloapps.tar
(54.63 MB)
📄
qloapps.tar.gz
(51.64 MB)
📄
qloapps.zip
(54.6 MB)
📄
qlogic.tar
(122 KB)
📄
qlogic.tar.gz
(67.16 KB)
📄
qlogic.zip
(117.88 KB)
📄
qml.tar
(2.13 MB)
📄
qml.tar.gz
(610.09 KB)
📄
qml.zip
(2.1 MB)
📄
qmldir.tar
(8 KB)
📄
qmldir.tar.gz
(219 B)
📄
qmlmodels.tar
(191.5 KB)
📄
qmlmodels.tar.gz
(63.08 KB)
📄
qmlmodels.zip
(188.6 KB)
📄
qmltooling.tar
(761.5 KB)
📄
qmltooling.tar.gz
(283.45 KB)
📄
qmltooling.zip
(754.03 KB)
📄
qt5.tar
(7.58 MB)
📄
qt5.tar.gz
(2.67 MB)
📄
qt5.zip
(7.51 MB)
📄
qtestroot.tar
(3.5 KB)
📄
qtestroot.tar.gz
(521 B)
📄
qtestroot.zip
(1.09 KB)
📄
qtoa.png.png.tar.gz
(20.66 KB)
📄
qtoa.png.tar
(22 KB)
📄
qtoa.tar
(187.5 KB)
📄
qtoa.tar.gz
(103.01 KB)
📄
qtoa.zip
(164.2 KB)
📄
quassel.xml.tar
(2 KB)
📄
quassel.xml.xml.tar.gz
(290 B)
📄
queens.pyc.pyc.tar.gz
(1.29 KB)
📄
queens.pyc.tar
(4.5 KB)
📄
queens.pyo.pyo.tar.gz
(1.29 KB)
📄
queens.pyo.tar
(4.5 KB)
📄
queue.h.h.tar.gz
(3.69 KB)
📄
queue.h.tar
(21 KB)
📄
queue.py.py.tar.gz
(2.82 KB)
📄
queue.py.tar
(22.5 KB)
📄
queues.py.py.tar.gz
(2.48 KB)
📄
queues.py.tar
(18.5 KB)
📄
queues.pyc.pyc.tar.gz
(4.13 KB)
📄
queues.pyc.tar
(13 KB)
📄
queues.pyo.pyo.tar.gz
(4.09 KB)
📄
queues.pyo.tar
(13 KB)
📄
quopri.py.py.tar.gz
(2.42 KB)
📄
quopri.py.tar
(24.5 KB)
📄
quopri.pyc.pyc.tar.gz
(3.08 KB)
📄
quopri.pyc.tar
(8 KB)
📄
quopri.pyo.pyo.tar.gz
(3.08 KB)
📄
quopri.pyo.tar
(8 KB)
📄
quoprimime.pyc.pyc.tar.gz
(3.79 KB)
📄
quoprimime.pyc.tar
(10.5 KB)
📄
quoprimime.pyo.pyo.tar.gz
(3.79 KB)
📄
quoprimime.pyo.tar
(10.5 KB)
📄
quota.h.h.tar.gz
(2.29 KB)
📄
quota.h.tar
(7 KB)
📄
quota.tar
(10 KB)
📄
quota.tar.gz
(318 B)
📄
quota.zip
(1.22 KB)
📄
quotaon.service.service.tar.gz
(499 B)
📄
quotaon.service.tar
(2.5 KB)
📄
qxl_drm.h.h.tar.gz
(1.73 KB)
📄
qxl_drm.h.tar
(6 KB)
📄
r.tar
(11.96 MB)
📄
r.tar.gz
(7.33 MB)
📄
r.zip
(11.81 MB)
📄
r128.tar
(3.5 KB)
📄
r128.tar.gz
(748 B)
📄
r128.zip
(2.15 KB)
📄
r128_cce.bin.bin.tar.gz
(764 B)
📄
r128_cce.bin.tar
(6 KB)
📄
r4rs.go.go.tar.gz
(3.15 KB)
📄
r4rs.go.tar
(13 KB)
📄
r5rs.go.go.tar.gz
(872 B)
📄
r5rs.go.tar
(3 KB)
📄
r8a779x_usb3_v1.dlmem.dlmem.tar.gz
(6.41 KB)
📄
r8a779x_usb3_v1.dlmem.tar
(11 KB)
📄
r8a779x_usb3_v2.dlmem.dlmem.tar.gz
(6.41 KB)
📄
r8a779x_usb3_v2.dlmem.tar
(11 KB)
📄
r8a779x_usb3_v3.dlmem.dlmem.tar.gz
(6.41 KB)
📄
r8a779x_usb3_v3.dlmem.tar
(11 KB)
📄
racc.tar
(41.5 KB)
📄
racc.tar.gz
(8.93 KB)
📄
racc.zip
(37.75 KB)
📄
rackup.tar
(20.5 KB)
📄
rackup.tar.gz
(414 B)
📄
radeon.tar
(6.94 MB)
📄
radeon.tar.gz
(3.45 MB)
📄
radeon.zip
(6.81 MB)
📄
radeon_drm.h.h.tar.gz
(10.21 KB)
📄
radeon_drm.h.tar
(39 KB)
📄
radius.xml.tar
(2.5 KB)
📄
radius.xml.xml.tar.gz
(376 B)
📄
radon.tar
(218.72 MB)
📄
radon.tar.gz
(74.27 MB)
📄
radon.zip
(213.36 MB)
📄
radontect.com.tar
(167 KB)
📄
radontect.com.tar.gz
(32.69 KB)
📄
radontect.com.zip
(107.95 KB)
📄
raid5rec.mod.mod.tar.gz
(877 B)
📄
raid5rec.mod.tar
(3.5 KB)
📄
raid6rec.mod.mod.tar.gz
(1.42 KB)
📄
raid6rec.mod.tar
(4.5 KB)
📄
rain.pyc.pyc.tar.gz
(1.06 KB)
📄
rain.pyc.tar
(4 KB)
📄
rain.pyo.pyo.tar.gz
(1.06 KB)
📄
rain.pyo.tar
(4 KB)
📄
rainloop.tar
(216 KB)
📄
rainloop.tar.gz
(111.95 KB)
📄
rainloop.zip
(184.76 KB)
📄
rake.rb.rb.tar.gz
(1.1 KB)
📄
rake.rb.tar
(7 KB)
📄
rake.tar
(198 KB)
📄
rake.tar.gz
(412 B)
📄
rake.zip
(139.19 KB)
📄
rampatch_00130300.bin.bin.tar.gz
(45.72 KB)
📄
rampatch_00130300.bin.tar
(66 KB)
📄
rampatch_00130302.bin.bin.tar.gz
(22.82 KB)
📄
rampatch_00130302.bin.tar
(33 KB)
📄
rampatch_00230302.bin.bin.tar.gz
(23.45 KB)
📄
rampatch_00230302.bin.tar
(34 KB)
📄
rampatch_00440302.bin.bin.tar.gz
(48.31 KB)
📄
rampatch_00440302.bin.tar
(68 KB)
📄
rampatch_usb_00000200.bin.bin.tar.gz
(37.84 KB)
📄
rampatch_usb_00000200.bin.tar
(55 KB)
📄
rampatch_usb_00000201.bin.bin.tar.gz
(37.84 KB)
📄
rampatch_usb_00000201.bin.tar
(55 KB)
📄
rampatch_usb_00000300.bin.bin.tar.gz
(45.53 KB)
📄
rampatch_usb_00000300.bin.tar
(66 KB)
📄
rampatch_usb_00000302.bin.bin.tar.gz
(48.63 KB)
📄
rampatch_usb_00000302.bin.tar
(69 KB)
📄
rampatch_usb_00130200.bin.bin.tar.gz
(139.85 KB)
📄
rampatch_usb_00130200.bin.tar
(194.5 KB)
📄
rampatch_usb_00130201.bin.bin.tar.gz
(117.27 KB)
📄
rampatch_usb_00130201.bin.tar
(160.5 KB)
📄
rampatch_usb_00190200.bin.bin.tar.gz
(177.73 KB)
📄
rampatch_usb_00190200.bin.tar
(246 KB)
📄
ramps_0x01020001_26.dfu.dfu.tar.gz
(1.05 KB)
📄
ramps_0x01020001_26.dfu.tar
(3 KB)
📄
ramps_0x01020200_26.dfu.dfu.tar.gz
(1.06 KB)
📄
ramps_0x01020200_26.dfu.tar
(3 KB)
📄
ramps_0x01020201_26.dfu.dfu.tar.gz
(329 B)
📄
ramps_0x01020201_26.dfu.tar
(2 KB)
📄
ramps_0x01020201_40.dfu.dfu.tar.gz
(329 B)
📄
ramps_0x01020201_40.dfu.tar
(2 KB)
📄
rand.h.h.tar.gz
(1.06 KB)
📄
rand.h.tar
(4 KB)
📄
rand_drbg.h.h.tar.gz
(1.46 KB)
📄
rand_drbg.h.tar
(6.5 KB)
📄
random.h.h.tar.gz
(829 B)
📄
random.h.tar
(3 KB)
📄
random.mod.mod.tar.gz
(2.36 KB)
📄
random.mod.tar
(12 KB)
📄
random.py.py.tar.gz
(8.64 KB)
📄
random.py.tar
(90 KB)
📄
random.pyc.pyc.tar.gz
(10.19 KB)
📄
random.pyc.tar
(27 KB)
📄
random.pyo.pyo.tar.gz
(10.19 KB)
📄
random.pyo.tar
(27 KB)
📄
random.tar
(8 KB)
📄
random.tar.gz
(315 B)
📄
random.zip
(1.07 KB)
📄
random_compat.tar
(48.5 KB)
📄
random_compat.tar.gz
(7.58 KB)
📄
randomize_va_space.tar
(2 KB)
📄
randomize_va_space.tar.gz
(119 B)
📄
randr.h.h.tar.gz
(11.02 KB)
📄
randr.h.tar
(138 KB)
📄
ranlib.tar
(63.5 KB)
📄
ranlib.tar.gz
(28.99 KB)
📄
raphael.tar
(76.5 KB)
📄
raphael.tar.gz
(55.77 KB)
📄
raphael.zip
(66.25 KB)
📄
raven.tar
(3.5 KB)
📄
raven.tar.gz
(565 B)
📄
raven2_asd.bin.bin.tar.gz
(60.22 KB)
📄
raven2_asd.bin.tar
(190 KB)
📄
raven2_ce.bin.bin.tar.gz
(3.5 KB)
📄
raven2_ce.bin.tar
(11 KB)
📄
raven2_gpu_info.bin.bin.tar.gz
(174 B)
📄
raven2_gpu_info.bin.tar
(2 KB)
📄
raven2_me.bin.bin.tar.gz
(6.8 KB)
📄
raven2_me.bin.tar
(19 KB)
📄
raven2_mec.bin.bin.tar.gz
(32.48 KB)
📄
raven2_mec.bin.tar
(263.5 KB)
📄
raven2_mec2.bin.bin.tar.gz
(32.49 KB)
📄
raven2_mec2.bin.tar
(263.5 KB)
📄
raven2_pfp.bin.bin.tar.gz
(10.11 KB)
📄
raven2_pfp.bin.tar
(23 KB)
📄
raven2_rlc.bin.bin.tar.gz
(10.98 KB)
📄
raven2_rlc.bin.tar
(39 KB)
📄
raven2_sdma.bin.bin.tar.gz
(8.38 KB)
📄
raven2_sdma.bin.tar
(18.5 KB)
📄
raven2_ta.bin.bin.tar.gz
(13.41 KB)
📄
raven2_ta.bin.tar
(34.5 KB)
📄
raven2_vcn.bin.bin.tar.gz
(251.28 KB)
📄
raven2_vcn.bin.tar
(359.5 KB)
📄
raven_asd.bin.bin.tar.gz
(62.09 KB)
📄
raven_asd.bin.tar
(190 KB)
📄
raven_ce.bin.bin.tar.gz
(3.47 KB)
📄
raven_ce.bin.tar
(11 KB)
📄
raven_dmcu.bin.bin.tar.gz
(11.79 KB)
📄
raven_dmcu.bin.tar
(24.5 KB)
📄
raven_gpu_info.bin.bin.tar.gz
(174 B)
📄
raven_gpu_info.bin.tar
(2 KB)
📄
raven_ip_discovery.bin.bin.tar.gz
(372 B)
📄
raven_ip_discovery.bin.tar
(2.5 KB)
📄
raven_me.bin.bin.tar.gz
(6.91 KB)
📄
raven_me.bin.tar
(19 KB)
📄
raven_mec.bin.bin.tar.gz
(32.66 KB)
📄
raven_mec.bin.tar
(263.5 KB)
📄
raven_mec2.bin.bin.tar.gz
(32.66 KB)
📄
raven_mec2.bin.tar
(263.5 KB)
📄
raven_pfp.bin.bin.tar.gz
(10.14 KB)
📄
raven_pfp.bin.tar
(23 KB)
📄
raven_rlc.bin.bin.tar.gz
(11.77 KB)
📄
raven_rlc.bin.tar
(79 KB)
📄
raven_sdma.bin.bin.tar.gz
(8.38 KB)
📄
raven_sdma.bin.tar
(18.5 KB)
📄
raven_ta.bin.bin.tar.gz
(13.45 KB)
📄
raven_ta.bin.tar
(34.5 KB)
📄
raven_vcn.bin.bin.tar.gz
(251.28 KB)
📄
raven_vcn.bin.tar
(359.5 KB)
📄
raw.h.h.tar.gz
(733 B)
📄
raw.h.tar
(3 KB)
📄
raw.la.la.tar.gz
(676 B)
📄
raw.la.tar
(3 KB)
📄
raw.tar
(12 KB)
📄
raw.tar.gz
(228 B)
📄
raw6.tar
(9 KB)
📄
raw6.tar.gz
(185 B)
📄
razor.tar
(123.5 KB)
📄
razor.tar.gz
(63.97 KB)
📄
razor.zip
(104.16 KB)
📄
rbconfig.rb.rb.tar.gz
(4.35 KB)
📄
rbconfig.rb.tar
(16 KB)
📄
rbconfig.tar
(17.5 KB)
📄
rbconfig.tar.gz
(5.58 KB)
📄
rbconfig.zip
(15.99 KB)
📄
rc-inst.sh.sh.tar.gz
(1.67 KB)
📄
rc-inst.sh.tar
(8 KB)
📄
rc-local.service.service.tar.gz
(549 B)
📄
rc-local.service.tar
(4 KB)
📄
rcar_gen4_pcie.bin.bin.tar.gz
(12.02 KB)
📄
rcar_gen4_pcie.bin.tar
(33.5 KB)
📄
rcrt1.o.o.tar.gz
(1.54 KB)
📄
rcrt1.o.tar
(10 KB)
📄
rd.rb.rb.tar.gz
(1.64 KB)
📄
rd.rb.tar
(28 KB)
📄
rd.tar
(58 KB)
📄
rd.tar.gz
(11.34 KB)
📄
rd.zip
(55.32 KB)
📄
rdf.php.php.tar.gz
(491 B)
📄
rdf.php.tar
(2.5 KB)
📄
rdisc.service.service.tar.gz
(266 B)
📄
rdisc.service.tar
(2 KB)
📄
rdma.tar
(197 KB)
📄
rdma.tar.gz
(37.79 KB)
📄
rdma.zip
(179.06 KB)
📄
rdma_netlink.h.h.tar.gz
(4.26 KB)
📄
rdma_netlink.h.tar
(16.5 KB)
📄
rdma_user_cm.h.h.tar.gz
(2.28 KB)
📄
rdma_user_cm.h.tar
(8.5 KB)
📄
rdma_user_ioctl.h.h.tar.gz
(1.61 KB)
📄
rdma_user_ioctl.h.tar
(5.5 KB)
📄
rdma_user_ioctl_cmds.h.h.tar.gz
(1.37 KB)
📄
rdma_user_ioctl_cmds.h.tar
(4.5 KB)
📄
rdn_name.so.so.tar.gz
(6.99 KB)
📄
rdn_name.so.tar
(21.5 KB)
📄
rdoc.rb.rb.tar.gz
(2.04 KB)
📄
rdoc.rb.tar
(23.5 KB)
📄
rdoc.tar
(1.95 MB)
📄
rdoc.tar.gz
(411 B)
📄
rdoc.zip
(1.83 MB)
📄
rdp.xml.tar
(3 KB)
📄
rdp.xml.xml.tar.gz
(243 B)
📄
rdwr.h.h.tar.gz
(2.57 KB)
📄
rdwr.h.tar
(11 KB)
📄
re.cpython-38.pyc.cpython-38.pyc.tar.gz
(5.83 KB)
📄
re.cpython-38.pyc.tar
(16 KB)
📄
re.pm.pm.tar.gz
(7.87 KB)
📄
re.pm.tar
(24 KB)
📄
re.py.py.tar.gz
(5.02 KB)
📄
re.py.tar
(47 KB)
📄
re.pyc.pyc.tar.gz
(5.16 KB)
📄
re.pyc.tar
(15 KB)
📄
re.pyo.pyo.tar.gz
(5.16 KB)
📄
re.pyo.tar
(15 KB)
📄
re.so.so.tar.gz
(232.17 KB)
📄
re.so.tar
(563.5 KB)
📄
re.tar
(563.5 KB)
📄
re.tar.gz
(232.15 KB)
📄
re.zip
(561.75 KB)
📄
re_comp.h.h.tar.gz
(634 B)
📄
re_comp.h.tar
(2.5 KB)
📄
read.mod.mod.tar.gz
(1003 B)
📄
read.mod.tar
(3.5 KB)
📄
readdir.so.so.tar.gz
(4.38 KB)
📄
readdir.so.tar
(13.5 KB)
📄
readelf.tar
(626.5 KB)
📄
readelf.tar.gz
(264.23 KB)
📄
reader.h.h.tar.gz
(2.71 KB)
📄
reader.h.tar
(9.5 KB)
📄
readerself.tar
(115.5 KB)
📄
readerself.tar.gz
(57.76 KB)
📄
readerself.zip
(97.22 KB)
📄
readfile.so.so.tar.gz
(4.6 KB)
📄
readfile.so.tar
(13.5 KB)
📄
readline.so.so.tar.gz
(14.21 KB)
📄
readline.so.tar
(38 KB)
📄
readlink.tar
(47.5 KB)
📄
readlink.tar.gz
(22.05 KB)
📄
reads.tar
(2 KB)
📄
reads.tar.gz
(109 B)
📄
realesbar.tar
(287.12 MB)
📄
realesbar.tar.gz
(118.32 MB)
📄
realestate.tar
(47.13 MB)
📄
realestate.tar.gz
(43.73 MB)
📄
realestate.zip
(47.11 MB)
📄
realpath.tar
(51.5 KB)
📄
realpath.tar.gz
(23.22 KB)
📄
realtek.tar
(49 KB)
📄
realtek.tar.gz
(17.44 KB)
📄
realtek.zip
(46.38 KB)
📄
realtimeReqReport.php.php.tar.gz
(2.44 KB)
📄
realtimeReqReport.php.tar
(8.5 KB)
📄
reboot.h.h.tar.gz
(939 B)
📄
reboot.h.tar
(3.5 KB)
📄
reboot.mod.mod.tar.gz
(1020 B)
📄
reboot.mod.tar
(6 KB)
📄
reboot.target.tar
(4 KB)
📄
reboot.target.target.tar.gz
(469 B)
📄
receive.go.go.tar.gz
(1.03 KB)
📄
receive.go.tar
(3.5 KB)
📄
recent_authed_mail_ips.tar
(5.5 KB)
📄
recent_authed_mail_ips.tar.gz
(1.67 KB)
📄
recode.tar
(49 KB)
📄
recode.tar.gz
(20.92 KB)
📄
recommend.d.tar
(3.5 KB)
📄
recommend.d.tar.gz
(932 B)
📄
recommend.d.zip
(2.01 KB)
📄
record.h.h.tar.gz
(2.93 KB)
📄
record.h.tar
(29 KB)
📄
redax.tar
(176 KB)
📄
redax.tar.gz
(94.7 KB)
📄
redax.zip
(151.93 KB)
📄
redemo.py.py.tar.gz
(1.65 KB)
📄
redemo.py.tar
(7.5 KB)
📄
redemo.pyo.pyo.tar.gz
(2.5 KB)
📄
redemo.pyo.tar
(7 KB)
📄
redhat-annobin-cc1.tar
(2 KB)
📄
redhat-annobin-cc1.tar.gz
(179 B)
📄
redhat-hardened-cc1.tar
(2 KB)
📄
redhat-hardened-cc1.tar.gz
(162 B)
📄
redhat-hardened-ld.tar
(2 KB)
📄
redhat-hardened-ld.tar.gz
(153 B)
📄
redhat.tar
(125.5 KB)
📄
redhat.tar.gz
(33.4 KB)
📄
redhat.zip
(115 KB)
📄
redirect.xml.tar
(2 KB)
📄
redirect.xml.xml.tar.gz
(243 B)
📄
redirect_load.tar
(2 KB)
📄
redirect_load.tar.gz
(121 B)
📄
redirect_number.tar
(2 KB)
📄
redirect_number.tar.gz
(122 B)
📄
redis-sentinel.xml.tar
(2 KB)
📄
redis-sentinel.xml.xml.tar.gz
(257 B)
📄
redis.xml.tar
(2 KB)
📄
redis.xml.xml.tar.gz
(301 B)
📄
reduction.pyc.pyc.tar.gz
(2.45 KB)
📄
reduction.pyc.tar
(7.5 KB)
📄
reduction.pyo.pyo.tar.gz
(2.45 KB)
📄
reduction.pyo.tar
(7.5 KB)
📄
reentr.h.h.tar.gz
(7.26 KB)
📄
reentr.h.tar
(78 KB)
📄
reg.h.h.tar.gz
(898 B)
📄
reg.h.tar
(3.5 KB)
📄
regcharclass.h.h.tar.gz
(13.84 KB)
📄
regcharclass.h.tar
(143 KB)
📄
regcomp.h.h.tar.gz
(15.15 KB)
📄
regcomp.h.tar
(48.5 KB)
📄
regen.tar
(2 KB)
📄
regen.tar.gz
(253 B)
📄
regen_max_retry.tar
(2 KB)
📄
regen_max_retry.tar.gz
(125 B)
📄
regex.h.h.tar.gz
(14.7 KB)
📄
regex.h.tar
(111 KB)
📄
regexp.h.h.tar.gz
(10.62 KB)
📄
regexp.h.tar
(37.5 KB)
📄
regexp.mod.mod.tar.gz
(33.56 KB)
📄
regexp.mod.tar
(173 KB)
📄
regnodes.h.h.tar.gz
(7.07 KB)
📄
regnodes.h.tar
(36.5 KB)
📄
reindent.pyc.pyc.tar.gz
(4.51 KB)
📄
reindent.pyc.tar
(11 KB)
📄
reindent.pyo.pyo.tar.gz
(4.49 KB)
📄
reindent.pyo.tar
(11 KB)
📄
reindexdb.tar
(72 KB)
📄
reindexdb.tar.gz
(28.39 KB)
📄
reiserfs.mod.mod.tar.gz
(5.62 KB)
📄
reiserfs.mod.tar
(13.5 KB)
📄
relayhosts.tar
(5 KB)
📄
relayhosts.tar.gz
(1.45 KB)
📄
release.sh.sh.tar.gz
(509 B)
📄
release.sh.tar
(2.5 KB)
📄
relocator.mod.mod.tar.gz
(8.31 KB)
📄
relocator.mod.tar
(43 KB)
📄
remote-fs-pre.target.tar
(2 KB)
📄
remote-fs-pre.target.target.tar.gz
(392 B)
📄
remote-fs.target.tar
(4 KB)
📄
remote-fs.target.target.tar.gz
(447 B)
📄
remove.php.php.tar.gz
(2.33 KB)
📄
remove.php.tar
(70.5 KB)
📄
rename.h.h.tar.gz
(2.67 KB)
📄
rename.h.tar
(12 KB)
📄
rename.tar
(18 KB)
📄
rename.tar.gz
(6.56 KB)
📄
rename_device.tar
(35 KB)
📄
rename_device.tar.gz
(6.42 KB)
📄
render.h.h.tar.gz
(8.86 KB)
📄
render.h.tar
(103 KB)
📄
renew-dummy-cert.tar
(2.5 KB)
📄
renew-dummy-cert.tar.gz
(498 B)
📄
renice.tar
(18 KB)
📄
renice.tar.gz
(5.81 KB)
📄
renoir_asd.bin.bin.tar.gz
(65.75 KB)
📄
renoir_asd.bin.tar
(202 KB)
📄
renoir_ce.bin.bin.tar.gz
(3.51 KB)
📄
renoir_ce.bin.tar
(11 KB)
📄
renoir_dmcub.bin.bin.tar.gz
(74.04 KB)
📄
renoir_dmcub.bin.tar
(120.5 KB)
📄
renoir_gpu_info.bin.bin.tar.gz
(175 B)
📄
renoir_gpu_info.bin.tar
(2 KB)
📄
renoir_me.bin.bin.tar.gz
(6.79 KB)
📄
renoir_me.bin.tar
(19 KB)
📄
renoir_mec.bin.bin.tar.gz
(33.41 KB)
📄
renoir_mec.bin.tar
(263.5 KB)
📄
renoir_mec2.bin.bin.tar.gz
(33.42 KB)
📄
renoir_mec2.bin.tar
(263.5 KB)
📄
renoir_pfp.bin.bin.tar.gz
(10.37 KB)
📄
renoir_pfp.bin.tar
(23 KB)
📄
renoir_rlc.bin.bin.tar.gz
(11.74 KB)
📄
renoir_rlc.bin.tar
(40.5 KB)
📄
renoir_sdma.bin.bin.tar.gz
(8.59 KB)
📄
renoir_sdma.bin.tar
(18.5 KB)
📄
renoir_ta.bin.bin.tar.gz
(14.73 KB)
📄
renoir_ta.bin.tar
(46.5 KB)
📄
renoir_vcn.bin.bin.tar.gz
(279.76 KB)
📄
renoir_vcn.bin.tar
(397 KB)
📄
replace.tar
(4.54 MB)
📄
replace.tar.gz
(1003.7 KB)
📄
repr.py.py.tar.gz
(1.27 KB)
📄
repr.py.tar
(6 KB)
📄
repr.pyc.pyc.tar.gz
(2.08 KB)
📄
repr.pyc.tar
(7 KB)
📄
repr.pyo.pyo.tar.gz
(2.08 KB)
📄
repr.pyo.tar
(7 KB)
📄
reprlib.py.py.tar.gz
(1.57 KB)
📄
reprlib.py.tar
(13 KB)
📄
requirements.txt.tar
(2.5 KB)
📄
requirements.txt.txt.tar.gz
(477 B)
📄
res.h.h.tar.gz
(2.59 KB)
📄
res.h.tar
(25.5 KB)
📄
res_state.h.h.tar.gz
(1006 B)
📄
res_state.h.tar
(3.5 KB)
📄
rescue.service.service.tar.gz
(593 B)
📄
rescue.service.tar
(2.5 KB)
📄
rescue.target.tar
(2 KB)
📄
rescue.target.target.tar.gz
(409 B)
📄
reserve.tar
(2 KB)
📄
reserve.tar.gz
(113 B)
📄
reset.tar
(26.5 KB)
📄
reset.tar.gz
(11.37 KB)
📄
resolv.conf.conf.tar.gz
(153 B)
📄
resolv.conf.tar
(5 KB)
📄
resolv.h.h.tar.gz
(3.91 KB)
📄
resolv.h.tar
(13.5 KB)
📄
resolver.tar
(5 KB)
📄
resolver.tar.gz
(1.04 KB)
📄
resource.h.h.tar.gz
(2.33 KB)
📄
resource.h.tar
(16 KB)
📄
restate.tar
(285.73 MB)
📄
restore.php.php.tar.gz
(2.11 KB)
📄
restore.php.tar
(68.5 KB)
📄
result.py.py.tar.gz
(2.18 KB)
📄
result.py.tar
(9 KB)
📄
retrans_time.tar
(5 KB)
📄
retrans_time.tar.gz
(124 B)
📄
retrans_time_ms.tar
(5 KB)
📄
retrans_time_ms.tar.gz
(126 B)
📄
return_slip.html.html.tar.gz
(3.63 KB)
📄
return_slip.html.tar
(40 KB)
📄
rev.tar
(14 KB)
📄
rev.tar.gz
(5.31 KB)
📄
revoutput.so.so.tar.gz
(3.91 KB)
📄
revoutput.so.tar
(13.5 KB)
📄
revtwoway.so.so.tar.gz
(4.43 KB)
📄
revtwoway.so.tar
(13.5 KB)
📄
rexec.py.py.tar.gz
(5.27 KB)
📄
rexec.py.tar
(21.5 KB)
📄
rexec.pyc.pyc.tar.gz
(7.83 KB)
📄
rexec.pyc.tar
(25 KB)
📄
rexec.pyo.pyo.tar.gz
(7.83 KB)
📄
rexec.pyo.tar
(25 KB)
📄
rexml.tar
(307.5 KB)
📄
rexml.tar.gz
(68.33 KB)
📄
rexml.zip
(273.56 KB)
📄
rfc2396_parser.rb.rb.tar.gz
(4.94 KB)
📄
rfc2396_parser.rb.tar
(19 KB)
📄
rfc822.py.py.tar.gz
(9.33 KB)
📄
rfc822.py.tar
(34.5 KB)
📄
rfc822.pyc.pyc.tar.gz
(12.15 KB)
📄
rfc822.pyc.tar
(33 KB)
📄
rfc822.pyo.pyo.tar.gz
(12.16 KB)
📄
rfc822.pyo.tar
(33 KB)
📄
rgrep.pyc.pyc.tar.gz
(1.11 KB)
📄
rgrep.pyc.tar
(3.5 KB)
📄
rgrep.pyo.pyo.tar.gz
(1.11 KB)
📄
rgrep.pyo.tar
(3.5 KB)
📄
rh_flags.tar
(2 KB)
📄
rh_flags.tar.gz
(108 B)
📄
rhnsd.service.service.tar.gz
(299 B)
📄
rhnsd.service.tar
(3 KB)
📄
ri.rb.rb.tar.gz
(333 B)
📄
ri.rb.tar
(8 KB)
📄
ri.tar
(63.5 KB)
📄
ri.tar.gz
(822 B)
📄
ri.zip
(41.26 KB)
📄
ricar.tar
(151 KB)
📄
ricar.tar.gz
(83.31 KB)
📄
ricar.zip
(128.94 KB)
📄
rinda.tar
(36 KB)
📄
rinda.tar.gz
(8.95 KB)
📄
rinda.zip
(33.29 KB)
📄
ring.rb.rb.tar.gz
(3.7 KB)
📄
ring.rb.tar
(14 KB)
📄
ripemd.h.h.tar.gz
(671 B)
📄
ripemd.h.tar
(3 KB)
📄
ripper.so.so.tar.gz
(78.99 KB)
📄
ripper.so.tar
(218.5 KB)
📄
riscv64-linux.tar
(4.5 KB)
📄
riscv64-linux.tar.gz
(1.19 KB)
📄
riscv64-linux.zip
(3.11 KB)
📄
rlcompleter.py.py.tar.gz
(2.51 KB)
📄
rlcompleter.py.tar
(22.5 KB)
📄
rlcompleter.pyc.pyc.tar.gz
(2.89 KB)
📄
rlcompleter.pyc.tar
(7.5 KB)
📄
rlcompleter.pyo.pyo.tar.gz
(2.89 KB)
📄
rlcompleter.pyo.tar
(7.5 KB)
📄
rm.tar
(72 KB)
📄
rm.tar.gz
(33.43 KB)
📄
rmd160.so.so.tar.gz
(3.13 KB)
📄
rmd160.so.tar
(9 KB)
📄
rmdir.tar
(48 KB)
📄
rmdir.tar.gz
(20.9 KB)
📄
rmem_default.tar
(2 KB)
📄
rmem_default.tar.gz
(119 B)
📄
rmem_max.tar
(2 KB)
📄
rmem_max.tar.gz
(115 B)
📄
rmt.pyc.pyc.tar.gz
(2.16 KB)
📄
rmt.pyc.tar
(6.5 KB)
📄
rmt.pyo.pyo.tar.gz
(2.16 KB)
📄
rmt.pyo.tar
(6.5 KB)
📄
rnano.tar
(249.5 KB)
📄
rnano.tar.gz
(121.43 KB)
📄
rnrs.go.go.tar.gz
(7.73 KB)
📄
rnrs.go.tar
(23 KB)
📄
rnrs.tar
(230 KB)
📄
rnrs.tar.gz
(60.32 KB)
📄
rnrs.zip
(214.05 KB)
📄
rnusersclient.pyc.pyc.tar.gz
(1.65 KB)
📄
rnusersclient.pyc.tar
(7 KB)
📄
rnusersclient.pyo.pyo.tar.gz
(1.65 KB)
📄
rnusersclient.pyo.tar
(7 KB)
📄
robotparser.py.py.tar.gz
(2.39 KB)
📄
robotparser.py.tar
(9.5 KB)
📄
robotparser.pyc.pyc.tar.gz
(3.28 KB)
📄
robotparser.pyc.tar
(9.5 KB)
📄
robotparser.pyo.pyo.tar.gz
(3.28 KB)
📄
robotparser.pyo.tar
(9.5 KB)
📄
robots.txt.tar
(13.5 KB)
📄
robots.txt.txt.tar.gz
(214 B)
📄
rockchip.tar
(98 KB)
📄
rockchip.tar.gz
(33.11 KB)
📄
rockchip.zip
(96.16 KB)
📄
roles.h.h.tar.gz
(271 B)
📄
roles.h.tar
(2 KB)
📄
romfs.mod.mod.tar.gz
(2.71 KB)
📄
romfs.mod.tar
(14 KB)
📄
root.tar
(29.5 KB)
📄
root.tar.gz
(8.61 KB)
📄
root.zip
(27.8 KB)
📄
root_.htaccess.htaccess.tar.gz
(344 B)
📄
root_.htaccess.tar
(2 KB)
📄
root_maxbytes.tar
(2 KB)
📄
root_maxbytes.tar.gz
(119 B)
📄
root_maxkeys.tar
(2 KB)
📄
root_maxkeys.tar.gz
(115 B)
📄
rosariosis.tar
(10.31 MB)
📄
rosariosis.tar.gz
(9.82 MB)
📄
rosariosis.zip
(10.28 MB)
📄
rose.h.h.tar.gz
(1.34 KB)
📄
rose.h.tar
(5 KB)
📄
rotorstep.tar
(2 KB)
📄
rotorstep.tar.gz
(107 B)
📄
roundcube.sql.sql.tar.gz
(1.8 KB)
📄
roundcube.sql.tar
(16.5 KB)
📄
roundcube.tar
(11.25 MB)
📄
roundcube.tar.gz
(10.37 MB)
📄
roundcube.zip
(11.22 MB)
📄
route.h.h.tar.gz
(1.95 KB)
📄
route.h.tar
(6.5 KB)
📄
route_localnet.tar
(4 KB)
📄
route_localnet.tar.gz
(123 B)
📄
routed.h.h.tar.gz
(1.92 KB)
📄
routed.h.tar
(5.5 KB)
📄
routing.php.php.tar.gz
(400 B)
📄
routing.php.tar
(3 KB)
📄
routing.yml.tar
(5 KB)
📄
routing.yml.yml.tar.gz
(1.04 KB)
📄
row.rb.rb.tar.gz
(3.65 KB)
📄
row.rb.tar
(13 KB)
📄
rp2.fw.fw.tar.gz
(162 B)
📄
rp2.fw.tar
(3 KB)
📄
rp_filter.tar
(2 KB)
📄
rp_filter.tar.gz
(120 B)
📄
rpc-bind.xml.tar
(2 KB)
📄
rpc-bind.xml.xml.tar.gz
(244 B)
📄
rpc-gssd.service.service.tar.gz
(306 B)
📄
rpc-gssd.service.tar
(2 KB)
📄
rpc-statd.service.service.tar.gz
(362 B)
📄
rpc-statd.service.tar
(2 KB)
📄
rpc.h.h.tar.gz
(1.5 KB)
📄
rpc.h.tar
(26.5 KB)
📄
rpc.proto.proto.tar.gz
(1.96 KB)
📄
rpc.proto.tar
(7 KB)
📄
rpc.py.py.tar.gz
(6.53 KB)
📄
rpc.py.tar
(49 KB)
📄
rpc.pyc.pyc.tar.gz
(7.86 KB)
📄
rpc.pyc.tar
(23 KB)
📄
rpc.pyo.pyo.tar.gz
(7.8 KB)
📄
rpc.pyo.tar
(23 KB)
📄
rpc.tar
(183.5 KB)
📄
rpc.tar.gz
(863 B)
📄
rpc.zip
(166.07 KB)
📄
rpc_compat.h.h.tar.gz
(1.2 KB)
📄
rpc_compat.h.tar
(4 KB)
📄
rpc_debug.tar
(2 KB)
📄
rpc_debug.tar.gz
(110 B)
📄
rpc_msg.h.h.tar.gz
(2.1 KB)
📄
rpc_msg.h.tar
(6.5 KB)
📄
rpc_pipefs.target.tar
(2 KB)
📄
rpc_pipefs.target.target.tar.gz
(159 B)
📄
rpc_struct.h.h.tar.gz
(1.54 KB)
📄
rpc_struct.h.tar
(5 KB)
📄
rpcbind.conf.conf.tar.gz
(174 B)
📄
rpcbind.conf.tar
(3 KB)
📄
rpcbind.service.service.tar.gz
(444 B)
📄
rpcbind.service.tar
(2.5 KB)
📄
rpcbind.socket.socket.tar.gz
(318 B)
📄
rpcbind.socket.tar
(2 KB)
📄
rpcbind.target.tar
(2.5 KB)
📄
rpcbind.target.target.tar.gz
(462 B)
📄
rpm-plugins.tar
(26 KB)
📄
rpm-plugins.tar.gz
(7.27 KB)
📄
rpm-plugins.zip
(23.7 KB)
📄
rpm.conf.conf.tar.gz
(127 B)
📄
rpm.conf.tar
(3 KB)
📄
rpm.daily.daily.tar.gz
(279 B)
📄
rpm.daily.tar
(3 KB)
📄
rpm.log.log.tar.gz
(150 B)
📄
rpm.log.tar
(3 KB)
📄
rpm.supp.supp.tar.gz
(392 B)
📄
rpm.supp.tar
(4 KB)
📄
rpm.tar
(5 KB)
📄
rpm.tar.gz
(618 B)
📄
rpm.zip
(2.22 KB)
📄
rpm2cpio.sh.sh.tar.gz
(720 B)
📄
rpm2cpio.sh.tar
(5 KB)
📄
rpmdb_loadcvt.tar
(5 KB)
📄
rpmdb_loadcvt.tar.gz
(692 B)
📄
rpmpopt-4.14.3.14.3.tar.gz
(3.41 KB)
📄
rpmpopt-4.14.3.tar
(25 KB)
📄
rpmrc.tar
(48 KB)
📄
rpmrc.tar.gz
(3.29 KB)
📄
rpmver.tar
(2 KB)
📄
rpmver.tar.gz
(147 B)
📄
rps_default_mask.tar
(2 KB)
📄
rps_default_mask.tar.gz
(125 B)
📄
rps_sock_flow_entries.tar
(2 KB)
📄
rps_sock_flow_entries.tar.gz
(125 B)
📄
rquotad.xml.tar
(2 KB)
📄
rquotad.xml.xml.tar.gz
(242 B)
📄
rrdcached.service.service.tar.gz
(359 B)
📄
rrdcached.service.tar
(2 KB)
📄
rrdcached.socket.socket.tar.gz
(315 B)
📄
rrdcached.socket.tar
(3 KB)
📄
rrdgraph.tar
(5 KB)
📄
rrdgraph.tar.gz
(1.45 KB)
📄
rrdgraph.zip
(3.36 KB)
📄
rs9113_wlan_bt_dual_mode.rps.rps.tar.gz
(179.85 KB)
📄
rs9113_wlan_bt_dual_mode.rps.tar
(326 KB)
📄
rs9116_wlan.rps.rps.tar.gz
(54.72 KB)
📄
rs9116_wlan.rps.tar
(103 KB)
📄
rsd.xml.tar
(2.5 KB)
📄
rsd.xml.xml.tar.gz
(375 B)
📄
rsh.xml.tar
(3 KB)
📄
rsh.xml.xml.tar.gz
(315 B)
📄
rsi.tar
(1.24 MB)
📄
rsi.tar.gz
(657.97 KB)
📄
rsi.zip
(1.24 MB)
📄
rsi_91x.fw.fw.tar.gz
(53.9 KB)
📄
rsi_91x.fw.tar
(186 KB)
📄
rss.rb.rb.tar.gz
(7.25 KB)
📄
rss.rb.tar
(248.5 KB)
📄
rsync.tar
(512 KB)
📄
rsync.tar.gz
(263.62 KB)
📄
rsyncd.xml.tar
(2 KB)
📄
rsyncd.xml.xml.tar.gz
(285 B)
📄
rsyslog.service.d.tar
(2 KB)
📄
rsyslog.service.d.tar.gz
(124 B)
📄
rsyslog.service.d.zip
(188 B)
📄
rsyslog.service.service.tar.gz
(688 B)
📄
rsyslog.service.tar
(2.5 KB)
📄
rsyslog.tar
(831.5 KB)
📄
rsyslog.tar.gz
(287.27 KB)
📄
rsyslog.zip
(808.14 KB)
📄
rt1320.tar
(49 KB)
📄
rt1320.tar.gz
(17.45 KB)
📄
rt1320.zip
(46.34 KB)
📄
rt2561.bin.bin.tar.gz
(4.03 KB)
📄
rt2561.bin.tar
(18 KB)
📄
rt2561s.bin.bin.tar.gz
(4.02 KB)
📄
rt2561s.bin.tar
(18 KB)
📄
rt2661.bin.bin.tar.gz
(4.12 KB)
📄
rt2661.bin.tar
(18 KB)
📄
rt2860.bin.bin.tar.gz
(2.89 KB)
📄
rt2860.bin.tar
(18 KB)
📄
rt2870.bin.bin.tar.gz
(2.75 KB)
📄
rt2870.bin.tar
(18 KB)
📄
rt3070.bin.bin.tar.gz
(2.75 KB)
📄
rt3070.bin.tar
(18 KB)
📄
rt3071.bin.bin.tar.gz
(2.62 KB)
📄
rt3071.bin.tar
(10 KB)
📄
rt3090.bin.bin.tar.gz
(2.89 KB)
📄
rt3090.bin.tar
(18 KB)
📄
rt3290.bin.bin.tar.gz
(2.63 KB)
📄
rt3290.bin.tar
(10 KB)
📄
rt5514-tplg.bin.bin.tar.gz
(673 B)
📄
rt5514-tplg.bin.tar
(5 KB)
📄
rt5640-tplg.bin.bin.tar.gz
(865 B)
📄
rt5640-tplg.bin.tar
(7.5 KB)
📄
rt5663-tplg.bin.bin.tar.gz
(772 B)
📄
rt5663-tplg.bin.tar
(6 KB)
📄
rt73.bin.bin.tar.gz
(1.19 KB)
📄
rt73.bin.tar
(6 KB)
📄
rtc.tar
(2 KB)
📄
rtc.tar.gz
(279 B)
📄
rtl8105e-1.fw.fw.tar.gz
(1.04 KB)
📄
rtl8105e-1.fw.tar
(4 KB)
📄
rtl8106e-1.fw.fw.tar.gz
(1015 B)
📄
rtl8106e-1.fw.tar
(3.5 KB)
📄
rtl8106e-2.fw.fw.tar.gz
(531 B)
📄
rtl8106e-2.fw.tar
(2.5 KB)
📄
rtl8107e-1.fw.fw.tar.gz
(884 B)
📄
rtl8107e-1.fw.tar
(2.5 KB)
📄
rtl8107e-2.fw.fw.tar.gz
(873 B)
📄
rtl8107e-2.fw.tar
(2.5 KB)
📄
rtl8125a-3.fw.fw.tar.gz
(1.98 KB)
📄
rtl8125a-3.fw.tar
(5 KB)
📄
rtl8125b-1.fw.fw.tar.gz
(3.88 KB)
📄
rtl8125b-1.fw.tar
(11.5 KB)
📄
rtl8125b-2.fw.fw.tar.gz
(1.76 KB)
📄
rtl8125b-2.fw.tar
(5 KB)
📄
rtl8125bp-2.fw.fw.tar.gz
(690 B)
📄
rtl8125bp-2.fw.tar
(2.5 KB)
📄
rtl8125d-1.fw.fw.tar.gz
(5.41 KB)
📄
rtl8125d-1.fw.tar
(18.5 KB)
📄
rtl8125d-2.fw.fw.tar.gz
(2.35 KB)
📄
rtl8125d-2.fw.tar
(8.5 KB)
📄
rtl8125k-1.fw.fw.tar.gz
(2.87 KB)
📄
rtl8125k-1.fw.tar
(9.5 KB)
📄
rtl8126a-2.fw.fw.tar.gz
(8.99 KB)
📄
rtl8126a-2.fw.tar
(30.5 KB)
📄
rtl8126a-3.fw.fw.tar.gz
(4.8 KB)
📄
rtl8126a-3.fw.tar
(14.5 KB)
📄
rtl8127a-1.fw.fw.tar.gz
(4.8 KB)
📄
rtl8127a-1.fw.tar
(11 KB)
📄
rtl8153a-2.fw.fw.tar.gz
(1.55 KB)
📄
rtl8153a-2.fw.tar
(3.5 KB)
📄
rtl8153a-3.fw.fw.tar.gz
(1.3 KB)
📄
rtl8153a-3.fw.tar
(3 KB)
📄
rtl8153a-4.fw.fw.tar.gz
(1.11 KB)
📄
rtl8153a-4.fw.tar
(3 KB)
📄
rtl8153b-2.fw.fw.tar.gz
(1.53 KB)
📄
rtl8153b-2.fw.tar
(3.5 KB)
📄
rtl8153c-1.fw.fw.tar.gz
(731 B)
📄
rtl8153c-1.fw.tar
(2.5 KB)
📄
rtl8156a-2.fw.fw.tar.gz
(2.9 KB)
📄
rtl8156a-2.fw.tar
(5.5 KB)
📄
rtl8156b-2.fw.fw.tar.gz
(3.2 KB)
📄
rtl8156b-2.fw.tar
(7.5 KB)
📄
rtl8168d-1.fw.fw.tar.gz
(948 B)
📄
rtl8168d-1.fw.tar
(3 KB)
📄
rtl8168d-2.fw.fw.tar.gz
(865 B)
📄
rtl8168d-2.fw.tar
(3 KB)
📄
rtl8168e-1.fw.fw.tar.gz
(2.93 KB)
📄
rtl8168e-1.fw.tar
(13 KB)
📄
rtl8168e-2.fw.fw.tar.gz
(2.2 KB)
📄
rtl8168e-2.fw.tar
(5.5 KB)
📄
rtl8168e-3.fw.fw.tar.gz
(2.14 KB)
📄
rtl8168e-3.fw.tar
(5.5 KB)
📄
rtl8168f-1.fw.fw.tar.gz
(1.87 KB)
📄
rtl8168f-1.fw.tar
(5 KB)
📄
rtl8168f-2.fw.fw.tar.gz
(847 B)
📄
rtl8168f-2.fw.tar
(3 KB)
📄
rtl8168fp-3.fw.fw.tar.gz
(373 B)
📄
rtl8168fp-3.fw.tar
(2 KB)
📄
rtl8168g-1.fw.fw.tar.gz
(2.26 KB)
📄
rtl8168g-1.fw.tar
(6 KB)
📄
rtl8168g-2.fw.fw.tar.gz
(2.74 KB)
📄
rtl8168g-2.fw.tar
(6.5 KB)
📄
rtl8168g-3.fw.fw.tar.gz
(533 B)
📄
rtl8168g-3.fw.tar
(2.5 KB)
📄
rtl8168h-1.fw.fw.tar.gz
(889 B)
📄
rtl8168h-1.fw.tar
(2.5 KB)
📄
rtl8168h-2.fw.fw.tar.gz
(872 B)
📄
rtl8168h-2.fw.tar
(2.5 KB)
📄
rtl8188efw.bin.bin.tar.gz
(6.39 KB)
📄
rtl8188efw.bin.tar
(12.5 KB)
📄
rtl8188eufw.bin.bin.tar.gz
(10.06 KB)
📄
rtl8188eufw.bin.tar
(16.5 KB)
📄
rtl8188fufw.bin.bin.tar.gz
(13.59 KB)
📄
rtl8188fufw.bin.tar
(22.5 KB)
📄
rtl8192cfw.bin.bin.tar.gz
(8.72 KB)
📄
rtl8192cfw.bin.tar
(17.5 KB)
📄
rtl8192cfwU.bin.bin.tar.gz
(7.82 KB)
📄
rtl8192cfwU.bin.tar
(16 KB)
📄
rtl8192cfwU_B.bin.bin.tar.gz
(8.59 KB)
📄
rtl8192cfwU_B.bin.tar
(17.5 KB)
📄
rtl8192cufw.bin.bin.tar.gz
(7.66 KB)
📄
rtl8192cufw.bin.tar
(17.5 KB)
📄
rtl8192cufw_A.bin.bin.tar.gz
(8.72 KB)
📄
rtl8192cufw_A.bin.tar
(17.5 KB)
📄
rtl8192cufw_B.bin.bin.tar.gz
(8.7 KB)
📄
rtl8192cufw_B.bin.tar
(17.5 KB)
📄
rtl8192cufw_TMSC.bin.bin.tar.gz
(8.72 KB)
📄
rtl8192cufw_TMSC.bin.tar
(17.5 KB)
📄
rtl8192defw.bin.bin.tar.gz
(13.01 KB)
📄
rtl8192defw.bin.tar
(32.5 KB)
📄
rtl8192dufw.bin.bin.tar.gz
(13.24 KB)
📄
rtl8192dufw.bin.tar
(32.5 KB)
📄
rtl8192ee_fw.bin.bin.tar.gz
(19.27 KB)
📄
rtl8192ee_fw.bin.tar
(39.5 KB)
📄
rtl8192eefw.bin.bin.tar.gz
(20.33 KB)
📄
rtl8192eefw.bin.tar
(33.5 KB)
📄
rtl8192eu_fw.bin.bin.tar.gz
(19.04 KB)
📄
rtl8192eu_fw.bin.tar
(39 KB)
📄
rtl8192eu_nic.bin.bin.tar.gz
(20.33 KB)
📄
rtl8192eu_nic.bin.tar
(33.5 KB)
📄
rtl8192eu_wowlan.bin.bin.tar.gz
(17.77 KB)
📄
rtl8192eu_wowlan.bin.tar
(30 KB)
📄
rtl8192fufw.bin.bin.tar.gz
(19.4 KB)
📄
rtl8192fufw.bin.tar
(32 KB)
📄
rtl8192sefw.bin.bin.tar.gz
(35.75 KB)
📄
rtl8192sefw.bin.tar
(80 KB)
📄
rtl8402-1.fw.fw.tar.gz
(981 B)
📄
rtl8402-1.fw.tar
(3.5 KB)
📄
rtl8411-1.fw.fw.tar.gz
(1.29 KB)
📄
rtl8411-1.fw.tar
(4 KB)
📄
rtl8411-2.fw.fw.tar.gz
(667 B)
📄
rtl8411-2.fw.tar
(3 KB)
📄
rtl8712u.bin.bin.tar.gz
(61.63 KB)
📄
rtl8712u.bin.tar
(121 KB)
📄
rtl8723a_fw.bin.bin.tar.gz
(17.36 KB)
📄
rtl8723a_fw.bin.tar
(25.5 KB)
📄
rtl8723aufw_A.bin.bin.tar.gz
(11.68 KB)
📄
rtl8723aufw_A.bin.tar
(23.5 KB)
📄
rtl8723aufw_B.bin.bin.tar.gz
(12.54 KB)
📄
rtl8723aufw_B.bin.tar
(25.5 KB)
📄
rtl8723b_config.bin.bin.tar.gz
(181 B)
📄
rtl8723b_config.bin.tar
(2 KB)
📄
rtl8723b_fw.bin.bin.tar.gz
(22.66 KB)
📄
rtl8723b_fw.bin.tar
(45.5 KB)
📄
rtl8723befw.bin.bin.tar.gz
(16.13 KB)
📄
rtl8723befw.bin.tar
(32 KB)
📄
rtl8723befw_36.bin.bin.tar.gz
(20.66 KB)
📄
rtl8723befw_36.bin.tar
(33 KB)
📄
rtl8723bs_fw.bin.bin.tar.gz
(32.54 KB)
📄
rtl8723bs_fw.bin.tar
(52.5 KB)
📄
rtl8723bs_nic.bin.bin.tar.gz
(20.76 KB)
📄
rtl8723bs_nic.bin.tar
(33 KB)
📄
rtl8723bs_wowlan.bin.bin.tar.gz
(16.78 KB)
📄
rtl8723bs_wowlan.bin.tar
(27.5 KB)
📄
rtl8723bu_nic.bin.bin.tar.gz
(20.75 KB)
📄
rtl8723bu_nic.bin.tar
(33 KB)
📄
rtl8723bu_wowlan.bin.bin.tar.gz
(16.78 KB)
📄
rtl8723bu_wowlan.bin.tar
(27.5 KB)
📄
rtl8723cs_xx_fw.bin.bin.tar.gz
(12.32 KB)
📄
rtl8723cs_xx_fw.bin.tar
(21 KB)
📄
rtl8723d_config.bin.bin.tar.gz
(130 B)
📄
rtl8723d_config.bin.tar
(2 KB)
📄
rtl8723d_fw.bin.bin.tar.gz
(33.07 KB)
📄
rtl8723d_fw.bin.tar
(52.5 KB)
📄
rtl8723defw.bin.bin.tar.gz
(17.57 KB)
📄
rtl8723defw.bin.tar
(29 KB)
📄
rtl8723fw.bin.bin.tar.gz
(6.25 KB)
📄
rtl8723fw.bin.tar
(13 KB)
📄
rtl8723fw_B.bin.bin.tar.gz
(11.81 KB)
📄
rtl8723fw_B.bin.tar
(24 KB)
📄
rtl8761a_fw.bin.bin.tar.gz
(41.62 KB)
📄
rtl8761a_fw.bin.tar
(74.5 KB)
📄
rtl8761b_config.bin.bin.tar.gz
(147 B)
📄
rtl8761b_config.bin.tar
(2 KB)
📄
rtl8761b_fw.bin.bin.tar.gz
(30.85 KB)
📄
rtl8761b_fw.bin.tar
(46 KB)
📄
rtl8761bu_fw.bin.bin.tar.gz
(30.27 KB)
📄
rtl8761bu_fw.bin.tar
(45 KB)
📄
rtl8761cu_fw.bin.bin.tar.gz
(454 B)
📄
rtl8761cu_fw.bin.tar
(12 KB)
📄
rtl8812ae_fw.bin.bin.tar.gz
(20.03 KB)
📄
rtl8812ae_fw.bin.tar
(41.5 KB)
📄
rtl8812aefw.bin.bin.tar.gz
(14.41 KB)
📄
rtl8812aefw.bin.tar
(28.5 KB)
📄
rtl8821a_config.bin.bin.tar.gz
(131 B)
📄
rtl8821a_config.bin.tar
(3 KB)
📄
rtl8821a_fw.bin.bin.tar.gz
(20.13 KB)
📄
rtl8821a_fw.bin.tar
(38.5 KB)
📄
rtl8821aefw.bin.bin.tar.gz
(15.3 KB)
📄
rtl8821aefw.bin.tar
(30 KB)
📄
rtl8821aefw_29.bin.bin.tar.gz
(18.33 KB)
📄
rtl8821aefw_29.bin.tar
(29.5 KB)
📄
rtl8821c_config.bin.bin.tar.gz
(131 B)
📄
rtl8821c_config.bin.tar
(2 KB)
📄
rtl8821c_fw.bin.bin.tar.gz
(36.55 KB)
📄
rtl8821c_fw.bin.tar
(55 KB)
📄
rtl8821cs_fw.bin.bin.tar.gz
(37.98 KB)
📄
rtl8821cs_fw.bin.tar
(57 KB)
📄
rtl8822b_config.bin.bin.tar.gz
(134 B)
📄
rtl8822b_config.bin.tar
(2 KB)
📄
rtl8822b_fw.bin.bin.tar.gz
(25.92 KB)
📄
rtl8822b_fw.bin.tar
(51.5 KB)
📄
rtl8822befw.bin.bin.tar.gz
(66.83 KB)
📄
rtl8822befw.bin.tar
(126.5 KB)
📄
rtl8822cs_fw.bin.bin.tar.gz
(40.12 KB)
📄
rtl8822cs_fw.bin.tar
(63.5 KB)
📄
rtl8822cu_fw.bin.bin.tar.gz
(26.52 KB)
📄
rtl8822cu_fw.bin.tar
(38 KB)
📄
rtl8851bu_fw.bin.bin.tar.gz
(33.21 KB)
📄
rtl8851bu_fw.bin.tar
(50.5 KB)
📄
rtl8852au_fw.bin.bin.tar.gz
(46.58 KB)
📄
rtl8852au_fw.bin.tar
(67.5 KB)
📄
rtl8852btu_config.bin.bin.tar.gz
(128 B)
📄
rtl8852btu_config.bin.tar
(2 KB)
📄
rtl8852bu_fw.bin.bin.tar.gz
(88.13 KB)
📄
rtl8852bu_fw.bin.tar
(126 KB)
📄
rtl8852cu_fw.bin.bin.tar.gz
(74.71 KB)
📄
rtl8852cu_fw.bin.tar
(112.5 KB)
📄
rtl8852cu_fw_v2.bin.bin.tar.gz
(75.24 KB)
📄
rtl8852cu_fw_v2.bin.tar
(112 KB)
📄
rtl8922au_fw.bin.bin.tar.gz
(50.13 KB)
📄
rtl8922au_fw.bin.tar
(71.5 KB)
📄
rtl9151a-1.fw.fw.tar.gz
(471 B)
📄
rtl9151a-1.fw.tar
(2.5 KB)
📄
rtl_bt.tar
(1.41 MB)
📄
rtl_bt.tar.gz
(897.38 KB)
📄
rtl_bt.zip
(1.39 MB)
📄
rtl_nic.tar
(189 KB)
📄
rtl_nic.tar.gz
(64.78 KB)
📄
rtl_nic.zip
(165.62 KB)
📄
rtlwifi.tar
(1.1 MB)
📄
rtlwifi.tar.gz
(575.61 KB)
📄
rtlwifi.zip
(1.07 MB)
📄
rtsp.xml.tar
(2 KB)
📄
rtsp.xml.xml.tar.gz
(316 B)
📄
rtw8703b_fw.bin.bin.tar.gz
(13.33 KB)
📄
rtw8703b_fw.bin.tar
(21.5 KB)
📄
rtw8723d_fw.bin.bin.tar.gz
(18.27 KB)
📄
rtw8723d_fw.bin.tar
(30 KB)
📄
rtw88.tar
(838.5 KB)
📄
rtw88.tar.gz
(420.33 KB)
📄
rtw88.zip
(830.92 KB)
📄
rtw8812a_fw.bin.bin.tar.gz
(17.01 KB)
📄
rtw8812a_fw.bin.tar
(28 KB)
📄
rtw8814a_fw.bin.bin.tar.gz
(37.07 KB)
📄
rtw8814a_fw.bin.tar
(68.5 KB)
📄
rtw8821a_fw.bin.bin.tar.gz
(19.87 KB)
📄
rtw8821a_fw.bin.tar
(33 KB)
📄
rtw8821c_fw.bin.bin.tar.gz
(55.98 KB)
📄
rtw8821c_fw.bin.tar
(138 KB)
📄
rtw8822b_fw.bin.bin.tar.gz
(85.62 KB)
📄
rtw8822b_fw.bin.tar
(159 KB)
📄
rtw8822c_fw.bin.bin.tar.gz
(91.03 KB)
📄
rtw8822c_fw.bin.tar
(199.5 KB)
📄
rtw8851b_fw.bin.bin.tar.gz
(583.79 KB)
📄
rtw8851b_fw.bin.tar
(1.11 MB)
📄
rtw8852a_fw.bin.bin.tar.gz
(649.97 KB)
📄
rtw8852a_fw.bin.tar
(1.36 MB)
📄
rtw8852b_fw-1.bin.bin.tar.gz
(623.84 KB)
📄
rtw8852b_fw-1.bin.tar
(1.19 MB)
📄
rtw8852b_fw-2.bin.bin.tar.gz
(659.91 KB)
📄
rtw8852b_fw-2.bin.tar
(1.23 MB)
📄
rtw8852b_fw.bin.bin.tar.gz
(513.16 KB)
📄
rtw8852b_fw.bin.tar
(1012.5 KB)
📄
rtw8852c_fw-1.bin.bin.tar.gz
(1.04 MB)
📄
rtw8852c_fw-1.bin.tar
(2.27 MB)
📄
rtw8852c_fw.bin.bin.tar.gz
(810.15 KB)
📄
rtw8852c_fw.bin.tar
(1.46 MB)
📄
rtw89.tar
(20.62 MB)
📄
rtw89.tar.gz
(10.36 MB)
📄
rtw89.zip
(20.61 MB)
📄
rtw8922a_fw-2.bin.bin.tar.gz
(836.84 KB)
📄
rtw8922a_fw-2.bin.tar
(1.52 MB)
📄
rtw8922a_fw-3.bin.bin.tar.gz
(593.01 KB)
📄
rtw8922a_fw-3.bin.tar
(1.18 MB)
📄
rtw8922a_fw-4.bin.bin.tar.gz
(604.78 KB)
📄
rtw8922a_fw-4.bin.tar
(1.21 MB)
📄
rtw8922a_fw.bin.bin.tar.gz
(807.39 KB)
📄
rtw8922a_fw.bin.tar
(1.47 MB)
📄
ru.tar
(471 KB)
📄
ru.tar.gz
(382.27 KB)
📄
ru.zip
(396.29 KB)
📄
ruby.tar
(4.72 MB)
📄
ruby.tar.gz
(227.45 KB)
📄
ruby.zip
(15.73 MB)
📄
ruby22.tar
(23.25 MB)
📄
ruby22.tar.gz
(7.26 MB)
📄
ruby22.zip
(22.25 MB)
📄
ruby27.tar
(20.29 MB)
📄
ruby27.tar.gz
(6.54 MB)
📄
ruby27.zip
(19.46 MB)
📄
ruby30.tar
(20.26 MB)
📄
ruby30.tar.gz
(6.53 MB)
📄
ruby30.zip
(19.46 MB)
📄
ruby31.tar
(21.38 MB)
📄
ruby31.tar.gz
(6.86 MB)
📄
ruby31.zip
(20.53 MB)
📄
ruby32.tar
(21.31 MB)
📄
ruby32.tar.gz
(6.76 MB)
📄
ruby32.zip
(20.44 MB)
📄
ruby33.tar
(22.35 MB)
📄
ruby33.tar.gz
(7.04 MB)
📄
ruby33.zip
(21.44 MB)
📄
ruby34.tar
(23.43 MB)
📄
ruby34.tar.gz
(7.24 MB)
📄
ruby34.zip
(22.49 MB)
📄
rubygems.tar
(2.57 MB)
📄
rubygems.tar.gz
(883.3 KB)
📄
ruko.png.png.tar.gz
(11.55 KB)
📄
ruko.png.tar
(13.5 KB)
📄
ruko.sql.sql.tar.gz
(7.4 KB)
📄
ruko.sql.tar
(65.5 KB)
📄
ruko.tar
(36.03 MB)
📄
ruko.tar.gz
(33.78 MB)
📄
ruko.zip
(36.01 MB)
📄
rules.d.tar
(128 KB)
📄
rules.d.tar.gz
(22.66 KB)
📄
rules.d.zip
(86.56 KB)
📄
rules.mk.mk.tar.gz
(2.51 KB)
📄
rules.mk.tar
(9 KB)
📄
run-with-aspell.tar
(2 KB)
📄
run-with-aspell.tar.gz
(162 B)
📄
run.py.py.tar.gz
(4.23 KB)
📄
run.py.tar
(14.5 KB)
📄
run.pyc.pyc.tar.gz
(5.92 KB)
📄
run.pyc.tar
(15 KB)
📄
run.pyo.pyo.tar.gz
(5.89 KB)
📄
run.pyo.tar
(15 KB)
📄
runlevel0.target.tar
(2.5 KB)
📄
runlevel0.target.target.tar.gz
(478 B)
📄
runlevel1.target.tar
(2 KB)
📄
runlevel1.target.target.tar.gz
(414 B)
📄
runlevel2.target.tar
(2.5 KB)
📄
runlevel2.target.target.tar.gz
(434 B)
📄
runlevel3.target.tar
(2.5 KB)
📄
runlevel3.target.target.tar.gz
(434 B)
📄
runlevel4.target.tar
(2.5 KB)
📄
runlevel4.target.target.tar.gz
(434 B)
📄
runlevel5.target.tar
(2.5 KB)
📄
runlevel5.target.target.tar.gz
(458 B)
📄
runlevel6.target.tar
(2.5 KB)
📄
runlevel6.target.target.tar.gz
(473 B)
📄
runner.py.py.tar.gz
(2.1 KB)
📄
runner.py.tar
(9.5 KB)
📄
runners.py.py.tar.gz
(889 B)
📄
runners.py.tar
(4 KB)
📄
runpy.py.py.tar.gz
(3.8 KB)
📄
runpy.py.tar
(37.5 KB)
📄
runpy.pyc.pyc.tar.gz
(3.81 KB)
📄
runpy.pyc.tar
(10.5 KB)
📄
runpy.pyo.pyo.tar.gz
(3.81 KB)
📄
runpy.pyo.tar
(10.5 KB)
📄
runq.go.go.tar.gz
(2.77 KB)
📄
runq.go.tar
(8 KB)
📄
ruscii.uni.tar
(10 KB)
📄
ruscii.uni.uni.tar.gz
(1.71 KB)
📄
rvi.tar
(1.13 MB)
📄
rvi.tar.gz
(583.55 KB)
📄
rview.tar
(1.13 MB)
📄
rview.tar.gz
(583.55 KB)
📄
rvim.tar
(2.93 MB)
📄
rvim.tar.gz
(1.48 MB)
📄
rvt-abi.h.h.tar.gz
(888 B)
📄
rvt-abi.h.tar
(3.5 KB)
📄
rw.go.go.tar.gz
(450 B)
📄
rw.go.tar
(2.5 KB)
📄
rwarray.so.so.tar.gz
(6.04 KB)
📄
rwarray.so.tar
(17.5 KB)
📄
rzusb-0.3.bin.3.bin.tar.gz
(3.96 KB)
📄
rzusb-0.3.bin.tar
(7.5 KB)
📄
s2250-1.fw.fw.tar.gz
(842 B)
📄
s2250-1.fw.tar
(5 KB)
📄
s2250-2.fw.fw.tar.gz
(5.74 KB)
📄
s2250-2.fw.tar
(21 KB)
📄
s2250.fw.fw.tar.gz
(5.73 KB)
📄
s2250.fw.tar
(21 KB)
📄
s2250_loader.fw.fw.tar.gz
(842 B)
📄
s2250_loader.fw.tar
(3 KB)
📄
s390-linux.tar
(4.5 KB)
📄
s390-linux.tar.gz
(1.19 KB)
📄
s390-linux.zip
(3.1 KB)
📄
s390x-linux.tar
(4.5 KB)
📄
s390x-linux.tar.gz
(1.19 KB)
📄
s390x-linux.zip
(3.1 KB)
📄
s5p-mfc-v12.fw.fw.tar.gz
(330.13 KB)
📄
s5p-mfc-v12.fw.tar
(1.37 MB)
📄
s5p-mfc-v6-v2.fw.fw.tar.gz
(174.06 KB)
📄
s5p-mfc-v6-v2.fw.tar
(674 KB)
📄
s5p-mfc-v6.fw.fw.tar.gz
(158.76 KB)
📄
s5p-mfc-v6.fw.tar
(601 KB)
📄
s5p-mfc-v7.fw.fw.tar.gz
(197.55 KB)
📄
s5p-mfc-v7.fw.tar
(750 KB)
📄
s5p-mfc-v8.fw.fw.tar.gz
(186.4 KB)
📄
s5p-mfc-v8.fw.tar
(707 KB)
📄
s5p-mfc.fw.fw.tar.gz
(158.34 KB)
📄
s5p-mfc.fw.tar
(691 KB)
📄
s9y.tar
(324 KB)
📄
s9y.tar.gz
(196.02 KB)
📄
s9y.zip
(292.1 KB)
📄
sa.tar
(88.5 KB)
📄
sa.tar.gz
(33.94 KB)
📄
sa.zip
(85.73 KB)
📄
sa1.tar
(2.5 KB)
📄
sa1.tar.gz
(646 B)
📄
sa2.tar
(3 KB)
📄
sa2.tar.gz
(769 B)
📄
sa8775p.tar
(24.99 MB)
📄
sa8775p.tar.gz
(11.71 MB)
📄
sa8775p.zip
(24.98 MB)
📄
sadc.tar
(85 KB)
📄
sadc.tar.gz
(32.52 KB)
📄
safe.go.go.tar.gz
(731 B)
📄
safe.go.tar
(3 KB)
📄
safestack.h.h.tar.gz
(2 KB)
📄
safestack.h.tar
(9.5 KB)
📄
safety_method.tar
(2 KB)
📄
safety_method.tar.gz
(119 B)
📄
saharadbgdownloadB.sys.sys.tar.gz
(20.53 KB)
📄
saharadbgdownloadB.sys.tar
(63 KB)
📄
saharadownloadB.sys.sys.tar.gz
(18.45 KB)
📄
saharadownloadB.sys.tar
(54.5 KB)
📄
salt-master.xml.tar
(2 KB)
📄
salt-master.xml.xml.tar.gz
(311 B)
📄
samba-client.xml.tar
(2 KB)
📄
samba-client.xml.xml.tar.gz
(335 B)
📄
samba-dc.xml.tar
(3 KB)
📄
samba-dc.xml.xml.tar.gz
(557 B)
📄
samba.xml.tar
(2 KB)
📄
samba.xml.xml.tar.gz
(347 B)
📄
sample.so.so.tar.gz
(4.04 KB)
📄
sample.so.tar
(13.5 KB)
📄
sample_concrete.php.php.tar.gz
(371 B)
📄
sample_concrete.php.tar
(2.5 KB)
📄
sample_data.sql.sql.tar.gz
(853.88 KB)
📄
sample_data.sql.tar
(22.29 MB)
📄
sane.xml.tar
(4 KB)
📄
sane.xml.xml.tar.gz
(205 B)
📄
sasl.h.h.tar.gz
(14.58 KB)
📄
sasl.h.tar
(52.5 KB)
📄
sasl.tar
(104.5 KB)
📄
sasl.tar.gz
(26.13 KB)
📄
sasl.zip
(99.19 KB)
📄
sasl2-shared-mechlist.tar
(14 KB)
📄
sasl2-shared-mechlist.tar.gz
(4.33 KB)
📄
sasl2.tar
(51 KB)
📄
sasl2.tar.gz
(17.76 KB)
📄
sasl2.zip
(49.12 KB)
📄
saslauthd.service.service.tar.gz
(306 B)
📄
saslauthd.service.tar
(2 KB)
📄
saslauthd.tar
(166.5 KB)
📄
saslauthd.tar.gz
(42.04 KB)
📄
sasldblistusers2.tar
(44 KB)
📄
sasldblistusers2.tar.gz
(8.56 KB)
📄
saslpasswd2.tar
(18 KB)
📄
saslpasswd2.tar.gz
(6.48 KB)
📄
saslplug.h.h.tar.gz
(8.54 KB)
📄
saslplug.h.tar
(35.5 KB)
📄
saslutil.h.h.tar.gz
(1.1 KB)
📄
saslutil.h.tar
(4.5 KB)
📄
saurus.tar
(143.5 KB)
📄
saurus.tar.gz
(82.3 KB)
📄
saurus.zip
(123.68 KB)
📄
save-history.rb.rb.tar.gz
(1.14 KB)
📄
save-history.rb.tar
(4.5 KB)
📄
save-stack.go.go.tar.gz
(643 B)
📄
save-stack.go.tar
(2.5 KB)
📄
savsoft.tar
(134.5 KB)
📄
savsoft.tar.gz
(78.5 KB)
📄
savsoft.zip
(114.83 KB)
📄
sb16_csp.h.h.tar.gz
(1.37 KB)
📄
sb16_csp.h.tar
(5 KB)
📄
sbin.tar
(11.19 MB)
📄
sbin.tar.gz
(2.2 MB)
📄
sbin.zip
(11.19 MB)
📄
sc7280.tar
(7.12 MB)
📄
sc7280.tar.gz
(3.41 MB)
📄
sc8280xp.tar
(25.24 MB)
📄
sc8280xp.tar.gz
(10.38 MB)
📄
sc8280xp.zip
(25.23 MB)
📄
scalar.pm.pm.tar.gz
(557 B)
📄
scalar.pm.tar
(2.5 KB)
📄
scalar.tar
(4.39 MB)
📄
scalar.tar.gz
(1.11 MB)
📄
scalar.zip
(15.8 KB)
📄
scan_report-2025-07-04_03-25.tar
(9 KB)
📄
scan_report-2025-07-04_03-25.tar.gz
(1.77 KB)
📄
scanner.py.py.tar.gz
(844 B)
📄
scanner.py.tar
(10 KB)
📄
sched.h.h.tar.gz
(1.45 KB)
📄
sched.h.tar
(11 KB)
📄
sched.py.py.tar.gz
(2.32 KB)
📄
sched.py.tar
(20.5 KB)
📄
sched.pyc.pyc.tar.gz
(2.25 KB)
📄
sched.pyc.tar
(6.5 KB)
📄
sched.pyo.pyo.tar.gz
(2.25 KB)
📄
sched.pyo.tar
(6.5 KB)
📄
sched_autogroup_enabled.tar
(2 KB)
📄
sched_autogroup_enabled.tar.gz
(123 B)
📄
sched_domain.tar
(385 KB)
📄
sched_domain.tar.gz
(4.84 KB)
📄
sched_domain.zip
(62.42 KB)
📄
sched_energy_aware.tar
(2 KB)
📄
sched_energy_aware.tar.gz
(119 B)
📄
sched_latency_ns.tar
(2 KB)
📄
sched_latency_ns.tar.gz
(121 B)
📄
sched_migration_cost_ns.tar
(2 KB)
📄
sched_migration_cost_ns.tar.gz
(126 B)
📄
sched_rt_period_us.tar
(2 KB)
📄
sched_rt_period_us.tar.gz
(122 B)
📄
sched_rt_runtime_us.tar
(2 KB)
📄
sched_rt_runtime_us.tar.gz
(123 B)
📄
schlix.sql.sql.tar.gz
(165.79 KB)
📄
schlix.sql.tar
(678.5 KB)
📄
schlix.tar
(14.02 MB)
📄
schlix.tar.gz
(12.65 MB)
📄
schlix.zip
(13.99 MB)
📄
schriter.h.h.tar.gz
(1.77 KB)
📄
schriter.h.tar
(8 KB)
📄
scl.attr.attr.tar.gz
(230 B)
📄
scl.attr.tar
(3 KB)
📄
scl.tar
(76 KB)
📄
scl.tar.gz
(1.01 KB)
📄
scl.zip
(6.23 KB)
📄
scl_enabled.tar
(2 KB)
📄
scl_enabled.tar.gz
(275 B)
📄
scl_source.tar
(3.5 KB)
📄
scl_source.tar.gz
(849 B)
📄
sclbuild.attr.attr.tar.gz
(230 B)
📄
sclbuild.attr.tar
(2 KB)
📄
scldeps.sh.sh.tar.gz
(280 B)
📄
scldeps.sh.tar
(3 KB)
📄
scope.h.h.tar.gz
(3.87 KB)
📄
scope.h.tar
(13.5 KB)
📄
scope.rb.rb.tar.gz
(509 B)
📄
scope.rb.tar
(4 KB)
📄
scp.img.img.tar.gz
(317.12 KB)
📄
scp.img.tar
(622.5 KB)
📄
scp.tar
(104.5 KB)
📄
scp.tar.gz
(49.5 KB)
📄
screen.conf.conf.tar.gz
(153 B)
📄
screen.conf.tar
(3 KB)
📄
screen.tar
(484 KB)
📄
screen.tar.gz
(251.8 KB)
📄
screenrc.tar
(8.5 KB)
📄
screenrc.tar.gz
(2.91 KB)
📄
script.pyc.pyc.tar.gz
(769 B)
📄
script.pyc.tar
(3 KB)
📄
script.pyo.pyo.tar.gz
(771 B)
📄
script.pyo.tar
(3 KB)
📄
script.sh.sh.tar.gz
(249 B)
📄
script.sh.tar
(2 KB)
📄
script.tar
(38.5 KB)
📄
script.tar.gz
(15.1 KB)
📄
script_helper.py.py.tar.gz
(147 B)
📄
script_helper.py.tar
(2 KB)
📄
scripts.tar
(1.37 MB)
📄
scripts.tar.gz
(9.56 KB)
📄
scripts.zip
(1.2 MB)
📄
scrolledtext.py.py.tar.gz
(940 B)
📄
scrolledtext.py.tar
(3.5 KB)
📄
scsi.h.h.tar.gz
(2.46 KB)
📄
scsi.h.tar
(8.5 KB)
📄
scsi.mod.mod.tar.gz
(2.9 KB)
📄
scsi.mod.tar
(8.5 KB)
📄
scsi.tar
(141.5 KB)
📄
scsi.tar.gz
(2.34 KB)
📄
scsi.zip
(125.4 KB)
📄
scsi_bsg_fc.h.h.tar.gz
(2.9 KB)
📄
scsi_bsg_fc.h.tar
(10.5 KB)
📄
scsi_bsg_mpi3mr.h.h.tar.gz
(3.88 KB)
📄
scsi_bsg_mpi3mr.h.tar
(17 KB)
📄
scsi_id.tar
(110 KB)
📄
scsi_id.tar.gz
(21.97 KB)
📄
scsi_ioctl.h.h.tar.gz
(768 B)
📄
scsi_ioctl.h.tar
(3 KB)
📄
scsi_netlink.h.h.tar.gz
(1.68 KB)
📄
scsi_netlink.h.tar
(5.5 KB)
📄
scsi_netlink_fc.h.h.tar.gz
(1.12 KB)
📄
scsi_netlink_fc.h.tar
(3.5 KB)
📄
sd7220.fw.fw.tar.gz
(5.05 KB)
📄
sd7220.fw.tar
(9.5 KB)
📄
sd8385.bin.bin.tar.gz
(65.87 KB)
📄
sd8385.bin.tar
(96 KB)
📄
sd8385_helper.bin.bin.tar.gz
(1.53 KB)
📄
sd8385_helper.bin.tar
(4 KB)
📄
sd8682.bin.bin.tar.gz
(110.72 KB)
📄
sd8682.bin.tar
(153.5 KB)
📄
sd8682_helper.bin.bin.tar.gz
(1.9 KB)
📄
sd8682_helper.bin.tar
(4.5 KB)
📄
sd8688.bin.bin.tar.gz
(183.49 KB)
📄
sd8688.bin.tar
(509 KB)
📄
sd8688_helper.bin.bin.tar.gz
(1.9 KB)
📄
sd8688_helper.bin.tar
(8 KB)
📄
sd8797_uapsta.bin.bin.tar.gz
(367.61 KB)
📄
sd8797_uapsta.bin.tar
(523 KB)
📄
sd8801_uapsta.bin.bin.tar.gz
(182.12 KB)
📄
sd8801_uapsta.bin.tar
(251.5 KB)
📄
sd8887_uapsta.bin.bin.tar.gz
(428.18 KB)
📄
sd8887_uapsta.bin.tar
(604 KB)
📄
sd8897_uapsta.bin.bin.tar.gz
(498.76 KB)
📄
sd8897_uapsta.bin.tar
(702 KB)
📄
sd_init1.bin.bin.tar.gz
(973 B)
📄
sd_init1.bin.tar
(3.5 KB)
📄
sd_init2.bin.bin.tar.gz
(1021 B)
📄
sd_init2.bin.tar
(3.5 KB)
📄
sda1-8.tar
(2 KB)
📄
sda1-8.tar.gz
(264 B)
📄
sda1-8.zip
(518 B)
📄
sda1.tar
(5 KB)
📄
sda1.tar.gz
(725 B)
📄
sda1.zip
(1.91 KB)
📄
sda2-8.tar
(2 KB)
📄
sda2-8.tar.gz
(273 B)
📄
sda2-8.zip
(530 B)
📄
sda2.tar
(93 KB)
📄
sda2.tar.gz
(15.25 KB)
📄
sda2.zip
(90.14 KB)
📄
sda3-8.tar
(2 KB)
📄
sda3-8.tar.gz
(273 B)
📄
sda3-8.zip
(530 B)
📄
sda3.tar
(48.5 KB)
📄
sda3.tar.gz
(7.68 KB)
📄
sda3.zip
(45.61 KB)
📄
sda5-8.tar
(2 KB)
📄
sda5-8.tar.gz
(273 B)
📄
sda5-8.zip
(529 B)
📄
sda5.tar
(21.5 KB)
📄
sda5.tar.gz
(1.81 KB)
📄
sda5.zip
(18.87 KB)
📄
sda7-8.tar
(2 KB)
📄
sda7-8.tar.gz
(270 B)
📄
sda7-8.zip
(531 B)
📄
sda7.tar
(497 KB)
📄
sda7.tar.gz
(104 KB)
📄
sda7.zip
(494.05 KB)
📄
sdb1-8.tar
(2 KB)
📄
sdb1-8.tar.gz
(278 B)
📄
sdb1-8.zip
(533 B)
📄
sdb1.tar
(8.53 MB)
📄
sdb1.tar.gz
(1.74 MB)
📄
sdb1.zip
(8.52 MB)
📄
sdbm.so.so.tar.gz
(13.95 KB)
📄
sdbm.so.tar
(34 KB)
📄
sdca.tar
(32 KB)
📄
sdca.tar.gz
(7.77 KB)
📄
sdca.zip
(22.64 KB)
📄
sdiff.tar
(107 KB)
📄
sdiff.tar.gz
(26.31 KB)
📄
sdma-imx6q.bin.bin.tar.gz
(1.8 KB)
📄
sdma-imx6q.bin.tar
(4.5 KB)
📄
sdma-imx7d.bin.bin.tar.gz
(1.88 KB)
📄
sdma-imx7d.bin.tar
(5 KB)
📄
sdma.tar
(8.5 KB)
📄
sdma.tar.gz
(2.09 KB)
📄
sdma.zip
(6.32 KB)
📄
sdma_4_4_2.bin.bin.tar.gz
(11.67 KB)
📄
sdma_4_4_2.bin.tar
(35 KB)
📄
sdma_4_4_4.bin.bin.tar.gz
(11.72 KB)
📄
sdma_4_4_4.bin.tar
(35 KB)
📄
sdma_4_4_5.bin.bin.tar.gz
(11.66 KB)
📄
sdma_4_4_5.bin.tar
(35 KB)
📄
sdma_5_2_6.bin.bin.tar.gz
(11.82 KB)
📄
sdma_5_2_6.bin.tar
(35 KB)
📄
sdma_5_2_7.bin.bin.tar.gz
(11.82 KB)
📄
sdma_5_2_7.bin.tar
(35 KB)
📄
sdma_6_0_0.bin.bin.tar.gz
(12.74 KB)
📄
sdma_6_0_0.bin.tar
(35.5 KB)
📄
sdma_6_0_1.bin.bin.tar.gz
(12.57 KB)
📄
sdma_6_0_1.bin.tar
(35.5 KB)
📄
sdma_6_0_2.bin.bin.tar.gz
(12.72 KB)
📄
sdma_6_0_2.bin.tar
(35.5 KB)
📄
sdma_6_0_3.bin.bin.tar.gz
(13.1 KB)
📄
sdma_6_0_3.bin.tar
(35.5 KB)
📄
sdma_6_1_0.bin.bin.tar.gz
(12.59 KB)
📄
sdma_6_1_0.bin.tar
(35.5 KB)
📄
sdma_6_1_1.bin.bin.tar.gz
(12.74 KB)
📄
sdma_6_1_1.bin.tar
(35.5 KB)
📄
sdma_6_1_2.bin.bin.tar.gz
(12.75 KB)
📄
sdma_6_1_2.bin.tar
(35.5 KB)
📄
sdma_6_1_3.bin.bin.tar.gz
(12.74 KB)
📄
sdma_6_1_3.bin.tar
(35.5 KB)
📄
sdma_7_0_0.bin.bin.tar.gz
(18.77 KB)
📄
sdma_7_0_0.bin.tar
(48.5 KB)
📄
sdma_7_0_1.bin.bin.tar.gz
(18.27 KB)
📄
sdma_7_0_1.bin.tar
(47.5 KB)
📄
sdsd8977_combo_v2.bin.bin.tar.gz
(410.7 KB)
📄
sdsd8977_combo_v2.bin.tar
(575 KB)
📄
sdsd8997_combo_v4.bin.bin.tar.gz
(428.35 KB)
📄
sdsd8997_combo_v4.bin.tar
(610.5 KB)
📄
sdt-config.h.h.tar.gz
(280 B)
📄
sdt-config.h.tar
(2 KB)
📄
sdt.h.h.tar.gz
(5.78 KB)
📄
sdt.h.tar
(23.5 KB)
📄
sdx35.tar
(1.3 MB)
📄
sdx35.tar.gz
(646.48 KB)
📄
sdx35.zip
(1.3 MB)
📄
sdx61.tar
(649.5 KB)
📄
sdx61.tar.gz
(306.17 KB)
📄
sdx61.zip
(648.19 KB)
📄
search.h.h.tar.gz
(2.11 KB)
📄
search.h.tar
(7 KB)
📄
search.mod.mod.tar.gz
(1.7 KB)
📄
search.mod.tar
(11 KB)
📄
search.php.php.tar.gz
(2.78 KB)
📄
search.php.tar
(36.5 KB)
📄
search_fs_file.mod.mod.tar.gz
(1.88 KB)
📄
search_fs_file.mod.tar
(5.5 KB)
📄
search_fs_uuid.mod.mod.tar.gz
(1.99 KB)
📄
search_fs_uuid.mod.tar
(5.5 KB)
📄
search_label.mod.mod.tar.gz
(1.89 KB)
📄
search_label.mod.tar
(5.5 KB)
📄
seccomp.tar
(3 KB)
📄
seccomp.tar.gz
(169 B)
📄
seccomp.zip
(398 B)
📄
secrets.py.py.tar.gz
(965 B)
📄
secrets.py.tar
(6 KB)
📄
secure.php.php.tar.gz
(955 B)
📄
secure.php.tar
(3.5 KB)
📄
secure_redirects.tar
(3 KB)
📄
secure_redirects.tar.gz
(125 B)
📄
security.h.h.tar.gz
(911 B)
📄
security.h.tar
(4.5 KB)
📄
security.html.html.tar.gz
(3.6 KB)
📄
security.html.tar
(12.5 KB)
📄
security.php.php.tar.gz
(624 B)
📄
security.php.tar
(4 KB)
📄
security.tar
(1.95 MB)
📄
security.tar.gz
(760.23 KB)
📄
security.yaml.tar
(2 KB)
📄
security.yaml.yaml.tar.gz
(130 B)
📄
security.zip
(1.91 MB)
📄
sed.tar
(117 KB)
📄
sed.tar.gz
(57.66 KB)
📄
seed.h.h.tar.gz
(1.44 KB)
📄
seed.h.tar
(5 KB)
📄
seed.png.png.tar.gz
(5.01 KB)
📄
seed.png.tar
(7 KB)
📄
seed.sql.sql.tar.gz
(4.25 KB)
📄
seed.sql.tar
(42.5 KB)
📄
seed.tar
(104.4 MB)
📄
seed.tar.gz
(99 MB)
📄
seed.zip
(104.37 MB)
📄
seg6_enabled.tar
(2 KB)
📄
seg6_enabled.tar.gz
(123 B)
📄
select.h.h.tar.gz
(1.05 KB)
📄
select.h.tar
(9 KB)
📄
select.ph.ph.tar.gz
(670 B)
📄
select.ph.tar
(6 KB)
📄
select2.h.h.tar.gz
(859 B)
📄
select2.h.tar
(3 KB)
📄
select2.ph.ph.tar.gz
(402 B)
📄
select2.ph.tar
(2 KB)
📄
selector.etc.tar
(1.5 KB)
📄
selector.etc.tar.gz
(81 B)
📄
selector.etc.zip
(148 B)
📄
selector.tar
(2.5 KB)
📄
selector.tar.gz
(115 B)
📄
selector.zip
(388 B)
📄
selector_events.py.py.tar.gz
(8.34 KB)
📄
selector_events.py.tar
(81.5 KB)
📄
selectorctl.tar
(9.5 KB)
📄
selectorctl.tar.gz
(2.36 KB)
📄
selectors.py.py.tar.gz
(3.93 KB)
📄
selectors.py.tar
(39.5 KB)
📄
selfoss.tar
(265 KB)
📄
selfoss.tar.gz
(162.54 KB)
📄
selfoss.zip
(238.17 KB)
📄
selinux-autorelabel.target.tar
(2 KB)
📄
selinux-autorelabel.target.target.tar.gz
(240 B)
📄
selinux-policy.conf.conf.tar.gz
(199 B)
📄
selinux-policy.conf.tar
(2 KB)
📄
selinux.so.so.tar.gz
(4.42 KB)
📄
selinux.so.tar
(13.5 KB)
📄
selinux.tar
(137 KB)
📄
selinux.tar.gz
(23.62 KB)
📄
selinux.zip
(130.55 KB)
📄
sem.h.h.tar.gz
(1.26 KB)
📄
sem.h.tar
(7 KB)
📄
sem.tar
(3 KB)
📄
sem.tar.gz
(176 B)
📄
sem_next_id.tar
(2 KB)
📄
sem_next_id.tar.gz
(113 B)
📄
semaphore.h.h.tar.gz
(1.12 KB)
📄
semaphore.h.tar
(6 KB)
📄
sembuf.h.h.tar.gz
(589 B)
📄
sembuf.h.tar
(3 KB)
📄
send.tar
(2 KB)
📄
send.tar.gz
(326 B)
📄
send_redirects.tar
(4 KB)
📄
send_redirects.tar.gz
(126 B)
📄
sendfile.h.h.tar.gz
(986 B)
📄
sendfile.h.tar
(3.5 KB)
📄
sendkey.mod.mod.tar.gz
(3.32 KB)
📄
sendkey.mod.tar
(9.5 KB)
📄
sendmail.tar
(7 KB)
📄
sendmail.tar.gz
(721 B)
📄
sentrifugo.tar
(154 KB)
📄
sentrifugo.tar.gz
(77.28 KB)
📄
sentrifugo.zip
(130.73 KB)
📄
seo.png.png.tar.gz
(21.04 KB)
📄
seo.png.tar
(22.5 KB)
📄
seo.sql.sql.tar.gz
(693.28 KB)
📄
seo.sql.tar
(3.38 MB)
📄
seo.tar
(30.16 MB)
📄
seo.tar.gz
(26.12 MB)
📄
seo.zip
(30.14 MB)
📄
sepol.h.h.tar.gz
(380 B)
📄
sepol.h.tar
(2.5 KB)
📄
sepol.tar
(160.5 KB)
📄
sepol.tar.gz
(28.33 KB)
📄
sepol.zip
(130.96 KB)
📄
seq.tar
(55 KB)
📄
seq.tar.gz
(24.02 KB)
📄
ser_users.php.php.tar.gz
(149 B)
📄
ser_users.php.tar
(2 KB)
📄
serial.mod.mod.tar.gz
(4.19 KB)
📄
serial.mod.tar
(22 KB)
📄
serve.pyc.pyc.tar.gz
(1.02 KB)
📄
serve.pyc.tar
(3.5 KB)
📄
serve.pyo.pyo.tar.gz
(1.02 KB)
📄
serve.pyo.tar
(3.5 KB)
📄
server.go.go.tar.gz
(15.44 KB)
📄
server.go.tar
(50 KB)
📄
server.py.py.tar.gz
(13.39 KB)
📄
server.py.tar
(92.5 KB)
📄
server.tar
(6.51 MB)
📄
server.tar.gz
(10.29 KB)
📄
server.zip
(6.23 MB)
📄
server_audit.so.so.tar.gz
(28.34 KB)
📄
server_audit.so.tar
(64.5 KB)
📄
server_sort.so.so.tar.gz
(5.76 KB)
📄
server_sort.so.tar
(17.5 KB)
📄
service.tar
(53 KB)
📄
service.tar.gz
(11.27 KB)
📄
service.zip
(44.79 KB)
📄
service_json.h.h.tar.gz
(1.41 KB)
📄
service_json.h.tar
(6 KB)
📄
service_sha1.h.h.tar.gz
(991 B)
📄
service_sha1.h.tar
(4 KB)
📄
service_sha2.h.h.tar.gz
(1.26 KB)
📄
service_sha2.h.tar
(7 KB)
📄
services.tar
(862 KB)
📄
services.tar.gz
(18.28 KB)
📄
services.zip
(82.85 KB)
📄
sess_0ac3c581cd3fcb9f13b4f763b8cb5183.tar
(5.5 KB)
📄
sess_0ac3c581cd3fcb9f13b4f763b8cb5183.tar.gz
(1.57 KB)
📄
sess_5040e636d8e51625dede03ecec4983d9.tar
(13 KB)
📄
sess_5040e636d8e51625dede03ecec4983d9.tar.gz
(3.78 KB)
📄
sess_da8b83eb167736fd33992abe1a8de059.tar
(10 KB)
📄
sess_da8b83eb167736fd33992abe1a8de059.tar.gz
(2.41 KB)
📄
sess_f3c99e0d5472aaf610e57f6cb3adc59e.tar
(4.5 KB)
📄
sess_f3c99e0d5472aaf610e57f6cb3adc59e.tar.gz
(1.73 KB)
📄
session.go.go.tar.gz
(10.38 KB)
📄
session.go.tar
(26 KB)
📄
session.inc.inc.tar.gz
(6.29 KB)
📄
session.inc.tar
(20 KB)
📄
session.php.php.tar.gz
(262 B)
📄
session.php.tar
(2 KB)
📄
session.tar
(6 KB)
📄
session.tar.gz
(135 B)
📄
session.zip
(421 B)
📄
setjmp.h.h.tar.gz
(1.48 KB)
📄
setjmp.h.tar
(7.5 KB)
📄
setjmp.mod.mod.tar.gz
(393 B)
📄
setjmp.mod.tar
(4 KB)
📄
setjmp2.h.h.tar.gz
(817 B)
📄
setjmp2.h.tar
(3.5 KB)
📄
setjmp_test.mod.mod.tar.gz
(845 B)
📄
setjmp_test.mod.tar
(3.5 KB)
📄
setobject.h.h.tar.gz
(1.26 KB)
📄
setobject.h.tar
(5 KB)
📄
setpci.mod.mod.tar.gz
(2.89 KB)
📄
setpci.mod.tar
(16 KB)
📄
sets.py.py.tar.gz
(4.94 KB)
📄
sets.py.tar
(20.5 KB)
📄
sets.pyc.pyc.tar.gz
(5.31 KB)
📄
sets.pyc.tar
(18 KB)
📄
sets.pyo.pyo.tar.gz
(5.31 KB)
📄
sets.pyo.tar
(18 KB)
📄
setsid.tar
(18 KB)
📄
setsid.tar.gz
(5.38 KB)
📄
setterm.tar
(47 KB)
📄
setterm.tar.gz
(19.24 KB)
📄
settings-defaults.php.php.tar.gz
(652 B)
📄
settings-defaults.php.tar
(3 KB)
📄
settings.inc.php.inc.php.tar.gz
(374 B)
📄
settings.inc.php.tar
(5 KB)
📄
settings.ini.ini.tar.gz
(2.37 KB)
📄
settings.ini.tar
(7.5 KB)
📄
settings.json.json.tar.gz
(212 B)
📄
settings.json.tar
(2 KB)
📄
settings.php.php.tar.gz
(2.77 KB)
📄
settings.php.tar
(106.5 KB)
📄
settings.tar
(46 KB)
📄
settings.tar.gz
(17.66 KB)
📄
settings.xml.tar
(31.5 KB)
📄
settings.xml.xml.tar.gz
(4.53 KB)
📄
settings.zip
(43.05 KB)
📄
setup.h.h.tar.gz
(245 B)
📄
setup.h.tar
(3 KB)
📄
setup.php.php.tar.gz
(660 B)
📄
setup.php.tar
(3.5 KB)
📄
setup.pyc.pyc.tar.gz
(444 B)
📄
setup.pyc.tar
(2.5 KB)
📄
setup.pyo.pyo.tar.gz
(445 B)
📄
setup.pyo.tar
(2.5 KB)
📄
sfnt_info.h.h.tar.gz
(2.36 KB)
📄
sfnt_info.h.tar
(8.5 KB)
📄
sfs.mod.mod.tar.gz
(3.51 KB)
📄
sfs.mod.tar
(17 KB)
📄
sftp-server.tar
(117 KB)
📄
sftp-server.tar.gz
(53.97 KB)
📄
sftp.tar
(161.5 KB)
📄
sftp.tar.gz
(75.76 KB)
📄
sg.h.h.tar.gz
(4.6 KB)
📄
sg.h.tar
(13 KB)
📄
sg.tar
(8 KB)
📄
sg.tar.gz
(398 B)
📄
sg.zip
(1.18 KB)
📄
sgml-filter.info.info.tar.gz
(375 B)
📄
sgml-filter.info.tar
(2 KB)
📄
sgml.amf.amf.tar.gz
(274 B)
📄
sgml.amf.tar
(2 KB)
📄
sgmllib.py.py.tar.gz
(4.62 KB)
📄
sgmllib.py.tar
(19 KB)
📄
sgmllib.pyc.pyc.tar.gz
(5.71 KB)
📄
sgmllib.pyc.tar
(17 KB)
📄
sgmllib.pyo.pyo.tar.gz
(5.71 KB)
📄
sgmllib.pyo.tar
(17 KB)
📄
sgtty.h.h.tar.gz
(798 B)
📄
sgtty.h.tar
(3 KB)
📄
sgx.h.h.tar.gz
(2.71 KB)
📄
sgx.h.tar
(10 KB)
📄
sh-linux.tar
(4.5 KB)
📄
sh-linux.tar.gz
(1.18 KB)
📄
sh-linux.zip
(3.09 KB)
📄
sh.tar
(1.1 MB)
📄
sh.tar.gz
(547.7 KB)
📄
sh3-linux.tar
(4.5 KB)
📄
sh3-linux.tar.gz
(1.18 KB)
📄
sh3-linux.zip
(3.09 KB)
📄
sh4-linux.tar
(4.5 KB)
📄
sh4-linux.tar.gz
(1.19 KB)
📄
sh4-linux.zip
(3.1 KB)
📄
sh4a-linux.tar
(4.5 KB)
📄
sh4a-linux.tar.gz
(1.19 KB)
📄
sh4a-linux.zip
(3.1 KB)
📄
sha.h.h.tar.gz
(1.19 KB)
📄
sha.h.tar
(5.5 KB)
📄
sha.py.py.tar.gz
(354 B)
📄
sha.py.tar
(2 KB)
📄
sha.pyc.pyc.tar.gz
(370 B)
📄
sha.pyc.tar
(2 KB)
📄
sha.pyo.pyo.tar.gz
(368 B)
📄
sha.pyo.tar
(2 KB)
📄
sha1.so.so.tar.gz
(3.11 KB)
📄
sha1.so.tar
(9 KB)
📄
sha1hmac.hmac.hmac.tar.gz
(189 B)
📄
sha1hmac.hmac.tar
(2 KB)
📄
sha1sum.tar
(47.5 KB)
📄
sha1sum.tar.gz
(20.17 KB)
📄
sha2.so.so.tar.gz
(3.45 KB)
📄
sha2.so.tar
(13 KB)
📄
sha224hmac.hmac.hmac.tar.gz
(191 B)
📄
sha224hmac.hmac.tar
(2 KB)
📄
sha224sum.tar
(47.5 KB)
📄
sha224sum.tar.gz
(20.41 KB)
📄
sha256.php.php.tar.gz
(5.33 KB)
📄
sha256.php.tar
(21 KB)
📄
sha256hmac.hmac.hmac.tar.gz
(191 B)
📄
sha256hmac.hmac.tar
(2 KB)
📄
sha256sum.tar
(47.5 KB)
📄
sha256sum.tar.gz
(20.39 KB)
📄
sha384hmac.hmac.hmac.tar.gz
(191 B)
📄
sha384hmac.hmac.tar
(2 KB)
📄
sha384sum.tar
(47.5 KB)
📄
sha384sum.tar.gz
(20.48 KB)
📄
sha512hmac.hmac.hmac.tar.gz
(191 B)
📄
sha512hmac.hmac.tar
(2 KB)
📄
sha512sum.tar
(47.5 KB)
📄
sha512sum.tar.gz
(20.47 KB)
📄
shadow.h.h.tar.gz
(1.64 KB)
📄
shadow.h.tar
(7 KB)
📄
shape.h.h.tar.gz
(2.58 KB)
📄
shape.h.tar
(22 KB)
📄
share.tar
(127.23 MB)
📄
share.tar.gz
(1.87 MB)
📄
share.zip
(115.36 MB)
📄
shared_media.tar
(2 KB)
📄
shared_media.tar.gz
(122 B)
📄
sharedctypes.py.py.tar.gz
(2.52 KB)
📄
sharedctypes.py.tar
(9.5 KB)
📄
sharedimage.tar
(45 KB)
📄
sharedimage.tar.gz
(16.32 KB)
📄
sharedimage.zip
(41.83 KB)
📄
shell.tar
(42 KB)
📄
shell.tar.gz
(8.64 KB)
📄
shell.zip
(36.31 KB)
📄
shellwords.rb.rb.tar.gz
(2.64 KB)
📄
shellwords.rb.tar
(27 KB)
📄
shelve.py.py.tar.gz
(2.74 KB)
📄
shelve.py.tar
(27.5 KB)
📄
shelve.pyc.pyc.tar.gz
(3.78 KB)
📄
shelve.pyc.tar
(12 KB)
📄
shelve.pyo.pyo.tar.gz
(3.78 KB)
📄
shelve.pyo.tar
(12 KB)
📄
shield.svg.svg.tar.gz
(943 B)
📄
shield.svg.tar
(3 KB)
📄
shift_jis.so.so.tar.gz
(5.47 KB)
📄
shift_jis.so.tar
(17.5 KB)
📄
shift_test.mod.mod.tar.gz
(1.46 KB)
📄
shift_test.mod.tar
(5 KB)
📄
shlex.py.py.tar.gz
(3.17 KB)
📄
shlex.py.tar
(40 KB)
📄
shlex.pyc.pyc.tar.gz
(3.33 KB)
📄
shlex.pyc.tar
(9 KB)
📄
shlex.pyo.pyo.tar.gz
(3.33 KB)
📄
shlex.pyo.tar
(9 KB)
📄
shm.h.h.tar.gz
(1.51 KB)
📄
shm.h.tar
(25.5 KB)
📄
shm.tar
(10.5 KB)
📄
shm.tar.gz
(1.28 KB)
📄
shm_next_id.tar
(2 KB)
📄
shm_next_id.tar.gz
(113 B)
📄
shm_rmid_forced.tar
(2 KB)
📄
shm_rmid_forced.tar.gz
(116 B)
📄
shmall.tar
(2 KB)
📄
shmall.tar.gz
(124 B)
📄
shmbuf.h.h.tar.gz
(631 B)
📄
shmbuf.h.tar
(3 KB)
📄
shmmax.tar
(2 KB)
📄
shmmax.tar.gz
(125 B)
📄
shmmni.tar
(2 KB)
📄
shmmni.tar.gz
(110 B)
📄
shmparam.h.h.tar.gz
(268 B)
📄
shmparam.h.tar
(2 KB)
📄
shop1.json.json.tar.gz
(1.1 KB)
📄
shop1.json.tar
(8.5 KB)
📄
shopsite.tar
(135 KB)
📄
shopsite.tar.gz
(83.21 KB)
📄
shopsite.zip
(120.53 KB)
📄
shopware.png.png.tar.gz
(7.3 KB)
📄
shopware.png.tar
(9 KB)
📄
shopware.tar
(76.2 MB)
📄
shopware.tar.gz
(66.37 MB)
📄
shopware.zip
(76.17 MB)
📄
shred.tar
(63.5 KB)
📄
shred.tar.gz
(29.85 KB)
📄
shuf.tar
(60 KB)
📄
shuf.tar.gz
(27.8 KB)
📄
shutdown.target.tar
(2 KB)
📄
shutdown.target.target.tar.gz
(394 B)
📄
shutil.py.py.tar.gz
(13.66 KB)
📄
shutil.py.tar
(113 KB)
📄
shutil.pyc.pyc.tar.gz
(8.07 KB)
📄
shutil.pyc.tar
(20.5 KB)
📄
shutil.pyo.pyo.tar.gz
(8.07 KB)
📄
shutil.pyo.tar
(20.5 KB)
📄
si58_mc.bin.bin.tar.gz
(13 KB)
📄
si58_mc.bin.tar
(66 KB)
📄
sidu.png.png.tar.gz
(5.59 KB)
📄
sidu.png.tar
(7.5 KB)
📄
sidu.tar
(101 KB)
📄
sidu.tar.gz
(46.88 KB)
📄
sidu.zip
(83.59 KB)
📄
sienna_cichlid_ce.bin.bin.tar.gz
(5.21 KB)
📄
sienna_cichlid_ce.bin.tar
(259 KB)
📄
sienna_cichlid_me.bin.bin.tar.gz
(9.57 KB)
📄
sienna_cichlid_me.bin.tar
(259 KB)
📄
sienna_cichlid_mec.bin.bin.tar.gz
(41.78 KB)
📄
sienna_cichlid_mec.bin.tar
(263.5 KB)
📄
sienna_cichlid_pfp.bin.bin.tar.gz
(16.54 KB)
📄
sienna_cichlid_pfp.bin.tar
(259 KB)
📄
sienna_cichlid_rlc.bin.bin.tar.gz
(52.18 KB)
📄
sienna_cichlid_rlc.bin.tar
(131.5 KB)
📄
sienna_cichlid_smc.bin.bin.tar.gz
(116.42 KB)
📄
sienna_cichlid_smc.bin.tar
(243.5 KB)
📄
sienna_cichlid_sos.bin.bin.tar.gz
(132.33 KB)
📄
sienna_cichlid_sos.bin.tar
(224 KB)
📄
sienna_cichlid_ta.bin.bin.tar.gz
(122.91 KB)
📄
sienna_cichlid_ta.bin.tar
(375.5 KB)
📄
sienna_cichlid_vcn.bin.bin.tar.gz
(406.83 KB)
📄
sienna_cichlid_vcn.bin.tar
(568.5 KB)
📄
sigaction.h.h.tar.gz
(1.38 KB)
📄
sigaction.h.tar
(4.5 KB)
📄
sigcontext.h.h.tar.gz
(3.38 KB)
📄
sigcontext.h.tar
(11 KB)
📄
sigcontext.ph.ph.tar.gz
(462 B)
📄
sigcontext.ph.tar
(2.5 KB)
📄
sigcontext32.h.h.tar.gz
(266 B)
📄
sigcontext32.h.tar
(2 KB)
📄
sigevent-consts.h.h.tar.gz
(848 B)
📄
sigevent-consts.h.tar
(3 KB)
📄
siginfo-arch.h.h.tar.gz
(518 B)
📄
siginfo-arch.h.tar
(2.5 KB)
📄
siginfo-consts-arch.ph.ph.tar.gz
(245 B)
📄
siginfo-consts-arch.ph.tar
(2 KB)
📄
siginfo-consts.h.h.tar.gz
(2.11 KB)
📄
siginfo-consts.h.tar
(7.5 KB)
📄
siginfo-consts.ph.ph.tar.gz
(901 B)
📄
siginfo-consts.ph.tar
(5.5 KB)
📄
siginfo.h.h.tar.gz
(3.9 KB)
📄
siginfo.h.tar
(15 KB)
📄
siginfo_t.h.h.tar.gz
(1.34 KB)
📄
siginfo_t.h.tar
(5.5 KB)
📄
sign_on.php.php.tar.gz
(1.39 KB)
📄
sign_on.php.tar
(90 KB)
📄
sign_on_func.php.php.tar.gz
(847 B)
📄
sign_on_func.php.tar
(4 KB)
📄
signal.h.h.tar.gz
(3.64 KB)
📄
signal.h.tar
(18 KB)
📄
signal.ph.ph.tar.gz
(843 B)
📄
signal.ph.tar
(5 KB)
📄
signal.py.py.tar.gz
(736 B)
📄
signal.py.tar
(7 KB)
📄
signalfd.h.h.tar.gz
(684 B)
📄
signalfd.h.tar
(5.5 KB)
📄
signature_test.mod.mod.tar.gz
(4.62 KB)
📄
signature_test.mod.tar
(8 KB)
📄
signum-generic.h.h.tar.gz
(1.99 KB)
📄
signum-generic.h.tar
(6 KB)
📄
signum-generic.ph.ph.tar.gz
(754 B)
📄
signum-generic.ph.tar
(4.5 KB)
📄
signum.h.h.tar.gz
(905 B)
📄
signum.h.tar
(3.5 KB)
📄
signum.ph.ph.tar.gz
(545 B)
📄
signum.ph.tar
(3 KB)
📄
sigpwr.target.tar
(3 KB)
📄
sigpwr.target.target.tar.gz
(369 B)
📄
sigs.tar
(199.65 MB)
📄
sigs.tar.gz
(38.87 MB)
📄
sigs.zip
(199.62 MB)
📄
sigset_t.h.h.tar.gz
(219 B)
📄
sigset_t.h.tar
(2 KB)
📄
sigstack.ph.ph.tar.gz
(349 B)
📄
sigstack.ph.tar
(2 KB)
📄
sigthread.h.h.tar.gz
(955 B)
📄
sigthread.h.tar
(3.5 KB)
📄
sigval_t.h.h.tar.gz
(407 B)
📄
sigval_t.h.tar
(2.5 KB)
📄
simple.py.py.tar.gz
(148 B)
📄
simple.py.tar
(2 KB)
📄
simpledialog.py.py.tar.gz
(3.31 KB)
📄
simpledialog.py.tar
(13 KB)
📄
simpletz.h.h.tar.gz
(7.44 KB)
📄
simpletz.h.tar
(47 KB)
📄
sip.xml.tar
(4 KB)
📄
sip.xml.xml.tar.gz
(383 B)
📄
sips.xml.tar
(2 KB)
📄
sips.xml.xml.tar.gz
(281 B)
📄
site-inc.tar
(27.58 MB)
📄
site-inc.tar.gz
(6.22 MB)
📄
site-inc.zip
(27.05 MB)
📄
site-packages.tar
(76.61 MB)
📄
site-packages.tar.gz
(3.8 MB)
📄
site-packages.zip
(73.26 MB)
📄
site.php.php.tar.gz
(927 B)
📄
site.php.tar
(7.5 KB)
📄
site.py.py.tar.gz
(6.42 KB)
📄
site.py.tar
(66 KB)
📄
site.pyc.pyc.tar.gz
(8.67 KB)
📄
site.pyc.tar
(22 KB)
📄
site.pyo.pyo.tar.gz
(8.67 KB)
📄
site.pyo.tar
(22 KB)
📄
site.tar
(6.5 KB)
📄
site.tar.gz
(1.37 KB)
📄
site.zip
(4.83 KB)
📄
site_conf_.php.php.tar.gz
(267 B)
📄
site_conf_.php.tar
(2 KB)
📄
site_publisher.tar
(3.5 KB)
📄
site_publisher.tar.gz
(1.06 KB)
📄
site_publisher.zip
(1.72 KB)
📄
sitecake.tar
(59.5 KB)
📄
sitecake.tar.gz
(32.3 KB)
📄
sitecake.zip
(49.79 KB)
📄
sitemagic.tar
(149.5 KB)
📄
sitemagic.tar.gz
(71.52 KB)
📄
sitemagic.zip
(125.95 KB)
📄
sitemap.xml.tar
(2 KB)
📄
sitemap.xml.xml.tar.gz
(268 B)
📄
sites.tar
(1011.76 MB)
📄
sites.tar.gz
(470 MB)
📄
sites.zip
(176 MB)
📄
siw-abi.h.h.tar.gz
(1.47 KB)
📄
siw-abi.h.tar
(5 KB)
📄
size.tar
(35 KB)
📄
size.tar.gz
(14.24 KB)
📄
sizzle.tar
(54 KB)
📄
sizzle.tar.gz
(32.45 KB)
📄
sizzle.zip
(43.43 KB)
📄
sk.tar
(10 KB)
📄
sk.tar.gz
(8.46 KB)
📄
sk.zip
(8.46 KB)
📄
skel.tar
(4 KB)
📄
skel.tar.gz
(440 B)
📄
skel.zip
(957 B)
📄
skill.tar
(30.5 KB)
📄
skill.tar.gz
(11.88 KB)
📄
skip_cpus.tar
(2 KB)
📄
skip_cpus.tar.gz
(109 B)
📄
skipcpio.tar
(26 KB)
📄
skipcpio.tar.gz
(3.9 KB)
📄
skl.tar
(251.5 KB)
📄
skl.tar.gz
(153 KB)
📄
skl.zip
(249.68 KB)
📄
skl_dmc_ver1.bin.bin.tar.gz
(3.32 KB)
📄
skl_dmc_ver1.bin.tar
(10.5 KB)
📄
skl_guc_32.0.3.bin.0.3.bin.tar.gz
(80.96 KB)
📄
skl_guc_32.0.3.bin.tar
(173 KB)
📄
skl_guc_33.0.0.bin.0.0.bin.tar.gz
(83.7 KB)
📄
skl_guc_33.0.0.bin.tar
(179.5 KB)
📄
skl_guc_49.0.1.bin.0.1.bin.tar.gz
(85.36 KB)
📄
skl_guc_49.0.1.bin.tar
(193.5 KB)
📄
skl_guc_62.0.0.bin.0.0.bin.tar.gz
(90.5 KB)
📄
skl_guc_62.0.0.bin.tar
(196.5 KB)
📄
skl_guc_69.0.3.bin.0.3.bin.tar.gz
(101.47 KB)
📄
skl_guc_69.0.3.bin.tar
(213.5 KB)
📄
skl_guc_70.1.1.bin.1.1.bin.tar.gz
(92.78 KB)
📄
skl_guc_70.1.1.bin.tar
(203 KB)
📄
skl_guc_ver1.bin.bin.tar.gz
(41.62 KB)
📄
skl_guc_ver1.bin.tar
(109 KB)
📄
skl_guc_ver4.bin.bin.tar.gz
(59.92 KB)
📄
skl_guc_ver4.bin.tar
(127 KB)
📄
skl_guc_ver6.bin.bin.tar.gz
(61.57 KB)
📄
skl_guc_ver6.bin.tar
(127.5 KB)
📄
skl_guc_ver6_1.bin.bin.tar.gz
(61.57 KB)
📄
skl_guc_ver6_1.bin.tar
(127.5 KB)
📄
skl_huc_2.0.0.bin.0.0.bin.tar.gz
(59.31 KB)
📄
skl_huc_2.0.0.bin.tar
(135 KB)
📄
slabtop.tar
(22.5 KB)
📄
slabtop.tar.gz
(9.11 KB)
📄
slack.e82882b2.svg.e82882b2.svg.tar.gz
(1.02 KB)
📄
slack.e82882b2.svg.tar
(4 KB)
📄
slapi-plugin.h.h.tar.gz
(8.41 KB)
📄
slapi-plugin.h.tar
(39 KB)
📄
sleep.d.tar
(3.5 KB)
📄
sleep.d.tar.gz
(805 B)
📄
sleep.d.zip
(1.92 KB)
📄
sleep.mod.mod.tar.gz
(1.13 KB)
📄
sleep.mod.tar
(7 KB)
📄
sleep.tar
(39 KB)
📄
sleep.tar.gz
(16.06 KB)
📄
sleep.target.tar
(2 KB)
📄
sleep.target.target.tar.gz
(407 B)
📄
sleep_test.mod.mod.tar.gz
(1.28 KB)
📄
sleep_test.mod.tar
(4.5 KB)
📄
slib.go.go.tar.gz
(604 B)
📄
slib.go.tar
(2.5 KB)
📄
slices.target.tar
(2 KB)
📄
slices.target.target.tar.gz
(385 B)
📄
slicoss.tar
(267 KB)
📄
slicoss.tar.gz
(77.97 KB)
📄
slicoss.zip
(261.79 KB)
📄
slims.sql.sql.tar.gz
(23.37 KB)
📄
slims.sql.tar
(113 KB)
📄
slims.tar
(50.32 MB)
📄
slims.tar.gz
(48.65 MB)
📄
slims.zip
(50.29 MB)
📄
slp.xml.tar
(3 KB)
📄
slp.xml.xml.tar.gz
(292 B)
📄
sm1_vp9_mmu.bin.bin.tar.gz
(4.58 KB)
📄
sm1_vp9_mmu.bin.tar
(17.5 KB)
📄
sm3hmac.hmac.hmac.tar.gz
(190 B)
📄
sm3hmac.hmac.tar
(2 KB)
📄
sm8150.tar
(15.5 KB)
📄
sm8150.tar.gz
(3.69 KB)
📄
sm8150.zip
(14.08 KB)
📄
sm8250.tar
(27.49 MB)
📄
sm8250.tar.gz
(11.44 MB)
📄
sm8250.zip
(27.48 MB)
📄
sm8450.tar
(40.5 KB)
📄
sm8450.tar.gz
(4.77 KB)
📄
sm8450.zip
(38.59 KB)
📄
sm8550.tar
(72.5 KB)
📄
sm8550.tar.gz
(6.12 KB)
📄
sm8550.zip
(69.41 KB)
📄
sm8650.tar
(72.5 KB)
📄
sm8650.tar.gz
(6.11 KB)
📄
sm8650.zip
(69.42 KB)
📄
sm8750.tar
(22.54 MB)
📄
sm8750.tar.gz
(10.89 MB)
📄
sm8750.zip
(22.53 MB)
📄
small-logo-orange.svg.svg.tar.gz
(368 B)
📄
small-logo-orange.svg.tar
(3 KB)
📄
smartcard.target.tar
(2 KB)
📄
smartcard.target.target.tar.gz
(382 B)
📄
smartd.service.service.tar.gz
(351 B)
📄
smartd.service.tar
(2 KB)
📄
smarty.tar
(559 KB)
📄
smarty.tar.gz
(478.37 KB)
📄
smarty.zip
(548.65 KB)
📄
smf.png.png.tar.gz
(3.92 KB)
📄
smf.png.tar
(6 KB)
📄
smf.sql.sql.tar.gz
(20.01 KB)
📄
smf.sql.tar
(127 KB)
📄
smf.tar
(10.42 MB)
📄
smf.tar.gz
(9.86 MB)
📄
smf.zip
(10.37 MB)
📄
smf20.tar
(201 KB)
📄
smf20.tar.gz
(112.24 KB)
📄
smf20.zip
(178.67 KB)
📄
smp_affinity.tar
(30 KB)
📄
smp_affinity.tar.gz
(114 B)
📄
smp_affinity_list.tar
(11 KB)
📄
smp_affinity_list.tar.gz
(115 B)
📄
smpdtfmt.h.h.tar.gz
(15.36 KB)
📄
smpdtfmt.h.tar
(72.5 KB)
📄
sms1xxx-hcw-55xxx-dvbt-02.fw.fw.tar.gz
(52.16 KB)
📄
sms1xxx-hcw-55xxx-dvbt-02.fw.tar
(85.5 KB)
📄
sms1xxx-hcw-55xxx-isdbt-02.fw.fw.tar.gz
(42.2 KB)
📄
sms1xxx-hcw-55xxx-isdbt-02.fw.tar
(70.5 KB)
📄
sms1xxx-nova-a-dvbt-01.fw.fw.tar.gz
(52.16 KB)
📄
sms1xxx-nova-a-dvbt-01.fw.tar
(85.5 KB)
📄
sms1xxx-nova-b-dvbt-01.fw.fw.tar.gz
(46.75 KB)
📄
sms1xxx-nova-b-dvbt-01.fw.tar
(76.5 KB)
📄
sms1xxx-stellar-dvbt-01.fw.fw.tar.gz
(26.77 KB)
📄
sms1xxx-stellar-dvbt-01.fw.tar
(40.5 KB)
📄
smtp-submission.xml.tar
(2 KB)
📄
smtp-submission.xml.xml.tar.gz
(269 B)
📄
smtp.xml.tar
(2.5 KB)
📄
smtp.xml.xml.tar.gz
(433 B)
📄
smtpd.py.py.tar.gz
(8.43 KB)
📄
smtpd.py.tar
(89 KB)
📄
smtpd.pyc.pyc.tar.gz
(6.68 KB)
📄
smtpd.pyc.tar
(17.5 KB)
📄
smtpd.pyo.pyo.tar.gz
(6.68 KB)
📄
smtpd.pyo.tar
(17.5 KB)
📄
smtplib.py.py.tar.gz
(12.03 KB)
📄
smtplib.py.tar
(121.5 KB)
📄
smtplib.pyc.pyc.tar.gz
(11.18 KB)
📄
smtplib.pyc.tar
(31.5 KB)
📄
smtplib.pyo.pyo.tar.gz
(11.18 KB)
📄
smtplib.pyo.tar
(31.5 KB)
📄
smtps.xml.tar
(2.5 KB)
📄
smtps.xml.xml.tar.gz
(454 B)
📄
smu_13_0_0.bin.bin.tar.gz
(140.35 KB)
📄
smu_13_0_0.bin.tar
(287.5 KB)
📄
smu_13_0_0_kicker.bin.bin.tar.gz
(137.92 KB)
📄
smu_13_0_0_kicker.bin.tar
(257.5 KB)
📄
smu_13_0_10.bin.bin.tar.gz
(137.91 KB)
📄
smu_13_0_10.bin.tar
(533 KB)
📄
smu_13_0_14.bin.bin.tar.gz
(830 B)
📄
smu_13_0_14.bin.tar
(3 KB)
📄
smu_13_0_6.bin.bin.tar.gz
(2.06 KB)
📄
smu_13_0_6.bin.tar
(5.5 KB)
📄
smu_13_0_7.bin.bin.tar.gz
(120.86 KB)
📄
smu_13_0_7.bin.tar
(282 KB)
📄
smu_14_0_2.bin.bin.tar.gz
(139.62 KB)
📄
smu_14_0_2.bin.tar
(327 KB)
📄
smu_14_0_3.bin.bin.tar.gz
(140.13 KB)
📄
smu_14_0_3.bin.tar
(327 KB)
📄
smu_14_0_3_kicker.bin.bin.tar.gz
(139.25 KB)
📄
smu_14_0_3_kicker.bin.tar
(321.5 KB)
📄
snd_sst_tokens.h.h.tar.gz
(3.05 KB)
📄
snd_sst_tokens.h.tar
(13 KB)
📄
sndhdr.py.py.tar.gz
(2.45 KB)
📄
sndhdr.py.tar
(22.5 KB)
📄
sndhdr.pyc.pyc.tar.gz
(3.09 KB)
📄
sndhdr.pyc.tar
(9 KB)
📄
sndhdr.pyo.pyo.tar.gz
(3.09 KB)
📄
sndhdr.pyo.tar
(9 KB)
📄
snice.tar
(30.5 KB)
📄
snice.tar.gz
(11.88 KB)
📄
snipeit.sql.sql.tar.gz
(14.54 KB)
📄
snipeit.sql.tar
(90.5 KB)
📄
snipeit.tar
(53.75 MB)
📄
snipeit.tar.gz
(48.4 MB)
📄
snipeit.zip
(53.72 MB)
📄
snmp.tar
(1.75 MB)
📄
snmp.tar.gz
(322.27 KB)
📄
snmp.xml.tar
(4 KB)
📄
snmp.xml.xml.tar.gz
(214 B)
📄
snmp.zip
(1.7 MB)
📄
snmp_monitoring.tar
(116 KB)
📄
snmp_monitoring.tar.gz
(14.24 KB)
📄
snmp_monitoring.zip
(110.82 KB)
📄
snmptrap.xml.tar
(2 KB)
📄
snmptrap.xml.xml.tar.gz
(306 B)
📄
soccpr.jsn.jsn.tar.gz
(234 B)
📄
soccpr.jsn.tar
(2 KB)
📄
sockaddr.h.h.tar.gz
(884 B)
📄
sockaddr.h.tar
(3 KB)
📄
sockaddr.ph.ph.tar.gz
(340 B)
📄
sockaddr.ph.tar
(2 KB)
📄
sockcreate.tar
(1.5 KB)
📄
sockcreate.tar.gz
(104 B)
📄
socket.h.h.tar.gz
(3.06 KB)
📄
socket.h.tar
(12.5 KB)
📄
socket.ph.ph.tar.gz
(696 B)
📄
socket.ph.tar
(21.5 KB)
📄
socket.py.py.tar.gz
(7.85 KB)
📄
socket.py.tar
(84.5 KB)
📄
socket.pyc.pyc.tar.gz
(6.98 KB)
📄
socket.pyc.tar
(17.5 KB)
📄
socket.pyo.pyo.tar.gz
(6.94 KB)
📄
socket.pyo.tar
(17.5 KB)
📄
socket.so.so.tar.gz
(80.4 KB)
📄
socket.so.tar
(188.5 KB)
📄
socket2.h.h.tar.gz
(1.04 KB)
📄
socket2.h.tar
(4.5 KB)
📄
socket2.ph.ph.tar.gz
(248 B)
📄
socket2.ph.tar
(2 KB)
📄
socket_type.h.h.tar.gz
(1.11 KB)
📄
socket_type.h.tar
(4 KB)
📄
socket_type.ph.ph.tar.gz
(390 B)
📄
socket_type.ph.tar
(2.5 KB)
📄
sockets.tar
(119 KB)
📄
sockets.tar.gz
(26.65 KB)
📄
sockets.target.tar
(2 KB)
📄
sockets.target.target.tar.gz
(364 B)
📄
sockets.zip
(90.25 KB)
📄
socketserver.py.py.tar.gz
(7.41 KB)
📄
socketserver.py.tar
(55.5 KB)
📄
socketvar.h.h.tar.gz
(210 B)
📄
socketvar.h.tar
(2 KB)
📄
sockios.h.h.tar.gz
(344 B)
📄
sockios.h.tar
(3 KB)
📄
sockios.ph.ph.tar.gz
(176 B)
📄
sockios.ph.tar
(2 KB)
📄
soelim.tar
(44.5 KB)
📄
soelim.tar.gz
(16.86 KB)
📄
sof-mt8186.ri.ri.tar.gz
(77.14 KB)
📄
sof-mt8186.ri.tar
(128 KB)
📄
sof-mt8188.ri.ri.tar.gz
(81.04 KB)
📄
sof-mt8188.ri.tar
(111.5 KB)
📄
sof-mt8195.ri.ri.tar.gz
(64.46 KB)
📄
sof-mt8195.ri.tar
(100 KB)
📄
sof-tplg.tar
(83.5 KB)
📄
sof-tplg.tar.gz
(1.79 KB)
📄
sof-tplg.zip
(79.86 KB)
📄
sof.tar
(495.5 KB)
📄
sof.tar.gz
(255.22 KB)
📄
sof.zip
(488.32 KB)
📄
sofawiki.tar
(1.86 MB)
📄
sofawiki.tar.gz
(1.76 MB)
📄
sofawiki.zip
(1.84 MB)
📄
soft.htaccess.htaccess.tar.gz
(209 B)
📄
soft.htaccess.tar
(24 KB)
📄
soft_delete.php.php.tar.gz
(1.05 KB)
📄
soft_delete.php.tar
(9 KB)
📄
soft_watchdog.tar
(2 KB)
📄
soft_watchdog.tar.gz
(113 B)
📄
softaculous.ini.ini.tar.gz
(1.29 KB)
📄
softaculous.ini.tar
(7 KB)
📄
softaculous_templates.tar
(11.26 MB)
📄
softaculous_templates.tar.gz
(1.17 MB)
📄
softaculous_templates.zip
(11.26 MB)
📄
softlockup_panic.tar
(2 KB)
📄
softlockup_panic.tar.gz
(117 B)
📄
soho.png.png.tar.gz
(26.07 KB)
📄
soho.png.tar
(27.5 KB)
📄
soho.tar
(145.5 KB)
📄
soho.tar.gz
(86.25 KB)
📄
soho.zip
(127.55 KB)
📄
somaxconn.tar
(2 KB)
📄
somaxconn.tar.gz
(115 B)
📄
soplanning.tar
(24.7 MB)
📄
soplanning.tar.gz
(23.69 MB)
📄
soplanning.zip
(24.68 MB)
📄
sort.tar
(125 KB)
📄
sort.tar.gz
(59.18 KB)
📄
sotruss-lib.so.so.tar.gz
(5.32 KB)
📄
sotruss-lib.so.tar
(13.5 KB)
📄
sound.sh.sh.tar.gz
(632 B)
📄
sound.sh.tar
(3.5 KB)
📄
sound.tar
(219.5 KB)
📄
sound.tar.gz
(50.93 KB)
📄
sound.target.tar
(2 KB)
📄
sound.target.target.tar.gz
(376 B)
📄
sound.zip
(205.48 KB)
📄
soundcard.h.h.tar.gz
(126 B)
📄
soundcard.h.tar
(2 KB)
📄
source-quench.xml.tar
(2 KB)
📄
source-quench.xml.xml.tar.gz
(282 B)
📄
source.py.py.tar.gz
(445 B)
📄
source.py.tar
(2.5 KB)
📄
sp-config.php.php.tar.gz
(936 B)
📄
sp-config.php.tar
(4 KB)
📄
sp.png.png.tar.gz
(22.89 KB)
📄
sp.png.tar
(27.5 KB)
📄
sp.sql.sql.tar.gz
(4.17 KB)
📄
sp.sql.tar
(23 KB)
📄
sp.tar
(19.93 MB)
📄
sp.tar.gz
(19.17 MB)
📄
sp.zip
(19.9 MB)
📄
space.tar
(7 KB)
📄
space.tar.gz
(686 B)
📄
spamassassin.tar
(8 MB)
📄
spamassassin.tar.gz
(2.04 MB)
📄
spamassassin.zip
(7.92 MB)
📄
sparc-linux.tar
(4.5 KB)
📄
sparc-linux.tar.gz
(1.2 KB)
📄
sparc-linux.zip
(3.12 KB)
📄
sparc64-linux.tar
(4.5 KB)
📄
sparc64-linux.tar.gz
(1.2 KB)
📄
sparc64-linux.zip
(3.13 KB)
📄
sparc64v-linux.tar
(4.5 KB)
📄
sparc64v-linux.tar.gz
(1.2 KB)
📄
sparc64v-linux.zip
(3.13 KB)
📄
sparcv8-linux.tar
(4.5 KB)
📄
sparcv8-linux.tar.gz
(1.2 KB)
📄
sparcv8-linux.zip
(3.13 KB)
📄
sparcv9-linux.tar
(4.5 KB)
📄
sparcv9-linux.tar.gz
(1.2 KB)
📄
sparcv9-linux.zip
(3.12 KB)
📄
sparcv9v-linux.tar
(4.5 KB)
📄
sparcv9v-linux.tar.gz
(1.2 KB)
📄
sparcv9v-linux.zip
(3.12 KB)
📄
spawn.h.h.tar.gz
(1.85 KB)
📄
spawn.h.tar
(8.5 KB)
📄
spdif.fw.fw.tar.gz
(12.31 KB)
📄
spdif.fw.tar
(29.5 KB)
📄
special.mk.mk.tar.gz
(808 B)
📄
special.mk.tar
(3 KB)
📄
speculative_prealloc_lifetime.tar
(2 KB)
📄
speculative_prealloc_lifetime.tar.gz
(126 B)
📄
spell.tar
(2 KB)
📄
spell.tar.gz
(186 B)
📄
spf_example.tar
(71 KB)
📄
spf_example.tar.gz
(13.23 KB)
📄
spfd.tar
(161 KB)
📄
spfd.tar.gz
(29.24 KB)
📄
spfquery.tar
(120 KB)
📄
spfquery.tar.gz
(22.13 KB)
📄
spftest.tar
(73 KB)
📄
spftest.tar.gz
(13.39 KB)
📄
spip.png.png.tar.gz
(11.55 KB)
📄
spip.png.tar
(13.5 KB)
📄
spip.sql.sql.tar.gz
(7.39 KB)
📄
spip.sql.tar
(46.5 KB)
📄
spip.tar
(9.57 MB)
📄
spip.tar.gz
(8.57 MB)
📄
spip.zip
(9.53 MB)
📄
spkmodem.mod.mod.tar.gz
(1.07 KB)
📄
spkmodem.mod.tar
(7 KB)
📄
splain.tar
(20.5 KB)
📄
splain.tar.gz
(7.22 KB)
📄
split.kbd.kbd.tar.gz
(186 B)
📄
split.kbd.tar
(2 KB)
📄
split.tar
(60 KB)
📄
split.tar.gz
(27.13 KB)
📄
spotify-sync.xml.tar
(2 KB)
📄
spotify-sync.xml.xml.tar.gz
(278 B)
📄
sprof.tar
(30.5 KB)
📄
sprof.tar.gz
(12.92 KB)
📄
spurious.tar
(30 KB)
📄
spurious.tar.gz
(131 B)
📄
sql_common.h.h.tar.gz
(1.9 KB)
📄
sql_common.h.tar
(7 KB)
📄
sql_state.h.h.tar.gz
(2.94 KB)
📄
sql_state.h.tar
(16.5 KB)
📄
sqlconf.php.php.tar.gz
(382 B)
📄
sqlconf.php.tar
(2.5 KB)
📄
sqldrivers.tar
(84 KB)
📄
sqldrivers.tar.gz
(31.68 KB)
📄
sqldrivers.zip
(82.34 KB)
📄
sqlite.tar
(2.95 MB)
📄
sqlite.tar.gz
(63.38 KB)
📄
sqlite.zip
(2.94 MB)
📄
sqlite3.tar
(2.89 MB)
📄
sqlite3.tar.gz
(698.52 KB)
📄
sqlite3.zip
(46.61 KB)
📄
squash4.mod.mod.tar.gz
(5.09 KB)
📄
squash4.mod.tar
(12 KB)
📄
squid.xml.tar
(3 KB)
📄
squid.xml.xml.tar.gz
(230 B)
📄
squirrel.tar
(161.5 KB)
📄
squirrel.tar.gz
(87.33 KB)
📄
squirrel.zip
(141.2 KB)
📄
sr.tar
(43.5 KB)
📄
sr.tar.gz
(41.88 KB)
📄
sr.zip
(41.85 KB)
📄
sr150_fw.bin.bin.tar.gz
(207.54 KB)
📄
sr150_fw.bin.tar
(209.5 KB)
📄
src.tar
(190.1 MB)
📄
src.tar.gz
(7.31 MB)
📄
src.zip
(185.42 MB)
📄
src_valid_mark.tar
(4 KB)
📄
src_valid_mark.tar.gz
(126 B)
📄
sre.py.py.tar.gz
(330 B)
📄
sre.py.tar
(2 KB)
📄
sre.pyc.pyc.tar.gz
(439 B)
📄
sre.pyc.tar
(2.5 KB)
📄
sre.pyo.pyo.tar.gz
(437 B)
📄
sre.pyo.tar
(2.5 KB)
📄
sre_compile.py.py.tar.gz
(5.1 KB)
📄
sre_compile.py.tar
(67.5 KB)
📄
sre_compile.pyc.pyc.tar.gz
(5.49 KB)
📄
sre_compile.pyc.tar
(14 KB)
📄
sre_compile.pyo.pyo.tar.gz
(5.41 KB)
📄
sre_compile.pyo.tar
(14 KB)
📄
sre_constants.pyc.pyc.tar.gz
(2.76 KB)
📄
sre_constants.pyc.tar
(8 KB)
📄
sre_constants.pyo.pyo.tar.gz
(2.76 KB)
📄
sre_constants.pyo.tar
(8 KB)
📄
sre_parse.py.py.tar.gz
(7.44 KB)
📄
sre_parse.py.tar
(108 KB)
📄
srfi.tar
(1006 KB)
📄
srfi.tar.gz
(299 KB)
📄
srfi.zip
(984.13 KB)
📄
srp.h.h.tar.gz
(1.36 KB)
📄
srp.h.tar
(5.5 KB)
📄
srs.tar
(78 KB)
📄
srs.tar.gz
(15.48 KB)
📄
srtp.h.h.tar.gz
(723 B)
📄
srtp.h.tar
(3 KB)
📄
ss1.pyc.pyc.tar.gz
(10.44 KB)
📄
ss1.pyc.tar
(33.5 KB)
📄
ss1.pyo.pyo.tar.gz
(10.2 KB)
📄
ss1.pyo.tar
(33 KB)
📄
ss_flags.h.h.tar.gz
(749 B)
📄
ss_flags.h.tar
(3 KB)
📄
ss_flags.ph.ph.tar.gz
(358 B)
📄
ss_flags.ph.tar
(2 KB)
📄
ssa-agent.service.service.tar.gz
(332 B)
📄
ssa-agent.service.tar
(2 KB)
📄
ssa-agent.socket.socket.tar.gz
(265 B)
📄
ssa-agent.socket.tar
(3 KB)
📄
ssdp.xml.tar
(2 KB)
📄
ssdp.xml.xml.tar.gz
(347 B)
📄
ssh-add.tar
(348 KB)
📄
ssh-add.tar.gz
(150.17 KB)
📄
ssh-agent.tar
(327.5 KB)
📄
ssh-agent.tar.gz
(141.82 KB)
📄
ssh-copy-id.tar
(12 KB)
📄
ssh-copy-id.tar.gz
(4.43 KB)
📄
ssh-keygen.tar
(429 KB)
📄
ssh-keygen.tar.gz
(191.85 KB)
📄
ssh-keyscan.tar
(430.5 KB)
📄
ssh-keyscan.tar.gz
(192.54 KB)
📄
ssh.tar
(1.29 MB)
📄
ssh.tar.gz
(19.11 KB)
📄
ssh.xml.tar
(3 KB)
📄
ssh.xml.xml.tar.gz
(391 B)
📄
ssh.zip
(0 B)
📄
sshd-keygen@.service.service.tar.gz
(297 B)
📄
sshd-keygen@.service.tar
(2 KB)
📄
sshd.service.service.tar.gz
(408 B)
📄
sshd.service.tar
(2 KB)
📄
sshd.socket.socket.tar.gz
(251 B)
📄
sshd.socket.tar
(3 KB)
📄
sshd@.service.service.tar.gz
(340 B)
📄
sshd@.service.tar
(3 KB)
📄
sshd_priv.service.service.tar.gz
(425 B)
📄
sshd_priv.service.tar
(2 KB)
📄
sshdump.tar
(35.5 KB)
📄
sshdump.tar.gz
(12.76 KB)
📄
ssl.db.cache.db.cache.tar.gz
(4.46 KB)
📄
ssl.db.cache.tar
(21 KB)
📄
ssl.db.db.tar.gz
(4.37 KB)
📄
ssl.db.tar
(21.5 KB)
📄
ssl.h.h.tar.gz
(23.09 KB)
📄
ssl.h.tar
(110.5 KB)
📄
ssl.py.py.tar.gz
(11.2 KB)
📄
ssl.py.tar
(134.5 KB)
📄
ssl.pyc.pyc.tar.gz
(12.91 KB)
📄
ssl.pyc.tar
(33.5 KB)
📄
ssl.pyo.pyo.tar.gz
(12.92 KB)
📄
ssl.pyo.tar
(33.5 KB)
📄
ssl.rb.rb.tar.gz
(3.59 KB)
📄
ssl.rb.tar
(94.5 KB)
📄
ssl.tar
(85 KB)
📄
ssl.tar.gz
(24.13 KB)
📄
ssl.zip
(74.08 KB)
📄
ssl2.h.h.tar.gz
(428 B)
📄
ssl2.h.tar
(2.5 KB)
📄
ssl23.h.h.tar.gz
(1.74 KB)
📄
ssl23.h.tar
(5.5 KB)
📄
ssl3.h.h.tar.gz
(3.69 KB)
📄
ssl3.h.tar
(16 KB)
📄
sslerr.h.h.tar.gz
(8.34 KB)
📄
sslerr.h.tar
(47.5 KB)
📄
sslopt-longopts.h.h.tar.gz
(1.16 KB)
📄
sslopt-longopts.h.tar
(4.5 KB)
📄
ssm4567-tplg.bin.bin.tar.gz
(765 B)
📄
ssm4567-tplg.bin.tar
(5.5 KB)
📄
sss.so.so.tar.gz
(15.29 KB)
📄
sss.so.tar
(38.5 KB)
📄
sssd-autofs.service.service.tar.gz
(400 B)
📄
sssd-autofs.service.tar
(2 KB)
📄
sssd-kcm.service.service.tar.gz
(396 B)
📄
sssd-kcm.service.tar
(2 KB)
📄
sssd-kcm.socket.socket.tar.gz
(257 B)
📄
sssd-kcm.socket.tar
(2 KB)
📄
sssd-nss.service.service.tar.gz
(343 B)
📄
sssd-nss.service.tar
(3 KB)
📄
sssd-nss.socket.socket.tar.gz
(356 B)
📄
sssd-nss.socket.tar
(2 KB)
📄
sssd-pac.service.service.tar.gz
(396 B)
📄
sssd-pac.service.tar
(2 KB)
📄
sssd-pac.socket.socket.tar.gz
(343 B)
📄
sssd-pac.socket.tar
(2 KB)
📄
sssd-pam-priv.socket.socket.tar.gz
(376 B)
📄
sssd-pam-priv.socket.tar
(2 KB)
📄
sssd-pam.service.service.tar.gz
(400 B)
📄
sssd-pam.service.tar
(2 KB)
📄
sssd-pam.socket.socket.tar.gz
(355 B)
📄
sssd-pam.socket.tar
(2 KB)
📄
sssd-ssh.service.service.tar.gz
(395 B)
📄
sssd-ssh.service.tar
(2 KB)
📄
sssd-ssh.socket.socket.tar.gz
(342 B)
📄
sssd-ssh.socket.tar
(2 KB)
📄
sssd-sudo.service.service.tar.gz
(401 B)
📄
sssd-sudo.service.tar
(2 KB)
📄
sssd-sudo.socket.socket.tar.gz
(347 B)
📄
sssd-sudo.socket.tar
(3 KB)
📄
sssd.conf.conf.tar.gz
(226 B)
📄
sssd.conf.tar
(2 KB)
📄
sssd.service.service.tar.gz
(566 B)
📄
sssd.service.tar
(2.5 KB)
📄
sssd.tar
(2.38 MB)
📄
sssd.tar.gz
(904.2 KB)
📄
sssd.zip
(2.37 MB)
📄
stab.def.def.tar.gz
(3.42 KB)
📄
stab.def.tar
(10.5 KB)
📄
stab.h.h.tar.gz
(269 B)
📄
stab.h.tar
(2 KB)
📄
stack.h.h.tar.gz
(941 B)
📄
stack.h.tar
(5 KB)
📄
stack_tracer_enabled.tar
(2 KB)
📄
stack_tracer_enabled.tar.gz
(119 B)
📄
staggered.py.py.tar.gz
(2.26 KB)
📄
staggered.py.tar
(7.5 KB)
📄
stale_loss_cnt.tar
(2 KB)
📄
stale_loss_cnt.tar.gz
(116 B)
📄
standard.kbd.kbd.tar.gz
(184 B)
📄
standard.kbd.tar
(2 KB)
📄
starfire_rx.bin.bin.tar.gz
(517 B)
📄
starfire_rx.bin.tar
(2.5 KB)
📄
starfire_tx.bin.bin.tar.gz
(518 B)
📄
starfire_tx.bin.tar
(2.5 KB)
📄
stat.h.h.tar.gz
(2.22 KB)
📄
stat.h.tar
(33 KB)
📄
stat.py.py.tar.gz
(1.85 KB)
📄
stat.py.tar
(15 KB)
📄
stat.pyc.pyc.tar.gz
(1.04 KB)
📄
stat.pyc.tar
(4.5 KB)
📄
stat.pyo.pyo.tar.gz
(1.04 KB)
📄
stat.pyo.tar
(4.5 KB)
📄
stat.tar
(94 KB)
📄
stat.tar.gz
(1.96 KB)
📄
stat_interval.tar
(2 KB)
📄
stat_interval.tar.gz
(108 B)
📄
state.php.php.tar.gz
(224 B)
📄
state.php.tar
(2 KB)
📄
statfs.h.h.tar.gz
(849 B)
📄
statfs.h.tar
(7.5 KB)
📄
static.so.so.tar.gz
(16.89 KB)
📄
static.so.tar
(38.5 KB)
📄
statprof.go.go.tar.gz
(11.73 KB)
📄
statprof.go.tar
(30 KB)
📄
stats.py.py.tar.gz
(1.05 KB)
📄
stats.py.tar
(4.5 KB)
📄
stats.pyc.pyc.tar.gz
(1.42 KB)
📄
stats.pyc.tar
(5 KB)
📄
stats.pyo.pyo.tar.gz
(1.39 KB)
📄
stats.pyo.tar
(5 KB)
📄
stats.rb.rb.tar.gz
(2.7 KB)
📄
stats.rb.tar
(55 KB)
📄
stats.tar
(8 KB)
📄
stats.tar.gz
(484 B)
📄
stats.zip
(3.42 KB)
📄
stats_clear.tar
(2 KB)
📄
stats_clear.tar.gz
(110 B)
📄
status.json.json.tar.gz
(255 B)
📄
status.json.tar
(3 KB)
📄
status.tar
(2 KB)
📄
status.tar.gz
(120 B)
📄
statvfs.h.h.tar.gz
(1.36 KB)
📄
statvfs.h.tar
(8.5 KB)
📄
statvfs.py.py.tar.gz
(507 B)
📄
statvfs.py.tar
(2.5 KB)
📄
statvfs.pyc.pyc.tar.gz
(487 B)
📄
statvfs.pyc.tar
(2.5 KB)
📄
statvfs.pyo.pyo.tar.gz
(487 B)
📄
statvfs.pyo.tar
(2.5 KB)
📄
statx.h.h.tar.gz
(823 B)
📄
statx.h.tar
(3 KB)
📄
stdarg.ph.ph.tar.gz
(768 B)
📄
stdarg.ph.tar
(4.5 KB)
📄
stdbuf.tar
(51 KB)
📄
stdbuf.tar.gz
(23.55 KB)
📄
stdc-predef.h.h.tar.gz
(1.18 KB)
📄
stdc-predef.h.tar
(4 KB)
📄
stdc-predef.ph.ph.tar.gz
(348 B)
📄
stdc-predef.ph.tar
(2.5 KB)
📄
stdcheaders.h.h.tar.gz
(681 B)
📄
stdcheaders.h.tar
(3 KB)
📄
stddef.ph.ph.tar.gz
(1.93 KB)
📄
stddef.ph.tar
(15.5 KB)
📄
stdint-intn.h.h.tar.gz
(652 B)
📄
stdint-intn.h.tar
(3 KB)
📄
stdint-intn.ph.ph.tar.gz
(244 B)
📄
stdint-intn.ph.tar
(2 KB)
📄
stdint-uintn.h.h.tar.gz
(655 B)
📄
stdint-uintn.h.tar
(3 KB)
📄
stdint.h.h.tar.gz
(1.99 KB)
📄
stdint.h.tar
(10 KB)
📄
stdio.h.h.tar.gz
(6.24 KB)
📄
stdio.h.tar
(37 KB)
📄
stdio2.h.h.tar.gz
(2.42 KB)
📄
stdio2.h.tar
(14 KB)
📄
stdio_ext.h.h.tar.gz
(1.19 KB)
📄
stdio_ext.h.tar
(4.5 KB)
📄
stdio_lim.h.h.tar.gz
(743 B)
📄
stdio_lim.h.tar
(3 KB)
📄
stdlib-bsearch.h.h.tar.gz
(804 B)
📄
stdlib-bsearch.h.tar
(3 KB)
📄
stdlib-float.h.h.tar.gz
(743 B)
📄
stdlib-float.h.tar
(3 KB)
📄
stdlib-ldbl.h.h.tar.gz
(781 B)
📄
stdlib-ldbl.h.tar
(3 KB)
📄
stdlib.h.h.tar.gz
(8.1 KB)
📄
stdlib.h.tar
(42 KB)
📄
steam-streaming.xml.tar
(2.5 KB)
📄
steam-streaming.xml.xml.tar.gz
(426 B)
📄
stones.py.py.tar.gz
(483 B)
📄
stones.py.tar
(2.5 KB)
📄
stones.pyc.pyc.tar.gz
(767 B)
📄
stones.pyc.tar
(3 KB)
📄
stones.pyo.pyo.tar.gz
(767 B)
📄
stones.pyo.tar
(3 KB)
📄
stoney_ce.bin.bin.tar.gz
(2.55 KB)
📄
stoney_ce.bin.tar
(10.5 KB)
📄
stoney_me.bin.bin.tar.gz
(5.64 KB)
📄
stoney_me.bin.tar
(18.5 KB)
📄
stoney_mec.bin.bin.tar.gz
(27.69 KB)
📄
stoney_mec.bin.tar
(258.5 KB)
📄
stoney_pfp.bin.bin.tar.gz
(7.23 KB)
📄
stoney_pfp.bin.tar
(18.5 KB)
📄
stoney_rlc.bin.bin.tar.gz
(6.58 KB)
📄
stoney_rlc.bin.tar
(18.5 KB)
📄
stoney_sdma.bin.bin.tar.gz
(4.38 KB)
📄
stoney_sdma.bin.tar
(12 KB)
📄
stoney_uvd.bin.bin.tar.gz
(165.53 KB)
📄
stoney_uvd.bin.tar
(272.5 KB)
📄
stoney_vce.bin.bin.tar.gz
(88.11 KB)
📄
stoney_vce.bin.tar
(164.5 KB)
📄
store.h.h.tar.gz
(2.98 KB)
📄
store.h.tar
(12.5 KB)
📄
store.rb.rb.tar.gz
(903 B)
📄
store.rb.tar
(103 KB)
📄
storeerr.h.h.tar.gz
(1.25 KB)
📄
storeerr.h.tar
(6 KB)
📄
strace.tar
(1.94 MB)
📄
strace.tar.gz
(660.8 KB)
📄
stream.rb.rb.tar.gz
(543 B)
📄
stream.rb.tar
(5.5 KB)
📄
stream.tar
(13.5 KB)
📄
stream.tar.gz
(3.62 KB)
📄
stream_flags.h.h.tar.gz
(2.32 KB)
📄
stream_flags.h.tar
(10 KB)
📄
streams.go.go.tar.gz
(3.25 KB)
📄
streams.go.tar
(9.5 KB)
📄
streams.py.py.tar.gz
(6.59 KB)
📄
streams.py.tar
(52.5 KB)
📄
string-fun.go.go.tar.gz
(3.15 KB)
📄
string-fun.go.tar
(10 KB)
📄
string.h.h.tar.gz
(3.93 KB)
📄
string.h.tar
(19 KB)
📄
string.py.py.tar.gz
(3.47 KB)
📄
string.py.tar
(46.5 KB)
📄
string.pyc.pyc.tar.gz
(6.78 KB)
📄
string.pyc.tar
(21.5 KB)
📄
string.pyo.pyo.tar.gz
(6.78 KB)
📄
string.pyo.tar
(21.5 KB)
📄
stringio.so.so.tar.gz
(15.72 KB)
📄
stringio.so.tar
(38 KB)
📄
stringold.py.py.tar.gz
(3.75 KB)
📄
stringold.py.tar
(14 KB)
📄
stringprep.h.h.tar.gz
(2.05 KB)
📄
stringprep.h.tar
(10 KB)
📄
stringprep.pyc.pyc.tar.gz
(5.89 KB)
📄
stringprep.pyc.tar
(16 KB)
📄
stringprep.pyo.pyo.tar.gz
(5.83 KB)
📄
stringprep.pyo.tar
(16 KB)
📄
strings.h.h.tar.gz
(1.59 KB)
📄
strings.h.tar
(6.5 KB)
📄
strings.tar
(39 KB)
📄
strings.tar.gz
(16.96 KB)
📄
strip.tar
(242 KB)
📄
strip.tar.gz
(109.97 KB)
📄
stripe.sql.sql.tar.gz
(4.29 KB)
📄
stripe.sql.tar
(54 KB)
📄
stripe.tar
(23.06 MB)
📄
stripe.tar.gz
(20.58 MB)
📄
stripe.zip
(23.04 MB)
📄
strscan.so.so.tar.gz
(11.38 KB)
📄
strscan.so.tar
(59 KB)
📄
strtoull_test.mod.mod.tar.gz
(1.08 KB)
📄
strtoull_test.mod.tar
(4 KB)
📄
struct.py.py.tar.gz
(244 B)
📄
struct.py.tar
(4 KB)
📄
struct.pyc.pyc.tar.gz
(255 B)
📄
struct.pyc.tar
(2 KB)
📄
struct.pyo.pyo.tar.gz
(255 B)
📄
struct.pyo.tar
(2 KB)
📄
struct_FILE.h.h.tar.gz
(1.73 KB)
📄
struct_FILE.h.tar
(6 KB)
📄
struct_itimerspec.h.h.tar.gz
(257 B)
📄
struct_itimerspec.h.tar
(2 KB)
📄
struct_timeval.h.h.tar.gz
(285 B)
📄
struct_timeval.h.tar
(2 KB)
📄
struct_tm.h.h.tar.gz
(458 B)
📄
struct_tm.h.tar
(2.5 KB)
📄
structmember.h.h.tar.gz
(993 B)
📄
structmember.h.tar
(3.5 KB)
📄
structseq.h.h.tar.gz
(546 B)
📄
structseq.h.tar
(3 KB)
📄
stsearch.h.h.tar.gz
(5.09 KB)
📄
stsearch.h.tar
(23 KB)
📄
stty.tar
(79.5 KB)
📄
stty.tar.gz
(33.32 KB)
📄
stubs-64.h.h.tar.gz
(397 B)
📄
stubs-64.h.tar
(2.5 KB)
📄
stubs-64.ph.ph.tar.gz
(390 B)
📄
stubs-64.ph.tar
(3 KB)
📄
stubs.h.h.tar.gz
(294 B)
📄
stubs.h.tar
(2 KB)
📄
stubs.ph.ph.tar.gz
(227 B)
📄
stubs.ph.tar
(2 KB)
📄
stv0672_vp4.bin.bin.tar.gz
(842 B)
📄
stv0672_vp4.bin.tar
(2.5 KB)
📄
style.css.css.tar.gz
(453 B)
📄
style.css.tar
(2.5 KB)
📄
styles.css.css.tar.gz
(184 B)
📄
styles.css.tar
(2 KB)
📄
styles.tar
(10 KB)
📄
styles.tar.gz
(2.68 KB)
📄
styles.zip
(8.29 KB)
📄
subprocess.cpython-38.opt-1.pyc.cpython-38.opt-1.pyc.tar.gz
(18.62 KB)
📄
subprocess.cpython-38.opt-1.pyc.tar
(43 KB)
📄
subprocess.py.py.tar.gz
(14.5 KB)
📄
subprocess.py.tar
(62.5 KB)
📄
subprocess.pyc.pyc.tar.gz
(13.11 KB)
📄
subprocess.pyc.tar
(33.5 KB)
📄
subprocess.pyo.pyo.tar.gz
(13.11 KB)
📄
subprocess.pyo.tar
(33.5 KB)
📄
subrion.tar
(240 KB)
📄
subrion.tar.gz
(132.54 KB)
📄
subrion.zip
(211.6 KB)
📄
subscriptions.tar
(2 KB)
📄
subscriptions.tar.gz
(133 B)
📄
sudo.conf.conf.tar.gz
(290 B)
📄
sudo.conf.tar
(3 KB)
📄
sugar.tar
(221 KB)
📄
sugar.tar.gz
(125.32 KB)
📄
sugar.zip
(196.08 KB)
📄
suid_dumpable.tar
(2 KB)
📄
suid_dumpable.tar.gz
(110 B)
📄
suite.py.py.tar.gz
(2.84 KB)
📄
suite.py.tar
(14.5 KB)
📄
suitecrm.tar
(108.94 MB)
📄
suitecrm.tar.gz
(100.3 MB)
📄
suitecrm.zip
(108.9 MB)
📄
suitecrm7.sql.sql.tar.gz
(56.39 KB)
📄
suitecrm7.sql.tar
(404 KB)
📄
suitecrm7.tar
(52.27 MB)
📄
suitecrm7.tar.gz
(47.32 MB)
📄
suitecrm7.zip
(52.24 MB)
📄
suiv.tar
(1.01 MB)
📄
suiv.tar.gz
(645.44 KB)
📄
suiv.zip
(997.09 KB)
📄
sum.tar
(47.5 KB)
📄
sum.tar.gz
(20.19 KB)
📄
sun.tar
(57.5 KB)
📄
sun.tar.gz
(1.59 KB)
📄
sun.zip
(46.19 KB)
📄
sunau.py.py.tar.gz
(4.04 KB)
📄
sunau.py.tar
(55.5 KB)
📄
sunau.pyc.pyc.tar.gz
(5.82 KB)
📄
sunau.pyc.tar
(19.5 KB)
📄
sunau.pyo.pyo.tar.gz
(5.82 KB)
📄
sunau.pyo.tar
(19.5 KB)
📄
sunaudio.py.py.tar.gz
(685 B)
📄
sunaudio.py.tar
(3 KB)
📄
sunaudio.pyc.pyc.tar.gz
(1.05 KB)
📄
sunaudio.pyc.tar
(3.5 KB)
📄
sunaudio.pyo.pyo.tar.gz
(1.05 KB)
📄
sunaudio.pyo.tar
(3.5 KB)
📄
sunrpc.tar
(12 KB)
📄
sunrpc.tar.gz
(348 B)
📄
sunrpc.zip
(1.6 KB)
📄
supercali.tar
(111 KB)
📄
supercali.tar.gz
(61.28 KB)
📄
supercali.zip
(94.69 KB)
📄
support.tar
(508 KB)
📄
support.tar.gz
(142.68 KB)
📄
support.zip
(497.56 KB)
📄
suppress_frag_ndisc.tar
(2 KB)
📄
suppress_frag_ndisc.tar.gz
(125 B)
📄
suspend.target.tar
(3 KB)
📄
suspend.target.target.tar.gz
(419 B)
📄
sv.h.h.tar.gz
(22.37 KB)
📄
sv.h.tar
(84 KB)
📄
sv.tar
(192.5 KB)
📄
sv.tar.gz
(154.66 KB)
📄
sv.zip
(160.13 KB)
📄
svc.h.h.tar.gz
(4.26 KB)
📄
svc.h.tar
(13 KB)
📄
svdrp.xml.tar
(2 KB)
📄
svdrp.xml.xml.tar.gz
(293 B)
📄
svkill.pyc.pyc.tar.gz
(2.61 KB)
📄
svkill.pyc.tar
(7.5 KB)
📄
svkill.pyo.pyo.tar.gz
(2.61 KB)
📄
svkill.pyo.tar
(7.5 KB)
📄
svm.h.h.tar.gz
(2.24 KB)
📄
svm.h.tar
(11.5 KB)
📄
svn.xml.tar
(3 KB)
📄
svn.xml.xml.tar.gz
(261 B)
📄
svneol.py.py.tar.gz
(1.26 KB)
📄
svneol.py.tar
(4.5 KB)
📄
swab.h.h.tar.gz
(431 B)
📄
swab.h.tar
(3.5 KB)
📄
swap.h.h.tar.gz
(919 B)
📄
swap.h.tar
(3.5 KB)
📄
swap.target.tar
(3 KB)
📄
swap.target.target.tar.gz
(360 B)
📄
swappiness.tar
(2 KB)
📄
swappiness.tar.gz
(107 B)
📄
sxg.tar
(116.5 KB)
📄
sxg.tar.gz
(38.46 KB)
📄
sxg.zip
(114.69 KB)
📄
sxml.tar
(233 KB)
📄
sxml.tar.gz
(84.39 KB)
📄
sxml.zip
(227.52 KB)
📄
syck.rb.rb.tar.gz
(3.78 KB)
📄
syck.rb.tar
(15.5 KB)
📄
syck.so.so.tar.gz
(56.54 KB)
📄
syck.so.tar
(133 KB)
📄
syck.tar
(53.5 KB)
📄
syck.tar.gz
(10.71 KB)
📄
syck.zip
(44.35 KB)
📄
symbol.py.py.tar.gz
(1.04 KB)
📄
symbol.py.tar
(10 KB)
📄
symbol.pyc.pyc.tar.gz
(1.52 KB)
📄
symbol.pyc.tar
(4.5 KB)
📄
symbol.pyo.pyo.tar.gz
(1.52 KB)
📄
symbol.pyo.tar
(4.5 KB)
📄
symbols.pyc.pyc.tar.gz
(6.01 KB)
📄
symbols.pyc.tar
(19 KB)
📄
symbols.pyo.pyo.tar.gz
(5.98 KB)
📄
symbols.pyo.tar
(19 KB)
📄
symfony2.tar
(58 KB)
📄
symfony2.tar.gz
(30.37 KB)
📄
symfony2.zip
(46.96 KB)
📄
symfony24.tar
(2.13 MB)
📄
symfony24.tar.gz
(1.82 MB)
📄
symfony24.zip
(2.12 MB)
📄
symfony3.tar
(62 KB)
📄
symfony3.tar.gz
(33 KB)
📄
symfony3.zip
(51.56 KB)
📄
symhacks.h.h.tar.gz
(638 B)
📄
symhacks.h.tar
(3 KB)
📄
symilar.tar
(2 KB)
📄
symilar.tar.gz
(235 B)
📄
symtable.h.h.tar.gz
(1.69 KB)
📄
symtable.h.tar
(6 KB)
📄
symtable.py.py.tar.gz
(2.1 KB)
📄
symtable.py.tar
(25.5 KB)
📄
symtable.pyc.pyc.tar.gz
(3.78 KB)
📄
symtable.pyc.tar
(13.5 KB)
📄
symtable.pyo.pyo.tar.gz
(3.71 KB)
📄
symtable.pyo.tar
(13 KB)
📄
sync.h.h.tar.gz
(4.09 KB)
📄
sync.h.tar
(44.5 KB)
📄
sync.py.py.tar.gz
(6.34 KB)
📄
sync.py.tar
(23 KB)
📄
sync.rb.rb.tar.gz
(2.07 KB)
📄
sync.rb.tar
(32.5 KB)
📄
sync.tar
(39 KB)
📄
sync.tar.gz
(15.54 KB)
📄
syncase.go.go.tar.gz
(606 B)
📄
syncase.go.tar
(2.5 KB)
📄
syncs.tar
(2 KB)
📄
syncs.tar.gz
(111 B)
📄
syncthing.xml.tar
(2 KB)
📄
syncthing.xml.xml.tar.gz
(293 B)
📄
synergy.xml.tar
(2 KB)
📄
synergy.xml.xml.tar.gz
(409 B)
📄
syntax.py.py.tar.gz
(742 B)
📄
syntax.py.tar
(3 KB)
📄
syntax_suggest.tar
(5.5 KB)
📄
syntax_suggest.tar.gz
(422 B)
📄
sys-kernel-config.mount.mount.tar.gz
(560 B)
📄
sys-kernel-config.mount.tar
(2.5 KB)
📄
sys.tar
(415 KB)
📄
sys.tar.gz
(7.35 KB)
📄
sys.zip
(352.61 KB)
📄
sys_errlist.h.h.tar.gz
(725 B)
📄
sys_errlist.h.tar
(3 KB)
📄
syscall.h.h.tar.gz
(117 B)
📄
syscall.h.tar
(49.5 KB)
📄
syscall.ph.ph.tar.gz
(170 B)
📄
syscall.ph.tar
(79.5 KB)
📄
sysconfig.py.py.tar.gz
(7.15 KB)
📄
sysconfig.py.tar
(74 KB)
📄
sysconfig.tar
(3 KB)
📄
sysconfig.tar.gz
(344 B)
📄
sysconfig.zip
(1.19 KB)
📄
sysctl.d.tar
(10.5 KB)
📄
sysctl.d.tar.gz
(2.62 KB)
📄
sysctl.d.zip
(6.23 KB)
📄
sysctl.h.h.tar.gz
(611 B)
📄
sysctl.h.tar
(5 KB)
📄
sysctl_writes_strict.tar
(2 KB)
📄
sysctl_writes_strict.tar.gz
(118 B)
📄
sysexits.h.h.tar.gz
(2.4 KB)
📄
sysexits.h.tar
(7 KB)
📄
sysinit.target.tar
(2.5 KB)
📄
sysinit.target.target.tar.gz
(422 B)
📄
syslimits.ph.ph.tar.gz
(356 B)
📄
syslimits.ph.tar
(2 KB)
📄
syslinuxcfg.mod.mod.tar.gz
(9.12 KB)
📄
syslinuxcfg.mod.tar
(25.5 KB)
📄
syslog-ldbl.h.h.tar.gz
(745 B)
📄
syslog-ldbl.h.tar
(3 KB)
📄
syslog-ldbl.ph.ph.tar.gz
(325 B)
📄
syslog-ldbl.ph.tar
(2 KB)
📄
syslog-path.h.h.tar.gz
(670 B)
📄
syslog-path.h.tar
(3 KB)
📄
syslog-path.ph.ph.tar.gz
(310 B)
📄
syslog-path.ph.tar
(2 KB)
📄
syslog.h.h.tar.gz
(115 B)
📄
syslog.h.tar
(13 KB)
📄
syslog.ph.ph.tar.gz
(168 B)
📄
syslog.ph.tar
(7.5 KB)
📄
syslog.so.so.tar.gz
(6.67 KB)
📄
syslog.so.tar
(17.5 KB)
📄
syslog.socket.socket.tar.gz
(789 B)
📄
syslog.socket.tar
(3 KB)
📄
syslog.tar
(7.5 KB)
📄
syslog.tar.gz
(2.21 KB)
📄
syslog.xml.tar
(3 KB)
📄
syslog.xml.xml.tar.gz
(308 B)
📄
syslog.zip
(5.93 KB)
📄
sysmacros.h.h.tar.gz
(1.2 KB)
📄
sysmacros.h.tar
(7.5 KB)
📄
sysmodule.h.h.tar.gz
(501 B)
📄
sysmodule.h.tar
(3 KB)
📄
sysrq.tar
(2 KB)
📄
sysrq.tar.gz
(105 B)
📄
sysstat-collect.service.service.tar.gz
(330 B)
📄
sysstat-collect.service.tar
(2 KB)
📄
sysstat-summary.service.service.tar.gz
(317 B)
📄
sysstat-summary.service.tar
(2 KB)
📄
sysstat.service.service.tar.gz
(410 B)
📄
sysstat.service.tar
(2 KB)
📄
system-generators.tar
(346.5 KB)
📄
system-generators.tar.gz
(131.89 KB)
📄
system-generators.zip
(337.49 KB)
📄
system-preset.tar
(12.5 KB)
📄
system-preset.tar.gz
(2.35 KB)
📄
system-preset.zip
(7.51 KB)
📄
system-update.target.tar
(2.5 KB)
📄
system-update.target.target.tar.gz
(460 B)
📄
system.h.h.tar.gz
(3.09 KB)
📄
system.h.tar
(20 KB)
📄
system.tar
(690 KB)
📄
system.tar.gz
(219.74 KB)
📄
system.zip
(672.29 KB)
📄
system_core.php.php.tar.gz
(2.49 KB)
📄
system_core.php.tar
(9 KB)
📄
systemd-ac-power.tar
(13.5 KB)
📄
systemd-ac-power.tar.gz
(4.27 KB)
📄
systemd-backlight.tar
(52 KB)
📄
systemd-backlight.tar.gz
(9.18 KB)
📄
systemd-binfmt.tar
(36 KB)
📄
systemd-binfmt.tar.gz
(6.4 KB)
📄
systemd-cgroups-agent.tar
(14 KB)
📄
systemd-cgroups-agent.tar.gz
(4.25 KB)
📄
systemd-coredump.tar
(63 KB)
📄
systemd-coredump.tar.gz
(26.72 KB)
📄
systemd-cryptsetup.tar
(60 KB)
📄
systemd-cryptsetup.tar.gz
(12.99 KB)
📄
systemd-dissect.tar
(35 KB)
📄
systemd-dissect.tar.gz
(7.01 KB)
📄
systemd-export.tar
(85 KB)
📄
systemd-export.tar.gz
(17.4 KB)
📄
systemd-fsck.tar
(52 KB)
📄
systemd-fsck.tar.gz
(9.21 KB)
📄
systemd-growfs.tar
(43 KB)
📄
systemd-growfs.tar.gz
(8.53 KB)
📄
systemd-hibernate-resume.tar
(14 KB)
📄
systemd-hibernate-resume.tar.gz
(4.57 KB)
📄
systemd-hostnamed.tar
(30.5 KB)
📄
systemd-hostnamed.tar.gz
(10.63 KB)
📄
systemd-initctl.tar
(43 KB)
📄
systemd-initctl.tar.gz
(7.6 KB)
📄
systemd-journald.tar
(156 KB)
📄
systemd-journald.tar.gz
(64.2 KB)
📄
systemd-localed.tar
(101 KB)
📄
systemd-localed.tar.gz
(20.36 KB)
📄
systemd-logind.tar
(533 KB)
📄
systemd-logind.tar.gz
(106.12 KB)
📄
systemd-makefs.tar
(27 KB)
📄
systemd-makefs.tar.gz
(4.96 KB)
📄
systemd-modules-load.tar
(22 KB)
📄
systemd-modules-load.tar.gz
(7.68 KB)
📄
systemd-nologin.conf.conf.tar.gz
(472 B)
📄
systemd-nologin.conf.tar
(4 KB)
📄
systemd-portabled.tar
(91.5 KB)
📄
systemd-portabled.tar.gz
(37.35 KB)
📄
systemd-pstore.conf.conf.tar.gz
(803 B)
📄
systemd-pstore.conf.tar
(3 KB)
📄
systemd-pstore.tar
(44 KB)
📄
systemd-pstore.tar.gz
(9.03 KB)
📄
systemd-quotacheck.tar
(27 KB)
📄
systemd-quotacheck.tar.gz
(4.46 KB)
📄
systemd-random-seed.tar
(18 KB)
📄
systemd-random-seed.tar.gz
(5.83 KB)
📄
systemd-remount-fs.tar
(52 KB)
📄
systemd-remount-fs.tar.gz
(10.08 KB)
📄
systemd-reply-password.tar
(14 KB)
📄
systemd-reply-password.tar.gz
(4.9 KB)
📄
systemd-resolved.tar
(454.5 KB)
📄
systemd-resolved.tar.gz
(199.73 KB)
📄
systemd-rfkill.tar
(52 KB)
📄
systemd-rfkill.tar.gz
(9.91 KB)
📄
systemd-shutdown.tar
(63 KB)
📄
systemd-shutdown.tar.gz
(25.81 KB)
📄
systemd-sleep.tar
(22.5 KB)
📄
systemd-sleep.tar.gz
(8.53 KB)
📄
systemd-socket-proxyd.tar
(26.5 KB)
📄
systemd-socket-proxyd.tar.gz
(10.92 KB)
📄
systemd-sulogin-shell.tar
(18 KB)
📄
systemd-sulogin-shell.tar.gz
(6.07 KB)
📄
systemd-sysctl.tar
(44 KB)
📄
systemd-sysctl.tar.gz
(7.97 KB)
📄
systemd-timedated.tar
(38.5 KB)
📄
systemd-timedated.tar.gz
(14.46 KB)
📄
systemd-udevd.tar
(410.5 KB)
📄
systemd-udevd.tar.gz
(141.23 KB)
📄
systemd-update-done.tar
(14 KB)
📄
systemd-update-done.tar.gz
(4.71 KB)
📄
systemd-update-utmp.tar
(18 KB)
📄
systemd-update-utmp.tar.gz
(6.47 KB)
📄
systemd-user-runtime-dir.tar
(247 KB)
📄
systemd-user-runtime-dir.tar.gz
(98.7 KB)
📄
systemd-user-sessions.tar
(26 KB)
📄
systemd-user-sessions.tar.gz
(3.85 KB)
📄
systemd-vconsole-setup.tar
(22 KB)
📄
systemd-vconsole-setup.tar.gz
(9.21 KB)
📄
systemd-veritysetup.tar
(14 KB)
📄
systemd-veritysetup.tar.gz
(5.33 KB)
📄
systemd-volatile-root.tar
(14 KB)
📄
systemd-volatile-root.tar.gz
(5.43 KB)
📄
systemd.be.catalog.be.catalog.tar.gz
(4.05 KB)
📄
systemd.be.catalog.tar
(14.5 KB)
📄
systemd.bg.catalog.bg.catalog.tar.gz
(4.17 KB)
📄
systemd.bg.catalog.tar
(15.5 KB)
📄
systemd.catalog.catalog.tar.gz
(4.3 KB)
📄
systemd.catalog.tar
(14.5 KB)
📄
systemd.conf.conf.tar.gz
(328 B)
📄
systemd.conf.tar
(11 KB)
📄
systemd.de.catalog.de.catalog.tar.gz
(424 B)
📄
systemd.de.catalog.tar
(2 KB)
📄
systemd.fr.catalog.fr.catalog.tar.gz
(4.3 KB)
📄
systemd.fr.catalog.tar
(15 KB)
📄
systemd.it.catalog.it.catalog.tar.gz
(3.76 KB)
📄
systemd.it.catalog.tar
(13 KB)
📄
systemd.pl.catalog.pl.catalog.tar.gz
(4.5 KB)
📄
systemd.pl.catalog.tar
(14.5 KB)
📄
systemd.pt_BR.catalog.pt_BR.catalog.tar.gz
(2.81 KB)
📄
systemd.pt_BR.catalog.tar
(10 KB)
📄
systemd.ru.catalog.ru.catalog.tar.gz
(6.25 KB)
📄
systemd.ru.catalog.tar
(22 KB)
📄
systemd.tar
(3.08 MB)
📄
systemd.tar.gz
(564.67 KB)
📄
systemd.zh_CN.catalog.tar
(9 KB)
📄
systemd.zh_CN.catalog.zh_CN.catalog.tar.gz
(2.85 KB)
📄
systemd.zh_TW.catalog.tar
(9 KB)
📄
systemd.zh_TW.catalog.zh_TW.catalog.tar.gz
(2.81 KB)
📄
systemd_inhibit.so.so.tar.gz
(4.28 KB)
📄
systemd_inhibit.so.tar
(13.5 KB)
📄
sysusers.d.tar
(7 KB)
📄
sysusers.d.tar.gz
(809 B)
📄
sysusers.d.zip
(2.39 KB)
📄
sysvipc.tar
(12.5 KB)
📄
sysvipc.tar.gz
(1.43 KB)
📄
sysvipc.zip
(9.94 KB)
📄
t1lib.tar
(492 KB)
📄
t1lib.tar.gz
(185.26 KB)
📄
t1lib.zip
(485.33 KB)
📄
t1libconfig.tar
(5.5 KB)
📄
t1libconfig.tar.gz
(1.81 KB)
📄
t4fw-1.14.4.0.bin.14.4.0.bin.tar.gz
(347.07 KB)
📄
t4fw-1.14.4.0.bin.tar
(528.5 KB)
📄
t4fw-1.27.5.0.bin.27.5.0.bin.tar.gz
(372.77 KB)
📄
t4fw-1.27.5.0.bin.tar
(559 KB)
📄
t4fw.bin.bin.tar.gz
(372.77 KB)
📄
t4fw.bin.tar
(559 KB)
📄
t5fw-1.14.4.0.bin.14.4.0.bin.tar.gz
(374.56 KB)
📄
t5fw-1.14.4.0.bin.tar
(581.5 KB)
📄
t5fw-1.27.5.0.bin.27.5.0.bin.tar.gz
(435.73 KB)
📄
t5fw-1.27.5.0.bin.tar
(664.5 KB)
📄
t5fw.bin.bin.tar.gz
(435.72 KB)
📄
t5fw.bin.tar
(664.5 KB)
📄
t6fw-1.27.5.0.bin.27.5.0.bin.tar.gz
(449.63 KB)
📄
t6fw-1.27.5.0.bin.tar
(715 KB)
📄
t6fw.bin.bin.tar.gz
(449.62 KB)
📄
t6fw.bin.tar
(715 KB)
📄
tabbedpages.pyc.pyc.tar.gz
(6.6 KB)
📄
tabbedpages.pyc.tar
(20 KB)
📄
tabnanny.py.py.tar.gz
(3.71 KB)
📄
tabnanny.py.tar
(37 KB)
📄
tabnanny.pyc.pyc.tar.gz
(3.67 KB)
📄
tabnanny.pyc.tar
(10 KB)
📄
tabnanny.pyo.pyo.tar.gz
(3.67 KB)
📄
tabnanny.pyo.tar
(10 KB)
📄
tabs.inc.inc.tar.gz
(916 B)
📄
tabs.inc.tar
(3.5 KB)
📄
tabs.tar
(18.5 KB)
📄
tabs.tar.gz
(7.67 KB)
📄
tac.tar
(43 KB)
📄
tac.tar.gz
(18.54 KB)
📄
tag.h.h.tar.gz
(1.81 KB)
📄
tag.h.tar
(6.5 KB)
📄
tag.tar
(5 KB)
📄
tag.tar.gz
(115 B)
📄
tag_compat.h.h.tar.gz
(1.15 KB)
📄
tag_compat.h.tar
(4 KB)
📄
tahiti_ce.bin.bin.tar.gz
(1.06 KB)
📄
tahiti_ce.bin.tar
(20 KB)
📄
tahiti_k_smc.bin.bin.tar.gz
(26.75 KB)
📄
tahiti_k_smc.bin.tar
(128 KB)
📄
tahiti_mc.bin.bin.tar.gz
(12.65 KB)
📄
tahiti_mc.bin.tar
(65 KB)
📄
tahiti_me.bin.bin.tar.gz
(3.67 KB)
📄
tahiti_me.bin.tar
(20 KB)
📄
tahiti_pfp.bin.bin.tar.gz
(2.78 KB)
📄
tahiti_pfp.bin.tar
(20 KB)
📄
tahiti_rlc.bin.bin.tar.gz
(2.61 KB)
📄
tahiti_rlc.bin.tar
(19 KB)
📄
tahiti_smc.bin.bin.tar.gz
(26.53 KB)
📄
tahiti_smc.bin.tar
(127 KB)
📄
tahiti_uvd.bin.bin.tar.gz
(144.34 KB)
📄
tahiti_uvd.bin.tar
(216.5 KB)
📄
tail.tar
(76 KB)
📄
tail.tar.gz
(34.73 KB)
📄
tainted.tar
(2 KB)
📄
tainted.tar.gz
(112 B)
📄
tamarack.cis.cis.tar.gz
(199 B)
📄
tamarack.cis.tar
(2 KB)
📄
tangobb.tar
(189 KB)
📄
tangobb.tar.gz
(107.46 KB)
📄
tangobb.zip
(167.77 KB)
📄
tap-snapshots.tar
(5.5 KB)
📄
tap-snapshots.tar.gz
(1.06 KB)
📄
tap-snapshots.zip
(3.42 KB)
📄
tap.tar
(2 KB)
📄
tap.tar.gz
(226 B)
📄
tar.h.h.tar.gz
(1.81 KB)
📄
tar.h.tar
(5.5 KB)
📄
tar.mod.mod.tar.gz
(2.42 KB)
📄
tar.mod.tar
(13 KB)
📄
tarfile.py.py.tar.gz
(25.47 KB)
📄
tarfile.py.tar
(305 KB)
📄
tarfile.pyc.pyc.tar.gz
(27.39 KB)
📄
tarfile.pyc.tar
(76 KB)
📄
tarfile.pyo.pyo.tar.gz
(27.39 KB)
📄
tarfile.pyo.tar
(76 KB)
📄
tas2563.tar
(23.5 KB)
📄
tas2563.tar.gz
(6.32 KB)
📄
tas2563.zip
(21.01 KB)
📄
tas2781.tar
(3.63 MB)
📄
tas2781.tar.gz
(351.69 KB)
📄
tas2781.zip
(3.57 MB)
📄
task.rb.rb.tar.gz
(2.96 KB)
📄
task.rb.tar
(9.5 KB)
📄
task_manager.rb.rb.tar.gz
(2.84 KB)
📄
task_manager.rb.tar
(10.5 KB)
📄
task_sched_stat.tar
(2 KB)
📄
task_sched_stat.tar.gz
(135 B)
📄
taskfreak.tar
(165.5 KB)
📄
taskfreak.tar.gz
(90.24 KB)
📄
taskfreak.zip
(142.79 KB)
📄
taskset.tar
(39 KB)
📄
taskset.tar.gz
(15.84 KB)
📄
tastyigniter.tar
(19.4 MB)
📄
tastyigniter.tar.gz
(16.52 MB)
📄
tastyigniter.zip
(19.37 MB)
📄
taxonomy.yml.tar
(2.5 KB)
📄
taxonomy.yml.yml.tar.gz
(501 B)
📄
tbl.tar
(156.5 KB)
📄
tbl.tar.gz
(59.71 KB)
📄
tce_paths.php.php.tar.gz
(1.27 KB)
📄
tce_paths.php.tar
(5.5 KB)
📄
tcexam.sql.sql.tar.gz
(2.7 KB)
📄
tcexam.sql.tar
(21 KB)
📄
tcexam.tar
(16.83 MB)
📄
tcexam.tar.gz
(16.09 MB)
📄
tcexam.zip
(16.8 MB)
📄
tcl8.6.tar
(1.12 MB)
📄
tcl8.6.tar.gz
(259.22 KB)
📄
tcl8.6.zip
(1.02 MB)
📄
tclsh.tar
(11 KB)
📄
tclsh.tar.gz
(3.61 KB)
📄
tclsh8.6.6.tar.gz
(3.61 KB)
📄
tclsh8.6.tar
(11 KB)
📄
tcp.h.h.tar.gz
(3.92 KB)
📄
tcp.h.tar
(11.5 KB)
📄
tcp.tar
(3.67 MB)
📄
tcp.tar.gz
(47.24 KB)
📄
tcp6.tar
(70.5 KB)
📄
tcp6.tar.gz
(745 B)
📄
tcp_abort_on_overflow.tar
(2 KB)
📄
tcp_abort_on_overflow.tar.gz
(122 B)
📄
tcp_app_win.tar
(2 KB)
📄
tcp_app_win.tar.gz
(115 B)
📄
tcp_autocorking.tar
(2 KB)
📄
tcp_autocorking.tar.gz
(118 B)
📄
tcp_base_mss.tar
(2 KB)
📄
tcp_base_mss.tar.gz
(116 B)
📄
tcp_comp_sack_nr.tar
(2 KB)
📄
tcp_comp_sack_nr.tar.gz
(118 B)
📄
tcp_dsack.tar
(2 KB)
📄
tcp_dsack.tar.gz
(111 B)
📄
tcp_early_demux.tar
(2 KB)
📄
tcp_early_demux.tar.gz
(117 B)
📄
tcp_ecn.tar
(2 KB)
📄
tcp_ecn.tar.gz
(109 B)
📄
tcp_ecn_fallback.tar
(2 KB)
📄
tcp_ecn_fallback.tar.gz
(118 B)
📄
tcp_fack.tar
(2 KB)
📄
tcp_fack.tar.gz
(111 B)
📄
tcp_fastopen.tar
(2 KB)
📄
tcp_fastopen.tar.gz
(115 B)
📄
tcp_fin_timeout.tar
(3 KB)
📄
tcp_fin_timeout.tar.gz
(118 B)
📄
tcp_frto.tar
(2 KB)
📄
tcp_frto.tar.gz
(111 B)
📄
tcp_fwmark_accept.tar
(2 KB)
📄
tcp_fwmark_accept.tar.gz
(120 B)
📄
tcp_invalid_ratelimit.tar
(2 KB)
📄
tcp_invalid_ratelimit.tar.gz
(123 B)
📄
tcp_keepalive_time.tar
(2 KB)
📄
tcp_keepalive_time.tar.gz
(122 B)
📄
tcp_l3mdev_accept.tar
(2 KB)
📄
tcp_l3mdev_accept.tar.gz
(120 B)
📄
tcp_low_latency.tar
(2 KB)
📄
tcp_low_latency.tar.gz
(117 B)
📄
tcp_max_orphans.tar
(2 KB)
📄
tcp_max_orphans.tar.gz
(122 B)
📄
tcp_max_reordering.tar
(2 KB)
📄
tcp_max_reordering.tar.gz
(121 B)
📄
tcp_max_slot_table_entries.tar
(2 KB)
📄
tcp_max_slot_table_entries.tar.gz
(126 B)
📄
tcp_max_syn_backlog.tar
(2 KB)
📄
tcp_max_syn_backlog.tar.gz
(126 B)
📄
tcp_max_tw_buckets.tar
(2 KB)
📄
tcp_max_tw_buckets.tar.gz
(124 B)
📄
tcp_mem.tar
(2 KB)
📄
tcp_mem.tar.gz
(131 B)
📄
tcp_min_rtt_wlen.tar
(2 KB)
📄
tcp_min_rtt_wlen.tar.gz
(119 B)
📄
tcp_min_snd_mss.tar
(2 KB)
📄
tcp_min_snd_mss.tar.gz
(117 B)
📄
tcp_min_tso_segs.tar
(2 KB)
📄
tcp_min_tso_segs.tar.gz
(118 B)
📄
tcp_mtu_probing.tar
(2 KB)
📄
tcp_mtu_probing.tar.gz
(118 B)
📄
tcp_orphan_retries.tar
(2 KB)
📄
tcp_orphan_retries.tar.gz
(119 B)
📄
tcp_probe_interval.tar
(2 KB)
📄
tcp_probe_interval.tar.gz
(121 B)
📄
tcp_recovery.tar
(2 KB)
📄
tcp_recovery.tar.gz
(114 B)
📄
tcp_reordering.tar
(2 KB)
📄
tcp_reordering.tar.gz
(117 B)
📄
tcp_retries1.tar
(2 KB)
📄
tcp_retries1.tar.gz
(114 B)
📄
tcp_retries2.tar
(2 KB)
📄
tcp_retries2.tar.gz
(114 B)
📄
tcp_rfc1337.tar
(2 KB)
📄
tcp_rfc1337.tar.gz
(114 B)
📄
tcp_rmem.tar
(2 KB)
📄
tcp_rmem.tar.gz
(125 B)
📄
tcp_sack.tar
(2 KB)
📄
tcp_sack.tar.gz
(111 B)
📄
tcp_shrink_window.tar
(2 KB)
📄
tcp_shrink_window.tar.gz
(120 B)
📄
tcp_stdurg.tar
(2 KB)
📄
tcp_stdurg.tar.gz
(112 B)
📄
tcp_syn_retries.tar
(2 KB)
📄
tcp_syn_retries.tar.gz
(117 B)
📄
tcp_synack_retries.tar
(2 KB)
📄
tcp_synack_retries.tar.gz
(120 B)
📄
tcp_syncookies.tar
(2 KB)
📄
tcp_syncookies.tar.gz
(117 B)
📄
tcp_thin_linear_timeouts.tar
(2 KB)
📄
tcp_thin_linear_timeouts.tar.gz
(124 B)
📄
tcp_timestamps.tar
(2 KB)
📄
tcp_timestamps.tar.gz
(116 B)
📄
tcp_tw_reuse.tar
(2 KB)
📄
tcp_tw_reuse.tar.gz
(114 B)
📄
tcp_tx_skb_cache.tar
(2 KB)
📄
tcp_tx_skb_cache.tar.gz
(119 B)
📄
tcp_window_scaling.tar
(2 KB)
📄
tcp_window_scaling.tar.gz
(120 B)
📄
tcp_wmem.tar
(2 KB)
📄
tcp_wmem.tar.gz
(126 B)
📄
tcp_writer.h.h.tar.gz
(1.41 KB)
📄
tcp_writer.h.tar
(5 KB)
📄
tcsd.service.service.tar.gz
(213 B)
📄
tcsd.service.tar
(2 KB)
📄
tcvn.uni.tar
(4 KB)
📄
tcvn.uni.uni.tar.gz
(519 B)
📄
td-agent-bit.service.service.tar.gz
(293 B)
📄
td-agent-bit.service.tar
(2 KB)
📄
td-agent-bit.tar
(22.27 MB)
📄
td-agent-bit.tar.gz
(8.03 MB)
📄
td-agent-bit.zip
(22.27 MB)
📄
tdb.h.h.tar.gz
(2.56 KB)
📄
tdb.h.tar
(10.5 KB)
📄
tdb.so.so.tar.gz
(3.07 KB)
📄
tdb.so.tar
(9 KB)
📄
tdemo_chaos.py.py.tar.gz
(559 B)
📄
tdemo_chaos.py.tar
(2.5 KB)
📄
tdemo_clock.py.py.tar.gz
(1.27 KB)
📄
tdemo_clock.py.tar
(5 KB)
📄
tdemo_paint.py.py.tar.gz
(694 B)
📄
tdemo_paint.py.tar
(3 KB)
📄
tdemo_peace.py.py.tar.gz
(583 B)
📄
tdemo_peace.py.tar
(3 KB)
📄
tdemo_peace.pyo.pyo.tar.gz
(829 B)
📄
tdemo_peace.pyo.tar
(3 KB)
📄
tdemo_tree.pyc.pyc.tar.gz
(1.19 KB)
📄
tdemo_tree.pyc.tar
(4 KB)
📄
tdemo_tree.pyo.pyo.tar.gz
(1.19 KB)
📄
tdemo_tree.pyo.tar
(4 KB)
📄
tdmb_nova_12mhz.inp.inp.tar.gz
(25.12 KB)
📄
tdmb_nova_12mhz.inp.tar
(41 KB)
📄
teamd@.service.service.tar.gz
(281 B)
📄
teamd@.service.tar
(3 KB)
📄
tee.tar
(43 KB)
📄
tee.tar.gz
(17.53 KB)
📄
tegra124.tar
(149.5 KB)
📄
tegra124.tar.gz
(86.2 KB)
📄
tegra124.zip
(147.54 KB)
📄
tegra186.tar
(142.5 KB)
📄
tegra186.tar.gz
(82.57 KB)
📄
tegra186.zip
(140.54 KB)
📄
tegra194.tar
(150.5 KB)
📄
tegra194.tar.gz
(87.79 KB)
📄
tegra194.zip
(148.52 KB)
📄
tegra210.tar
(142 KB)
📄
tegra210.tar.gz
(82.58 KB)
📄
tegra210.zip
(140.04 KB)
📄
tegra_drm.h.h.tar.gz
(4.53 KB)
📄
tegra_drm.h.tar
(23 KB)
📄
tehuti.tar
(43.5 KB)
📄
tehuti.tar.gz
(7.67 KB)
📄
tehuti.zip
(41.91 KB)
📄
telnet.h.h.tar.gz
(3.82 KB)
📄
telnet.h.tar
(12 KB)
📄
telnet.pyc.pyc.tar.gz
(1.25 KB)
📄
telnet.pyc.tar
(7 KB)
📄
telnet.pyo.pyo.tar.gz
(1.25 KB)
📄
telnet.pyo.tar
(7 KB)
📄
telnet.rb.rb.tar.gz
(9.31 KB)
📄
telnet.rb.tar
(66 KB)
📄
telnet.xml.tar
(2 KB)
📄
telnet.xml.xml.tar.gz
(357 B)
📄
telnetlib.py.py.tar.gz
(6.67 KB)
📄
telnetlib.py.tar
(75 KB)
📄
temp1.php.php.tar.gz
(4.63 KB)
📄
temp1.php.tar
(17 KB)
📄
temp_prefered_lft.tar
(3 KB)
📄
temp_prefered_lft.tar.gz
(132 B)
📄
temp_valid_lft.tar
(4 KB)
📄
temp_valid_lft.tar.gz
(132 B)
📄
tempfile.py.py.tar.gz
(7.56 KB)
📄
tempfile.py.tar
(76.5 KB)
📄
tempfile.pyc.pyc.tar.gz
(7.41 KB)
📄
tempfile.pyc.tar
(21.5 KB)
📄
tempfile.pyo.pyo.tar.gz
(7.41 KB)
📄
tempfile.pyo.tar
(21.5 KB)
📄
templates.h.h.tar.gz
(759 B)
📄
templates.h.tar
(4 KB)
📄
tentacle.xml.tar
(2 KB)
📄
tentacle.xml.xml.tar.gz
(278 B)
📄
term.h.h.tar.gz
(7.85 KB)
📄
term.h.tar
(124 KB)
📄
term_entry.h.h.tar.gz
(2.97 KB)
📄
term_entry.h.tar
(20 KB)
📄
termbits.h.h.tar.gz
(1.41 KB)
📄
termbits.h.tar
(7.5 KB)
📄
termbits.ph.ph.tar.gz
(177 B)
📄
termbits.ph.tar
(2 KB)
📄
termcap.h.h.tar.gz
(1.32 KB)
📄
termcap.h.tar
(9 KB)
📄
terminal.lst.lst.tar.gz
(212 B)
📄
terminal.lst.tar
(2 KB)
📄
terminal.mod.mod.tar.gz
(1.98 KB)
📄
terminal.mod.tar
(7 KB)
📄
terminfo.mod.mod.tar.gz
(7.14 KB)
📄
terminfo.mod.tar
(20.5 KB)
📄
termio.h.h.tar.gz
(234 B)
📄
termio.h.tar
(2 KB)
📄
termios.h.h.tar.gz
(1.49 KB)
📄
termios.h.tar
(15.5 KB)
📄
termios.ph.ph.tar.gz
(176 B)
📄
termios.ph.tar
(2 KB)
📄
test.mod.mod.tar.gz
(2.82 KB)
📄
test.mod.tar
(9.5 KB)
📄
test.tar
(614 KB)
📄
test.tar.gz
(24.06 KB)
📄
test.zip
(535.8 KB)
📄
test1.php.php.tar.gz
(8.13 KB)
📄
test1.php.tar
(43 KB)
📄
test_asn1.mod.mod.tar.gz
(5.75 KB)
📄
test_asn1.mod.tar
(91 KB)
📄
test_blockarg.mod.mod.tar.gz
(738 B)
📄
test_blockarg.mod.tar
(3 KB)
📄
test_parser.pyc.pyc.tar.gz
(817 B)
📄
test_parser.pyc.tar
(3 KB)
📄
test_support.py.py.tar.gz
(157 B)
📄
test_support.py.tar
(2 KB)
📄
test_support.pyc.pyc.tar.gz
(256 B)
📄
test_support.pyc.tar
(2 KB)
📄
test_support.pyo.pyo.tar.gz
(255 B)
📄
test_support.pyo.tar
(2 KB)
📄
testlink.png.png.tar.gz
(5.56 KB)
📄
testlink.png.tar
(7.5 KB)
📄
testload.mod.mod.tar.gz
(1.5 KB)
📄
testload.mod.tar
(4.5 KB)
📄
testlogger.js.js.tar.gz
(1.17 KB)
📄
testlogger.js.tar
(5 KB)
📄
testrb.tar
(5 KB)
📄
testrb.tar.gz
(223 B)
📄
tests.tar
(747 KB)
📄
tests.tar.gz
(467.89 KB)
📄
tests.zip
(250.88 KB)
📄
testsaslauthd.tar
(18.5 KB)
📄
testsaslauthd.tar.gz
(6.63 KB)
📄
testspeed.mod.mod.tar.gz
(1.27 KB)
📄
testspeed.mod.tar
(7 KB)
📄
tex-filter.info.info.tar.gz
(918 B)
📄
tex-filter.info.tar
(4 KB)
📄
tex-filter.so.so.tar.gz
(9.78 KB)
📄
tex-filter.so.tar
(25.5 KB)
📄
tex.amf.amf.tar.gz
(246 B)
📄
tex.amf.tar
(2 KB)
📄
texcheck.pyc.pyc.tar.gz
(4.19 KB)
📄
texcheck.pyc.tar
(10 KB)
📄
texcheck.pyo.pyo.tar.gz
(4.19 KB)
📄
texcheck.pyo.tar
(10 KB)
📄
texi2html.py.py.tar.gz
(16.3 KB)
📄
texi2html.py.tar
(70 KB)
📄
texinfo.go.go.tar.gz
(19.38 KB)
📄
texinfo.go.tar
(45 KB)
📄
texinfo.tar
(112.5 KB)
📄
texinfo.tar.gz
(40.82 KB)
📄
texinfo.zip
(107.02 KB)
📄
text.rb.rb.tar.gz
(4.5 KB)
📄
text.rb.tar
(125 KB)
📄
text.sh.sh.tar.gz
(901 B)
📄
text.sh.tar
(5 KB)
📄
text.so.so.tar.gz
(8.12 KB)
📄
text.so.tar
(22 KB)
📄
textView.pyc.pyc.tar.gz
(2.01 KB)
📄
textView.pyc.tar
(5.5 KB)
📄
textView.pyo.pyo.tar.gz
(2.01 KB)
📄
textView.pyo.tar
(5.5 KB)
📄
text_formatter_test_case.rb.rb.tar.gz
(823 B)
📄
text_formatter_test_case.rb.tar
(4.5 KB)
📄
textpad.py.py.tar.gz
(2.2 KB)
📄
textpad.py.tar
(25 KB)
📄
textpad.pyc.pyc.tar.gz
(3.09 KB)
📄
textpad.pyc.tar
(8.5 KB)
📄
textpad.pyo.pyo.tar.gz
(3.09 KB)
📄
textpad.pyo.tar
(8.5 KB)
📄
textwrap.py.py.tar.gz
(5.95 KB)
📄
textwrap.py.tar
(58 KB)
📄
textwrap.pyc.pyc.tar.gz
(4.96 KB)
📄
textwrap.pyc.tar
(13.5 KB)
📄
textwrap.pyo.pyo.tar.gz
(4.92 KB)
📄
textwrap.pyo.tar
(13.5 KB)
📄
tftp-client.xml.tar
(2 KB)
📄
tftp-client.xml.xml.tar.gz
(312 B)
📄
tftp.h.h.tar.gz
(1.53 KB)
📄
tftp.h.tar
(4.5 KB)
📄
tftp.mod.mod.tar.gz
(2.89 KB)
📄
tftp.mod.tar
(8 KB)
📄
tftp.xml.tar
(4 KB)
📄
tftp.xml.xml.tar.gz
(204 B)
📄
tg1.bin.bin.tar.gz
(22.17 KB)
📄
tg1.bin.tar
(145 KB)
📄
tg2.bin.bin.tar.gz
(27.54 KB)
📄
tg2.bin.tar
(154 KB)
📄
tg3.bin.bin.tar.gz
(1.23 KB)
📄
tg3.bin.tar
(8 KB)
📄
tg357766.bin.bin.tar.gz
(229 B)
📄
tg357766.bin.tar
(2 KB)
📄
tg3_tso.bin.bin.tar.gz
(3.61 KB)
📄
tg3_tso.bin.tar
(16 KB)
📄
tg3_tso5.bin.bin.tar.gz
(2.09 KB)
📄
tg3_tso5.bin.tar
(5.5 KB)
📄
tga.mod.mod.tar.gz
(2.28 KB)
📄
tga.mod.tar
(15 KB)
📄
tgl_guc_35.2.0.bin.2.0.bin.tar.gz
(136.05 KB)
📄
tgl_guc_35.2.0.bin.tar
(409.5 KB)
📄
tgl_guc_49.0.1.bin.0.1.bin.tar.gz
(126.03 KB)
📄
tgl_guc_49.0.1.bin.tar
(316 KB)
📄
tgl_guc_62.0.0.bin.0.0.bin.tar.gz
(130.63 KB)
📄
tgl_guc_62.0.0.bin.tar
(320 KB)
📄
tgl_guc_69.0.3.bin.0.3.bin.tar.gz
(145.09 KB)
📄
tgl_guc_69.0.3.bin.tar
(337 KB)
📄
tgl_guc_70.1.1.bin.1.1.bin.tar.gz
(111.43 KB)
📄
tgl_guc_70.1.1.bin.tar
(272.5 KB)
📄
tgl_guc_70.bin.bin.tar.gz
(137.99 KB)
📄
tgl_guc_70.bin.tar
(329 KB)
📄
tgl_huc.bin.bin.tar.gz
(198.44 KB)
📄
tgl_huc.bin.tar
(578 KB)
📄
tgl_huc_7.0.12.bin.0.12.bin.tar.gz
(160.59 KB)
📄
tgl_huc_7.0.12.bin.tar
(519.5 KB)
📄
tgl_huc_7.0.3.bin.0.3.bin.tar.gz
(160.56 KB)
📄
tgl_huc_7.0.3.bin.tar
(511 KB)
📄
tgl_huc_7.5.0.bin.5.0.bin.tar.gz
(192.16 KB)
📄
tgl_huc_7.5.0.bin.tar
(569 KB)
📄
tgl_huc_7.9.3.bin.9.3.bin.tar.gz
(198.45 KB)
📄
tgl_huc_7.9.3.bin.tar
(578 KB)
📄
tgmath.h.h.tar.gz
(5.76 KB)
📄
tgmath.h.tar
(32.5 KB)
📄
tgpg.tar
(4 KB)
📄
tgpg.tar.gz
(572 B)
📄
thbees.sql.sql.tar.gz
(72.48 KB)
📄
thbees.sql.tar
(447 KB)
📄
thbees.tar
(41.71 MB)
📄
thbees.tar.gz
(37.89 MB)
📄
thbees.zip
(41.69 MB)
📄
thelia.sql.sql.tar.gz
(109.55 KB)
📄
thelia.sql.tar
(746 KB)
📄
thelia.tar
(61.87 MB)
📄
thelia.tar.gz
(57.5 MB)
📄
thelia.zip
(61.85 MB)
📄
theme.css.css.tar.gz
(41.56 KB)
📄
theme.css.tar
(293 KB)
📄
theme1.css.css.tar.gz
(41.57 KB)
📄
theme1.css.tar
(293 KB)
📄
this.py.py.tar.gz
(650 B)
📄
this.py.tar
(5.5 KB)
📄
this.pyc.pyc.tar.gz
(788 B)
📄
this.pyc.tar
(3 KB)
📄
this.pyo.pyo.tar.gz
(789 B)
📄
this.pyo.tar
(3 KB)
📄
thread-shared-types.ph.ph.tar.gz
(556 B)
📄
thread-shared-types.ph.tar
(3.5 KB)
📄
thread.h.h.tar.gz
(2.93 KB)
📄
thread.h.tar
(24 KB)
📄
thread_db.h.h.tar.gz
(4.72 KB)
📄
thread_db.h.tar
(17.5 KB)
📄
threading.py.py.tar.gz
(13.11 KB)
📄
threading.py.tar
(148 KB)
📄
threads-max.tar
(2 KB)
📄
threads-max.tar.gz
(119 B)
📄
threads.go.go.tar.gz
(4.97 KB)
📄
threads.go.tar
(13 KB)
📄
threads.h.h.tar.gz
(2.48 KB)
📄
threads.h.tar
(8 KB)
📄
threads.tar
(115 KB)
📄
threads.tar.gz
(26.75 KB)
📄
threads.zip
(100.52 KB)
📄
throughput-performance.tar
(5 KB)
📄
throughput-performance.tar.gz
(1.6 KB)
📄
throughput-performance.zip
(3.25 KB)
📄
throughput.py.py.tar.gz
(948 B)
📄
throughput.py.tar
(4 KB)
📄
thumb.php.php.tar.gz
(255 B)
📄
thumb.php.tar
(2 KB)
📄
thumbnailers.tar
(2 KB)
📄
thumbnailers.tar.gz
(166 B)
📄
thumbnailers.zip
(277 B)
📄
ti-connectivity.tar
(9.18 MB)
📄
ti-connectivity.tar.gz
(5.2 MB)
📄
ti-connectivity.zip
(9.16 MB)
📄
ti-keystone.tar
(3.5 KB)
📄
ti-keystone.tar.gz
(1.29 KB)
📄
ti-keystone.zip
(1.93 KB)
📄
ti.tar
(3.66 MB)
📄
ti.tar.gz
(360.75 KB)
📄
ti.zip
(3.6 MB)
📄
ti_3410.fw.fw.tar.gz
(7.55 KB)
📄
ti_3410.fw.tar
(29 KB)
📄
ti_5052.fw.fw.tar.gz
(7.53 KB)
📄
ti_5052.fw.tar
(29 KB)
📄
tic.h.h.tar.gz
(4.78 KB)
📄
tic.h.tar
(43 KB)
📄
tic.pc.pc.tar.gz
(359 B)
📄
tic.pc.tar
(2 KB)
📄
tic.tar
(87 KB)
📄
tic.tar.gz
(38.76 KB)
📄
tidy.tar
(886.5 KB)
📄
tidy.tar.gz
(262.24 KB)
📄
tiff.h.h.tar.gz
(11.62 KB)
📄
tiff.h.tar
(37 KB)
📄
tiffconf-64.h.h.tar.gz
(1.45 KB)
📄
tiffconf-64.h.tar
(5 KB)
📄
tiffconf.h.h.tar.gz
(253 B)
📄
tiffconf.h.tar
(2 KB)
📄
tiffio.h.h.tar.gz
(6.56 KB)
📄
tiffio.h.tar
(24.5 KB)
📄
tiffio.hxx.hxx.tar.gz
(1.02 KB)
📄
tiffio.hxx.tar
(3.5 KB)
📄
tiffvers.h.h.tar.gz
(359 B)
📄
tiffvers.h.tar
(2 KB)
📄
tigon.tar
(17.5 KB)
📄
tigon.tar.gz
(6.18 KB)
📄
tigon.zip
(13.92 KB)
📄
tiki.png.png.tar.gz
(4.94 KB)
📄
tiki.png.tar
(7 KB)
📄
tiki.tar
(332 KB)
📄
tiki.tar.gz
(199.03 KB)
📄
tiki.zip
(303.36 KB)
📄
tiki10.sql.sql.tar.gz
(744.1 KB)
📄
tiki10.sql.tar
(3.62 MB)
📄
tiki10.tar
(124.73 MB)
📄
tiki10.tar.gz
(110.87 MB)
📄
tiki10.zip
(124.7 MB)
📄
tiki15.tar
(245 KB)
📄
tiki15.tar.gz
(140.92 KB)
📄
tiki15.zip
(218.68 KB)
📄
tiki22.sql.sql.tar.gz
(1.99 MB)
📄
tiki22.sql.tar
(8.42 MB)
📄
tiki22.tar
(192.37 MB)
📄
tiki22.tar.gz
(176.02 MB)
📄
tiki22.zip
(192.34 MB)
📄
tiki24.sql.sql.tar.gz
(1.36 MB)
📄
tiki24.sql.tar
(6.24 MB)
📄
tiki24.tar
(158.69 MB)
📄
tiki24.tar.gz
(141.37 MB)
📄
tiki24.zip
(158.66 MB)
📄
tile38.xml.tar
(2 KB)
📄
tile38.xml.xml.tar.gz
(259 B)
📄
time-exceeded.xml.tar
(2 KB)
📄
time-exceeded.xml.xml.tar.gz
(280 B)
📄
time-sync.target.tar
(3 KB)
📄
time-sync.target.target.tar.gz
(399 B)
📄
time.go.go.tar.gz
(1.45 KB)
📄
time.go.tar
(4.5 KB)
📄
time.h.h.tar.gz
(3.46 KB)
📄
time.h.tar
(22.5 KB)
📄
time.mod.mod.tar.gz
(933 B)
📄
time.mod.tar
(3.5 KB)
📄
time.ph.ph.tar.gz
(729 B)
📄
time.ph.tar
(4 KB)
📄
time.rb.rb.tar.gz
(6.88 KB)
📄
time.rb.tar
(88 KB)
📄
time.so.so.tar.gz
(3.87 KB)
📄
time.so.tar
(13.5 KB)
📄
time64.h.h.tar.gz
(739 B)
📄
time64.h.tar
(3.5 KB)
📄
time_t.h.h.tar.gz
(193 B)
📄
time_t.h.tar
(2 KB)
📄
timeb.h.h.tar.gz
(841 B)
📄
timeb.h.tar
(3 KB)
📄
timed.h.h.tar.gz
(1.8 KB)
📄
timed.h.tar
(5.5 KB)
📄
timedatex.service.service.tar.gz
(276 B)
📄
timedatex.service.tar
(2 KB)
📄
timeit.py.py.tar.gz
(4.63 KB)
📄
timeit.py.tar
(42 KB)
📄
timeit.pyc.pyc.tar.gz
(5.4 KB)
📄
timeit.pyc.tar
(13.5 KB)
📄
timeit.pyo.pyo.tar.gz
(5.4 KB)
📄
timeit.pyo.tar
(13.5 KB)
📄
timeout.rb.rb.tar.gz
(1.81 KB)
📄
timeout.rb.tar
(18.5 KB)
📄
timeout.tar
(43.5 KB)
📄
timeout.tar.gz
(19.36 KB)
📄
timer_migration.tar
(2 KB)
📄
timer_migration.tar.gz
(116 B)
📄
timerfd.h.h.tar.gz
(707 B)
📄
timerfd.h.tar
(5.5 KB)
📄
timers.target.tar
(3 KB)
📄
timers.target.target.tar.gz
(393 B)
📄
times.h.h.tar.gz
(900 B)
📄
times.h.tar
(3.5 KB)
📄
timex.h.h.tar.gz
(1.06 KB)
📄
timex.h.tar
(4 KB)
📄
timezone.h.h.tar.gz
(10.3 KB)
📄
timezone.h.tar
(43 KB)
📄
tinc.xml.tar
(2 KB)
📄
tinc.xml.xml.tar.gz
(312 B)
📄
tine.png.png.tar.gz
(23.11 KB)
📄
tine.png.tar
(24.5 KB)
📄
tine.tar
(178 KB)
📄
tine.tar.gz
(103.97 KB)
📄
tine.zip
(157.88 KB)
📄
tinfo.pc.pc.tar.gz
(368 B)
📄
tinfo.pc.tar
(2 KB)
📄
tinyrss.tar
(161.5 KB)
📄
tinyrss.tar.gz
(84.56 KB)
📄
tinyrss.zip
(137.84 KB)
📄
tix.py.py.tar.gz
(15.4 KB)
📄
tix.py.tar
(77 KB)
📄
tix.tar
(353 KB)
📄
tix.tar.gz
(84.85 KB)
📄
tix.zip
(309.77 KB)
📄
tixwidgets.pyc.pyc.tar.gz
(12.94 KB)
📄
tixwidgets.pyc.tar
(39.5 KB)
📄
tixwidgets.pyo.pyo.tar.gz
(12.94 KB)
📄
tixwidgets.pyo.tar
(39.5 KB)
📄
tk.gif.gif.tar.gz
(203 B)
📄
tk.gif.tar
(2 KB)
📄
tk8.6.tar
(2 KB)
📄
tk8.6.tar.gz
(200 B)
📄
tk8.6.zip
(296 B)
📄
tkinter.tar
(2.28 MB)
📄
tkinter.tar.gz
(387.5 KB)
📄
tkinter.zip
(2.12 MB)
📄
tld.h.h.tar.gz
(1.74 KB)
📄
tld.h.tar
(6.5 KB)
📄
tlg2300_firmware.bin.bin.tar.gz
(35.82 KB)
📄
tlg2300_firmware.bin.tar
(52.5 KB)
📄
tload.tar
(18.5 KB)
📄
tload.tar.gz
(7.19 KB)
📄
tls.tar
(21.5 KB)
📄
tls.tar.gz
(8.41 KB)
📄
tls.zip
(20.01 KB)
📄
tls1.h.h.tar.gz
(10.08 KB)
📄
tls1.h.tar
(72.5 KB)
📄
tlv.h.h.tar.gz
(1.23 KB)
📄
tlv.h.tar
(5.5 KB)
📄
tmp.conf.conf.tar.gz
(493 B)
📄
tmp.conf.tar
(4 KB)
📄
tmp.mount.mount.tar.gz
(582 B)
📄
tmp.mount.tar
(2.5 KB)
📄
tmp.tar
(168.57 MB)
📄
tmp.tar.gz
(59.98 MB)
📄
tmp.zip
(167.58 MB)
📄
tmpfiles.d.tar
(43.5 KB)
📄
tmpfiles.d.tar.gz
(4.17 KB)
📄
tmpfiles.d.zip
(15.64 KB)
📄
tmpwatch.tar
(73 KB)
📄
tmpwatch.tar.gz
(14.46 KB)
📄
to_bs.rb.rb.tar.gz
(840 B)
📄
to_bs.rb.tar
(3.5 KB)
📄
to_tt_only.rb.rb.tar.gz
(1.01 KB)
📄
to_tt_only.rb.tar
(4 KB)
📄
toaiff.py.py.tar.gz
(1.27 KB)
📄
toaiff.py.tar
(5 KB)
📄
toaiff.pyc.pyc.tar.gz
(1.56 KB)
📄
toaiff.pyc.tar
(5 KB)
📄
toaiff.pyo.pyo.tar.gz
(1.56 KB)
📄
toaiff.pyo.tar
(5 KB)
📄
toaster.sql.sql.tar.gz
(69.46 KB)
📄
toaster.sql.tar
(508.5 KB)
📄
toaster.tar
(152.09 MB)
📄
toaster.tar.gz
(146.49 MB)
📄
toaster.zip
(152.06 MB)
📄
toe.tar
(18 KB)
📄
toe.tar.gz
(7.4 KB)
📄
token.py.py.tar.gz
(1.43 KB)
📄
token.py.tar
(11.5 KB)
📄
token.pyc.pyc.tar.gz
(1.93 KB)
📄
token.pyc.tar
(5.5 KB)
📄
token.pyo.pyo.tar.gz
(1.93 KB)
📄
token.pyo.tar
(5.5 KB)
📄
tokenize.py.py.tar.gz
(8.56 KB)
📄
tokenize.py.tar
(74.5 KB)
📄
tokenize.pyc.pyc.tar.gz
(6.38 KB)
📄
tokenize.pyc.tar
(16 KB)
📄
tokenize.pyo.pyo.tar.gz
(6.35 KB)
📄
tokenize.pyo.tar
(16 KB)
📄
tokens.h.h.tar.gz
(2.2 KB)
📄
tokens.h.tar
(13.5 KB)
📄
tonga_ce.bin.bin.tar.gz
(2.96 KB)
📄
tonga_ce.bin.tar
(10.5 KB)
📄
tonga_k_smc.bin.bin.tar.gz
(55.81 KB)
📄
tonga_k_smc.bin.tar
(129 KB)
📄
tonga_mc.bin.bin.tar.gz
(13.09 KB)
📄
tonga_mc.bin.tar
(32.5 KB)
📄
tonga_me.bin.bin.tar.gz
(6.86 KB)
📄
tonga_me.bin.tar
(18.5 KB)
📄
tonga_mec.bin.bin.tar.gz
(26.32 KB)
📄
tonga_mec.bin.tar
(258.5 KB)
📄
tonga_mec2.bin.bin.tar.gz
(26.32 KB)
📄
tonga_mec2.bin.tar
(258.5 KB)
📄
tonga_pfp.bin.bin.tar.gz
(8.49 KB)
📄
tonga_pfp.bin.tar
(18.5 KB)
📄
tonga_rlc.bin.bin.tar.gz
(5.66 KB)
📄
tonga_rlc.bin.tar
(16 KB)
📄
tonga_sdma.bin.bin.tar.gz
(4.04 KB)
📄
tonga_sdma.bin.tar
(12 KB)
📄
tonga_sdma1.bin.bin.tar.gz
(4.04 KB)
📄
tonga_sdma1.bin.tar
(12 KB)
📄
tonga_smc.bin.bin.tar.gz
(56.15 KB)
📄
tonga_smc.bin.tar
(129 KB)
📄
tonga_uvd.bin.bin.tar.gz
(223.2 KB)
📄
tonga_uvd.bin.tar
(319.5 KB)
📄
tonga_vce.bin.bin.tar.gz
(94.17 KB)
📄
tonga_vce.bin.tar
(159 KB)
📄
tool.py.py.tar.gz
(874 B)
📄
tool.py.tar
(7.5 KB)
📄
top.tar
(123.5 KB)
📄
top.tar.gz
(57.04 KB)
📄
topaz_ce.bin.bin.tar.gz
(2.74 KB)
📄
topaz_ce.bin.tar
(10.5 KB)
📄
topaz_k_smc.bin.bin.tar.gz
(33.18 KB)
📄
topaz_k_smc.bin.tar
(80.5 KB)
📄
topaz_mc.bin.bin.tar.gz
(13.18 KB)
📄
topaz_mc.bin.tar
(33 KB)
📄
topaz_me.bin.bin.tar.gz
(6.47 KB)
📄
topaz_me.bin.tar
(18.5 KB)
📄
topaz_mec.bin.bin.tar.gz
(22.36 KB)
📄
topaz_mec.bin.tar
(258.5 KB)
📄
topaz_mec2.bin.bin.tar.gz
(15.79 KB)
📄
topaz_mec2.bin.tar
(258.5 KB)
📄
topaz_pfp.bin.bin.tar.gz
(7.48 KB)
📄
topaz_pfp.bin.tar
(18.5 KB)
📄
topaz_rlc.bin.bin.tar.gz
(2.67 KB)
📄
topaz_rlc.bin.tar
(10 KB)
📄
topaz_sdma.bin.bin.tar.gz
(2.83 KB)
📄
topaz_sdma.bin.tar
(10 KB)
📄
topaz_sdma1.bin.bin.tar.gz
(2.83 KB)
📄
topaz_sdma1.bin.tar
(10 KB)
📄
topaz_smc.bin.bin.tar.gz
(33.04 KB)
📄
topaz_smc.bin.tar
(80.5 KB)
📄
tor-socks.xml.tar
(2.5 KB)
📄
tor-socks.xml.xml.tar.gz
(544 B)
📄
tortoisemerge.tar
(2.5 KB)
📄
tortoisemerge.tar.gz
(445 B)
📄
tos-host-redirect.xml.tar
(2 KB)
📄
tos-host-redirect.xml.xml.tar.gz
(276 B)
📄
touch.tar
(95.5 KB)
📄
touch.tar.gz
(45.02 KB)
📄
tput.tar
(26.5 KB)
📄
tput.tar.gz
(10 KB)
📄
tr.mod.mod.tar.gz
(1.34 KB)
📄
tr.mod.tar
(8 KB)
📄
tr.tar
(89.5 KB)
📄
tr.tar.gz
(23.61 KB)
📄
tr.zip
(30.89 KB)
📄
trace.py.py.tar.gz
(8.16 KB)
📄
trace.py.tar
(90 KB)
📄
trace.pyc.pyc.tar.gz
(9.47 KB)
📄
trace.pyc.tar
(24 KB)
📄
trace.pyo.pyo.tar.gz
(9.44 KB)
📄
trace.pyo.tar
(24 KB)
📄
traceback.h.h.tar.gz
(407 B)
📄
traceback.h.tar
(2.5 KB)
📄
traceback.py.py.tar.gz
(6.31 KB)
📄
traceback.py.tar
(60.5 KB)
📄
traceevent.tar
(118 KB)
📄
traceevent.tar.gz
(30.16 KB)
📄
traceevent.zip
(110.08 KB)
📄
tracemalloc.py.py.tar.gz
(3.54 KB)
📄
tracemalloc.py.tar
(35.5 KB)
📄
traceoff_on_warning.tar
(2 KB)
📄
traceoff_on_warning.tar.gz
(120 B)
📄
tracepoint_printk.tar
(2 KB)
📄
tracepoint_printk.tar.gz
(117 B)
📄
traceroute.tar
(72.5 KB)
📄
traceroute.tar.gz
(33.66 KB)
📄
trans.tar
(2.79 MB)
📄
trans.tar.gz
(1.34 MB)
📄
trans.zip
(2.78 MB)
📄
transdb.so.so.tar.gz
(5.23 KB)
📄
transdb.so.tar
(17 KB)
📄
transform.h.h.tar.gz
(1.13 KB)
📄
transform.h.tar
(8 KB)
📄
transformer.py.py.tar.gz
(11.06 KB)
📄
transformer.py.tar
(53.5 KB)
📄
translit.h.h.tar.gz
(16.04 KB)
📄
translit.h.tar
(67.5 KB)
📄
transports.tar
(2 KB)
📄
transports.tar.gz
(124 B)
📄
traq.png.png.tar.gz
(4.39 KB)
📄
traq.png.tar
(6.5 KB)
📄
traq.sql.sql.tar.gz
(3.32 KB)
📄
traq.sql.tar
(23.5 KB)
📄
traq.tar
(1.46 MB)
📄
traq.tar.gz
(1.18 MB)
📄
traq.zip
(1.43 MB)
📄
treesync.pyc.pyc.tar.gz
(2.81 KB)
📄
treesync.pyc.tar
(7.5 KB)
📄
treesync.pyo.pyo.tar.gz
(2.81 KB)
📄
treesync.pyo.tar
(7.5 KB)
📄
tribar.so.so.tar.gz
(8.12 KB)
📄
tribar.so.tar
(22 KB)
📄
trig.mod.mod.tar.gz
(898 B)
📄
trig.mod.tar
(3.5 KB)
📄
trigger_code.bin.bin.tar.gz
(273 B)
📄
trigger_code.bin.tar
(2 KB)
📄
trivial.tar
(3.5 KB)
📄
trivial.tar.gz
(774 B)
📄
troff.tar
(807 KB)
📄
troff.tar.gz
(279.07 KB)
📄
trsock.py.py.tar.gz
(1.34 KB)
📄
trsock.py.tar
(7.5 KB)
📄
true.mod.mod.tar.gz
(696 B)
📄
true.mod.tar
(3 KB)
📄
true.tar
(35 KB)
📄
true.tar.gz
(14.44 KB)
📄
truecrypt.mod.mod.tar.gz
(2.02 KB)
📄
truecrypt.mod.tar
(11 KB)
📄
truncate.tar
(43 KB)
📄
truncate.tar.gz
(18.05 KB)
📄
trusted-key.key.key.tar.gz
(417 B)
📄
trusted-key.key.tar
(2 KB)
📄
trusted.xml.tar
(2 KB)
📄
trusted.xml.xml.tar.gz
(233 B)
📄
ts.h.h.tar.gz
(8.39 KB)
📄
ts.h.tar
(58 KB)
📄
tserr.h.h.tar.gz
(1.66 KB)
📄
tserr.h.tar
(8.5 KB)
📄
tset.tar
(26.5 KB)
📄
tset.tar.gz
(11.37 KB)
📄
tsig-keygen.tar
(22 KB)
📄
tsig-keygen.tar.gz
(8.83 KB)
📄
tsort.tar
(43 KB)
📄
tsort.tar.gz
(17.94 KB)
📄
tsse_firmware.bin.bin.tar.gz
(137.99 KB)
📄
tsse_firmware.bin.tar
(522 KB)
📄
ttk.py.py.tar.gz
(14.17 KB)
📄
ttk.py.tar
(57.5 KB)
📄
ttusb-budget.tar
(14.5 KB)
📄
ttusb-budget.tar.gz
(6.54 KB)
📄
ttusb-budget.zip
(12.96 KB)
📄
tty.py.py.tar.gz
(479 B)
📄
tty.py.tar
(5.5 KB)
📄
tty.pyc.pyc.tar.gz
(768 B)
📄
tty.pyc.tar
(3 KB)
📄
tty.pyo.pyo.tar.gz
(769 B)
📄
tty.pyo.tar
(3 KB)
📄
tty.tar
(35 KB)
📄
tty.tar.gz
(14.67 KB)
📄
ttychars.h.h.tar.gz
(1.31 KB)
📄
ttychars.h.tar
(4 KB)
📄
ttydefaults.ph.ph.tar.gz
(763 B)
📄
ttydefaults.ph.tar
(4 KB)
📄
ttyent.h.h.tar.gz
(1.31 KB)
📄
ttyent.h.tar
(4 KB)
📄
tu102.tar
(50.28 MB)
📄
tu102.tar.gz
(28.98 MB)
📄
tu102.zip
(50.26 MB)
📄
tu10x.tar
(328.5 KB)
📄
tu10x.tar.gz
(133.36 KB)
📄
tu10x.zip
(325.38 KB)
📄
tuned.conf.conf.tar.gz
(465 B)
📄
tuned.conf.tar
(25 KB)
📄
tuned.service.service.tar.gz
(377 B)
📄
tuned.service.tar
(3 KB)
📄
tuned.tar
(57 KB)
📄
tuned.tar.gz
(10.95 KB)
📄
tuned.zip
(39.01 KB)
📄
turtle.py.py.tar.gz
(33.13 KB)
📄
turtle.py.tar
(142 KB)
📄
turtle.tar
(231.5 KB)
📄
turtle.tar.gz
(60.62 KB)
📄
turtle.zip
(195.9 KB)
📄
turtledemo.tar
(317.5 KB)
📄
turtledemo.tar.gz
(84.47 KB)
📄
turtledemo.zip
(267.35 KB)
📄
twg.png.png.tar.gz
(19.05 KB)
📄
twg.png.tar
(20.5 KB)
📄
twg.tar
(2.8 MB)
📄
twg.tar.gz
(2.7 MB)
📄
twg.zip
(2.87 MB)
📄
txets.php.php.tar.gz
(1.01 KB)
📄
txets.php.tar
(4.5 KB)
📄
txrehash.tar
(2 KB)
📄
txrehash.tar.gz
(110 B)
📄
txt_db.h.h.tar.gz
(809 B)
📄
txt_db.h.tar
(3.5 KB)
📄
txtpat.sql.sql.tar.gz
(34.8 KB)
📄
txtpat.sql.tar
(175 KB)
📄
txtpat.tar
(4.27 MB)
📄
txtpat.tar.gz
(3.91 MB)
📄
txtpat.zip
(4.24 MB)
📄
typelib.h.h.tar.gz
(1.33 KB)
📄
typelib.h.tar
(4.5 KB)
📄
types.h.h.tar.gz
(2.83 KB)
📄
types.h.tar
(23 KB)
📄
types.ph.ph.tar.gz
(845 B)
📄
types.ph.tar
(9.5 KB)
📄
types.py.py.tar.gz
(2.93 KB)
📄
types.py.tar
(23.5 KB)
📄
types.pyc.pyc.tar.gz
(1.33 KB)
📄
types.pyc.tar
(4.5 KB)
📄
types.pyo.pyo.tar.gz
(1.33 KB)
📄
types.pyo.tar
(4.5 KB)
📄
types.tar
(87.5 KB)
📄
types.tar.gz
(1.75 KB)
📄
types.zip
(10.69 KB)
📄
typesizes.h.h.tar.gz
(1.3 KB)
📄
typesizes.h.tar
(5 KB)
📄
typeslots.h.h.tar.gz
(810 B)
📄
typeslots.h.tar
(4 KB)
📄
typhoon.bin.bin.tar.gz
(29.81 KB)
📄
typhoon.bin.tar
(90 KB)
📄
typing.py.py.tar.gz
(19.24 KB)
📄
typing.py.tar
(148 KB)
📄
typo.png.png.tar.gz
(14.73 KB)
📄
typo.png.tar
(16.5 KB)
📄
typo.tar
(213 KB)
📄
typo.tar.gz
(118.59 KB)
📄
typo.zip
(183.97 KB)
📄
typo47.tar
(230.5 KB)
📄
typo47.tar.gz
(134.26 KB)
📄
typo47.zip
(205.83 KB)
📄
typo7.sql.sql.tar.gz
(5.68 KB)
📄
typo7.sql.tar
(54.5 KB)
📄
typo7.tar
(33.35 MB)
📄
typo7.tar.gz
(29.15 MB)
📄
typo7.zip
(33.33 MB)
📄
typo8.sql.sql.tar.gz
(5.7 KB)
📄
typo8.sql.tar
(61 KB)
📄
typo8.tar
(33.93 MB)
📄
typo8.tar.gz
(29.45 MB)
📄
typo8.zip
(33.9 MB)
📄
tzfmt.h.h.tar.gz
(8.16 KB)
📄
tzfmt.h.tar
(44.5 KB)
📄
tzselect.tar
(17 KB)
📄
tzselect.tar.gz
(5.93 KB)
📄
uapi.tar
(3 KB)
📄
uapi.tar.gz
(709 B)
📄
uartiw416_bt_v0.bin.bin.tar.gz
(104.9 KB)
📄
uartiw416_bt_v0.bin.tar
(151.5 KB)
📄
uartspi_n61x_v1.bin.se.bin.se.tar.gz
(245.99 KB)
📄
uartspi_n61x_v1.bin.se.tar
(248 KB)
📄
uartuart8987_bt.bin.bin.tar.gz
(140.28 KB)
📄
uartuart8987_bt.bin.tar
(206.5 KB)
📄
uartuart8997_bt_v4.bin.bin.tar.gz
(122 KB)
📄
uartuart8997_bt_v4.bin.tar
(180.5 KB)
📄
uartuart9098_bt_v1.bin.bin.tar.gz
(132.28 KB)
📄
uartuart9098_bt_v1.bin.tar
(189 KB)
📄
uauctions.tar
(226 KB)
📄
uauctions.tar.gz
(137.57 KB)
📄
uauctions.zip
(206.55 KB)
📄
ubi-user.h.h.tar.gz
(5.57 KB)
📄
ubi-user.h.tar
(19 KB)
📄
ubidi.h.h.tar.gz
(20 KB)
📄
ubidi.h.tar
(91.5 KB)
📄
ubygems.rb.rb.tar.gz
(328 B)
📄
ubygems.rb.tar
(4 KB)
📄
ucasemap.h.h.tar.gz
(3.02 KB)
📄
ucasemap.h.tar
(17 KB)
📄
ucast_solicit.tar
(7 KB)
📄
ucast_solicit.tar.gz
(124 B)
📄
uchar.h.h.tar.gz
(29.44 KB)
📄
uchar.h.tar
(145 KB)
📄
uchriter.h.h.tar.gz
(2.71 KB)
📄
uchriter.h.tar
(15 KB)
📄
ucnhash.h.h.tar.gz
(629 B)
📄
ucnhash.h.tar
(3 KB)
📄
ucnv_err.h.h.tar.gz
(3.86 KB)
📄
ucnv_err.h.tar
(22.5 KB)
📄
ucoleitr.h.h.tar.gz
(2.75 KB)
📄
ucoleitr.h.tar
(11 KB)
📄
uconfig.h.h.tar.gz
(32.89 KB)
📄
uconfig.h.tar
(165 KB)
📄
ucontext.h.h.tar.gz
(1.04 KB)
📄
ucontext.h.tar
(14 KB)
📄
ucontext.ph.ph.tar.gz
(780 B)
📄
ucontext.ph.tar
(5 KB)
📄
ucurr.h.h.tar.gz
(4.22 KB)
📄
ucurr.h.tar
(18 KB)
📄
udata.h.h.tar.gz
(4.94 KB)
📄
udata.h.tar
(17.5 KB)
📄
udev.tar
(9.2 MB)
📄
udev.tar.gz
(1.86 MB)
📄
udev.zip
(9.13 MB)
📄
udf.mod.mod.tar.gz
(5.67 KB)
📄
udf.mod.tar
(27 KB)
📄
udp.h.h.tar.gz
(1.74 KB)
📄
udp.h.tar
(5.5 KB)
📄
udp.tar
(67.5 KB)
📄
udp.tar.gz
(755 B)
📄
udp6.tar
(15 KB)
📄
udp6.tar.gz
(356 B)
📄
udp_early_demux.tar
(2 KB)
📄
udp_early_demux.tar.gz
(118 B)
📄
udp_l3mdev_accept.tar
(2 KB)
📄
udp_l3mdev_accept.tar.gz
(120 B)
📄
udp_mem.tar
(2 KB)
📄
udp_mem.tar.gz
(130 B)
📄
udp_rmem_min.tar
(2 KB)
📄
udp_rmem_min.tar.gz
(118 B)
📄
udp_wmem_min.tar
(2 KB)
📄
udp_wmem_min.tar.gz
(118 B)
📄
udpdump.tar
(31 KB)
📄
udpdump.tar.gz
(12.21 KB)
📄
udpecho.py.py.tar.gz
(640 B)
📄
udpecho.py.tar
(3 KB)
📄
udr.tar
(604 KB)
📄
udr.tar.gz
(156.18 KB)
📄
udr.zip
(601.66 KB)
📄
ueagle-atm.tar
(2.1 MB)
📄
ueagle-atm.tar.gz
(1.02 MB)
📄
ueagle-atm.zip
(2.09 MB)
📄
uenum.h.h.tar.gz
(2.21 KB)
📄
uenum.h.tar
(9.5 KB)
📄
ufs1.mod.mod.tar.gz
(3.55 KB)
📄
ufs1.mod.tar
(17 KB)
📄
ufs1_be.mod.mod.tar.gz
(3.75 KB)
📄
ufs1_be.mod.tar
(9.5 KB)
📄
ufs2.mod.mod.tar.gz
(3.6 KB)
📄
ufs2.mod.tar
(17 KB)
📄
uhci.mod.mod.tar.gz
(3.75 KB)
📄
uhci.mod.tar
(19 KB)
📄
ui.h.h.tar.gz
(6.01 KB)
📄
ui.h.tar
(36.5 KB)
📄
uidna.h.h.tar.gz
(5.85 KB)
📄
uidna.h.tar
(35 KB)
📄
uierr.h.h.tar.gz
(951 B)
📄
uierr.h.tar
(4.5 KB)
📄
uikit.tar
(370.5 KB)
📄
uikit.tar.gz
(348.48 KB)
📄
uikit.zip
(360.16 KB)
📄
uintn-identity.h.h.tar.gz
(872 B)
📄
uintn-identity.h.tar
(3.5 KB)
📄
uintn-identity.ph.ph.tar.gz
(390 B)
📄
uintn-identity.ph.tar
(2.5 KB)
📄
uio-ext.h.h.tar.gz
(959 B)
📄
uio-ext.h.tar
(3.5 KB)
📄
uio.h.h.tar.gz
(1.51 KB)
📄
uio.h.tar
(8 KB)
📄
uio_lim.h.h.tar.gz
(851 B)
📄
uio_lim.h.tar
(3 KB)
📄
uiter.h.h.tar.gz
(5.09 KB)
📄
uiter.h.tar
(24.5 KB)
📄
uk.tar
(121 KB)
📄
uk.tar.gz
(105.81 KB)
📄
uk.zip
(107.96 KB)
📄
ul.tar
(22.5 KB)
📄
ul.tar.gz
(8.99 KB)
📄
uldnames.h.h.tar.gz
(2 KB)
📄
uldnames.h.tar
(12 KB)
📄
ulimit.h.h.tar.gz
(932 B)
📄
ulimit.h.tar
(3.5 KB)
📄
uloc.h.h.tar.gz
(10.9 KB)
📄
uloc.h.tar
(52.5 KB)
📄
ulocdata.h.h.tar.gz
(3.05 KB)
📄
ulocdata.h.tar
(13 KB)
📄
umachine.h.h.tar.gz
(4.01 KB)
📄
umachine.h.tar
(15 KB)
📄
umich_ldap.so.so.tar.gz
(23.03 KB)
📄
umich_ldap.so.tar
(55 KB)
📄
umisc.h.h.tar.gz
(743 B)
📄
umisc.h.tar
(3 KB)
📄
umount.target.tar
(3 KB)
📄
umount.target.target.tar.gz
(404 B)
📄
umsch_mm_4_0_0.bin.bin.tar.gz
(34.35 KB)
📄
umsch_mm_4_0_0.bin.tar
(379.5 KB)
📄
un.h.h.tar.gz
(902 B)
📄
un.h.tar
(3 KB)
📄
una.png.png.tar.gz
(17.09 KB)
📄
una.png.tar
(19 KB)
📄
una.sql.sql.tar.gz
(242.7 KB)
📄
una.sql.tar
(1.15 MB)
📄
una.tar
(58.81 MB)
📄
una.tar.gz
(56.02 MB)
📄
una.zip
(58.79 MB)
📄
uname.tar
(39 KB)
📄
uname.tar.gz
(15.69 KB)
📄
unb.png.png.tar.gz
(3.21 KB)
📄
unb.png.tar
(5 KB)
📄
unb.tar
(111.5 KB)
📄
unb.tar.gz
(58.9 KB)
📄
unb.zip
(95.59 KB)
📄
unbirthday.py.py.tar.gz
(1.25 KB)
📄
unbirthday.py.tar
(5 KB)
📄
unbound-anchor.service.service.tar.gz
(307 B)
📄
unbound-anchor.service.tar
(2 KB)
📄
unbound-anchor.timer.tar
(2 KB)
📄
unbound-anchor.timer.timer.tar.gz
(356 B)
📄
unctrl.h.h.tar.gz
(1.29 KB)
📄
unctrl.h.tar
(13 KB)
📄
undill.tar
(2.5 KB)
📄
undill.tar.gz
(498 B)
📄
unexpand.tar
(47.5 KB)
📄
unexpand.tar.gz
(19.9 KB)
📄
unicast.py.py.tar.gz
(291 B)
📄
unicast.py.tar
(2 KB)
📄
unicode.go.go.tar.gz
(535 B)
📄
unicode.go.tar
(2.5 KB)
📄
unicode.tar
(4.49 MB)
📄
unicode.tar.gz
(897.49 KB)
📄
unicode.zip
(4.38 MB)
📄
unicode_constants.h.h.tar.gz
(1.94 KB)
📄
unicode_constants.h.tar
(9.5 KB)
📄
unicode_normalize.zip
(182.72 KB)
📄
unifunct.h.h.tar.gz
(1.52 KB)
📄
unifunct.h.tar
(5.5 KB)
📄
unimaps.tar
(265.5 KB)
📄
unimaps.tar.gz
(46.45 KB)
📄
unimaps.zip
(225.14 KB)
📄
unimatch.h.h.tar.gz
(2.18 KB)
📄
unimatch.h.tar
(8 KB)
📄
uniq.tar
(51.5 KB)
📄
uniq.tar.gz
(22.76 KB)
📄
unistd.h.h.tar.gz
(11.23 KB)
📄
unistd.h.tar
(57 KB)
📄
unistd.ph.ph.tar.gz
(306 B)
📄
unistd.ph.tar
(2 KB)
📄
unistd_32.h.h.tar.gz
(2.95 KB)
📄
unistd_32.h.tar
(12.5 KB)
📄
unistd_32.ph.ph.tar.gz
(4.47 KB)
📄
unistd_32.ph.tar
(31 KB)
📄
unistd_64.h.h.tar.gz
(2.56 KB)
📄
unistd_64.h.tar
(11 KB)
📄
unistd_64.ph.ph.tar.gz
(3.89 KB)
📄
unistd_64.ph.tar
(26.5 KB)
📄
unistd_x32.h.h.tar.gz
(2.75 KB)
📄
unistd_x32.h.tar
(18 KB)
📄
unittest.tar
(2.08 MB)
📄
unittest.tar.gz
(247.43 KB)
📄
unittest.zip
(2.01 MB)
📄
universal.php.php.tar.gz
(561 B)
📄
universal.php.tar
(3.5 KB)
📄
unix.tar
(1.69 MB)
📄
unix.tar.gz
(27.07 KB)
📄
unix.zip
(166 B)
📄
unix_chkpwd.tar
(38.5 KB)
📄
unix_chkpwd.tar.gz
(15.84 KB)
📄
unix_writer.h.h.tar.gz
(1.31 KB)
📄
unix_writer.h.tar
(4.5 KB)
📄
unixclient.py.py.tar.gz
(297 B)
📄
unixclient.py.tar
(2 KB)
📄
unixd.h.h.tar.gz
(1.83 KB)
📄
unixd.h.tar
(6 KB)
📄
unixish.h.h.tar.gz
(2.13 KB)
📄
unixish.h.tar
(6.5 KB)
📄
unixserver.py.py.tar.gz
(396 B)
📄
unixserver.py.tar
(2 KB)
📄
unknown-option.xml.tar
(2 KB)
📄
unknown-option.xml.xml.tar.gz
(272 B)
📄
unknown_nmi_panic.tar
(2 KB)
📄
unknown_nmi_panic.tar.gz
(118 B)
📄
unlink.tar
(36 KB)
📄
unlink.tar.gz
(14.86 KB)
📄
unmark.sql.sql.tar.gz
(3.41 KB)
📄
unmark.sql.tar
(16 KB)
📄
unmark.tar
(4.1 MB)
📄
unmark.tar.gz
(3.81 MB)
📄
unmark.zip
(4.07 MB)
📄
unorm.h.h.tar.gz
(5.74 KB)
📄
unorm.h.tar
(22 KB)
📄
unparse.pyc.pyc.tar.gz
(7 KB)
📄
unparse.pyc.tar
(25 KB)
📄
unparse.pyo.pyo.tar.gz
(6.94 KB)
📄
unparse.pyo.tar
(25 KB)
📄
unres_qlen.tar
(9 KB)
📄
unres_qlen.tar.gz
(128 B)
📄
unres_qlen_bytes.tar
(5 KB)
📄
unres_qlen_bytes.tar.gz
(132 B)
📄
unsupported-tools.tar
(3.02 MB)
📄
unsupported-tools.tar.gz
(1.27 MB)
📄
unsupported-tools.zip
(3.01 MB)
📄
untabify.pyc.pyc.tar.gz
(1002 B)
📄
untabify.pyc.tar
(3.5 KB)
📄
untabify.pyo.pyo.tar.gz
(1003 B)
📄
untabify.pyo.tar
(3.5 KB)
📄
unversioned.tar
(2.5 KB)
📄
unversioned.tar.gz
(455 B)
📄
unversioned.zip
(1.04 KB)
📄
unzip.tar
(203.5 KB)
📄
unzip.tar.gz
(98.72 KB)
📄
unzipsfx.tar
(103 KB)
📄
unzipsfx.tar.gz
(50.96 KB)
📄
update-dist-tags.js.js.tar.gz
(1.28 KB)
📄
update-dist-tags.js.tar
(5 KB)
📄
update.php.php.tar.gz
(6.44 KB)
📄
update.php.tar
(54 KB)
📄
update.pyc.pyc.tar.gz
(1.41 KB)
📄
update.pyc.tar
(4.5 KB)
📄
update.pyo.pyo.tar.gz
(1.41 KB)
📄
update.pyo.tar
(4.5 KB)
📄
update.settings.json.settings.json.tar.gz
(340 B)
📄
update.settings.json.tar
(2 KB)
📄
update_appkey.php.php.tar.gz
(554 B)
📄
update_appkey.php.tar
(4 KB)
📄
update_glpikey.php.php.tar.gz
(414 B)
📄
update_glpikey.php.tar
(2.5 KB)
📄
update_keys.php.php.tar.gz
(1.07 KB)
📄
update_keys.php.tar
(4 KB)
📄
update_pass.php.php.tar.gz
(435 B)
📄
update_pass.php.tar
(185.5 KB)
📄
update_rijndael.php.php.tar.gz
(750 B)
📄
update_rijndael.php.tar
(4.5 KB)
📄
upgrade.php.php.tar.gz
(4.23 KB)
📄
upgrade.php.tar
(3.92 MB)
📄
upgrade.tar
(53.17 MB)
📄
upgrade.tar.gz
(5.05 MB)
📄
upgrade.xml.tar
(246.5 KB)
📄
upgrade.xml.xml.tar.gz
(299 B)
📄
upgrade.zip
(53.16 MB)
📄
upgrader.tar
(129.5 KB)
📄
upgrader.tar.gz
(101.62 KB)
📄
upgrader.zip
(127.68 KB)
📄
upnp-client.xml.tar
(2 KB)
📄
upnp-client.xml.xml.tar.gz
(301 B)
📄
uptime.tar
(15.5 KB)
📄
uptime.tar.gz
(115 B)
📄
uri.go.go.tar.gz
(18.42 KB)
📄
uri.go.tar
(57.5 KB)
📄
url.amf.amf.tar.gz
(195 B)
📄
url.amf.tar
(2 KB)
📄
urlapi.h.h.tar.gz
(1.62 KB)
📄
urlapi.h.tar
(6 KB)
📄
urlget.tar
(19.5 KB)
📄
urlget.tar.gz
(6.09 KB)
📄
urllib.py.py.tar.gz
(14.81 KB)
📄
urllib.py.tar
(60.5 KB)
📄
urllib.pyc.pyc.tar.gz
(19.08 KB)
📄
urllib.pyc.tar
(52 KB)
📄
urllib.pyo.pyo.tar.gz
(19.03 KB)
📄
urllib.pyo.tar
(51.5 KB)
📄
urllib.tar
(853.5 KB)
📄
urllib.tar.gz
(177.65 KB)
📄
urllib.zip
(829.82 KB)
📄
urllib2.py.py.tar.gz
(14.74 KB)
📄
urllib2.py.tar
(53 KB)
📄
urllib2.pyc.pyc.tar.gz
(17.41 KB)
📄
urllib2.pyc.tar
(48 KB)
📄
urllib2.pyo.pyo.tar.gz
(17.37 KB)
📄
urllib2.pyo.tar
(48 KB)
📄
urlparse.py.py.tar.gz
(6.35 KB)
📄
urlparse.py.tar
(21.5 KB)
📄
urlparse.pyc.pyc.tar.gz
(7.67 KB)
📄
urlparse.pyc.tar
(19.5 KB)
📄
urlparse.pyo.pyo.tar.gz
(7.67 KB)
📄
urlparse.pyo.tar
(19.5 KB)
📄
usa18x.fw.fw.tar.gz
(3.53 KB)
📄
usa18x.fw.tar
(17 KB)
📄
usa19.fw.fw.tar.gz
(2.77 KB)
📄
usa19.fw.tar
(6.5 KB)
📄
usa19qi.fw.fw.tar.gz
(2.69 KB)
📄
usa19qi.fw.tar
(6.5 KB)
📄
usa19qw.fw.fw.tar.gz
(2.97 KB)
📄
usa19qw.fw.tar
(9 KB)
📄
usa19w.fw.fw.tar.gz
(2.87 KB)
📄
usa19w.fw.tar
(17 KB)
📄
usa28.fw.fw.tar.gz
(4.19 KB)
📄
usa28.fw.tar
(9.5 KB)
📄
usa28x.fw.fw.tar.gz
(3.53 KB)
📄
usa28x.fw.tar
(17 KB)
📄
usa28xa.fw.fw.tar.gz
(3.54 KB)
📄
usa28xa.fw.tar
(9 KB)
📄
usa28xb.fw.fw.tar.gz
(3.54 KB)
📄
usa28xb.fw.tar
(9 KB)
📄
usa49w.fw.fw.tar.gz
(3.92 KB)
📄
usa49w.fw.tar
(18 KB)
📄
usa49wlc.fw.fw.tar.gz
(3.96 KB)
📄
usa49wlc.fw.tar
(9.5 KB)
📄
usb.mod.mod.tar.gz
(6.76 KB)
📄
usb.mod.tar
(34 KB)
📄
usb8682.bin.bin.tar.gz
(123.19 KB)
📄
usb8682.bin.tar
(172 KB)
📄
usb8766_uapsta.bin.bin.tar.gz
(330.78 KB)
📄
usb8766_uapsta.bin.tar
(469.5 KB)
📄
usb8797_uapsta.bin.bin.tar.gz
(380.99 KB)
📄
usb8797_uapsta.bin.tar
(542.5 KB)
📄
usb8801_uapsta.bin.bin.tar.gz
(179.86 KB)
📄
usb8801_uapsta.bin.tar
(248 KB)
📄
usb8897_uapsta.bin.bin.tar.gz
(513.85 KB)
📄
usb8897_uapsta.bin.tar
(736.5 KB)
📄
usb_keyboard.mod.mod.tar.gz
(2.36 KB)
📄
usb_keyboard.mod.tar
(13 KB)
📄
usb_stream.h.h.tar.gz
(614 B)
📄
usb_stream.h.tar
(3 KB)
📄
usbdux_firmware.bin.bin.tar.gz
(1002 B)
📄
usbdux_firmware.bin.tar
(3.5 KB)
📄
usbduxfast_firmware.bin.bin.tar.gz
(518 B)
📄
usbduxfast_firmware.bin.tar
(2.5 KB)
📄
usbms.mod.mod.tar.gz
(3.96 KB)
📄
usbms.mod.tar
(22 KB)
📄
usbserial_ftdi.mod.mod.tar.gz
(1.33 KB)
📄
usbserial_ftdi.mod.tar
(4.5 KB)
📄
usbserial_usbdebug.mod.mod.tar.gz
(802 B)
📄
usbserial_usbdebug.mod.tar
(3.5 KB)
📄
usbtest.mod.mod.tar.gz
(2.18 KB)
📄
usbtest.mod.tar
(6 KB)
📄
usbusb8997_combo_v4.bin.bin.tar.gz
(416.89 KB)
📄
usbusb8997_combo_v4.bin.tar
(597.5 KB)
📄
use_oif_addrs_only.tar
(2 KB)
📄
use_oif_addrs_only.tar.gz
(127 B)
📄
use_optimistic.tar
(4 KB)
📄
use_optimistic.tar.gz
(124 B)
📄
use_tempaddr.tar
(2 KB)
📄
use_tempaddr.tar.gz
(122 B)
📄
user-.slice.d.tar
(2 KB)
📄
user-.slice.d.tar.gz
(397 B)
📄
user-.slice.d.zip
(617 B)
📄
user-email.tar
(16 KB)
📄
user-email.tar.gz
(3.91 KB)
📄
user-environment-generators.tar
(14 KB)
📄
user-environment-generators.tar.gz
(4.85 KB)
📄
user-environment-generators.zip
(12.22 KB)
📄
user-preset.tar
(2.5 KB)
📄
user-preset.tar.gz
(406 B)
📄
user-preset.zip
(681 B)
📄
user.h.h.tar.gz
(1.44 KB)
📄
user.h.tar
(7 KB)
📄
user.json.json.tar.gz
(243 B)
📄
user.json.tar
(2 KB)
📄
user.py.py.tar.gz
(889 B)
📄
user.py.tar
(3.5 KB)
📄
user.pyc.pyc.tar.gz
(1.07 KB)
📄
user.pyc.tar
(3.5 KB)
📄
user.pyo.pyo.tar.gz
(1.07 KB)
📄
user.pyo.tar
(3.5 KB)
📄
user.slice.slice.tar.gz
(387 B)
📄
user.slice.tar
(3 KB)
📄
user.tar
(41 KB)
📄
user.tar.gz
(2.24 KB)
📄
user.zip
(16.21 KB)
📄
user@.service.service.tar.gz
(512 B)
📄
user@.service.tar
(4 KB)
📄
user_admin.php.php.tar.gz
(184 B)
📄
user_admin.php.tar
(2 KB)
📄
user_privileges_1.php.php.tar.gz
(1.21 KB)
📄
user_privileges_1.php.tar
(6 KB)
📄
user_record.h.h.tar.gz
(623 B)
📄
user_record.h.tar
(4 KB)
📄
user_reserve_kbytes.tar
(2 KB)
📄
user_reserve_kbytes.tar.gz
(119 B)
📄
username.ini.ini.tar.gz
(314 B)
📄
username.ini.tar
(2 KB)
📄
users.auth.php.auth.php.tar.gz
(303 B)
📄
users.auth.php.tar
(2 KB)
📄
users.h.h.tar.gz
(831 B)
📄
users.h.tar
(3.5 KB)
📄
users.inc.inc.tar.gz
(5.59 KB)
📄
users.inc.tar
(23.5 KB)
📄
users.json.json.tar.gz
(239 B)
📄
users.json.tar
(2 KB)
📄
users.php.php.tar.gz
(498 B)
📄
users.php.tar
(3 KB)
📄
users.table.xml.table.xml.tar.gz
(369 B)
📄
users.table.xml.tar
(2.5 KB)
📄
users.tar
(39 KB)
📄
users.tar.gz
(15.97 KB)
📄
userspice.sql.sql.tar.gz
(9.1 KB)
📄
userspice.sql.tar
(54 KB)
📄
userspice.tar
(6.05 MB)
📄
userspice.tar.gz
(5.27 MB)
📄
userspice.zip
(6.03 MB)
📄
usetiter.h.h.tar.gz
(2.68 KB)
📄
usetiter.h.tar
(11 KB)
📄
usr.tar
(204.3 MB)
📄
usr.tar.gz
(2.73 MB)
📄
usr.zip
(203.38 MB)
📄
utext.h.h.tar.gz
(13.16 KB)
📄
utext.h.tar
(60 KB)
📄
utf16.h.h.tar.gz
(3.41 KB)
📄
utf16.h.tar
(24 KB)
📄
utf32.h.h.tar.gz
(505 B)
📄
utf32.h.tar
(2.5 KB)
📄
utf8.h.h.tar.gz
(14.49 KB)
📄
utf8.h.tar
(59.5 KB)
📄
utf8_and_big5.so.so.tar.gz
(59.82 KB)
📄
utf8_and_big5.so.tar
(121.5 KB)
📄
utf8_and_euc2004.so.so.tar.gz
(61.17 KB)
📄
utf8_and_euc2004.so.tar
(209 KB)
📄
utf8_and_euc_cn.so.so.tar.gz
(40.92 KB)
📄
utf8_and_euc_cn.so.tar
(85.5 KB)
📄
utf8_and_euc_jp.so.so.tar.gz
(62.51 KB)
📄
utf8_and_euc_jp.so.tar
(157.5 KB)
📄
utf8_and_euc_kr.so.so.tar.gz
(45.24 KB)
📄
utf8_and_euc_kr.so.tar
(109.5 KB)
📄
utf8_and_euc_tw.so.so.tar.gz
(81.32 KB)
📄
utf8_and_euc_tw.so.tar
(205.5 KB)
📄
utf8_and_gb18030.so.so.tar.gz
(106.71 KB)
📄
utf8_and_gb18030.so.tar
(265.5 KB)
📄
utf8_and_gbk.so.so.tar.gz
(84.18 KB)
📄
utf8_and_gbk.so.tar
(153.5 KB)
📄
utf8_and_iso8859.so.so.tar.gz
(7.68 KB)
📄
utf8_and_iso8859.so.tar
(33.5 KB)
📄
utf8_and_iso8859_1.so.so.tar.gz
(3.43 KB)
📄
utf8_and_iso8859_1.so.tar
(9.5 KB)
📄
utf8_and_sjis.so.so.tar.gz
(40.22 KB)
📄
utf8_and_sjis.so.tar
(89.5 KB)
📄
utf8_and_uhc.so.so.tar.gz
(72.26 KB)
📄
utf8_and_uhc.so.tar
(173.5 KB)
📄
utf8_and_win.so.so.tar.gz
(7.46 KB)
📄
utf8_and_win.so.tar
(37.5 KB)
📄
utf_16_32.so.so.tar.gz
(4.93 KB)
📄
utf_16_32.so.tar
(17.5 KB)
📄
utf_16be.so.so.tar.gz
(3.75 KB)
📄
utf_16be.so.tar
(13.5 KB)
📄
utf_16le.so.so.tar.gz
(3.72 KB)
📄
utf_16le.so.tar
(13.5 KB)
📄
utf_32be.so.so.tar.gz
(3.64 KB)
📄
utf_32be.so.tar
(13.5 KB)
📄
utf_32le.so.so.tar.gz
(3.63 KB)
📄
utf_32le.so.tar
(13.5 KB)
📄
utfebcdic.h.h.tar.gz
(7.63 KB)
📄
utfebcdic.h.tar
(67.5 KB)
📄
utflist.tar
(41.5 KB)
📄
utflist.tar.gz
(10.12 KB)
📄
util.h.h.tar.gz
(3.91 KB)
📄
util.h.tar
(41.5 KB)
📄
util.py.py.tar.gz
(4.47 KB)
📄
util.py.tar
(96.5 KB)
📄
util.pyc.pyc.tar.gz
(3.94 KB)
📄
util.pyc.tar
(10 KB)
📄
util.pyo.pyo.tar.gz
(3.95 KB)
📄
util.pyo.tar
(10 KB)
📄
util_cfgtree.h.h.tar.gz
(1.41 KB)
📄
util_cfgtree.h.tar
(5 KB)
📄
util_charset.h.h.tar.gz
(1.06 KB)
📄
util_charset.h.tar
(4 KB)
📄
util_cookies.h.h.tar.gz
(1.51 KB)
📄
util_cookies.h.tar
(6.5 KB)
📄
util_ebcdic.h.h.tar.gz
(1.2 KB)
📄
util_ebcdic.h.tar
(4.5 KB)
📄
util_fcgi.h.h.tar.gz
(2.87 KB)
📄
util_fcgi.h.tar
(11.5 KB)
📄
util_filter.h.h.tar.gz
(7 KB)
📄
util_filter.h.tar
(27.5 KB)
📄
util_ldap.h.h.tar.gz
(4.71 KB)
📄
util_ldap.h.tar
(19.5 KB)
📄
util_md5.h.h.tar.gz
(1.01 KB)
📄
util_md5.h.tar
(4 KB)
📄
util_script.h.h.tar.gz
(2.05 KB)
📄
util_script.h.tar
(11.5 KB)
📄
util_time.h.h.tar.gz
(1.56 KB)
📄
util_time.h.tar
(6 KB)
📄
util_varbuf.h.h.tar.gz
(2.73 KB)
📄
util_varbuf.h.tar
(10 KB)
📄
util_xml.h.h.tar.gz
(836 B)
📄
util_xml.h.tar
(3 KB)
📄
utility.tar
(75 KB)
📄
utility.tar.gz
(14.43 KB)
📄
utility.zip
(65.7 KB)
📄
utils.py.py.tar.gz
(4.95 KB)
📄
utils.py.tar
(45 KB)
📄
utils.pyc.pyc.tar.gz
(4.35 KB)
📄
utils.pyc.tar
(11 KB)
📄
utils.pyo.pyo.tar.gz
(4.35 KB)
📄
utils.pyo.tar
(11 KB)
📄
utime.h.h.tar.gz
(887 B)
📄
utime.h.tar
(3 KB)
📄
utime.tar
(2.5 KB)
📄
utime.tar.gz
(317 B)
📄
utmp.h.h.tar.gz
(1.76 KB)
📄
utmp.h.tar
(5.5 KB)
📄
utmp.tar
(8 KB)
📄
utmp.tar.gz
(345 B)
📄
utmpdump.tar
(30.5 KB)
📄
utmpdump.tar.gz
(10.89 KB)
📄
utmpx.h.h.tar.gz
(1.23 KB)
📄
utmpx.h.tar
(10 KB)
📄
utmscale.h.h.tar.gz
(3.68 KB)
📄
utmscale.h.tar
(15.5 KB)
📄
utsname.h.h.tar.gz
(746 B)
📄
utsname.h.tar
(6 KB)
📄
uu.cpython-38.pyc.cpython-38.pyc.tar.gz
(2.38 KB)
📄
uu.cpython-38.pyc.tar
(5.5 KB)
📄
uu.py.py.tar.gz
(2.49 KB)
📄
uu.py.tar
(24 KB)
📄
uu.pyc.pyc.tar.gz
(2.28 KB)
📄
uu.pyc.tar
(6 KB)
📄
uu.pyo.pyo.tar.gz
(2.28 KB)
📄
uu.pyo.tar
(6 KB)
📄
uudmap.h.h.tar.gz
(252 B)
📄
uudmap.h.tar
(2.5 KB)
📄
uuid.h.h.tar.gz
(1.61 KB)
📄
uuid.h.tar
(5.5 KB)
📄
uuid.pc.pc.tar.gz
(249 B)
📄
uuid.pc.tar
(2 KB)
📄
uuid.py.py.tar.gz
(6.99 KB)
📄
uuid.py.tar
(79 KB)
📄
uuid.pyc.pyc.tar.gz
(8.96 KB)
📄
uuid.pyc.tar
(24.5 KB)
📄
uuid.pyo.pyo.tar.gz
(8.91 KB)
📄
uuid.pyo.tar
(24.5 KB)
📄
uuid.tar
(6.5 KB)
📄
uuid.tar.gz
(140 B)
📄
uuid.zip
(3.96 KB)
📄
uvdesk.sql.sql.tar.gz
(8.14 KB)
📄
uvdesk.sql.tar
(64 KB)
📄
uvdesk.tar
(23.19 MB)
📄
uvdesk.tar.gz
(19.78 MB)
📄
uvdesk.yaml.tar
(3 KB)
📄
uvdesk.yaml.yaml.tar.gz
(591 B)
📄
uvdesk.zip
(23.16 MB)
📄
uversion.h.h.tar.gz
(2.09 KB)
📄
uversion.h.tar
(8.5 KB)
📄
v3d_drm.h.h.tar.gz
(4.53 KB)
📄
v3d_drm.h.tar
(16.5 KB)
📄
v4l-cx23418-apu.fw.fw.tar.gz
(50.2 KB)
📄
v4l-cx23418-apu.fw.tar
(139.5 KB)
📄
v4l-cx23418-cpu.fw.fw.tar.gz
(76.67 KB)
📄
v4l-cx23418-cpu.fw.tar
(156.5 KB)
📄
v4l-cx23418-dig.fw.fw.tar.gz
(8.14 KB)
📄
v4l-cx23418-dig.fw.tar
(17.5 KB)
📄
v4l-cx25840.fw.fw.tar.gz
(8.11 KB)
📄
v4l-cx25840.fw.tar
(34 KB)
📄
v4l_id.tar
(27 KB)
📄
v4l_id.tar.gz
(4.48 KB)
📄
vacuumdb.tar
(80 KB)
📄
vacuumdb.tar.gz
(30.96 KB)
📄
validate.pyc.pyc.tar.gz
(6.06 KB)
📄
validate.pyc.tar
(18 KB)
📄
validate.pyo.pyo.tar.gz
(6.06 KB)
📄
validate.pyo.tar
(18 KB)
📄
validation.tar
(22.5 KB)
📄
validation.tar.gz
(3.39 KB)
📄
values.h.h.tar.gz
(984 B)
📄
values.h.tar
(3.5 KB)
📄
vangogh_asd.bin.bin.tar.gz
(65.76 KB)
📄
vangogh_asd.bin.tar
(202 KB)
📄
vangogh_ce.bin.bin.tar.gz
(5.2 KB)
📄
vangogh_ce.bin.tar
(259 KB)
📄
vangogh_me.bin.bin.tar.gz
(9.61 KB)
📄
vangogh_me.bin.tar
(259 KB)
📄
vangogh_mec.bin.bin.tar.gz
(41.58 KB)
📄
vangogh_mec.bin.tar
(263.5 KB)
📄
vangogh_mec2.bin.bin.tar.gz
(41.57 KB)
📄
vangogh_mec2.bin.tar
(263.5 KB)
📄
vangogh_pfp.bin.bin.tar.gz
(16.64 KB)
📄
vangogh_pfp.bin.tar
(259 KB)
📄
vangogh_rlc.bin.bin.tar.gz
(15.8 KB)
📄
vangogh_rlc.bin.tar
(46 KB)
📄
vangogh_sdma.bin.bin.tar.gz
(43.46 KB)
📄
vangogh_sdma.bin.tar
(134 KB)
📄
vangogh_toc.bin.bin.tar.gz
(962 B)
📄
vangogh_toc.bin.tar
(3.5 KB)
📄
vangogh_vcn.bin.bin.tar.gz
(400.8 KB)
📄
vangogh_vcn.bin.tar
(560.5 KB)
📄
vanilla.tar
(375.5 KB)
📄
vanilla.tar.gz
(234.18 KB)
📄
vanilla.zip
(346.16 KB)
📄
var.conf.conf.tar.gz
(397 B)
📄
var.conf.tar
(4 KB)
📄
var.tar
(4.59 MB)
📄
var.tar.gz
(1.3 KB)
📄
var.zip
(4.37 MB)
📄
variables.h.h.tar.gz
(1.01 KB)
📄
variables.h.tar
(5 KB)
📄
vbe.mod.mod.tar.gz
(5.22 KB)
📄
vbe.mod.tar
(28 KB)
📄
vc4_drm.h.h.tar.gz
(4.75 KB)
📄
vc4_drm.h.tar
(16 KB)
📄
vce_1_0_0.bin.bin.tar.gz
(37.13 KB)
📄
vce_1_0_0.bin.tar
(49.5 KB)
📄
vcn_3_1_2.bin.bin.tar.gz
(400.8 KB)
📄
vcn_3_1_2.bin.tar
(560.5 KB)
📄
vcn_4_0_0.bin.bin.tar.gz
(286.91 KB)
📄
vcn_4_0_0.bin.tar
(396 KB)
📄
vcn_4_0_2.bin.bin.tar.gz
(286.91 KB)
📄
vcn_4_0_2.bin.tar
(396 KB)
📄
vcn_4_0_3.bin.bin.tar.gz
(255.21 KB)
📄
vcn_4_0_3.bin.tar
(353 KB)
📄
vcn_4_0_4.bin.bin.tar.gz
(286.91 KB)
📄
vcn_4_0_4.bin.tar
(396 KB)
📄
vcn_4_0_5.bin.bin.tar.gz
(286.17 KB)
📄
vcn_4_0_5.bin.tar
(396 KB)
📄
vcn_4_0_6.bin.bin.tar.gz
(286.17 KB)
📄
vcn_4_0_6.bin.tar
(396 KB)
📄
vcn_4_0_6_1.bin.bin.tar.gz
(286.17 KB)
📄
vcn_4_0_6_1.bin.tar
(396 KB)
📄
vcn_5_0_0.bin.bin.tar.gz
(312.45 KB)
📄
vcn_5_0_0.bin.tar
(427.5 KB)
📄
vcn_5_0_1.bin.bin.tar.gz
(152.73 KB)
📄
vcn_5_0_1.bin.tar
(208 KB)
📄
vcp.img.img.tar.gz
(372.87 KB)
📄
vcp.img.tar
(5.49 MB)
📄
vdec.tar
(328.5 KB)
📄
vdec.tar.gz
(102.15 KB)
📄
vdec.zip
(322.06 KB)
📄
vdir.tar
(141.5 KB)
📄
vdir.tar.gz
(65.83 KB)
📄
vdsm.xml.tar
(2.5 KB)
📄
vdsm.xml.xml.tar.gz
(441 B)
📄
vega10_acg_smc.bin.bin.tar.gz
(64.96 KB)
📄
vega10_acg_smc.bin.tar
(258.5 KB)
📄
vega10_asd.bin.bin.tar.gz
(65.76 KB)
📄
vega10_asd.bin.tar
(202 KB)
📄
vega10_ce.bin.bin.tar.gz
(3.46 KB)
📄
vega10_ce.bin.tar
(11 KB)
📄
vega10_gpu_info.bin.bin.tar.gz
(173 B)
📄
vega10_gpu_info.bin.tar
(2 KB)
📄
vega10_me.bin.bin.tar.gz
(6.96 KB)
📄
vega10_me.bin.tar
(19 KB)
📄
vega10_mec.bin.bin.tar.gz
(34.29 KB)
📄
vega10_mec.bin.tar
(263.5 KB)
📄
vega10_mec2.bin.bin.tar.gz
(34.29 KB)
📄
vega10_mec2.bin.tar
(263.5 KB)
📄
vega10_pfp.bin.bin.tar.gz
(10.21 KB)
📄
vega10_pfp.bin.tar
(23 KB)
📄
vega10_rlc.bin.bin.tar.gz
(7.28 KB)
📄
vega10_rlc.bin.tar
(18.5 KB)
📄
vega10_sdma.bin.bin.tar.gz
(8.48 KB)
📄
vega10_sdma.bin.tar
(18.5 KB)
📄
vega10_sdma1.bin.bin.tar.gz
(8.48 KB)
📄
vega10_sdma1.bin.tar
(18.5 KB)
📄
vega10_smc.bin.bin.tar.gz
(59.62 KB)
📄
vega10_smc.bin.tar
(258.5 KB)
📄
vega10_sos.bin.bin.tar.gz
(162.65 KB)
📄
vega10_sos.bin.tar
(164.5 KB)
📄
vega10_uvd.bin.bin.tar.gz
(249.67 KB)
📄
vega10_uvd.bin.tar
(373.5 KB)
📄
vega10_vce.bin.bin.tar.gz
(106.57 KB)
📄
vega10_vce.bin.tar
(171.5 KB)
📄
vega12_asd.bin.bin.tar.gz
(65.76 KB)
📄
vega12_asd.bin.tar
(202 KB)
📄
vega12_ce.bin.bin.tar.gz
(3.46 KB)
📄
vega12_ce.bin.tar
(21 KB)
📄
vega12_gpu_info.bin.bin.tar.gz
(177 B)
📄
vega12_gpu_info.bin.tar
(2 KB)
📄
vega12_me.bin.bin.tar.gz
(6.82 KB)
📄
vega12_me.bin.tar
(19 KB)
📄
vega12_mec.bin.bin.tar.gz
(33.56 KB)
📄
vega12_mec.bin.tar
(263.5 KB)
📄
vega12_mec2.bin.bin.tar.gz
(33.56 KB)
📄
vega12_mec2.bin.tar
(263.5 KB)
📄
vega12_pfp.bin.bin.tar.gz
(10.15 KB)
📄
vega12_pfp.bin.tar
(23 KB)
📄
vega12_rlc.bin.bin.tar.gz
(10 KB)
📄
vega12_rlc.bin.tar
(29.5 KB)
📄
vega12_sdma.bin.bin.tar.gz
(8.48 KB)
📄
vega12_sdma.bin.tar
(18.5 KB)
📄
vega12_sdma1.bin.bin.tar.gz
(8.47 KB)
📄
vega12_sdma1.bin.tar
(18.5 KB)
📄
vega12_smc.bin.bin.tar.gz
(80.87 KB)
📄
vega12_smc.bin.tar
(258.5 KB)
📄
vega12_sos.bin.bin.tar.gz
(162.65 KB)
📄
vega12_sos.bin.tar
(164.5 KB)
📄
vega12_uvd.bin.bin.tar.gz
(249.67 KB)
📄
vega12_uvd.bin.tar
(373.5 KB)
📄
vega12_vce.bin.bin.tar.gz
(106.57 KB)
📄
vega12_vce.bin.tar
(171.5 KB)
📄
vega20_asd.bin.bin.tar.gz
(65.75 KB)
📄
vega20_asd.bin.tar
(202 KB)
📄
vega20_ce.bin.bin.tar.gz
(3.46 KB)
📄
vega20_ce.bin.tar
(11 KB)
📄
vega20_me.bin.bin.tar.gz
(6.82 KB)
📄
vega20_me.bin.tar
(19 KB)
📄
vega20_mec.bin.bin.tar.gz
(33.83 KB)
📄
vega20_mec.bin.tar
(263.5 KB)
📄
vega20_mec2.bin.bin.tar.gz
(33.83 KB)
📄
vega20_mec2.bin.tar
(263.5 KB)
📄
vega20_pfp.bin.bin.tar.gz
(10.16 KB)
📄
vega20_pfp.bin.tar
(23 KB)
📄
vega20_rlc.bin.bin.tar.gz
(12.3 KB)
📄
vega20_rlc.bin.tar
(50 KB)
📄
vega20_sdma.bin.bin.tar.gz
(8.69 KB)
📄
vega20_sdma.bin.tar
(18.5 KB)
📄
vega20_sdma1.bin.bin.tar.gz
(8.69 KB)
📄
vega20_sdma1.bin.tar
(18.5 KB)
📄
vega20_smc.bin.bin.tar.gz
(86.74 KB)
📄
vega20_smc.bin.tar
(258.5 KB)
📄
vega20_sos.bin.bin.tar.gz
(91.92 KB)
📄
vega20_sos.bin.tar
(172.5 KB)
📄
vega20_ta.bin.bin.tar.gz
(28.45 KB)
📄
vega20_ta.bin.tar
(90.5 KB)
📄
vega20_uvd.bin.bin.tar.gz
(251.2 KB)
📄
vega20_uvd.bin.tar
(376.5 KB)
📄
vega20_vce.bin.bin.tar.gz
(106.57 KB)
📄
vega20_vce.bin.tar
(171.5 KB)
📄
vegam_ce.bin.bin.tar.gz
(3.04 KB)
📄
vegam_ce.bin.tar
(10.5 KB)
📄
vegam_me.bin.bin.tar.gz
(6.3 KB)
📄
vegam_me.bin.tar
(18.5 KB)
📄
vegam_mec.bin.bin.tar.gz
(27.31 KB)
📄
vegam_mec.bin.tar
(258.5 KB)
📄
vegam_mec2.bin.bin.tar.gz
(27.56 KB)
📄
vegam_mec2.bin.tar
(258.5 KB)
📄
vegam_pfp.bin.bin.tar.gz
(8.46 KB)
📄
vegam_pfp.bin.tar
(18.5 KB)
📄
vegam_rlc.bin.bin.tar.gz
(6.08 KB)
📄
vegam_rlc.bin.tar
(18 KB)
📄
vegam_sdma.bin.bin.tar.gz
(4.69 KB)
📄
vegam_sdma.bin.tar
(14 KB)
📄
vegam_sdma1.bin.bin.tar.gz
(4.69 KB)
📄
vegam_sdma1.bin.tar
(14 KB)
📄
vegam_smc.bin.bin.tar.gz
(54.35 KB)
📄
vegam_smc.bin.tar
(129.5 KB)
📄
vegam_uvd.bin.bin.tar.gz
(246.19 KB)
📄
vegam_uvd.bin.tar
(368.5 KB)
📄
vegam_vce.bin.bin.tar.gz
(91.35 KB)
📄
vegam_vce.bin.tar
(164.5 KB)
📄
vendor.tar
(6.72 MB)
📄
vendor.tar.gz
(1.02 MB)
📄
vendor.zip
(5.7 MB)
📄
vendor_perl.tar
(18.63 MB)
📄
vendor_perl.tar.gz
(4.7 MB)
📄
vendor_perl.zip
(18.43 MB)
📄
venus-1.8.tar
(971.5 KB)
📄
venus-1.8.tar.gz
(487.96 KB)
📄
venus-1.8.zip
(969.85 KB)
📄
venus-4.2.tar
(905.5 KB)
📄
venus-4.2.tar.gz
(459.73 KB)
📄
venus-4.2.zip
(903.89 KB)
📄
venus-5.2.tar
(864.5 KB)
📄
venus-5.2.tar.gz
(449.78 KB)
📄
venus-5.2.zip
(862.71 KB)
📄
venus-5.4.tar
(902.5 KB)
📄
venus-5.4.tar.gz
(469.68 KB)
📄
venus-5.4.zip
(900.84 KB)
📄
venus-6.0.tar
(1.71 MB)
📄
venus-6.0.tar.gz
(480.52 KB)
📄
venus-6.0.zip
(1.71 MB)
📄
venus.mbn.mbn.tar.gz
(459.76 KB)
📄
venus.mbn.tar
(4.71 MB)
📄
venus.mdt.mdt.tar.gz
(449.81 KB)
📄
venus.mdt.tar
(2.73 MB)
📄
venv.tar
(126.5 KB)
📄
venv.tar.gz
(16.43 KB)
📄
venv.zip
(115.76 KB)
📄
verde_ce.bin.bin.tar.gz
(1.06 KB)
📄
verde_ce.bin.tar
(20 KB)
📄
verde_k_smc.bin.bin.tar.gz
(27.55 KB)
📄
verde_k_smc.bin.tar
(127 KB)
📄
verde_mc.bin.bin.tar.gz
(12.79 KB)
📄
verde_mc.bin.tar
(65 KB)
📄
verde_me.bin.bin.tar.gz
(3.68 KB)
📄
verde_me.bin.tar
(20 KB)
📄
verde_pfp.bin.bin.tar.gz
(2.82 KB)
📄
verde_pfp.bin.tar
(20 KB)
📄
verde_rlc.bin.bin.tar.gz
(4.61 KB)
📄
verde_rlc.bin.tar
(19 KB)
📄
verde_smc.bin.bin.tar.gz
(26.54 KB)
📄
verde_smc.bin.tar
(123 KB)
📄
verde_uvd.bin.bin.tar.gz
(144.34 KB)
📄
verde_uvd.bin.tar
(216.5 KB)
📄
verifiers.mod.mod.tar.gz
(1.88 KB)
📄
verifiers.mod.tar
(10 KB)
📄
version.h.h.tar.gz
(218 B)
📄
version.h.tar
(7.5 KB)
📄
version.json.json.tar.gz
(163 B)
📄
version.json.tar
(2 KB)
📄
version.php.php.tar.gz
(574 B)
📄
version.php.tar
(3.5 KB)
📄
version.pod.pod.tar.gz
(3.71 KB)
📄
version.pod.tar
(11.5 KB)
📄
version.tar
(56.5 KB)
📄
version.tar.gz
(241 B)
📄
version.txt.tar
(2 KB)
📄
version.txt.txt.tar.gz
(118 B)
📄
version.zip
(50.83 KB)
📄
version_option.rb.rb.tar.gz
(698 B)
📄
version_option.rb.tar
(3.5 KB)
📄
versions.yaml.tar
(2 KB)
📄
versions.yaml.yaml.tar.gz
(163 B)
📄
verto-module.h.h.tar.gz
(2.22 KB)
📄
verto-module.h.tar
(8 KB)
📄
verto.h.h.tar.gz
(5.14 KB)
📄
verto.h.tar
(20.5 KB)
📄
vfs.h.h.tar.gz
(220 B)
📄
vfs.h.tar
(2 KB)
📄
vfs_cache_pressure.tar
(2 KB)
📄
vfs_cache_pressure.tar.gz
(116 B)
📄
vga.mod.mod.tar.gz
(2.45 KB)
📄
vga.mod.tar
(14 KB)
📄
vga2iso.tar
(3.5 KB)
📄
vga2iso.tar.gz
(630 B)
📄
vga_text.mod.mod.tar.gz
(1.33 KB)
📄
vga_text.mod.tar
(4.5 KB)
📄
vgauthd.service.service.tar.gz
(284 B)
📄
vgauthd.service.tar
(2 KB)
📄
vgem_drm.h.h.tar.gz
(1.08 KB)
📄
vgem_drm.h.tar
(3.5 KB)
📄
vi.tar
(1.13 MB)
📄
vi.tar.gz
(583.55 KB)
📄
via.pm.pm.tar.gz
(2.84 KB)
📄
via.pm.tar
(9 KB)
📄
via.tar
(25.5 KB)
📄
via.tar.gz
(9.57 KB)
📄
via.zip
(23.85 KB)
📄
vicam.tar
(4 KB)
📄
vicam.tar.gz
(1.33 KB)
📄
vicam.zip
(2.21 KB)
📄
video.lst.lst.tar.gz
(139 B)
📄
video.lst.tar
(3 KB)
📄
video.mod.mod.tar.gz
(3.16 KB)
📄
video.mod.tar
(19 KB)
📄
video.sh.sh.tar.gz
(475 B)
📄
video.sh.tar
(2.5 KB)
📄
video.tar
(12 KB)
📄
video.tar.gz
(3.28 KB)
📄
video.zip
(9.12 KB)
📄
video_bochs.mod.mod.tar.gz
(3.27 KB)
📄
video_bochs.mod.tar
(9.5 KB)
📄
video_cirrus.mod.mod.tar.gz
(3.72 KB)
📄
video_cirrus.mod.tar
(10.5 KB)
📄
video_colors.mod.mod.tar.gz
(2.87 KB)
📄
video_colors.mod.tar
(8 KB)
📄
video_fb.mod.mod.tar.gz
(11.46 KB)
📄
video_fb.mod.tar
(35.5 KB)
📄
videoinfo.mod.mod.tar.gz
(2.12 KB)
📄
videoinfo.mod.tar
(12 KB)
📄
videotest.mod.mod.tar.gz
(2.01 KB)
📄
videotest.mod.tar
(12 KB)
📄
videotest_checksum.mod.mod.tar.gz
(1.12 KB)
📄
videotest_checksum.mod.tar
(4 KB)
📄
view.tar
(1.13 MB)
📄
view.tar.gz
(583.55 KB)
📄
vim.tar
(2.93 MB)
📄
vim.tar.gz
(1.48 MB)
📄
vimdiff.tar
(2.94 MB)
📄
vimdiff.tar.gz
(1.48 MB)
📄
vimrc.tar
(3.5 KB)
📄
vimrc.tar.gz
(1.1 KB)
📄
vimtutor.tar
(4 KB)
📄
vimtutor.tar.gz
(1.17 KB)
📄
vips-modules-8.16.tar
(191.5 KB)
📄
vips-modules-8.16.tar.gz
(70.58 KB)
📄
vips-modules-8.16.zip
(187.41 KB)
📄
vips.tar
(4.02 MB)
📄
vips.tar.gz
(1.78 MB)
📄
vips.zip
(4.01 MB)
📄
virc.tar
(3 KB)
📄
virc.tar.gz
(761 B)
📄
virtual-guest.tar
(2.5 KB)
📄
virtual-guest.tar.gz
(538 B)
📄
virtual-guest.zip
(903 B)
📄
virtual-host.tar
(2.5 KB)
📄
virtual-host.tar.gz
(449 B)
📄
virtual-host.zip
(701 B)
📄
virtualenv-3.tar
(2.5 KB)
📄
virtualenv-3.tar.gz
(576 B)
📄
virtualenv-37.tar
(2.5 KB)
📄
virtualenv-37.tar.gz
(577 B)
📄
virtualenv.tar
(4.5 KB)
📄
virtualenv.tar.gz
(265 B)
📄
viscii.uni.tar
(6 KB)
📄
viscii.uni.uni.tar.gz
(795 B)
📄
visibility.h.h.tar.gz
(1.19 KB)
📄
visibility.h.tar
(4 KB)
📄
vision.tar
(128.5 KB)
📄
vision.tar.gz
(64.76 KB)
📄
vision.zip
(108.17 KB)
📄
visitor.pyc.pyc.tar.gz
(1.9 KB)
📄
visitor.pyc.tar
(6 KB)
📄
visitor.pyo.pyo.tar.gz
(1.9 KB)
📄
visitor.pyo.tar
(6 KB)
📄
vli.h.h.tar.gz
(2.11 KB)
📄
vli.h.tar
(8 KB)
📄
vlimit.h.h.tar.gz
(1.03 KB)
📄
vlimit.h.tar
(3.5 KB)
📄
vm86.h.h.tar.gz
(777 B)
📄
vm86.h.tar
(7 KB)
📄
vmstat.tar
(38.5 KB)
📄
vmstat.tar.gz
(14.37 KB)
📄
vmtoolsd.service.service.tar.gz
(380 B)
📄
vmtoolsd.service.tar
(3 KB)
📄
vmw_pvrdma-abi.h.h.tar.gz
(2.76 KB)
📄
vmw_pvrdma-abi.h.tar
(9.5 KB)
📄
vmwgfx_drm.h.h.tar.gz
(9.28 KB)
📄
vmwgfx_drm.h.tar
(38.5 KB)
📄
vmx.h.h.tar.gz
(1.92 KB)
📄
vmx.h.tar
(9 KB)
📄
vntwusb.fw.fw.tar.gz
(5.02 KB)
📄
vntwusb.fw.tar
(25 KB)
📄
vpdma-1b8.bin.bin.tar.gz
(2.01 KB)
📄
vpdma-1b8.bin.tar
(5.5 KB)
📄
vpe_6_1_0.bin.bin.tar.gz
(9.47 KB)
📄
vpe_6_1_0.bin.tar
(27 KB)
📄
vpe_6_1_1.bin.bin.tar.gz
(10.59 KB)
📄
vpe_6_1_1.bin.tar
(27 KB)
📄
vpe_6_1_3.bin.bin.tar.gz
(9.35 KB)
📄
vpe_6_1_3.bin.tar
(27 KB)
📄
vpu.tar
(24.01 MB)
📄
vpu.tar.gz
(6.85 MB)
📄
vpu.zip
(24 MB)
📄
vpu20_p1.mbn.mbn.tar.gz
(640.93 KB)
📄
vpu20_p1.mbn.tar
(1.93 MB)
📄
vpu20_p1_gen2.mbn.mbn.tar.gz
(651.87 KB)
📄
vpu20_p1_gen2.mbn.tar
(1.94 MB)
📄
vpu20_p4.mbn.mbn.tar.gz
(612.94 KB)
📄
vpu20_p4.mbn.tar
(1.89 MB)
📄
vpu30_p4.mbn.mbn.tar.gz
(813.57 KB)
📄
vpu30_p4.mbn.tar
(2.22 MB)
📄
vpu30_p4_s6_16mb.mbn.mbn.tar.gz
(812.1 KB)
📄
vpu30_p4_s6_16mb.mbn.tar
(2.21 MB)
📄
vpu33_p4.mbn.mbn.tar.gz
(833.58 KB)
📄
vpu33_p4.mbn.tar
(2.24 MB)
📄
vpu35_p4.mbn.mbn.tar.gz
(883.9 KB)
📄
vpu35_p4.mbn.tar
(2.3 MB)
📄
vpu_37xx_v1.bin.bin.tar.gz
(545.3 KB)
📄
vpu_37xx_v1.bin.tar
(2.32 MB)
📄
vpu_40xx_v1.bin.bin.tar.gz
(392.61 KB)
📄
vpu_40xx_v1.bin.tar
(987.5 KB)
📄
vpu_50xx_v1.bin.bin.tar.gz
(378.7 KB)
📄
vpu_50xx_v1.bin.tar
(966 KB)
📄
vpu_d.bin.bin.tar.gz
(32.13 KB)
📄
vpu_d.bin.tar
(8.52 MB)
📄
vpu_p.bin.bin.tar.gz
(78.17 KB)
📄
vpu_p.bin.tar
(388 KB)
📄
vs-698a75a9617bd.tar
(65.5 KB)
📄
vs-698a75a9617bd.tar.gz
(24.13 KB)
📄
vsc.tar
(11 MB)
📄
vsc.tar.gz
(5.63 MB)
📄
vsc.zip
(10.98 MB)
📄
vsyscall.h.h.tar.gz
(282 B)
📄
vsyscall.h.tar
(2 KB)
📄
vsyscall32.tar
(2 KB)
📄
vsyscall32.tar.gz
(107 B)
📄
vt.h.h.tar.gz
(118 B)
📄
vt.h.tar
(2 KB)
📄
vtiger.sql.sql.tar.gz
(108.92 KB)
📄
vtiger.sql.tar
(735 KB)
📄
vtiger.tar
(84.61 MB)
📄
vtiger.tar.gz
(79.65 MB)
📄
vtiger.zip
(84.57 MB)
📄
vtiger72.tar
(214.5 KB)
📄
vtiger72.tar.gz
(118.48 KB)
📄
vtiger72.zip
(187.66 KB)
📄
vtigercron.sh.sh.tar.gz
(433 B)
📄
vtigercron.sh.tar
(2.5 KB)
📄
vtimes.h.h.tar.gz
(1.23 KB)
📄
vtimes.h.tar
(4 KB)
📄
vty.png.png.tar.gz
(8.32 KB)
📄
vty.png.tar
(10 KB)
📄
vty.tar
(55 KB)
📄
vty.tar.gz
(32.16 KB)
📄
vty.zip
(46.31 KB)
📄
vue.png.png.tar.gz
(4.85 KB)
📄
vue.png.tar
(7 KB)
📄
vue.tar
(165.5 KB)
📄
vue.tar.gz
(146.9 KB)
📄
vue.zip
(156.22 KB)
📄
vutil.h.h.tar.gz
(2.12 KB)
📄
vutil.h.tar
(9 KB)
📄
vxgb.png.png.tar.gz
(12.04 KB)
📄
vxgb.png.tar
(13.5 KB)
📄
vxgb.tar
(144 KB)
📄
vxgb.tar.gz
(76.64 KB)
📄
vxgb.zip
(124.62 KB)
📄
wacart.sql.sql.tar.gz
(18.18 KB)
📄
wacart.sql.tar
(178.5 KB)
📄
wacart.tar
(43 MB)
📄
wacart.tar.gz
(39.51 MB)
📄
wacart.zip
(42.97 MB)
📄
waid.php.php.tar.gz
(263 B)
📄
waid.php.tar
(2.5 KB)
📄
wait.h.h.tar.gz
(2.03 KB)
📄
wait.h.tar
(7 KB)
📄
wait.ph.ph.tar.gz
(167 B)
📄
wait.ph.tar
(5.5 KB)
📄
wait.so.so.tar.gz
(4.66 KB)
📄
wait.so.tar
(13.5 KB)
📄
waitflags.h.h.tar.gz
(970 B)
📄
waitflags.h.tar
(3.5 KB)
📄
waitstatus.h.h.tar.gz
(1.09 KB)
📄
waitstatus.h.tar
(4 KB)
📄
waitstatus.ph.ph.tar.gz
(584 B)
📄
waitstatus.ph.tar
(3.5 KB)
📄
wakeup.tar
(2 KB)
📄
wakeup.tar.gz
(133 B)
📄
wallabag.tar
(66.12 MB)
📄
wallabag.tar.gz
(62.72 MB)
📄
wallabag.zip
(66.09 MB)
📄
warnings.h.h.tar.gz
(2.25 KB)
📄
warnings.h.tar
(9.5 KB)
📄
warnings.py.py.tar.gz
(5.45 KB)
📄
warnings.py.tar
(55 KB)
📄
warnings.pyc.pyc.tar.gz
(5.79 KB)
📄
warnings.pyc.tar
(15 KB)
📄
warnings.pyo.pyo.tar.gz
(5.52 KB)
📄
warnings.pyo.tar
(14 KB)
📄
warnings.tar
(3 KB)
📄
warnings.tar.gz
(111 B)
📄
watch.tar
(31 KB)
📄
watch.tar.gz
(11.81 KB)
📄
watchdog.tar
(2 KB)
📄
watchdog.tar.gz
(109 B)
📄
watchdog_thresh.tar
(2 KB)
📄
watchdog_thresh.tar.gz
(117 B)
📄
watermark_boost_factor.tar
(2 KB)
📄
watermark_boost_factor.tar.gz
(121 B)
📄
watermark_scale_factor.tar
(2 KB)
📄
watermark_scale_factor.tar.gz
(118 B)
📄
wave.py.py.tar.gz
(3.97 KB)
📄
wave.py.tar
(56.5 KB)
📄
wave.pyc.pyc.tar.gz
(6.05 KB)
📄
wave.pyc.tar
(21.5 KB)
📄
wave.pyo.pyo.tar.gz
(5.98 KB)
📄
wave.pyo.tar
(21 KB)
📄
wave521c_k3_codec_fw.bin.bin.tar.gz
(177.67 KB)
📄
wave521c_k3_codec_fw.bin.tar
(1.91 MB)
📄
wbce.png.png.tar.gz
(25.78 KB)
📄
wbce.png.tar
(27.5 KB)
📄
wbce.sql.sql.tar.gz
(18.86 KB)
📄
wbce.sql.tar
(78 KB)
📄
wbce.tar
(11.11 MB)
📄
wbce.tar.gz
(10.22 MB)
📄
wbce.zip
(11.09 MB)
📄
wbem-http.xml.tar
(2 KB)
📄
wbem-http.xml.xml.tar.gz
(341 B)
📄
wc.tar
(51.5 KB)
📄
wc.tar.gz
(22.01 KB)
📄
wchar.h.h.tar.gz
(5.83 KB)
📄
wchar.h.tar
(34.5 KB)
📄
wchar2.h.h.tar.gz
(2.78 KB)
📄
wchar2.h.tar
(19.5 KB)
📄
wcnhpbtfw21.tlv.tar
(151 KB)
📄
wcnhpbtfw21.tlv.tlv.tar.gz
(110.31 KB)
📄
wcnhpnv21.b10c.b10c.tar.gz
(3.03 KB)
📄
wcnhpnv21.b10c.tar
(8 KB)
📄
wcnhpnv21.b111.b111.tar.gz
(3.03 KB)
📄
wcnhpnv21.b111.tar
(8 KB)
📄
wcnhpnv21.b8c.b8c.tar.gz
(3.25 KB)
📄
wcnhpnv21.b8c.tar
(15 KB)
📄
wcnhpnv21.b9f.b9f.tar.gz
(3.25 KB)
📄
wcnhpnv21.b9f.tar
(15 KB)
📄
wcnhpnv21.ba0.ba0.tar.gz
(3.25 KB)
📄
wcnhpnv21.ba0.tar
(15 KB)
📄
wcnhpnv21.ba1.ba1.tar.gz
(3.25 KB)
📄
wcnhpnv21.ba1.tar
(15 KB)
📄
wcnhpnv21.ba2.ba2.tar.gz
(3.25 KB)
📄
wcnhpnv21.ba2.tar
(15 KB)
📄
wcnhpnv21.ba3.ba3.tar.gz
(3.14 KB)
📄
wcnhpnv21.ba3.tar
(15 KB)
📄
wcnhpnv21.ba4.ba4.tar.gz
(3.14 KB)
📄
wcnhpnv21.ba4.tar
(15 KB)
📄
wcnhpnv21.baa.baa.tar.gz
(3.03 KB)
📄
wcnhpnv21.baa.tar
(15 KB)
📄
wcnhpnv21.bb8.bb8.tar.gz
(3.25 KB)
📄
wcnhpnv21.bb8.tar
(15 KB)
📄
wcnhpnv21.bin.bin.tar.gz
(3.25 KB)
📄
wcnhpnv21.bin.tar
(15 KB)
📄
wcnhpnv21g.b10c.b10c.tar.gz
(3.03 KB)
📄
wcnhpnv21g.b10c.tar
(8 KB)
📄
wcnhpnv21g.b111.b111.tar.gz
(3.03 KB)
📄
wcnhpnv21g.b111.tar
(8 KB)
📄
wcnhpnv21g.b8c.b8c.tar.gz
(3.25 KB)
📄
wcnhpnv21g.b8c.tar
(8 KB)
📄
wcnhpnv21g.b9f.b9f.tar.gz
(3.24 KB)
📄
wcnhpnv21g.b9f.tar
(8 KB)
📄
wcnhpnv21g.ba0.ba0.tar.gz
(3.24 KB)
📄
wcnhpnv21g.ba0.tar
(8 KB)
📄
wcnhpnv21g.ba1.ba1.tar.gz
(3.25 KB)
📄
wcnhpnv21g.ba1.tar
(8 KB)
📄
wcnhpnv21g.ba2.ba2.tar.gz
(3.25 KB)
📄
wcnhpnv21g.ba2.tar
(8 KB)
📄
wcnhpnv21g.ba3.ba3.tar.gz
(3.14 KB)
📄
wcnhpnv21g.ba3.tar
(15 KB)
📄
wcnhpnv21g.ba4.ba4.tar.gz
(3.14 KB)
📄
wcnhpnv21g.ba4.tar
(8 KB)
📄
wcnhpnv21g.baa.baa.tar.gz
(3.03 KB)
📄
wcnhpnv21g.baa.tar
(8 KB)
📄
wcnhpnv21g.bb8.bb8.tar.gz
(3.24 KB)
📄
wcnhpnv21g.bb8.tar
(8 KB)
📄
wcnhpnv21g.bin.bin.tar.gz
(3.25 KB)
📄
wcnhpnv21g.bin.tar
(8 KB)
📄
wctype-wchar.h.h.tar.gz
(2.08 KB)
📄
wctype-wchar.h.tar
(8 KB)
📄
wctype.h.h.tar.gz
(1.67 KB)
📄
wctype.h.tar
(7 KB)
📄
weakref.py.py.tar.gz
(4.74 KB)
📄
weakref.py.tar
(58 KB)
📄
weakref.pyc.pyc.tar.gz
(4.88 KB)
📄
weakref.pyc.tar
(18 KB)
📄
weakref.pyo.pyo.tar.gz
(4.88 KB)
📄
weakref.pyo.tar
(18 KB)
📄
weakref.rb.rb.tar.gz
(779 B)
📄
weakref.rb.tar
(13 KB)
📄
web.sh.sh.tar.gz
(495 B)
📄
web.sh.tar
(3 KB)
📄
web.tar
(397.5 KB)
📄
web.tar.gz
(126.96 KB)
📄
web.zip
(391.75 KB)
📄
webasyst.tar
(130.46 MB)
📄
webasyst.tar.gz
(127.33 MB)
📄
webbrowser.py.py.tar.gz
(5.9 KB)
📄
webbrowser.py.tar
(70.5 KB)
📄
webbrowser.pyc.pyc.tar.gz
(7.53 KB)
📄
webbrowser.pyc.tar
(21 KB)
📄
webbrowser.pyo.pyo.tar.gz
(7.5 KB)
📄
webbrowser.pyo.tar
(21 KB)
📄
webcachemgr.tar
(624 KB)
📄
webcachemgr.tar.gz
(90.31 KB)
📄
webcachemgr.zip
(574.99 KB)
📄
webcal.sql.sql.tar.gz
(3.46 KB)
📄
webcal.sql.tar
(20.5 KB)
📄
webcal.tar
(5.3 MB)
📄
webcal.tar.gz
(5.11 MB)
📄
webcal.zip
(5.28 MB)
📄
webcollab.tar
(150 KB)
📄
webcollab.tar.gz
(77.8 KB)
📄
webcollab.zip
(128.68 KB)
📄
webconsole.html.html.tar.gz
(1.69 KB)
📄
webconsole.html.tar
(7.5 KB)
📄
weberp.tar
(229 KB)
📄
weberp.tar.gz
(109 KB)
📄
weberp.zip
(199.64 KB)
📄
webid.tar
(214.5 KB)
📄
webid.tar.gz
(120.2 KB)
📄
webid.zip
(188.9 KB)
📄
webmail.sql.sql.tar.gz
(5.1 KB)
📄
webmail.sql.tar
(44 KB)
📄
webmail.tar
(67.12 MB)
📄
webmail.tar.gz
(58.23 MB)
📄
webmail.zip
(67.09 MB)
📄
webp.tar
(97.5 KB)
📄
webp.tar.gz
(23.72 KB)
📄
webp.zip
(92.44 KB)
📄
webpmux.tar
(264 KB)
📄
webpmux.tar.gz
(125.95 KB)
📄
webrick.rb.rb.tar.gz
(2.57 KB)
📄
webrick.rb.tar
(31 KB)
📄
webrick.tar
(202.5 KB)
📄
webrick.tar.gz
(48.02 KB)
📄
webrick.zip
(181.74 KB)
📄
webtrees.tar
(28.96 MB)
📄
webtrees.tar.gz
(26.64 MB)
📄
webtrees.zip
(28.93 MB)
📄
wfm_wf200_C0.sec.sec.tar.gz
(305.32 KB)
📄
wfm_wf200_C0.sec.tar
(307 KB)
📄
wfx.tar
(311.5 KB)
📄
wfx.tar.gz
(305.72 KB)
📄
wfx.zip
(307.43 KB)
📄
wget.tar
(523 KB)
📄
wget.tar.gz
(250.02 KB)
📄
wgetrc.tar
(6.5 KB)
📄
wgetrc.tar.gz
(2.26 KB)
📄
wheel.tar
(2 KB)
📄
wheel.tar.gz
(254 B)
📄
whereis.tar
(31 KB)
📄
whereis.tar.gz
(12.12 KB)
📄
which.pyc.pyc.tar.gz
(985 B)
📄
which.pyc.tar
(3.5 KB)
📄
which.pyo.pyo.tar.gz
(984 B)
📄
which.pyo.tar
(3.5 KB)
📄
which.tar
(31 KB)
📄
which.tar.gz
(12.75 KB)
📄
whichdb.py.py.tar.gz
(1.31 KB)
📄
whichdb.py.tar
(5 KB)
📄
whichdb.pyc.pyc.tar.gz
(1.25 KB)
📄
whichdb.pyc.tar
(4 KB)
📄
whichdb.pyo.pyo.tar.gz
(1.25 KB)
📄
whichdb.pyo.tar
(4 KB)
📄
whiteheat.fw.fw.tar.gz
(13.1 KB)
📄
whiteheat.fw.tar
(25 KB)
📄
whiteheat_loader.fw.fw.tar.gz
(3.39 KB)
📄
whiteheat_loader.fw.tar
(7 KB)
📄
whmcs.sql.sql.tar.gz
(42.97 KB)
📄
whmcs.sql.tar
(270.5 KB)
📄
whmcs.tar
(164.49 MB)
📄
whmcs.tar.gz
(151.79 MB)
📄
whmcs.zip
(164.46 MB)
📄
whmcs81.tar
(230 KB)
📄
whmcs81.tar.gz
(131.45 KB)
📄
whmcs81.zip
(205.94 KB)
📄
whmcs813.tar
(145.59 MB)
📄
whmcs813.tar.gz
(141.86 MB)
📄
whmcs813.zip
(145.56 MB)
📄
whmcs82.tar
(235.5 KB)
📄
whmcs82.tar.gz
(133.9 KB)
📄
whmcs82.zip
(210.62 KB)
📄
whmcs83.tar
(228.5 KB)
📄
whmcs83.tar.gz
(131.19 KB)
📄
whmcs83.zip
(203.14 KB)
📄
whmcs89.sql.sql.tar.gz
(41.56 KB)
📄
whmcs89.sql.tar
(261 KB)
📄
whmcs89.tar
(113.58 MB)
📄
whmcs89.tar.gz
(109.85 MB)
📄
whmcs89.zip
(113.55 MB)
📄
who.tar
(55.5 KB)
📄
who.tar.gz
(25.16 KB)
📄
whoami.tar
(35 KB)
📄
whoami.tar.gz
(14.88 KB)
📄
whrlpool.h.h.tar.gz
(720 B)
📄
whrlpool.h.tar
(3 KB)
📄
wiki-icon.png.png.tar.gz
(1.54 KB)
📄
wiki-icon.png.tar
(3 KB)
📄
wiki.pyc.pyc.tar.gz
(2.43 KB)
📄
wiki.pyc.tar
(7 KB)
📄
wiki.pyo.pyo.tar.gz
(2.43 KB)
📄
wiki.pyo.tar
(7 KB)
📄
wikka.tar
(276 KB)
📄
wikka.tar.gz
(161.27 KB)
📄
wikka.zip
(244.14 KB)
📄
wil6210.brd.brd.tar.gz
(1.75 KB)
📄
wil6210.brd.tar
(10 KB)
📄
wil6210.fw.fw.tar.gz
(247.26 KB)
📄
wil6210.fw.tar
(784 KB)
📄
wilc1000_fw.bin.bin.tar.gz
(72.31 KB)
📄
wilc1000_fw.bin.tar
(123.5 KB)
📄
wilc1000_p2p_fw.bin.bin.tar.gz
(81.83 KB)
📄
wilc1000_p2p_fw.bin.tar
(141.5 KB)
📄
wilc1000_wifi_firmware.bin.bin.tar.gz
(83.83 KB)
📄
wilc1000_wifi_firmware.bin.tar
(135 KB)
📄
win32.rb.rb.tar.gz
(802 B)
📄
win32.rb.tar
(8.5 KB)
📄
windows_1250.so.so.tar.gz
(4.36 KB)
📄
windows_1250.so.tar
(13.5 KB)
📄
windows_1251.so.so.tar.gz
(4.23 KB)
📄
windows_1251.so.tar
(13.5 KB)
📄
windows_1252.so.so.tar.gz
(4.36 KB)
📄
windows_1252.so.tar
(13.5 KB)
📄
windows_1253.so.so.tar.gz
(4.26 KB)
📄
windows_1253.so.tar
(13.5 KB)
📄
windows_1254.so.so.tar.gz
(4.44 KB)
📄
windows_1254.so.tar
(13.5 KB)
📄
windows_1257.so.so.tar.gz
(4.42 KB)
📄
windows_1257.so.tar
(13.5 KB)
📄
wint_t.h.h.tar.gz
(507 B)
📄
wint_t.h.tar
(2.5 KB)
📄
wintercms.sql.sql.tar.gz
(4.13 KB)
📄
wintercms.sql.tar
(30 KB)
📄
wintercms.tar
(25.46 MB)
📄
wintercms.tar.gz
(22.26 MB)
📄
wintercms.zip
(25.44 MB)
📄
wireshark.tar
(2.52 MB)
📄
wireshark.tar.gz
(729.45 KB)
📄
wireshark.zip
(2.5 MB)
📄
wis-startrek.fw.fw.tar.gz
(4.29 KB)
📄
wis-startrek.fw.tar
(8 KB)
📄
wish.py.py.tar.gz
(448 B)
📄
wish.py.tar
(2.5 KB)
📄
wl1251-fw.bin.bin.tar.gz
(113.49 KB)
📄
wl1251-fw.bin.tar
(191.5 KB)
📄
wl1271-fw-ap.bin.bin.tar.gz
(156.98 KB)
📄
wl1271-fw-ap.bin.tar
(268 KB)
📄
wl1271-fw.bin.bin.tar.gz
(160.68 KB)
📄
wl1271-fw.bin.tar
(267 KB)
📄
wl128x-fw-ap.bin.bin.tar.gz
(156.97 KB)
📄
wl128x-fw-ap.bin.tar
(261 KB)
📄
wl128x-fw.bin.bin.tar.gz
(165.54 KB)
📄
wl128x-fw.bin.tar
(268.5 KB)
📄
wl18xx-fw.bin.bin.tar.gz
(196.36 KB)
📄
wl18xx-fw.bin.tar
(406 KB)
📄
wmem_default.tar
(2 KB)
📄
wmem_default.tar.gz
(120 B)
📄
wmem_max.tar
(2 KB)
📄
wmem_max.tar.gz
(116 B)
📄
wolf.png.png.tar.gz
(18.25 KB)
📄
wolf.png.tar
(20 KB)
📄
wolf.tar
(169 KB)
📄
wolf.tar.gz
(100.08 KB)
📄
wolf.zip
(150.6 KB)
📄
wonder.tar
(262.5 KB)
📄
wonder.tar.gz
(190.33 KB)
📄
wonder.zip
(241.78 KB)
📄
word-list-compress.tar
(13.5 KB)
📄
word-list-compress.tar.gz
(4.25 KB)
📄
wordsize.h.h.tar.gz
(334 B)
📄
wordsize.h.tar
(2 KB)
📄
wordsize.ph.ph.tar.gz
(349 B)
📄
wordsize.ph.tar
(2.5 KB)
📄
work.xml.tar
(2 KB)
📄
work.xml.xml.tar.gz
(315 B)
📄
workspace.xml.tar
(53.5 KB)
📄
workspace.xml.xml.tar.gz
(6.78 KB)
📄
wp-22.php.php.tar.gz
(85.65 KB)
📄
wp-22.php.tar
(154.5 KB)
📄
wp-config.php.php.tar.gz
(1.27 KB)
📄
wp-config.php.tar
(76 KB)
📄
wp-content.tar
(51 KB)
📄
wp-content.tar.gz
(18.55 KB)
📄
wp-content.zip
(48.27 KB)
📄
wp-includes.tar
(102 KB)
📄
wp-includes.tar.gz
(36.96 KB)
📄
wp-includes.zip
(96.82 KB)
📄
wp.tar
(6.2 MB)
📄
wp.tar.gz
(1.29 MB)
📄
wp.zip
(76.29 MB)
📄
wp49.sql.sql.tar.gz
(6.56 KB)
📄
wp49.sql.tar
(29 KB)
📄
wp49.tar
(43.28 MB)
📄
wp49.tar.gz
(42.54 MB)
📄
wp49.zip
(43.21 MB)
📄
wp50.sql.sql.tar.gz
(6.65 KB)
📄
wp50.sql.tar
(30.5 KB)
📄
wp50.tar
(43.38 MB)
📄
wp50.tar.gz
(42.59 MB)
📄
wp50.zip
(43.31 MB)
📄
wp51.sql.sql.tar.gz
(6.67 KB)
📄
wp51.sql.tar
(30.5 KB)
📄
wp51.tar
(43.08 MB)
📄
wp51.tar.gz
(42.29 MB)
📄
wp51.zip
(43.02 MB)
📄
wp52.sql.sql.tar.gz
(6.71 KB)
📄
wp52.sql.tar
(30.5 KB)
📄
wp52.tar
(45.26 MB)
📄
wp52.tar.gz
(44.42 MB)
📄
wp52.zip
(45.2 MB)
📄
wp53.sql.sql.tar.gz
(6.74 KB)
📄
wp53.sql.tar
(30.5 KB)
📄
wp53.tar
(46.11 MB)
📄
wp53.tar.gz
(45.28 MB)
📄
wp53.zip
(46.05 MB)
📄
wp54.sql.sql.tar.gz
(6.77 KB)
📄
wp54.sql.tar
(31 KB)
📄
wp54.tar
(46.98 MB)
📄
wp54.tar.gz
(46.15 MB)
📄
wp54.zip
(46.92 MB)
📄
wp55.sql.sql.tar.gz
(6.8 KB)
📄
wp55.sql.tar
(31 KB)
📄
wp55.tar
(49.51 MB)
📄
wp55.tar.gz
(48.58 MB)
📄
wp55.zip
(49.44 MB)
📄
wp56.sql.sql.tar.gz
(6.87 KB)
📄
wp56.sql.tar
(31.5 KB)
📄
wp56.tar
(51.72 MB)
📄
wp56.tar.gz
(50.75 MB)
📄
wp56.zip
(51.65 MB)
📄
wp57.sql.sql.tar.gz
(6.78 KB)
📄
wp57.sql.tar
(31 KB)
📄
wp57.tar
(51.93 MB)
📄
wp57.tar.gz
(50.96 MB)
📄
wp57.zip
(51.86 MB)
📄
wp58.sql.sql.tar.gz
(6.85 KB)
📄
wp58.sql.tar
(31.5 KB)
📄
wp58.tar
(52.97 MB)
📄
wp58.tar.gz
(51.88 MB)
📄
wp58.zip
(52.91 MB)
📄
wp59.sql.sql.tar.gz
(6.79 KB)
📄
wp59.sql.tar
(31.5 KB)
📄
wp59.tar
(59.54 MB)
📄
wp59.tar.gz
(58.4 MB)
📄
wp59.zip
(59.47 MB)
📄
wp60.sql.sql.tar.gz
(6.83 KB)
📄
wp60.sql.tar
(31.5 KB)
📄
wp60.tar
(60.9 MB)
📄
wp60.tar.gz
(59.69 MB)
📄
wp60.zip
(60.83 MB)
📄
wp61.sql.sql.tar.gz
(6.85 KB)
📄
wp61.sql.tar
(31.5 KB)
📄
wp61.tar
(62.89 MB)
📄
wp61.tar.gz
(61.68 MB)
📄
wp61.zip
(62.83 MB)
📄
wp62.sql.sql.tar.gz
(6.86 KB)
📄
wp62.sql.tar
(31.5 KB)
📄
wp62.tar
(62.48 MB)
📄
wp62.tar.gz
(61.32 MB)
📄
wp62.zip
(62.42 MB)
📄
wp63.sql.sql.tar.gz
(6.86 KB)
📄
wp63.sql.tar
(31.5 KB)
📄
wp63.tar
(63.16 MB)
📄
wp63.tar.gz
(61.98 MB)
📄
wp63.zip
(63.1 MB)
📄
wp64.sql.sql.tar.gz
(6.86 KB)
📄
wp64.sql.tar
(31.5 KB)
📄
wp64.tar
(64.31 MB)
📄
wp64.tar.gz
(63.16 MB)
📄
wp64.zip
(64.25 MB)
📄
wp65.sql.sql.tar.gz
(6.88 KB)
📄
wp65.sql.tar
(32 KB)
📄
wp65.tar
(64.83 MB)
📄
wp65.tar.gz
(63.71 MB)
📄
wp65.zip
(64.77 MB)
📄
wp66.sql.sql.tar.gz
(6.91 KB)
📄
wp66.sql.tar
(32 KB)
📄
wp66.tar
(65.08 MB)
📄
wp66.tar.gz
(63.93 MB)
📄
wp66.zip
(65.01 MB)
📄
wp67.sql.sql.tar.gz
(6.91 KB)
📄
wp67.sql.tar
(32 KB)
📄
wp67.tar
(68.21 MB)
📄
wp67.tar.gz
(67 MB)
📄
wp67.zip
(68.14 MB)
📄
wp68.sql.sql.tar.gz
(6.91 KB)
📄
wp68.sql.tar
(32 KB)
📄
wp68.tar
(69.19 MB)
📄
wp68.tar.gz
(67.95 MB)
📄
wp68.zip
(69.12 MB)
📄
wp_plugins.tar
(21.37 MB)
📄
wp_plugins.tar.gz
(21.2 MB)
📄
wp_plugins.zip
(21.35 MB)
📄
wpfix.tar
(11 KB)
📄
wpfix.tar.gz
(3.03 KB)
📄
wpg.so.so.tar.gz
(14.49 KB)
📄
wpg.so.tar
(33.5 KB)
📄
wpss.mdt.mdt.tar.gz
(3.41 MB)
📄
wpss.mdt.tar
(7.12 MB)
📄
wrapper.py.py.tar.gz
(887 B)
📄
wrapper.py.tar
(3.5 KB)
📄
wrapper.pyc.pyc.tar.gz
(778 B)
📄
wrapper.pyc.tar
(3 KB)
📄
wrapper.pyo.pyo.tar.gz
(780 B)
📄
wrapper.pyo.tar
(3 KB)
📄
writer.h.h.tar.gz
(2.78 KB)
📄
writer.h.tar
(10 KB)
📄
writes.tar
(2 KB)
📄
writes.tar.gz
(117 B)
📄
ws.tar
(458.5 KB)
📄
ws.tar.gz
(106.74 KB)
📄
ws.zip
(449.54 KB)
📄
wsgiref.tar
(454.5 KB)
📄
wsgiref.tar.gz
(48.16 KB)
📄
wsgiref.zip
(421.74 KB)
📄
wsm_22.bin.bin.tar.gz
(53.89 KB)
📄
wsm_22.bin.tar
(194 KB)
📄
wsman.xml.tar
(3 KB)
📄
wsman.xml.xml.tar.gz
(319 B)
📄
wsmans.xml.tar
(2 KB)
📄
wsmans.xml.xml.tar.gz
(322 B)
📄
wsrep_info.so.so.tar.gz
(7.76 KB)
📄
wsrep_info.so.tar
(21.5 KB)
📄
wswatch.sh.sh.tar.gz
(395 B)
📄
wswatch.sh.tar
(2.5 KB)
📄
www.tar
(1.3 GB)
📄
www.tar.gz
(389.63 MB)
📄
www.zip
(4.63 GB)
📄
wwwindex.php.php.tar.gz
(123 B)
📄
wwwindex.php.tar
(3 KB)
📄
x11-xcb.pc.pc.tar.gz
(253 B)
📄
x11-xcb.pc.tar
(2 KB)
📄
x11.conf.conf.tar.gz
(446 B)
📄
x11.conf.tar
(4 KB)
📄
x11.pc.pc.tar.gz
(276 B)
📄
x11.pc.tar
(2 KB)
📄
x1e80100.tar
(81.38 MB)
📄
x1e80100.tar.gz
(41.64 MB)
📄
x1e80100.zip
(81.35 MB)
📄
x1p42100.tar
(13.5 KB)
📄
x1p42100.tar.gz
(2.12 KB)
📄
x1p42100.zip
(11.97 KB)
📄
x2.zip
(112.77 KB)
📄
x509.h.h.tar.gz
(8.28 KB)
📄
x509.h.tar
(44 KB)
📄
x509.rb.rb.tar.gz
(1.77 KB)
📄
x509.rb.tar
(6 KB)
📄
x509_vfy.h.h.tar.gz
(6.35 KB)
📄
x509_vfy.h.tar
(33.5 KB)
📄
x509v3.h.h.tar.gz
(7.65 KB)
📄
x509v3.h.tar
(34.5 KB)
📄
x509v3err.h.h.tar.gz
(2.04 KB)
📄
x509v3err.h.tar
(10.5 KB)
📄
x86_64-linux.tar
(4.5 KB)
📄
x86_64-linux.tar.gz
(1.19 KB)
📄
x86_64-linux.zip
(3.1 KB)
📄
xaps_plugin.so.so.tar.gz
(3.95 KB)
📄
xaps_plugin.so.tar
(15 KB)
📄
xargs.tar
(76 KB)
📄
xargs.tar.gz
(34.97 KB)
📄
xattr.h.h.tar.gz
(1.2 KB)
📄
xattr.h.tar
(6 KB)
📄
xau.pc.pc.tar.gz
(253 B)
📄
xau.pc.tar
(2 KB)
📄
xc_misc.h.h.tar.gz
(1.24 KB)
📄
xc_misc.h.tar
(8.5 KB)
📄
xcache_3.tar
(6.5 KB)
📄
xcache_3.tar.gz
(1.32 KB)
📄
xcache_3.zip
(3.61 KB)
📄
xcb-dpms.pc.pc.tar.gz
(253 B)
📄
xcb-dpms.pc.tar
(2 KB)
📄
xcb-dri2.pc.pc.tar.gz
(252 B)
📄
xcb-dri2.pc.tar
(2 KB)
📄
xcb-dri3.pc.pc.tar.gz
(252 B)
📄
xcb-dri3.pc.tar
(2 KB)
📄
xcb-glx.pc.pc.tar.gz
(251 B)
📄
xcb-glx.pc.tar
(2 KB)
📄
xcb-present.pc.pc.tar.gz
(271 B)
📄
xcb-present.pc.tar
(2 KB)
📄
xcb-randr.pc.pc.tar.gz
(258 B)
📄
xcb-randr.pc.tar
(2 KB)
📄
xcb-res.pc.pc.tar.gz
(255 B)
📄
xcb-res.pc.tar
(2 KB)
📄
xcb-screensaver.pc.pc.tar.gz
(257 B)
📄
xcb-screensaver.pc.tar
(2 KB)
📄
xcb-shape.pc.pc.tar.gz
(253 B)
📄
xcb-shape.pc.tar
(2 KB)
📄
xcb-shm.pc.pc.tar.gz
(252 B)
📄
xcb-shm.pc.tar
(2 KB)
📄
xcb-sync.pc.pc.tar.gz
(253 B)
📄
xcb-sync.pc.tar
(2 KB)
📄
xcb-xf86dri.pc.pc.tar.gz
(261 B)
📄
xcb-xf86dri.pc.tar
(2 KB)
📄
xcb-xinerama.pc.pc.tar.gz
(256 B)
📄
xcb-xinerama.pc.tar
(2 KB)
📄
xcb-xkb.pc.pc.tar.gz
(272 B)
📄
xcb-xkb.pc.tar
(2 KB)
📄
xcb-xselinux.pc.pc.tar.gz
(257 B)
📄
xcb-xselinux.pc.tar
(2 KB)
📄
xcb-xtest.pc.pc.tar.gz
(255 B)
📄
xcb-xtest.pc.tar
(2 KB)
📄
xcb-xv.pc.pc.tar.gz
(254 B)
📄
xcb-xv.pc.tar
(2 KB)
📄
xcb-xvmc.pc.pc.tar.gz
(256 B)
📄
xcb-xvmc.pc.tar
(2 KB)
📄
xcb.h.h.tar.gz
(5.94 KB)
📄
xcb.h.tar
(22.5 KB)
📄
xcb.pc.pc.tar.gz
(274 B)
📄
xcb.pc.tar
(2 KB)
📄
xcb.tar
(1.99 MB)
📄
xcb.tar.gz
(176.23 KB)
📄
xcb.zip
(1.97 MB)
📄
xcbext.h.h.tar.gz
(3.42 KB)
📄
xcbext.h.tar
(15.5 KB)
📄
xcbglintegrations.tar
(155 KB)
📄
xcbglintegrations.tar.gz
(57.06 KB)
📄
xcbglintegrations.zip
(152.83 KB)
📄
xcloner.tar
(135.5 KB)
📄
xcloner.tar.gz
(64.98 KB)
📄
xcloner.zip
(112.84 KB)
📄
xdmcp.xml.tar
(2 KB)
📄
xdmcp.xml.xml.tar.gz
(326 B)
📄
xdr.h.h.tar.gz
(4.02 KB)
📄
xdr.h.tar
(13.5 KB)
📄
xdr.py.py.tar.gz
(1.32 KB)
📄
xdr.py.tar
(6.5 KB)
📄
xdrlib.py.py.tar.gz
(1.53 KB)
📄
xdrlib.py.tar
(20.5 KB)
📄
xdrlib.pyc.pyc.tar.gz
(3.12 KB)
📄
xdrlib.pyc.tar
(11.5 KB)
📄
xdrlib.pyo.pyo.tar.gz
(3.12 KB)
📄
xdrlib.pyo.tar
(11.5 KB)
📄
xe.tar
(3.95 MB)
📄
xe.tar.gz
(2.3 MB)
📄
xe.zip
(3.94 MB)
📄
xe2lpd_dmc.bin.bin.tar.gz
(16.96 KB)
📄
xe2lpd_dmc.bin.tar
(61 KB)
📄
xe3lpd_dmc.bin.bin.tar.gz
(20.08 KB)
📄
xe3lpd_dmc.bin.tar
(95 KB)
📄
xe3p_lpd_dmc.bin.bin.tar.gz
(15.59 KB)
📄
xe3p_lpd_dmc.bin.tar
(69 KB)
📄
xen.tar
(21.5 KB)
📄
xen.tar.gz
(4.69 KB)
📄
xen.zip
(17.81 KB)
📄
xevie.h.h.tar.gz
(1.7 KB)
📄
xevie.h.tar
(13 KB)
📄
xf86dri.h.h.tar.gz
(2.72 KB)
📄
xf86dri.h.tar
(29 KB)
📄
xf86driproto.h.h.tar.gz
(2.17 KB)
📄
xf86driproto.h.tar
(11 KB)
📄
xfixes.h.h.tar.gz
(5.14 KB)
📄
xfixes.h.tar
(58.5 KB)
📄
xfrm4_gc_thresh.tar
(2 KB)
📄
xfrm4_gc_thresh.tar.gz
(122 B)
📄
xfrm6_gc_thresh.tar
(2 KB)
📄
xfrm6_gc_thresh.tar.gz
(121 B)
📄
xfrm_acq_expires.tar
(2 KB)
📄
xfrm_acq_expires.tar.gz
(119 B)
📄
xfrm_aevent_etime.tar
(2 KB)
📄
xfrm_aevent_etime.tar.gz
(119 B)
📄
xfrm_aevent_rseqth.tar
(2 KB)
📄
xfrm_aevent_rseqth.tar.gz
(120 B)
📄
xfrm_larval_drop.tar
(2 KB)
📄
xfrm_larval_drop.tar.gz
(118 B)
📄
xfs.mod.mod.tar.gz
(6.23 KB)
📄
xfs.mod.tar
(30 KB)
📄
xfssyncd_centisecs.tar
(2 KB)
📄
xfssyncd_centisecs.tar.gz
(117 B)
📄
xinerama.h.h.tar.gz
(1.88 KB)
📄
xinerama.h.tar
(16.5 KB)
📄
xinput.h.h.tar.gz
(23.05 KB)
📄
xinput.h.tar
(300 KB)
📄
xircom_pgs.fw.fw.tar.gz
(1.36 KB)
📄
xircom_pgs.fw.tar
(3.5 KB)
📄
xkb.h.h.tar.gz
(21.06 KB)
📄
xkb.h.tar
(242.5 KB)
📄
xkb.tar
(1.65 MB)
📄
xkb.tar.gz
(1.28 MB)
📄
xkb.zip
(1.46 MB)
📄
xlib-2.0.typelib.0.typelib.tar.gz
(474 B)
📄
xlib-2.0.typelib.tar
(2.5 KB)
📄
xmas.pyc.pyc.tar.gz
(5.02 KB)
📄
xmas.pyc.tar
(21 KB)
📄
xmas.pyo.pyo.tar.gz
(5.02 KB)
📄
xmas.pyo.tar
(21 KB)
📄
xmb.png.png.tar.gz
(14.71 KB)
📄
xmb.png.tar
(16.5 KB)
📄
xmb.sql.sql.tar.gz
(4.82 KB)
📄
xmb.sql.tar
(28 KB)
📄
xmb.tar
(1.99 MB)
📄
xmb.tar.gz
(1.7 MB)
📄
xmb.zip
(1.96 MB)
📄
xml.rb.rb.tar.gz
(641 B)
📄
xml.rb.tar
(15.5 KB)
📄
xml.tar
(2.23 MB)
📄
xml.tar.gz
(268.92 KB)
📄
xml.zip
(2.11 MB)
📄
xml2Conf.sh.sh.tar.gz
(262 B)
📄
xml2Conf.sh.tar
(2 KB)
📄
xmlcatalog.tar
(43 KB)
📄
xmlcatalog.tar.gz
(8.18 KB)
📄
xmllib.py.py.tar.gz
(7.61 KB)
📄
xmllib.py.tar
(36 KB)
📄
xmllib.pyc.pyc.tar.gz
(10.06 KB)
📄
xmllib.pyc.tar
(28 KB)
📄
xmllib.pyo.pyo.tar.gz
(10.06 KB)
📄
xmllib.pyo.tar
(28 KB)
📄
xmllint.tar
(149 KB)
📄
xmllint.tar.gz
(29.05 KB)
📄
xmlparser.rb.rb.tar.gz
(685 B)
📄
xmlparser.rb.tar
(3.5 KB)
📄
xmlrpc.rb.rb.tar.gz
(2.98 KB)
📄
xmlrpc.rb.tar
(10 KB)
📄
xmlrpc.tar
(444 KB)
📄
xmlrpc.tar.gz
(73.31 KB)
📄
xmlrpc.zip
(431.05 KB)
📄
xmlrpclib.py.py.tar.gz
(14.04 KB)
📄
xmlrpclib.py.tar
(52.5 KB)
📄
xmlwf.tar
(38.5 KB)
📄
xmlwf.tar.gz
(14.73 KB)
📄
xmp.rb.rb.tar.gz
(1.81 KB)
📄
xmp.rb.tar
(33.5 KB)
📄
xmpp-bosh.xml.tar
(2 KB)
📄
xmpp-bosh.xml.xml.tar.gz
(406 B)
📄
xmpp-client.xml.tar
(2 KB)
📄
xmpp-client.xml.xml.tar.gz
(384 B)
📄
xmpp-server.xml.tar
(2.5 KB)
📄
xmpp-server.xml.xml.tar.gz
(406 B)
📄
xms.png.png.tar.gz
(5 KB)
📄
xms.png.tar
(7 KB)
📄
xms.tar
(96.5 KB)
📄
xms.tar.gz
(47.99 KB)
📄
xms.zip
(79.6 KB)
📄
xnu.mod.mod.tar.gz
(14.85 KB)
📄
xnu.mod.tar
(74 KB)
📄
xnu_uuid.mod.mod.tar.gz
(1.4 KB)
📄
xnu_uuid.mod.tar
(4.5 KB)
📄
xnu_uuid_test.mod.mod.tar.gz
(999 B)
📄
xnu_uuid_test.mod.tar
(4 KB)
📄
xoops.sql.sql.tar.gz
(44.15 KB)
📄
xoops.sql.tar
(269 KB)
📄
xoops.tar
(14.76 MB)
📄
xoops.tar.gz
(13.28 MB)
📄
xoops.zip
(14.73 MB)
📄
xpdo.class.php.class.php.tar.gz
(25.26 KB)
📄
xpdo.class.php.tar
(131 KB)
📄
xpm.h.h.tar.gz
(4.25 KB)
📄
xpm.h.tar
(17.5 KB)
📄
xpm.pc.pc.tar.gz
(247 B)
📄
xpm.pc.tar
(2 KB)
📄
xprint.h.h.tar.gz
(4.78 KB)
📄
xprint.h.tar
(57.5 KB)
📄
xproto.h.h.tar.gz
(42.52 KB)
📄
xproto.h.tar
(378.5 KB)
📄
xqm.tar
(2 KB)
📄
xqm.tar.gz
(98 B)
📄
xqmstat.tar
(2 KB)
📄
xqmstat.tar.gz
(103 B)
📄
xselinux.h.h.tar.gz
(3.86 KB)
📄
xselinux.h.tar
(57 KB)
📄
xslt.h.h.tar.gz
(864 B)
📄
xslt.h.tar
(3.5 KB)
📄
xsltConf.sh.sh.tar.gz
(238 B)
📄
xsltConf.sh.tar
(2 KB)
📄
xsltexports.h.h.tar.gz
(883 B)
📄
xsltexports.h.tar
(5 KB)
📄
xsltproc.tar
(30 KB)
📄
xsltproc.tar.gz
(11.61 KB)
📄
xsltutils.h.h.tar.gz
(2.41 KB)
📄
xsltutils.h.tar
(10 KB)
📄
xsubpp.tar
(6.5 KB)
📄
xsubpp.tar.gz
(2.39 KB)
📄
xtables.tar
(1.68 MB)
📄
xtables.tar.gz
(426.59 KB)
📄
xtables.zip
(1.6 MB)
📄
xtest.h.h.tar.gz
(1.42 KB)
📄
xtest.h.tar
(9 KB)
📄
xv.h.h.tar.gz
(5.26 KB)
📄
xv.h.tar
(58 KB)
📄
xvmc.h.h.tar.gz
(2.69 KB)
📄
xvmc.h.tar
(25.5 KB)
📄
xxd.tar
(22.5 KB)
📄
xxd.tar.gz
(9.29 KB)
📄
xy.php.php.tar.gz
(4.86 KB)
📄
xy.php.tar
(25.5 KB)
📄
xzio.mod.mod.tar.gz
(10.44 KB)
📄
xzio.mod.tar
(54 KB)
📄
y.rb.rb.tar.gz
(233 B)
📄
y.rb.tar
(8 KB)
📄
yam.tar
(13 KB)
📄
yam.tar.gz
(5.63 KB)
📄
yam.zip
(10.63 KB)
📄
yama.tar
(2 KB)
📄
yama.tar.gz
(96 B)
📄
yama.zip
(160 B)
📄
yamato_pfp.fw.fw.tar.gz
(713 B)
📄
yamato_pfp.fw.tar
(3 KB)
📄
yamato_pm4.fw.fw.tar.gz
(2.26 KB)
📄
yamato_pm4.fw.tar
(11 KB)
📄
yaml.rb.rb.tar.gz
(1.02 KB)
📄
yaml.rb.tar
(12 KB)
📄
yaml.tar
(12 KB)
📄
yaml.tar.gz
(2.75 KB)
📄
yaml.zip
(8.99 KB)
📄
yaml_events.rb.rb.tar.gz
(445 B)
📄
yaml_events.rb.tar
(2.5 KB)
📄
yellow_carp_asd.bin.bin.tar.gz
(46.27 KB)
📄
yellow_carp_asd.bin.tar
(166 KB)
📄
yellow_carp_ce.bin.bin.tar.gz
(5.21 KB)
📄
yellow_carp_ce.bin.tar
(259 KB)
📄
yellow_carp_dmcub.bin.bin.tar.gz
(157.94 KB)
📄
yellow_carp_dmcub.bin.tar
(231 KB)
📄
yellow_carp_me.bin.bin.tar.gz
(9.62 KB)
📄
yellow_carp_me.bin.tar
(259 KB)
📄
yellow_carp_mec.bin.bin.tar.gz
(41.59 KB)
📄
yellow_carp_mec.bin.tar
(263.5 KB)
📄
yellow_carp_pfp.bin.bin.tar.gz
(16.65 KB)
📄
yellow_carp_pfp.bin.tar
(259 KB)
📄
yellow_carp_rlc.bin.bin.tar.gz
(48.44 KB)
📄
yellow_carp_rlc.bin.tar
(175.5 KB)
📄
yellow_carp_ta.bin.bin.tar.gz
(79.7 KB)
📄
yellow_carp_ta.bin.tar
(238.5 KB)
📄
yellow_carp_toc.bin.bin.tar.gz
(1.05 KB)
📄
yellow_carp_toc.bin.tar
(3.5 KB)
📄
yellow_carp_vcn.bin.bin.tar.gz
(400.8 KB)
📄
yellow_carp_vcn.bin.tar
(560.5 KB)
📄
yes.tar
(35 KB)
📄
yes.tar.gz
(15.27 KB)
📄
yeti.png.png.tar.gz
(6.06 KB)
📄
yeti.png.tar
(8 KB)
📄
yeti.sql.sql.tar.gz
(208.81 KB)
📄
yeti.sql.tar
(1.57 MB)
📄
yeti.tar
(94.03 MB)
📄
yeti.tar.gz
(87.32 MB)
📄
yeti.zip
(94.01 MB)
📄
yii.png.png.tar.gz
(23.58 KB)
📄
yii.png.tar
(25 KB)
📄
yii.tar
(16.63 MB)
📄
yii.tar.gz
(16.21 MB)
📄
yii.zip
(16.62 MB)
📄
yourls.sql.sql.tar.gz
(998 B)
📄
yourls.sql.tar
(4.5 KB)
📄
yourls.tar
(5.67 MB)
📄
yourls.tar.gz
(5.28 MB)
📄
yourls.zip
(5.64 MB)
📄
yui.png.png.tar.gz
(6.04 KB)
📄
yui.png.tar
(8 KB)
📄
yui.tar
(54.5 KB)
📄
yui.tar.gz
(29.87 KB)
📄
yui.zip
(44.42 KB)
📄
zabbix-agent.conf.conf.tar.gz
(142 B)
📄
zabbix-agent.conf.tar
(2 KB)
📄
zabbix-agent.service.service.tar.gz
(376 B)
📄
zabbix-agent.service.tar
(2 KB)
📄
zabbix-agent.xml.tar
(2 KB)
📄
zabbix-agent.xml.xml.tar.gz
(309 B)
📄
zcat.tar
(3.5 KB)
📄
zcat.tar.gz
(1.06 KB)
📄
zcmp.tar
(3.5 KB)
📄
zcmp.tar.gz
(958 B)
📄
zconf.h.h.tar.gz
(4.43 KB)
📄
zconf.h.tar
(17.5 KB)
📄
zdiff.tar
(7.5 KB)
📄
zdiff.tar.gz
(1.96 KB)
📄
zegrep.tar
(2 KB)
📄
zegrep.tar.gz
(122 B)
📄
zen.png.png.tar.gz
(4.39 KB)
📄
zen.png.tar
(6.5 KB)
📄
zen.sql.sql.tar.gz
(14.54 KB)
📄
zen.sql.tar
(100 KB)
📄
zen.tar
(28.7 MB)
📄
zen.tar.gz
(27.62 MB)
📄
zen.zip
(28.66 MB)
📄
zenario.sql.sql.tar.gz
(10.76 MB)
📄
zenario.sql.tar
(11.16 MB)
📄
zenario.tar
(79.28 MB)
📄
zenario.tar.gz
(75.69 MB)
📄
zenario.zip
(79.25 MB)
📄
zenber.tar
(177 KB)
📄
zenber.tar.gz
(99.62 KB)
📄
zenber.zip
(155.99 KB)
📄
zencart.sql.sql.tar.gz
(57.54 KB)
📄
zencart.sql.tar
(334 KB)
📄
zencart.tar
(12.51 MB)
📄
zencart.tar.gz
(11.05 MB)
📄
zencart.zip
(12.48 MB)
📄
zend.png.png.tar.gz
(22.19 KB)
📄
zend.png.tar
(24 KB)
📄
zend.tar
(99 KB)
📄
zend.tar.gz
(57.85 KB)
📄
zend.zip
(84.49 KB)
📄
zenphoto.cfg.php.cfg.php.tar.gz
(1.66 KB)
📄
zenphoto.cfg.php.tar
(6 KB)
📄
zentao.sql.sql.tar.gz
(206.15 KB)
📄
zentao.sql.tar
(1.89 MB)
📄
zentao.tar
(98.64 MB)
📄
zentao.tar.gz
(90.52 MB)
📄
zentao.zip
(98.62 MB)
📄
zero.tar
(6 KB)
📄
zero.tar.gz
(450 B)
📄
zeromq.tar
(725.5 KB)
📄
zeromq.tar.gz
(257.53 KB)
📄
zeromq.zip
(720.55 KB)
📄
zeus.png.png.tar.gz
(3.9 KB)
📄
zeus.png.tar
(6 KB)
📄
zeus.tar
(162.5 KB)
📄
zeus.tar.gz
(87.8 KB)
📄
zeus.zip
(141.53 KB)
📄
zfgrep.tar
(2 KB)
📄
zfgrep.tar.gz
(122 B)
📄
zforce.tar
(4 KB)
📄
zforce.tar.gz
(1.12 KB)
📄
zfs.mod.mod.tar.gz
(24.24 KB)
📄
zfs.mod.tar
(118 KB)
📄
zfscrypt.mod.mod.tar.gz
(3.45 KB)
📄
zfscrypt.mod.tar
(8.5 KB)
📄
zfsinfo.mod.mod.tar.gz
(3.14 KB)
📄
zfsinfo.mod.tar
(9 KB)
📄
zgrep.tar
(9 KB)
📄
zgrep.tar.gz
(3.01 KB)
📄
zh_CN.tar
(126 KB)
📄
zh_CN.tar.gz
(96.55 KB)
📄
zh_CN.zip
(100.93 KB)
📄
zh_TW.tar
(22 KB)
📄
zh_TW.tar.gz
(14.68 KB)
📄
zh_TW.zip
(15.64 KB)
📄
zikula.tar
(297.5 KB)
📄
zikula.tar.gz
(188.49 KB)
📄
zikula.zip
(270.39 KB)
📄
zikula15.tar
(295.5 KB)
📄
zikula15.tar.gz
(176.81 KB)
📄
zikula15.zip
(268.31 KB)
📄
zipapp.py.py.tar.gz
(2.56 KB)
📄
zipapp.py.tar
(16.5 KB)
📄
zipcloak.tar
(104.5 KB)
📄
zipcloak.tar.gz
(48.37 KB)
📄
zipfile.py.py.tar.gz
(21.12 KB)
📄
zipfile.py.tar
(225.5 KB)
📄
zipfile.pyc.pyc.tar.gz
(17.49 KB)
📄
zipfile.pyc.tar
(43 KB)
📄
zipfile.pyo.pyo.tar.gz
(17.49 KB)
📄
zipfile.pyo.tar
(43 KB)
📄
zipgrep.tar
(4.5 KB)
📄
zipgrep.tar.gz
(1.26 KB)
📄
zipimport.py.py.tar.gz
(8.4 KB)
📄
zipimport.py.tar
(32 KB)
📄
zipinfo.tar
(203.5 KB)
📄
zipinfo.tar.gz
(98.71 KB)
📄
zipnote.tar
(99.5 KB)
📄
zipnote.tar.gz
(45.71 KB)
📄
zipsplit.tar
(99.5 KB)
📄
zipsplit.tar.gz
(47.37 KB)
📄
zless.tar
(4 KB)
📄
zless.tar.gz
(1.16 KB)
📄
zlib.h.h.tar.gz
(25.49 KB)
📄
zlib.h.tar
(96 KB)
📄
zlib.pc.pc.tar.gz
(255 B)
📄
zlib.pc.tar
(2 KB)
📄
zlib.so.so.tar.gz
(29.34 KB)
📄
zlib.so.tar
(137 KB)
📄
zlib.tar
(21 KB)
📄
zlib.tar.gz
(4.02 KB)
📄
zlib.zip
(16 KB)
📄
zlibdemo.py.py.tar.gz
(689 B)
📄
zlibdemo.py.tar
(3 KB)
📄
zmore.tar
(3.5 KB)
📄
zmore.tar.gz
(1021 B)
📄
znew.tar
(6 KB)
📄
znew.tar.gz
(1.84 KB)
📄
zones.tar
(11.5 KB)
📄
zones.tar.gz
(1.09 KB)
📄
zones.zip
(4.79 KB)
📄
zsoelim.tar
(44.5 KB)
📄
zsoelim.tar.gz
(16.86 KB)
📄
zts-php-cgi.tar
(5.72 MB)
📄
zts-php-cgi.tar.gz
(2.19 MB)
📄
zts-php.tar
(5.77 MB)
📄
zts-php.tar.gz
(2.21 MB)
📄
zurmo.tar
(305.5 KB)
📄
zurmo.tar.gz
(172.25 KB)
📄
zurmo.zip
(273.32 KB)
📄
zwiicms.tar
(9.86 MB)
📄
zwiicms.tar.gz
(9.51 MB)
📄
zwiicms.zip
(9.84 MB)
📄
zz8.php.php.tar.gz
(103.53 KB)
📄
zz8.php.tar
(380.5 KB)
Editing: private.tar
sql_trigger.h 0000644 00000027610 15156036123 0007247 0 ustar 00 #ifndef SQL_TRIGGER_INCLUDED #define SQL_TRIGGER_INCLUDED /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <mysqld_error.h> /* Forward declarations */ class Item_trigger_field; class sp_head; class sp_name; class Query_tables_list; struct TABLE_LIST; class Query_tables_list; typedef struct st_ddl_log_state DDL_LOG_STATE; /** Event on which trigger is invoked. */ enum trg_event_type { TRG_EVENT_INSERT= 0, TRG_EVENT_UPDATE= 1, TRG_EVENT_DELETE= 2, TRG_EVENT_MAX }; static inline uint8 trg2bit(enum trg_event_type trg) { return static_cast<uint8>(1 << static_cast<int>(trg)); } #include "table.h" /* GRANT_INFO */ /* We need this two enums here instead of sql_lex.h because at least one of them is used by Item_trigger_field interface. Time when trigger is invoked (i.e. before or after row actually inserted/updated/deleted). */ enum trg_action_time_type { TRG_ACTION_BEFORE= 0, TRG_ACTION_AFTER= 1, TRG_ACTION_MAX }; enum trigger_order_type { TRG_ORDER_NONE= 0, TRG_ORDER_FOLLOWS= 1, TRG_ORDER_PRECEDES= 2 }; struct st_trg_execution_order { /** FOLLOWS or PRECEDES as specified in the CREATE TRIGGER statement. */ enum trigger_order_type ordering_clause; /** Trigger name referenced in the FOLLOWS/PRECEDES clause of the CREATE TRIGGER statement. */ LEX_CSTRING anchor_trigger_name; }; /* Parameter to change_table_name_in_triggers() */ class TRIGGER_RENAME_PARAM { public: TABLE table; bool upgrading50to51; bool got_error; TRIGGER_RENAME_PARAM() { upgrading50to51= got_error= 0; table.reset(); } ~TRIGGER_RENAME_PARAM() { reset(); } void reset(); }; class Table_triggers_list; /** The trigger object */ class Trigger :public Sql_alloc { public: Trigger(Table_triggers_list *base_arg, sp_head *code): base(base_arg), body(code), next(0), action_order(0) { bzero((char *)&subject_table_grants, sizeof(subject_table_grants)); } ~Trigger(); Table_triggers_list *base; sp_head *body; Trigger *next; /* Next trigger of same type */ LEX_CSTRING name; LEX_CSTRING on_table_name; /* Raw table name */ LEX_CSTRING definition; LEX_CSTRING definer; /* Character sets used */ LEX_CSTRING client_cs_name; LEX_CSTRING connection_cl_name; LEX_CSTRING db_cl_name; GRANT_INFO subject_table_grants; sql_mode_t sql_mode; /* Store create time. Can't be mysql_time_t as this holds also sub seconds */ my_hrtime_t hr_create_time; // Create time timestamp in microseconds trg_event_type event; trg_action_time_type action_time; uint action_order; void get_trigger_info(LEX_CSTRING *stmt, LEX_CSTRING *body, LEX_STRING *definer); /* Functions executed over each active trigger */ bool change_on_table_name(void* param_arg); bool change_table_name(void* param_arg); bool add_to_file_list(void* param_arg); }; typedef bool (Trigger::*Triggers_processor)(void *arg); /** This class holds all information about triggers of table. */ class Table_triggers_list: public Sql_alloc { friend class Trigger; /* Points to first trigger for a certain type */ Trigger *triggers[TRG_EVENT_MAX][TRG_ACTION_MAX]; /** Copy of TABLE::Field array which all fields made nullable (using extra_null_bitmap, if needed). Used for NEW values in BEFORE INSERT/UPDATE triggers. */ Field **record0_field; uchar *extra_null_bitmap, *extra_null_bitmap_init; /** Copy of TABLE::Field array with field pointers set to TABLE::record[1] buffer instead of TABLE::record[0] (used for OLD values in on UPDATE trigger and DELETE trigger when it is called for REPLACE). */ Field **record1_field; /** During execution of trigger new_field and old_field should point to the array of fields representing new or old version of row correspondingly (so it can point to TABLE::field or to Tale_triggers_list::record1_field) */ Field **new_field; Field **old_field; /* TABLE instance for which this triggers list object was created */ TABLE *trigger_table; /** This flag indicates that one of the triggers was not parsed successfully, and as a precaution the object has entered a state where all trigger access results in errors until all such triggers are dropped. It is not safe to add triggers since we don't know if the broken trigger has the same name or event type. Nor is it safe to invoke any trigger for the aforementioned reasons. The only safe operations are drop_trigger and drop_all_triggers. @see Table_triggers_list::set_parse_error */ bool m_has_unparseable_trigger; /** This error will be displayed when the user tries to manipulate or invoke triggers on a table that has broken triggers. It will get set only once per statement and thus will contain the first parse error encountered in the trigger file. */ char m_parse_error_message[MYSQL_ERRMSG_SIZE]; uint count; /* Number of triggers */ public: /** Field responsible for storing triggers definitions in file. It have to be public because we are using it directly from parser. */ List<LEX_CSTRING> definitions_list; /** List of sql modes for triggers */ List<ulonglong> definition_modes_list; /** Create times for triggers */ List<ulonglong> hr_create_times; List<LEX_CSTRING> definers_list; /* Character set context, used for parsing and executing triggers. */ List<LEX_CSTRING> client_cs_names; List<LEX_CSTRING> connection_cl_names; List<LEX_CSTRING> db_cl_names; /* End of character ser context. */ Table_triggers_list(TABLE *table_arg) :record0_field(0), extra_null_bitmap(0), extra_null_bitmap_init(0), record1_field(0), trigger_table(table_arg), m_has_unparseable_trigger(false), count(0) { bzero((char *) triggers, sizeof(triggers)); } ~Table_triggers_list(); bool create_trigger(THD *thd, TABLE_LIST *table, String *stmt_query, DDL_LOG_STATE *ddl_log_state, DDL_LOG_STATE *ddl_log_state_tmp_file); bool drop_trigger(THD *thd, TABLE_LIST *table, LEX_CSTRING *sp_name, String *stmt_query, DDL_LOG_STATE *ddl_log_state); bool process_triggers(THD *thd, trg_event_type event, trg_action_time_type time_type, bool old_row_is_record1); void empty_lists(); bool create_lists_needed_for_files(MEM_ROOT *root); bool save_trigger_file(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name); static bool check_n_load(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, TABLE *table, bool names_only); static bool drop_all_triggers(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, myf MyFlags); static bool prepare_for_rename(THD *thd, TRIGGER_RENAME_PARAM *param, const LEX_CSTRING *db, const LEX_CSTRING *old_alias, const LEX_CSTRING *old_table, const LEX_CSTRING *new_db, const LEX_CSTRING *new_table); static bool change_table_name(THD *thd, TRIGGER_RENAME_PARAM *param, const LEX_CSTRING *db, const LEX_CSTRING *old_alias, const LEX_CSTRING *old_table, const LEX_CSTRING *new_db, const LEX_CSTRING *new_table); void add_trigger(trg_event_type event_type, trg_action_time_type action_time, trigger_order_type ordering_clause, LEX_CSTRING *anchor_trigger_name, Trigger *trigger); Trigger *get_trigger(trg_event_type event_type, trg_action_time_type action_time) { return triggers[event_type][action_time]; } /* Simpler version of the above, to avoid casts in the code */ Trigger *get_trigger(uint event_type, uint action_time) { return get_trigger((trg_event_type) event_type, (trg_action_time_type) action_time); } bool has_triggers(trg_event_type event_type, trg_action_time_type action_time) { return get_trigger(event_type,action_time) != 0; } bool has_delete_triggers() { return (has_triggers(TRG_EVENT_DELETE,TRG_ACTION_BEFORE) || has_triggers(TRG_EVENT_DELETE,TRG_ACTION_AFTER)); } void mark_fields_used(trg_event_type event); void set_parse_error_message(char *error_message); friend class Item_trigger_field; bool add_tables_and_routines_for_triggers(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list); Field **nullable_fields() { return record0_field; } void clear_extra_null_bitmap() { if (size_t null_bytes= extra_null_bitmap_init - extra_null_bitmap) bzero(extra_null_bitmap, null_bytes); } void default_extra_null_bitmap() { if (size_t null_bytes= extra_null_bitmap_init - extra_null_bitmap) memcpy(extra_null_bitmap, extra_null_bitmap_init, null_bytes); } Trigger *find_trigger(const LEX_CSTRING *name, bool remove_from_list); Trigger* for_all_triggers(Triggers_processor func, void *arg); private: bool prepare_record_accessors(TABLE *table); Trigger *change_table_name_in_trignames(const LEX_CSTRING *old_db_name, const LEX_CSTRING *new_db_name, const LEX_CSTRING *new_table_name, Trigger *trigger); bool change_table_name_in_triggers(THD *thd, const LEX_CSTRING *old_db_name, const LEX_CSTRING *new_db_name, const LEX_CSTRING *old_table_name, const LEX_CSTRING *new_table_name); bool check_for_broken_triggers() { if (m_has_unparseable_trigger) { my_message(ER_PARSE_ERROR, m_parse_error_message, MYF(0)); return true; } return false; } public: TABLE *get_subject_table() { return trigger_table; } }; bool add_table_for_trigger(THD *thd, const sp_name *trg_name, bool continue_if_not_exist, TABLE_LIST **table); void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path); bool check_trn_exists(const LEX_CSTRING *trn_path); bool load_table_name_for_trigger(THD *thd, const sp_name *trg_name, const LEX_CSTRING *trn_path, LEX_CSTRING *tbl_name); bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create); bool rm_trigname_file(char *path, const LEX_CSTRING *db, const LEX_CSTRING *trigger_name, myf MyFlags); extern const char * const TRG_EXT; extern const char * const TRN_EXT; #endif /* SQL_TRIGGER_INCLUDED */ sql_crypt.h 0000644 00000002635 15156036123 0006745 0 ustar 00 #ifndef SQL_CRYPT_INCLUDED #define SQL_CRYPT_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_alloc.h" /* Sql_alloc */ #include "my_rnd.h" /* rand_struct */ class SQL_CRYPT :public Sql_alloc { struct my_rnd_struct rand,org_rand; char decode_buff[256],encode_buff[256]; uint shift; public: SQL_CRYPT() = default; SQL_CRYPT(ulong *seed) { init(seed); } ~SQL_CRYPT() = default; void init(ulong *seed); void reinit() { shift=0; rand=org_rand; } void encode(char *str, uint length); void decode(char *str, uint length); }; #endif /* SQL_CRYPT_INCLUDED */ sql_profile.h 0000644 00000017210 15156036123 0007237 0 ustar 00 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SQL_PROFILE_H #define _SQL_PROFILE_H class Item; struct TABLE_LIST; class THD; class ST_FIELD_INFO; typedef struct st_schema_table ST_SCHEMA_TABLE; namespace Show { extern ST_FIELD_INFO query_profile_statistics_info[]; } // namespace Show int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); #define PROFILE_NONE (uint)0 #define PROFILE_CPU (uint)(1<<0) #define PROFILE_MEMORY (uint)(1<<1) #define PROFILE_BLOCK_IO (uint)(1<<2) #define PROFILE_CONTEXT (uint)(1<<3) #define PROFILE_PAGE_FAULTS (uint)(1<<4) #define PROFILE_IPC (uint)(1<<5) #define PROFILE_SWAPS (uint)(1<<6) #define PROFILE_SOURCE (uint)(1<<16) #define PROFILE_ALL (uint)(~0) #if defined(ENABLED_PROFILING) #include "sql_priv.h" #include "unireg.h" #ifdef _WIN32 #include <psapi.h> #endif #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> #endif extern PSI_memory_key key_memory_queue_item; class PROF_MEASUREMENT; class QUERY_PROFILE; class PROFILING; /** Implements a persistent FIFO using server List method names. Not thread-safe. Intended to be used on thread-local data only. */ template <class T> class Queue { private: struct queue_item { T *payload; struct queue_item *next, *previous; }; struct queue_item *first, *last; public: Queue() { elements= 0; first= last= NULL; } void empty() { struct queue_item *i, *after_i; for (i= first; i != NULL; i= after_i) { after_i= i->next; my_free(i); } elements= 0; } ulong elements; /* The count of items in the Queue */ void push_back(T *payload) { struct queue_item *new_item; new_item= (struct queue_item *) my_malloc(key_memory_queue_item, sizeof(struct queue_item), MYF(0)); if (!new_item) return; new_item->payload= payload; if (first == NULL) first= new_item; if (last != NULL) { DBUG_ASSERT(last->next == NULL); last->next= new_item; } new_item->previous= last; new_item->next= NULL; last= new_item; elements++; } T *pop() { struct queue_item *old_item= first; T *ret= NULL; if (first == NULL) { DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue")); return NULL; } ret= old_item->payload; if (first->next != NULL) first->next->previous= NULL; else last= NULL; first= first->next; my_free(old_item); elements--; return ret; } bool is_empty() { DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL))); return (elements == 0); } void *new_iterator() { return first; } void *iterator_next(void *current) { return ((struct queue_item *) current)->next; } T *iterator_value(void *current) { return ((struct queue_item *) current)->payload; } }; /** A single entry in a single profile. */ class PROF_MEASUREMENT { private: friend class QUERY_PROFILE; friend class PROFILING; QUERY_PROFILE *profile; char *status; #ifdef HAVE_GETRUSAGE struct rusage rusage; #elif defined(_WIN32) FILETIME ftKernel, ftUser; IO_COUNTERS io_count; PROCESS_MEMORY_COUNTERS mem_count; #endif char *function; char *file; unsigned int line; ulong m_seq; double time_usecs; char *allocated_status_memory; void set_label(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); void clean_up(); PROF_MEASUREMENT(); PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg); PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); ~PROF_MEASUREMENT(); void collect(); }; /** The full profile for a single query, and includes multiple PROF_MEASUREMENT objects. */ class QUERY_PROFILE { private: friend class PROFILING; PROFILING *profiling; query_id_t profiling_query_id; /* Session-specific id. */ char *query_source; double m_start_time_usecs; double m_end_time_usecs; ulong m_seq_counter; Queue<PROF_MEASUREMENT> entries; QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg); ~QUERY_PROFILE(); void set_query_source(char *query_source_arg, size_t query_length_arg); /* Add a profile status change to the current profile. */ void new_status(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); /* Reset the contents of this profile entry. */ void reset(); /* Show this profile. This is called by PROFILING. */ bool show(uint options); }; /** Profiling state for a single THD; contains multiple QUERY_PROFILE objects. */ class PROFILING { private: friend class PROF_MEASUREMENT; friend class QUERY_PROFILE; /* Not the system query_id, but a counter unique to profiling. */ query_id_t profile_id_counter; THD *thd; bool keeping; bool enabled; QUERY_PROFILE *current; QUERY_PROFILE *last; Queue<QUERY_PROFILE> history; query_id_t next_profile_id() { return(profile_id_counter++); } public: PROFILING(); ~PROFILING(); /** At a point in execution where we know the query source, save the text of it in the query profile. This must be called exactly once per descrete statement. */ void set_query_source(char *query_source_arg, size_t query_length_arg) { if (unlikely(current)) current->set_query_source(query_source_arg, query_length_arg); } /** Prepare to start processing a new query. It is an error to do this if there's a query already in process; nesting is not supported. @param initial_state (optional) name of period before first state change */ void start_new_query(const char *initial_state= "Starting") { DBUG_ASSERT(!current); if (unlikely(enabled)) { QUERY_PROFILE *new_profile= new QUERY_PROFILE(this, initial_state); if (new_profile) current= new_profile; } } void discard_current_query(); void finish_current_query() { if (unlikely(current)) finish_current_query_impl(); } void finish_current_query_impl(); void status_change(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg) { if (unlikely(current)) current->new_status(status_arg, function_arg, file_arg, line_arg); } inline void set_thd(THD *thd_arg) { thd= thd_arg; reset(); } /* SHOW PROFILES */ bool show_profiles(); /* ... from INFORMATION_SCHEMA.PROFILING ... */ int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); void reset(); void restart(); }; # endif /* ENABLED_PROFILING */ #endif /* _SQL_PROFILE_H */ sql_servers.h 0000644 00000003361 15156036123 0007272 0 ustar 00 #ifndef SQL_SERVERS_INCLUDED #define SQL_SERVERS_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "slave.h" // for tables_ok(), rpl_filter class THD; typedef struct st_lex_server_options LEX_SERVER_OPTIONS; typedef struct st_mem_root MEM_ROOT; /* structs */ typedef struct st_federated_server { const char *server_name; long port; size_t server_name_length; const char *db, *scheme, *username, *password, *socket, *owner, *host, *sport; } FOREIGN_SERVER; /* cache handlers */ bool servers_init(bool dont_read_server_table); bool servers_reload(THD *thd); void servers_free(bool end=0); /* insert functions */ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options); /* drop functions */ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options); /* update functions */ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options); /* lookup functions */ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, FOREIGN_SERVER *server_buffer); #endif /* SQL_SERVERS_INCLUDED */ threadpool_winsockets.h 0000644 00000004362 15156036123 0011336 0 ustar 00 /* Copyright (C) 2020 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #include <WinSock2.h> #include <windows.h> struct st_vio; struct win_aiosocket { /** OVERLAPPED is needed by all Windows AIO*/ OVERLAPPED m_overlapped{}; /** Handle to pipe, or socket */ HANDLE m_handle{}; /** Whether the m_handle refers to pipe*/ bool m_is_pipe{}; /* Read buffer handling */ /** Pointer to buffer of size READ_BUFSIZ. Can be NULL.*/ char *m_buf_ptr{}; /** Offset to current buffer position*/ size_t m_buf_off{}; /** Size of valid data in the buffer*/ size_t m_buf_datalen{}; /* Vio handling */ /** Pointer to original vio->vio_read/vio->has_data function */ size_t (*m_orig_vio_read)(st_vio *, unsigned char *, size_t){}; char (*m_orig_vio_has_data)(st_vio *){}; /** Begins asynchronnous reading from socket/pipe. On IO completion, pre-read some bytes into internal buffer */ DWORD begin_read(); /** Update number of bytes returned, and IO error status Should be called right after IO is completed GetQueuedCompletionStatus() , or threadpool IO completion callback would return nbytes and the error. Sets the valid data length in the read buffer. */ void end_read(ULONG nbytes, DWORD err); /** Override VIO routines with ours, accounting for one-shot buffering. */ void init(st_vio *vio); /** Return number of unread bytes.*/ size_t buffer_remaining(); /* Frees the read buffer.*/ ~win_aiosocket(); }; /* Functions related to IO buffers caches.*/ extern void init_win_aio_buffers(unsigned int n_buffers); extern void destroy_win_aio_buffers(); sql_type_int.h 0000644 00000023421 15156036123 0007433 0 ustar 00 /* Copyright (c) 2018, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TYPE_INT_INCLUDED #define SQL_TYPE_INT_INCLUDED #include "my_bit.h" // my_count_bits() class Null_flag { protected: bool m_is_null; public: bool is_null() const { return m_is_null; } Null_flag(bool is_null) :m_is_null(is_null) { } }; class Longlong { protected: longlong m_value; public: longlong value() const { return m_value; } Longlong(longlong nr) :m_value(nr) { } ulonglong abs() { if (m_value == LONGLONG_MIN) // avoid undefined behavior return ((ulonglong) LONGLONG_MAX) + 1; return m_value < 0 ? -m_value : m_value; } }; class Longlong_null: public Longlong, public Null_flag { public: Longlong_null(longlong nr, bool is_null) :Longlong(nr), Null_flag(is_null) { } explicit Longlong_null() :Longlong(0), Null_flag(true) { } explicit Longlong_null(longlong nr) :Longlong(nr), Null_flag(false) { } Longlong_null operator|(const Longlong_null &other) const { if (is_null() || other.is_null()) return Longlong_null(); return Longlong_null(value() | other.value()); } Longlong_null operator&(const Longlong_null &other) const { if (is_null() || other.is_null()) return Longlong_null(); return Longlong_null(value() & other.value()); } Longlong_null operator^(const Longlong_null &other) const { if (is_null() || other.is_null()) return Longlong_null(); return Longlong_null((longlong) (value() ^ other.value())); } Longlong_null operator~() const { if (is_null()) return *this; return Longlong_null((longlong) ~ (ulonglong) value()); } Longlong_null operator<<(const Longlong_null &llshift) const { ulonglong res; uint shift; if (is_null() || llshift.is_null()) return Longlong_null(); shift= (uint) llshift.value(); res= 0; if (shift < sizeof(longlong) * 8) res= ((ulonglong) value()) << shift; return Longlong_null((longlong) res); } Longlong_null operator>>(const Longlong_null &llshift) const { ulonglong res; uint shift; if (is_null() || llshift.is_null()) return Longlong_null(); shift= (uint) llshift.value(); res= 0; if (shift < sizeof(longlong) * 8) res= ((ulonglong) value()) >> shift; return Longlong_null(res); } Longlong_null bit_count() const { if (is_null()) return *this; return Longlong_null((longlong) my_count_bits((ulonglong) value())); } }; class ULonglong { protected: ulonglong m_value; public: ulonglong value() const { return m_value; } explicit ULonglong(ulonglong nr) :m_value(nr) { } static bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2) { return ULONGLONG_MAX - arg1 < arg2; } Longlong_null operator-() const { if (m_value > (ulonglong) LONGLONG_MAX) // Avoid undefined behaviour { return m_value == (ulonglong) LONGLONG_MAX + 1 ? Longlong_null(LONGLONG_MIN, false) : Longlong_null(0, true); } return Longlong_null(-(longlong) m_value, false); } // Convert to Longlong_null with the range check Longlong_null to_longlong_null() const { if (m_value > (ulonglong) LONGLONG_MAX) return Longlong_null(0, true); return Longlong_null((longlong) m_value, false); } }; class ULonglong_null: public ULonglong, public Null_flag { public: ULonglong_null(ulonglong nr, bool is_null) :ULonglong(nr), Null_flag(is_null) { } /* Multiply two ulonglong values. Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 + + (a1 * b0 + a0 * b1) * 2^32 + a0 * b0; We can determine if the above sum overflows the ulonglong range by sequentially checking the following conditions: 1. If both a1 and b1 are non-zero. 2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX. 3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than ULONGLONG_MAX. */ static ULonglong_null ullmul(ulonglong a, ulonglong b) { ulong a1= (ulong)(a >> 32); ulong b1= (ulong)(b >> 32); if (a1 && b1) return ULonglong_null(0, true); ulong a0= (ulong)(0xFFFFFFFFUL & a); ulong b0= (ulong)(0xFFFFFFFFUL & b); ulonglong res1= (ulonglong) a1 * b0 + (ulonglong) a0 * b1; if (res1 > 0xFFFFFFFFUL) return ULonglong_null(0, true); res1= res1 << 32; ulonglong res0= (ulonglong) a0 * b0; if (test_if_sum_overflows_ull(res1, res0)) return ULonglong_null(0, true); return ULonglong_null(res1 + res0, false); } }; // A longlong/ulonglong hybrid. Good to store results of val_int(). class Longlong_hybrid: public Longlong { protected: bool m_unsigned; int cmp_signed(const Longlong_hybrid& other) const { return m_value < other.m_value ? -1 : m_value == other.m_value ? 0 : 1; } int cmp_unsigned(const Longlong_hybrid& other) const { return (ulonglong) m_value < (ulonglong) other.m_value ? -1 : m_value == other.m_value ? 0 : 1; } public: Longlong_hybrid(longlong nr, bool unsigned_flag) :Longlong(nr), m_unsigned(unsigned_flag) { } bool is_unsigned() const { return m_unsigned; } bool is_unsigned_outside_of_signed_range() const { return m_unsigned && ((ulonglong) m_value) > (ulonglong) LONGLONG_MAX; } bool neg() const { return m_value < 0 && !m_unsigned; } ulonglong abs() const { if (m_unsigned) return (ulonglong) m_value; return Longlong(m_value).abs(); } /* Convert to an unsigned number: - Negative numbers are converted to 0. - Positive numbers bigger than upper_bound are converted to upper_bound. - Other numbers are returned as is. */ ulonglong to_ulonglong(ulonglong upper_bound) const { return neg() ? 0 : (ulonglong) m_value > upper_bound ? upper_bound : (ulonglong) m_value; } uint to_uint(uint upper_bound) const { return (uint) to_ulonglong(upper_bound); } Longlong_null val_int_signed() const { if (m_unsigned) return ULonglong((ulonglong) m_value).to_longlong_null(); return Longlong_null(m_value, false); } Longlong_null val_int_unsigned() const { if (!m_unsigned && m_value < 0) return Longlong_null(0, true); return Longlong_null(m_value, false); } /* Return in Item compatible val_int() format: - signed numbers as a straight longlong value - unsigned numbers as a ulonglong value reinterpreted to longlong */ Longlong_null val_int(bool want_unsigned_value) const { return want_unsigned_value ? val_int_unsigned() : val_int_signed(); } int cmp(const Longlong_hybrid& other) const { if (m_unsigned == other.m_unsigned) return m_unsigned ? cmp_unsigned(other) : cmp_signed(other); if (is_unsigned_outside_of_signed_range()) return 1; if (other.is_unsigned_outside_of_signed_range()) return -1; /* The unsigned argument is in the range 0..LONGLONG_MAX. The signed argument is in the range LONGLONG_MIN..LONGLONG_MAX. Safe to compare as signed. */ return cmp_signed(other); } bool operator==(const Longlong_hybrid &nr) const { return cmp(nr) == 0; } bool operator==(ulonglong nr) const { return cmp(Longlong_hybrid((longlong) nr, true)) == 0; } bool operator==(uint nr) const { return cmp(Longlong_hybrid((longlong) nr, true)) == 0; } bool operator==(longlong nr) const { return cmp(Longlong_hybrid(nr, false)) == 0; } bool operator==(int nr) const { return cmp(Longlong_hybrid(nr, false)) == 0; } }; class Longlong_hybrid_null: public Longlong_hybrid, public Null_flag { public: Longlong_hybrid_null(const Longlong_null &nr, bool unsigned_flag) :Longlong_hybrid(nr.value(), unsigned_flag), Null_flag(nr.is_null()) { } }; /* Stores the absolute value of a number, and the sign. Value range: -ULONGLONG_MAX .. +ULONGLONG_MAX. Provides a wider range for negative numbers than Longlong_hybrid does. Usefull to store intermediate results of an expression whose value is further needed to be negated. For example, these methods: - Item_func_mul::int_op() - Item_func_int_div::val_int() - Item_func_mod::int_op() calculate the result of absolute values of the arguments, then optionally negate the result. */ class ULonglong_hybrid: public ULonglong { bool m_neg; public: ULonglong_hybrid(ulonglong value, bool neg) :ULonglong(value), m_neg(neg) { if (m_neg && !m_value) m_neg= false; // convert -0 to +0 } Longlong_null val_int_unsigned() const { return m_neg ? Longlong_null(0, true) : Longlong_null((longlong) m_value, false); } Longlong_null val_int_signed() const { return m_neg ? -ULonglong(m_value) : ULonglong::to_longlong_null(); } /* Return in Item compatible val_int() format: - signed numbers as a straight longlong value - unsigned numbers as a ulonglong value reinterpreted to longlong */ Longlong_null val_int(bool want_unsigned_value) const { return want_unsigned_value ? val_int_unsigned() : val_int_signed(); } }; #endif // SQL_TYPE_INT_INCLUDED keycaches.h 0000644 00000003701 15156036124 0006660 0 ustar 00 #ifndef KEYCACHES_INCLUDED #define KEYCACHES_INCLUDED /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_list.h" #include <keycache.h> #include <rpl_filter.h> extern "C" { typedef int (*process_key_cache_t) (const char *, KEY_CACHE *, void *); } class NAMED_ILINK; class NAMED_ILIST: public I_List<NAMED_ILINK> { public: void delete_elements(void (*free_element)(const char*, void*)); bool delete_element(const char *name, size_t length, void (*free_element)(const char*, void*)); }; /* For key cache */ extern LEX_CSTRING default_base; extern KEY_CACHE zero_key_cache; extern NAMED_ILIST key_caches; KEY_CACHE *create_key_cache(const char *name, size_t length); KEY_CACHE *get_key_cache(const LEX_CSTRING *cache_name); KEY_CACHE *get_or_create_key_cache(const char *name, size_t length); void free_key_cache(const char *name, void *key_cache); bool process_key_caches(process_key_cache_t func, void *param); /* For Rpl_filter */ extern LEX_CSTRING default_rpl_filter_base; extern NAMED_ILIST rpl_filters; Rpl_filter *create_rpl_filter(const char *name, size_t length); Rpl_filter *get_rpl_filter(LEX_CSTRING *filter_name); Rpl_filter *get_or_create_rpl_filter(const char *name, size_t length); void free_all_rpl_filters(void); #endif /* KEYCACHES_INCLUDED */ sql_update.h 0000644 00000007060 15156036124 0007064 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_UPDATE_INCLUDED #define SQL_UPDATE_INCLUDED #include "sql_class.h" /* enum_duplicates */ #include "sql_cmd.h" // Sql_cmd_dml #include "sql_base.h" class Item; struct TABLE_LIST; class THD; typedef class st_select_lex SELECT_LEX; typedef class st_select_lex_unit SELECT_LEX_UNIT; bool check_unique_table(THD *thd, TABLE_LIST *table_list); bool records_are_comparable(const TABLE *table); bool compare_record(const TABLE *table); /** @class Sql_cmd_update - class used for any UPDATE statements This class is derived from Sql_cmd_dml and contains implementations for abstract virtual function of the latter such as precheck() and prepare_inner(). It also overrides the implementation of execute_inner() providing a special handling for single-table update statements that are not converted to multi-table updates. The class provides an object of the Multiupdate_prelocking_strategy class for the virtual function get_dml_prelocking_strategy(). */ class Sql_cmd_update final : public Sql_cmd_dml { public: ha_rows found{0}, updated{0}; Sql_cmd_update(bool multitable_arg) : orig_multitable(multitable_arg), multitable(multitable_arg) {} enum_sql_command sql_command_code() const override { return orig_multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE; } DML_prelocking_strategy *get_dml_prelocking_strategy() override { return &multiupdate_prelocking_strategy; } bool processing_as_multitable_update_prohibited(THD *thd); bool is_multitable() const { return multitable; } void set_as_multitable() { multitable= true; } void get_dml_stat (ha_rows &found, ha_rows &changed) override { found= this->found; changed= this->updated; } protected: /** @brief Perform precheck of table privileges for update statements */ bool precheck(THD *thd) override; /** @brief Perform context analysis for update statements */ bool prepare_inner(THD *thd) override; /** @brief Perform optimization and execution actions needed for updates */ bool execute_inner(THD *thd) override; private: /** @brief Special handling of single-table updates after prepare phase */ bool update_single_table(THD *thd); /* Original value of the 'multitable' flag set by constructor */ const bool orig_multitable; /* True if the statement is a multi-table update or converted to such. For a single-table update this flag is set to true if the statement is supposed to be converted to multi-table update. */ bool multitable; /* The prelocking strategy used when opening the used tables */ Multiupdate_prelocking_strategy multiupdate_prelocking_strategy; public: /* The list of the updating expressions used in the set clause */ List<Item> *update_value_list; }; #endif /* SQL_UPDATE_INCLUDED */ wsrep_priv.h 0000644 00000003142 15156036124 0007120 0 ustar 00 /* Copyright 2010-2023 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ //! @file declares symbols private to wsrep integration layer #ifndef WSREP_PRIV_H #define WSREP_PRIV_H #include "wsrep_api.h" #include "wsrep/server_state.hpp" ssize_t wsrep_sst_prepare (void** msg); wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, const wsrep_buf_t* msg, const wsrep_gtid_t* state_id, const wsrep_buf_t* state, bool bypass); extern wsrep_uuid_t local_uuid; extern wsrep_seqno_t local_seqno; // a helper function bool wsrep_sst_received(THD*, const wsrep_uuid_t&, wsrep_seqno_t, const void*, size_t); void wsrep_notify_status(enum wsrep::server_state::state status, const wsrep::view* view= 0); #endif /* WSREP_PRIV_H */ pfs_metadata_provider.h 0000644 00000003552 15156036124 0011267 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_METADATA_PROVIDER_H #define PFS_METADATA_PROVIDER_H /** @file include/pfs_metadata_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_METADATA_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_METADATA_CALL(M) pfs_ ## M ## _v1 C_MODE_START PSI_metadata_lock* pfs_create_metadata_lock_v1 (void *identity, const MDL_key *key, opaque_mdl_type mdl_type, opaque_mdl_duration mdl_duration, opaque_mdl_status mdl_status, const char *src_file, uint src_line); void pfs_set_metadata_lock_status_v1 (PSI_metadata_lock *lock, opaque_mdl_status mdl_status); void pfs_destroy_metadata_lock_v1(PSI_metadata_lock *lock); struct PSI_metadata_locker* pfs_start_metadata_wait_v1 (struct PSI_metadata_locker_state_v1 *state, struct PSI_metadata_lock *mdl, const char *src_file, uint src_line); void pfs_end_metadata_wait_v1 (struct PSI_metadata_locker *locker, int rc); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_METADATA_INTERFACE */ #endif maria.h 0000644 00000013360 15156036124 0006014 0 ustar 00 /* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file should be included when using maria functions */ #ifndef _maria_h #define _maria_h #include <my_base.h> #include <m_ctype.h> #include "my_compare.h" #include "ft_global.h" #include <myisamchk.h> #ifdef __cplusplus extern "C" { #endif #define MARIA_UNIQUE_HASH_LENGTH 4 extern my_bool maria_delay_key_write; uint maria_max_key_length(void); #define maria_max_key_segments() HA_MAX_KEY_SEG struct st_maria_bit_buff; struct st_maria_page; struct st_maria_s_param; struct st_maria_share; typedef struct st_maria_decode_tree MARIA_DECODE_TREE; typedef struct st_maria_handler MARIA_HA; typedef struct st_maria_key MARIA_KEY; typedef ulonglong MARIA_RECORD_POS; typedef struct st_maria_keydef /* Key definition with open & info */ { struct st_maria_share *share; /* Pointer to base (set in open) */ mysql_rwlock_t root_lock; /* locking of tree */ uint16 keysegs; /* Number of key-segment */ uint16 flag; /* NOSAME, PACK_USED */ uint8 key_alg; /* BTREE, RTREE */ uint8 key_nr; /* key number (auto) */ uint16 block_length; /* Length of keyblock (auto) */ uint16 underflow_block_length; /* When to execute underflow */ uint16 keylength; /* Tot length of keyparts (auto) */ uint16 minlength; /* min length of (packed) key (auto) */ uint16 maxlength; /* max length of (packed) key (auto) */ uint16 max_store_length; /* Size to store key + overhead */ uint32 write_comp_flag; /* compare flag for write key (auto) */ uint32 version; /* For concurrent read/write */ uint32 ftkey_nr; /* full-text index number */ HA_KEYSEG *seg, *end; struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ int (*bin_search)(const MARIA_KEY *key, const struct st_maria_page *page, uint32 comp_flag, uchar **ret_pos, uchar *buff, my_bool *was_last_key); uint (*get_key)(MARIA_KEY *key, uint page_flag, uint nod_flag, uchar **page); uchar *(*skip_key)(MARIA_KEY *key, uint page_flag, uint nod_flag, uchar *page); int (*pack_key)(const MARIA_KEY *key, uint nod_flag, uchar *next_key, uchar *org_key, uchar *prev_key, struct st_maria_s_param *s_temp); void (*store_key)(struct st_maria_keydef *keyinfo, uchar *key_pos, struct st_maria_s_param *s_temp); my_bool (*ck_insert)(MARIA_HA *inf, MARIA_KEY *key); my_bool (*ck_delete)(MARIA_HA *inf, MARIA_KEY *klen); MARIA_KEY *(*make_key)(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, uchar *key, const uchar *record, MARIA_RECORD_POS filepos, ulonglong trid); } MARIA_KEYDEF; typedef struct st_maria_unique_def /* Segment definition of unique */ { uint16 keysegs; /* Number of key-segment */ uint8 key; /* Mapped to which key */ uint8 null_are_equal; HA_KEYSEG *seg, *end; } MARIA_UNIQUEDEF; /* Note that null markers should always be first in a row ! When creating a column, one should only specify: type, length, null_bit and null_pos */ typedef struct st_maria_columndef /* column information */ { enum en_fieldtype type; uint32 offset; /* Offset to position in row */ uint16 length; /* length of field */ uint16 column_nr; /* Intern variable (size of total storage area for the row) */ uint16 fill_length; uint16 null_pos; /* Position for null marker */ uint16 empty_pos; /* Position for empty marker */ uint8 null_bit; /* If column may be NULL */ /* Intern. Set if column should be zero packed (part of empty_bits) */ uint8 empty_bit; #ifndef NOT_PACKED_DATABASES void(*unpack)(struct st_maria_columndef *rec, struct st_maria_bit_buff *buff, uchar *start, uchar *end); enum en_fieldtype base_type; uint space_length_bits, pack_type; MARIA_DECODE_TREE *huff_tree; #endif } MARIA_COLUMNDEF; typedef struct st_maria_create_info { const char *index_file_name, *data_file_name; /* If using symlinks */ ha_rows max_rows; ha_rows reloc_rows; ulonglong auto_increment; ulonglong data_file_length; ulonglong key_file_length; ulong s3_block_size; /* Size of null bitmap at start of row */ uint null_bytes; uint old_options; uint compression_algorithm; enum data_file_type org_data_file_type; uint16 language; my_bool with_auto_increment, transactional, encrypted; } MARIA_CREATE_INFO; extern int maria_create(const char *name, enum data_file_type record_type, uint keys, MARIA_KEYDEF *keydef, uint columns, MARIA_COLUMNDEF *columndef, uint uniques, MARIA_UNIQUEDEF *uniquedef, MARIA_CREATE_INFO *create_info, uint flags); #ifdef __cplusplus } #endif #endif sql_union.h 0000644 00000002054 15156036124 0006730 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_UNION_INCLUDED #define SQL_UNION_INCLUDED class THD; class select_result; struct LEX; typedef class st_select_lex_unit SELECT_LEX_UNIT; bool mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit, ulonglong setup_tables_done_option); #endif /* SQL_UNION_INCLUDED */ spatial.h 0000644 00000054252 15156036124 0006365 0 ustar 00 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _spatial_h #define _spatial_h #include "sql_string.h" /* String, LEX_STRING */ #include <my_compiler.h> #include <json_lib.h> #ifdef HAVE_SPATIAL class Gis_read_stream; #include "gcalc_tools.h" const uint SRID_SIZE= 4; const uint SIZEOF_STORED_DOUBLE= 8; const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2); const uint WKB_HEADER_SIZE= 1+4; const uint32 GET_SIZE_ERROR= ((uint32) -1); struct st_point_2d { double x; double y; }; struct st_linear_ring { uint32 n_points; st_point_2d points; }; /***************************** MBR *******************************/ /* It's ok that a lot of the functions are inline as these are only used once in MySQL */ struct MBR { double xmin, ymin, xmax, ymax; MBR() { xmin= ymin= DBL_MAX; xmax= ymax= -DBL_MAX; } MBR(const double xmin_arg, const double ymin_arg, const double xmax_arg, const double ymax_arg) :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg) {} MBR(const st_point_2d &min, const st_point_2d &max) :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y) {} MBR(const MBR &mbr1, const MBR &mbr2) :xmin(mbr1.xmin), ymin(mbr1.ymin), xmax(mbr1.xmax), ymax(mbr1.ymax) { add_mbr(&mbr2); } inline void add_xy(double x, double y) { /* Not using "else" for proper one point MBR calculation */ if (x < xmin) xmin= x; if (x > xmax) xmax= x; if (y < ymin) ymin= y; if (y > ymax) ymax= y; } void add_xy(const char *px, const char *py) { double x, y; float8get(x, px); float8get(y, py); add_xy(x,y); } void add_mbr(const MBR *mbr) { if (mbr->xmin < xmin) xmin= mbr->xmin; if (mbr->xmax > xmax) xmax= mbr->xmax; if (mbr->ymin < ymin) ymin= mbr->ymin; if (mbr->ymax > ymax) ymax= mbr->ymax; } void buffer(double d) { xmin-= d; ymin-= d; xmax+= d; ymax+= d; } int equals(const MBR *mbr) { /* The following should be safe, even if we compare doubles */ return ((mbr->xmin == xmin) && (mbr->ymin == ymin) && (mbr->xmax == xmax) && (mbr->ymax == ymax)); } int disjoint(const MBR *mbr) { /* The following should be safe, even if we compare doubles */ return ((mbr->xmin > xmax) || (mbr->ymin > ymax) || (mbr->xmax < xmin) || (mbr->ymax < ymin)); } int intersects(const MBR *mbr) { return !disjoint(mbr); } int touches(const MBR *mbr) { /* The following should be safe, even if we compare doubles */ return ((mbr->xmin == xmax || mbr->xmax == xmin) && ((mbr->ymin >= ymin && mbr->ymin <= ymax) || (mbr->ymax >= ymin && mbr->ymax <= ymax))) || ((mbr->ymin == ymax || mbr->ymax == ymin) && ((mbr->xmin >= xmin && mbr->xmin <= xmax) || (mbr->xmax >= xmin && mbr->xmax <= xmax))); } int within(const MBR *mbr); int contains(const MBR *mbr) { /* The following should be safe, even if we compare doubles */ return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) && (mbr->xmax <= xmax) && (mbr->ymax <= ymax)); } bool inner_point(double x, double y) const { /* The following should be safe, even if we compare doubles */ return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y); } /** The dimension maps to an integer as: - Polygon -> 2 - Horizontal or vertical line -> 1 - Point -> 0 - Invalid MBR -> -1 */ int dimension() const { int d= 0; if (xmin > xmax) return -1; else if (xmin < xmax) d++; if (ymin > ymax) return -1; else if (ymin < ymax) d++; return d; } int overlaps(const MBR *mbr) { /* overlaps() requires that some point inside *this is also inside *mbr, and that both geometries and their intersection are of the same dimension. */ int d = dimension(); if (d != mbr->dimension() || d <= 0 || contains(mbr) || within(mbr)) return 0; MBR intersection(MY_MAX(xmin, mbr->xmin), MY_MAX(ymin, mbr->ymin), MY_MIN(xmax, mbr->xmax), MY_MIN(ymax, mbr->ymax)); return (d == intersection.dimension()); } int valid() const { return xmin <= xmax && ymin <= ymax; } }; /***************************** Geometry *******************************/ struct Geometry_buffer; class Geometry { public: Geometry() = default; /* Remove gcc warning */ virtual ~Geometry() = default; /* Remove gcc warning */ static void *operator new(size_t size, void *buffer) { return buffer; } static void operator delete(void *ptr, void *buffer) {} static void operator delete(void *buffer) {} enum wkbType { wkb_point= 1, wkb_linestring= 2, wkb_polygon= 3, wkb_multipoint= 4, wkb_multilinestring= 5, wkb_multipolygon= 6, wkb_geometrycollection= 7, wkb_last=7 }; enum wkbByteOrder { wkb_xdr= 0, /* Big Endian */ wkb_ndr= 1 /* Little Endian */ }; enum geojson_errors { GEOJ_INCORRECT_GEOJSON= 1, GEOJ_TOO_FEW_POINTS= 2, GEOJ_POLYGON_NOT_CLOSED= 3, GEOJ_DIMENSION_NOT_SUPPORTED= 4, GEOJ_EMPTY_COORDINATES= 5, }; /** Callback which creates Geometry objects on top of a given placement. */ typedef Geometry *(*create_geom_t)(char *); class Class_info { public: LEX_STRING m_name; LEX_STRING m_geojson_name; int m_type_id; create_geom_t m_create_func; Class_info(const char *name, const char *gejson_name, int type_id, create_geom_t create_func); }; virtual const Class_info *get_class_info() const=0; virtual uint32 get_data_size() const=0; /* The 'binary_valid' spatial object can be stored in the database and be the correct argument to the spatial functions. It can still be not valid by the OPENGIS standard like having self-intersecting borders. */ bool is_binary_valid() const { uint32 data_size= get_data_size(); return (data_size == GET_SIZE_ERROR) ? false : !no_data(m_data, data_size); } virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0; /* returns the length of the wkb that was read */ virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res)=0; virtual uint init_from_opresult(String *bin, const char *opres, uint res_len) { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; } virtual bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) { return true; } virtual bool get_data_as_wkt(String *txt, const char **end) const=0; virtual bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const=0; virtual bool get_mbr(MBR *mbr, const char **end) const=0; virtual bool dimension(uint32 *dim, const char **end) const=0; virtual int get_x(double *x) const { return -1; } virtual int get_y(double *y) const { return -1; } virtual int geom_length(double *len, const char **end) const { return -1; } virtual int area(double *ar, const char **end) const { return -1;} virtual int is_closed(int *closed) const { return -1; } virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; } virtual int num_points(uint32 *n_points) const { return -1; } virtual int num_geometries(uint32 *num) const { return -1; } virtual int start_point(String *point) const { return -1; } virtual int end_point(String *point) const { return -1; } virtual int exterior_ring(String *ring) const { return -1; } virtual int centroid(String *point) const { return -1; } virtual int point_n(uint32 num, String *result) const { return -1; } virtual int interior_ring_n(uint32 num, String *result) const { return -1; } virtual int geometry_n(uint32 num, String *result) const { return -1; } virtual int store_shapes(Gcalc_shape_transporter *trn) const=0; public: static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id); static Geometry *construct(Geometry_buffer *buffer, const char *data, uint32 data_len); static Geometry *create_from_wkt(Geometry_buffer *buffer, Gis_read_stream *trs, String *wkt, bool init_stream=1); static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb, uint32 len, String *res); static Geometry *create_from_json(Geometry_buffer *buffer, json_engine_t *je, bool er_on_3D, String *res); static Geometry *create_from_opresult(Geometry_buffer *g_buf, String *res, Gcalc_result_receiver &rr); static uint get_key_image_itMBR(LEX_CSTRING &src, uchar *buff, uint length); int as_wkt(String *wkt, const char **end); int as_json(String *wkt, uint max_dec_digits, const char **end); int bbox_as_json(String *wkt); inline void set_data_ptr(const char *data, uint32 data_len) { m_data= data; m_data_end= data + data_len; } inline void shift_wkb_header() { m_data+= WKB_HEADER_SIZE; } const char *get_data_ptr() const { return m_data; } bool envelope(String *result) const; static Class_info *ci_collection[wkb_last+1]; static bool create_point(String *result, double x, double y); protected: static Class_info *find_class(int type_id) { return ((type_id < wkb_point) || (type_id > wkb_last)) ? NULL : ci_collection[type_id]; } static Class_info *find_class(const char *name, size_t len); const char *append_points(String *txt, uint32 n_points, const char *data, uint32 offset) const; bool create_point(String *result, const char *data) const; const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset) const; public: /** Check if there're enough data remaining as requested @arg cur_data pointer to the position in the binary form @arg data_amount number of points expected @return true if not enough data */ inline bool no_data(const char *cur_data, size_t data_amount) const { return (cur_data + data_amount > m_data_end); } /** Check if there're enough points remaining as requested Need to perform the calculation in logical units, since multiplication can overflow the size data type. @arg data pointer to the beginning of the points array @arg expected_points number of points expected @arg extra_point_space extra space for each point element in the array @return true if there are not enough points */ inline bool not_enough_points(const char *data, uint32 expected_points, uint32 extra_point_space = 0) const { return (m_data_end < data || (expected_points > ((m_data_end - data) / (POINT_DATA_SIZE + extra_point_space)))); } protected: const char *m_data; const char *m_data_end; }; /***************************** Point *******************************/ class Gis_point: public Geometry { public: Gis_point() = default; /* Remove gcc warning */ virtual ~Gis_point() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int get_xy(double *x, double *y) const { const char *data= m_data; if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; float8get(*x, data); float8get(*y, data + SIZEOF_STORED_DOUBLE); return 0; } int get_xy_radian(double *x, double *y) const { if (!get_xy(x, y)) { *x= (*x)*M_PI/180; *y= (*y)*M_PI/180; return 0; } return 1; } int get_x(double *x) const override { if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1; float8get(*x, m_data); return 0; } int get_y(double *y) const override { const char *data= m_data; if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; float8get(*y, data + SIZEOF_STORED_DOUBLE); return 0; } int geom_length(double *len, const char **end) const override; int area(double *ar, const char **end) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 0; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; double calculate_haversine(const Geometry *g, const double sphere_radius, int *error); int spherical_distance_multipoints(Geometry *g, const double r, double *result, int *error); }; /***************************** LineString *******************************/ class Gis_line_string: public Geometry { public: Gis_line_string() = default; /* Remove gcc warning */ virtual ~Gis_line_string() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int geom_length(double *len, const char **end) const override; int area(double *ar, const char **end) const override; int is_closed(int *closed) const override; int num_points(uint32 *n_points) const override; int start_point(String *point) const override; int end_point(String *point) const override; int point_n(uint32 n, String *result) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 1; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; }; /***************************** Polygon *******************************/ class Gis_polygon: public Geometry { public: Gis_polygon() = default; /* Remove gcc warning */ virtual ~Gis_polygon() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; uint init_from_opresult(String *bin, const char *opres, uint res_len) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int area(double *ar, const char **end) const override; int exterior_ring(String *result) const override; int num_interior_ring(uint32 *n_int_rings) const override; int interior_ring_n(uint32 num, String *result) const override; int centroid_xy(double *x, double *y) const; int centroid(String *result) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 2; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; }; /***************************** MultiPoint *******************************/ class Gis_multi_point: public Geometry { // Maximum number of points in MultiPoint that can fit into String static const uint32 max_n_points= (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / (WKB_HEADER_SIZE + POINT_DATA_SIZE); public: Gis_multi_point() = default; /* Remove gcc warning */ virtual ~Gis_multi_point() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; uint init_from_opresult(String *bin, const char *opres, uint res_len) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 0; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; int spherical_distance_multipoints(Geometry *g, const double r, double *res, int *error); }; /***************************** MultiLineString *******************************/ class Gis_multi_line_string: public Geometry { public: Gis_multi_line_string() = default; /* Remove gcc warning */ virtual ~Gis_multi_line_string() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; uint init_from_opresult(String *bin, const char *opres, uint res_len) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; int geom_length(double *len, const char **end) const override; int is_closed(int *closed) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 1; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; }; /***************************** MultiPolygon *******************************/ class Gis_multi_polygon: public Geometry { public: Gis_multi_polygon() = default; /* Remove gcc warning */ virtual ~Gis_multi_polygon() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; int area(double *ar, const char **end) const override; int centroid(String *result) const override; bool dimension(uint32 *dim, const char **end) const override { *dim= 2; *end= 0; /* No default end */ return 0; } int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; uint init_from_opresult(String *bin, const char *opres, uint res_len) override; }; /*********************** GeometryCollection *******************************/ class Gis_geometry_collection: public Geometry { public: Gis_geometry_collection() = default; /* Remove gcc warning */ virtual ~Gis_geometry_collection() = default; /* Remove gcc warning */ uint32 get_data_size() const override; bool init_from_wkt(Gis_read_stream *trs, String *wkb) override; uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res) override; uint init_from_opresult(String *bin, const char *opres, uint res_len) override; bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) override; bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; int area(double *ar, const char **end) const override; int geom_length(double *len, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; bool dimension(uint32 *dim, const char **end) const override; int store_shapes(Gcalc_shape_transporter *trn) const override; const Class_info *get_class_info() const override; }; struct Geometry_buffer : public my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {}; #endif /*HAVE_SPATIAL*/ #endif field.h 0000644 00000663433 15156036124 0006022 0 ustar 00 #ifndef FIELD_INCLUDED #define FIELD_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. Copyright (c) 2008, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Because of the function make_new_field() all field classes that have static variables must declare the size_of() member function. */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "mysqld.h" /* system_charset_info */ #include "table.h" /* TABLE */ #include "sql_string.h" /* String */ #include "my_decimal.h" /* my_decimal */ #include "sql_error.h" /* Sql_condition */ #include "compat56.h" #include "sql_type.h" /* Type_std_attributes */ #include "field_comp.h" class Send_field; class Copy_field; class Protocol; class Protocol_text; class Create_field; class Relay_log_info; class Field; class Column_statistics; class Column_statistics_collected; class Item_func; class Item_bool_func; class Item_equal; class Virtual_tmp_table; class Qualified_column_ident; class Table_ident; class SEL_ARG; class RANGE_OPT_PARAM; struct KEY_PART; struct SORT_FIELD; struct SORT_FIELD_ATTR; enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_EXPRESSION, CHECK_FIELD_WARN, CHECK_FIELD_ERROR_FOR_NULL, }; enum ignore_value_reaction { IGNORE_MEANS_ERROR, IGNORE_MEANS_DEFAULT, IGNORE_MEANS_FIELD_VALUE }; ignore_value_reaction find_ignore_reaction(THD *thd); enum enum_conv_type { CONV_TYPE_PRECISE, CONV_TYPE_VARIANT, CONV_TYPE_SUBSET_TO_SUPERSET, CONV_TYPE_SUPERSET_TO_SUBSET, CONV_TYPE_IMPOSSIBLE }; class Conv_param { uint16 m_table_def_flags; public: Conv_param(uint16 table_def_flags) :m_table_def_flags(table_def_flags) { } uint16 table_def_flags() const { return m_table_def_flags; } }; class Conv_source: public Type_handler_hybrid_field_type { uint16 m_metadata; CHARSET_INFO *m_cs; public: Conv_source(const Type_handler *h, uint16 metadata, CHARSET_INFO *cs) :Type_handler_hybrid_field_type(h), m_metadata(metadata), m_cs(cs) { DBUG_ASSERT(cs); } uint16 metadata() const { return m_metadata; } uint mbmaxlen() const { return m_cs->mbmaxlen; } }; /* Common declarations for Field and Item */ class Value_source { protected: // Parameters for warning and note generation class Warn_filter { bool m_want_warning_edom; bool m_want_note_truncated_spaces; public: Warn_filter(bool want_warning_edom, bool want_note_truncated_spaces) : m_want_warning_edom(want_warning_edom), m_want_note_truncated_spaces(want_note_truncated_spaces) { } Warn_filter(const THD *thd); bool want_warning_edom() const { return m_want_warning_edom; } bool want_note_truncated_spaces() const { return m_want_note_truncated_spaces; } }; class Warn_filter_all: public Warn_filter { public: Warn_filter_all() :Warn_filter(true, true) { } }; class Converter_double_to_longlong { protected: bool m_error; longlong m_result; public: Converter_double_to_longlong(double nr, bool unsigned_flag); longlong result() const { return m_result; } bool error() const { return m_error; } void push_warning(THD *thd, double nr, bool unsigned_flag); }; class Converter_double_to_longlong_with_warn: public Converter_double_to_longlong { public: Converter_double_to_longlong_with_warn(THD *thd, double nr, bool unsigned_flag) :Converter_double_to_longlong(nr, unsigned_flag) { if (m_error) push_warning(thd, nr, unsigned_flag); } Converter_double_to_longlong_with_warn(double nr, bool unsigned_flag) :Converter_double_to_longlong(nr, unsigned_flag) { if (m_error) push_warning(current_thd, nr, unsigned_flag); } }; // String-to-number converters class Converter_string_to_number { protected: char *m_end_of_num; // Where the low-level conversion routine stopped int m_error; // The error code returned by the low-level routine bool m_edom; // If EDOM-alike error happened during conversion /** Check string-to-number conversion and produce a warning if - could not convert any digits (EDOM-alike error) - found garbage at the end of the string - found extra spaces at the end (a note) See also Field_num::check_edom_and_truncation() for a similar function. @param thd - the thread that will be used to generate warnings. Can be NULL (which means current_thd will be used if a warning is really necessary). @param type - name of the data type (e.g. "INTEGER", "DECIMAL", "DOUBLE") @param cs - character set of the original string @param str - the original string @param end - the end of the string @param allow_notes - tells if trailing space notes should be displayed or suppressed. Unlike Field_num::check_edom_and_truncation(), this function does not distinguish between EDOM and truncation and reports the same warning for both cases. Perhaps we should eventually print different warnings, to make the explicit CAST work closer to the implicit cast in Field_xxx::store(). */ void check_edom_and_truncation(THD *thd, Warn_filter filter, const char *type, CHARSET_INFO *cs, const char *str, size_t length) const; public: int error() const { return m_error; } }; class Converter_strntod: public Converter_string_to_number { double m_result; public: Converter_strntod(CHARSET_INFO *cs, const char *str, size_t length) { m_result= cs->strntod((char *) str, length, &m_end_of_num, &m_error); // strntod() does not set an error if the input string was empty m_edom= m_error !=0 || str == m_end_of_num; } double result() const { return m_result; } }; class Converter_string_to_longlong: public Converter_string_to_number { protected: longlong m_result; public: longlong result() const { return m_result; } }; class Converter_strntoll: public Converter_string_to_longlong { public: Converter_strntoll(CHARSET_INFO *cs, const char *str, size_t length) { m_result= cs->strntoll(str, length, 10, &m_end_of_num, &m_error); /* All non-zero errors means EDOM error. strntoll() does not set an error if the input string was empty. Check it here. Notice the different with the same condition in Converter_strntoll10. */ m_edom= m_error != 0 || str == m_end_of_num; } }; class Converter_strtoll10: public Converter_string_to_longlong { public: Converter_strtoll10(CHARSET_INFO *cs, const char *str, size_t length) { m_end_of_num= (char *) str + length; m_result= cs->strtoll10(str, &m_end_of_num, &m_error); /* Negative error means "good negative number". Only a positive m_error value means a real error. strtoll10() sets error to MY_ERRNO_EDOM in case of an empty string, so we don't have to additionally catch empty strings here. */ m_edom= m_error > 0; } }; class Converter_str2my_decimal: public Converter_string_to_number { public: Converter_str2my_decimal(uint mask, CHARSET_INFO *cs, const char *str, size_t length, my_decimal *buf) { DBUG_ASSERT(length < UINT_MAX32); m_error= str2my_decimal(mask, str, length, cs, buf, (const char **) &m_end_of_num); // E_DEC_TRUNCATED means a very minor truncation: '1e-100' -> 0 m_edom= m_error && m_error != E_DEC_TRUNCATED; } }; // String-to-number converters with automatic warning generation class Converter_strntod_with_warn: public Converter_strntod { public: Converter_strntod_with_warn(THD *thd, Warn_filter filter, CHARSET_INFO *cs, const char *str, size_t length) :Converter_strntod(cs, str, length) { check_edom_and_truncation(thd, filter, "DOUBLE", cs, str, length); } }; class Converter_strntoll_with_warn: public Converter_strntoll { public: Converter_strntoll_with_warn(THD *thd, Warn_filter filter, CHARSET_INFO *cs, const char *str, size_t length) :Converter_strntoll(cs, str, length) { check_edom_and_truncation(thd, filter, "INTEGER", cs, str, length); } }; class Converter_strtoll10_with_warn: public Converter_strtoll10 { public: Converter_strtoll10_with_warn(THD *thd, Warn_filter filter, CHARSET_INFO *cs, const char *str, size_t length) :Converter_strtoll10(cs, str, length) { check_edom_and_truncation(thd, filter, "INTEGER", cs, str, length); } }; class Converter_str2my_decimal_with_warn: public Converter_str2my_decimal { public: Converter_str2my_decimal_with_warn(THD *thd, Warn_filter filter, uint mask, CHARSET_INFO *cs, const char *str, size_t length, my_decimal *buf) :Converter_str2my_decimal(mask, cs, str, length, buf) { check_edom_and_truncation(thd, filter, "DECIMAL", cs, str, length); } }; // String-to-number conversion methods for the old code compatibility longlong longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr, const char *end) const { /* TODO: Give error if we wanted a signed integer and we got an unsigned one Notice, longlong_from_string_with_check() honors thd->no_error, because it's used to handle queries like this: SELECT COUNT(@@basedir); and is called when Item_func_get_system_var::update_null_value() suppresses warnings and then calls val_int(). The other methods {double|decimal}_from_string_with_check() ignore thd->no_errors, because they are not used for update_null_value() and they always allow all kind of warnings. */ THD *thd= current_thd; return Converter_strtoll10_with_warn(thd, Warn_filter(thd), cs, cptr, end - cptr).result(); } double double_from_string_with_check(CHARSET_INFO *cs, const char *cptr, const char *end) const { return Converter_strntod_with_warn(NULL, Warn_filter_all(), cs, cptr, end - cptr).result(); } my_decimal *decimal_from_string_with_check(my_decimal *decimal_value, CHARSET_INFO *cs, const char *cptr, const char *end) { Converter_str2my_decimal_with_warn(NULL, Warn_filter_all(), E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM, cs, cptr, end - cptr, decimal_value); return decimal_value; } longlong longlong_from_hex_hybrid(const char *str, size_t length) { const char *end= str + length; const char *ptr= end - MY_MIN(length, sizeof(longlong)); ulonglong value= 0; for ( ; ptr != end ; ptr++) value= (value << 8) + (ulonglong) (uchar) *ptr; return (longlong) value; } longlong longlong_from_string_with_check(const String *str) const { return longlong_from_string_with_check(str->charset(), str->ptr(), str->end()); } double double_from_string_with_check(const String *str) const { return double_from_string_with_check(str->charset(), str->ptr(), str->end()); } my_decimal *decimal_from_string_with_check(my_decimal *decimal_value, const String *str) { return decimal_from_string_with_check(decimal_value, str->charset(), str->ptr(), str->end()); } // End of String-to-number conversion methods public: /* The enumeration Subst_constraint is currently used only in implementations of the virtual function subst_argument_checker. */ enum Subst_constraint { ANY_SUBST, /* Any substitution for a field is allowed */ IDENTITY_SUBST /* Substitution for a field is allowed if any two different values of the field type are not equal */ }; /* Item context attributes. Comparison functions pass their attributes to propagate_equal_fields(). For example, for string comparison, the collation of the comparison operation is important inside propagate_equal_fields(). */ class Context { /* Which type of propagation is allowed: - ANY_SUBST (loose equality, according to the collation), or - IDENTITY_SUBST (strict binary equality). */ Subst_constraint m_subst_constraint; /* Comparison type. Important only when ANY_SUBSTS. */ const Type_handler *m_compare_handler; /* Collation of the comparison operation. Important only when ANY_SUBST. */ CHARSET_INFO *m_compare_collation; public: Context(Subst_constraint subst, const Type_handler *h, CHARSET_INFO *cs) :m_subst_constraint(subst), m_compare_handler(h), m_compare_collation(cs) { DBUG_ASSERT(h == h->type_handler_for_comparison()); } Subst_constraint subst_constraint() const { return m_subst_constraint; } const Type_handler *compare_type_handler() const { DBUG_ASSERT(m_subst_constraint == ANY_SUBST); return m_compare_handler; } CHARSET_INFO *compare_collation() const { DBUG_ASSERT(m_subst_constraint == ANY_SUBST); return m_compare_collation; } }; class Context_identity: public Context { // Use this to request only exact value, no invariants. public: Context_identity() :Context(IDENTITY_SUBST, &type_handler_long_blob, &my_charset_bin) { } }; class Context_boolean: public Context { // Use this when an item is [a part of] a boolean expression public: Context_boolean() :Context(ANY_SUBST, &type_handler_slonglong, &my_charset_bin) { } }; }; #define STORAGE_TYPE_MASK 7 #define COLUMN_FORMAT_MASK 7 #define COLUMN_FORMAT_SHIFT 3 /* The length of the header part for each virtual column in the .frm file */ #define FRM_VCOL_OLD_HEADER_SIZE(b) (3 + MY_TEST(b)) #define FRM_VCOL_NEW_BASE_SIZE 16 #define FRM_VCOL_NEW_HEADER_SIZE 6 class Count_distinct_field; struct ha_field_option_struct; struct st_cache_field; int field_conv(Field *to,Field *from); int truncate_double(double *nr, uint field_length, decimal_digits_t dec, bool unsigned_flag, double max_value); inline uint get_enum_pack_length(int elements) { return elements < 256 ? 1 : 2; } inline uint get_set_pack_length(int elements) { uint len= (elements + 7) / 8; return len > 4 ? 8 : len; } /** Tests if field type is temporal and has date part, i.e. represents DATE, DATETIME or TIMESTAMP types in SQL. @param type Field type, as returned by field->type(). @retval true If field type is temporal type with date part. @retval false If field type is not temporal type with date part. */ inline bool is_temporal_type_with_date(enum_field_types type) { switch (type) { case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: return true; case MYSQL_TYPE_DATETIME2: case MYSQL_TYPE_TIMESTAMP2: DBUG_ASSERT(0); // field->real_type() should not get to here. return false; default: return false; } } enum enum_vcol_info_type { VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED, VCOL_DEFAULT, VCOL_CHECK_FIELD, VCOL_CHECK_TABLE, VCOL_USING_HASH, /* Additional types should be added here */ VCOL_GENERATED_VIRTUAL_INDEXED, // this is never written in .frm /* Following is the highest value last */ VCOL_TYPE_NONE = 127 // Since the 0 value is already in use }; static inline const char *vcol_type_name(enum_vcol_info_type type) { switch (type) { case VCOL_GENERATED_VIRTUAL: case VCOL_GENERATED_VIRTUAL_INDEXED: case VCOL_GENERATED_STORED: return "GENERATED ALWAYS AS"; case VCOL_DEFAULT: return "DEFAULT"; case VCOL_CHECK_FIELD: case VCOL_CHECK_TABLE: return "CHECK"; case VCOL_USING_HASH: return "USING HASH"; case VCOL_TYPE_NONE: return "UNTYPED"; } return 0; } /* Flags for Virtual_column_info. If none is set, the expression must be a constant with no side-effects, so it's calculated at CREATE TABLE time, stored in table->record[2], and not recalculated for every statement. */ #define VCOL_FIELD_REF 1 #define VCOL_NON_DETERMINISTIC 2 #define VCOL_SESSION_FUNC 4 /* uses session data, e.g. USER or DAYNAME */ #define VCOL_TIME_FUNC 8 /* safe for SBR */ #define VCOL_AUTO_INC 16 #define VCOL_IMPOSSIBLE 32 #define VCOL_NEXTVAL 64 /* NEXTVAL is not implemented for vcols */ #define VCOL_NOT_STRICTLY_DETERMINISTIC \ (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC) /* Virtual_column_info is the class to contain additional characteristics that is specific for a virtual/computed field such as: - the defining expression that is evaluated to compute the value of the field - whether the field is to be stored in the database - whether the field is used in a partitioning expression */ class Virtual_column_info: public Sql_alloc, private Type_handler_hybrid_field_type { private: enum_vcol_info_type vcol_type; /* Virtual column expression type */ /* The following data is only updated by the parser and read when a Create_field object is created/initialized. */ /* Flag indicating that the field used in a partitioning expression */ bool in_partitioning_expr; public: /* Flag indicating that the field is physically stored in the database */ bool utf8; /* Already in utf8 */ bool automatic_name; bool if_not_exists; Item *expr; Lex_ident name; /* Name of constraint */ /* see VCOL_* (VCOL_FIELD_REF, ...) */ uint flags; Virtual_column_info() :Type_handler_hybrid_field_type(&type_handler_null), vcol_type((enum_vcol_info_type)VCOL_TYPE_NONE), in_partitioning_expr(FALSE), utf8(TRUE), automatic_name(FALSE), expr(NULL), flags(0) { name.str= NULL; name.length= 0; }; Virtual_column_info* clone(THD *thd); ~Virtual_column_info() = default; enum_vcol_info_type get_vcol_type() const { return vcol_type; } void set_vcol_type(enum_vcol_info_type v_type) { vcol_type= v_type; } const char *get_vcol_type_name() const { DBUG_ASSERT(vcol_type != VCOL_TYPE_NONE); return vcol_type_name(vcol_type); } void set_handler(const Type_handler *handler) { /* Calling this function can only be done once. */ DBUG_ASSERT(type_handler() == &type_handler_null); Type_handler_hybrid_field_type::set_handler(handler); } bool is_stored() const { /* after reading the row vcol value is already in the buffer */ return vcol_type == VCOL_GENERATED_STORED; } bool is_in_partitioning_expr() const { return in_partitioning_expr; } void mark_as_in_partitioning_expr() { in_partitioning_expr= TRUE; } bool need_refix() const { return flags & VCOL_SESSION_FUNC; } bool fix_expr(THD *thd); bool fix_session_expr(THD *thd); bool cleanup_session_expr(); bool fix_and_check_expr(THD *thd, TABLE *table); bool check_access(THD *thd); inline bool is_equal(const Virtual_column_info* vcol, bool cmp_names) const; inline void print(String*); }; class Binlog_type_info { public: enum binlog_sign_t { SIGN_SIGNED, SIGN_UNSIGNED, SIGN_NOT_APPLICABLE // for non-numeric types }; /** Retrieve the field metadata for fields. */ CHARSET_INFO *m_cs; // NULL if not relevant TYPELIB *m_enum_typelib; // NULL if not relevant TYPELIB *m_set_typelib; // NULL if not relevant binlog_sign_t m_signedness; uint16 m_metadata; uint8 m_metadata_size; uchar m_type_code; // according to Field::binlog_type() uchar m_geom_type; // Non-geometry fields can return 0 Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size) :m_cs(NULL), m_enum_typelib(NULL), m_set_typelib(NULL), m_signedness(SIGN_NOT_APPLICABLE), m_metadata(metadata), m_metadata_size(metadata_size), m_type_code(type_code), m_geom_type(0) {}; Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size, binlog_sign_t signedness) : m_cs(NULL), m_enum_typelib(NULL), m_set_typelib(NULL), m_signedness(signedness), m_metadata(metadata), m_metadata_size(metadata_size), m_type_code(type_code), m_geom_type(0) {}; Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size, CHARSET_INFO *cs) :m_cs(cs), m_enum_typelib(NULL), m_set_typelib(NULL), m_signedness(SIGN_NOT_APPLICABLE), m_metadata(metadata), m_metadata_size(metadata_size), m_type_code(type_code), m_geom_type(0) {}; Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size, CHARSET_INFO *cs, TYPELIB *t_enum, TYPELIB *t_set) :m_cs(cs), m_enum_typelib(t_enum), m_set_typelib(t_set), m_signedness(SIGN_NOT_APPLICABLE), m_metadata(metadata), m_metadata_size(metadata_size), m_type_code(type_code), m_geom_type(0) {}; Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size, CHARSET_INFO *cs, uchar geom_type) :m_cs(cs), m_enum_typelib(NULL), m_set_typelib(NULL), m_signedness(SIGN_NOT_APPLICABLE), m_metadata(metadata), m_metadata_size(metadata_size), m_type_code(type_code), m_geom_type(geom_type) {}; static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } }; class Binlog_type_info_fixed_string: public Binlog_type_info { public: Binlog_type_info_fixed_string(uchar type_code, uint32 octet_length, CHARSET_INFO *cs); }; class Field: public Value_source { Field(const Item &); /* Prevent use of these */ void operator=(Field &); protected: int save_in_field_str(Field *to) { StringBuffer<MAX_FIELD_WIDTH> result(charset()); val_str(&result); return to->store(result.ptr(), result.length(), charset()); } void error_generated_column_function_is_not_allowed(THD *thd, bool error) const; static void do_field_eq(const Copy_field *copy); static void do_field_int(const Copy_field *copy); static void do_field_real(const Copy_field *copy); static void do_field_string(const Copy_field *copy); static void do_field_date(const Copy_field *copy); static void do_field_temporal(const Copy_field *copy, date_mode_t fuzzydate); static void do_field_datetime(const Copy_field *copy); static void do_field_timestamp(const Copy_field *copy); static void do_field_decimal(const Copy_field *copy); public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void *operator new(size_t size) throw () { DBUG_ASSERT(size < UINT_MAX32); return thd_alloc(current_thd, (uint) size); } static void operator delete(void *ptr_arg, size_t size) { TRASH_FREE(ptr_arg, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { DBUG_ASSERT(0); } bool marked_for_read() const; bool marked_for_write_or_computed() const; /** Used by System Versioning. */ virtual void set_max() { DBUG_ASSERT(0); } virtual bool is_max(const uchar *ptr_arg) const { DBUG_ASSERT(0); return false; } bool is_max() const { return is_max(ptr); } uchar *ptr; // Position to field in record /** Byte where the @c NULL bit is stored inside a record. If this Field is a @c NOT @c NULL field, this member is @c NULL. */ uchar *null_ptr; /* Note that you can use table->in_use as replacement for current_thd member only inside of val_*() and store() members (e.g. you can't use it in cons) */ TABLE *table; // Pointer for table TABLE *orig_table; // Pointer to original table const char * const *table_name; // Pointer to alias in TABLE LEX_CSTRING field_name; LEX_CSTRING comment; /** reference to the list of options or NULL */ engine_option_value *option_list; ha_field_option_struct *option_struct; /* structure with parsed options */ /* Field is part of the following keys */ key_map key_start, part_of_key, part_of_key_not_clustered; /* Bitmap of indexes that have records ordered by col1, ... this_field, ... For example, INDEX (col(prefix_n)) is not present in col.part_of_sortkey. */ key_map part_of_sortkey; /* We use three additional unireg types for TIMESTAMP to overcome limitation of current binary format of .frm file. We'd like to be able to support NOW() as default and on update value for such fields but unable to hold this info anywhere except unireg_check field. This issue will be resolved in more clean way with transition to new text based .frm format. See also comment for Field_timestamp::Field_timestamp(). */ enum __attribute__((packed)) utype { NONE=0, NEXT_NUMBER=15, // AUTO_INCREMENT TIMESTAMP_OLD_FIELD=18, // TIMESTAMP created before 4.1.3 TIMESTAMP_DN_FIELD=21, // TIMESTAMP DEFAULT NOW() TIMESTAMP_UN_FIELD=22, // TIMESTAMP ON UPDATE NOW() TIMESTAMP_DNUN_FIELD=23, // TIMESTAMP DEFAULT NOW() ON UPDATE NOW() TMYSQL_COMPRESSED= 24, // Compatibility with TMySQL }; enum imagetype { itRAW, itMBR}; utype unireg_check; field_visibility_t invisible; uint32 field_length; // Length of field uint32 flags; field_index_t field_index; // field number in fields array uchar null_bit; // Bit used to test null bit /** If true, this field was created in create_tmp_field_from_item from a NULL value. This means that the type of the field is just a guess, and the type may be freely coerced to another type. @see create_tmp_field_from_item @see Item_type_holder::get_real_type */ bool is_created_from_null_item; /* Selectivity of the range condition over this field. When calculating this selectivity a range predicate is taken into account only if: - it is extracted from the WHERE clause - it depends only on the table the field belongs to */ double cond_selectivity; /* The next field in the class of equal fields at the top AND level of the WHERE clause */ Field *next_equal_field; /* This structure is used for statistical data on the column that has been read from the statistical table column_stat */ Column_statistics *read_stats; /* This structure is used for statistical data on the column that is collected by the function collect_statistics_for_table */ Column_statistics_collected *collected_stats; /* This is additional data provided for any computed(virtual) field, default function or check constraint. In particular it includes a pointer to the item by which this field can be computed from other fields. */ Virtual_column_info *vcol_info, *check_constraint, *default_value; Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg); virtual ~Field() = default; virtual Type_numeric_attributes type_numeric_attributes() const { return Type_numeric_attributes(field_length, decimals(), is_unsigned()); } Type_std_attributes type_std_attributes() const { return Type_std_attributes(type_numeric_attributes(), dtcollation()); } bool is_unsigned() const { return flags & UNSIGNED_FLAG; } bool check_assignability_from(const Type_handler *from, bool ignore) const; bool check_assignability_from(const Field *from, bool ignore) const { return check_assignability_from(from->type_handler(), ignore); } /** Convenience definition of a copy function returned by Field::get_copy_func() */ typedef void Copy_func(const Copy_field*); virtual Copy_func *get_copy_func(const Field *from) const= 0; virtual Copy_func *get_copy_func_to(const Field *to) const { return to->get_copy_func(this); } /* Store functions returns 1 on overflow and -1 on fatal error */ virtual int store_field(Field *from) { return from->save_in_field(this); } virtual int save_in_field(Field *to)= 0; /** Check if it is possible just copy the value of the field 'from' to the field 'this', e.g. for INSERT INTO t1 (field1) SELECT field2 FROM t2; @param from - The field to copy from @retval true - it is possible to just copy value of 'from' to 'this' @retval false - conversion is needed */ virtual bool memcpy_field_possible(const Field *from) const= 0; virtual bool make_empty_rec_store_default_value(THD *thd, Item *item); virtual void make_empty_rec_reset() { reset(); } virtual int store(const char *to, size_t length,CHARSET_INFO *cs)=0; /* This is used by engines like CSV and Federated to signal the field that the data is going to be in text (rather than binary) representation, even if cs points to &my_charset_bin. If a Field distinguishes between text and binary formats (e.g. INET6), we cannot call store(str,length,&my_charset_bin), to avoid "field" mis-interpreting the data format as binary. */ virtual int store_text(const char *to, size_t length, CHARSET_INFO *cs) { return store(to, length, cs); } virtual int store_binary(const char *to, size_t length) { return store(to, length, &my_charset_bin); } virtual int store_hex_hybrid(const char *str, size_t length); virtual int store(double nr)=0; virtual int store(longlong nr, bool unsigned_val)=0; virtual int store_decimal(const my_decimal *d)=0; virtual int store_time_dec(const MYSQL_TIME *ltime, uint dec); virtual int store_timestamp_dec(const timeval &ts, uint dec); int store_timestamp(my_time_t timestamp, ulong sec_part) { return store_timestamp_dec(Timeval(timestamp, sec_part), TIME_SECOND_PART_DIGITS); } /** Store a value represented in native format */ virtual int store_native(const Native &value) { DBUG_ASSERT(0); reset(); return 0; } int store_time(const MYSQL_TIME *ltime) { return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); } int store(const char *to, size_t length, CHARSET_INFO *cs, enum_check_fields check_level); int store_text(const char *to, size_t length, CHARSET_INFO *cs, enum_check_fields check_level); int store(const LEX_CSTRING *ls, CHARSET_INFO *cs) { DBUG_ASSERT(ls->length < UINT_MAX32); return store(ls->str, (uint) ls->length, cs); } int store(const LEX_CSTRING &ls, CHARSET_INFO *cs) { DBUG_ASSERT(ls.length < UINT_MAX32); return store(ls.str, (uint) ls.length, cs); } /* @brief Store minimum/maximum value of a column in the statistics table. @param field statistical table field str value buffer */ virtual int store_to_statistical_minmax_field(Field *field, String *str); /* @brief Store minimum/maximum value of a column from the statistical table. @param field statistical table field str value buffer */ virtual int store_from_statistical_minmax_field(Field *field, String *str, MEM_ROOT *mem); #ifdef HAVE_MEM_CHECK /** Mark unused memory in the field as defined. Mainly used to ensure that if we write full field to disk (for example in Count_distinct_field::add(), we don't write unitalized data to disk which would confuse valgrind or MSAN. */ virtual void mark_unused_memory_as_defined() {} #else void mark_unused_memory_as_defined() {} #endif virtual double val_real()=0; virtual longlong val_int()=0; /* Get ulonglong representation. Negative values are truncated to 0. */ virtual ulonglong val_uint(void) { longlong nr= val_int(); return nr < 0 ? 0 : (ulonglong) nr; } virtual bool val_bool()= 0; virtual my_decimal *val_decimal(my_decimal *)=0; inline String *val_str(String *str) { return val_str(str, str); } /* val_str(buf1, buf2) gets two buffers and should use them as follows: if it needs a temp buffer to convert result to string - use buf1 example Field_tiny::val_str() if the value exists as a string already - use buf2 example Field_string::val_str() consequently, buf2 may be created as 'String buf;' - no memory will be allocated for it. buf1 will be allocated to hold a value if it's too small. Using allocated buffer for buf2 may result in an unnecessary free (and later, may be an alloc). This trickery is used to decrease a number of malloc calls. */ virtual String *val_str(String*,String *)=0; virtual bool val_native(Native *to) { DBUG_ASSERT(!is_null()); return to->copy((const char *) ptr, pack_length()); } String *val_int_as_str(String *val_buffer, bool unsigned_flag); /* Copy the Field::val_str() value to MEM_ROOT as a 0x00-teminated string. @param mem_root The memory root to put the value to. @returns {NULL,0} in case of EOM, or the field value otherwise. Only one 0x00 terminating byte is put in the end, even in case of complex character sets like UCS2/UTF16/UTF32. This is OK, since this method is used to read system tables, which are in utf8. */ LEX_STRING val_lex_string_strmake(MEM_ROOT *mem_root); /* Return the field value as a LEX_CSTRING, without padding to full length (MODE_PAD_CHAR_TO_FULL_LENGTH is temporarily suppressed during the call). In case of an empty value, to[0] is assigned to empty_clex_string, memory is not allocated. In case of a non-empty value, the memory is allocated on mem_root. In case of a memory allocation failure, to[0] is assigned to {NULL,0}. @param [IN] mem_root store non-empty values here @param [OUT to return the string here @retval false (success) @retval true (EOM) */ bool val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to); fast_field_copier get_fast_field_copier(const Field *from); /* str_needs_quotes() returns TRUE if the value returned by val_str() needs to be quoted when used in constructing an SQL query. */ virtual bool str_needs_quotes() const { return false; } const Type_handler *type_handler_for_comparison() const { return type_handler()->type_handler_for_comparison(); } Item_result result_type () const { return type_handler()->result_type(); } Item_result cmp_type () const { return type_handler()->cmp_type(); } virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && null_bit == field->null_bit && field->type() == type()); } virtual bool eq_def(const Field *field) const; /* pack_length() returns size (in bytes) used to store field data in memory (i.e. it returns the maximum size of the field in a row of the table, which is located in RAM). */ virtual uint32 pack_length() const { return (uint32) field_length; } /* pack_length_in_rec() returns size (in bytes) used to store field data on storage (i.e. it returns the maximal size of the field in a row of the table, which is located on disk). */ virtual uint32 pack_length_in_rec() const { return pack_length(); } virtual bool compatible_field_size(uint metadata, const Relay_log_info *rli, uint16 mflags, int *order) const; virtual uint pack_length_from_metadata(uint field_metadata) const { DBUG_ENTER("Field::pack_length_from_metadata"); DBUG_RETURN(field_metadata); } virtual uint row_pack_length() const { return 0; } /* data_length() return the "real size" of the data in memory. */ virtual uint32 data_length() { return pack_length(); } virtual uint32 sort_length() const { return pack_length(); } /* sort_suffix_length() return the length bytes needed to store the length for binary charset */ virtual uint32 sort_suffix_length() const { return 0; } /* Get the number bytes occupied by the value in the field. CHAR values are stripped of trailing spaces. Flexible values are stripped of their length. */ virtual uint32 value_length() { uint len; if (!zero_pack() && (type() == MYSQL_TYPE_STRING && (len= pack_length()) >= 4 && len < 256)) { uchar *str, *end; for (str= ptr, end= str+len; end > str && end[-1] == ' '; end--) {} len=(uint) (end-str); return len; } return data_length(); } /** Get the maximum size of the data in packed format. @return Maximum data length of the field when packed using the Field::pack() function. */ virtual uint32 max_data_length() const { return pack_length(); }; virtual int reset() { bzero(ptr,pack_length()); return 0; } virtual void reset_fields() {} const uchar *ptr_in_record(const uchar *record) const { my_ptrdiff_t l_offset= (my_ptrdiff_t) (ptr - table->record[0]); DBUG_ASSERT(l_offset >= 0 && table->s->rec_buff_length - l_offset > 0); return record + l_offset; } virtual int set_default(); bool has_update_default_function() const { return flags & ON_UPDATE_NOW_FLAG; } bool has_default_now_unireg_check() const { return unireg_check == TIMESTAMP_DN_FIELD || unireg_check == TIMESTAMP_DNUN_FIELD; } /* Mark the field as having a value supplied by the client, thus it should not be auto-updated. */ void set_has_explicit_value() { bitmap_set_bit(&table->has_value_set, field_index); } bool has_explicit_value() const { return bitmap_is_set(&table->has_value_set, field_index); } void clear_has_explicit_value() { bitmap_clear_bit(&table->has_value_set, field_index); } virtual my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const { DBUG_ASSERT(0); return 0; } my_time_t get_timestamp(ulong *sec_part) const { return get_timestamp(ptr, sec_part); } virtual bool binary() const { return 1; } virtual bool zero_pack() const { return 1; } virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } virtual uint16 key_part_flag() const { return 0; } virtual uint16 key_part_length_bytes() const { return 0; } virtual uint32 key_length() const { return pack_length(); } virtual const Type_handler *type_handler() const = 0; virtual enum_field_types type() const { return type_handler()->field_type(); } virtual enum_field_types real_type() const { return type_handler()->real_field_type(); } virtual enum_field_types binlog_type() const { /* Binlog stores field->type() as type code by default. For example, it puts MYSQL_TYPE_STRING in case of CHAR, VARCHAR, SET and ENUM, with extra data type details put into metadata. Binlog behaviour slightly differs between various MySQL and MariaDB versions for the temporal data types TIME, DATETIME and TIMESTAMP. MySQL prior to 5.6 uses MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP type codes in binlog and stores no additional metadata. MariaDB-5.3 implements new versions for TIME, DATATIME, TIMESTAMP with fractional second precision, but uses the old format for the types TIME(0), DATETIME(0), TIMESTAMP(0), and it still stores MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP in binlog, with no additional metadata. So row-based replication between temporal data types of different precision is not possible in MariaDB. MySQL-5.6 also implements a new version of TIME, DATETIME, TIMESTAMP which support fractional second precision 0..6, and use the new format even for the types TIME(0), DATETIME(0), TIMESTAMP(0). For these new data types, MySQL-5.6 stores new type codes MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIMESTAMP2 in binlog, with fractional precision 0..6 put into metadata. This makes it in theory possible to do row-based replication between columns of different fractional precision (e.g. from TIME(1) on master to TIME(6) on slave). However, it's not currently fully implemented yet. MySQL-5.6 can only do row-based replication from the old types TIME, DATETIME, TIMESTAMP (represented by MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP type codes in binlog) to the new corresponding types TIME(0), DATETIME(0), TIMESTAMP(0). Note: MariaDB starting from the version 10.0 understands the new MySQL-5.6 type codes MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIMESTAMP2. When started over MySQL-5.6 tables both on master and on slave, MariaDB-10.0 can also do row-based replication from the old types TIME, DATETIME, TIMESTAMP to the new MySQL-5.6 types TIME(0), DATETIME(0), TIMESTAMP(0). Note: perhaps binlog should eventually be modified to store real_type() instead of type() for all column types. */ return type(); } virtual Binlog_type_info binlog_type_info() const { DBUG_ASSERT(Field::type() == binlog_type()); return Binlog_type_info(Field::type(), 0, 0); } virtual en_fieldtype tmp_engine_column_type(bool use_packed_rows) const { return FIELD_NORMAL; } /* Conversion type for from the source to the current field. */ virtual enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const= 0; enum_conv_type rpl_conv_type_from_same_data_type(uint16 metadata, const Relay_log_info *rli, const Conv_param ¶m) const; inline int cmp(const uchar *str) const { return cmp(ptr,str); } /* The following method is used for comparing prefix keys. Currently it's only used in partitioning. */ virtual int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const { return cmp(a, b); } virtual int cmp(const uchar *,const uchar *) const=0; virtual int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const { return memcmp(a,b,pack_length()); } virtual int cmp_offset(my_ptrdiff_t row_offset) { return cmp(ptr,ptr+row_offset); } virtual int cmp_binary_offset(uint row_offset) { return cmp_binary(ptr, ptr+row_offset); }; virtual int key_cmp(const uchar *a,const uchar *b) const { return cmp(a, b); } virtual int key_cmp(const uchar *str, uint length) const { return cmp(ptr,str); } /* Update the value m of the 'min_val' field with the current value v of this field if force_update is set to TRUE or if v < m. Return TRUE if the value has been updated. */ virtual bool update_min(Field *min_val, bool force_update) { bool update_fl= force_update || cmp(ptr, min_val->ptr) < 0; if (update_fl) { min_val->set_notnull(); memcpy(min_val->ptr, ptr, pack_length()); } return update_fl; } /* Update the value m of the 'max_val' field with the current value v of this field if force_update is set to TRUE or if v > m. Return TRUE if the value has been updated. */ virtual bool update_max(Field *max_val, bool force_update) { bool update_fl= force_update || cmp(ptr, max_val->ptr) > 0; if (update_fl) { max_val->set_notnull(); memcpy(max_val->ptr, ptr, pack_length()); } return update_fl; } virtual void store_field_value(uchar *val, uint len) { memcpy(ptr, val, len); } virtual decimal_digits_t decimals() const { return 0; } virtual Information_schema_numeric_attributes information_schema_numeric_attributes() const { return Information_schema_numeric_attributes(); } virtual Information_schema_character_attributes information_schema_character_attributes() const { return Information_schema_character_attributes(); } virtual void update_data_type_statistics(Data_type_statistics *st) const { } /* Caller beware: sql_type can change str.Ptr, so check ptr() to see if it changed if you are using your own buffer in str and restore it with set() if needed */ virtual void sql_type(String &str) const =0; virtual void sql_rpl_type(String *str) const { sql_type(*str); } virtual uint size_of() const =0; // For new field inline bool is_null(my_ptrdiff_t row_offset= 0) const { /* The table may have been marked as containing only NULL values for all fields if it is a NULL-complemented row of an OUTER JOIN or if the query is an implicitly grouped query (has aggregate functions but no GROUP BY clause) with no qualifying rows. If this is the case (in which TABLE::null_row is true), the field is considered to be NULL. Note that if a table->null_row is set then also all null_bits are set for the row. In the case of the 'result_field' for GROUP BY, table->null_row might refer to the *next* row in the table (when the algorithm is: read the next row, see if any of group column values have changed, send the result - grouped - row to the client if yes). So, table->null_row might be wrong, but such a result_field is always nullable (that's defined by original_field->maybe_null()) and we trust its null bit. */ return null_ptr ? null_ptr[row_offset] & null_bit : table->null_row; } inline bool is_real_null(my_ptrdiff_t row_offset= 0) const { return null_ptr && (null_ptr[row_offset] & null_bit); } inline bool is_null_in_record(const uchar *record) const { if (maybe_null_in_table()) return record[(uint) (null_ptr - table->record[0])] & null_bit; return 0; } inline void set_null(my_ptrdiff_t row_offset= 0) { if (null_ptr) null_ptr[row_offset]|= null_bit; } inline void set_notnull(my_ptrdiff_t row_offset= 0) { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; } inline bool maybe_null(void) const { return null_ptr != 0 || table->maybe_null; } // Set to NULL on LOAD DATA or LOAD XML virtual bool load_data_set_null(THD *thd); // Reset when a LOAD DATA file ended unexpectedly virtual bool load_data_set_no_data(THD *thd, bool fixed_format); void load_data_set_value(const char *pos, uint length, CHARSET_INFO *cs); /* @return true if this field is NULL-able (even if temporarily) */ inline bool real_maybe_null() const { return null_ptr != 0; } uint null_offset(const uchar *record) const { return (uint) (null_ptr - record); } /* For a NULL-able field (that can actually store a NULL value in a table) null_ptr points to the "null bitmap" in the table->record[0] header. For NOT NULL fields it is either 0 or points outside table->record[0] into the table->triggers->extra_null_bitmap (so that the field can store a NULL value temporarily, only in memory) */ bool maybe_null_in_table() const { return null_ptr >= table->record[0] && null_ptr <= ptr; } uint null_offset() const { return null_offset(table->record[0]); } void set_null_ptr(uchar *p_null_ptr, uint p_null_bit) { null_ptr= p_null_ptr; null_bit= static_cast<uchar>(p_null_bit); } bool stored_in_db() const { return !vcol_info || vcol_info->is_stored(); } bool check_vcol_sql_mode_dependency(THD *, vcol_init_mode mode) const; virtual sql_mode_t value_depends_on_sql_mode() const { return 0; } virtual sql_mode_t conversion_depends_on_sql_mode(THD *thd, Item *expr) const { return (sql_mode_t) 0; } virtual sql_mode_t can_handle_sql_mode_dependency_on_store() const { return 0; } inline THD *get_thd() const { return likely(table) ? table->in_use : current_thd; } enum { LAST_NULL_BYTE_UNDEF= 0 }; /* Find the position of the last null byte for the field. SYNOPSIS last_null_byte() DESCRIPTION Return a pointer to the last byte of the null bytes where the field conceptually is placed. RETURN VALUE The position of the last null byte relative to the beginning of the record. If the field does not use any bits of the null bytes, the value 0 (LAST_NULL_BYTE_UNDEF) is returned. */ size_t last_null_byte() const { size_t bytes= do_last_null_byte(); DBUG_PRINT("debug", ("last_null_byte() ==> %ld", (long) bytes)); DBUG_ASSERT(bytes <= table->s->null_bytes); return bytes; } /* Create mem-comparable sort key part for a sort key */ void make_sort_key_part(uchar *buff, uint length); /* create a compact sort key which can be compared with a comparison function. They are called packed sort keys */ virtual uint make_packed_sort_key_part(uchar *buff, const SORT_FIELD_ATTR *sort_field); virtual void make_send_field(Send_field *); /* Some implementations actually may write up to 8 bytes regardless of what size was requested. This is due to the minimum value of the system variable max_sort_length. */ virtual void sort_string(uchar *buff,uint length)=0; virtual bool optimize_range(uint idx, uint part) const; virtual void free() {} virtual Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit); Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table, bool maybe_null_arg); Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table) { return create_tmp_field(root, new_table, maybe_null()); } Field *clone(MEM_ROOT *mem_root, TABLE *new_table); Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff); inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; } inline void move_field(uchar *ptr_arg) { ptr=ptr_arg; } inline uchar *record_ptr() // record[0] or wherever the field was moved to { my_ptrdiff_t offset= table->s->field[field_index]->ptr - table->s->default_values; return ptr - offset; } virtual void move_field_offset(my_ptrdiff_t ptr_diff) { ptr=ADD_TO_PTR(ptr,ptr_diff, uchar*); if (null_ptr) { null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*); if (table) { DBUG_ASSERT(null_ptr < ptr); DBUG_ASSERT(ptr - null_ptr <= (int)table->s->rec_buff_length); } } } /* Copy the Field's value to buff. The value will be in table->record[] format. */ void get_image(uchar *buff, uint length, CHARSET_INFO *cs) const { get_image(buff, length, ptr, cs); } virtual void get_image(uchar *buff, uint length, const uchar *ptr_arg, CHARSET_INFO *cs) const { memcpy(buff,ptr_arg,length); } /* Set Field's value to the value in *buf. */ virtual void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) { memcpy(ptr,buff,length); } /* Copy a field part into an output buffer. SYNOPSIS Field::get_key_image() buff [out] output buffer length output buffer size type itMBR for geometry blobs, otherwise itRAW DESCRIPTION This function makes a copy of field part of size equal to or less than "length" parameter value. For fields of string types (CHAR, VARCHAR, TEXT) the rest of buffer is padded by zero byte. NOTES For variable length character fields (i.e. UTF-8) the "length" parameter means a number of output buffer bytes as if all field characters have maximal possible size (mbmaxlen). In the other words, "length" parameter is a number of characters multiplied by field_charset->mbmaxlen. RETURN Number of copied bytes (excluding padded zero bytes -- see above). */ uint get_key_image(uchar *buff, uint length, imagetype type_arg) const { return get_key_image(buff, length, ptr, type_arg); } virtual uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type_arg) const { get_image(buff, length, ptr_arg, &my_charset_bin); return length; } virtual void set_key_image(const uchar *buff,uint length) { set_image(buff,length, &my_charset_bin); } inline longlong val_int_offset(uint row_offset) { ptr+=row_offset; longlong tmp=val_int(); ptr-=row_offset; return tmp; } inline longlong val_int(const uchar *new_ptr) { uchar *old_ptr= ptr; longlong return_value; ptr= (uchar*) new_ptr; return_value= val_int(); ptr= old_ptr; return return_value; } inline String *val_str(String *str, const uchar *new_ptr) { uchar *old_ptr= ptr; ptr= (uchar*) new_ptr; val_str(str); ptr= old_ptr; return str; } virtual bool send(Protocol *protocol); virtual uchar *pack(uchar *to, const uchar *from, uint max_length); /** @overload Field::pack(uchar*, const uchar*, uint, bool) */ uchar *pack(uchar *to, const uchar *from) { DBUG_ENTER("Field::pack"); uchar *result= this->pack(to, from, UINT_MAX); DBUG_RETURN(result); } virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data=0); virtual uint packed_col_length(const uchar *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) { return max_length;} virtual bool is_packable() const { return false; } uint offset(const uchar *record) const { return (uint) (ptr - record); } void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); virtual longlong val_datetime_packed(THD *thd); virtual longlong val_time_packed(THD *thd); virtual const TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset() const= 0; /* returns TRUE if the new charset differs. */ virtual void change_charset(const DTCollation &new_cs) {} virtual const DTCollation &dtcollation() const= 0; virtual CHARSET_INFO *charset_for_protocol(void) const { return binary() ? &my_charset_bin : charset(); } virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } virtual int set_time() { return 1; } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment, ulong current_row=0) const; virtual void print_key_value(String *out, uint32 length); void print_key_part_value(String *out, const uchar *key, uint32 length); void print_key_value_binary(String *out, const uchar* key, uint32 length); void raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, const LEX_CSTRING &op, CHARSET_INFO *op_collation, Item *value, const Data_type_compatibility reason) const; void raise_note_key_become_unused(THD *thd, const String &expr) const; protected: bool set_warning(unsigned int code, int cuted_increment) const { return set_warning(Sql_condition::WARN_LEVEL_WARN, code, cuted_increment); } bool set_note(unsigned int code, int cuted_increment) const { return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment); } void set_datetime_warning(Sql_condition::enum_warning_level, uint code, const ErrConv *str, const char *typestr, int cuted_increment) const; void set_datetime_warning(uint code, const ErrConv *str, const char *typestr, int cuted_increment) const { set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, code, str, typestr, cuted_increment); } void set_warning_truncated_wrong_value(const char *type, const char *value); inline bool check_overflow(int op_result) { return (op_result == E_DEC_OVERFLOW); } int warn_if_overflow(int op_result); Copy_func *get_identical_copy_func() const; bool cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond, const Item *item) const; Data_type_compatibility can_optimize_scalar_range( const RANGE_OPT_PARAM *param, const KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) const; uchar *make_key_image(MEM_ROOT *mem_root, const KEY_PART *key_part); SEL_ARG *get_mm_leaf_int(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value, bool unsigned_field); /* Make a leaf tree for the cases when the value was stored to the field exactly, without any truncation, rounding or adjustments. For example, if we stored an INT value into an INT column, and value->save_in_field_no_warnings() returned 0, we know that the value was stored exactly. */ SEL_ARG *stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param, KEY_PART *key_part, scalar_comparison_op op, Item *value); /* Make a leaf tree for the cases when we don't know if the value was stored to the field without any data loss, or was modified to a smaller or a greater value. Used for the data types whose methods Field::store*() silently adjust the value. This is the most typical case. */ SEL_ARG *stored_field_make_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, scalar_comparison_op op, Item *value); /* Make a leaf tree when an INT value was stored into a field of INT type, and some truncation happened. Tries to adjust the range search condition when possible, e.g. "tinytint < 300" -> "tinyint <= 127". Can also return SEL_ARG_IMPOSSIBLE(), and NULL (not sargable). */ SEL_ARG *stored_field_make_mm_leaf_bounded_int(RANGE_OPT_PARAM *param, KEY_PART *key_part, scalar_comparison_op op, Item *value, bool unsigned_field); /* Make a leaf tree when some truncation happened during value->save_in_field_no_warning(this), and we cannot yet adjust the range search condition for the current combination of the field and the value data types. Returns SEL_ARG_IMPOSSIBLE() for "=" and "<=>". Returns NULL (not sargable) for other comparison operations. */ SEL_ARG *stored_field_make_mm_leaf_truncated(RANGE_OPT_PARAM *prm, scalar_comparison_op, Item *value); public: void set_table_name(String *alias) { table_name= &alias->Ptr; } void init(TABLE *table_arg) { orig_table= table= table_arg; set_table_name(&table_arg->alias); } virtual void init_for_tmp_table(Field *org_field, TABLE *new_table) { init(new_table); orig_table= org_field->orig_table; vcol_info= 0; cond_selectivity= 1.0; next_equal_field= NULL; option_list= NULL; option_struct= NULL; if (org_field->type() == MYSQL_TYPE_VAR_STRING || org_field->type() == MYSQL_TYPE_VARCHAR) new_table->s->db_create_options|= HA_OPTION_PACK_RECORD; } void init_for_make_new_field(TABLE *new_table_arg, TABLE *orig_table_arg) { init(new_table_arg); /* Normally orig_table is different from table only if field was created via ::make_new_field. Here we alter the type of field, so ::make_new_field is not applicable. But we still need to preserve the original field metadata for the client-server protocol. */ orig_table= orig_table_arg; } /* maximum possible display length */ virtual uint32 max_display_length() const= 0; /** Whether a field being created has the samle type. Used by the ALTER TABLE */ virtual bool is_equal(const Column_definition &new_field) const= 0; /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, int *err); /* Maximum number of bytes in character representation. - For string types it is equal to the field capacity, in bytes. - For non-string types it represents the longest possible string length after conversion to string. */ virtual uint32 character_octet_length() const { return field_length; } /* The max. number of characters */ virtual uint32 char_length() const { return field_length / charset()->mbmaxlen; } ha_storage_media field_storage_type() const { return (ha_storage_media) ((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3); } void set_storage_type(ha_storage_media storage_type_arg) { DBUG_ASSERT(field_storage_type() == HA_SM_DEFAULT); flags |= static_cast<uint32>(storage_type_arg) << FIELD_FLAGS_STORAGE_MEDIA; } column_format_type column_format() const { return (column_format_type) ((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3); } void set_column_format(column_format_type column_format_arg) { DBUG_ASSERT(column_format() == COLUMN_FORMAT_TYPE_DEFAULT); flags |= static_cast<uint32>(column_format_arg) << FIELD_FLAGS_COLUMN_FORMAT; } bool vers_sys_field() const { return flags & (VERS_ROW_START | VERS_ROW_END); } bool vers_sys_start() const { return flags & VERS_ROW_START; } bool vers_sys_end() const { return flags & VERS_ROW_END; } bool vers_update_unversioned() const { return flags & VERS_UPDATE_UNVERSIONED_FLAG; } /* Validate a non-null field value stored in the given record according to the current thread settings, e.g. sql_mode. @param thd - the thread @param record - the record to check in */ virtual bool validate_value_in_record(THD *thd, const uchar *record) const { return false; } bool validate_value_in_record_with_warn(THD *thd, const uchar *record); key_map get_possible_keys(); /* Hash value */ void hash(Hasher *hasher) { if (is_null()) hasher->add_null(); else hash_not_null(hasher); } virtual void hash_not_null(Hasher *hasher); /** Get the upper limit of the MySQL integral and floating-point type. @return maximum allowed value for the field */ virtual ulonglong get_max_int_value() const { DBUG_ASSERT(false); return 0ULL; } /** Checks whether a string field is part of write_set. @return FALSE - If field is not char/varchar/.... - If field is char/varchar/.. and is not part of write set. TRUE - If field is char/varchar/.. and is part of write set. */ virtual bool is_varchar_and_in_write_set() const { return FALSE; } /* Check whether the field can be used as a join attribute in hash join */ virtual bool hash_join_is_possible() { return TRUE; } virtual bool eq_cmp_as_binary() { return TRUE; } /* Position of the field value within the interval of [min, max] */ virtual double pos_in_interval(Field *min, Field *max) { return (double) 0.5; } virtual bool pos_through_val_str() { return false;} /* Check if comparison between the field and an item unambiguously identifies a distinct field value. Example1: SELECT * FROM t1 WHERE int_column=10; This example returns distinct integer value of 10. Example2: SELECT * FROM t1 WHERE varchar_column=DATE'2001-01-01' This example returns non-distinct values. Comparison as DATE will return '2001-01-01' and '2001-01-01x', but these two values are not equal to each other as VARCHARs. See also the function with the same name in sql_select.cc. */ virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item) const; virtual bool can_be_substituted_to_equal_item(const Context &ctx, const Item_equal *item); virtual Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) { return const_item; } virtual Data_type_compatibility can_optimize_keypart_ref( const Item_bool_func *cond, const Item *item) const; virtual Data_type_compatibility can_optimize_hash_join( const Item_bool_func *cond, const Item *item) const { return can_optimize_keypart_ref(cond, item); } virtual Data_type_compatibility can_optimize_group_min_max( const Item_bool_func *cond, const Item *const_item) const; /** Test if Field can use range optimizer for a standard comparison operation: <=, <, =, <=>, >, >= Note, this method does not cover spatial operations. */ virtual Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const; virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value)= 0; Data_type_compatibility can_optimize_outer_join_table_elimination( const Item_bool_func *cond, const Item *item) const { // Exactly the same rules with REF access return can_optimize_keypart_ref(cond, item); } bool save_in_field_default_value(bool view_eror_processing); bool save_in_field_ignore_value(bool view_error_processing); /* Mark field in read map. Updates also virtual fields */ void register_field_in_read_map(); virtual Compression_method *compression_method() const { return 0; } virtual Virtual_tmp_table **virtual_tmp_table_addr() { return NULL; } virtual bool sp_prepare_and_store_item(THD *thd, Item **value); friend int cre_myisam(char * name, TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; friend class Item_avg_field; friend class Item_std_field; friend class Item_sum_num; friend class Item_sum_sum; friend class Item_sum_count; friend class Item_sum_avg; friend class Item_sum_std; friend class Item_sum_min; friend class Item_sum_max; friend class Item_func_group_concat; private: /* Primitive for implementing last_null_byte(). SYNOPSIS do_last_null_byte() DESCRIPTION Primitive for the implementation of the last_null_byte() function. This represents the inheritance interface and can be overridden by subclasses. */ virtual size_t do_last_null_byte() const; protected: uchar *pack_int(uchar *to, const uchar *from, size_t size) { memcpy(to, from, size); return to + size; } const uchar *unpack_int(uchar* to, const uchar *from, const uchar *from_end, size_t size) { if (from + size > from_end) return 0; memcpy(to, from, size); return from + size; } uchar *pack_int16(uchar *to, const uchar *from) { return pack_int(to, from, 2); } const uchar *unpack_int16(uchar* to, const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 2); } uchar *pack_int24(uchar *to, const uchar *from) { return pack_int(to, from, 3); } const uchar *unpack_int24(uchar* to, const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 3); } uchar *pack_int32(uchar *to, const uchar *from) { return pack_int(to, from, 4); } const uchar *unpack_int32(uchar* to, const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 4); } uchar *pack_int64(uchar* to, const uchar *from) { return pack_int(to, from, 8); } const uchar *unpack_int64(uchar* to, const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 8); } double pos_in_interval_val_real(Field *min, Field *max); double pos_in_interval_val_str(Field *min, Field *max, uint data_offset); }; class Field_num :public Field { protected: int check_edom_and_important_data_truncation(const char *type, bool edom, CHARSET_INFO *cs, const char *str, size_t length, const char *end_of_num); int check_edom_and_truncation(const char *type, bool edom, CHARSET_INFO *cs, const char *str, size_t length, const char *end_of_num); int check_int(CHARSET_INFO *cs, const char *str, size_t length, const char *int_end, int error) { return check_edom_and_truncation("integer", error == MY_ERRNO_EDOM || str == int_end, cs, str, length, int_end); } bool get_int(CHARSET_INFO *cs, const char *from, size_t len, longlong *rnd, ulonglong unsigned_max, longlong signed_min, longlong signed_max); void prepend_zeros(String *value) const; Item *get_equal_zerofill_const_item(THD *thd, const Context &ctx, Item *const_item); Binlog_type_info::binlog_sign_t binlog_signedness() const { return (flags & UNSIGNED_FLAG) ? Binlog_type_info::SIGN_UNSIGNED : Binlog_type_info::SIGN_SIGNED; } bool send_numeric_zerofill_str(Protocol_text *protocol, protocol_send_type_t send_type); public: const decimal_digits_t dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg); CHARSET_INFO *charset() const override { return DTCollation_numeric::singleton().collation; } const DTCollation &dtcollation() const override { return DTCollation_numeric::singleton(); } sql_mode_t can_handle_sql_mode_dependency_on_store() const override; Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override { return (flags & ZEROFILL_FLAG) ? get_equal_zerofill_const_item(thd, ctx, const_item) : const_item; } void add_zerofill_and_unsigned(String &res) const; friend class Create_field; void make_send_field(Send_field *) override; decimal_digits_t decimals() const override { return dec; } uint size_of() const override { return sizeof(*this); } bool eq_def(const Field *field) const override; Copy_func *get_copy_func(const Field *from) const override { if (unsigned_flag && from->cmp_type() == DECIMAL_RESULT) return do_field_decimal; return do_field_int; } int save_in_field(Field *to) override { return to->store(val_int(), MY_TEST(flags & UNSIGNED_FLAG)); } bool is_equal(const Column_definition &new_field) const override; uint row_pack_length() const override { return pack_length(); } uint32 pack_length_from_metadata(uint field_metadata) const override { uint32 length= pack_length(); DBUG_PRINT("result", ("pack_length_from_metadata(%d): %u", field_metadata, length)); return length; } double pos_in_interval(Field *min, Field *max) override { return pos_in_interval_val_real(min, max); } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override; Binlog_type_info binlog_type_info() const override { DBUG_ASSERT(Field_num::type() == binlog_type()); return Binlog_type_info(Field_num::type(), 0, 0, binlog_signedness()); } }; class Field_str :public Field { protected: DTCollation m_collation; // A short alias for m_collation.collation with non-virtual linkage const CHARSET_INFO *field_charset() const { return m_collation.collation; } uint mbmaxlen() const { return m_collation.collation->mbmaxlen; } public: bool can_be_substituted_to_equal_item(const Context &ctx, const Item_equal *item_equal) override; Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation); decimal_digits_t decimals() const override { return is_created_from_null_item ? 0 : DECIMAL_NOT_SPECIFIED; } int save_in_field(Field *to) override { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const override { return real_type() == from->real_type() && pack_length() == from->pack_length() && charset() == from->charset(); } int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; int store(const char *to,size_t length,CHARSET_INFO *cs) override=0; int store_hex_hybrid(const char *str, size_t length) override { return store(str, length, &my_charset_bin); } CHARSET_INFO *charset() const override { return m_collation.collation; } const DTCollation &dtcollation() const override { return m_collation; } void change_charset(const DTCollation &new_cs) override; bool binary() const override { return field_charset() == &my_charset_bin; } uint32 max_display_length() const override { return field_length; } uint32 character_octet_length() const override { return field_length; } uint32 char_length() const override { return field_length / mbmaxlen(); } Information_schema_character_attributes information_schema_character_attributes() const override { return Information_schema_character_attributes(max_display_length(), char_length()); } friend class Create_field; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override { return val_real() != 0e0; } bool str_needs_quotes() const override { return true; } bool eq_cmp_as_binary() override { return MY_TEST(flags & BINARY_FLAG); } virtual uint length_size() const { return 0; } double pos_in_interval(Field *min, Field *max) override { return pos_in_interval_val_str(min, max, length_size()); } bool pos_through_val_str() override {return true;} bool test_if_equality_guarantees_uniqueness(const Item *const_item) const override; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override; Binlog_type_info binlog_type_info() const override { DBUG_ASSERT(Field_str::type() == binlog_type()); return Binlog_type_info(Field_str::type(), 0, 0, charset()); } }; /* base class for Field_string, Field_varstring and Field_blob */ class Field_longstr :public Field_str { protected: int report_if_important_data(const char *ptr, const char *end, bool count_spaces); bool check_string_copy_error(const String_copier *copier, const char *end, CHARSET_INFO *cs); int check_conversion_status(const String_copier *copier, const char *end, CHARSET_INFO *cs, bool count_spaces) { if (check_string_copy_error(copier, end, cs)) return 2; return report_if_important_data(copier->source_end_pos(), end, count_spaces); } int well_formed_copy_with_check(char *to, size_t to_length, CHARSET_INFO *from_cs, const char *from, size_t from_length, size_t nchars, bool count_spaces, uint *copy_length) { String_copier copier; *copy_length= copier.well_formed_copy(field_charset(), to, to_length, from_cs, from, from_length, nchars); return check_conversion_status(&copier, from + from_length, from_cs, count_spaces); } Data_type_compatibility cmp_to_string_with_same_collation( const Item_bool_func *cond, const Item *item) const; Data_type_compatibility cmp_to_string_with_stricter_collation( const Item_bool_func *cond, const Item *item) const; int compress(char *to, uint to_length, const char *from, uint length, uint max_length, uint *out_length, CHARSET_INFO *cs, size_t nchars); String *uncompress(String *val_buffer, String *val_ptr, const uchar *from, uint from_length) const; public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, collation) {} enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; int store_decimal(const my_decimal *d) override; uint32 max_data_length() const override; void make_send_field(Send_field *) override; bool send(Protocol *protocol) override; bool is_varchar_and_in_write_set() const override { DBUG_ASSERT(table && table->write_set); return bitmap_is_set(table->write_set, field_index); } bool match_collation_to_optimize_range() const { return true; } Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const override; Data_type_compatibility can_optimize_hash_join(const Item_bool_func *cond, const Item *item) const override; Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const override; Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const override; bool is_packable() const override { return true; } uint make_packed_sort_key_part(uchar *buff, const SORT_FIELD_ATTR *sort_field)override; uchar* pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field); }; /* base class for float and double and decimal (old one) */ class Field_real :public Field_num { protected: double get_double(const char *str, size_t length, CHARSET_INFO *cs, int *err); public: bool not_fixed; Field_real(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg), not_fixed(dec_arg >= FLOATING_POINT_DECIMALS) {} Copy_func *get_copy_func(const Field *from) const override { return do_field_real; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Information_schema_numeric_attributes information_schema_numeric_attributes() const override { return dec == DECIMAL_NOT_SPECIFIED ? Information_schema_numeric_attributes(field_length) : Information_schema_numeric_attributes(field_length, dec); } void sql_type(String &str) const override; int save_in_field(Field *to) override { return to->store(val_real()); } bool memcpy_field_possible(const Field *from) const override { /* Cannot do memcpy from a longer field to a shorter field, e.g. a DOUBLE(53,10) into a DOUBLE(10,10). But it should be OK the other way around. */ return real_type() == from->real_type() && pack_length() == from->pack_length() && is_unsigned() <= from->is_unsigned() && decimals() == from->decimals() && field_length >= from->field_length; } int store_decimal(const my_decimal *dec) override { return store(dec->to_double()); } int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override { return val_real() != 0e0; } uint32 max_display_length() const override { return field_length; } uint size_of() const override { return sizeof *this; } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override; }; class Field_decimal final :public Field_real { public: Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg, bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg) {} Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; const Type_handler *type_handler() const override { return &type_handler_olddecimal; } enum ha_base_keytype key_type() const override { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } Information_schema_numeric_attributes information_schema_numeric_attributes() const override { uint tmp= dec ? 2 : 1; // The sign and the decimal point return Information_schema_numeric_attributes(field_length - tmp, dec); } Copy_func *get_copy_func(const Field *from) const override { return eq_def(from) ? get_identical_copy_func() : do_field_string; } int reset() override; int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; void overflow(bool negative); bool zero_pack() const override { return false; } void sql_type(String &str) const override; uchar *pack(uchar* to, const uchar *from, uint max_length) override { return Field::pack(to, from, max_length); } }; /* New decimal/numeric field which use fixed point arithmetic */ class Field_new_decimal final :public Field_num { public: /* The maximum number of decimal digits can be stored */ decimal_digits_t precision; uint32 bin_size; /* Constructors take max_length of the field as a parameter - not the precision as the number of decimal digits allowed. So for example we need to count length from precision handling CREATE TABLE ( DECIMAL(x,y)) */ Field_new_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg); const Type_handler *type_handler() const override { return &type_handler_newdecimal; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } Copy_func *get_copy_func(const Field *from) const override { // if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why? // return do_field_int; return do_field_decimal; } int save_in_field(Field *to) override { my_decimal tmp(ptr, precision, dec); return to->store_decimal(&tmp); } bool memcpy_field_possible(const Field *from) const override { return real_type() == from->real_type() && pack_length() == from->pack_length() && is_unsigned() <= from->is_unsigned() && decimals() == from->decimals() && field_length == from->field_length; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; int reset() override; bool store_value(const my_decimal *decimal_value); bool store_value(const my_decimal *decimal_value, int *native_error); void set_value_on_overflow(my_decimal *decimal_value, bool sign); int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store_decimal(const my_decimal *) override; double val_real() override { return my_decimal(ptr, precision, dec).to_double(); } longlong val_int() override { return my_decimal(ptr, precision, dec).to_longlong(unsigned_flag); } ulonglong val_uint() override { return (ulonglong) my_decimal(ptr, precision, dec).to_longlong(true); } my_decimal *val_decimal(my_decimal *) override; String *val_str(String *val_buffer, String *) override { uint fixed_precision= zerofill ? precision : 0; return my_decimal(ptr, precision, dec). to_string(val_buffer, fixed_precision, dec, '0'); } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { my_decimal nr(ptr, precision, dec); return decimal_to_datetime_with_warn(get_thd(), &nr, ltime, fuzzydate, table->s, field_name.str); } bool val_bool() override { return my_decimal(ptr, precision, dec).to_bool(); } int cmp(const uchar *, const uchar *) const override; void sort_string(uchar *buff, uint length) override; bool zero_pack() const override { return false; } void sql_type(String &str) const override; uint32 max_display_length() const override { return field_length; } Information_schema_numeric_attributes information_schema_numeric_attributes() const override { return Information_schema_numeric_attributes(precision, dec); } uint size_of() const override { return sizeof *this; } uint32 pack_length() const override { return bin_size; } uint pack_length_from_metadata(uint field_metadata) const override; uint row_pack_length() const override { return pack_length(); } bool compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; bool is_equal(const Column_definition &new_field) const override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override; Binlog_type_info binlog_type_info() const override; }; class Field_int :public Field_num { protected: String *val_str_from_long(String *val_buffer, uint max_char_length, int radix, long nr); public: Field_int(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg, unsigned_arg) {} enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; bool memcpy_field_possible(const Field *from) const override { return real_type() == from->real_type() && pack_length() == from->pack_length() && is_unsigned() == from->is_unsigned(); } int store_decimal(const my_decimal *) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override { return val_int() != 0; } ulonglong val_uint() override { longlong nr= val_int(); return nr < 0 && !unsigned_flag ? 0 : (ulonglong) nr; } int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; virtual const Type_limits_int *type_limits_int() const= 0; uint32 max_display_length() const override { return type_limits_int()->char_length(); } Type_numeric_attributes type_numeric_attributes() const override { /* For integer data types, the user-specified length does not constrain the supported range, so e.g. a column of the INT(1) data type supports the full integer range anyway. Choose the maximum from the user-specified length and the maximum possible length determined by the data type capacity: INT(1) -> 11 INT(10) -> 11 INT(40) -> 40 */ uint32 length1= max_display_length(); uint32 length2= field_length; return Type_numeric_attributes(MY_MAX(length1, length2), decimals(), is_unsigned()); } Information_schema_numeric_attributes information_schema_numeric_attributes() const override { uint32 prec= type_limits_int()->precision(); return Information_schema_numeric_attributes(prec, 0); } void sql_type(String &str) const override; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override { return get_mm_leaf_int(param, key_part, cond, op, value, unsigned_flag); } }; class Field_tiny :public Field_int { const Type_handler_general_purpose_int *type_handler_priv() const { if (is_unsigned()) return &type_handler_utiny; return &type_handler_stiny; } public: Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg) {} const Type_handler *type_handler() const override { return type_handler_priv(); } enum ha_base_keytype key_type() const override { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { ptr[0]=0; return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 1; } const Type_limits_int *type_limits_int() const override { return type_handler_priv()->type_limits_int(); } uchar *pack(uchar* to, const uchar *from, uint max_length) override { *to= *from; return to + 1; } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override { if (from == from_end) return 0; *to= *from; return from + 1; } ulonglong get_max_int_value() const override { return unsigned_flag ? 0xFFULL : 0x7FULL; } }; class Field_short final :public Field_int { const Type_handler_general_purpose_int *type_handler_priv() const { if (is_unsigned()) return &type_handler_ushort; return &type_handler_sshort; } public: Field_short(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg) {} Field_short(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, bool unsigned_arg) :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, 0, unsigned_arg) {} const Type_handler *type_handler() const override { return type_handler_priv(); } enum ha_base_keytype key_type() const override { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;} int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { ptr[0]=ptr[1]=0; return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 2; } const Type_limits_int *type_limits_int() const override { return type_handler_priv()->type_limits_int(); } uchar *pack(uchar* to, const uchar *from, uint) override { return pack_int16(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int16(to, from, from_end); } ulonglong get_max_int_value() const override { return unsigned_flag ? 0xFFFFULL : 0x7FFFULL; } }; class Field_medium final :public Field_int { const Type_handler_general_purpose_int *type_handler_priv() const { if (is_unsigned()) return &type_handler_uint24; return &type_handler_sint24; } public: Field_medium(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg) {} const Type_handler *type_handler() const override { return type_handler_priv(); } enum ha_base_keytype key_type() const override { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } const Type_limits_int *type_limits_int() const override { return type_handler_priv()->type_limits_int(); } uchar *pack(uchar* to, const uchar *from, uint max_length) override { return Field::pack(to, from, max_length); } ulonglong get_max_int_value() const override { return unsigned_flag ? 0xFFFFFFULL : 0x7FFFFFULL; } }; class Field_long final :public Field_int { const Type_handler_general_purpose_int *type_handler_priv() const { if (is_unsigned()) return &type_handler_ulong; return &type_handler_slong; } public: Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg) {} Field_long(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, bool unsigned_arg) :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, 0, unsigned_arg) {} const Type_handler *type_handler() const override { return type_handler_priv(); } enum ha_base_keytype key_type() const override { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real() override; longlong val_int() override; bool send(Protocol *protocol) override; String *val_str(String *, String *) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } const Type_limits_int *type_limits_int() const override { return type_handler_priv()->type_limits_int(); } uchar *pack(uchar* to, const uchar *from, uint) override { return pack_int32(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int32(to, from, from_end); } ulonglong get_max_int_value() const override { return unsigned_flag ? 0xFFFFFFFFULL : 0x7FFFFFFFULL; } }; class Field_longlong :public Field_int { const Type_handler_general_purpose_int *type_handler_priv() const { if (is_unsigned()) return &type_handler_ulonglong; return &type_handler_slonglong; } public: Field_longlong(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg) {} Field_longlong(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, bool unsigned_arg) :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, 0, unsigned_arg) {} const Type_handler *type_handler() const override { return type_handler_priv(); } enum ha_base_keytype key_type() const override { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } const Type_limits_int *type_limits_int() const override { return type_handler_priv()->type_limits_int(); } uchar *pack(uchar* to, const uchar *from, uint) override { return pack_int64(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int64(to, from, from_end); } void set_max() override; bool is_max(const uchar *ptr_arg) const override; ulonglong get_max_int_value() const override { return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL; } }; class Field_vers_trx_id :public Field_longlong { MYSQL_TIME cache; ulonglong cached; public: Field_vers_trx_id(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) : Field_longlong(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, zero_arg, unsigned_arg), cached(0) {} const Type_handler *type_handler() const override { return &type_handler_vers_trx_id; } uint size_of() const override { return sizeof *this; } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate, ulonglong trx_id); bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date(ltime, fuzzydate, (ulonglong) val_int()); } bool test_if_equality_guarantees_uniqueness(const Item *item) const override; Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *, const Item *) const override { return Data_type_compatibility::OK; } Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *, const Item *) const override { return Data_type_compatibility::OK; } Data_type_compatibility can_optimize_range(const Item_bool_func *, const Item *, bool is_eq_func) const override { return Data_type_compatibility::OK; } /* cmp_type() cannot be TIME_RESULT, because we want to compare this field against integers. But in all other cases we treat it as TIME_RESULT! */ }; static inline decimal_digits_t fix_dec_arg(decimal_digits_t dec_arg) { return dec_arg >= FLOATING_POINT_DECIMALS ? DECIMAL_NOT_SPECIFIED : dec_arg; } class Field_float final :public Field_real { public: Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, fix_dec_arg(dec_arg), zero_arg, unsigned_arg) { } Field_float(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) { } const Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int reset() override { bzero(ptr,sizeof(float)); return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff, uint length) override; uint32 pack_length() const override { return sizeof(float); } uint row_pack_length() const override { return pack_length(); } ulonglong get_max_int_value() const override { /* We use the maximum as per IEEE754-2008 standard, 2^24 */ return 0x1000000ULL; } Binlog_type_info binlog_type_info() const override; }; class Field_double :public Field_real { longlong val_int_from_real(bool want_unsigned_result); public: Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, fix_dec_arg(dec_arg), zero_arg, unsigned_arg) { } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) { } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg, bool not_fixed_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) { not_fixed= not_fixed_arg; } void init_for_tmp_table(Field *org_field, TABLE *new_table) override { Field::init_for_tmp_table(org_field, new_table); not_fixed= true; } const Type_handler *type_handler() const override { return &type_handler_double; } enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_DOUBLE; } int store(const char *to,size_t length,CHARSET_INFO *charset) override final; int store(double nr) override final; int store(longlong nr, bool unsigned_val) override final; int reset() override final { bzero(ptr,sizeof(double)); return 0; } double val_real() override final; longlong val_int() override final { return val_int_from_real(false); } ulonglong val_uint() override final { return (ulonglong) val_int_from_real(true); } String *val_str(String *, String *) override final; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override final; void sort_string(uchar *buff, uint length) override final; uint32 pack_length() const override final { return sizeof(double); } uint row_pack_length() const override final { return pack_length(); } ulonglong get_max_int_value() const override final { /* We use the maximum as per IEEE754-2008 standard, 2^53 */ return 0x20000000000000ULL; } Binlog_type_info binlog_type_info() const override final; }; /* Everything saved in this will disappear. It will always return NULL */ class Field_null :public Field_str { static uchar null[1]; public: Field_null(uchar *ptr_arg, uint32 len_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation) :Field_str(ptr_arg, len_arg, null, 1, unireg_check_arg, field_name_arg, collation) {} const Type_handler *type_handler() const override { return &type_handler_null; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Information_schema_character_attributes information_schema_character_attributes() const override { return Information_schema_character_attributes(); } Copy_func *get_copy_func(const Field *from) const override { return do_field_string; } int store(const char *to, size_t length, CHARSET_INFO *cs) override final { null[0]=1; return 0; } int store(double nr) override final { null[0]=1; return 0; } int store(longlong nr, bool unsigned_val) override final { null[0]=1; return 0; } int store_decimal(const my_decimal *d) override final { null[0]=1; return 0; } int reset() override final { return 0; } double val_real() override final { return 0.0;} longlong val_int() override final { return 0;} bool val_bool() override final { return false; } my_decimal *val_decimal(my_decimal *) override final { return 0; } String *val_str(String *value,String *value2) override final { value2->length(0); return value2;} bool is_equal(const Column_definition &new_field) const override final; int cmp(const uchar *a, const uchar *b) const override final { return 0;} void sort_string(uchar *buff, uint length) override final {} uint32 pack_length() const override final { return 0; } void sql_type(String &str) const override final; uint size_of() const override final { return sizeof *this; } uint32 max_display_length() const override final { return 4; } void move_field_offset(my_ptrdiff_t ptr_diff) override final {} Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const override final { return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const override final { return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } }; class Field_temporal :public Field { protected: Item *get_equal_const_item_datetime(THD *thd, const Context &ctx, Item *const_item); void set_warnings(Sql_condition::enum_warning_level trunc_level, const ErrConv *str, int was_cut, const char *typestr); int store_TIME_return_code_with_warnings(int warn, const ErrConv *str, const char *typestr) { if (!MYSQL_TIME_WARN_HAVE_WARNINGS(warn) && MYSQL_TIME_WARN_HAVE_NOTES(warn)) { set_warnings(Sql_condition::WARN_LEVEL_NOTE, str, warn | MYSQL_TIME_WARN_TRUNCATED, typestr); return 3; } set_warnings(Sql_condition::WARN_LEVEL_WARN, str, warn, typestr); return warn ? 2 : 0; } int store_invalid_with_warning(const ErrConv *str, int was_cut, const char *typestr) { DBUG_ASSERT(was_cut); reset(); Sql_condition::enum_warning_level level= Sql_condition::WARN_LEVEL_WARN; if (was_cut & MYSQL_TIME_WARN_ZERO_DATE) { set_warnings(level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, typestr); return 2; } set_warnings(level, str, MYSQL_TIME_WARN_TRUNCATED, typestr); return 1; } void sql_type_comment(String &str, const Name &name, const Name &comment) const; void sql_type_dec_comment(String &str, const Name &name, uint dec, const Name &comment) const; void sql_type_opt_dec_comment(String &str, const Name &name, uint dec, const Name &comment) const { if (dec) sql_type_dec_comment(str, name, dec, comment); else sql_type_comment(str, name, comment); } static const Name &type_version_mysql56(); public: Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { flags|= BINARY_FLAG; } int store_hex_hybrid(const char *str, size_t length) override { return store(str, length, &my_charset_bin); } sql_mode_t can_handle_sql_mode_dependency_on_store() const override; Copy_func *get_copy_func(const Field *from) const override; int save_in_field(Field *to) override { MYSQL_TIME ltime; // For temporal types no truncation needed. Rounding mode is not important. if (get_date(<ime, TIME_CONV_NONE | TIME_FRAC_NONE)) return to->reset(); return to->store_time_dec(<ime, decimals()); } bool memcpy_field_possible(const Field *from) const override; uint32 max_display_length() const override { return field_length; } bool str_needs_quotes() const override { return true; } CHARSET_INFO *charset() const override { return DTCollation_numeric::singleton().collation; } const DTCollation &dtcollation() const override { return DTCollation_numeric::singleton(); } CHARSET_INFO *sort_charset() const override { return &my_charset_bin; } bool binary() const override { return true; } bool val_bool() override { return val_real() != 0e0; } bool is_equal(const Column_definition &new_field) const override; bool eq_def(const Field *field) const override { return (Field::eq_def(field) && decimals() == field->decimals()); } my_decimal *val_decimal(my_decimal*) override; double pos_in_interval(Field *min, Field *max) override { return pos_in_interval_val_real(min, max); } Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const override; Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const override; Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const override { return Data_type_compatibility::OK; } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override; }; /** Abstract class for: - DATE - DATETIME - DATETIME(1..6) - DATETIME(0..6) - MySQL56 version */ class Field_temporal_with_date :public Field_temporal { protected: virtual void store_TIME(const MYSQL_TIME *ltime) = 0; void store_datetime(const Datetime &dt) { return store_TIME(dt.get_mysql_time()); } virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const = 0; bool validate_MMDD(bool not_zero_date, uint month, uint day, date_mode_t fuzzydate) const { if (!not_zero_date) return bool(fuzzydate & TIME_NO_ZERO_DATE); if (!month || !day) return bool(fuzzydate & TIME_NO_ZERO_IN_DATE); return false; } public: Field_temporal_with_date(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} bool validate_value_in_record(THD *thd, const uchar *record) const override; }; class Field_timestamp :public Field_temporal { protected: int store_TIME_with_warning(THD *, const Datetime *, const ErrConv *, int warn); virtual void store_TIMEVAL(const timeval &tv)= 0; void store_TIMESTAMP(const Timestamp &ts) { store_TIMEVAL(ts.tv()); } int zero_time_stored_return_code_with_warning(); public: Field_timestamp(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share); const Type_handler *type_handler() const override { return &type_handler_timestamp; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Copy_func *get_copy_func(const Field *from) const override; sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override; int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store_decimal(const my_decimal *) override; int store_timestamp_dec(const timeval &ts, uint dec) override; int save_in_field(Field *to) override; longlong val_int() override; String *val_str(String *, String *) override; bool zero_pack() const override { return false; } /* This method is used by storage/perfschema and Item_func_now_local::save_in_field(). */ void store_TIME(my_time_t ts, ulong sec_part) { int warn; time_round_mode_t mode= Datetime::default_round_mode(get_thd()); store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn)); } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; int store_native(const Native &value) override; bool validate_value_in_record(THD *thd, const uchar *record) const override; Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override { return get_equal_const_item_datetime(thd, ctx, const_item); } bool load_data_set_null(THD *thd) override; bool load_data_set_no_data(THD *thd, bool fixed_format) override; }; class Field_timestamp0 :public Field_timestamp { void store_TIMEVAL(const timeval &tv) override { int4store(ptr, tv.tv_sec); } public: Field_timestamp0(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share) :Field_timestamp(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share) { } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_ULONG_INT; } void sql_type(String &str) const override { sql_type_comment(str, Field_timestamp0::type_handler()->name(), Type_handler::version_mariadb53()); } double val_real() override { return (double) Field_timestamp0::val_int(); } bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } int set_time() override; /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */ my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override; bool val_native(Native *to) override; uchar *pack(uchar *to, const uchar *from, uint) override { return pack_int32(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int32(to, from, from_end); } uint size_of() const override { return sizeof *this; } }; /** Abstract class for: - TIMESTAMP(1..6) - TIMESTAMP(0..6) - MySQL56 version */ class Field_timestamp_with_dec :public Field_timestamp { protected: decimal_digits_t dec; public: Field_timestamp_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, decimal_digits_t dec_arg) : Field_timestamp(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share), dec(dec_arg) { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); } decimal_digits_t decimals() const override { return dec; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } uchar *pack(uchar *to, const uchar *from, uint max_length) override { return Field::pack(to, from, max_length); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override { return Field::unpack(to, from, from_end, param_data); } void make_send_field(Send_field *field) override; void sort_string(uchar *to, uint length) override { DBUG_ASSERT(length == pack_length()); memcpy(to, ptr, length); } bool send(Protocol *protocol) override; double val_real() override; my_decimal* val_decimal(my_decimal*) override; int set_time() override; }; class Field_timestamp_hires :public Field_timestamp_with_dec { uint sec_part_bytes(uint dec) const { return Type_handler_timestamp::sec_part_bytes(dec); } void store_TIMEVAL(const timeval &tv) override; public: Field_timestamp_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, decimal_digits_t dec_arg) : Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, dec_arg) { DBUG_ASSERT(dec); } void sql_type(String &str) const override { sql_type_dec_comment(str, Field_timestamp_hires::type_handler()->name(), dec, Type_handler::version_mariadb53()); } bool val_native(Native *to) override; my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override; int cmp(const uchar *,const uchar *) const override; uint32 pack_length() const override { return 4 + sec_part_bytes(dec); } uint size_of() const override { return sizeof *this; } }; /** TIMESTAMP(0..6) - MySQL56 version */ class Field_timestampf :public Field_timestamp_with_dec { void store_TIMEVAL(const timeval &tv) override; public: Field_timestampf(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, decimal_digits_t dec_arg) : Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, dec_arg) {} const Type_handler *type_handler() const override { return &type_handler_timestamp2; } enum_field_types binlog_type() const override { return MYSQL_TYPE_TIMESTAMP2; } void sql_type(String &str) const override { sql_type_opt_dec_comment(str, Field_timestampf::type_handler()->name(), dec, type_version_mysql56()); } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; uint32 pack_length() const override { return my_timestamp_binary_length(dec); } uint row_pack_length() const override { return pack_length(); } uint pack_length_from_metadata(uint field_metadata) const override { DBUG_ENTER("Field_timestampf::pack_length_from_metadata"); uint tmp= my_timestamp_binary_length(field_metadata); DBUG_RETURN(tmp); } int cmp(const uchar *a_ptr,const uchar *b_ptr) const override { return memcmp(a_ptr, b_ptr, pack_length()); } void set_max() override; bool is_max(const uchar *ptr_arg) const override; my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override; bool val_native(Native *to) override; uint size_of() const override { return sizeof *this; } Binlog_type_info binlog_type_info() const override; }; class Field_year final :public Field_tiny { public: Field_year(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 1, 1) {} const Type_handler *type_handler() const override { return field_length == 2 ? &type_handler_year2 : &type_handler_year; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Copy_func *get_copy_func(const Field *from) const override { if (eq_def(from)) return get_identical_copy_func(); switch (from->cmp_type()) { case STRING_RESULT: { const Type_handler *handler= from->type_handler(); if (handler == &type_handler_enum || handler == &type_handler_set) return do_field_int; return do_field_string; } case TIME_RESULT: return do_field_date; case DECIMAL_RESULT: return do_field_decimal; case REAL_RESULT: return do_field_real; case INT_RESULT: break; case ROW_RESULT: default: DBUG_ASSERT(0); break; } return do_field_int; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool send(Protocol *protocol) override; Information_schema_numeric_attributes information_schema_numeric_attributes() const override { return Information_schema_numeric_attributes(); } uint32 max_display_length() const override { return field_length; } void sql_type(String &str) const override; }; class Field_date_common :public Field_temporal_with_date { protected: int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, int was_cut); public: Field_date_common(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} Copy_func *get_copy_func(const Field *from) const override; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store_decimal(const my_decimal *) override; }; class Field_date final :public Field_date_common { void store_TIME(const MYSQL_TIME *ltime) override; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const override; public: Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} const Type_handler *type_handler() const override { return &type_handler_date; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_ULONG_INT; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_date::get_TIME(ltime, ptr, fuzzydate); } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } void sql_type(String &str) const override; uchar *pack(uchar* to, const uchar *from, uint) override { return pack_int32(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int32(to, from, from_end); } uint size_of() const override { return sizeof *this; } }; class Field_newdate final :public Field_date_common { void store_TIME(const MYSQL_TIME *ltime) override; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const override; public: Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} const Type_handler *type_handler() const override { return &type_handler_newdate; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_UINT24; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; int reset() override { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } void sql_type(String &str) const override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); } longlong val_datetime_packed(THD *thd) override; uint size_of() const override { return sizeof *this; } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override; }; class Field_time :public Field_temporal { /* when this Field_time instance is used for storing values for index lookups (see class store_key, Field::new_key_field(), etc), the following might be set to TO_DAYS(CURDATE()). See also Field_time::store_time_dec() */ long curdays; protected: virtual void store_TIME(const MYSQL_TIME *ltime)= 0; void store_TIME(const Time &t) { return store_TIME(t.get_mysql_time()); } int store_TIME_with_warning(const Time *ltime, const ErrConv *str, int warn); bool check_zero_in_date_with_warn(date_mode_t fuzzydate); static void do_field_time(const Copy_field *copy); public: Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), curdays(0) {} bool can_be_substituted_to_equal_item(const Context &ctx, const Item_equal *item_equal) override; const Type_handler *type_handler() const override { return &type_handler_time; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Copy_func *get_copy_func(const Field *from) const override { return from->cmp_type() == REAL_RESULT ? do_field_string : // MDEV-9344 from->type() == MYSQL_TYPE_YEAR ? do_field_int : from->type() == MYSQL_TYPE_BIT ? do_field_int : eq_def(from) ? get_identical_copy_func() : do_field_time; } bool memcpy_field_possible(const Field *from) const override { return real_type() == from->real_type() && decimals() == from->decimals(); } sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override; int store_native(const Native &value) override; bool val_native(Native *to) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; void set_curdays(THD *thd); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit) override; Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override; }; class Field_time0 final :public Field_time { protected: void store_TIME(const MYSQL_TIME *ltime) override; public: Field_time0(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_time(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_INT24; } void sql_type(String &str) const override { sql_type_comment(str, Field_time0::type_handler()->name(), Type_handler::version_mariadb53()); } double val_real() override; longlong val_int() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } uint size_of() const override { return sizeof *this; } }; /** Abstract class for: - TIME(1..6) - TIME(0..6) - MySQL56 version */ class Field_time_with_dec :public Field_time { protected: decimal_digits_t dec; public: Field_time_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), dec(dec_arg) { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); } decimal_digits_t decimals() const override { return dec; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } longlong val_int() override; double val_real() override; void make_send_field(Send_field *) override; }; /** TIME(1..6) */ class Field_time_hires final :public Field_time_with_dec { longlong zero_point; void store_TIME(const MYSQL_TIME *) override; public: Field_time_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_time_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) { DBUG_ASSERT(dec); zero_point= sec_part_shift( ((TIME_MAX_VALUE_SECONDS+1LL)*TIME_SECOND_PART_FACTOR), dec); } void sql_type(String &str) const override { sql_type_dec_comment(str, Field_time_hires::type_handler()->name(), dec, Type_handler::version_mariadb53()); } int reset() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return Type_handler_time::hires_bytes(dec); } uint size_of() const override { return sizeof *this; } }; /** TIME(0..6) - MySQL56 version */ class Field_timef final :public Field_time_with_dec { void store_TIME(const MYSQL_TIME *ltime) override; public: Field_timef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_time_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); } const Type_handler *type_handler() const override { return &type_handler_time2; } enum_field_types binlog_type() const override { return MYSQL_TYPE_TIME2; } void sql_type(String &str) const override { sql_type_opt_dec_comment(str, Field_timef::type_handler()->name(), dec, type_version_mysql56()); } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; uint32 pack_length() const override { return my_time_binary_length(dec); } uint row_pack_length() const override { return pack_length(); } uint pack_length_from_metadata(uint field_metadata) const override { DBUG_ENTER("Field_timef::pack_length_from_metadata"); uint tmp= my_time_binary_length(field_metadata); DBUG_RETURN(tmp); } void sort_string(uchar *to, uint length) override { DBUG_ASSERT(length == Field_timef::pack_length()); memcpy(to, ptr, length); } int cmp(const uchar *a_ptr, const uchar *b_ptr) const override { return memcmp(a_ptr, b_ptr, pack_length()); } int reset() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; longlong val_time_packed(THD *thd) override; int store_native(const Native &value) override; bool val_native(Native *to) override; uint size_of() const override { return sizeof *this; } Binlog_type_info binlog_type_info() const override; }; class Field_datetime :public Field_temporal_with_date { protected: int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, int was_cut); public: Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { if (unireg_check == TIMESTAMP_UN_FIELD || unireg_check == TIMESTAMP_DNUN_FIELD) flags|= ON_UPDATE_NOW_FLAG; } const Type_handler *type_handler() const override { return &type_handler_datetime; } sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override; enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store_decimal(const my_decimal *) override; int set_time() override; Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override { return get_equal_const_item_datetime(thd, ctx, const_item); } }; /* Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte */ class Field_datetime0 final :public Field_datetime { void store_TIME(const MYSQL_TIME *ltime) override; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const override; public: Field_datetime0(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_datetime(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} enum ha_base_keytype key_type() const override { return HA_KEYTYPE_ULONGLONG; } void sql_type(String &str) const override { sql_type_comment(str, Field_datetime0::type_handler()->name(), Type_handler::version_mariadb53()); } double val_real() override { return (double) Field_datetime0::val_int(); } longlong val_int() override; String *val_str(String *, String *) override; bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_datetime0::get_TIME(ltime, ptr, fuzzydate); } uchar *pack(uchar* to, const uchar *from, uint) override { return pack_int64(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint) override { return unpack_int64(to, from, from_end); } uint size_of() const override { return sizeof *this; } }; /** Abstract class for: - DATETIME(1..6) - DATETIME(0..6) - MySQL56 version */ class Field_datetime_with_dec :public Field_datetime { protected: decimal_digits_t dec; public: Field_datetime_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_datetime(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), dec(dec_arg) { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); } decimal_digits_t decimals() const override final { return dec; } enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_BINARY; } void make_send_field(Send_field *field) override final; bool send(Protocol *protocol) override final; uchar *pack(uchar *to, const uchar *from, uint max_length) override final { return Field::pack(to, from, max_length); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override final { return Field::unpack(to, from, from_end, param_data); } void sort_string(uchar *to, uint length) override final { DBUG_ASSERT(length == pack_length()); memcpy(to, ptr, length); } double val_real() override final; longlong val_int() override final; String *val_str(String *, String *) override final; }; /** DATETIME(1..6) */ class Field_datetime_hires final :public Field_datetime_with_dec { void store_TIME(const MYSQL_TIME *ltime) override; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const override; public: Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) { DBUG_ASSERT(dec); } void sql_type(String &str) const override { sql_type_dec_comment(str, Field_datetime_hires::type_handler()->name(), dec, Type_handler::version_mariadb53()); } int cmp(const uchar *,const uchar *) const override; uint32 pack_length() const override { return Type_handler_datetime::hires_bytes(dec); } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); } uint size_of() const override { return sizeof *this; } }; /** DATETIME(0..6) - MySQL56 version */ class Field_datetimef final :public Field_datetime_with_dec { void store_TIME(const MYSQL_TIME *ltime) override; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const override; public: Field_datetimef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg) :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) {} const Type_handler *type_handler() const override { return &type_handler_datetime2; } enum_field_types binlog_type() const override { return MYSQL_TYPE_DATETIME2; } void sql_type(String &str) const override { sql_type_opt_dec_comment(str, Field_datetimef::type_handler()->name(), dec, type_version_mysql56()); } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; uint32 pack_length() const override { return my_datetime_binary_length(dec); } uint row_pack_length() const override { return pack_length(); } uint pack_length_from_metadata(uint field_metadata) const override { DBUG_ENTER("Field_datetimef::pack_length_from_metadata"); uint tmp= my_datetime_binary_length(field_metadata); DBUG_RETURN(tmp); } int cmp(const uchar *a_ptr, const uchar *b_ptr) const override { return memcmp(a_ptr, b_ptr, pack_length()); } int reset() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_datetimef::get_TIME(ltime, ptr, fuzzydate); } longlong val_datetime_packed(THD *thd) override; uint size_of() const override { return sizeof *this; } Binlog_type_info binlog_type_info() const override; }; static inline Field_timestamp * new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit, enum Field::utype unireg_check, const LEX_CSTRING *field_name, TABLE_SHARE *share, decimal_digits_t dec) { if (dec==0) return new (root) Field_timestamp0(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit, unireg_check, field_name, share); if (dec >= FLOATING_POINT_DECIMALS) dec= MAX_DATETIME_PRECISION; return new (root) Field_timestamp_hires(ptr, null_ptr, null_bit, unireg_check, field_name, share, dec); } static inline Field_time * new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit, enum Field::utype unireg_check, const LEX_CSTRING *field_name, decimal_digits_t dec) { if (dec == 0) return new (root) Field_time0(ptr, MIN_TIME_WIDTH, null_ptr, null_bit, unireg_check, field_name); if (dec >= FLOATING_POINT_DECIMALS) dec= MAX_DATETIME_PRECISION; return new (root) Field_time_hires(ptr, null_ptr, null_bit, unireg_check, field_name, dec); } static inline Field_datetime * new_Field_datetime(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit, enum Field::utype unireg_check, const LEX_CSTRING *field_name, decimal_digits_t dec) { if (dec == 0) return new (root) Field_datetime0(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit, unireg_check, field_name); if (dec >= FLOATING_POINT_DECIMALS) dec= MAX_DATETIME_PRECISION; return new (root) Field_datetime_hires(ptr, null_ptr, null_bit, unireg_check, field_name, dec); } class Field_string final :public Field_longstr { class Warn_filter_string: public Warn_filter { public: Warn_filter_string(const THD *thd, const Field_string *field); }; bool is_var_string() const { return can_alter_field_type && orig_table && (orig_table->s->db_create_options & HA_OPTION_PACK_RECORD) && field_length >= 4 && orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR; } LEX_CSTRING to_lex_cstring() const; public: bool can_alter_field_type; Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, collation), can_alter_field_type(1) {}; Field_string(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, collation), can_alter_field_type(1) {}; const Type_handler *type_handler() const override; enum ha_base_keytype key_type() const override { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override; bool zero_pack() const override { return false; } Copy_func *get_copy_func(const Field *from) const override; int reset() override { charset()->fill((char*) ptr, field_length, (has_charset() ? ' ' : 0)); return 0; } int store(const char *to,size_t length,CHARSET_INFO *charset) override; using Field_str::store; double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; int cmp(const uchar *,const uchar *) const override; int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const override; void sort_string(uchar *buff,uint length) override; void update_data_type_statistics(Data_type_statistics *st) const override { st->m_fixed_string_count++; st->m_fixed_string_total_length+= pack_length(); } void sql_type(String &str) const override; void sql_rpl_type(String*) const override; bool is_equal(const Column_definition &new_field) const override; uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; uint pack_length_from_metadata(uint field_metadata) const override { DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata)); if (field_metadata == 0) return row_pack_length(); return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff); } bool compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; uint row_pack_length() const override { return field_length; } uint packed_col_length(const uchar *to, uint length) override; uint max_packed_col_length(uint max_length) override; uint size_of() const override { return sizeof *this; } bool has_charset() const override { return charset() != &my_charset_bin; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type) const override; sql_mode_t value_depends_on_sql_mode() const override; sql_mode_t can_handle_sql_mode_dependency_on_store() const override; void print_key_value(String *out, uint32 length) override; Binlog_type_info binlog_type_info() const override; }; class Field_varstring :public Field_longstr { public: const uchar *get_data() const { return get_data(ptr); } const uchar *get_data(const uchar *ptr_arg) const { return ptr_arg + length_bytes; } uint get_length() const { return get_length(ptr); } uint get_length(const uchar *ptr_arg) const { return length_bytes == 1 ? (uint) *ptr_arg : uint2korr(ptr_arg); } protected: void store_length(uint32 number) { if (length_bytes == 1) *ptr= (uchar) number; else int2store(ptr, number); } virtual void val_str_from_ptr(String *val, const uchar *ptr) const; public: /* The maximum space available in a Field_varstring, in bytes. See length_bytes. */ static const uint MAX_SIZE; /* Store number of bytes used to store length (1 or 2) */ uint32 length_bytes; Field_varstring(uchar *ptr_arg, uint32 len_arg, uint length_bytes_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, collation), length_bytes(length_bytes_arg) { share->varchar_fields++; } Field_varstring(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, const DTCollation &collation) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, collation), length_bytes(len_arg < 256 ? 1 :2) { share->varchar_fields++; } const Type_handler *type_handler() const override; en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override { return FIELD_VARCHAR; } enum ha_base_keytype key_type() const override; uint16 key_part_flag() const override { return HA_VAR_LENGTH_PART; } uint16 key_part_length_bytes() const override { return HA_KEY_BLOB_LENGTH; } uint row_pack_length() const override { return field_length; } bool zero_pack() const override { return false; } int reset() override { bzero(ptr,field_length+length_bytes); return 0; } uint32 pack_length() const override { return (uint32) field_length+length_bytes; } uint32 key_length() const override { return (uint32) field_length; } uint32 sort_length() const override { return (uint32) field_length + sort_suffix_length(); } uint32 sort_suffix_length() const override { return (field_charset() == &my_charset_bin ? length_bytes : 0); } Copy_func *get_copy_func(const Field *from) const override; bool memcpy_field_possible(const Field *from) const override; void update_data_type_statistics(Data_type_statistics *st) const override { st->m_variable_string_count++; st->m_variable_string_total_length+= pack_length(); } int store(const char *to,size_t length,CHARSET_INFO *charset) override; using Field_str::store; #ifdef HAVE_MEM_CHECK void mark_unused_memory_as_defined() override; #endif double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; bool send(Protocol *protocol) override; int cmp(const uchar *a,const uchar *b) const override; int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const override; void sort_string(uchar *buff,uint length) override; uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type) const override; void set_key_image(const uchar *buff,uint length) override; void sql_type(String &str) const override; void sql_rpl_type(String*) const override; uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const override; int key_cmp(const uchar *,const uchar*) const override; int key_cmp(const uchar *str, uint length) const override; uint packed_col_length(const uchar *to, uint length) override; uint max_packed_col_length(uint max_length) override; uint32 data_length() override; uint size_of() const override { return sizeof *this; } bool has_charset() const override { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit) override; bool is_equal(const Column_definition &new_field) const override; void hash_not_null(Hasher *hasher) override; uint length_size() const override { return length_bytes; } void print_key_value(String *out, uint32 length) override; Binlog_type_info binlog_type_info() const override; }; class Field_varstring_compressed final :public Field_varstring { public: Field_varstring_compressed(uchar *ptr_arg, uint32 len_arg, uint length_bytes_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, const DTCollation &collation, Compression_method *compression_method_arg): Field_varstring(ptr_arg, len_arg, length_bytes_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, collation), compression_method_ptr(compression_method_arg) { DBUG_ASSERT(len_arg > 0); } Compression_method *compression_method() const override { return compression_method_ptr; } private: Compression_method *compression_method_ptr; void val_str_from_ptr(String *val, const uchar *ptr) const override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; using Field_str::store; String *val_str(String *, String *) override; double val_real() override; longlong val_int() override; uint size_of() const override { return sizeof *this; } /* We use the default Field::send() implementation, because the derived optimized version (from Field_longstr) is not suitable for compressed fields. */ bool send(Protocol *protocol) override { return Field::send(protocol); } enum_field_types binlog_type() const override { return MYSQL_TYPE_VARCHAR_COMPRESSED; } void sql_type(String &str) const override { Field_varstring::sql_type(str); str.append(STRING_WITH_LEN(" /*M!100301 COMPRESSED*/")); } uint32 max_display_length() const override { return field_length - 1; } uint32 character_octet_length() const override { return field_length - 1; } uint32 char_length() const override { return (field_length - 1) / mbmaxlen(); } int cmp(const uchar *a_ptr, const uchar *b_ptr) const override; /* Compressed fields can't have keys as two rows may have different compression methods or compression levels. */ int key_cmp(const uchar *str, uint length) const override { DBUG_ASSERT(0); return 0; } using Field_varstring::key_cmp; Binlog_type_info binlog_type_info() const override; Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; }; static inline uint8 number_storage_requirement(uint32 n) { return n < 256 ? 1 : n < 65536 ? 2 : n < 16777216 ? 3 : 4; } static inline void store_bigendian(ulonglong num, uchar *to, uint bytes) { switch(bytes) { case 1: mi_int1store(to, num); break; case 2: mi_int2store(to, num); break; case 3: mi_int3store(to, num); break; case 4: mi_int4store(to, num); break; case 5: mi_int5store(to, num); break; case 6: mi_int6store(to, num); break; case 7: mi_int7store(to, num); break; case 8: mi_int8store(to, num); break; default: DBUG_ASSERT(0); } } static inline longlong read_bigendian(const uchar *from, uint bytes) { switch(bytes) { case 1: return mi_uint1korr(from); case 2: return mi_uint2korr(from); case 3: return mi_uint3korr(from); case 4: return mi_uint4korr(from); case 5: return mi_uint5korr(from); case 6: return mi_uint6korr(from); case 7: return mi_uint7korr(from); case 8: return mi_sint8korr(from); default: DBUG_ASSERT(0); return 0; } } static inline void store_lowendian(ulonglong num, uchar *to, uint bytes) { switch(bytes) { case 1: *to= (uchar)num; break; case 2: int2store(to, num); break; case 3: int3store(to, num); break; case 4: int4store(to, num); break; case 8: int8store(to, num); break; default: DBUG_ASSERT(0); } } static inline longlong read_lowendian(const uchar *from, uint bytes) { switch(bytes) { case 1: return from[0]; case 2: return uint2korr(from); case 3: return uint3korr(from); case 4: return uint4korr(from); case 8: return sint8korr(from); default: DBUG_ASSERT(0); return 0; } } extern LEX_CSTRING temp_lex_str; class Field_blob :public Field_longstr { protected: /** The number of bytes used to represent the length of the blob. */ uint packlength; /** The 'value'-object is a cache fronting the storage engine. */ String value; /** Cache for blob values when reading a row with a virtual blob field. This is needed to not destroy the old cached value when updating the blob with a new value when creating the new row. */ String read_value; static void do_copy_blob(const Copy_field *copy); static void do_conv_blob(const Copy_field *copy); uint get_key_image_itRAW(const uchar *ptr_arg, uchar *buff, uint length) const; public: Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, const DTCollation &collation); Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, collation), packlength(4) { flags|= BLOB_FLAG; } Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation, bool set_packlength) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, collation) { flags|= BLOB_FLAG; packlength= set_packlength ? number_storage_requirement(len_arg) : 4; } Field_blob(uint32 packlength_arg) :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str, system_charset_info), packlength(packlength_arg) {} const Type_handler *type_handler() const override; /* Note that the default copy constructor is used, in clone() */ enum_field_types type() const override { /* We cannot return type_handler()->field_type() here. Some pieces of the code (e.g. in engines) rely on the fact that Field::type(), Field::real_type() and Item_field::field_type() return MYSQL_TYPE_BLOB for all blob variants. We should eventually fix all such code pieces to expect all BLOB type codes. */ return MYSQL_TYPE_BLOB; } enum_field_types real_type() const override { return MYSQL_TYPE_BLOB; } enum ha_base_keytype key_type() const override { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } uint16 key_part_flag() const override { return HA_BLOB_PART; } uint16 key_part_length_bytes() const override { return HA_KEY_BLOB_LENGTH; } en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override { return FIELD_BLOB; } Type_numeric_attributes type_numeric_attributes() const override { return Type_numeric_attributes(Field_blob::max_display_length(), decimals(), is_unsigned()); } Information_schema_character_attributes information_schema_character_attributes() const override { uint32 octets= Field_blob::character_octet_length(); uint32 chars= octets / field_charset()->mbminlen; return Information_schema_character_attributes(octets, chars); } void update_data_type_statistics(Data_type_statistics *st) const override { st->m_blob_count++; } void make_send_field(Send_field *) override; Copy_func *get_copy_func(const Field *from) const override { /* TODO: MDEV-9331 if (from->type() == MYSQL_TYPE_BIT) return do_field_int; */ if (!(from->flags & BLOB_FLAG) || from->charset() != charset() || !from->compression_method() != !compression_method()) return do_conv_blob; if (from->pack_length() != Field_blob::pack_length()) return do_copy_blob; return get_identical_copy_func(); } int store_field(Field *from) override { // Be sure the value is stored if (field_charset() == &my_charset_bin && from->type_handler()->convert_to_binary_using_val_native()) { NativeBuffer<64> tmp; from->val_native(&tmp); value.copy(tmp.ptr(), tmp.length(), &my_charset_bin); return store(value.ptr(), value.length(), &my_charset_bin); } from->val_str(&value); if (table->copy_blobs || (!value.is_alloced() && from->is_varchar_and_in_write_set())) value.copy(); return store(value.ptr(), value.length(), from->charset()); } bool memcpy_field_possible(const Field *from) const override { return Field_str::memcpy_field_possible(from) && !compression_method() == !from->compression_method() && !table->copy_blobs; } bool make_empty_rec_store_default_value(THD *thd, Item *item) override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store_from_statistical_minmax_field(Field *stat_field, String *str, MEM_ROOT *mem) override; using Field_str::store; void hash_not_null(Hasher *hasher) override; double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; int cmp(const uchar *a, const uchar *b) const override; int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const override; int cmp(const uchar *a, uint32 a_length, const uchar *b, uint32 b_length) const; int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const override; int key_cmp(const uchar *,const uchar*) const override; int key_cmp(const uchar *str, uint length) const override; /* Never update the value of min_val for a blob field */ bool update_min(Field *min_val, bool force_update) override { return false; } /* Never update the value of max_val for a blob field */ bool update_max(Field *max_val, bool force_update) override { return false; } uint32 key_length() const override { return 0; } void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return (uint32) (packlength + portable_sizeof_char_ptr); } /** Return the packed length without the pointer size added. This is used to determine the size of the actual data in the row buffer. @returns The length of the raw data itself without the pointer. */ uint32 pack_length_no_ptr() const { return (uint32) (packlength); } uint row_pack_length() const override { return pack_length_no_ptr(); } uint32 sort_length() const override; uint32 sort_suffix_length() const override; uint32 value_length() override { return get_length(); } uint32 max_data_length() const override { return (uint32) (((ulonglong) 1 << (packlength*8)) -1); } int reset() override { bzero(ptr, packlength+sizeof(uchar*)); return 0; } void reset_fields() override { bzero((uchar*) &value, sizeof value); bzero((uchar*) &read_value, sizeof read_value); } uint32 get_field_buffer_size() { return value.alloced_length(); } void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number); void store_length(size_t number) { DBUG_ASSERT(number < UINT_MAX32); store_length(ptr, packlength, (uint32)number); } inline uint32 get_length(my_ptrdiff_t row_offset= 0) const { return get_length(ptr+row_offset, this->packlength); } uint32 get_length(const uchar *ptr, uint packlength) const; uint32 get_length(const uchar *ptr_arg) const { return get_length(ptr_arg, this->packlength); } inline uchar *get_ptr() const { return get_ptr(ptr); } inline uchar *get_ptr(const uchar *ptr_arg) const { uchar *s; memcpy(&s, ptr_arg + packlength, sizeof(uchar*)); return s; } inline void set_ptr(uchar *length, uchar *data) { memcpy(ptr,length,packlength); memcpy(ptr+packlength, &data,sizeof(char*)); } void set_ptr_offset(my_ptrdiff_t ptr_diff, uint32 length, const uchar *data) { uchar *ptr_ofs= ADD_TO_PTR(ptr,ptr_diff,uchar*); store_length(ptr_ofs, packlength, length); memcpy(ptr_ofs+packlength, &data, sizeof(char*)); } inline void set_ptr(uint32 length, uchar *data) { set_ptr_offset(0, length, data); } int copy_value(Field_blob *from); uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type) const override { DBUG_ASSERT(type == itRAW); return get_key_image_itRAW(ptr_arg, buff, length); } void set_key_image(const uchar *buff,uint length) override; Field *make_new_field(MEM_ROOT *, TABLE *new_table, bool keep_type) override; Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit) override; void sql_type(String &str) const override; /** Copy blob buffer into internal storage "value" and update record pointer. @retval true Memory allocation error @retval false Success */ bool copy() { uchar *tmp= get_ptr(); if (value.copy((char*) tmp, get_length(), charset())) { Field_blob::reset(); return 1; } tmp=(uchar*) value.ptr(); memcpy(ptr+packlength, &tmp, sizeof(char*)); return 0; } void swap(String &inout, bool set_read_value) { if (set_read_value) read_value.swap(inout); else value.swap(inout); } /** Return pointer to blob cache or NULL if not cached. */ String * cached(bool *set_read_value) { char *tmp= (char *) get_ptr(); if (!value.is_empty() && tmp == value.ptr()) { *set_read_value= false; return &value; } if (!read_value.is_empty() && tmp == read_value.ptr()) { *set_read_value= true; return &read_value; } return NULL; } /* store value for the duration of the current read record */ inline void swap_value_and_read_value() { read_value.swap(value); } inline void set_value(uchar *data) { /* Set value pointer. Lengths are not important */ value.reset((char*) data, 1, 1, &my_charset_bin); } uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; uint packed_col_length(const uchar *col_ptr, uint length) override; uint max_packed_col_length(uint max_length) override; void free() override { value.free(); read_value.free(); } inline void clear_temporary() { uchar *tmp= get_ptr(); if (likely(value.ptr() == (char*) tmp)) bzero((uchar*) &value, sizeof(value)); else { /* Currently read_value should never point to tmp, the following code is mainly here to make things future proof. */ if (unlikely(read_value.ptr() == (char*) tmp)) bzero((uchar*) &read_value, sizeof(read_value)); } } uint size_of() const override { return sizeof *this; } bool has_charset() const override { return charset() != &my_charset_bin; } uint32 max_display_length() const override; uint32 char_length() const override; uint32 character_octet_length() const override; bool is_equal(const Column_definition &new_field) const override; void print_key_value(String *out, uint32 length) override; Binlog_type_info binlog_type_info() const override; friend void TABLE::remember_blob_values(String *blob_storage); friend void TABLE::restore_blob_values(String *blob_storage); }; class Field_blob_compressed final :public Field_blob { public: Field_blob_compressed(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, const DTCollation &collation, Compression_method *compression_method_arg): Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, blob_pack_length, collation), compression_method_ptr(compression_method_arg) {} Compression_method *compression_method() const override { return compression_method_ptr; } private: Compression_method *compression_method_ptr; int store(const char *to, size_t length, CHARSET_INFO *charset) override; using Field_str::store; String *val_str(String *, String *) override; double val_real() override; longlong val_int() override; /* We use the default Field::send() implementation, because the derived optimized version (from Field_longstr) is not suitable for compressed fields. */ bool send(Protocol *protocol) override { return Field::send(protocol); } uint size_of() const override { return sizeof *this; } enum_field_types binlog_type() const override { return MYSQL_TYPE_BLOB_COMPRESSED; } void sql_type(String &str) const override { Field_blob::sql_type(str); str.append(STRING_WITH_LEN(" /*M!100301 COMPRESSED*/")); } /* Compressed fields can't have keys as two rows may have different compression methods or compression levels. */ uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type_arg) const override { DBUG_ASSERT(0); return 0; } void set_key_image(const uchar *, uint) override { DBUG_ASSERT(0); } int key_cmp(const uchar *, const uchar *) const override { DBUG_ASSERT(0); return 0; } int key_cmp(const uchar *, uint) const override { DBUG_ASSERT(0); return 0; } Field *new_key_field(MEM_ROOT *, TABLE *, uchar *, uint32, uchar *, uint) override { DBUG_ASSERT(0); return 0; } Binlog_type_info binlog_type_info() const override; Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; }; class Field_enum :public Field_str { static void do_field_enum(const Copy_field *copy_field); longlong val_int(const uchar *) const; Data_type_compatibility can_optimize_range_or_keypart_ref( const Item_bool_func *cond, const Item *item) const; protected: uint packlength; public: const TYPELIB *typelib; Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint packlength_arg, const TYPELIB *typelib_arg, const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, collation), packlength(packlength_arg),typelib(typelib_arg) { flags|=ENUM_FLAG; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) override; const Type_handler *type_handler() const override { return &type_handler_enum; } enum ha_base_keytype key_type() const override; sql_mode_t can_handle_sql_mode_dependency_on_store() const override; enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; Copy_func *get_copy_func(const Field *from) const override { if (eq_def(from)) return get_identical_copy_func(); if (real_type() == MYSQL_TYPE_ENUM && from->real_type() == MYSQL_TYPE_ENUM) return do_field_enum; if (from->result_type() == STRING_RESULT) return do_field_string; return do_field_int; } int store_field(Field *from) override { if (from->real_type() == MYSQL_TYPE_ENUM && from->val_int() == 0) { store_type(0); return 0; } return from->save_in_field(this); } int save_in_field(Field *to) override { if (to->result_type() != STRING_RESULT) return to->store(val_int(), 0); return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const override { return false; } void make_empty_rec_reset() override { if (flags & NOT_NULL_FLAG) { set_notnull(); store(1LL, true); } else reset(); } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return (uint32) packlength; } void store_type(ulonglong value); void sql_type(String &str) const override; uint size_of() const override { return sizeof *this; } uint pack_length_from_metadata(uint field_metadata) const override { return (field_metadata & 0x00ff); } uint row_pack_length() const override { return pack_length(); } bool zero_pack() const override { return false; } bool optimize_range(uint, uint) const override { return false; } bool eq_def(const Field *field) const override; bool has_charset() const override { return true; } /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset() const override { return &my_charset_bin; } decimal_digits_t decimals() const override { return 0; } const TYPELIB *get_typelib() const override { return typelib; } uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const override { return can_optimize_range_or_keypart_ref(cond, item); } Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const override { /* Can't use GROUP_MIN_MAX optimization for ENUM and SET, because the values are stored as numbers in index, while MIN() and MAX() work as strings. It would return the records with min and max enum numeric indexes. "Bug#45300 MAX() and ENUM type" should be fixed first. */ return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const override { return can_optimize_range_or_keypart_ref(cond, item); } Binlog_type_info binlog_type_info() const override; private: bool is_equal(const Column_definition &new_field) const override; }; class Field_set final :public Field_enum { public: Field_set(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint32 packlength_arg, const TYPELIB *typelib_arg, const DTCollation &collation) :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, packlength_arg, typelib_arg, collation) { flags=(flags & ~ENUM_FLAG) | SET_FLAG; } void make_empty_rec_reset() override { Field::make_empty_rec_reset(); } int store_field(Field *from) override { return from->save_in_field(this); } int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override { return Field_set::store((longlong) nr, FALSE); } int store(longlong nr, bool unsigned_val) override; bool zero_pack() const override { return true; } String *val_str(String *, String *) override; void sql_type(String &str) const override; uint size_of() const override { return sizeof *this; } const Type_handler *type_handler() const override { return &type_handler_set; } bool has_charset() const override { return true; } Binlog_type_info binlog_type_info() const override; }; /* Note: To use Field_bit::cmp_binary() you need to copy the bits stored in the beginning of the record (the NULL bytes) to each memory you want to compare (where the arguments point). This is the reason: - Field_bit::cmp_binary() is only implemented in the base class (Field::cmp_binary()). - Field::cmp_binary() currently uses pack_length() to calculate how long the data is. - pack_length() includes size of the bits stored in the NULL bytes of the record. */ class Field_bit :public Field { public: uchar *bit_ptr; // position in record where 'uneven' bits store uchar bit_ofs; // offset to 'uneven' high bits uint bit_len; // number of 'uneven' high bits uint bytes_in_rec; Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg); const Type_handler *type_handler() const override { return &type_handler_bit; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BIT; } uint16 key_part_flag() const override { return HA_BIT_PART; } uint32 key_length() const override { return (uint32) (field_length + 7) / 8; } uint32 max_data_length() const override { return key_length(); } uint32 max_display_length() const override { return field_length; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; CHARSET_INFO *charset() const override { return &my_charset_bin; } const DTCollation & dtcollation() const override; Information_schema_numeric_attributes information_schema_numeric_attributes() const override { return Information_schema_numeric_attributes(field_length); } void update_data_type_statistics(Data_type_statistics *st) const override { st->m_uneven_bit_length+= field_length & 7; } uint size_of() const override { return sizeof *this; } int reset() override { bzero(ptr, bytes_in_rec); if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits clr_rec_bits(bit_ptr, bit_ofs, bit_len); return 0; } Copy_func *get_copy_func(const Field *from) const override { if (from->cmp_type() == DECIMAL_RESULT) return do_field_decimal; return do_field_int; } int save_in_field(Field *to) override { return to->store(val_int(), true); } bool memcpy_field_possible(const Field *from) const override{ return false; } int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; double val_real() override; longlong val_int() override; String *val_str(String*, String *) override; bool str_needs_quotes() const override { return true; } my_decimal *val_decimal(my_decimal *) override; bool val_bool() override { return val_int() != 0; } int cmp(const uchar *a, const uchar *b) const override { DBUG_ASSERT(ptr == a || ptr == b); if (ptr == a) return Field_bit::key_cmp(b, bytes_in_rec + MY_TEST(bit_len)); else return Field_bit::key_cmp(a, bytes_in_rec + MY_TEST(bit_len)) * -1; } int cmp_binary_offset(uint row_offset) override { return cmp_offset(row_offset); } int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_length) const override; int key_cmp(const uchar *a, const uchar *b) const override { return cmp_binary((uchar *) a, (uchar *) b); } int key_cmp(const uchar *str, uint length) const override; int cmp_offset(my_ptrdiff_t row_offset) override; bool update_min(Field *min_val, bool force_update) override { longlong val= val_int(); bool update_fl= force_update || val < min_val->val_int(); if (update_fl) { min_val->set_notnull(); min_val->store(val, FALSE); } return update_fl; } bool update_max(Field *max_val, bool force_update) override { longlong val= val_int(); bool update_fl= force_update || val > max_val->val_int(); if (update_fl) { max_val->set_notnull(); max_val->store(val, FALSE); } return update_fl; } void store_field_value(uchar *val, uint) override { store(*((longlong *)val), TRUE); } double pos_in_interval(Field *min, Field *max) override { return pos_in_interval_val_real(min, max); } void get_image(uchar *buff, uint length, const uchar *ptr_arg, CHARSET_INFO *cs) const override { get_key_image(buff, length, ptr_arg, itRAW); } void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) override { Field_bit::store((char *) buff, length, cs); } uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type) const override; void set_key_image(const uchar *buff, uint length) override { Field_bit::store((char*) buff, length, &my_charset_bin); } void sort_string(uchar *buff, uint length) override { get_key_image(buff, length, ptr, itRAW); } uint32 pack_length() const override { return (uint32) (field_length + 7) / 8; } uint32 pack_length_in_rec() const override { return bytes_in_rec; } uint pack_length_from_metadata(uint field_metadata) const override; uint row_pack_length() const override { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } bool compatible_field_size(uint metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; void sql_type(String &str) const override; uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; int set_default() override; Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit) override; void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg) { bit_ptr= bit_ptr_arg; bit_ofs= bit_ofs_arg; } bool eq(Field *field) override { return (Field::eq(field) && bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ofs == ((Field_bit *)field)->bit_ofs); } bool is_equal(const Column_definition &new_field) const override; void move_field_offset(my_ptrdiff_t ptr_diff) override { Field::move_field_offset(ptr_diff); /* clang does not like when things are added to a null pointer, even if it is never referenced. */ if (bit_ptr) bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*); } void hash_not_null(Hasher *hasher) override; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override { return get_mm_leaf_int(param, key_part, cond, op, value, true); } void print_key_value(String *out, uint32 length) override { val_int_as_str(out, 1); } /** Save the field metadata for bit fields. Saves the bit length in the first byte and bytes in record in the second byte of the field metadata array at index of *metadata_ptr and *(metadata_ptr + 1). @param metadata_ptr First byte of field metadata @returns number of bytes written to metadata_ptr */ Binlog_type_info binlog_type_info() const override { DBUG_PRINT("debug", ("bit_len: %d, bytes_in_rec: %d", bit_len, bytes_in_rec)); /* Since this class and Field_bit_as_char have different ideas of what should be stored here, we compute the values of the metadata explicitly using the field_length. */ return Binlog_type_info(type(), static_cast<uint16>((field_length & 7) | ((field_length / 8) << 8)), 2); } private: size_t do_last_null_byte() const override; }; /** BIT field represented as chars for non-MyISAM tables. @todo The inheritance relationship is backwards since Field_bit is an extended version of Field_bit_as_char and not the other way around. Hence, we should refactor it to fix the hierarchy order. */ class Field_bit_as_char final :public Field_bit { public: Field_bit_as_char(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg); enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } uint size_of() const override { return sizeof *this; } int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override { return Field_bit::store(nr); } int store(longlong nr, bool unsigned_val) override { return Field_bit::store(nr, unsigned_val); } void sql_type(String &str) const override; }; class Field_row final :public Field_null { class Virtual_tmp_table *m_table; public: Field_row(uchar *ptr_arg, const LEX_CSTRING *field_name_arg) :Field_null(ptr_arg, 0, Field::NONE, field_name_arg, &my_charset_bin), m_table(NULL) {} ~Field_row(); en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override { DBUG_ASSERT(0); return Field::tmp_engine_column_type(use_packed_rows); } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override { DBUG_ASSERT(0); return CONV_TYPE_IMPOSSIBLE; } Virtual_tmp_table **virtual_tmp_table_addr() override { return &m_table; } bool sp_prepare_and_store_item(THD *thd, Item **value) override; }; extern const LEX_CSTRING null_clex_str; class Column_definition_attributes { public: /* At various stages in execution this can be length of field in bytes or max number of characters. */ ulonglong length; const TYPELIB *interval; CHARSET_INFO *charset; uint32 srid; uint32 pack_flag; decimal_digits_t decimals; Field::utype unireg_check; Column_definition_attributes() :length(0), interval(NULL), charset(&my_charset_bin), srid(0), pack_flag(0), decimals(0), unireg_check(Field::NONE) { } Column_definition_attributes(const Field *field); Column_definition_attributes(const Type_all_attributes &attr); Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const Record_addr *rec, const Type_handler *handler, const LEX_CSTRING *field_name, uint32 flags) const; uint temporal_dec(uint intlen) const { return (uint) (length > intlen ? length - intlen - 1 : 0); } uint pack_flag_to_pack_length() const; void frm_pack_basic(uchar *buff) const; void frm_pack_charset(uchar *buff) const; void frm_pack_numeric_with_dec(uchar *buff) const; void frm_unpack_basic(const uchar *buff); bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff); bool frm_unpack_numeric_with_dec(TABLE_SHARE *share, const uchar *buff); bool frm_unpack_temporal_with_dec(TABLE_SHARE *share, uint intlen, const uchar *buff); void set_length_and_dec(const Lex_length_and_dec_st &attr); CHARSET_INFO *explicit_or_derived_charset(const Column_derived_attributes *derived_attr) const { return charset ? charset : derived_attr->charset(); } }; /* Create field class for CREATE TABLE */ class Column_definition: public Sql_alloc, public Type_handler_hybrid_field_type, public Column_definition_attributes { /** Create "interval" from "interval_list". @param mem_root - memory root to create the TYPELIB instance and its values on @param reuse_interval_list_values - determines if TYPELIB can reuse strings from interval_list, or should always allocate a copy on mem_root, even if character set conversion is not needed @retval false on success @retval true on error (bad values, or EOM) */ bool create_interval_from_interval_list(MEM_ROOT *mem_root, bool reuse_interval_list_values); /* Calculate TYPELIB (set or enum) max and total lengths @param cs charset+collation pair of the interval @param max_length length of the longest item @param tot_length sum of the item lengths After this method call: - ENUM uses max_length - SET uses tot_length. */ void calculate_interval_lengths(uint32 *max_length, uint32 *tot_length) { const char **pos; uint *len; *max_length= *tot_length= 0; for (pos= interval->type_names, len= interval->type_lengths; *pos ; pos++, len++) { size_t length= charset->numchars(*pos, *pos + *len); DBUG_ASSERT(length < UINT_MAX32); *tot_length+= (uint) length; set_if_bigger(*max_length, (uint32)length); } } bool prepare_stage1_check_typelib_default(); bool prepare_stage1_convert_default(THD *, MEM_ROOT *, CHARSET_INFO *to); const Type_handler *field_type() const; // Prevent using this Compression_method *compression_method_ptr; public: Lex_ident field_name; LEX_CSTRING comment; // Comment for field enum enum_column_versioning { VERSIONING_NOT_SET, WITH_VERSIONING, WITHOUT_VERSIONING }; Item *on_update; // ON UPDATE NOW() field_visibility_t invisible; /* The value of `length' as set by parser: is the number of characters for most of the types, or of bytes for BLOBs or numeric types. */ uint32 char_length; uint flags, pack_length; List<String> interval_list; engine_option_value *option_list; bool explicitly_nullable; /* This is additinal data provided for any computed(virtual) field. In particular it includes a pointer to the item by which this field can be computed from other fields. */ Virtual_column_info *vcol_info, // Virtual field *default_value, // Default value *check_constraint; // Check constraint enum_column_versioning versioning; Table_period_info *period; Column_definition() :Type_handler_hybrid_field_type(&type_handler_null), compression_method_ptr(0), comment(null_clex_str), on_update(NULL), invisible(VISIBLE), char_length(0), flags(0), pack_length(0), option_list(NULL), explicitly_nullable(false), vcol_info(0), default_value(0), check_constraint(0), versioning(VERSIONING_NOT_SET), period(NULL) { interval_list.empty(); } Column_definition(THD *thd, Field *field, Field *orig_field); bool set_attributes(THD *thd, const Lex_field_type_st &attr, column_definition_type_t type); void create_length_to_internal_length_null() { DBUG_ASSERT(length == 0); pack_length= 0; } void create_length_to_internal_length_simple() { pack_length= type_handler()->calc_pack_length((uint32) length); } void create_length_to_internal_length_string() { length*= charset->mbmaxlen; if (real_field_type() == MYSQL_TYPE_VARCHAR && compression_method()) length++; set_if_smaller(length, UINT_MAX32); pack_length= type_handler()->calc_pack_length((uint32) length); } void create_length_to_internal_length_typelib() { /* Pack_length already calculated in sql_parse.cc */ length*= charset->mbmaxlen; } bool vers_sys_field() const { return flags & (VERS_ROW_START | VERS_ROW_END); } void create_length_to_internal_length_bit(); void create_length_to_internal_length_newdecimal(); /* Prepare the "charset" member for string data types, such as CHAR, VARCHAR, TEXT, ENUM, SET: - derive the charset if not specified explicitly - find a _bin collation if the BINARY comparison style was specified, e.g.: CREATE TABLE t1 (a VARCHAR(10) BINARY) CHARSET utf8; */ bool prepare_charset_for_string(Sql_used *used, const Charset_collation_map_st &map, const Column_derived_attributes *dattr); /** Prepare a SET/ENUM field. Create "interval" from "interval_list" if needed, and adjust "length". @param mem_root - Memory root to allocate TYPELIB and its values on @param reuse_interval_list_values - determines if TYPELIB can reuse value buffers from interval_list, or should always allocate a copy on mem_root, even if character set conversion is not needed */ bool prepare_interval_field(MEM_ROOT *mem_root, bool reuse_interval_list_values); void prepare_interval_field_calc_length() { uint32 field_length, dummy; if (real_field_type() == MYSQL_TYPE_SET) { calculate_interval_lengths(&dummy, &field_length); length= field_length + (interval->count - 1); } else /* MYSQL_TYPE_ENUM */ { calculate_interval_lengths(&field_length, &dummy); length= field_length; } set_if_smaller(length, MAX_FIELD_WIDTH - 1); } bool prepare_blob_field(THD *thd); bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root); bool prepare_stage1(THD *thd, MEM_ROOT *mem_root, column_definition_type_t type, const Column_derived_attributes *derived_attr); void prepare_stage1_simple(CHARSET_INFO *cs) { charset= cs; create_length_to_internal_length_simple(); } bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root, column_definition_type_t deftype); bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root); bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root); bool bulk_alter(const Column_derived_attributes *derived_attr, const Column_bulk_alter_attributes *bulk_attr) { return type_handler()->Column_definition_bulk_alter(this, derived_attr, bulk_attr); } void redefine_stage1_common(const Column_definition *dup_field, const handler *file); bool redefine_stage1(const Column_definition *dup_field, const handler *file) { const Type_handler *handler= dup_field->type_handler(); return handler->Column_definition_redefine_stage1(this, dup_field, file); } bool prepare_stage2(handler *handler, ulonglong table_flags); bool prepare_stage2_blob(handler *handler, ulonglong table_flags, uint field_flags); bool prepare_stage2_varchar(ulonglong table_flags); bool prepare_stage2_typelib(const char *type_name, uint field_flags, uint *dup_val_count); uint pack_flag_numeric() const; uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; } bool check_length(uint mysql_errno, uint max_allowed_length) const; bool fix_attributes_real(uint default_length); bool fix_attributes_int(uint default_length); bool fix_attributes_decimal(); bool fix_attributes_temporal_with_time(uint int_part_length); bool fix_attributes_bit(); bool check(THD *thd); bool validate_check_constraint(THD *thd); bool stored_in_db() const { return !vcol_info || vcol_info->is_stored(); } ha_storage_media field_storage_type() const { return (ha_storage_media) ((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3); } column_format_type column_format() const { return (column_format_type) ((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3); } bool has_default_function() const { return unireg_check != Field::NONE; } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const Record_addr *addr, const LEX_CSTRING *field_name_arg) const { return Column_definition_attributes::make_field(share, mem_root, addr, type_handler(), field_name_arg, flags); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *field_name_arg) const { Record_addr addr(true); return make_field(share, mem_root, &addr, field_name_arg); } /* Return true if default is an expression that must be saved explicitly */ bool has_default_expression(); bool has_default_now_unireg_check() const { return unireg_check == Field::TIMESTAMP_DN_FIELD || unireg_check == Field::TIMESTAMP_DNUN_FIELD; } void set_type(const Column_definition &other) { set_handler(other.type_handler()); length= other.length; char_length= other.char_length; decimals= other.decimals; flags= other.flags; pack_length= other.pack_length; unireg_check= other.unireg_check; interval= other.interval; charset= other.charset; srid= other.srid; pack_flag= other.pack_flag; } // Replace the entire value by another definition void set_column_definition(const Column_definition *def) { *this= *def; } bool set_compressed(const char *method); bool set_compressed_deprecated(THD *thd, const char *method); bool set_compressed_deprecated_column_attribute(THD *thd, const char *pos, const char *method); void set_compression_method(Compression_method *compression_method_arg) { compression_method_ptr= compression_method_arg; } Compression_method *compression_method() const { return compression_method_ptr; } bool check_vcol_for_key(THD *thd) const; void set_charset_collation_attrs(Sql_used *used, const Charset_collation_map_st &map, const Lex_column_charset_collation_attrs_st &lc) { charset= lc.charset_info(used, map); if (lc.is_contextually_typed_collation()) flags|= CONTEXT_COLLATION_FLAG; else flags&= ~CONTEXT_COLLATION_FLAG; } Lex_column_charset_collation_attrs charset_collation_attrs() const { if (!charset) return Lex_column_charset_collation_attrs(); if (flags & CONTEXT_COLLATION_FLAG) return Lex_column_charset_collation_attrs(Lex_context_collation(charset)); return Lex_column_charset_collation_attrs(Lex_exact_collation(charset)); } }; /** List of ROW element definitions, e.g.: DECLARE a ROW(a INT,b VARCHAR(10)) */ class Row_definition_list: public List<class Spvar_definition> { public: inline bool eq_name(const Spvar_definition *def, const LEX_CSTRING *name) const; /** Find a ROW field by name. @param [IN] name - the name @param [OUT] offset - if the ROW field found, its offset it returned here @retval NULL - the ROW field was not found @retval !NULL - the pointer to the found ROW field */ Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const { // Cast-off the "const" qualifier List_iterator<Spvar_definition> it(*((List<Spvar_definition>*)this)); Spvar_definition *def; for (*offset= 0; (def= it++); (*offset)++) { if (eq_name(def, name)) return def; } return 0; } static Row_definition_list *make(MEM_ROOT *mem_root, Spvar_definition *var) { Row_definition_list *list; if (!(list= new (mem_root) Row_definition_list())) return NULL; return list->push_back(var, mem_root) ? NULL : list; } bool append_uniq(MEM_ROOT *thd, Spvar_definition *var); bool adjust_formal_params_to_actual_params(THD *thd, List<Item> *args); bool adjust_formal_params_to_actual_params(THD *thd, Item **args, uint arg_count); bool resolve_type_refs(THD *); }; /** This class is used during a stored routine or a trigger execution, at sp_rcontext::create() time. Currently it can represent: - variables with explicit data types: DECLARE a INT; - variables with data type references: DECLARE a t1.a%TYPE; - ROW type variables Notes: - Scalar variables have m_field_definitions==NULL. - ROW variables are defined as having MYSQL_TYPE_NULL, with a non-empty m_field_definitions. Data type references to other object types will be added soon, e.g.: - DECLARE a table_name%ROWTYPE; - DECLARE a cursor_name%ROWTYPE; - DECLARE a record_name%TYPE; - DECLARE a variable_name%TYPE; */ class Spvar_definition: public Column_definition { const Qualified_column_ident *m_column_type_ref; // for %TYPE Table_ident *m_table_rowtype_ref; // for table%ROWTYPE bool m_cursor_rowtype_ref; // for cursor%ROWTYPE uint m_cursor_rowtype_offset; // for cursor%ROWTYPE Row_definition_list *m_row_field_definitions; // for ROW public: Spvar_definition() :m_column_type_ref(NULL), m_table_rowtype_ref(NULL), m_cursor_rowtype_ref(false), m_cursor_rowtype_offset(0), m_row_field_definitions(NULL) { } Spvar_definition(THD *thd, Field *field) :Column_definition(thd, field, NULL), m_column_type_ref(NULL), m_table_rowtype_ref(NULL), m_cursor_rowtype_ref(false), m_cursor_rowtype_offset(0), m_row_field_definitions(NULL) { } const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } bool is_column_type_ref() const { return m_column_type_ref != 0; } bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; } bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; } bool is_explicit_data_type() const { return !is_column_type_ref() && !is_table_rowtype_ref() && !is_cursor_rowtype_ref(); } const Qualified_column_ident *column_type_ref() const { return m_column_type_ref; } void set_column_type_ref(const Qualified_column_ident *ref) { m_column_type_ref= ref; } Table_ident *table_rowtype_ref() const { return m_table_rowtype_ref; } void set_table_rowtype_ref(Table_ident *ref) { DBUG_ASSERT(ref); set_handler(&type_handler_row); m_table_rowtype_ref= ref; } uint cursor_rowtype_offset() const { return m_cursor_rowtype_offset; } void set_cursor_rowtype_ref(uint offset) { set_handler(&type_handler_row); m_cursor_rowtype_ref= true; m_cursor_rowtype_offset= offset; } /* Find a ROW field by name. See Row_field_list::find_row_field_by_name() for details. */ Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const { DBUG_ASSERT(m_row_field_definitions); return m_row_field_definitions->find_row_field_by_name(name, offset); } uint is_row() const { return m_row_field_definitions != NULL; } // Check if "this" defines a ROW variable with n elements uint is_row(uint n) const { return m_row_field_definitions != NULL && m_row_field_definitions->elements == n; } Row_definition_list *row_field_definitions() const { return m_row_field_definitions; } void set_row_field_definitions(Row_definition_list *list) { DBUG_ASSERT(list); set_handler(&type_handler_row); m_row_field_definitions= list; } }; inline bool Row_definition_list::eq_name(const Spvar_definition *def, const LEX_CSTRING *name) const { return def->field_name.length == name->length && my_strcasecmp(system_charset_info, def->field_name.str, name->str) == 0; } class Create_field :public Column_definition { public: LEX_CSTRING change; // Old column name if column is renamed by ALTER LEX_CSTRING after; // Put column after this one Field *field; // For alter table const TYPELIB *save_interval; // Temporary copy for the above // Used only for UCS2 intervals /** structure with parsed options (for comparing fields in ALTER TABLE) */ ha_field_option_struct *option_struct; uint offset; uint8 interval_id; bool create_if_not_exists; // Used in ALTER TABLE IF NOT EXISTS Create_field(): Column_definition(), field(0), option_struct(NULL), create_if_not_exists(false) { change= after= null_clex_str; } Create_field(THD *thd, Field *old_field, Field *orig_field): Column_definition(thd, old_field, orig_field), change(old_field->field_name), field(old_field), option_struct(old_field->option_struct), create_if_not_exists(false) { after= null_clex_str; } /* Used to make a clone of this object for ALTER/CREATE TABLE */ Create_field *clone(MEM_ROOT *mem_root) const; static void upgrade_data_types(List<Create_field> &list) { List_iterator<Create_field> it(list); while (Create_field *f= it++) f->type_handler()->type_handler_for_implicit_upgrade()-> Column_definition_implicit_upgrade_to_this(f); } }; /* A class for sending info to the client */ class Send_field :public Sql_alloc, public Type_handler_hybrid_field_type, public Send_field_extended_metadata { public: LEX_CSTRING db_name; LEX_CSTRING table_name, org_table_name; LEX_CSTRING col_name, org_col_name; ulong length; uint flags; decimal_digits_t decimals; Send_field(Field *field) { field->make_send_field(this); DBUG_ASSERT(table_name.str != 0); normalize(); } Send_field(THD *thd, Item *item); Send_field(Field *field, const LEX_CSTRING &db_name_arg, const LEX_CSTRING &table_name_arg) :Type_handler_hybrid_field_type(field->type_handler()), db_name(db_name_arg), table_name(table_name_arg), org_table_name(table_name_arg), col_name(field->field_name), org_col_name(field->field_name), length(field->field_length), flags(field->table->maybe_null ? (field->flags & ~NOT_NULL_FLAG) : field->flags), decimals(field->decimals()) { normalize(); } private: void normalize() { /* limit number of decimals for float and double */ if (type_handler()->field_type() == MYSQL_TYPE_FLOAT || type_handler()->field_type() == MYSQL_TYPE_DOUBLE) set_if_smaller(decimals, FLOATING_POINT_DECIMALS); } public: // This should move to Type_handler eventually uint32 max_char_length(CHARSET_INFO *cs) const { return type_handler()->field_type() >= MYSQL_TYPE_TINY_BLOB && type_handler()->field_type() <= MYSQL_TYPE_BLOB ? static_cast<uint32>(length / cs->mbminlen) : static_cast<uint32>(length / cs->mbmaxlen); } uint32 max_octet_length(CHARSET_INFO *from, CHARSET_INFO *to) const { /* For TEXT/BLOB columns, field_length describes the maximum data length in bytes. There is no limit to the number of characters that a TEXT column can store, as long as the data fits into the designated space. For the rest of textual columns, field_length is evaluated as char_count * mbmaxlen, where character count is taken from the definition of the column. In other words, the maximum number of characters here is limited by the column definition. When one has a LONG TEXT column with a single-byte character set, and the connection character set is multi-byte, the client may get fields longer than UINT_MAX32, due to <character set column> -> <character set connection> conversion. In that case column max length would not fit into the 4 bytes reserved for it in the protocol. So we cut it here to UINT_MAX32. */ return char_to_byte_length_safe(max_char_length(from), to->mbmaxlen); } // This should move to Type_handler eventually bool is_sane_float() const { return (decimals <= FLOATING_POINT_DECIMALS || (type_handler()->field_type() != MYSQL_TYPE_FLOAT && type_handler()->field_type() != MYSQL_TYPE_DOUBLE)); } bool is_sane_signess() const { if (type_handler() == type_handler()->type_handler_signed() && type_handler() == type_handler()->type_handler_unsigned()) return true; // Any signess is allowed, e.g. DOUBLE, DECIMAL /* We are here e.g. in case of INT data type. The UNSIGNED_FLAG bit must match in flags and in the type handler. */ return ((bool) (flags & UNSIGNED_FLAG)) == type_handler()->is_unsigned(); } bool is_sane() const { return is_sane_float() && is_sane_signess(); } }; /* A class for quick copying data to fields */ class Copy_field :public Sql_alloc { public: uchar *from_ptr,*to_ptr; uchar *from_null_ptr,*to_null_ptr; bool *null_row; uint from_bit,to_bit; /** Number of bytes in the fields pointed to by 'from_ptr' and 'to_ptr'. Usually this is the number of bytes that are copied from 'from_ptr' to 'to_ptr'. For variable-length fields (VARCHAR), the first byte(s) describe the actual length of the text. For VARCHARs with length < 256 there is 1 length byte >= 256 there is 2 length bytes Thus, if from_field is VARCHAR(10), from_length (and in most cases to_length) is 11. For VARCHAR(1024), the length is 1026. @see Field_varstring::length_bytes Note that for VARCHARs, do_copy() will be do_varstring*() which only copies the length-bytes (1 or 2) + the actual length of the text instead of from/to_length bytes. */ uint from_length,to_length; Field *from_field,*to_field; mutable String tmp; // For items Copy_field() = default; ~Copy_field() = default; void set(Field *to,Field *from,bool save); // Field to field void set(uchar *to,Field *from); // Field to string void (*do_copy)(const Copy_field *); void (*do_copy2)(const Copy_field *); // Used to handle null values }; uint pack_length_to_packflag(uint type); enum_field_types get_blob_type_from_length(ulong length); int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); int convert_null_to_field_value_or_error(Field *field, uint err); bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name, enum_vcol_info_type type, Alter_info *alter_info= NULL); /* The following are for the interface with the .frm file */ #define FIELDFLAG_DECIMAL 1U #define FIELDFLAG_BINARY 1U // Shares same flag #define FIELDFLAG_NUMBER 2U #define FIELDFLAG_ZEROFILL 4U #define FIELDFLAG_PACK 120U // Bits used for packing #define FIELDFLAG_INTERVAL 256U // mangled with decimals! #define FIELDFLAG_BITFIELD 512U // mangled with decimals! #define FIELDFLAG_BLOB 1024U // mangled with decimals! #define FIELDFLAG_GEOM 2048U // mangled with decimals! #define FIELDFLAG_TREAT_BIT_AS_CHAR 4096U /* use Field_bit_as_char */ #define FIELDFLAG_LONG_DECIMAL 8192U #define FIELDFLAG_NO_DEFAULT 16384U /* sql */ #define FIELDFLAG_MAYBE_NULL 32768U // sql #define FIELDFLAG_HEX_ESCAPE 0x10000U #define FIELDFLAG_PACK_SHIFT 3 #define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_MAX_DEC 63U #define FIELDFLAG_DEC_MASK 0x3F00U #define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type #define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL) #define f_is_num(x) ((x) & FIELDFLAG_NUMBER) #define f_is_zerofill(x) ((x) & FIELDFLAG_ZEROFILL) #define f_is_packed(x) ((x) & FIELDFLAG_PACK) #define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15) #define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC)) #define f_is_alpha(x) (!f_is_num(x)) #define f_is_binary(x) ((x) & FIELDFLAG_BINARY) // 4.0- compatibility #define f_is_enum(x) (((x) & (FIELDFLAG_INTERVAL | FIELDFLAG_NUMBER)) == FIELDFLAG_INTERVAL) #define f_is_bitfield(x) (((x) & (FIELDFLAG_BITFIELD | FIELDFLAG_NUMBER)) == FIELDFLAG_BITFIELD) #define f_is_blob(x) (((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB) #define f_is_geom(x) (((x) & (FIELDFLAG_GEOM | FIELDFLAG_NUMBER)) == FIELDFLAG_GEOM) #define f_settype(x) (((uint) (x)) << FIELDFLAG_PACK_SHIFT) #define f_maybe_null(x) ((x) & FIELDFLAG_MAYBE_NULL) #define f_no_default(x) ((x) & FIELDFLAG_NO_DEFAULT) #define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR) #define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE) #define f_visibility(x) (static_cast<field_visibility_t> ((x) & INVISIBLE_MAX_BITS)) inline ulonglong TABLE::vers_end_id(const uchar *record_arg) const { DBUG_ASSERT(versioned(VERS_TRX_ID)); DBUG_ASSERT(dynamic_cast<Field_longlong*>(vers_end_field())); const uchar *ptr= vers_end_field()->ptr_in_record(record_arg); return static_cast<ulonglong>(sint8korr(ptr)); } inline ulonglong TABLE::vers_start_id(const uchar *record_arg) const { DBUG_ASSERT(versioned(VERS_TRX_ID)); DBUG_ASSERT(dynamic_cast<Field_longlong*>(vers_start_field())); const uchar *ptr= vers_start_field()->ptr_in_record(record_arg); return static_cast<ulonglong>(sint8korr(ptr)); } double pos_in_interval_for_string(CHARSET_INFO *cset, const uchar *midp_val, uint32 midp_len, const uchar *min_val, uint32 min_len, const uchar *max_val, uint32 max_len); double pos_in_interval_for_double(double midp_val, double min_val, double max_val); #endif /* FIELD_INCLUDED */ sql_cte.h 0000644 00000040156 15156036125 0006361 0 ustar 00 /* Copyright (c) 2016, 2017 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_CTE_INCLUDED #define SQL_CTE_INCLUDED #include "sql_list.h" #include "sql_lex.h" #include "sql_select.h" class select_unit; struct st_unit_ctxt_elem; /** @class With_element_head @brief Head of the definition of a CTE table It contains the name of the CTE and it contains the position of the subchain of table references used in the definition in the global chain of table references used in the query where this definition is encountered. */ class With_element_head : public Sql_alloc { /* The name of the defined CTE */ LEX_CSTRING *query_name; public: /* The structure describing the subchain of the table references used in the specification of the defined CTE in the global chain of table references used in the query. The structure is fully defined only after the CTE definition has been parsed. */ TABLE_CHAIN tables_pos; With_element_head(LEX_CSTRING *name) : query_name(name) { tables_pos.set_start_pos(0); tables_pos.set_end_pos(0); } friend class With_element; }; /** @class With_element @brief Definition of a CTE table It contains a reference to the name of the table introduced by this with element, and a reference to the unit that specificies this table. Also it contains a reference to the with clause to which this element belongs to. */ class With_element : public Sql_alloc { private: With_clause *owner; // with clause this object belongs to With_element *next; // next element in the with clause uint number; // number of the element in the with clause (starting from 0) table_map elem_map; // The map where with only one 1 set in this->number /* The map base_dep_map has 1 in the i-th position if the query that specifies this with element contains a reference to the with element number i in the query FROM list. (In this case this with element depends directly on the i-th with element.) */ table_map base_dep_map; /* The map derived_dep_map has 1 in i-th position if this with element depends directly or indirectly from the i-th with element. */ table_map derived_dep_map; /* The map sq_dep_map has 1 in i-th position if there is a reference to this with element somewhere in subqueries of the specifications of the tables defined in the with clause containing this element; */ table_map sq_dep_map; table_map work_dep_map; // dependency map used for work /* Dependency map of with elements mutually recursive with this with element */ table_map mutually_recursive; /* Dependency map built only for the top level references i.e. for those that are encountered in from lists of the selects of the specification unit */ table_map top_level_dep_map; /* Points to a recursive reference in subqueries. Used only for specifications without recursive references on the top level. */ TABLE_LIST *sq_rec_ref; /* The next with element from the circular chain of the with elements mutually recursive with this with element. (If This element is simply recursive than next_mutually_recursive contains the pointer to itself. If it's not recursive than next_mutually_recursive is set to NULL.) */ With_element *next_mutually_recursive; /* Total number of references to this element in the FROM lists of the queries that are in the scope of the element (including subqueries and specifications of other with elements). */ uint references; /* true <=> this With_element is referred in the query in which the element is defined */ bool referenced; /* true <=> this With_element is needed for the execution of the query in which the element is defined */ bool is_used_in_query; /* Unparsed specification of the query that specifies this element. It's used to build clones of the specification if they are needed. */ LEX_CSTRING unparsed_spec; /* Offset of the specification in the input string */ my_ptrdiff_t unparsed_spec_offset; /* True if the with element is used a prepared statement */ bool stmt_prepare_mode; /* Return the map where 1 is set only in the position for this element */ table_map get_elem_map() { return (table_map) 1 << number; } public: /* Contains the name of the defined With element and the position of the subchain of the tables references used by its definition in the global chain of TABLE_LIST objects created for the whole query. */ With_element_head *head; /* Optional list of column names to name the columns of the table introduced by this with element. It is used in the case when the names are not inherited from the query that specified the table. Otherwise the list is always empty. */ List <Lex_ident_sys> column_list; List <Lex_ident_sys> *cycle_list; /* The query that specifies the table introduced by this with element */ st_select_lex_unit *spec; /* Set to true is recursion is used (directly or indirectly) for the definition of this element */ bool is_recursive; /* For a simple recursive CTE: the number of references to the CTE from outside of the CTE specification. For a CTE mutually recursive with other CTEs : the total number of references to all these CTEs outside of their specification. Each of these mutually recursive CTEs has the same value in this field. */ uint rec_outer_references; /* Any non-recursive select in the specification of a recursive with element is a called anchor. In the case mutually recursive elements the specification of some them may be without any anchor. Yet at least one of them must contain an anchor. All anchors of any recursivespecification are moved ahead before the prepare stage. */ /* Set to true if this is a recursive element with an anchor */ bool with_anchor; /* Set to the first recursive select of the unit specifying the element after all anchor have been moved to the head of the unit. */ st_select_lex *first_recursive; /* The number of the last performed iteration for recursive table (the number of the initial non-recursive step is 0, the number of the first iteration is 1). */ uint level; /* The pointer to the object used to materialize this with element if it's recursive. This object is built at the end of prepare stage and is used at the execution stage. */ select_union_recursive *rec_result; /* List of Item_subselects containing recursive references to this CTE */ SQL_I_List<Item_subselect> sq_with_rec_ref; /* List of derived tables containing recursive references to this CTE */ SQL_I_List<TABLE_LIST> derived_with_rec_ref; With_element(With_element_head *h, List <Lex_ident_sys> list, st_select_lex_unit *unit) : next(NULL), base_dep_map(0), derived_dep_map(0), sq_dep_map(0), work_dep_map(0), mutually_recursive(0), top_level_dep_map(0), sq_rec_ref(NULL), next_mutually_recursive(NULL), references(0), referenced(false), is_used_in_query(false), head(h), column_list(list), cycle_list(0), spec(unit), is_recursive(false), rec_outer_references(0), with_anchor(false), level(0), rec_result(NULL) { unit->with_element= this; } LEX_CSTRING *get_name() { return head->query_name; } const char *get_name_str() { return get_name()->str; } void set_tables_start_pos(TABLE_LIST **pos) { head->tables_pos.set_start_pos(pos); } void set_tables_end_pos(TABLE_LIST **pos) { head->tables_pos.set_end_pos(pos); } bool check_dependencies_in_spec(); void check_dependencies_in_select(st_select_lex *sl, st_unit_ctxt_elem *ctxt, bool in_subq, table_map *dep_map); void check_dependencies_in_unit(st_select_lex_unit *unit, st_unit_ctxt_elem *ctxt, bool in_subq, table_map *dep_map); void check_dependencies_in_with_clause(With_clause *with_clause, st_unit_ctxt_elem *ctxt, bool in_subq, table_map *dep_map); void set_dependency_on(With_element *with_elem) { base_dep_map|= with_elem->get_elem_map(); } bool check_dependency_on(With_element *with_elem) { return base_dep_map & with_elem->get_elem_map(); } TABLE_LIST *find_first_sq_rec_ref_in_select(st_select_lex *sel); bool set_unparsed_spec(THD *thd, const char *spec_start, const char *spec_end, my_ptrdiff_t spec_offset); st_select_lex_unit *clone_parsed_spec(LEX *old_lex, TABLE_LIST *with_table); bool is_referenced() { return referenced; } bool is_hanging_recursive() { return is_recursive && !rec_outer_references; } void inc_references() { references++; } bool process_columns_of_derived_unit(THD *thd, st_select_lex_unit *unit); bool prepare_unreferenced(THD *thd); bool check_unrestricted_recursive(st_select_lex *sel, table_map &unrestricted, table_map &encountered); void print(THD *thd, String *str, enum_query_type query_type); With_clause *get_owner() { return owner; } bool contains_sq_with_recursive_reference() { return sq_dep_map & mutually_recursive; } bool no_rec_ref_on_top_level() { return !(top_level_dep_map & mutually_recursive); } table_map get_mutually_recursive() { return mutually_recursive; } With_element *get_next_mutually_recursive() { return next_mutually_recursive; } TABLE_LIST *get_sq_rec_ref() { return sq_rec_ref; } bool is_anchor(st_select_lex *sel); void move_anchors_ahead(); bool is_unrestricted(); bool is_with_prepared_anchor(); void mark_as_with_prepared_anchor(); bool is_cleaned(); void mark_as_cleaned(); void reset_recursive_for_exec(); void cleanup_stabilized(); void set_as_stabilized(); bool is_stabilized(); bool all_are_stabilized(); bool instantiate_tmp_tables(); void prepare_for_next_iteration(); void set_cycle_list(List<Lex_ident_sys> *cycle_list_arg); friend class With_clause; friend bool LEX::resolve_references_to_cte(TABLE_LIST *tables, TABLE_LIST **tables_last, st_select_lex_unit *excl_spec); }; const uint max_number_of_elements_in_with_clause= sizeof(table_map)*8; /** @class With_clause @brief Set of with_elements It has a reference to the first with element from this with clause. This reference allows to navigate through all the elements of the with clause. It contains a reference to the unit to which this with clause is attached. It also contains a flag saying whether this with clause was specified as recursive. */ class With_clause : public Sql_alloc { private: st_select_lex_unit *owner; // the unit this with clause attached to /* The list of all with elements from this with clause */ SQL_I_List<With_element> with_list; /* The with clause immediately containing this with clause if there is any, otherwise NULL. Now used only at parsing. */ With_clause *embedding_with_clause; /* The next with the clause of the chain of with clauses encountered in the current statement */ With_clause *next_with_clause; /* Set to true if dependencies between with elements have been checked */ bool dependencies_are_checked; /* The bitmap of all recursive with elements whose specifications are not complied with restrictions imposed by the SQL standards on recursive specifications. */ table_map unrestricted; /* The bitmap of all recursive with elements whose anchors has been already prepared. */ table_map with_prepared_anchor; table_map cleaned; /* The bitmap of all recursive with elements that has been already materialized */ table_map stabilized; public: /* If true the specifier RECURSIVE is present in the with clause */ bool with_recursive; With_clause(bool recursive_fl, With_clause *emb_with_clause) : owner(NULL), embedding_with_clause(emb_with_clause), next_with_clause(NULL), dependencies_are_checked(false), unrestricted(0), with_prepared_anchor(0), cleaned(0), stabilized(0), with_recursive(recursive_fl) { } bool add_with_element(With_element *elem); /* Add this with clause to the list of with clauses used in the statement */ void add_to_list(With_clause **ptr, With_clause ** &last_next) { if (embedding_with_clause) { /* An embedded with clause is always placed before the embedding one in the list of with clauses used in the query. */ while (*ptr != embedding_with_clause) ptr= &(*ptr)->next_with_clause; *ptr= this; next_with_clause= embedding_with_clause; } else { *last_next= this; last_next= &this->next_with_clause; } } st_select_lex_unit *get_owner() { return owner; } void set_owner(st_select_lex_unit *unit) { owner= unit; } void attach_to(st_select_lex *select_lex); With_clause *pop() { return embedding_with_clause; } bool check_dependencies(); bool check_anchors(); void move_anchors_ahead(); With_element *find_table_def(TABLE_LIST *table, With_element *barrier, st_select_lex_unit *excl_spec); With_element *find_table_def_in_with_clauses(TABLE_LIST *table); bool prepare_unreferenced_elements(THD *thd); void add_unrestricted(table_map map) { unrestricted|= map; } void print(THD *thd, String *str, enum_query_type query_type); friend class With_element; friend struct LEX; }; inline bool With_element::is_unrestricted() { return owner->unrestricted & get_elem_map(); } inline bool With_element::is_with_prepared_anchor() { return owner->with_prepared_anchor & get_elem_map(); } inline void With_element::mark_as_with_prepared_anchor() { owner->with_prepared_anchor|= mutually_recursive; } inline bool With_element::is_cleaned() { return owner->cleaned & get_elem_map(); } inline void With_element::mark_as_cleaned() { owner->cleaned|= get_elem_map(); } inline void With_element::reset_recursive_for_exec() { DBUG_ASSERT(is_recursive); level= 0; owner->with_prepared_anchor&= ~mutually_recursive; owner->cleaned&= ~get_elem_map(); cleanup_stabilized(); spec->columns_are_renamed= false; } inline void With_element::cleanup_stabilized() { owner->stabilized&= ~mutually_recursive; } inline void With_element::set_as_stabilized() { owner->stabilized|= get_elem_map(); } inline bool With_element::is_stabilized() { return owner->stabilized & get_elem_map(); } inline bool With_element::all_are_stabilized() { return (owner->stabilized & mutually_recursive) == mutually_recursive; } inline void With_element::prepare_for_next_iteration() { With_element *with_elem= this; while ((with_elem= with_elem->get_next_mutually_recursive()) != this) { TABLE *rec_table= with_elem->rec_result->first_rec_table_to_update; if (rec_table) rec_table->reginfo.join_tab->preread_init_done= false; } } inline void With_clause::attach_to(st_select_lex *select_lex) { for (With_element *with_elem= with_list.first; with_elem; with_elem= with_elem->next) { select_lex->register_unit(with_elem->spec, NULL); } } inline void st_select_lex::set_with_clause(With_clause *with_clause) { master_unit()->with_clause= with_clause; if (with_clause) with_clause->set_owner(master_unit()); } #endif /* SQL_CTE_INCLUDED */ hash_filo.h 0000644 00000013070 15156036125 0006656 0 ustar 00 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* ** A class for static sized hash tables where old entries are deleted in ** first-in-last-out to usage. */ #ifndef HASH_FILO_H #define HASH_FILO_H #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class interface */ #endif #include "hash.h" /* my_hash_get_key, my_hash_free_key, HASH */ #include "m_string.h" /* bzero */ #include "mysqld.h" /* key_hash_filo_lock */ class hash_filo_element { private: hash_filo_element *next_used,*prev_used; public: hash_filo_element() = default; hash_filo_element *next() { return next_used; } hash_filo_element *prev() { return prev_used; } friend class hash_filo; }; class hash_filo { private: PSI_memory_key m_psi_key; const uint key_offset, key_length; const my_hash_get_key get_key; /** Size of this hash table. */ uint m_size; my_hash_free_key free_element; bool init; CHARSET_INFO *hash_charset; hash_filo_element *first_link,*last_link; public: mysql_mutex_t lock; HASH cache; hash_filo(PSI_memory_key psi_key, uint size_arg, uint key_offset_arg, uint key_length_arg, my_hash_get_key get_key_arg, my_hash_free_key free_element_arg, CHARSET_INFO *hash_charset_arg) : m_psi_key(psi_key), key_offset(key_offset_arg), key_length(key_length_arg), get_key(get_key_arg), m_size(size_arg), free_element(free_element_arg),init(0), hash_charset(hash_charset_arg), first_link(NULL), last_link(NULL) { bzero((char*) &cache,sizeof(cache)); } ~hash_filo() { if (init) { if (cache.array.buffer) /* Avoid problems with thread library */ (void) my_hash_free(&cache); mysql_mutex_destroy(&lock); } } void clear(bool locked=0) { if (!init) { init=1; mysql_mutex_init(key_hash_filo_lock, &lock, MY_MUTEX_INIT_FAST); } if (!locked) mysql_mutex_lock(&lock); first_link= NULL; last_link= NULL; (void) my_hash_free(&cache); (void) my_hash_init(m_psi_key, &cache,hash_charset,m_size,key_offset, key_length, get_key, free_element, 0); if (!locked) mysql_mutex_unlock(&lock); } hash_filo_element *first() { mysql_mutex_assert_owner(&lock); return first_link; } hash_filo_element *last() { mysql_mutex_assert_owner(&lock); return last_link; } hash_filo_element *search(uchar* key, size_t length) { mysql_mutex_assert_owner(&lock); hash_filo_element *entry=(hash_filo_element*) my_hash_search(&cache,(uchar*) key,length); if (entry) { // Found; link it first DBUG_ASSERT(first_link != NULL); DBUG_ASSERT(last_link != NULL); if (entry != first_link) { // Relink used-chain if (entry == last_link) { last_link= last_link->prev_used; /* The list must have at least 2 elements, otherwise entry would be equal to first_link. */ DBUG_ASSERT(last_link != NULL); last_link->next_used= NULL; } else { DBUG_ASSERT(entry->next_used != NULL); DBUG_ASSERT(entry->prev_used != NULL); entry->next_used->prev_used = entry->prev_used; entry->prev_used->next_used = entry->next_used; } entry->prev_used= NULL; entry->next_used= first_link; first_link->prev_used= entry; first_link=entry; } } return entry; } bool add(hash_filo_element *entry) { if (!m_size) return 1; if (cache.records == m_size) { hash_filo_element *tmp=last_link; last_link= last_link->prev_used; if (last_link != NULL) { last_link->next_used= NULL; } else { /* Pathological case, m_size == 1 */ first_link= NULL; } my_hash_delete(&cache,(uchar*) tmp); } if (my_hash_insert(&cache,(uchar*) entry)) { if (free_element) (*free_element)(entry); // This should never happen return 1; } entry->prev_used= NULL; entry->next_used= first_link; if (first_link != NULL) first_link->prev_used= entry; else last_link= entry; first_link= entry; return 0; } uint size() { return m_size; } void resize(uint new_size) { mysql_mutex_lock(&lock); m_size= new_size; clear(true); mysql_mutex_unlock(&lock); } }; template <class T> class Hash_filo: public hash_filo { public: Hash_filo(PSI_memory_key psi_key, uint size_arg, uint key_offset_arg, uint key_length_arg, my_hash_get_key get_key_arg, my_hash_free_key free_element_arg, CHARSET_INFO *hash_charset_arg) : hash_filo(psi_key, size_arg, key_offset_arg, key_length_arg, get_key_arg, free_element_arg, hash_charset_arg) {} T* first() { return (T*)hash_filo::first(); } T* last() { return (T*)hash_filo::last(); } T* search(uchar* key, size_t len) { return (T*)hash_filo::search(key, len); } }; #endif rpl_mi.h 0000644 00000040446 15156036125 0006213 0 ustar 00 /* Copyright (c) 2006, 2012, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_MI_H #define RPL_MI_H #ifdef HAVE_REPLICATION #include "rpl_rli.h" #include "rpl_reporting.h" #include <my_sys.h> #include "rpl_filter.h" #include "keycaches.h" typedef struct st_mysql MYSQL; /** Domain id based filter to handle DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS used to set filtering on replication slave based on event's GTID domain_id. */ class Domain_id_filter { private: /* Flag to tell whether the events in the current GTID group get written to the relay log. It is set according to the domain_id based filtering rule on every GTID_EVENT and reset at the end of current GTID event group. */ bool m_filter; public: /* domain id list types */ enum enum_list_type { DO_DOMAIN_IDS= 0, IGNORE_DOMAIN_IDS }; /* DO_DOMAIN_IDS (0): Ignore all the events which do not belong to any of the domain ids in the list. IGNORE_DOMAIN_IDS (1): Ignore the events which belong to one of the domain ids in the list. */ DYNAMIC_ARRAY m_domain_ids[2]; Domain_id_filter(); ~Domain_id_filter(); /* Returns whether the current group needs to be filtered. */ bool is_group_filtered() { return m_filter; } /* Checks whether the group with the specified domain_id needs to be filtered and updates m_filter flag accordingly. */ void do_filter(ulong domain_id); /* Reset m_filter. It should be called when IO thread receives COMMIT_EVENT or XID_EVENT. */ void reset_filter(); /* Clear do_ids and ignore_ids to disable domain id filtering */ void clear_ids(); /* Update the do/ignore domain id filter lists. @param do_ids [IN] domain ids to be kept @param ignore_ids [IN] domain ids to be filtered out @param using_gtid [IN] use GTID? @retval false Success true Error */ bool update_ids(DYNAMIC_ARRAY *do_ids, DYNAMIC_ARRAY *ignore_ids, bool using_gtid); /* Serialize and store the ids from domain id lists into the thd's protocol buffer. @param thd [IN] thread handler @retval void */ void store_ids(THD *thd); /* Initialize the given domain id list (DYNAMIC_ARRAY) with the space-separated list of numbers from the specified IO_CACHE where the first number is the total number of entries to follows. @param f [IN] IO_CACHE file @param type [IN] domain id list type @retval false Success true Error */ bool init_ids(IO_CACHE *f, enum_list_type type); /* Return the elements of the give domain id list type as string. @param type [IN] domain id list type @retval a string buffer storing the total number of elements followed by the individual elements (space-separated) in the specified list. Note: Its caller's responsibility to free the returned string buffer. */ char *as_string(enum_list_type type); }; extern TYPELIB slave_parallel_mode_typelib; typedef struct st_rows_event_tracker { char binlog_file_name[FN_REFLEN]; my_off_t first_seen; my_off_t last_seen; bool stmt_end_seen; void update(const char *file_name, my_off_t pos, const uchar *buf, const Format_description_log_event *fdle); void reset(); bool check_and_report(const char* file_name, my_off_t pos); } Rows_event_tracker; /***************************************************************************** Replication IO Thread Master_info contains: - information about how to connect to a master - current master log name - current master log offset - misc control variables Master_info is initialized once from the master.info file if such exists. Otherwise, data members corresponding to master.info fields are initialized with defaults specified by master-* options. The initialization is done through init_master_info() call. The format of master.info file: log_name log_pos master_host master_user master_pass master_port master_connect_retry To write out the contents of master.info file to disk ( needed every time we read and queue data from the master ), a call to flush_master_info() is required. To clean up, call end_master_info() *****************************************************************************/ class Master_info : public Slave_reporting_capability { public: enum enum_using_gtid { USE_GTID_NO= 0, USE_GTID_CURRENT_POS= 1, USE_GTID_SLAVE_POS= 2 }; Master_info(LEX_CSTRING *connection_name, bool is_slave_recovery); ~Master_info(); bool shall_ignore_server_id(ulong s_id); void clear_in_memory_info(bool all); bool error() { /* If malloc() in initialization failed */ return connection_name.str == 0; } static const char *using_gtid_astext(enum enum_using_gtid arg); bool using_parallel() { return opt_slave_parallel_threads > 0 && parallel_mode > SLAVE_PARALLEL_NONE; } void release(); void wait_until_free(); void lock_slave_threads(); void unlock_slave_threads(); ulonglong get_slave_skip_counter() { return rli.slave_skip_counter; } ulonglong get_max_relay_log_size() { return rli.max_relay_log_size; } /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN+6]; /* Room for multi-*/ char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1]; char user[USERNAME_LENGTH+1]; char password[MAX_PASSWORD_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1]; LEX_CSTRING connection_name; /* User supplied connection name */ LEX_CSTRING cmp_connection_name; /* Connection name in lower case */ bool ssl; // enables use of SSL connection if true char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN]; char ssl_crl[FN_REFLEN], ssl_crlpath[FN_REFLEN]; my_bool ssl_verify_server_cert; /* MUST be my_bool, see mysql_option() */ my_off_t master_log_pos; File fd; // we keep the file open, so we need to remember the file pointer IO_CACHE file; mysql_mutex_t data_lock, run_lock, sleep_lock, start_stop_lock, start_alter_lock, start_alter_list_lock; mysql_cond_t data_cond, start_cond, stop_cond, sleep_cond; THD *io_thd; MYSQL* mysql; uint32 file_id; /* for 3.23 load data infile */ Relay_log_info rli; uint port; Rpl_filter* rpl_filter; /* Each replication can set its filter rule*/ /* to hold checksum alg in use until IO thread has received FD. Initialized to novalue, then set to the queried from master @@global.binlog_checksum and deactivated once FD has been received. */ enum_binlog_checksum_alg checksum_alg_before_fd; uint connect_retry; #ifndef DBUG_OFF int events_till_disconnect; /* The following are auxiliary DBUG variables used to kill IO thread in the middle of a group/transaction (see "kill_slave_io_after_2_events"). */ bool dbug_do_disconnect; int dbug_event_counter; #endif bool inited; volatile bool abort_slave; volatile uint slave_running; volatile ulong slave_run_id; /* The difference in seconds between the clock of the master and the clock of the slave (second - first). It must be signed as it may be <0 or >0. clock_diff_with_master is computed when the I/O thread starts; for this the I/O thread does a SELECT UNIX_TIMESTAMP() on the master. "how late the slave is compared to the master" is computed like this: clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master */ long clock_diff_with_master; /* Keeps track of the number of events before fsyncing. The option --sync-master-info determines how many events should happen before fsyncing. */ uint sync_counter; float heartbeat_period; // interface with CHANGE MASTER or master.info ulonglong received_heartbeats; // counter of received heartbeat events DYNAMIC_ARRAY ignore_server_ids; ulong master_id; /* At reconnect and until the first rotate event is seen, prev_master_id is the value of master_id during the previous connection, used to detect silent change of master server during reconnects. */ ulong prev_master_id; /* Which kind of GTID position (if any) is used when connecting to master. Note that you can not change the numeric values of these, they are used in master.info. */ enum enum_using_gtid using_gtid; /* This GTID position records how far we have fetched into the relay logs. This is used to continue fetching when the IO thread reconnects to the master. (Full slave stop/start does not use it, as it resets the relay logs). */ slave_connection_state gtid_current_pos; /* If events_queued_since_last_gtid is non-zero, it is the number of events queued so far in the relaylog of a GTID-prefixed event group. It is zero when no partial event group has been queued at the moment. */ uint64 events_queued_since_last_gtid; /* The GTID of the partially-queued event group, when events_queued_since_last_gtid is non-zero. */ rpl_gtid last_queued_gtid; /* Whether last_queued_gtid had the FL_STANDALONE flag set. */ bool last_queued_gtid_standalone; /* When slave IO thread needs to reconnect, gtid_reconnect_event_skip_count counts number of events to skip from the first GTID-prefixed event group, to avoid duplicating events in the relay log. */ uint64 gtid_reconnect_event_skip_count; /* gtid_event_seen is false until we receive first GTID event from master. */ bool gtid_event_seen; /** The struct holds some history of Rows- log-event reading/queuing by the receiver thread. Its fields are updated per each such event at time of queue_event(), and they are checked to detect the Rows- event group integrity violation at time of first non-Rows- event gets handled. */ Rows_event_tracker rows_event_tracker; bool in_start_all_slaves, in_stop_all_slaves; bool in_flush_all_relay_logs; uint users; /* Active user for object */ uint killed; /* No of DDL event group */ Atomic_counter<uint64> total_ddl_groups; /* No of non-transactional event group*/ Atomic_counter<uint64> total_non_trans_groups; /* No of transactional event group*/ Atomic_counter<uint64> total_trans_groups; /* domain-id based filter */ Domain_id_filter domain_id_filter; /* The parallel replication mode. */ enum_slave_parallel_mode parallel_mode; /* semi_ack is used to identify if the current binlog event needs an ACK from slave, or if delay_master is enabled. */ int semi_ack; /* The flag has replicate_same_server_id semantics and is raised to accept a same-server-id event group by the gtid strict mode semisync slave. Own server-id events can normally appear as result of EITHER A. this server semisync (failover to) slave crash-recovery: the transaction was created on this server then being master, got replicated elsewhere right before the crash before commit, and finally at recovery the transaction gets evicted from the server's binlog and its gtid (slave) state; OR B. in a general circular configuration and then when a recieved (returned to slave) gtid exists in the server's binlog. Then, in gtid strict mode, it must be ignored similarly to the replicate-same-server-id rule. */ bool do_accept_own_server_id= false; /* Set to 1 when semi_sync is enabled. Set to 0 if there is any transmit problems to the slave, in which case any furter semi-sync reply is ignored */ bool semi_sync_reply_enabled; List <start_alter_info> start_alter_list; MEM_ROOT mem_root; /* Flag is raised at the parallel worker slave stop. Its purpose is to mark the whole start_alter_list when slave stops. The flag is read by Start Alter event to self-mark its state accordingly at time its alter info struct is about to be appened to the list. */ bool is_shutdown= false; /* A replica will default to Slave_Pos for using Using_Gtid; however, we first need to test if the master supports GTIDs. If not, fall back to 'No'. Cache the value so future RESET SLAVE commands don't revert to Slave_Pos. */ bool master_supports_gtid= true; /* When TRUE, transition this server from being an active master to a slave. This updates the replication state to account for any transactions which were committed into the binary log. In particular, it merges gtid_binlog_pos into gtid_slave_pos. */ bool is_demotion= false; }; struct start_alter_thd_args { rpl_group_info *rgi; LEX_CSTRING query; LEX_CSTRING *db; char *catalog; bool shutdown; CHARSET_INFO *cs; }; int init_master_info(Master_info* mi, const char* master_info_fname, const char* slave_info_fname, bool abort_if_no_master_info_file, int thread_mask); void end_master_info(Master_info* mi); int flush_master_info(Master_info* mi, bool flush_relay_log_cache, bool need_lock_relay_log); void copy_filter_setting(Rpl_filter* dst_filter, Rpl_filter* src_filter); void update_change_master_ids(DYNAMIC_ARRAY *new_ids, DYNAMIC_ARRAY *old_ids); void prot_store_ids(THD *thd, DYNAMIC_ARRAY *ids); /* Multi master are handled trough this struct. Changes to this needs to be protected by LOCK_active_mi; */ class Master_info_index { private: IO_CACHE index_file; char index_file_name[FN_REFLEN]; public: Master_info_index(); ~Master_info_index(); HASH master_info_hash; bool init_all_master_info(); bool write_master_name_to_index_file(LEX_CSTRING *connection_name, bool do_sync); bool check_duplicate_master_info(LEX_CSTRING *connection_name, const char *host, uint port); bool add_master_info(Master_info *mi, bool write_to_file); bool remove_master_info(Master_info *mi, bool clear_log_files); Master_info *get_master_info(const LEX_CSTRING *connection_name, Sql_condition::enum_warning_level warning); bool start_all_slaves(THD *thd); bool stop_all_slaves(THD *thd); void free_connections(); bool flush_all_relay_logs(); }; /* The class rpl_io_thread_info is the THD::system_thread_info for the IO thread. */ class rpl_io_thread_info { public: }; Master_info *get_master_info(const LEX_CSTRING *connection_name, Sql_condition::enum_warning_level warning); bool check_master_connection_name(LEX_CSTRING *name); void create_logfile_name_with_suffix(char *res_file_name, size_t length, const char *info_file, bool append, LEX_CSTRING *suffix); uchar *get_key_master_info(Master_info *mi, size_t *length, my_bool not_used __attribute__((unused))); void free_key_master_info(Master_info *mi); uint any_slave_sql_running(bool already_locked); bool give_error_if_slave_running(bool already_lock); /* Sets up the basic options for a MYSQL connection, mysql, to connect to the primary server described by the Master_info parameter, mi. The timeout must be passed explicitly, as different types of connections created by the slave will use different values. Assumes mysql_init() has already been called on the mysql connection object. */ void setup_mysql_connection_for_master(MYSQL *mysql, Master_info *mi, uint timeout); #endif /* HAVE_REPLICATION */ #endif /* RPL_MI_H */ ha_handler_stats.h 0000644 00000004437 15156036125 0010234 0 ustar 00 #ifndef HA_HANDLER_STATS_INCLUDED #define HA_HANDLER_STATS_INCLUDED /* Copyright (c) 2023, MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Definitions for parameters to do with handler-routines */ class ha_handler_stats { public: ulonglong pages_accessed; /* Pages accessed from page cache */ ulonglong pages_updated; /* Pages changed in page cache */ ulonglong pages_read_count; /* Pages read from disk */ /* Time spent reading pages, in timer_tracker_frequency() units */ ulonglong pages_read_time; /* Number of pages that we've requested to prefetch while running the query. Note that we don't know: - how much time was spent reading these pages (and how to count the time if reading was done in parallel) - whether the pages were read by "us" or somebody else... */ ulonglong pages_prefetched; ulonglong undo_records_read; /* Time spent in engine, in timer_tracker_frequency() units */ ulonglong engine_time; uint active; /* <> 0 if status has to be updated */ ha_handler_stats() { active= 0; } #define first_stat pages_accessed #define last_stat engine_time inline void reset() { bzero((void*) this, sizeof(*this)); } inline void add(ha_handler_stats *stats) { ulonglong *to= &first_stat; ulonglong *from= &stats->first_stat; do { (*to)+= *from++; } while (to++ != &last_stat); } inline bool has_stats() { if (!active) return 0; ulonglong *to= &first_stat; do { if (*to) return 1; } while (to++ != &last_stat); return 0; } }; #endif /* HA_HANDLER_STATS_INCLUDED */ wsrep_mysqld_c.h 0000644 00000002313 15156036125 0007753 0 ustar 00 /* Copyright 2018-2018 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef WSREP_MYSQLD_C_H #define WSREP_MYSQLD_C_H enum enum_wsrep_certification_rules { WSREP_CERTIFICATION_RULES_STRICT, WSREP_CERTIFICATION_RULES_OPTIMIZED }; /* This is intentionally declared as a weak global symbol, so that the same ha_innodb.so can be used with the embedded server (which does not link to the definition of this variable) and with the regular server built WITH_WSREP. */ extern ulong wsrep_certification_rules __attribute__((weak)); #endif /* WSREP_MYSQLD_C_H */ des_key_file.h 0000644 00000002324 15156036125 0007344 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef DES_KEY_FILE_INCLUDED #define DES_KEY_FILE_INCLUDED #ifdef HAVE_des #include <openssl/des.h> #include "violite.h" /* DES_cblock, DES_key_schedule */ struct st_des_keyblock { DES_cblock key1, key2, key3; }; struct st_des_keyschedule { DES_key_schedule ks1, ks2, ks3; }; extern struct st_des_keyschedule des_keyschedule[10]; extern uint des_default_key; bool load_des_key_file(const char *file_name); #endif /* HAVE_des */ #endif /* DES_KEY_FILE_INCLUDED */ key.h 0000644 00000004124 15156036125 0005512 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef KEY_INCLUDED #define KEY_INCLUDED class Field; class String; struct TABLE; typedef struct st_bitmap MY_BITMAP; typedef struct st_key KEY; typedef struct st_key_part_info KEY_PART_INFO; int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, uint *key_length, uint *keypart); void key_copy(uchar *to_key, const uchar *from_record, const KEY *key_info, uint key_length, bool with_zerofill= FALSE); void key_restore(uchar *to_record, const uchar *from_key, KEY *key_info, uint key_length); bool key_cmp_if_same(TABLE *form,const uchar *key,uint index,uint key_length); void key_unpack(String *to, TABLE *table, KEY *key); void field_unpack(String *to, Field *field, const uchar *rec, uint max_length, bool prefix_key); bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields); int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length); ulong key_hashnr(KEY *key_info, uint used_key_parts, const uchar *key); bool key_buf_cmp(KEY *key_info, uint used_key_parts, const uchar *key1, const uchar *key2); extern "C" int key_rec_cmp(const KEY *const *key_info, const uchar *a, const uchar *b); int key_tuple_cmp(KEY_PART_INFO *part, const uchar *key1, const uchar *key2, uint tuple_length); #endif /* KEY_INCLUDED */ debug_sync.h 0000644 00000003776 15156036125 0007060 0 ustar 00 #ifndef DEBUG_SYNC_INCLUDED #define DEBUG_SYNC_INCLUDED /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file Declarations for the Debug Sync Facility. See debug_sync.cc for details. */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif class THD; #if defined(ENABLED_DEBUG_SYNC) /* Command line option --debug-sync-timeout. See mysqld.cc. */ extern MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout; /* Default WAIT_FOR timeout if command line option is given without argument. */ #define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300 /* Debug Sync prototypes. See debug_sync.cc. */ extern int debug_sync_init(void); extern void debug_sync_end(void); extern void debug_sync_init_thread(THD *thd); extern void debug_sync_end_thread(THD *thd); void debug_sync_reset_thread(THD *thd); extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len); extern bool debug_sync_update(THD *thd, char *val_str, size_t len); extern uchar *debug_sync_value_ptr(THD *thd); #else static inline void debug_sync_init_thread(THD *thd) {} static inline void debug_sync_end_thread(THD *thd) {} static inline void debug_sync_reset_thread(THD *thd) {} static inline bool debug_sync_set_action(THD *, const char *, size_t) { return false; } #endif /* defined(ENABLED_DEBUG_SYNC) */ #endif /* DEBUG_SYNC_INCLUDED */ wsrep_allowlist_service.h 0000644 00000002013 15156036125 0011667 0 ustar 00 /* Copyright 2021 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Implementation of wsrep provider threads instrumentation. */ #ifndef WSREP_PROVIDER_ALLOWLIST_H #define WSREP_PROVIDER_ALLOWLIST_H #include "wsrep/allowlist_service.hpp" wsrep::allowlist_service* wsrep_allowlist_service_init(); void wsrep_allowlist_service_deinit(); #endif /* WSREP_PROVIDER_ALLOWLIST_H */ sp_pcontext.h 0000644 00000061333 15156036125 0007275 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_PCONTEXT_H_ #define _SP_PCONTEXT_H_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_string.h" // LEX_STRING #include "field.h" // Create_field #include "sql_array.h" // Dynamic_array /// This class represents a stored program variable or a parameter /// (also referenced as 'SP-variable'). class sp_variable : public Sql_alloc { public: enum enum_mode { MODE_IN, MODE_OUT, MODE_INOUT }; /// Name of the SP-variable. LEX_CSTRING name; /// Mode of the SP-variable. enum_mode mode; /// The index to the variable's value in the runtime frame. /// /// It is calculated during parsing and used when creating sp_instr_set /// instructions and Item_splocal items. I.e. values are set/referred by /// array indexing in runtime. uint offset; /// Default value of the SP-variable (if any). Item *default_value; /// Full type information (field meta-data) of the SP-variable. Spvar_definition field_def; /// Field-type of the SP-variable. const Type_handler *type_handler() const { return field_def.type_handler(); } public: sp_variable(const LEX_CSTRING *name_arg, uint offset_arg) :Sql_alloc(), name(*name_arg), mode(MODE_IN), offset(offset_arg), default_value(NULL) { } /* Find a ROW field by its qualified name. @param var_name - the name of the variable @param field_name - the name of the variable field @param[OUT] row_field_offset - the index of the field @retval NULL if the variable with the given name was not found, or it is not a row variable, or it does not have a field with the given name, or a non-null pointer otherwise. row_field_offset[0] is set only when the method returns !NULL. */ const Spvar_definition *find_row_field(const LEX_CSTRING *var_name, const LEX_CSTRING *field_name, uint *row_field_offset); }; /* This class stores FETCH statement target variables: FETCH cur INTO t1, t2, t2; Targets can be: - Local SP variables - PACKAGE BODY variables */ class sp_fetch_target: public Sql_alloc, public sp_rcontext_addr { public: LEX_CSTRING name; sp_fetch_target(const LEX_CSTRING &name_arg, const sp_rcontext_addr &addr) :sp_rcontext_addr(addr), name(name_arg) { } }; /////////////////////////////////////////////////////////////////////////// /// This class represents an SQL/PSM label. Can refer to the identifier /// used with the "label_name:" construct which may precede some SQL/PSM /// statements, or to an implicit implementation-dependent identifier which /// the parser inserts before a high-level flow control statement such as /// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a /// combination of low-level jump/jump_if instructions and labels. class sp_label : public Sql_alloc { public: enum enum_type { /// Implicit label generated by parser. IMPLICIT, /// Label at BEGIN. BEGIN, /// Label at iteration control ITERATION, /// Label for jump GOTO }; /// Name of the label. LEX_CSTRING name; /// Instruction pointer of the label. uint ip; /// Type of the label. enum_type type; /// Scope of the label. class sp_pcontext *ctx; public: sp_label(const LEX_CSTRING *_name, uint _ip, enum_type _type, sp_pcontext *_ctx) :Sql_alloc(), name(*_name), ip(_ip), type(_type), ctx(_ctx) { } }; /////////////////////////////////////////////////////////////////////////// /// This class represents condition-value term in DECLARE CONDITION or /// DECLARE HANDLER statements. sp_condition_value has little to do with /// SQL-conditions. /// /// In some sense, this class is a union -- a set of filled attributes /// depends on the sp_condition_value::type value. class sp_condition_value : public Sql_alloc, public Sql_state_errno { bool m_is_user_defined; public: enum enum_type { ERROR_CODE, SQLSTATE, WARNING, NOT_FOUND, EXCEPTION }; /// Type of the condition value. enum_type type; public: sp_condition_value(uint _mysqlerr) :Sql_alloc(), Sql_state_errno(_mysqlerr), m_is_user_defined(false), type(ERROR_CODE) { } sp_condition_value(uint _mysqlerr, const char *_sql_state) :Sql_alloc(), Sql_state_errno(_mysqlerr, _sql_state), m_is_user_defined(false), type(ERROR_CODE) { } sp_condition_value(const char *_sql_state, bool is_user_defined= false) :Sql_alloc(), Sql_state_errno(0, _sql_state), m_is_user_defined(is_user_defined), type(SQLSTATE) { } sp_condition_value(enum_type _type) :Sql_alloc(), m_is_user_defined(false), type(_type) { DBUG_ASSERT(type != ERROR_CODE && type != SQLSTATE); } /// Check if two instances of sp_condition_value are equal or not. /// /// @param cv another instance of sp_condition_value to check. /// /// @return true if the instances are equal, false otherwise. bool equals(const sp_condition_value *cv) const; /** Checks if this condition is OK for search. See also sp_context::find_handler(). @param identity - The condition identity @param found_cv - A previously found matching condition or NULL. @return true - If the current value matches identity and makes a stronger match than the previously found condition found_cv. @return false - If the current value does not match identity, of the current value makes a weaker match than found_cv. */ bool matches(const Sql_condition_identity &identity, const sp_condition_value *found_cv) const; Sql_user_condition_identity get_user_condition_identity() const { return Sql_user_condition_identity(m_is_user_defined ? this : NULL); } }; class sp_condition_value_user_defined: public sp_condition_value { public: sp_condition_value_user_defined() :sp_condition_value("45000", true) { } }; /////////////////////////////////////////////////////////////////////////// /// This class represents 'DECLARE CONDITION' statement. /// sp_condition has little to do with SQL-conditions. class sp_condition : public Sql_alloc { public: /// Name of the condition. LEX_CSTRING name; /// Value of the condition. sp_condition_value *value; public: sp_condition(const LEX_CSTRING *name_arg, sp_condition_value *value_arg) :Sql_alloc(), name(*name_arg), value(value_arg) { } sp_condition(const char *name_arg, size_t name_length_arg, sp_condition_value *value_arg) :value(value_arg) { name.str= name_arg; name.length= name_length_arg; } bool eq_name(const LEX_CSTRING *str) const { return system_charset_info->strnncoll(name.str, name.length, str->str, str->length) == 0; } }; /////////////////////////////////////////////////////////////////////////// /** class sp_pcursor. Stores information about a cursor: - Cursor's name in LEX_STRING. - Cursor's formal parameter descriptions. Formal parameter descriptions reside in a separate context block, pointed by the "m_param_context" member. m_param_context can be NULL. This means a cursor with no parameters. Otherwise, the number of variables in m_param_context means the number of cursor's formal parameters. Note, m_param_context can be not NULL, but have no variables. This is also means a cursor with no parameters (similar to NULL). */ class sp_pcursor: public LEX_CSTRING { class sp_pcontext *m_param_context; // Formal parameters class sp_lex_cursor *m_lex; // The cursor statement LEX public: sp_pcursor(const LEX_CSTRING *name, class sp_pcontext *param_ctx, class sp_lex_cursor *lex) :LEX_CSTRING(*name), m_param_context(param_ctx), m_lex(lex) { } class sp_pcontext *param_context() const { return m_param_context; } class sp_lex_cursor *lex() const { return m_lex; } bool check_param_count_with_error(uint param_count) const; }; /////////////////////////////////////////////////////////////////////////// /// This class represents 'DECLARE HANDLER' statement. class sp_handler : public Sql_alloc { public: /// Enumeration of possible handler types. /// Note: UNDO handlers are not (and have never been) supported. enum enum_type { EXIT, CONTINUE }; /// Handler type. enum_type type; /// Conditions caught by this handler. List<sp_condition_value> condition_values; public: /// The constructor. /// /// @param _type SQL-handler type. sp_handler(enum_type _type) :Sql_alloc(), type(_type) { } }; /////////////////////////////////////////////////////////////////////////// /// The class represents parse-time context, which keeps track of declared /// variables/parameters, conditions, handlers, cursors and labels. /// /// sp_pcontext objects are organized in a tree according to the following /// rules: /// - one sp_pcontext object corresponds for each BEGIN..END block; /// - one sp_pcontext object corresponds for each exception handler; /// - one additional sp_pcontext object is created to contain /// Stored Program parameters. /// /// sp_pcontext objects are used both at parse-time and at runtime. /// /// During the parsing stage sp_pcontext objects are used: /// - to look up defined names (e.g. declared variables and visible /// labels); /// - to check for duplicates; /// - for error checking; /// - to calculate offsets to be used at runtime. /// /// During the runtime phase, a tree of sp_pcontext objects is used: /// - for error checking (e.g. to check correct number of parameters); /// - to resolve SQL-handlers. class sp_pcontext : public Sql_alloc { public: enum enum_scope { /// REGULAR_SCOPE designates regular BEGIN ... END blocks. REGULAR_SCOPE, /// HANDLER_SCOPE designates SQL-handler blocks. HANDLER_SCOPE }; class Lex_for_loop: public Lex_for_loop_st { public: /* The label poiting to the body start, either explicit or automatically generated. Used during generation of "ITERATE loop_label" to check if "loop_label" is a FOR loop label. - In case of a FOR loop, some additional code (cursor fetch or iteger increment) is generated before the backward jump to the beginning of the loop body. - In case of other loop types (WHILE, REPEAT) only the jump is generated. */ const sp_label *m_start_label; Lex_for_loop() :m_start_label(NULL) { Lex_for_loop_st::init(); } Lex_for_loop(const Lex_for_loop_st &for_loop, const sp_label *start) :m_start_label(start) { Lex_for_loop_st::operator=(for_loop); } }; public: sp_pcontext(); ~sp_pcontext(); /// Create and push a new context in the tree. /// @param thd thread context. /// @param scope scope of the new parsing context. /// @return the node created. sp_pcontext *push_context(THD *thd, enum_scope scope); /// Pop a node from the parsing context tree. /// @return the parent node. sp_pcontext *pop_context(); sp_pcontext *parent_context() const { return m_parent; } sp_pcontext *child_context(uint i) const { return i < m_children.elements() ? m_children.at(i) : NULL; } /// Calculate and return the number of handlers to pop between the given /// context and this one. /// /// @param ctx the other parsing context. /// @param exclusive specifies if the last scope should be excluded. /// /// @return the number of handlers to pop between the given context and /// this one. If 'exclusive' is true, don't count the last scope we are /// leaving; this is used for LEAVE where we will jump to the hpop /// instructions. uint diff_handlers(const sp_pcontext *ctx, bool exclusive) const; /// Calculate and return the number of cursors to pop between the given /// context and this one. /// /// @param ctx the other parsing context. /// @param exclusive specifies if the last scope should be excluded. /// /// @return the number of cursors to pop between the given context and /// this one. If 'exclusive' is true, don't count the last scope we are /// leaving; this is used for LEAVE where we will jump to the cpop /// instructions. uint diff_cursors(const sp_pcontext *ctx, bool exclusive) const; ///////////////////////////////////////////////////////////////////////// // SP-variables (parameters and variables). ///////////////////////////////////////////////////////////////////////// /// @return the maximum number of variables used in this and all child /// contexts. For the root parsing context, this gives us the number of /// slots needed for variables during the runtime phase. uint max_var_index() const { return m_max_var_index; } /// @return the current number of variables used in the parent contexts /// (from the root), including this context. uint current_var_count() const { return m_var_offset + (uint)m_vars.elements(); } /// @return the number of variables in this context alone. uint context_var_count() const { return (uint)m_vars.elements(); } /// return the i-th variable on the current context sp_variable *get_context_variable(uint i) const { DBUG_ASSERT(i < m_vars.elements()); return m_vars.at(i); } /* Return the i-th last context variable. If i is 0, then return the very last variable in m_vars. */ sp_variable *get_last_context_variable(uint i= 0) const { DBUG_ASSERT(i < m_vars.elements()); return m_vars.at(m_vars.elements() - i - 1); } /// Add SP-variable to the parsing context. /// /// @param thd Thread context. /// @param name Name of the SP-variable. /// /// @return instance of newly added SP-variable. sp_variable *add_variable(THD *thd, const LEX_CSTRING *name); /// Retrieve full type information about SP-variables in this parsing /// context and its children. /// /// @param field_def_lst[out] Container to store type information. void retrieve_field_definitions(List<Spvar_definition> *field_def_lst) const; /// Find SP-variable by name. /// /// The function does a linear search (from newer to older variables, /// in case we have shadowed names). /// /// The function is called only at parsing time. /// /// @param name Variable name. /// @param current_scope_only A flag if we search only in current scope. /// /// @return instance of found SP-variable, or NULL if not found. sp_variable *find_variable(const LEX_CSTRING *name, bool current_scope_only) const; /// Find SP-variable by the offset in the root parsing context. /// /// The function is used for two things: /// - When evaluating parameters at the beginning, and setting out parameters /// at the end, of invocation. (Top frame only, so no recursion then.) /// - For printing of sp_instr_set. (Debug mode only.) /// /// @param offset Variable offset in the root parsing context. /// /// @return instance of found SP-variable, or NULL if not found. sp_variable *find_variable(uint offset) const; /// Set the current scope boundary (for default values). /// /// @param n The number of variables to skip. void declare_var_boundary(uint n) { m_pboundary= n; } ///////////////////////////////////////////////////////////////////////// // CASE expressions. ///////////////////////////////////////////////////////////////////////// int register_case_expr() { return m_num_case_exprs++; } int get_num_case_exprs() const { return m_num_case_exprs; } bool push_case_expr_id(int case_expr_id) { return m_case_expr_ids.append(case_expr_id); } void pop_case_expr_id() { m_case_expr_ids.pop(); } int get_current_case_expr_id() const { return *m_case_expr_ids.back(); } ///////////////////////////////////////////////////////////////////////// // Labels. ///////////////////////////////////////////////////////////////////////// sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type, List<sp_label> * list); sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type) { return push_label(thd, name, ip, type, &m_labels); } sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type) { return push_label(thd, name, ip, type, &m_goto_labels); } sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip) { return push_label(thd, name, ip, sp_label::IMPLICIT); } sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip) { return push_goto_label(thd, name, ip, sp_label::GOTO); } sp_label *find_label(const LEX_CSTRING *name); sp_label *find_goto_label(const LEX_CSTRING *name, bool recusive); sp_label *find_goto_label(const LEX_CSTRING *name) { return find_goto_label(name, true); } sp_label *find_label_current_loop_start(); sp_label *last_label() { sp_label *label= m_labels.head(); if (!label && m_parent) label= m_parent->last_label(); return label; } sp_label *last_goto_label() { return m_goto_labels.head(); } sp_label *pop_label() { return m_labels.pop(); } bool block_label_declare(LEX_CSTRING *label) { sp_label *lab= find_label(label); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), label->str); return true; } return false; } ///////////////////////////////////////////////////////////////////////// // Conditions. ///////////////////////////////////////////////////////////////////////// bool add_condition(THD *thd, const LEX_CSTRING *name, sp_condition_value *value); /// See comment for find_variable() above. sp_condition_value *find_condition(const LEX_CSTRING *name, bool current_scope_only) const; sp_condition_value * find_declared_or_predefined_condition(THD *thd, const LEX_CSTRING *name) const; bool declare_condition(THD *thd, const LEX_CSTRING *name, sp_condition_value *val) { if (find_condition(name, true)) { my_error(ER_SP_DUP_COND, MYF(0), name->str); return true; } return add_condition(thd, name, val); } ///////////////////////////////////////////////////////////////////////// // Handlers. ///////////////////////////////////////////////////////////////////////// sp_handler *add_handler(THD* thd, sp_handler::enum_type type); /// This is an auxilary parsing-time function to check if an SQL-handler /// exists in the current parsing context (current scope) for the given /// SQL-condition. This function is used to check for duplicates during /// the parsing phase. /// /// This function can not be used during the runtime phase to check /// SQL-handler existence because it searches for the SQL-handler in the /// current scope only (during runtime, current and parent scopes /// should be checked according to the SQL-handler resolution rules). /// /// @param condition_value the handler condition value /// (not SQL-condition!). /// /// @retval true if such SQL-handler exists. /// @retval false otherwise. bool check_duplicate_handler(const sp_condition_value *cond_value) const; /// Find an SQL handler for the given SQL condition according to the /// SQL-handler resolution rules. This function is used at runtime. /// /// @param value The error code and the SQL state /// @param level The SQL condition level /// /// @return a pointer to the found SQL-handler or NULL. sp_handler *find_handler(const Sql_condition_identity &identity) const; ///////////////////////////////////////////////////////////////////////// // Cursors. ///////////////////////////////////////////////////////////////////////// bool add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx, class sp_lex_cursor *lex); /// See comment for find_variable() above. const sp_pcursor *find_cursor(const LEX_CSTRING *name, uint *poff, bool current_scope_only) const; const sp_pcursor *find_cursor_with_error(const LEX_CSTRING *name, uint *poff, bool current_scope_only) const { const sp_pcursor *pcursor= find_cursor(name, poff, current_scope_only); if (!pcursor) { my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str); return NULL; } return pcursor; } /// Find cursor by offset (for SHOW {PROCEDURE|FUNCTION} CODE only). const sp_pcursor *find_cursor(uint offset) const; const sp_pcursor *get_cursor_by_local_frame_offset(uint offset) const { return &m_cursors.at(offset); } uint cursor_offset() const { return m_cursor_offset; } uint frame_cursor_count() const { return (uint)m_cursors.elements(); } uint max_cursor_index() const { return m_max_cursor_index + (uint)m_cursors.elements(); } uint current_cursor_count() const { return m_cursor_offset + (uint)m_cursors.elements(); } void set_for_loop(const Lex_for_loop_st &for_loop) { m_for_loop= Lex_for_loop(for_loop, last_label()); } const Lex_for_loop &for_loop() { return m_for_loop; } private: /// Constructor for a tree node. /// @param prev the parent parsing context /// @param scope scope of this parsing context sp_pcontext(sp_pcontext *prev, enum_scope scope); void init(uint var_offset, uint cursor_offset, int num_case_expressions); /* Prevent use of these */ sp_pcontext(const sp_pcontext &); void operator=(sp_pcontext &); sp_condition_value *find_predefined_condition(const LEX_CSTRING *name) const; private: /// m_max_var_index -- number of variables (including all types of arguments) /// in this context including all children contexts. /// /// m_max_var_index >= m_vars.elements(). /// /// m_max_var_index of the root parsing context contains number of all /// variables (including arguments) in all enclosed contexts. uint m_max_var_index; /// The maximum sub context's framesizes. uint m_max_cursor_index; /// Parent context. sp_pcontext *m_parent; /// An index of the first SP-variable in this parsing context. The index /// belongs to a runtime table of SP-variables. /// /// Note: /// - m_var_offset is 0 for root parsing context; /// - m_var_offset is different for all nested parsing contexts. uint m_var_offset; /// Cursor offset for this context. uint m_cursor_offset; /// Boundary for finding variables in this context. This is the number of /// variables currently "invisible" to default clauses. This is normally 0, /// but will be larger during parsing of DECLARE ... DEFAULT, to get the /// scope right for DEFAULT values. uint m_pboundary; int m_num_case_exprs; /// SP parameters/variables. Dynamic_array<sp_variable *> m_vars; /// Stack of CASE expression ids. Dynamic_array<int> m_case_expr_ids; /// Stack of SQL-conditions. Dynamic_array<sp_condition *> m_conditions; /// Stack of cursors. Dynamic_array<sp_pcursor> m_cursors; /// Stack of SQL-handlers. Dynamic_array<sp_handler *> m_handlers; /* In the below example the label <<lab>> has two meanings: - GOTO lab : must go before the beginning of the loop - CONTINUE lab : must go to the beginning of the loop We solve this by storing block labels and goto labels into separate lists. BEGIN <<lab>> FOR i IN a..10 LOOP ... GOTO lab; ... CONTINUE lab; ... END LOOP; END; */ /// List of block labels List<sp_label> m_labels; /// List of goto labels List<sp_label> m_goto_labels; /// Children contexts, used for destruction. Dynamic_array<sp_pcontext *> m_children; /// Scope of this parsing context. enum_scope m_scope; /// FOR LOOP characteristics Lex_for_loop m_for_loop; }; // class sp_pcontext : public Sql_alloc #endif /* _SP_PCONTEXT_H_ */ thr_malloc.h 0000644 00000002262 15156036126 0007050 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef THR_MALLOC_INCLUDED #define THR_MALLOC_INCLUDED typedef struct st_mem_root MEM_ROOT; void init_sql_alloc(PSI_memory_key key, MEM_ROOT *root, uint block_size, uint pre_alloc_size, myf my_flags); char *sql_strmake_with_convert(THD *thd, const char *str, size_t arg_length, CHARSET_INFO *from_cs, size_t max_res_length, CHARSET_INFO *to_cs, size_t *result_length); #endif /* THR_MALLOC_INCLUDED */ innodb_priv.h 0000644 00000002447 15156036126 0007242 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef INNODB_PRIV_INCLUDED #define INNODB_PRIV_INCLUDED /** @file Declaring server-internal functions that are used by InnoDB. */ #include <sql_priv.h> #include <strfunc.h> /* strconvert */ class THD; int get_quote_char_for_identifier(THD *thd, const char *name, size_t length); bool schema_table_store_record(THD *thd, TABLE *table); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); void sql_print_error(const char *format, ...); #define thd_binlog_pos(X, Y, Z) mysql_bin_log_commit_pos(X, Z, Y) #endif /* INNODB_PRIV_INCLUDED */ derived_handler.h 0000644 00000004513 15156036126 0010044 0 ustar 00 /* Copyright (c) 2016, 2017 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DERIVED_HANDLER_INCLUDED #define DERIVED_HANDLER_INCLUDED #include "mariadb.h" #include "sql_priv.h" class TMP_TABLE_PARAM; typedef class st_select_lex_unit SELECT_LEX_UNIT; /** @class derived_handler This interface class is to be used for execution of queries that specify derived table by foreign engines */ class derived_handler { public: THD *thd; handlerton *ht; TABLE_LIST *derived; /* Temporary table where all results should be stored in record[0] The table has a field for every item from the select list of the specification of derived. */ TABLE *table; /* The parameters if the temporary table used at its creation */ TMP_TABLE_PARAM *tmp_table_param; SELECT_LEX_UNIT *unit; // Specifies the derived table SELECT_LEX *select; // The first select of the specification derived_handler(THD *thd_arg, handlerton *ht_arg) : thd(thd_arg), ht(ht_arg), derived(0),table(0), tmp_table_param(0), unit(0), select(0) {} virtual ~derived_handler() = default; /* Functions to scan data. All these returns 0 if ok, error code in case of error */ /* Initialize the process of producing rows of the derived table */ virtual int init_scan()= 0; /* Put the next produced row of the derived in table->record[0] and return 0. Return HA_ERR_END_OF_FILE if there are no more rows, return other error number in case of fatal error. */ virtual int next_row()= 0; /* End prodicing rows */ virtual int end_scan()=0; /* Report errors */ virtual void print_error(int error, myf errflag); void set_derived(TABLE_LIST *tbl); }; #endif /* DERIVED_HANDLER_INCLUDED */ my_tracker.h 0000644 00000002575 15156036126 0007073 0 ustar 00 /* Copyright (c) 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Trivial framework to add a tracker to a C function */ #include "my_rdtsc.h" struct my_time_tracker { ulonglong counter; ulonglong cycles; }; #ifdef HAVE_TIME_TRACKING #define START_TRACKING ulonglong my_start_time= my_timer_cycles() #define END_TRACKING(var) \ { \ ulonglong my_end_time= my_timer_cycles(); \ (var)->counter++; \ (var)->cycles+= (unlikely(my_end_time < my_start_time) ? \ my_end_time - my_start_time + ULONGLONG_MAX : \ my_end_time - my_start_time); \ } #else #define START_TRACKING #define END_TRACKING(var) do { } while(0) #endif authors.h 0000644 00000023635 15156036126 0006420 0 ustar 00 #ifndef AUTHORS_INCLUDED #define AUTHORS_INCLUDED /* Copyright (c) 2005, 2010, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Structure of the name list */ struct show_table_authors_st { const char *name; const char *location; const char *comment; }; /* Output from "SHOW AUTHORS" If you can update it, you get to be in it :) Don't be offended if your name is not in here, just add it! Active people in the MariaDB are listed first, active people in MySQL then, not active last. Names should be encoded using UTF-8. See also https://mariadb.com/kb/en/log-of-mariadb-contributions/ */ struct show_table_authors_st show_table_authors[]= { /* Active people on MariaDB */ { "Michael (Monty) Widenius", "Tusby, Finland", "Lead developer and main author" }, { "Sergei Golubchik", "Kerpen, Germany", "Architect, Full-text search, precision math, plugin framework, merges etc" }, { "Igor Babaev", "Bellevue, USA", "Optimizer, keycache, core work"}, { "Sergey Petrunia", "St. Petersburg, Russia", "Optimizer"}, { "Oleksandr Byelkin", "Lugansk, Ukraine", "Query Cache (4.0), Subqueries (4.1), Views (5.0)" }, { "Timour Katchaounov", "Sofia , Bulgaria", "Optimizer"}, { "Kristian Nielsen", "Copenhagen, Denmark", "Replication, Async client prototocol, General buildbot stuff" }, { "Alexander (Bar) Barkov", "Izhevsk, Russia", "Unicode and character sets" }, { "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia", "GIS extensions, embedded server, precision math"}, { "Daniel Bartholomew", "Raleigh, USA", "MariaDB documentation, Buildbot, releases"}, { "Colin Charles", "Selangor, Malesia", "MariaDB documentation, talks at a LOT of conferences"}, { "Sergey Vojtovich", "Izhevsk, Russia", "initial implementation of plugin architecture, maintained native storage engines (MyISAM, MEMORY, ARCHIVE, etc), rewrite of table cache"}, { "Vladislav Vaintroub", "Mannheim, Germany", "MariaDB Java connector, new thread pool, Windows optimizations"}, { "Elena Stepanova", "Sankt Petersburg, Russia", "QA, test cases"}, { "Georg Richter", "Heidelberg, Germany", "New LGPL C connector, PHP connector"}, { "Jan Lindström", "Ylämylly, Finland", "Working on InnoDB"}, { "Lixun Peng", "Hangzhou, China", "Multi Source replication" }, { "Olivier Bertrand", "Paris, France", "CONNECT storage engine"}, { "Kentoku Shiba", "Tokyo, Japan", "Spider storage engine, metadata_lock_info Information schema"}, { "Percona", "CA, USA", "XtraDB, microslow patches, extensions to slow log"}, { "Vicentiu Ciorbaru", "Bucharest, Romania", "Roles"}, { "Sudheera Palihakkara", "", "PCRE Regular Expressions" }, { "Pavel Ivanov", "USA", "Some patches and bug fixes"}, { "Konstantin Osipov", "Moscow, Russia", "Prepared statements (4.1), Cursors (5.0), GET_LOCK (10.0)" }, { "Ian Gilfillan", "South Africa", "MariaDB documentation"}, { "Federico Razolli", "Italy", "MariaDB documentation Italian translation"}, { "Vinchen", "Shenzhen, China", "Instant ADD Column for InnoDB, Spider engine optimization, from Tencent Game DBA Team" }, { "Willhan", "Shenzhen, China", "Big Column Compression, Spider engine optimization, from Tencent Game DBA Team" }, { "Anders Karlsson", "Ystad, Sweden", "Replication patch for enforcing triggers on slave"}, { "Otto Kekäläinen", "Tampere, Finland", "Debian packaging, install/upgrade engineering, QA pipelines, documentation"}, { "Daniel Black", "Canberra, Australia", "Modernising large page support, systemd, and bug fixes"}, /* People working on MySQL code base (not NDB) */ { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" }, { "Andrei Elkin", "Espoo, Finland", "Replication" }, { "Dmitri Lenev", "Moscow, Russia", "Time zones support (4.1), Triggers (5.0)" }, { "Marc Alff", "Denver, CO, USA", "Signal, Resignal, Performance schema" }, { "Mikael Ronström", "Stockholm, Sweden", "NDB Cluster, Partitioning, online alter table" }, { "Ingo Strüwing", "Berlin, Germany", "Bug fixing in MyISAM, Merge tables etc" }, {"Marko Mäkelä", "Helsinki, Finland", "InnoDB core developer"}, /* People not active anymore */ { "David Axmark", "London, England", "MySQL founder; Small stuff long time ago, Monty ripped it out!" }, { "Brian (Krow) Aker", "Seattle, WA, USA", "Architecture, archive, blackhole, federated, bunch of little stuff :)" }, { "Venu Anuganti", "", "Client/server protocol (4.1)" }, { "Omer BarNir", "Sunnyvale, CA, USA", "Testing (sometimes) and general QA stuff" }, { "John Birrell", "", "Emulation of pthread_mutex() for OS/2" }, { "Andreas F. Bobak", "", "AGGREGATE extension to user-defined functions" }, { "Reggie Burnett", "Nashville, TN, USA", "Windows development, Connectors" }, { "Kent Boortz", "Orebro, Sweden", "Test platform, and general build stuff" }, { "Tim Bunce", "", "mysqlhotcopy" }, { "Yves Carlier", "", "mysqlaccess" }, { "Joshua Chamas", "Cupertino, CA, USA", "Concurrent insert, extended date syntax" }, { "Petr Chardin", "Moscow, Russia", "Instance Manager (5.0), Server log tables (5.1)" }, { "Wei-Jou Chen", "", "Chinese (Big5) character set" }, { "Albert Chin-A-Young", "", "Tru64 port, large file support, better TCP wrappers support" }, { "Jorge del Conde", "Mexico City, Mexico", "Windows development" }, { "Antony T. Curtis", "Norwalk, CA, USA", "Parser, port to OS/2, storage engines and some random stuff" }, { "Yuri Dario", "", "OS/2 port" }, { "Patrick Galbraith", "Sharon, NH", "Federated Engine, mysqlslap" }, { "Lenz Grimmer", "Hamburg, Germany", "Production (build and release) engineering" }, { "Nikolay Grishakin", "Austin, TX, USA", "Testing - Server" }, { "Wei He", "", "Chinese (GBK) character set" }, { "Eric Herman", "Amsterdam, Netherlands", "Bug fixing - federated" }, { "Andrey Hristov", "Walldorf, Germany", "Event scheduler (5.1)" }, { "Alexander (Alexi) Ivanov", "St. Petersburg, Russia", "Replication" }, { "Mattias Jonsson", "Uppsala, Sweden", "Partitioning" }, { "Alexander (Salle) Keremidarski", "Sofia, Bulgaria", "Bug fixing" }, { "Mats Kindahl", "Storvreta, Sweden", "Replication" }, { "Serge Kozlov", "Velikie Luki, Russia", "Testing - Cluster" }, { "Hakan Küçükyılmaz", "Walldorf, Germany", "Testing - Server" }, { "Matthias Leich", "Berlin, Germany", "Testing - Server" }, { "Arjen Lentz", "Brisbane, Australia", "Documentation (2001-2004), Dutch error messages, LOG2()" }, { "Marc Liyanage", "", "Created Mac OS X packages" }, { "Kelly Long", "Denver, CO, USA", "Pool Of Threads" }, { "Zarko Mocnik", "", "Sorting for Slovenian language" }, { "Per-Erik Martin", "Uppsala, Sweden", "Stored Procedures (5.0)" }, { "Alexis Mikhailov", "", "User-defined functions" }, { "Sinisa Milivojevic", "Larnaca, Cyprus", "UNION (4.0), Subqueries in FROM clause (4.1), many other features" }, { "Jonathan (Jeb) Miller", "Kyle, TX, USA", "Testing - Cluster, Replication" }, { "Elliot Murphy", "Cocoa, FL, USA", "Replication and backup" }, { "Pekka Nouisiainen", "Stockholm, Sweden", "NDB Cluster: BLOB support, character set support, ordered indexes" }, { "Alexander Nozdrin", "Moscow, Russia", "Bug fixing (Stored Procedures, 5.0)" }, { "Per Eric Olsson", "", "Testing of dynamic record format" }, { "Jonas Oreland", "Stockholm, Sweden", "NDB Cluster, Online Backup, lots of other things" }, { "Alexander (Sasha) Pachev", "Provo, UT, USA", "Statement-based replication, SHOW CREATE TABLE, mysql-bench" }, { "Irena Pancirov", "", "Port to Windows with Borland compiler" }, { "Jan Pazdziora", "", "Czech sorting order" }, { "Benjamin Pflugmann", "", "Extended MERGE storage engine to handle INSERT" }, { "Igor Romanenko", "", "mysqldump" }, { "Tõnu Samuel", "Estonia", "VIO interface, other miscellaneous features" }, { "Carsten Segieth (Pino)", "Fredersdorf, Germany", "Testing - Server"}, { "Martin Sköld", "Stockholm, Sweden", "NDB Cluster: Unique indexes, integration into MySQL" }, { "Timothy Smith", "Auckland, New Zealand", "Dynamic character sets, parts of the build system, libmysqld"}, { "Miguel Solorzano", "Florianopolis, Santa Catarina, Brazil", "Windows development, Windows NT service"}, { "Punita Srivastava", "Austin, TX, USA", "Testing - Merlin"}, { "Alexey Stroganov (Ranger)", "Lugansk, Ukraine", "Testing - Benchmarks"}, { "Magnus Svensson", "Öregrund, Sweden", "NDB Cluster: Integration into MySQL, test framework" }, { "Zeev Suraski", "", "FROM_UNIXTIME(), ENCRYPT()" }, { "TAMITO", "", "The _MB character set macros and UJIS and SJIS character sets" }, { "Jani Tolonen", "Helsinki, Finland", "mysqlimport, extensions to command-line clients, PROCEDURE ANALYSE()" }, { "Lars Thalmann", "Stockholm, Sweden", "Replication and cluster development" }, { "Tomas Ulin", "Stockholm, Sweden", "NDB Cluster: Configuration, installation" }, { "Gianmassimo Vigazzola", "", "Initial Windows port" }, { "Sergey Vojtovich", "Izhevsk, Russia", "Plugins infrastructure (5.1)" }, { "Matt Wagner", "Northfield, MN, USA", "Bug fixing" }, { "Jim Winstead Jr.", "Los Angeles, CA, USA", "Bug fixing" }, { "Peter Zaitsev", "Tacoma, WA, USA", "SHA1(), AES_ENCRYPT(), AES_DECRYPT(), bug fixing" }, {"Mark Mark Callaghan", "Texas, USA", "Statistics patches"}, {NULL, NULL, NULL} }; #endif /* AUTHORS_INCLUDED */ privilege.h 0000644 00000070707 15156036126 0006723 0 ustar 00 #ifndef PRIVILEGE_H_INCLUDED #define PRIVILEGE_H_INCLUDED /* Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_global.h" // ulonglong /* A strict enum to store privilege bits. We should eventually make if even stricter using "enum class privilege_t" and: - Replace all code pieces like `if (priv)` to `if (priv != NO_ACL)` - Remove "delete" comparison operators below */ enum privilege_t: unsigned long long { NO_ACL = (0), SELECT_ACL = (1UL << 0), INSERT_ACL = (1UL << 1), UPDATE_ACL = (1UL << 2), DELETE_ACL = (1UL << 3), CREATE_ACL = (1UL << 4), DROP_ACL = (1UL << 5), RELOAD_ACL = (1UL << 6), SHUTDOWN_ACL = (1UL << 7), PROCESS_ACL = (1UL << 8), FILE_ACL = (1UL << 9), GRANT_ACL = (1UL << 10), REFERENCES_ACL = (1UL << 11), INDEX_ACL = (1UL << 12), ALTER_ACL = (1UL << 13), SHOW_DB_ACL = (1UL << 14), SUPER_ACL = (1UL << 15), CREATE_TMP_ACL = (1UL << 16), LOCK_TABLES_ACL = (1UL << 17), EXECUTE_ACL = (1UL << 18), REPL_SLAVE_ACL = (1UL << 19), BINLOG_MONITOR_ACL = (1UL << 20), // Was REPL_CLIENT_ACL prior to 10.5.2 CREATE_VIEW_ACL = (1UL << 21), SHOW_VIEW_ACL = (1UL << 22), CREATE_PROC_ACL = (1UL << 23), ALTER_PROC_ACL = (1UL << 24), CREATE_USER_ACL = (1UL << 25), EVENT_ACL = (1UL << 26), TRIGGER_ACL = (1UL << 27), CREATE_TABLESPACE_ACL = (1UL << 28), DELETE_HISTORY_ACL = (1UL << 29), // Added in 10.3.4 SET_USER_ACL = (1UL << 30), // Added in 10.5.2 FEDERATED_ADMIN_ACL = (1UL << 31), // Added in 10.5.2 CONNECTION_ADMIN_ACL = (1ULL << 32), // Added in 10.5.2 READ_ONLY_ADMIN_ACL = (1ULL << 33), // Added in 10.5.2 REPL_SLAVE_ADMIN_ACL = (1ULL << 34), // Added in 10.5.2 REPL_MASTER_ADMIN_ACL = (1ULL << 35), // Added in 10.5.2 BINLOG_ADMIN_ACL = (1ULL << 36), // Added in 10.5.2 BINLOG_REPLAY_ACL = (1ULL << 37), // Added in 10.5.2 SLAVE_MONITOR_ACL = (1ULL << 38), // Added in 10.5.8 SHOW_CREATE_ROUTINE_ACL = (1ULL << 39) // added in 11.3.0 /* When adding new privilege bits, don't forget to update: In this file: - Add a new LAST_version_ACL - Add a new ALL_KNOWN_ACL_version - Change ALL_KNOWN_ACL to ALL_KNOWN_ACL_version - Change GLOBAL_ACLS, DB_ACLS, TABLE_ACLS, PROC_ACLS if needed - Change SUPER_ADDED_SINCE_USER_TABLE_ACL if needed In other files: - static struct show_privileges_st sys_privileges[] - static const char *command_array[] and static uint command_lengths[] - mariadb_system_tables.sql and mariadb_system_tables_fix.sql - acl_init() or whatever - to define behaviour for old privilege tables - Update User_table_json::get_access() - sql_yacc.yy - for GRANT/REVOKE to work Important: the enum should contain only single-bit values. In this case, debuggers print bit combinations in the readable form: (gdb) p (privilege_t) (15) $8 = (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL) Bit-OR combinations of the above values should be declared outside! */ }; constexpr static inline privilege_t ALL_KNOWN_BITS(privilege_t x) { return (privilege_t)(x | (x-1)); } // Version markers constexpr privilege_t LAST_100304_ACL= DELETE_HISTORY_ACL; constexpr privilege_t LAST_100502_ACL= BINLOG_REPLAY_ACL; constexpr privilege_t LAST_100508_ACL= SLAVE_MONITOR_ACL; constexpr privilege_t LAST_110300_ACL= SHOW_CREATE_ROUTINE_ACL; // Current version markers constexpr privilege_t LAST_CURRENT_ACL= LAST_110300_ACL; constexpr uint PRIVILEGE_T_MAX_BIT= my_bit_log2_uint64((ulonglong) LAST_CURRENT_ACL); static_assert((privilege_t)(1ULL << PRIVILEGE_T_MAX_BIT) == LAST_CURRENT_ACL, "Something went fatally badly: " "LAST_CURRENT_ACL and PRIVILEGE_T_MAX_BIT do not match"); // A combination of all bits defined in 10.3.4 (and earlier) constexpr privilege_t ALL_KNOWN_ACL_100304 = ALL_KNOWN_BITS(LAST_100304_ACL); // A combination of all bits defined in 10.5.2 constexpr privilege_t ALL_KNOWN_ACL_100502= ALL_KNOWN_BITS(LAST_100502_ACL); // A combination of all bits defined in 10.5.8 constexpr privilege_t ALL_KNOWN_ACL_100508= ALL_KNOWN_BITS(LAST_100508_ACL); // unfortunately, SLAVE_MONITOR_ACL was added in 10.5.9, but also in 10.5.8-5 // let's stay compatible with that branch too. constexpr privilege_t ALL_KNOWN_ACL_100509= ALL_KNOWN_ACL_100508; // A combination of all bits defined in 11.3.0 constexpr privilege_t ALL_KNOWN_ACL_110300= ALL_KNOWN_BITS(LAST_110300_ACL); // A combination of all bits defined as of the current version constexpr privilege_t ALL_KNOWN_ACL= ALL_KNOWN_BITS(LAST_CURRENT_ACL); // Unary operators static inline constexpr ulonglong operator~(privilege_t access) { return ~static_cast<ulonglong>(access); } /* Comparison operators. Delete automatic conversion between to/from integer types as much as possible. This forces to use `(priv == NO_ACL)` instead of `(priv == 0)`. Note: these operators will be gone when we change privilege_t to "enum class privilege_t". See comments above. */ static inline bool operator==(privilege_t, ulonglong)= delete; static inline bool operator==(privilege_t, ulong)= delete; static inline bool operator==(privilege_t, uint)= delete; static inline bool operator==(privilege_t, uchar)= delete; static inline bool operator==(privilege_t, longlong)= delete; static inline bool operator==(privilege_t, long)= delete; static inline bool operator==(privilege_t, int)= delete; static inline bool operator==(privilege_t, char)= delete; static inline bool operator==(privilege_t, bool)= delete; static inline bool operator==(ulonglong, privilege_t)= delete; static inline bool operator==(ulong, privilege_t)= delete; static inline bool operator==(uint, privilege_t)= delete; static inline bool operator==(uchar, privilege_t)= delete; static inline bool operator==(longlong, privilege_t)= delete; static inline bool operator==(long, privilege_t)= delete; static inline bool operator==(int, privilege_t)= delete; static inline bool operator==(char, privilege_t)= delete; static inline bool operator==(bool, privilege_t)= delete; static inline bool operator!=(privilege_t, ulonglong)= delete; static inline bool operator!=(privilege_t, ulong)= delete; static inline bool operator!=(privilege_t, uint)= delete; static inline bool operator!=(privilege_t, uchar)= delete; static inline bool operator!=(privilege_t, longlong)= delete; static inline bool operator!=(privilege_t, long)= delete; static inline bool operator!=(privilege_t, int)= delete; static inline bool operator!=(privilege_t, char)= delete; static inline bool operator!=(privilege_t, bool)= delete; static inline bool operator!=(ulonglong, privilege_t)= delete; static inline bool operator!=(ulong, privilege_t)= delete; static inline bool operator!=(uint, privilege_t)= delete; static inline bool operator!=(uchar, privilege_t)= delete; static inline bool operator!=(longlong, privilege_t)= delete; static inline bool operator!=(long, privilege_t)= delete; static inline bool operator!=(int, privilege_t)= delete; static inline bool operator!=(char, privilege_t)= delete; static inline bool operator!=(bool, privilege_t)= delete; // Dyadic bitwise operators static inline constexpr privilege_t operator&(privilege_t a, privilege_t b) { return static_cast<privilege_t>(static_cast<ulonglong>(a) & static_cast<ulonglong>(b)); } static inline constexpr privilege_t operator&(ulonglong a, privilege_t b) { return static_cast<privilege_t>(a & static_cast<ulonglong>(b)); } static inline constexpr privilege_t operator&(privilege_t a, ulonglong b) { return static_cast<privilege_t>(static_cast<ulonglong>(a) & b); } static inline constexpr privilege_t operator|(privilege_t a, privilege_t b) { return static_cast<privilege_t>(static_cast<ulonglong>(a) | static_cast<ulonglong>(b)); } // Dyadyc bitwise assignment operators static inline privilege_t& operator&=(privilege_t &a, privilege_t b) { return a= a & b; } static inline privilege_t& operator&=(privilege_t &a, ulonglong b) { return a= a & b; } static inline privilege_t& operator|=(privilege_t &a, privilege_t b) { return a= a | b; } /* A combination of all privileges that SUPER used to allow before 10.11.0 */ constexpr privilege_t ALLOWED_BY_SUPER_BEFORE_101100= READ_ONLY_ADMIN_ACL; /* A combination of all privileges that SUPER used to allow before 11.0.0 */ constexpr privilege_t ALLOWED_BY_SUPER_BEFORE_110000= SET_USER_ACL | FEDERATED_ADMIN_ACL | CONNECTION_ADMIN_ACL | REPL_SLAVE_ADMIN_ACL | BINLOG_ADMIN_ACL | BINLOG_REPLAY_ACL | SLAVE_MONITOR_ACL | BINLOG_MONITOR_ACL | REPL_MASTER_ADMIN_ACL; constexpr privilege_t COL_DML_ACLS= SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL; constexpr privilege_t VIEW_ACLS= CREATE_VIEW_ACL | SHOW_VIEW_ACL; constexpr privilege_t STD_TABLE_DDL_ACLS= CREATE_ACL | DROP_ACL | ALTER_ACL; constexpr privilege_t ALL_TABLE_DDL_ACLS= STD_TABLE_DDL_ACLS | INDEX_ACL; constexpr privilege_t COL_ACLS= SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL; constexpr privilege_t PROC_DDL_ACLS= CREATE_PROC_ACL | ALTER_PROC_ACL; constexpr privilege_t SHOW_PROC_WITHOUT_DEFINITION_ACLS= PROC_DDL_ACLS | EXECUTE_ACL; /* When changing this, don't forget to update tables_priv at scripts/mariadb_system_tables.sql, scripts/mariadb_system_tables_fix.sql and scripts/sys_schema/i_s/table_privileges.sql */ constexpr privilege_t TABLE_ACLS= COL_DML_ACLS | ALL_TABLE_DDL_ACLS | VIEW_ACLS | GRANT_ACL | REFERENCES_ACL | TRIGGER_ACL | DELETE_HISTORY_ACL; constexpr privilege_t DB_ACLS= TABLE_ACLS | PROC_DDL_ACLS | EXECUTE_ACL | CREATE_TMP_ACL | LOCK_TABLES_ACL | EVENT_ACL | SHOW_CREATE_ROUTINE_ACL; constexpr privilege_t PROC_ACLS= ALTER_PROC_ACL | EXECUTE_ACL | GRANT_ACL | SHOW_CREATE_ROUTINE_ACL; constexpr privilege_t GLOBAL_ACLS= DB_ACLS | SHOW_DB_ACL | CREATE_USER_ACL | CREATE_TABLESPACE_ACL | SUPER_ACL | RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | REPL_SLAVE_ACL | ALLOWED_BY_SUPER_BEFORE_101100 | ALLOWED_BY_SUPER_BEFORE_110000; constexpr privilege_t DEFAULT_CREATE_PROC_ACLS= ALTER_PROC_ACL | EXECUTE_ACL; constexpr privilege_t SHOW_CREATE_TABLE_ACLS= COL_DML_ACLS | ALL_TABLE_DDL_ACLS | TRIGGER_ACL | REFERENCES_ACL | GRANT_ACL | VIEW_ACLS; /** Table-level privileges which are automatically "granted" to everyone on existing temporary tables (CREATE_ACL is necessary for ALTER ... RENAME). */ constexpr privilege_t TMP_TABLE_ACLS= COL_DML_ACLS | ALL_TABLE_DDL_ACLS | REFERENCES_ACL; constexpr privilege_t PRIV_LOCK_TABLES= SELECT_ACL | LOCK_TABLES_ACL; /* Allow to set an object definer: CREATE DEFINER=xxx {TRIGGER|VIEW|FUNCTION|PROCEDURE} Was SUPER prior to 10.5.2 */ constexpr privilege_t PRIV_DEFINER_CLAUSE= SET_USER_ACL; /* If a VIEW has a `definer=invoker@host` clause and the specified definer does not exists, then - The invoker with REVEAL_MISSING_DEFINER_ACL gets: ERROR: The user specified as a definer ('definer1'@'localhost') doesn't exist - The invoker without MISSING_DEFINER_ACL gets a generic access error, without revealing details that the definer does not exists. TODO: we should eventually test the same privilege when processing other objects that have the DEFINER clause (e.g. routines, triggers). Currently the missing definer is revealed for non-privileged invokers in case of routines, triggers, etc. Was SUPER prior to 10.5.2 */ constexpr privilege_t PRIV_REVEAL_MISSING_DEFINER= SET_USER_ACL; /* Actions that require only the SUPER privilege */ constexpr privilege_t PRIV_DES_DECRYPT_ONE_ARG= SUPER_ACL; constexpr privilege_t PRIV_LOG_BIN_TRUSTED_SP_CREATOR= SUPER_ACL; constexpr privilege_t PRIV_DEBUG= SUPER_ACL; constexpr privilege_t PRIV_SET_GLOBAL_SYSTEM_VARIABLE= SUPER_ACL; constexpr privilege_t PRIV_SET_RESTRICTED_SESSION_SYSTEM_VARIABLE= SUPER_ACL; /* The following variables respected only SUPER_ACL prior to 10.5.2 */ constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_FORMAT= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_DIRECT_NON_TRANSACTIONAL_UPDATES= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_ANNOTATE_ROW_EVENTS= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_ROW_IMAGE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_VAR_SQL_LOG_BIN= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_CACHE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_FILE_CACHE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_STMT_CACHE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_COMMIT_WAIT_COUNT= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_COMMIT_WAIT_USEC= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_ROW_METADATA= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_LEGACY_EVENT_POS= SUPER_ACL | BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_PAGE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_SPAN_MIN= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_EXPIRE_LOGS_DAYS= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_LOG_BIN_COMPRESS= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_LOG_BIN_COMPRESS_MIN_LEN= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_LOG_BIN_TRUST_FUNCTION_CREATORS= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_CACHE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_STMT_CACHE_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_SIZE= BINLOG_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SYNC_BINLOG= BINLOG_ADMIN_ACL; /* Privileges related to --read-only */ // Was super prior to 10.5.2 constexpr privilege_t PRIV_IGNORE_READ_ONLY= READ_ONLY_ADMIN_ACL; // Was super prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_READ_ONLY= READ_ONLY_ADMIN_ACL; /* Privileges related to connection handling. */ // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_IGNORE_INIT_CONNECT= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_IGNORE_MAX_USER_CONNECTIONS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_IGNORE_MAX_CONNECTIONS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_IGNORE_MAX_PASSWORD_ERRORS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_KILL_OTHER_USER_PROCESS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_CONNECT_TIMEOUT= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_DISCONNECT_ON_EXPIRED_PASSWORD= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_EXTRA_MAX_CONNECTIONS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_INIT_CONNECT= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_CONNECTIONS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_CONNECT_ERRORS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_PASSWORD_ERRORS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_PROXY_PROTOCOL_NETWORKS= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SECURE_AUTH= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLOW_LAUNCH_TIME= CONNECTION_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_THREAD_POOL= CONNECTION_ADMIN_ACL; /* Binary log related privileges that are checked regardless of active replication running. */ /* This command was renamed from "SHOW MASTER STATUS" to "SHOW BINLOG STATUS" in 10.5.2. Was SUPER_ACL | REPL_CLIENT_ACL prior to 10.5.2 REPL_CLIENT_ACL was renamed to BINLOG_MONITOR_ACL. */ constexpr privilege_t PRIV_STMT_SHOW_BINLOG_STATUS= BINLOG_MONITOR_ACL; /* Was SUPER_ACL | REPL_CLIENT_ACL prior to 10.5.2 REPL_CLIENT_ACL was renamed to BINLOG_MONITOR_ACL. */ constexpr privilege_t PRIV_STMT_SHOW_BINARY_LOGS= BINLOG_MONITOR_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_PURGE_BINLOG= BINLOG_ADMIN_ACL; // Was REPL_SLAVE_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_SHOW_BINLOG_EVENTS= BINLOG_MONITOR_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_DO_DB = BINLOG_ADMIN_ACL | SUPER_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_IGNORE_DB = BINLOG_ADMIN_ACL | SUPER_ACL; /* Privileges for replication related statements and commands that are executed on the master. */ constexpr privilege_t PRIV_COM_REGISTER_SLAVE= REPL_SLAVE_ACL; constexpr privilege_t PRIV_COM_BINLOG_DUMP= REPL_SLAVE_ACL; // Was REPL_SLAVE_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_SHOW_SLAVE_HOSTS= REPL_MASTER_ADMIN_ACL; /* Replication master related variable privileges. Where SUPER prior to 10.5.2 */ constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_MASTER_ENABLED= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_MASTER_TIMEOUT= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_MASTER_WAIT_NO_SLAVE= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_MASTER_TRACE_LEVEL= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_MASTER_WAIT_POINT= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_MASTER_VERIFY_CHECKSUM= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_BINLOG_STATE= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SERVER_ID= REPL_MASTER_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_DOMAIN_ID= REPL_MASTER_ADMIN_ACL; /* Privileges for statements that are executed on the slave */ // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_START_SLAVE= REPL_SLAVE_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_STOP_SLAVE= REPL_SLAVE_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_CHANGE_MASTER= REPL_SLAVE_ADMIN_ACL; // Was (SUPER_ACL | REPL_CLIENT_ACL) prior to 10.5.2 // Was (SUPER_ACL | REPL_SLAVE_ADMIN_ACL) from 10.5.2 to 10.5.7 constexpr privilege_t PRIV_STMT_SHOW_SLAVE_STATUS= SLAVE_MONITOR_ACL; // Was REPL_SLAVE_ACL prior to 10.5.2 // Was REPL_SLAVE_ADMIN_ACL from 10.5.2 to 10.5.7 constexpr privilege_t PRIV_STMT_SHOW_RELAYLOG_EVENTS= SLAVE_MONITOR_ACL; /* Privileges related to binlog replying. Were SUPER_ACL prior to 10.5.2 */ constexpr privilege_t PRIV_STMT_BINLOG= BINLOG_REPLAY_ACL; constexpr privilege_t PRIV_SET_SYSTEM_SESSION_VAR_GTID_SEQ_NO= BINLOG_REPLAY_ACL; constexpr privilege_t PRIV_SET_SYSTEM_SESSION_VAR_PSEUDO_THREAD_ID= BINLOG_REPLAY_ACL; constexpr privilege_t PRIV_SET_SYSTEM_SESSION_VAR_SERVER_ID= BINLOG_REPLAY_ACL; constexpr privilege_t PRIV_SET_SYSTEM_SESSION_VAR_GTID_DOMAIN_ID= BINLOG_REPLAY_ACL; /* Privileges for slave related global variables. Were SUPER prior to 10.5.2. */ constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_EVENTS_MARKED_FOR_SKIP= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_REWRITE_DB= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_DO_DB= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_DO_TABLE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_IGNORE_DB= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_IGNORE_TABLE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_WILD_DO_TABLE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_REPLICATE_WILD_IGNORE_TABLE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_READ_BINLOG_SPEED_LIMIT= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_COMPRESSED_PROTOCOL= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_DDL_EXEC_MODE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_DOMAIN_PARALLEL_THREADS= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_EXEC_MODE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_MAX_ALLOWED_PACKET= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_MAX_STATEMENT_TIME= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_NET_TIMEOUT= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_PARALLEL_MAX_QUEUED= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_PARALLEL_MODE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_PARALLEL_THREADS= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_PARALLEL_WORKERS= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_RUN_TRIGGERS_FOR_RBR= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_SQL_VERIFY_CHECKSUM= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_TRANSACTION_RETRY_INTERVAL= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SLAVE_TYPE_CONVERSIONS= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_INIT_SLAVE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_SLAVE_ENABLED= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_SLAVE_DELAY_MASTER= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RPL_SEMI_SYNC_SLAVE_KILL_CONN_TIMEOUT= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RELAY_LOG_PURGE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_RELAY_LOG_RECOVERY= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SYNC_MASTER_INFO= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SYNC_RELAY_LOG= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_SYNC_RELAY_LOG_INFO= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_CLEANUP_BATCH_SIZE= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_IGNORE_DUPLICATES= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_POS_AUTO_ENGINES= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_SLAVE_POS= REPL_SLAVE_ADMIN_ACL; constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_GTID_STRICT_MODE= REPL_SLAVE_ADMIN_ACL; /* Privileges for federated database related statements */ // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_CREATE_SERVER= FEDERATED_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_ALTER_SERVER= FEDERATED_ADMIN_ACL; // Was SUPER_ACL prior to 10.5.2 constexpr privilege_t PRIV_STMT_DROP_SERVER= FEDERATED_ADMIN_ACL; /* Privileges related to processes */ constexpr privilege_t PRIV_COM_PROCESS_INFO= PROCESS_ACL; // This privilege applies both for SHOW EXPLAIN and SHOW ANALYZE constexpr privilege_t PRIV_STMT_SHOW_EXPLAIN= PROCESS_ACL; constexpr privilege_t PRIV_STMT_SHOW_ENGINE_STATUS= PROCESS_ACL; constexpr privilege_t PRIV_STMT_SHOW_ENGINE_MUTEX= PROCESS_ACL; constexpr privilege_t PRIV_STMT_SHOW_PROCESSLIST= PROCESS_ACL; /* Defines to change the above bits to how things are stored in tables This is needed as the 'host' and 'db' table is missing a few privileges */ /* Privileges that need to be reallocated (in continous chunks) */ constexpr privilege_t DB_CHUNK0 (COL_DML_ACLS | CREATE_ACL | DROP_ACL); constexpr privilege_t DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL); constexpr privilege_t DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL); constexpr privilege_t DB_CHUNK3 (VIEW_ACLS | PROC_DDL_ACLS); constexpr privilege_t DB_CHUNK4 (EXECUTE_ACL); constexpr privilege_t DB_CHUNK5 (EVENT_ACL | TRIGGER_ACL); constexpr privilege_t DB_CHUNK6 (DELETE_HISTORY_ACL); constexpr privilege_t DB_CHUNK7 (SHOW_CREATE_ROUTINE_ACL); static inline privilege_t fix_rights_for_db(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> (((A) & DB_CHUNK0) | ((A << 4) & DB_CHUNK1) | ((A << 6) & DB_CHUNK2) | ((A << 9) & DB_CHUNK3) | ((A << 2) & DB_CHUNK4) | ((A << 9) & DB_CHUNK5) | ((A << 10) & DB_CHUNK6) | ((A << 19) & DB_CHUNK7)); } static inline privilege_t get_rights_for_db(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> ((A & DB_CHUNK0) | ((A & DB_CHUNK1) >> 4) | ((A & DB_CHUNK2) >> 6) | ((A & DB_CHUNK3) >> 9) | ((A & DB_CHUNK4) >> 2) | ((A & DB_CHUNK5) >> 9) | ((A & DB_CHUNK6) >> 10) | ((A & DB_CHUNK7) >> 19)); } #define TBL_CHUNK0 DB_CHUNK0 #define TBL_CHUNK1 DB_CHUNK1 #define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL) #define TBL_CHUNK3 TRIGGER_ACL #define TBL_CHUNK4 (DELETE_HISTORY_ACL) static inline privilege_t fix_rights_for_table(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> ((A & TBL_CHUNK0) | ((A << 4) & TBL_CHUNK1) | ((A << 11) & TBL_CHUNK2) | ((A << 15) & TBL_CHUNK3) | ((A << 16) & TBL_CHUNK4)); } static inline privilege_t get_rights_for_table(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> ((A & TBL_CHUNK0) | ((A & TBL_CHUNK1) >> 4) | ((A & TBL_CHUNK2) >> 11) | ((A & TBL_CHUNK3) >> 15) | ((A & TBL_CHUNK4) >> 16)); } static inline privilege_t fix_rights_for_column(privilege_t A) { const ulonglong mask(SELECT_ACL | INSERT_ACL | UPDATE_ACL); return (A & mask) | static_cast<privilege_t>((A & ~mask) << 8); } static inline privilege_t get_rights_for_column(privilege_t A) { const ulonglong mask(SELECT_ACL | INSERT_ACL | UPDATE_ACL); return static_cast<privilege_t>((static_cast<ulonglong>(A) & mask) | (static_cast<ulonglong>(A) >> 8)); } static inline privilege_t fix_rights_for_procedure(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> (((A << 35) & SHOW_CREATE_ROUTINE_ACL) | ((A << 18) & EXECUTE_ACL) | ((A << 23) & ALTER_PROC_ACL) | ((A << 8) & GRANT_ACL)); } static inline privilege_t get_rights_for_procedure(privilege_t access) { ulonglong A(access); return static_cast<privilege_t> (((A & SHOW_CREATE_ROUTINE_ACL) >> 35) | ((A & EXECUTE_ACL) >> 18) | ((A & ALTER_PROC_ACL) >> 23) | ((A & GRANT_ACL) >> 8)); } #endif /* PRIVILEGE_H_INCLUDED */ my_base.h 0000644 00000066442 15156036126 0006355 0 ustar 00 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 1995, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file includes constants used with all databases */ #ifndef _my_base_h #define _my_base_h #include <my_dir.h> /* This includes types */ #include <my_sys.h> #include <m_string.h> #include <errno.h> #ifndef EOVERFLOW #define EOVERFLOW 84 #endif #include <my_list.h> /* The following is bits in the flag parameter to ha_open() */ #define HA_OPEN_ABORT_IF_LOCKED 0U /* default */ #define HA_OPEN_WAIT_IF_LOCKED 1U #define HA_OPEN_IGNORE_IF_LOCKED 2U /* Ignore lock error */ #define HA_OPEN_TMP_TABLE 4U /* Table is a temp table */ #define HA_OPEN_DELAY_KEY_WRITE 8U /* Don't update index */ #define HA_OPEN_ABORT_IF_CRASHED 16U #define HA_OPEN_FOR_REPAIR 32U /* open even if crashed */ #define HA_OPEN_FROM_SQL_LAYER 64U #define HA_OPEN_MMAP 128U /* open memory mapped */ #define HA_OPEN_COPY 256U /* Open copy (for repair) */ /* Internal temp table, used for temporary results */ #define HA_OPEN_INTERNAL_TABLE 512U #define HA_OPEN_NO_PSI_CALL 1024U /* Don't call/connect PSI */ #define HA_OPEN_MERGE_TABLE 2048U #define HA_OPEN_FOR_CREATE 4096U #define HA_OPEN_FOR_DROP (1U << 13) /* Open part of drop */ #define HA_OPEN_GLOBAL_TMP_TABLE (1U << 14) /* TMP table used by repliction */ /* This is to signal that the table will not be cached by the caller and the table should be open in read-only mode if the tool requests that */ #define HA_OPEN_FORCE_MODE (1U << 15) /* Force open mode */ #define HA_OPEN_DATA_READONLY (1U << 16) /* Use readonly for data */ /* Allow opening even if table is incompatible as this is for ALTER TABLE which will fix the table structure. */ #define HA_OPEN_FOR_ALTER 8192U /* Open table for FLUSH */ #define HA_OPEN_FOR_FLUSH 8192U /* The following is parameter to ha_rkey() how to use key */ /* We define a complete-field prefix of a key value as a prefix where the last included field in the prefix contains the full field, not just some bytes from the start of the field. A partial-field prefix is allowed to contain only a few first bytes from the last included field. Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a complete-field prefix of a key value as the search key. HA_READ_PREFIX and HA_READ_PREFIX_LAST could also take a partial-field prefix, but currently (4.0.10) they are only used with complete-field prefixes. MySQL uses a padding trick to implement LIKE 'abc%' queries. NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a partial-field prefix because InnoDB currently strips spaces from the end of varchar fields! */ enum ha_rkey_function { HA_READ_KEY_EXACT, /* Find first record else error */ HA_READ_KEY_OR_NEXT, /* Record or next record */ HA_READ_KEY_OR_PREV, /* Record or previous */ HA_READ_AFTER_KEY, /* Find next rec. after key-record */ HA_READ_BEFORE_KEY, /* Find next rec. before key-record */ HA_READ_PREFIX, /* Key which as same prefix */ HA_READ_PREFIX_LAST, /* Last key with the same prefix */ HA_READ_PREFIX_LAST_OR_PREV, /* Last or prev key with the same prefix */ HA_READ_MBR_CONTAIN, HA_READ_MBR_INTERSECT, HA_READ_MBR_WITHIN, HA_READ_MBR_DISJOINT, HA_READ_MBR_EQUAL }; /* Key algorithm types */ enum ha_key_alg { HA_KEY_ALG_UNDEF= 0, /* Not specified (old file) */ HA_KEY_ALG_BTREE= 1, /* B-tree, default one */ HA_KEY_ALG_RTREE= 2, /* R-tree, for spatial searches */ HA_KEY_ALG_HASH= 3, /* HASH keys (HEAP tables) */ HA_KEY_ALG_FULLTEXT= 4, /* FULLTEXT (MyISAM tables) */ HA_KEY_ALG_LONG_HASH= 5, /* long BLOB keys */ HA_KEY_ALG_UNIQUE_HASH= 6 /* Internal UNIQUE hash (Aria) */ }; /* Storage media types */ enum ha_storage_media { HA_SM_DEFAULT= 0, /* Not specified (engine default) */ HA_SM_DISK= 1, /* DISK storage */ HA_SM_MEMORY= 2 /* MAIN MEMORY storage */ }; /* The following is parameter to ha_extra() */ enum ha_extra_function { HA_EXTRA_NORMAL=0, /* Optimize for space (def) */ HA_EXTRA_QUICK=1, /* Optimize for speed */ HA_EXTRA_NOT_USED=2, /* Should be ignored by handler */ HA_EXTRA_CACHE=3, /* Cache record in HA_rrnd() */ HA_EXTRA_NO_CACHE=4, /* End caching of records (def) */ HA_EXTRA_NO_READCHECK=5, /* No readcheck on update */ HA_EXTRA_READCHECK=6, /* Use readcheck (def) */ HA_EXTRA_KEYREAD=7, /* Read only key to database */ HA_EXTRA_NO_KEYREAD=8, /* Normal read of records (def) */ HA_EXTRA_NO_USER_CHANGE=9, /* No user is allowed to write */ HA_EXTRA_KEY_CACHE=10, HA_EXTRA_NO_KEY_CACHE=11, HA_EXTRA_WAIT_LOCK=12, /* Wait until file is available (def) */ HA_EXTRA_NO_WAIT_LOCK=13, /* If file is locked, return quickly */ HA_EXTRA_WRITE_CACHE=14, /* Use write cache in ha_write() */ HA_EXTRA_FLUSH_CACHE=15, /* flush write_record_cache */ HA_EXTRA_NO_KEYS=16, /* Remove all update of keys */ HA_EXTRA_KEYREAD_CHANGE_POS=17, /* Keyread, but change pos */ /* xxxxchk -r must be used */ HA_EXTRA_REMEMBER_POS=18, /* Remember pos for next/prev */ HA_EXTRA_RESTORE_POS=19, HA_EXTRA_REINIT_CACHE=20, /* init cache from current record */ HA_EXTRA_FORCE_REOPEN=21, /* Datafile have changed on disk */ HA_EXTRA_FLUSH, /* Flush tables to disk */ HA_EXTRA_NO_ROWS, /* Don't write rows */ HA_EXTRA_RESET_STATE, /* Reset positions */ HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/ HA_EXTRA_NO_IGNORE_DUP_KEY, HA_EXTRA_PREPARE_FOR_DROP, HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */ /* On-the-fly switching between unique and non-unique key inserting. */ HA_EXTRA_CHANGE_KEY_TO_UNIQUE, HA_EXTRA_CHANGE_KEY_TO_DUP, /* When using HA_EXTRA_KEYREAD, overwrite only key member fields and keep other fields intact. When this is off (by default) InnoDB will use memcpy to overwrite entire row. */ HA_EXTRA_KEYREAD_PRESERVE_FIELDS, HA_EXTRA_MMAP, /* Ignore if the a tuple is not found, continue processing the transaction and ignore that 'row'. Needed for idempotency handling on the slave */ HA_EXTRA_IGNORE_NO_KEY, HA_EXTRA_NO_IGNORE_NO_KEY, /* Mark the table as a log table. For some handlers (e.g. CSV) this results in a special locking for the table. */ HA_EXTRA_MARK_AS_LOG_TABLE, /* Informs handler that write_row() which tries to insert new row into the table and encounters some already existing row with same primary/unique key can replace old row with new row instead of reporting error (basically it informs handler that we do REPLACE instead of simple INSERT). Off by default. */ HA_EXTRA_WRITE_CAN_REPLACE, HA_EXTRA_WRITE_CANNOT_REPLACE, /* Inform handler that delete_row()/update_row() cannot batch deletes/updates and should perform them immediately. This may be needed when table has AFTER DELETE/UPDATE triggers which access to subject table. These flags are reset by the handler::extra(HA_EXTRA_RESET) call. */ HA_EXTRA_DELETE_CANNOT_BATCH, HA_EXTRA_UPDATE_CANNOT_BATCH, /* Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY. */ HA_EXTRA_INSERT_WITH_UPDATE, /* Inform handler that we will do a rename */ HA_EXTRA_PREPARE_FOR_RENAME, /* Special actions for MERGE tables. */ HA_EXTRA_ADD_CHILDREN_LIST, HA_EXTRA_ATTACH_CHILDREN, HA_EXTRA_IS_ATTACHED_CHILDREN, HA_EXTRA_DETACH_CHILDREN, HA_EXTRA_DETACH_CHILD, /* Inform handler we will force a close as part of flush */ HA_EXTRA_PREPARE_FOR_FORCED_CLOSE, /* Inform handler that we will do an alter table */ HA_EXTRA_PREPARE_FOR_ALTER_TABLE, /* Used in ha_partition::handle_ordered_index_scan() to inform engine that we are starting an ordered index scan. Needed by Spider */ HA_EXTRA_STARTING_ORDERED_INDEX_SCAN, /** Start writing rows during ALTER TABLE...ALGORITHM=COPY. */ HA_EXTRA_BEGIN_ALTER_COPY, /** Finish writing rows during ALTER TABLE...ALGORITHM=COPY. */ HA_EXTRA_END_ALTER_COPY, /** Abort of writing rows during ALTER TABLE..ALGORITHM=COPY or CREATE..SELCT */ HA_EXTRA_ABORT_ALTER_COPY }; /* Compatible option, to be deleted in 6.0 */ #define HA_EXTRA_PREPARE_FOR_DELETE HA_EXTRA_PREPARE_FOR_DROP /* The following is parameter to ha_panic() */ enum ha_panic_function { HA_PANIC_CLOSE, /* Close all databases */ HA_PANIC_WRITE, /* Unlock and write status */ HA_PANIC_READ /* Lock and read keyinfo */ }; /* The following is parameter to ha_create(); keytypes */ enum ha_base_keytype { HA_KEYTYPE_END=0, HA_KEYTYPE_TEXT=1, /* Key is sorted as letters */ HA_KEYTYPE_BINARY=2, /* Key is sorted as unsigned chars */ HA_KEYTYPE_SHORT_INT=3, HA_KEYTYPE_LONG_INT=4, HA_KEYTYPE_FLOAT=5, HA_KEYTYPE_DOUBLE=6, HA_KEYTYPE_NUM=7, /* Not packed num with pre-space */ HA_KEYTYPE_USHORT_INT=8, HA_KEYTYPE_ULONG_INT=9, HA_KEYTYPE_LONGLONG=10, HA_KEYTYPE_ULONGLONG=11, HA_KEYTYPE_INT24=12, HA_KEYTYPE_UINT24=13, HA_KEYTYPE_INT8=14, /* Varchar (0-255 bytes) with length packed with 1 byte */ HA_KEYTYPE_VARTEXT1=15, /* Key is sorted as letters */ HA_KEYTYPE_VARBINARY1=16, /* Key is sorted as unsigned chars */ /* Varchar (0-65535 bytes) with length packed with 2 bytes */ HA_KEYTYPE_VARTEXT2=17, /* Key is sorted as letters */ HA_KEYTYPE_VARBINARY2=18, /* Key is sorted as unsigned chars */ HA_KEYTYPE_BIT=19 }; #define HA_MAX_KEYTYPE 31 /* Must be log2-1 */ /* These flags kan be OR:ed to key-flag Note that these can only be up to 16 bits! */ #define HA_NOSAME 1U /* Set if not dupplicated records */ #define HA_PACK_KEY 2U /* Pack string key to previous key */ #define HA_AUTO_KEY 16U /* MEMORY/MyISAM/Aria internal */ #define HA_BINARY_PACK_KEY 32U /* Packing of all keys to prev key */ #define HA_FULLTEXT 128U /* For full-text search */ #define HA_SPATIAL 1024U /* For spatial search */ #define HA_NULL_ARE_EQUAL 2048U /* NULL in key are cmp as equal */ #define HA_GENERATED_KEY 8192U /* Automatically generated key */ /* Part of unique hash key. Used only for temporary (work) tables so is not written to .frm files. */ #define HA_UNIQUE_HASH 262144U /* The combination of the above can be used for key type comparison. */ #define HA_KEYFLAG_MASK (HA_NOSAME | HA_AUTO_KEY | \ HA_FULLTEXT | \ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \ HA_UNIQUE_HASH) /* Key contains partial segments. This flag is internal to the MySQL server by design. It is not supposed neither to be saved in FRM-files, nor to be passed to storage engines. It is intended to pass information into internal static sort_keys(KEY *, KEY *) function. This flag can be calculated -- it's based on key lengths comparison. */ #define HA_KEY_HAS_PART_KEY_SEG 65536 /* Internal Flag Can be calculated */ #define HA_INVISIBLE_KEY 2<<18 /* Automatic bits in key-flag */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ #define HA_VAR_LENGTH_KEY 8 #define HA_NULL_PART_KEY 64 #define HA_USES_COMMENT 4096 #define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */ #define HA_USES_BLOCK_SIZE ((uint) 32768) #define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */ /* This flag can be used only in KEY::ext_key_flags */ #define HA_EXT_NOSAME 131072 /* These flags can be added to key-seg-flag */ #define HA_SPACE_PACK 1 /* Pack space in key-seg */ #define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */ #define HA_VAR_LENGTH_PART 8 #define HA_NULL_PART 16 #define HA_BLOB_PART 32 #define HA_SWAP_KEY 64 #define HA_REVERSE_SORT 128 /* Sort key in reverse order */ #define HA_NO_SORT 256 /* do not bother sorting on this keyseg */ #define HA_BIT_PART 1024 #define HA_CAN_MEMCMP 2048 /* internal, never stored in frm */ /* optionbits for database */ #define HA_OPTION_PACK_RECORD 1U #define HA_OPTION_PACK_KEYS 2U #define HA_OPTION_COMPRESS_RECORD 4U #define HA_OPTION_LONG_BLOB_PTR 8U /* new ISAM format */ #define HA_OPTION_TMP_TABLE 16U #define HA_OPTION_CHECKSUM 32U #define HA_OPTION_DELAY_KEY_WRITE 64U #define HA_OPTION_NO_PACK_KEYS 128U /* Reserved for MySQL */ /* unused 256 */ #define HA_OPTION_RELIES_ON_SQL_LAYER 512U #define HA_OPTION_NULL_FIELDS 1024U #define HA_OPTION_PAGE_CHECKSUM 2048U /* STATS_PERSISTENT=1 has been specified in the SQL command (either CREATE or ALTER TABLE). Table and index statistics that are collected by the storage engine and used by the optimizer for query optimization will be stored on disk and will not change after a server restart. */ #define HA_OPTION_STATS_PERSISTENT 4096U /* STATS_PERSISTENT=0 has been specified in CREATE/ALTER TABLE. Statistics for the table will be wiped away on server shutdown and new ones recalculated after the server is started again. If none of HA_OPTION_STATS_PERSISTENT or HA_OPTION_NO_STATS_PERSISTENT is set, this means that the setting is not explicitly set at table level and the corresponding table will use whatever is the global server default. */ #define HA_OPTION_NO_STATS_PERSISTENT 8192U /* .frm has extra create options in linked-list format */ #define HA_OPTION_TEXT_CREATE_OPTIONS_legacy (1U << 14) /* 5.2 to 5.5, unused since 10.0 */ #define HA_OPTION_TEMP_COMPRESS_RECORD (1U << 15) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA (1U << 16) /* Set by isamchk */ #define HA_OPTION_NO_CHECKSUM (1U << 17) #define HA_OPTION_NO_DELAY_KEY_WRITE (1U << 18) /* Bits in flag to create() */ #define HA_DONT_TOUCH_DATA 1U /* Don't empty datafile (isamchk) */ #define HA_PACK_RECORD 2U /* Request packed record format */ #define HA_CREATE_TMP_TABLE 4U #define HA_CREATE_CHECKSUM 8U #define HA_CREATE_KEEP_FILES 16U /* don't overwrite .MYD and MYI */ #define HA_CREATE_PAGE_CHECKSUM 32U #define HA_CREATE_DELAY_KEY_WRITE 64U #define HA_CREATE_RELIES_ON_SQL_LAYER 128U #define HA_CREATE_INTERNAL_TABLE 256U #define HA_PRESERVE_INSERT_ORDER 512U #define HA_CREATE_NO_ROLLBACK 1024U /* A temporary table that can be used by different threads, eg. replication threads. This flag ensure that memory is not allocated with THREAD_SPECIFIC, as we do for other temporary tables. */ #define HA_CREATE_GLOBAL_TMP_TABLE 2048U /* Flags used by start_bulk_insert */ #define HA_CREATE_UNIQUE_INDEX_BY_SORT 1U /* The following flags (OR-ed) are passed to handler::info() method. The method copies misc handler information out of the storage engine to data structures accessible from MySQL Same flags are also passed down to mi_status, myrg_status, etc. */ /* this one is not used */ #define HA_STATUS_POS 1U /* assuming the table keeps shared actual copy of the 'info' and local, possibly outdated copy, the following flag means that it should not try to get the actual data (locking the shared structure) slightly outdated version will suffice */ #define HA_STATUS_NO_LOCK 2U /* update the time of the last modification (in handler::update_time) */ #define HA_STATUS_TIME 4U /* update the 'constant' part of the info: handler::max_data_file_length, max_index_file_length, create_time sortkey, ref_length, block_size, data_file_name, index_file_name. handler::table->s->keys_in_use, keys_for_keyread, rec_per_key */ #define HA_STATUS_CONST 8U /* update the 'variable' part of the info: handler::records, deleted, data_file_length, index_file_length, check_time, mean_rec_length */ #define HA_STATUS_VARIABLE 16U /* get the information about the key that caused last duplicate value error update handler::errkey and handler::dupp_ref see handler::get_dup_key() */ #define HA_STATUS_ERRKEY 32U /* update handler::auto_increment_value */ #define HA_STATUS_AUTO 64U /* Get also delete_length when HA_STATUS_VARIABLE is called. It's ok to set it also when only HA_STATUS_VARIABLE but it won't be used. */ #define HA_STATUS_VARIABLE_EXTRA 128U /* Treat empty table as empty (ignore HA_STATUS_TIME hack). */ #define HA_STATUS_OPEN 256U /* Errorcodes given by handler functions opt_sum_query() assumes these codes are > 1 Do not add error numbers before HA_ERR_FIRST. If necessary to add lower numbers, change HA_ERR_FIRST accordingly. */ #define HA_ERR_FIRST 120 /* Copy of first error nr.*/ #define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ #define HA_ERR_FOUND_DUPP_KEY 121 /* Duplicate key on write */ #define HA_ERR_INTERNAL_ERROR 122 /* Internal error */ #define HA_ERR_RECORD_CHANGED 123 /* Update with is recoverable */ #define HA_ERR_WRONG_INDEX 124 /* Wrong index given to function */ #define HA_ERR_CRASHED 126 /* Indexfile is crashed */ #define HA_ERR_WRONG_IN_RECORD 127 /* Record-file is crashed */ #define HA_ERR_OUT_OF_MEM 128 /* Out of memory */ #define HA_ERR_RETRY_INIT 129 /* Initialization failed and should be retried */ #define HA_ERR_NOT_A_TABLE 130 /* not a MYI file - no signature */ #define HA_ERR_WRONG_COMMAND 131 /* Command not supported */ #define HA_ERR_OLD_FILE 132 /* old databasfile */ #define HA_ERR_NO_ACTIVE_RECORD 133 /* No record read in update() */ #define HA_ERR_RECORD_DELETED 134 /* A record is not there */ #define HA_ERR_RECORD_FILE_FULL 135 /* No more room in file */ #define HA_ERR_INDEX_FILE_FULL 136 /* No more room in file */ #define HA_ERR_END_OF_FILE 137 /* end in next/prev/first/last */ #define HA_ERR_UNSUPPORTED 138 /* unsupported extension used */ #define HA_ERR_TO_BIG_ROW 139 /* Too big row */ #define HA_WRONG_CREATE_OPTION 140 /* Wrong create option */ #define HA_ERR_FOUND_DUPP_UNIQUE 141 /* Duplicate unique on write */ #define HA_ERR_UNKNOWN_CHARSET 142 /* Can't open charset */ #define HA_ERR_WRONG_MRG_TABLE_DEF 143 /* conflicting tables in MERGE */ #define HA_ERR_CRASHED_ON_REPAIR 144 /* Last (automatic?) repair failed */ #define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */ #define HA_ERR_LOCK_WAIT_TIMEOUT 146 #define HA_ERR_LOCK_TABLE_FULL 147 #define HA_ERR_READ_ONLY_TRANSACTION 148 /* Updates not allowed */ #define HA_ERR_LOCK_DEADLOCK 149 #define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */ #define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */ #define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */ #define HA_ERR_NO_SAVEPOINT 153 /* No savepoint with that name */ #define HA_ERR_NON_UNIQUE_BLOCK_SIZE 154 /* Non unique key block size */ #define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */ #define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */ #define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */ /* NULLs are not supported in spatial index */ #define HA_ERR_NULL_IN_SPATIAL 158 #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ /* There's no partition in table for given value */ #define HA_ERR_NO_PARTITION_FOUND 160 #define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ #define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr */ /* Upholding foreign key constraints would lead to a duplicate key error in some other table. */ #define HA_ERR_FOREIGN_DUPLICATE_KEY 163 /* The table changed in storage engine */ #define HA_ERR_TABLE_NEEDS_UPGRADE 164 #define HA_ERR_TABLE_READONLY 165 /* The table is not writable */ #define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */ #define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */ #define HA_ERR_GENERIC 168 /* Generic error */ /* row not actually updated: new values same as the old values */ #define HA_ERR_RECORD_IS_THE_SAME 169 #define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this statement */ #define HA_ERR_CORRUPT_EVENT 171 /* The event was corrupt, leading to illegal data being read */ #define HA_ERR_NEW_FILE 172 /* New file format */ #define HA_ERR_ROWS_EVENT_APPLY 173 /* The event could not be processed no other handler error happened */ #define HA_ERR_INITIALIZATION 174 /* Error during initialization */ #define HA_ERR_FILE_TOO_SHORT 175 /* File too short */ #define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */ #define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */ /* There's no explicitly listed partition in table for the given value */ #define HA_ERR_NOT_IN_LOCK_PARTITIONS 178 #define HA_ERR_INDEX_COL_TOO_LONG 179 /* Index column length exceeds limit */ #define HA_ERR_INDEX_CORRUPT 180 /* Index corrupted */ #define HA_ERR_UNDO_REC_TOO_BIG 181 /* Undo log record too big */ #define HA_FTS_INVALID_DOCID 182 /* Invalid InnoDB Doc ID */ /* #define HA_ERR_TABLE_IN_FK_CHECK 183 */ /* Table being used in foreign key check */ #define HA_ERR_TABLESPACE_EXISTS 184 /* The tablespace existed in storage engine */ #define HA_ERR_TOO_MANY_FIELDS 185 /* Table has too many columns */ #define HA_ERR_ROW_IN_WRONG_PARTITION 186 /* Row in wrong partition */ #define HA_ERR_ROW_NOT_VISIBLE 187 #define HA_ERR_ABORTED_BY_USER 188 #define HA_ERR_DISK_FULL 189 #define HA_ERR_INCOMPATIBLE_DEFINITION 190 #define HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE 191 /* Too many words in a phrase */ #define HA_ERR_DECRYPTION_FAILED 192 /* Table encrypted but decrypt failed */ #define HA_ERR_FK_DEPTH_EXCEEDED 193 /* FK cascade depth exceeded */ #define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */ #define HA_ERR_SEQUENCE_INVALID_DATA 195 #define HA_ERR_SEQUENCE_RUN_OUT 196 #define HA_ERR_COMMIT_ERROR 197 #define HA_ERR_PARTITION_LIST 198 #define HA_ERR_NO_ENCRYPTION 199 #define HA_ERR_ROLLBACK 200 /* Automatic rollback done */ #define HA_ERR_LAST 200 /* Copy of last error nr * */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) /* aliases */ #define HA_ERR_TABLE_CORRUPT HA_ERR_WRONG_IN_RECORD #define HA_ERR_QUERY_INTERRUPTED HA_ERR_ABORTED_BY_USER #define HA_ERR_NOT_ALLOWED_COMMAND HA_ERR_WRONG_COMMAND /* Other constants */ #define HA_NAMELEN 64 /* Max length of saved filename */ #define NO_SUCH_KEY (~(uint)0) /* used as a key no. */ typedef ulong key_part_map; #define HA_WHOLE_KEY (~(key_part_map)0) /* Intern constants in databases */ /* bits in _search */ #define SEARCH_FIND 1U #define SEARCH_NO_FIND 2U #define SEARCH_SAME 4U #define SEARCH_BIGGER 8U #define SEARCH_SMALLER 16U #define SEARCH_SAVE_BUFF 32U #define SEARCH_UPDATE 64U #define SEARCH_PREFIX 128U #define SEARCH_LAST 256U #define MBR_CONTAIN 512U #define MBR_INTERSECT 1024U #define MBR_WITHIN 2048U #define MBR_DISJOINT 4096U #define MBR_EQUAL 8192U #define MBR_DATA 16384U #define SEARCH_NULL_ARE_EQUAL 32768U /* NULL in keys are equal */ #define SEARCH_NULL_ARE_NOT_EQUAL 65536U/* NULL in keys are not equal */ /* Use this when inserting a key in position order */ #define SEARCH_INSERT (SEARCH_NULL_ARE_NOT_EQUAL*2) /* Only part of the key is specified while reading */ #define SEARCH_PART_KEY (SEARCH_INSERT*2) /* Used when user key (key 2) contains transaction id's */ #define SEARCH_USER_KEY_HAS_TRANSID (SEARCH_PART_KEY*2) /* Used when page key (key 1) contains transaction id's */ #define SEARCH_PAGE_KEY_HAS_TRANSID (SEARCH_USER_KEY_HAS_TRANSID*2) /* bits in opt_flag */ #define QUICK_USED 1U #define READ_CACHE_USED 2U #define READ_CHECK_USED 4U #define KEY_READ_USED 8U #define WRITE_CACHE_USED 16U #define OPT_NO_ROWS 32U /* bits in update */ #define HA_STATE_CHANGED 1U /* Database has changed */ #define HA_STATE_AKTIV 2U /* Has a current record */ #define HA_STATE_WRITTEN 4U /* Record is written */ #define HA_STATE_DELETED 8U #define HA_STATE_NEXT_FOUND 16U /* Next found record (record before) */ #define HA_STATE_PREV_FOUND 32U /* Prev found record (record after) */ #define HA_STATE_NO_KEY 64U /* Last read didn't find record */ #define HA_STATE_KEY_CHANGED 128U #define HA_STATE_WRITE_AT_END 256U /* set in _ps_find_writepos */ #define HA_STATE_BUFF_SAVED 512U /* If current keybuff is info->buff */ #define HA_STATE_ROW_CHANGED 1024U /* To invalidate ROW cache */ #define HA_STATE_EXTEND_BLOCK 2048U #define HA_STATE_RNEXT_SAME 4096U /* rnext_same occupied lastkey2 */ /* myisampack expects no more than 32 field types. */ enum en_fieldtype { FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, FIELD_VARCHAR,FIELD_CHECK, FIELD_enum_val_count }; enum data_file_type { STATIC_RECORD, DYNAMIC_RECORD, COMPRESSED_RECORD, BLOCK_RECORD, NO_RECORD }; /* For key ranges */ #define NO_MIN_RANGE 1U #define NO_MAX_RANGE 2U #define NEAR_MIN 4U #define NEAR_MAX 8U #define UNIQUE_RANGE 16U #define EQ_RANGE 32U #define NULL_RANGE 64U #define GEOM_FLAG 128U typedef struct st_key_range { const uchar *key; uint length; key_part_map keypart_map; enum ha_rkey_function flag; } key_range; typedef void *range_id_t; typedef struct st_key_multi_range { key_range start_key; key_range end_key; range_id_t ptr; /* Free to use by caller (ptr to row etc) */ /* A set of range flags that describe both endpoints: UNIQUE_RANGE, NULL_RANGE, EQ_RANGE, GEOM_FLAG. (Flags that describe one endpoint, NO_{MIN|MAX}_RANGE, NEAR_{MIN|MAX} will not be set here) */ uint range_flag; } KEY_MULTI_RANGE; /* Store first and last leaf page accessed by records_in_range */ typedef struct st_page_range { ulonglong first_page; ulonglong last_page; } page_range; #define UNUSED_PAGE_NO ULONGLONG_MAX #define unused_page_range { UNUSED_PAGE_NO, UNUSED_PAGE_NO } /* For number of records */ #ifdef BIG_TABLES #define rows2double(A) ulonglong2double(A) typedef my_off_t ha_rows; #else #define rows2double(A) (double) (A) typedef ulong ha_rows; #endif #define HA_POS_ERROR (~ (ha_rows) 0) #define HA_OFFSET_ERROR (~ (my_off_t) 0) #define HA_ROWS_MAX HA_POS_ERROR #if SIZEOF_OFF_T == 4 #define MAX_FILE_SIZE INT_MAX32 #else #define MAX_FILE_SIZE LONGLONG_MAX #endif #define HA_VARCHAR_PACKLENGTH(field_length) ((field_length) < 256 ? 1 :2) /* invalidator function reference for Query Cache */ C_MODE_START typedef void (* invalidator_by_filename)(const char * filename); C_MODE_END #endif /* _my_base_h */ tzfile.h 0000644 00000011626 15156036126 0006225 0 ustar 00 #ifndef TZFILE_INCLUDED #define TZFILE_INCLUDED /* Copyright (c) 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file is based on public domain code from ftp://elsie.ncih.nist.gov/ Initial source code is in the public domain, so clarified as of 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). */ /* Information about time zone files. */ #ifndef TZDIR #define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ #endif /* !defined TZDIR */ /* Each file begins with. . . */ #define TZ_MAGIC "TZif" struct tzhead { uchar tzh_magic[4]; /* TZ_MAGIC */ uchar tzh_reserved[16]; /* reserved for future use */ uchar tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ uchar tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ uchar tzh_leapcnt[4]; /* coded number of leap seconds */ uchar tzh_timecnt[4]; /* coded number of transition times */ uchar tzh_typecnt[4]; /* coded number of local time types */ uchar tzh_charcnt[4]; /* coded number of abbr. chars */ }; /* . . .followed by. . . tzh_timecnt (char [4])s coded transition times a la time(2) tzh_timecnt (unsigned char)s types of local time starting at above tzh_typecnt repetitions of one (char [4]) coded UTC offset in seconds one (unsigned char) used to set tm_isdst one (unsigned char) that's an abbreviation list index tzh_charcnt (char)s '\0'-terminated zone abbreviations tzh_leapcnt repetitions of one (char [4]) coded leap second transition times one (char [4]) total correction after above tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition time is standard time, if FALSE, transition time is wall clock time if absent, transition times are assumed to be wall clock time tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition time is UTC, if FALSE, transition time is local time if absent, transition times are assumed to be local time */ /* In the current implementation, we refuse to deal with files that exceed any of the limits below. */ #ifndef TZ_MAX_TIMES /* The TZ_MAX_TIMES value below is enough to handle a bit more than a year's worth of solar time (corrected daily to the nearest second) or 138 years of Pacific Presidential Election time (where there are three time zone transitions every fourth year). */ #define TZ_MAX_TIMES 370 #endif /* !defined TZ_MAX_TIMES */ #ifndef TZ_MAX_TYPES #ifdef SOLAR #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #else /* Must be at least 14 for Europe/Riga as of Jan 12 1995, as noted by Earl Chew <earl@hpato.aus.hp.com>. */ #define TZ_MAX_TYPES 20 /* Maximum number of local time types */ #endif /* defined SOLAR */ #endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ /* (limited by what unsigned chars can hold) */ #endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ #endif /* !defined TZ_MAX_LEAPS */ #ifndef TZ_MAX_REV_RANGES #ifdef SOLAR /* Solar (Asia/RiyadhXX) zones need significantly bigger TZ_MAX_REV_RANGES */ #define TZ_MAX_REV_RANGES (TZ_MAX_TIMES*2+TZ_MAX_LEAPS*2+2) #else #define TZ_MAX_REV_RANGES (TZ_MAX_TIMES+TZ_MAX_LEAPS+2) #endif #endif #define SECS_PER_MIN 60 #define MINS_PER_HOUR 60 #define HOURS_PER_DAY 24 #define DAYS_PER_WEEK 7 #define DAYS_PER_NYEAR 365 #define DAYS_PER_LYEAR 366 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) #define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY) #define MONS_PER_YEAR 12 #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 /* Accurate only for the past couple of centuries, that will probably do. */ #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) #endif mdl.h 0000644 00000113233 15156036126 0005501 0 ustar 00 #ifndef MDL_H #define MDL_H /* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2020, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_plist.h" #include "ilist.h" #include <my_sys.h> #include <m_string.h> #include <mysql_com.h> #include <lf.h> #include "lex_ident.h" class THD; class MDL_context; class MDL_lock; class MDL_ticket; typedef unsigned short mdl_bitmap_t; #define MDL_BIT(A) static_cast<mdl_bitmap_t>(1U << A) /** @def ENTER_COND(C, M, S, O) Start a wait on a condition. @param C the condition to wait on @param M the associated mutex @param S the new stage to enter @param O the previous stage @sa EXIT_COND(). */ #define ENTER_COND(C, M, S, O) enter_cond(C, M, S, O, __func__, __FILE__, __LINE__) /** @def EXIT_COND(S) End a wait on a condition @param S the new stage to enter */ #define EXIT_COND(S) exit_cond(S, __func__, __FILE__, __LINE__) /** An interface to separate the MDL module from the THD, and the rest of the server code. */ class MDL_context_owner { public: virtual ~MDL_context_owner() = default; /** Enter a condition wait. For @c enter_cond() / @c exit_cond() to work the mutex must be held before @c enter_cond(); this mutex is then released by @c exit_cond(). Usage must be: lock mutex; enter_cond(); your code; exit_cond(). @param cond the condition to wait on @param mutex the associated mutex @param [in] stage the stage to enter, or NULL @param [out] old_stage the previous stage, or NULL @param src_function function name of the caller @param src_file file name of the caller @param src_line line number of the caller @sa ENTER_COND(), THD::enter_cond() @sa EXIT_COND(), THD::exit_cond() */ virtual void enter_cond(mysql_cond_t *cond, mysql_mutex_t *mutex, const PSI_stage_info *stage, PSI_stage_info *old_stage, const char *src_function, const char *src_file, int src_line) = 0; /** @def EXIT_COND(S) End a wait on a condition @param [in] stage the new stage to enter @param src_function function name of the caller @param src_file file name of the caller @param src_line line number of the caller @sa ENTER_COND(), THD::enter_cond() @sa EXIT_COND(), THD::exit_cond() */ virtual void exit_cond(const PSI_stage_info *stage, const char *src_function, const char *src_file, int src_line) = 0; /** Has the owner thread been killed? */ virtual int is_killed() = 0; /** This one is only used for DEBUG_SYNC. (Do not use it to peek/poke into other parts of THD.) */ virtual THD* get_thd() = 0; /** @see THD::notify_shared_lock() */ virtual bool notify_shared_lock(MDL_context_owner *in_use, bool needs_thr_lock_abort) = 0; }; /** Type of metadata lock request. @sa Comments for MDL_object_lock::can_grant_lock() and MDL_scoped_lock::can_grant_lock() for details. Scoped locks are database (or schema) locks. The object locks are for tables, triggers etc. */ enum enum_mdl_type { /* This means that the MDL_request is not initialized */ MDL_NOT_INITIALIZED= -1, /* An intention exclusive metadata lock (IX). Used only for scoped locks. Owner of this type of lock can acquire upgradable exclusive locks on individual objects. Compatible with other IX locks, but is incompatible with scoped S and X locks. IX lock is taken in SCHEMA namespace when we intend to modify object metadata. Object may refer table, stored procedure, trigger, view/etc. */ MDL_INTENTION_EXCLUSIVE= 0, /* A shared metadata lock (S). To be used in cases when we are interested in object metadata only and there is no intention to access object data (e.g. for stored routines or during preparing prepared statements). We also mis-use this type of lock for open HANDLERs, since lock acquired by this statement has to be compatible with lock acquired by LOCK TABLES ... WRITE statement, i.e. SNRW (We can't get by by acquiring S lock at HANDLER ... OPEN time and upgrading it to SR lock for HANDLER ... READ as it doesn't solve problem with need to abort DML statements which wait on table level lock while having open HANDLER in the same connection). To avoid deadlock which may occur when SNRW lock is being upgraded to X lock for table on which there is an active S lock which is owned by thread which waits in its turn for table-level lock owned by thread performing upgrade we have to use thr_abort_locks_for_thread() facility in such situation. This problem does not arise for locks on stored routines as we don't use SNRW locks for them. It also does not arise when S locks are used during PREPARE calls as table-level locks are not acquired in this case. This lock is taken for global read lock, when caching a stored procedure in memory for the duration of the transaction and for tables used by prepared statements. */ MDL_SHARED, /* A high priority shared metadata lock. Used for cases when there is no intention to access object data (i.e. data in the table). "High priority" means that, unlike other shared locks, it is granted ignoring pending requests for exclusive locks. Intended for use in cases when we only need to access metadata and not data, e.g. when filling an INFORMATION_SCHEMA table. Since SH lock is compatible with SNRW lock, the connection that holds the SH lock should not try to acquire any kind of table-level or row-level lock, as this can lead to a deadlock. Moreover, after acquiring SH lock, the connection should not wait for any other resource, as it might cause starvation for X locks and a potential deadlock during upgrade of SNW or SNRW to X lock (e.g. if the upgrading connection holds the resource that is being waited for). */ MDL_SHARED_HIGH_PRIO, /* A shared metadata lock (SR) for cases when there is an intention to read data from table. A connection holding this kind of lock can read table metadata and read table data (after acquiring appropriate table and row-level locks). This means that one can only acquire TL_READ, TL_READ_NO_INSERT, and similar table-level locks on table if one holds SR MDL lock on it. To be used for tables in SELECTs, subqueries, and LOCK TABLE ... READ statements. */ MDL_SHARED_READ, /* A shared metadata lock (SW) for cases when there is an intention to modify (and not just read) data in the table. A connection holding SW lock can read table metadata and modify or read table data (after acquiring appropriate table and row-level locks). To be used for tables to be modified by INSERT, UPDATE, DELETE statements, but not LOCK TABLE ... WRITE or DDL). Also taken by SELECT ... FOR UPDATE. */ MDL_SHARED_WRITE, /* An upgradable shared metadata lock for cases when there is an intention to modify (and not just read) data in the table. Can be upgraded to MDL_SHARED_NO_WRITE and MDL_EXCLUSIVE. A connection holding SU lock can read table metadata and modify or read table data (after acquiring appropriate table and row-level locks). To be used for the first phase of ALTER TABLE. */ MDL_SHARED_UPGRADABLE, /* A shared metadata lock for cases when we need to read data from table and block all concurrent modifications to it (for both data and metadata). Used by LOCK TABLES READ statement. */ MDL_SHARED_READ_ONLY, /* An upgradable shared metadata lock which blocks all attempts to update table data, allowing reads. A connection holding this kind of lock can read table metadata and read table data. Can be upgraded to X metadata lock. Note, that since this type of lock is not compatible with SNRW or SW lock types, acquiring appropriate engine-level locks for reading (TL_READ* for MyISAM, shared row locks in InnoDB) should be contention-free. To be used for the first phase of ALTER TABLE, when copying data between tables, to allow concurrent SELECTs from the table, but not UPDATEs. */ MDL_SHARED_NO_WRITE, /* An upgradable shared metadata lock which allows other connections to access table metadata, but not data. It blocks all attempts to read or update table data, while allowing INFORMATION_SCHEMA and SHOW queries. A connection holding this kind of lock can read table metadata modify and read table data. Can be upgraded to X metadata lock. To be used for LOCK TABLES WRITE statement. Not compatible with any other lock type except S and SH. */ MDL_SHARED_NO_READ_WRITE, /* An exclusive metadata lock (X). A connection holding this lock can modify both table's metadata and data. No other type of metadata lock can be granted while this lock is held. To be used for CREATE/DROP/RENAME TABLE statements and for execution of certain phases of other DDL statements. */ MDL_EXCLUSIVE, /* This should be the last !!! */ MDL_TYPE_END }; /** Backup locks */ /** Block concurrent backup */ #define MDL_BACKUP_START enum_mdl_type(0) /** Block new write requests to non transactional tables */ #define MDL_BACKUP_FLUSH enum_mdl_type(1) /** In addition to previous locks, blocks running requests to non trans tables Used to wait until all DML usage of on trans tables are finished */ #define MDL_BACKUP_WAIT_FLUSH enum_mdl_type(2) /** In addition to previous locks, blocks new DDL's from starting */ #define MDL_BACKUP_WAIT_DDL enum_mdl_type(3) /** In addition to previous locks, blocks commits */ #define MDL_BACKUP_WAIT_COMMIT enum_mdl_type(4) /** Blocks (or is blocked by) statements that intend to modify data. Acquired before commit lock by FLUSH TABLES WITH READ LOCK. */ #define MDL_BACKUP_FTWRL1 enum_mdl_type(5) /** Blocks (or is blocked by) commits. Acquired after global read lock by FLUSH TABLES WITH READ LOCK. */ #define MDL_BACKUP_FTWRL2 enum_mdl_type(6) #define MDL_BACKUP_DML enum_mdl_type(7) #define MDL_BACKUP_TRANS_DML enum_mdl_type(8) #define MDL_BACKUP_SYS_DML enum_mdl_type(9) /** Must be acquired by DDL statements that intend to modify data. Currently it's also used for LOCK TABLES. */ #define MDL_BACKUP_DDL enum_mdl_type(10) /** Blocks new DDL's. Used by backup code to enable DDL logging */ #define MDL_BACKUP_BLOCK_DDL enum_mdl_type(11) /* Statement is modifying data, but will not block MDL_BACKUP_DDL or earlier BACKUP stages. ALTER TABLE is started with MDL_BACKUP_DDL, but changed to MDL_BACKUP_ALTER_COPY while alter table is copying or modifing data. */ #define MDL_BACKUP_ALTER_COPY enum_mdl_type(12) /** Must be acquired during commit. */ #define MDL_BACKUP_COMMIT enum_mdl_type(13) #define MDL_BACKUP_END enum_mdl_type(14) /** Duration of metadata lock. */ enum enum_mdl_duration { /** Locks with statement duration are automatically released at the end of statement or transaction. */ MDL_STATEMENT= 0, /** Locks with transaction duration are automatically released at the end of transaction. */ MDL_TRANSACTION, /** Locks with explicit duration survive the end of statement and transaction. They have to be released explicitly by calling MDL_context::release_lock(). */ MDL_EXPLICIT, /* This should be the last ! */ MDL_DURATION_END }; /** Maximal length of key for metadata locking subsystem. */ #define MAX_MDLKEY_LENGTH (1 + NAME_LEN + 1 + NAME_LEN + 1) /** Metadata lock object key. A lock is requested or granted based on a fully qualified name and type. E.g. They key for a table consists of <0 (=table)>+<database>+<table name>. Elsewhere in the comments this triple will be referred to simply as "key" or "name". */ struct MDL_key { public: #ifdef HAVE_PSI_INTERFACE static void init_psi_keys(); #endif /** Object namespaces. Sic: when adding a new member to this enum make sure to update m_namespace_to_wait_state_name array in mdl.cc and metadata_lock_info_lock_name in metadata_lock_info.cc! Different types of objects exist in different namespaces - SCHEMA is for databases (to protect against DROP DATABASE) - TABLE is for tables and views. - BACKUP is for locking DML, DDL and COMMIT's during BACKUP STAGES - FUNCTION is for stored functions. - PROCEDURE is for stored procedures. - TRIGGER is for triggers. - EVENT is for event scheduler events Note that although there isn't metadata locking on triggers, it's necessary to have a separate namespace for them since MDL_key is also used outside of the MDL subsystem. */ enum enum_mdl_namespace { BACKUP=0, SCHEMA, TABLE, FUNCTION, PROCEDURE, PACKAGE_BODY, TRIGGER, EVENT, USER_LOCK, /* user level locks. */ /* This should be the last ! */ NAMESPACE_END }; const uchar *ptr() const { return (uchar*) m_ptr; } uint length() const { return m_length; } const char *db_name() const { return m_ptr + 1; } uint db_name_length() const { return m_db_name_length; } const char *name() const { return m_ptr + m_db_name_length + 2; } uint name_length() const { return m_length - m_db_name_length - 3; } enum_mdl_namespace mdl_namespace() const { return (enum_mdl_namespace)(m_ptr[0]); } /** Construct a metadata lock key from a triplet (mdl_namespace, database and name). @remark The key for a table is <mdl_namespace>+<database name>+<table name> @param mdl_namespace Id of namespace of object to be locked @param db Name of database to which the object belongs @param name Name of the object @param key Where to store the MDL key. */ void mdl_key_init(enum_mdl_namespace mdl_namespace_arg, const char *db, const char *name_arg) { m_ptr[0]= (char) mdl_namespace_arg; /* It is responsibility of caller to ensure that db and object names are not longer than NAME_LEN. Still we play safe and try to avoid buffer overruns. */ DBUG_ASSERT(strlen(db) <= NAME_LEN); DBUG_ASSERT(strlen(name_arg) <= NAME_LEN); m_db_name_length= static_cast<uint16>(strmake(m_ptr + 1, db, NAME_LEN) - m_ptr - 1); m_length= static_cast<uint16>(strmake(m_ptr + m_db_name_length + 2, name_arg, NAME_LEN) - m_ptr + 1); m_hash_value= my_hash_sort(&my_charset_bin, (uchar*) m_ptr + 1, m_length - 1); DBUG_SLOW_ASSERT(mdl_namespace_arg == USER_LOCK || Lex_ident_fs(db, m_db_name_length). ok_for_lower_case_names()); } void mdl_key_init(const MDL_key *rhs) { memcpy(m_ptr, rhs->m_ptr, rhs->m_length); m_length= rhs->m_length; m_db_name_length= rhs->m_db_name_length; m_hash_value= rhs->m_hash_value; } bool is_equal(const MDL_key *rhs) const { return (m_length == rhs->m_length && memcmp(m_ptr, rhs->m_ptr, m_length) == 0); } /** Compare two MDL keys lexicographically. */ int cmp(const MDL_key *rhs) const { /* The key buffer is always '\0'-terminated. Since key character set is utf-8, we can safely assume that no character starts with a zero byte. */ return memcmp(m_ptr, rhs->m_ptr, MY_MIN(m_length, rhs->m_length)); } MDL_key(const MDL_key *rhs) { mdl_key_init(rhs); } MDL_key(enum_mdl_namespace namespace_arg, const char *db_arg, const char *name_arg) { mdl_key_init(namespace_arg, db_arg, name_arg); } MDL_key() = default; /* To use when part of MDL_request. */ /** Get thread state name to be used in case when we have to wait on resource identified by key. */ const PSI_stage_info * get_wait_state_name() const { return & m_namespace_to_wait_state_name[(int)mdl_namespace()]; } my_hash_value_type hash_value() const { return m_hash_value + mdl_namespace(); } my_hash_value_type tc_hash_value() const { return m_hash_value; } private: uint16 m_length; uint16 m_db_name_length; my_hash_value_type m_hash_value; char m_ptr[MAX_MDLKEY_LENGTH]; static PSI_stage_info m_namespace_to_wait_state_name[NAMESPACE_END]; private: MDL_key(const MDL_key &); /* not implemented */ MDL_key &operator=(const MDL_key &); /* not implemented */ friend my_hash_value_type mdl_hash_function(CHARSET_INFO *, const uchar *, size_t); }; /** A pending metadata lock request. A lock request and a granted metadata lock are represented by different classes because they have different allocation sites and hence different lifetimes. The allocation of lock requests is controlled from outside of the MDL subsystem, while allocation of granted locks (tickets) is controlled within the MDL subsystem. MDL_request is a C structure, you don't need to call a constructor or destructor for it. */ class MDL_request { public: /** Type of metadata lock. */ enum enum_mdl_type type; /** Duration for requested lock. */ enum enum_mdl_duration duration; /** Pointers for participating in the list of lock requests for this context. */ MDL_request *next_in_list; MDL_request **prev_in_list; /** Pointer to the lock ticket object for this lock request. Valid only if this lock request is satisfied. */ MDL_ticket *ticket; /** A lock is requested based on a fully qualified name and type. */ MDL_key key; const char *m_src_file; uint m_src_line; public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void operator delete(void *, MEM_ROOT *) {} void init_with_source(MDL_key::enum_mdl_namespace namespace_arg, const char *db_arg, const char *name_arg, enum_mdl_type mdl_type_arg, enum_mdl_duration mdl_duration_arg, const char *src_file, uint src_line); void init_by_key_with_source(const MDL_key *key_arg, enum_mdl_type mdl_type_arg, enum_mdl_duration mdl_duration_arg, const char *src_file, uint src_line); /** Set type of lock request. Can be only applied to pending locks. */ inline void set_type(enum_mdl_type type_arg) { DBUG_ASSERT(ticket == NULL); type= type_arg; } void move_from(MDL_request &from) { type= from.type; duration= from.duration; ticket= from.ticket; next_in_list= from.next_in_list; prev_in_list= from.prev_in_list; key.mdl_key_init(&from.key); from.ticket= NULL; // that's what "move" means } /** Is this a request for a lock which allow data to be updated? @note This method returns true for MDL_SHARED_UPGRADABLE type of lock. Even though this type of lock doesn't allow updates it will always be upgraded to one that does. */ bool is_write_lock_request() const { return (type >= MDL_SHARED_WRITE && type != MDL_SHARED_READ_ONLY); } /* This is to work around the ugliness of TABLE_LIST compiler-generated assignment operator. It is currently used in several places to quickly copy "most" of the members of the table list. These places currently never assume that the mdl request is carried over to the new TABLE_LIST, or shared between lists. This method does not initialize the instance being assigned! Use of init() for initialization after this assignment operator is mandatory. Can only be used before the request has been granted. */ MDL_request& operator=(const MDL_request &) { type= MDL_NOT_INITIALIZED; ticket= NULL; /* Do nothing, in particular, don't try to copy the key. */ return *this; } /* Another piece of ugliness for TABLE_LIST constructor */ MDL_request(): type(MDL_NOT_INITIALIZED), ticket(NULL) {} MDL_request(const MDL_request *rhs) :type(rhs->type), duration(rhs->duration), ticket(NULL), key(&rhs->key) {} }; typedef void (*mdl_cached_object_release_hook)(void *); #define MDL_REQUEST_INIT(R, P1, P2, P3, P4, P5) \ (*R).init_with_source(P1, P2, P3, P4, P5, __FILE__, __LINE__) #define MDL_REQUEST_INIT_BY_KEY(R, P1, P2, P3) \ (*R).init_by_key_with_source(P1, P2, P3, __FILE__, __LINE__) /** An abstract class for inspection of a connected subgraph of the wait-for graph. */ class MDL_wait_for_graph_visitor { public: virtual bool enter_node(MDL_context *node) = 0; virtual void leave_node(MDL_context *node) = 0; virtual bool inspect_edge(MDL_context *dest) = 0; virtual ~MDL_wait_for_graph_visitor(); MDL_wait_for_graph_visitor() = default; }; /** Abstract class representing an edge in the waiters graph to be traversed by deadlock detection algorithm. */ class MDL_wait_for_subgraph { public: virtual ~MDL_wait_for_subgraph(); /** Accept a wait-for graph visitor to inspect the node this edge is leading to. */ virtual bool accept_visitor(MDL_wait_for_graph_visitor *gvisitor) = 0; enum enum_deadlock_weight { DEADLOCK_WEIGHT_FTWRL1= 0, DEADLOCK_WEIGHT_DML= 1, DEADLOCK_WEIGHT_DDL= 100 }; /* A helper used to determine which lock request should be aborted. */ virtual uint get_deadlock_weight() const = 0; }; /** A granted metadata lock. @warning MDL_ticket members are private to the MDL subsystem. @note Multiple shared locks on a same object are represented by a single ticket. The same does not apply for other lock types. @note There are two groups of MDL_ticket members: - "Externally accessible". These members can be accessed from threads/contexts different than ticket owner in cases when ticket participates in some list of granted or waiting tickets for a lock. Therefore one should change these members before including then to waiting/granted lists or while holding lock protecting those lists. - "Context private". Such members are private to thread/context owning this ticket. I.e. they should not be accessed from other threads/contexts. */ class MDL_ticket : public MDL_wait_for_subgraph, public ilist_node<> { public: /** Pointers for participating in the list of lock requests for this context. Context private. */ MDL_ticket *next_in_context; MDL_ticket **prev_in_context; #ifndef DBUG_OFF /** Duration of lock represented by this ticket. Context public. Debug-only. */ public: enum_mdl_duration m_duration; #endif ulonglong m_time; #ifdef WITH_WSREP void wsrep_report(bool debug) const; #endif /* WITH_WSREP */ bool has_pending_conflicting_lock() const; MDL_context *get_ctx() const { return m_ctx; } bool is_upgradable_or_exclusive() const { return m_type == MDL_SHARED_UPGRADABLE || m_type == MDL_SHARED_NO_WRITE || m_type == MDL_SHARED_NO_READ_WRITE || m_type == MDL_EXCLUSIVE; } enum_mdl_type get_type() const { return m_type; } const LEX_STRING *get_type_name() const; const LEX_STRING *get_type_name(enum_mdl_type type) const; MDL_lock *get_lock() const { return m_lock; } MDL_key *get_key() const; void downgrade_lock(enum_mdl_type type); bool has_stronger_or_equal_type(enum_mdl_type type) const; bool is_incompatible_when_granted(enum_mdl_type type) const; bool is_incompatible_when_waiting(enum_mdl_type type) const; /** Implement MDL_wait_for_subgraph interface. */ bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor) override; uint get_deadlock_weight() const override; /** Status of lock request represented by the ticket as reflected in P_S. */ enum enum_psi_status { PENDING = 0, GRANTED, PRE_ACQUIRE_NOTIFY, POST_RELEASE_NOTIFY }; private: friend class MDL_context; MDL_ticket(MDL_context *ctx_arg, enum_mdl_type type_arg #ifndef DBUG_OFF , enum_mdl_duration duration_arg #endif ) : #ifndef DBUG_OFF m_duration(duration_arg), #endif m_time(0), m_type(type_arg), m_ctx(ctx_arg), m_lock(NULL), m_psi(NULL) {} virtual ~MDL_ticket() { DBUG_ASSERT(m_psi == NULL); } static MDL_ticket *create(MDL_context *ctx_arg, enum_mdl_type type_arg #ifndef DBUG_OFF , enum_mdl_duration duration_arg #endif ); static void destroy(MDL_ticket *ticket); private: /** Type of metadata lock. Externally accessible. */ enum enum_mdl_type m_type; /** Context of the owner of the metadata lock ticket. Externally accessible. */ MDL_context *m_ctx; /** Pointer to the lock object for this lock ticket. Externally accessible. */ MDL_lock *m_lock; PSI_metadata_lock *m_psi; private: MDL_ticket(const MDL_ticket &); /* not implemented */ MDL_ticket &operator=(const MDL_ticket &); /* not implemented */ }; /** Savepoint for MDL context. Doesn't include metadata locks with explicit duration as they are not released during rollback to savepoint. */ class MDL_savepoint { public: MDL_savepoint() = default;; private: MDL_savepoint(MDL_ticket *stmt_ticket, MDL_ticket *trans_ticket) : m_stmt_ticket(stmt_ticket), m_trans_ticket(trans_ticket) {} friend class MDL_context; private: /** Pointer to last lock with statement duration which was taken before creation of savepoint. */ MDL_ticket *m_stmt_ticket; /** Pointer to last lock with transaction duration which was taken before creation of savepoint. */ MDL_ticket *m_trans_ticket; }; /** A reliable way to wait on an MDL lock. */ class MDL_wait { public: MDL_wait(); ~MDL_wait(); enum enum_wait_status { EMPTY = 0, GRANTED, VICTIM, TIMEOUT, KILLED }; bool set_status(enum_wait_status result_arg); enum_wait_status get_status(); void reset_status(); enum_wait_status timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, bool signal_timeout, const PSI_stage_info *wait_state_name); private: /** Condvar which is used for waiting until this context's pending request can be satisfied or this thread has to perform actions to resolve a potential deadlock (we subscribe to such notification by adding a ticket corresponding to the request to an appropriate queue of waiters). */ mysql_mutex_t m_LOCK_wait_status; mysql_cond_t m_COND_wait_status; enum_wait_status m_wait_status; }; typedef I_P_List<MDL_request, I_P_List_adapter<MDL_request, &MDL_request::next_in_list, &MDL_request::prev_in_list>, I_P_List_counter> MDL_request_list; /** Context of the owner of metadata locks. I.e. each server connection has such a context. */ class MDL_context { public: typedef I_P_List<MDL_ticket, I_P_List_adapter<MDL_ticket, &MDL_ticket::next_in_context, &MDL_ticket::prev_in_context> > Ticket_list; typedef Ticket_list::Iterator Ticket_iterator; MDL_context(); void destroy(); bool try_acquire_lock(MDL_request *mdl_request); bool acquire_lock(MDL_request *mdl_request, double lock_wait_timeout); bool acquire_locks(MDL_request_list *requests, double lock_wait_timeout); bool upgrade_shared_lock(MDL_ticket *mdl_ticket, enum_mdl_type new_type, double lock_wait_timeout); bool clone_ticket(MDL_request *mdl_request); void release_all_locks_for_name(MDL_ticket *ticket); void release_lock(MDL_ticket *ticket); bool is_lock_owner(MDL_key::enum_mdl_namespace mdl_namespace, const char *db, const char *name, enum_mdl_type mdl_type); unsigned long get_lock_owner(MDL_key *mdl_key); bool has_lock(const MDL_savepoint &mdl_savepoint, MDL_ticket *mdl_ticket); inline bool has_locks() const { return !(m_tickets[MDL_STATEMENT].is_empty() && m_tickets[MDL_TRANSACTION].is_empty() && m_tickets[MDL_EXPLICIT].is_empty()); } bool has_explicit_locks() const { return !m_tickets[MDL_EXPLICIT].is_empty(); } inline bool has_transactional_locks() const { return !m_tickets[MDL_TRANSACTION].is_empty(); } MDL_savepoint mdl_savepoint() { return MDL_savepoint(m_tickets[MDL_STATEMENT].front(), m_tickets[MDL_TRANSACTION].front()); } void set_explicit_duration_for_all_locks(); void set_transaction_duration_for_all_locks(); void set_lock_duration(MDL_ticket *mdl_ticket, enum_mdl_duration duration); void release_statement_locks(); void release_transactional_locks(THD *thd); void release_explicit_locks(); void rollback_to_savepoint(const MDL_savepoint &mdl_savepoint); MDL_context_owner *get_owner() { return m_owner; } /** @pre Only valid if we started waiting for lock. */ inline uint get_deadlock_weight() const { return m_waiting_for->get_deadlock_weight() + m_deadlock_overweight; } void inc_deadlock_overweight() { m_deadlock_overweight++; } /** Post signal to the context (and wake it up if necessary). @retval FALSE - Success, signal was posted. @retval TRUE - Failure, signal was not posted since context already has received some signal or closed signal slot. */ void init(MDL_context_owner *arg) { m_owner= arg; reset(); } void reset() { m_deadlock_overweight= 0; } void set_needs_thr_lock_abort(bool needs_thr_lock_abort) { /* @note In theory, this member should be modified under protection of some lock since it can be accessed from different threads. In practice, this is not necessary as code which reads this value and so might miss the fact that value was changed will always re-try reading it after small timeout and therefore will see the new value eventually. */ m_needs_thr_lock_abort= needs_thr_lock_abort; } bool get_needs_thr_lock_abort() const { return m_needs_thr_lock_abort; } public: /** If our request for a lock is scheduled, or aborted by the deadlock detector, the result is recorded in this class. */ MDL_wait m_wait; private: /** Lists of all MDL tickets acquired by this connection. Lists of MDL tickets: --------------------- The entire set of locks acquired by a connection can be separated in three subsets according to their duration: locks released at the end of statement, at the end of transaction and locks are released explicitly. Statement and transactional locks are locks with automatic scope. They are accumulated in the course of a transaction, and released either at the end of uppermost statement (for statement locks) or on COMMIT, ROLLBACK or ROLLBACK TO SAVEPOINT (for transactional locks). They must not be (and never are) released manually, i.e. with release_lock() call. Tickets with explicit duration are taken for locks that span multiple transactions or savepoints. These are: HANDLER SQL locks (HANDLER SQL is transaction-agnostic), LOCK TABLES locks (you can COMMIT/etc under LOCK TABLES, and the locked tables stay locked), user level locks (GET_LOCK()/RELEASE_LOCK() functions) and locks implementing "global read lock". Statement/transactional locks are always prepended to the beginning of the appropriate list. In other words, they are stored in reverse temporal order. Thus, when we rollback to a savepoint, we start popping and releasing tickets from the front until we reach the last ticket acquired after the savepoint. Locks with explicit duration are not stored in any particular order, and among each other can be split into four sets: [LOCK TABLES locks] [USER locks] [HANDLER locks] [GLOBAL READ LOCK locks] The following is known about these sets: * GLOBAL READ LOCK locks are always stored last. This is because one can't say SET GLOBAL read_only=1 or FLUSH TABLES WITH READ LOCK if one has locked tables. One can, however, LOCK TABLES after having entered the read only mode. Note, that subsequent LOCK TABLES statement will unlock the previous set of tables, but not the GRL! There are no HANDLER locks after GRL locks because SET GLOBAL read_only performs a FLUSH TABLES WITH READ LOCK internally, and FLUSH TABLES, in turn, implicitly closes all open HANDLERs. However, one can open a few HANDLERs after entering the read only mode. * LOCK TABLES locks include intention exclusive locks on involved schemas and global intention exclusive lock. */ Ticket_list m_tickets[MDL_DURATION_END]; MDL_context_owner *m_owner; /** TRUE - if for this context we will break protocol and try to acquire table-level locks while having only S lock on some table. To avoid deadlocks which might occur during concurrent upgrade of SNRW lock on such object to X lock we have to abort waits for table-level locks for such connections. FALSE - Otherwise. */ bool m_needs_thr_lock_abort; /** Read-write lock protecting m_waiting_for member. @note The fact that this read-write lock prefers readers is important as deadlock detector won't work correctly otherwise. @sa Comment for MDL_lock::m_rwlock. */ mysql_prlock_t m_LOCK_waiting_for; /** Tell the deadlock detector what metadata lock or table definition cache entry this session is waiting for. In principle, this is redundant, as information can be found by inspecting waiting queues, but we'd very much like it to be readily available to the wait-for graph iterator. */ MDL_wait_for_subgraph *m_waiting_for; LF_PINS *m_pins; uint m_deadlock_overweight; private: MDL_ticket *find_ticket(MDL_request *mdl_req, enum_mdl_duration *duration); void release_locks_stored_before(enum_mdl_duration duration, MDL_ticket *sentinel); void release_lock(enum_mdl_duration duration, MDL_ticket *ticket); bool try_acquire_lock_impl(MDL_request *mdl_request, MDL_ticket **out_ticket); bool fix_pins(); public: THD *get_thd() const { return m_owner->get_thd(); } bool has_explicit_locks(); void find_deadlock(); ulong get_thread_id() const { return thd_get_thread_id(get_thd()); } bool visit_subgraph(MDL_wait_for_graph_visitor *dvisitor); /** Inform the deadlock detector there is an edge in the wait-for graph. */ void will_wait_for(MDL_wait_for_subgraph *waiting_for_arg) { mysql_prlock_wrlock(&m_LOCK_waiting_for); m_waiting_for= waiting_for_arg; mysql_prlock_unlock(&m_LOCK_waiting_for); } /** Remove the wait-for edge from the graph after we're done waiting. */ void done_waiting_for() { mysql_prlock_wrlock(&m_LOCK_waiting_for); m_waiting_for= NULL; mysql_prlock_unlock(&m_LOCK_waiting_for); } void lock_deadlock_victim() { mysql_prlock_rdlock(&m_LOCK_waiting_for); } void unlock_deadlock_victim() { mysql_prlock_unlock(&m_LOCK_waiting_for); } private: MDL_context(const MDL_context &rhs); /* not implemented */ MDL_context &operator=(MDL_context &rhs); /* not implemented */ /* metadata_lock_info plugin */ friend int i_s_metadata_lock_info_fill_row(MDL_ticket*, void*); #ifndef DBUG_OFF public: /** This is for the case when the thread opening the table does not acquire the lock itself, but utilizes a lock guarantee from another MDL context. For example, in InnoDB, MDL is acquired by the purge_coordinator_task, but the table may be opened and used in a purge_worker_task. The coordinator thread holds the lock for the duration of worker's purge job, or longer, possibly reusing shared MDL for different workers and jobs. */ MDL_context *lock_warrant= NULL; inline bool is_lock_warrantee(MDL_key::enum_mdl_namespace ns, const char *db, const char *name, enum_mdl_type mdl_type) const { return lock_warrant && lock_warrant->is_lock_owner(ns, db, name, mdl_type); } #endif }; void mdl_init(); void mdl_destroy(); extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd); /** Check if a connection in question is no longer connected. @details Replication apply thread is always connected. Otherwise, does a poll on the associated socket to check if the client is gone. */ extern "C" int thd_is_connected(MYSQL_THD thd); /* Metadata locking subsystem tries not to grant more than max_write_lock_count high-prio, strong locks successively, to avoid starving out weak, low-prio locks. */ extern "C" ulong max_write_lock_count; typedef int (*mdl_iterator_callback)(MDL_ticket *ticket, void *arg, bool granted); extern MYSQL_PLUGIN_IMPORT int mdl_iterate(mdl_iterator_callback callback, void *arg); #endif /* MDL_H */ my_json_writer.h 0000644 00000044224 15156036127 0010003 0 ustar 00 /* Copyright (C) 2014 SkySQL Ab, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef JSON_WRITER_INCLUDED #define JSON_WRITER_INCLUDED #include "my_base.h" #include "sql_string.h" #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) || defined ENABLED_JSON_WRITER_CONSISTENCY_CHECKS #include <set> #include <stack> #include <string> #include <vector> #endif #ifdef JSON_WRITER_UNIT_TEST // Also, mock objects are defined in my_json_writer-t.cc #define VALIDITY_ASSERT(x) if (!(x)) this->invalid_json= true; #else #include "sql_class.h" // For class THD #include "log.h" // for sql_print_error #define VALIDITY_ASSERT(x) DBUG_ASSERT(x) #endif #include <type_traits> class Opt_trace_stmt; class Opt_trace_context; class Json_writer; struct TABLE; struct st_join_table; using JOIN_TAB= struct st_join_table; /* Single_line_formatting_helper is used by Json_writer to do better formatting of JSON documents. The idea is to catch arrays that can be printed on one line: arrayName : [ "boo", 123, 456 ] and actually print them on one line. Arrrays that occupy too much space on the line, or have nested members cannot be printed on one line. We hook into JSON printing functions and try to detect the pattern. While detecting the pattern, we will accumulate "boo", 123, 456 as strings. Then, - either the pattern is broken, and we print the elements out, - or the pattern lasts till the end of the array, and we print the array on one line. */ class Single_line_formatting_helper { enum enum_state { INACTIVE, ADD_MEMBER, IN_ARRAY, DISABLED }; /* This works like a finite automaton. state=DISABLED means the helper is disabled - all on_XXX functions will return false (which means "not handled") and do nothing. +->-+ | v INACTIVE ---> ADD_MEMBER ---> IN_ARRAY--->-+ ^ | +------------------<--------------------+ For other states: INACTIVE - initial state, we have nothing. ADD_MEMBER - add_member() was called, the buffer has "member_name\0". IN_ARRAY - start_array() was called. */ enum enum_state state; enum { MAX_LINE_LEN= 80 }; char buffer[80]; /* The data in the buffer is located between buffer[0] and buf_ptr */ char *buf_ptr; uint line_len; Json_writer *owner; public: Single_line_formatting_helper() : state(INACTIVE), buf_ptr(buffer) {} void init(Json_writer *owner_arg) { owner= owner_arg; } bool on_add_member(const char *name, size_t len); bool on_start_array(); bool on_end_array(); void on_start_object(); // on_end_object() is not needed. bool on_add_str(const char *str, size_t num_bytes); /* Returns true if the helper is flushing its buffer and is probably making calls back to its Json_writer. (The Json_writer uses this function to avoid re-doing the processing that it has already done before making a call to fmt_helper) */ bool is_making_writer_calls() const { return state == DISABLED; } private: void flush_on_one_line(); void disable_and_flush(); }; /* Something that looks like class String, but has an internal limit of how many bytes one can append to it. Bytes that were truncated due to the size limitation are counted. */ class String_with_limit { public: String_with_limit() : size_limit(SIZE_T_MAX), truncated_len(0) { str.length(0); } size_t get_truncated_bytes() const { return truncated_len; } size_t get_size_limit() { return size_limit; } void set_size_limit(size_t limit_arg) { // Setting size limit to be shorter than length will not have the desired // effect DBUG_ASSERT(str.length() < size_limit); size_limit= limit_arg; } void append(const char *s, size_t size) { if (str.length() + size <= size_limit) { // Whole string can be added, just do it str.append(s, size); } else { // We cannot add the whole string if (str.length() < size_limit) { // But we can still add something size_t bytes_to_add = size_limit - str.length(); str.append(s, bytes_to_add); truncated_len += size - bytes_to_add; } else truncated_len += size; } } void append(const char *s) { append(s, strlen(s)); } void append(char c) { if (str.length() + 1 > size_limit) truncated_len++; else str.append(c); } const String *get_string() { return &str; } size_t length() { return str.length(); } private: String str; // str must not get longer than this many bytes. size_t size_limit; // How many bytes were truncated from the string size_t truncated_len; }; /* A class to write well-formed JSON documents. The documents are also formatted for human readability. */ class Json_writer { #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) /* In debug mode, Json_writer will fail and assertion if one attempts to produce an invalid JSON document (e.g. JSON array having named elements). */ std::vector<bool> named_items_expectation; std::stack<std::set<std::string> > named_items; bool named_item_expected() const; bool got_name; #ifdef JSON_WRITER_UNIT_TEST public: // When compiled for unit test, creating invalid JSON will set this to true // instead of an assertion. bool invalid_json= false; #endif #endif public: /* Add a member. We must be in an object. */ Json_writer& add_member(const char *name); Json_writer& add_member(const char *name, size_t len); /* Add atomic values */ /* Note: the add_str methods do not do escapes. Should this change? */ void add_str(const char* val); void add_str(const char* val, size_t num_bytes); void add_str(const String &str); void add_str(Item *item); void add_table_name(const JOIN_TAB *tab); void add_table_name(const TABLE* table); void add_ll(longlong val); void add_ull(ulonglong val); void add_size(longlong val); void add_double(double val); void add_bool(bool val); void add_null(); private: void add_unquoted_str(const char* val); void add_unquoted_str(const char* val, size_t len); bool on_add_str(const char *str, size_t num_bytes); void on_start_object(); public: /* Start a child object */ void start_object(); void start_array(); void end_object(); void end_array(); /* One can set a limit of how large a JSON document should be. Writes beyond that size will be counted, but will not be collected. */ void set_size_limit(size_t mem_size) { output.set_size_limit(mem_size); } size_t get_truncated_bytes() { return output.get_truncated_bytes(); } Json_writer() : #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) got_name(false), #endif indent_level(0), document_start(true), element_started(false), first_child(true) { fmt_helper.init(this); } private: // TODO: a stack of (name, bool is_object_or_array) elements. int indent_level; enum { INDENT_SIZE = 2 }; friend class Single_line_formatting_helper; friend class Json_writer_nesting_guard; bool document_start; bool element_started; bool first_child; Single_line_formatting_helper fmt_helper; void append_indent(); void start_element(); void start_sub_element(); public: String_with_limit output; }; /* A class to add values to Json_writer_object and Json_writer_array */ class Json_value_helper { Json_writer* writer; public: void init(Json_writer *my_writer) { writer= my_writer; } void add_str(const char* val) { writer->add_str(val); } void add_str(const char* val, size_t length) { writer->add_str(val, length); } void add_str(const String &str) { writer->add_str(str.ptr(), str.length()); } void add_str(const LEX_CSTRING &str) { writer->add_str(str.str, str.length); } void add_str(Item *item) { writer->add_str(item); } void add_ll(longlong val) { writer->add_ll(val); } void add_size(longlong val) { writer->add_size(val); } void add_double(double val) { writer->add_double(val); } void add_bool(bool val) { writer->add_bool(val); } void add_null() { writer->add_null(); } void add_table_name(const JOIN_TAB *tab) { writer->add_table_name(tab); } void add_table_name(const TABLE* table) { writer->add_table_name(table); } }; /* A common base for Json_writer_object and Json_writer_array */ class Json_writer_struct { Json_writer_struct(const Json_writer_struct&)= delete; Json_writer_struct& operator=(const Json_writer_struct&)= delete; #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS static thread_local std::vector<bool> named_items_expectation; #endif protected: Json_writer* my_writer; Json_value_helper context; /* Tells when a json_writer_struct has been closed or not */ bool closed; explicit Json_writer_struct(Json_writer *writer) : my_writer(writer) { context.init(my_writer); closed= false; #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS named_items_expectation.push_back(expect_named_children); #endif } explicit Json_writer_struct(THD *thd) : Json_writer_struct(thd->opt_trace.get_current_json()) { } public: #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS virtual ~Json_writer_struct() { named_items_expectation.pop_back(); } #else virtual ~Json_writer_struct() = default; #endif inline bool trace_started() const { return my_writer != 0; } #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS bool named_item_expected() const { return named_items_expectation.size() > 1 && *(named_items_expectation.rbegin() + 1); } #endif }; /* RAII-based class to start/end writing a JSON object into the JSON document There is "ignore mode": one can initialize Json_writer_object with a NULL Json_writer argument, and then all its calls will do nothing. This is used by optimizer trace which can be enabled or disabled. */ class Json_writer_object : public Json_writer_struct { private: void add_member(const char *name) { my_writer->add_member(name); } public: explicit Json_writer_object(Json_writer* writer, const char *str= nullptr) : Json_writer_struct(writer) { #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS DBUG_ASSERT(named_item_expected()); #endif if (unlikely(my_writer)) { if (str) my_writer->add_member(str); my_writer->start_object(); } } explicit Json_writer_object(THD* thd, const char *str= nullptr) : Json_writer_object(thd->opt_trace.get_current_json(), str) { } ~Json_writer_object() { if (my_writer && !closed) my_writer->end_object(); closed= TRUE; } Json_writer_object& add(const char *name, bool value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_bool(value); } return *this; } Json_writer_object& add(const char *name, ulonglong value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); my_writer->add_ull(value); } return *this; } template<class IntT, typename= typename ::std::enable_if<std::is_integral<IntT>::value>::type > Json_writer_object& add(const char *name, IntT value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_ll(value); } return *this; } Json_writer_object& add(const char *name, double value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_double(value); } return *this; } Json_writer_object& add(const char *name, const char *value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_str(value); } return *this; } Json_writer_object& add(const char *name, const char *value, size_t num_bytes) { add_member(name); context.add_str(value, num_bytes); return *this; } Json_writer_object& add(const char *name, const LEX_CSTRING &value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_str(value.str, value.length); } return *this; } Json_writer_object& add(const char *name, Item *value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_str(value); } return *this; } Json_writer_object& add_null(const char*name) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); context.add_null(); } return *this; } Json_writer_object& add_table_name(const JOIN_TAB *tab) { DBUG_ASSERT(!closed); if (my_writer) { add_member("table"); context.add_table_name(tab); } return *this; } Json_writer_object& add_table_name(const TABLE *table) { DBUG_ASSERT(!closed); if (my_writer) { add_member("table"); context.add_table_name(table); } return *this; } Json_writer_object& add_select_number(uint select_number) { DBUG_ASSERT(!closed); if (my_writer) { add_member("select_id"); if (unlikely(select_number == FAKE_SELECT_LEX_ID)) context.add_str("fake"); else context.add_ll(static_cast<longlong>(select_number)); } return *this; } void end() { DBUG_ASSERT(!closed); if (unlikely(my_writer)) my_writer->end_object(); closed= TRUE; } }; /* RAII-based class to start/end writing a JSON array into the JSON document There is "ignore mode": one can initialize Json_writer_array with a NULL Json_writer argument, and then all its calls will do nothing. This is used by optimizer trace which can be enabled or disabled. */ class Json_writer_array : public Json_writer_struct { public: explicit Json_writer_array(Json_writer *writer, const char *str= nullptr) : Json_writer_struct(writer) { #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS DBUG_ASSERT(!named_item_expected()); #endif if (unlikely(my_writer)) { if (str) my_writer->add_member(str); my_writer->start_array(); } } explicit Json_writer_array(THD *thd, const char *str= nullptr) : Json_writer_array(thd->opt_trace.get_current_json(), str) { } ~Json_writer_array() { if (unlikely(my_writer && !closed)) { my_writer->end_array(); closed= TRUE; } } void end() { DBUG_ASSERT(!closed); if (unlikely(my_writer)) my_writer->end_array(); closed= TRUE; } Json_writer_array& add(bool value) { DBUG_ASSERT(!closed); if (my_writer) context.add_bool(value); return *this; } Json_writer_array& add(ulonglong value) { DBUG_ASSERT(!closed); if (my_writer) context.add_ll(static_cast<longlong>(value)); return *this; } Json_writer_array& add(longlong value) { DBUG_ASSERT(!closed); if (my_writer) context.add_ll(value); return *this; } Json_writer_array& add(double value) { DBUG_ASSERT(!closed); if (my_writer) context.add_double(value); return *this; } #ifndef _WIN64 Json_writer_array& add(size_t value) { DBUG_ASSERT(!closed); if (my_writer) context.add_ll(static_cast<longlong>(value)); return *this; } #endif Json_writer_array& add(const char *value) { DBUG_ASSERT(!closed); if (my_writer) context.add_str(value); return *this; } Json_writer_array& add(const char *value, size_t num_bytes) { DBUG_ASSERT(!closed); if (my_writer) context.add_str(value, num_bytes); return *this; } Json_writer_array& add(const LEX_CSTRING &value) { DBUG_ASSERT(!closed); if (my_writer) context.add_str(value.str, value.length); return *this; } Json_writer_array& add(Item *value) { DBUG_ASSERT(!closed); if (my_writer) context.add_str(value); return *this; } Json_writer_array& add_null() { DBUG_ASSERT(!closed); if (my_writer) context.add_null(); return *this; } Json_writer_array& add_table_name(const JOIN_TAB *tab) { DBUG_ASSERT(!closed); if (my_writer) context.add_table_name(tab); return *this; } Json_writer_array& add_table_name(const TABLE *table) { DBUG_ASSERT(!closed); if (my_writer) context.add_table_name(table); return *this; } }; /* RAII-based class to disable writing into the JSON document The tracing is disabled as soon as the object is created. The destuctor is called as soon as we exit the scope of the object and the tracing is enabled back. */ class Json_writer_temp_disable { public: Json_writer_temp_disable(THD *thd_arg); ~Json_writer_temp_disable(); THD *thd; }; /* RAII-based helper class to detect incorrect use of Json_writer. The idea is that a function typically must leave Json_writer at the same identation level as it was when it was invoked. Leaving it at a different level typically means we forgot to close an object or an array So, here is a way to guard void foo(Json_writer *writer) { Json_writer_nesting_guard(writer); .. do something with writer // at the end of the function, ~Json_writer_nesting_guard() is called // and it makes sure that the nesting is the same as when the function was // entered. } */ class Json_writer_nesting_guard { #ifdef DBUG_OFF public: Json_writer_nesting_guard(Json_writer *) {} #else Json_writer* writer; int indent_level; public: Json_writer_nesting_guard(Json_writer *writer_arg) : writer(writer_arg), indent_level(writer->indent_level) {} ~Json_writer_nesting_guard() { DBUG_ASSERT(indent_level == writer->indent_level); } #endif }; #endif sql_type_string.h 0000644 00000003135 15156036127 0010153 0 ustar 00 /* Copyright (c) 2019 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_TYPE_STRING_INCLUDED #define SQL_TYPE_STRING_INCLUDED class StringPack { CHARSET_INFO *m_cs; uint32 m_octet_length; CHARSET_INFO *charset() const { return m_cs; } uint mbmaxlen() const { return m_cs->mbmaxlen; }; uint32 char_length() const { return m_octet_length / mbmaxlen(); } public: StringPack(CHARSET_INFO *cs, uint32 octet_length) :m_cs(cs), m_octet_length(octet_length) { } uchar *pack(uchar *to, const uchar *from, uint max_length) const; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) const; public: static uint max_packed_col_length(uint max_length) { return (max_length > 255 ? 2 : 1) + max_length; } static uint packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) return uint2korr(data_ptr)+2; return (uint) *data_ptr + 1; } }; #endif // SQL_TYPE_STRING_INCLUDED myisammrg.h 0000644 00000011441 15156036127 0006731 0 ustar 00 /* Copyright (c) 2000-2002, 2004, 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file should be included when using merge_isam_functions */ #ifndef _myisammrg_h #define _myisammrg_h #ifdef __cplusplus extern "C" { #endif #ifndef _my_base_h #include <my_base.h> #endif #ifndef _myisam_h #include <myisam.h> #endif #include <queues.h> #define MYRG_NAME_EXT ".MRG" #define MYRG_NAME_TMPEXT ".MRG_TMP" /* In which table to INSERT rows */ #define MERGE_INSERT_DISABLED 0 #define MERGE_INSERT_TO_FIRST 1 #define MERGE_INSERT_TO_LAST 2 extern TYPELIB merge_insert_method; /* Param to/from myrg_info */ typedef struct st_mymerge_info /* Struct from h_info */ { ulonglong records; /* Records in database */ ulonglong deleted; /* Deleted records in database */ ulonglong recpos; /* Pos for last used record */ ulonglong data_file_length; ulonglong dupp_key_pos; /* Offset of the Duplicate key in the merge table */ uint reclength; /* Recordlength */ int errkey; /* With key was duplicated on err */ uint options; /* HA_OPTION_... used */ ulong *rec_per_key; /* for sql optimizing */ } MYMERGE_INFO; typedef struct st_myrg_table_info { struct st_myisam_info *table; ulonglong file_offset; } MYRG_TABLE; typedef struct st_myrg_info { MYRG_TABLE *open_tables,*current_table,*end_table,*last_used_table; ulonglong records; /* records in tables */ ulonglong del; /* Removed records */ ulonglong data_file_length; ulong cache_size; uint merge_insert_method; uint tables,options,reclength,keys; uint key_parts; my_bool cache_in_use; /* If MERGE children attached to parent. See top comment in ha_myisammrg.cc */ my_bool children_attached; LIST open_list; QUEUE by_key; ulong *rec_per_key_part; /* for sql optimizing */ mysql_mutex_t mutex; } MYRG_INFO; /* Prototypes for merge-functions */ extern int myrg_close(MYRG_INFO *file); extern int myrg_delete(MYRG_INFO *file,const uchar *buff); extern MYRG_INFO *myrg_open(const char *name,int mode,int wait_if_locked); extern MYRG_INFO *myrg_parent_open(const char *parent_name, int (*callback)(void*, const char*), void *callback_param); extern int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, MI_INFO *(*callback)(void*), void *callback_param, my_bool *need_compat_check); extern int myrg_detach_children(MYRG_INFO *m_info); extern int myrg_panic(enum ha_panic_function function); extern int myrg_rfirst(MYRG_INFO *file,uchar *buf,int inx); extern int myrg_rlast(MYRG_INFO *file,uchar *buf,int inx); extern int myrg_rnext(MYRG_INFO *file,uchar *buf,int inx); extern int myrg_rprev(MYRG_INFO *file,uchar *buf,int inx); extern int myrg_rnext_same(MYRG_INFO *file,uchar *buf); extern int myrg_rkey(MYRG_INFO *info,uchar *buf,int inx, const uchar *key, key_part_map keypart_map, enum ha_rkey_function search_flag); extern int myrg_rrnd(MYRG_INFO *file,uchar *buf,ulonglong pos); extern int myrg_rsame(MYRG_INFO *file,uchar *record,int inx); extern int myrg_update(MYRG_INFO *file,const uchar *old, const uchar *new_rec); extern int myrg_write(MYRG_INFO *info,const uchar *rec); extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag); extern int myrg_lock_database(MYRG_INFO *file,int lock_type); extern int myrg_create(const char *name, const char **table_names, uint insert_method, my_bool fix_names); extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function, void *extra_arg); extern int myrg_reset(MYRG_INFO *info); extern void myrg_extrafunc(MYRG_INFO *info,invalidator_by_filename inv); extern ha_rows myrg_records_in_range(MYRG_INFO *info, int inx, const key_range *min_key, const key_range *max_key, page_range *pages); extern ha_rows myrg_records(MYRG_INFO *info); extern ulonglong myrg_position(MYRG_INFO *info); #ifdef __cplusplus } #endif #endif wsrep_event_service.h 0000644 00000002507 15156036127 0011010 0 ustar 00 /* Copyright 2021-2022 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_EVENT_SERVICE_H #define WSREP_EVENT_SERVICE_H /* wsrep-lib */ #include "wsrep/event_service.hpp" /* implementation */ #include "wsrep_status.h" class Wsrep_event_service : public wsrep::event_service { public: void process_event(const std::string& name, const std::string& value) override { if (name == "progress") { Wsrep_status::report_progress(value); } else if (name == "event") { Wsrep_status::report_event(value); } else { // not interested in the event } } static wsrep::event_service* instance(); }; #endif /* WSREP_EVENT_SERVICE_H */ wsrep_server_state.h 0000644 00000006072 15156036127 0010656 0 ustar 00 /* Copyright 2018-2021 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_SERVER_STATE_H #define WSREP_SERVER_STATE_H /* wsrep-lib */ #include "wsrep/server_state.hpp" #include "wsrep/provider.hpp" #include "wsrep/provider_options.hpp" /* implementation */ #include "wsrep_server_service.h" #include "wsrep_mutex.h" #include "wsrep_condition_variable.h" class Wsrep_server_state : public wsrep::server_state { public: static void init_once(const std::string& name, const std::string& incoming_address, const std::string& address, const std::string& working_dir, const wsrep::gtid& initial_position, int max_protocol_version); static int init_provider(const std::string& provider, const std::string& options); static int init_options(); static void deinit_provider(); static void destroy(); static Wsrep_server_state& instance() { return *m_instance; } static bool is_inited() { return (m_instance != NULL); } static wsrep::provider& get_provider() { return instance().provider(); } static wsrep::provider_options* get_options() { return m_options.get(); } static bool has_capability(int capability) { return (get_provider().capabilities() & capability); } static void init_provider_services(); static void deinit_provider_services(); static const wsrep::provider::services& provider_services() { return m_provider_services; } static void handle_fatal_signal(); private: Wsrep_server_state(const std::string& name, const std::string& incoming_address, const std::string& address, const std::string& working_dir, const wsrep::gtid& initial_position, int max_protocol_version); ~Wsrep_server_state(); Wsrep_mutex m_mutex; Wsrep_condition_variable m_cond; Wsrep_server_service m_service; static wsrep::provider::services m_provider_services; static Wsrep_server_state* m_instance; static std::unique_ptr<wsrep::provider_options> m_options; // Sysvars for provider plugin. We keep these here because // they are allocated dynamically and must be freed at some // point during shutdown (after the plugin is deinitialized). static std::vector<st_mysql_sys_var *> m_sysvars; }; #endif // WSREP_SERVER_STATE_H sql_signal.h 0000644 00000006442 15156036127 0007065 0 ustar 00 /* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_SIGNAL_H #define SQL_SIGNAL_H /** Sql_cmd_common_signal represents the common properties of the SIGNAL and RESIGNAL statements. */ class Sql_cmd_common_signal : public Sql_cmd { protected: /** Constructor. @param cond the condition signaled if any, or NULL. @param set collection of signal condition item assignments. */ Sql_cmd_common_signal(const sp_condition_value *cond, const Set_signal_information& set) : Sql_cmd(), m_cond(cond), m_set_signal_information(set) {} virtual ~Sql_cmd_common_signal() = default; /** Evaluate each signal condition items for this statement. @param thd the current thread. @param cond the condition to update. @return 0 on success. */ int eval_signal_informations(THD *thd, Sql_condition *cond); /** Raise a SQL condition. @param thd the current thread. @param cond the condition to raise. @return false on success. */ bool raise_condition(THD *thd, Sql_condition *cond); /** The condition to signal or resignal. This member is optional and can be NULL (RESIGNAL). */ const sp_condition_value *m_cond; /** Collection of 'SET item = value' assignments in the SIGNAL/RESIGNAL statement. */ Set_signal_information m_set_signal_information; }; /** Sql_cmd_signal represents a SIGNAL statement. */ class Sql_cmd_signal : public Sql_cmd_common_signal { public: /** Constructor, used to represent a SIGNAL statement. @param cond the SQL condition to signal (required). @param set the collection of signal information to signal. */ Sql_cmd_signal(const sp_condition_value *cond, const Set_signal_information& set) : Sql_cmd_common_signal(cond, set) {} virtual ~Sql_cmd_signal() = default; enum_sql_command sql_command_code() const override { return SQLCOM_SIGNAL; } bool execute(THD *thd) override; }; /** Sql_cmd_resignal represents a RESIGNAL statement. */ class Sql_cmd_resignal : public Sql_cmd_common_signal { public: /** Constructor, used to represent a RESIGNAL statement. @param cond the SQL condition to resignal (optional, may be NULL). @param set the collection of signal information to resignal. */ Sql_cmd_resignal(const sp_condition_value *cond, const Set_signal_information& set) : Sql_cmd_common_signal(cond, set) {} virtual ~Sql_cmd_resignal() = default; enum_sql_command sql_command_code() const override { return SQLCOM_RESIGNAL; } bool execute(THD *thd) override; }; #endif probes_mysql.h 0000644 00000001715 15156036127 0007446 0 ustar 00 /* Copyright (c) 2008 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef PROBES_MYSQL_H #define PROBES_MYSQL_H #if defined(HAVE_DTRACE) && !defined(DISABLE_DTRACE) #include "probes_mysql_dtrace.h" #else /* no dtrace */ #include "probes_mysql_nodtrace.h" #endif #endif /* PROBES_MYSQL_H */ ilist.h 0000644 00000016105 15156036127 0006052 0 ustar 00 /* Copyright (c) 2019, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef ILIST_H #define ILIST_H #include "my_dbug.h" #include <cstddef> #include <iterator> // Derive your class from this struct to insert to a linked list. template <class Tag= void> struct ilist_node { #ifndef DBUG_OFF ilist_node() noexcept : next(NULL), prev(NULL) {} #else ilist_node() = default; #endif ilist_node(ilist_node *next, ilist_node *prev) noexcept : next(next), prev(prev) { } ilist_node *next; ilist_node *prev; }; // Modelled after std::list<T> template <class T, class Tag= void> class ilist { public: typedef ilist_node<Tag> ListNode; class Iterator; // All containers in C++ should define these types to implement generic // container interface. typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type &reference; typedef const value_type &const_reference; typedef T *pointer; typedef const T *const_pointer; typedef Iterator iterator; typedef Iterator const_iterator; /* FIXME */ typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const iterator> const_reverse_iterator; class Iterator { public: // All iterators in C++ should define these types to implement generic // iterator interface. typedef std::bidirectional_iterator_tag iterator_category; typedef T value_type; typedef std::ptrdiff_t difference_type; typedef T *pointer; typedef T &reference; explicit Iterator(ListNode *node) noexcept : node_(node) { DBUG_ASSERT(node_ != nullptr); } Iterator &operator++() noexcept { node_= node_->next; DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator++(int) noexcept { Iterator tmp(*this); operator++(); return tmp; } Iterator &operator--() noexcept { node_= node_->prev; DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator--(int) noexcept { Iterator tmp(*this); operator--(); return tmp; } reference operator*() noexcept { return *static_cast<pointer>(node_); } const_reference operator*() const noexcept { return *static_cast<pointer>(node_); } pointer operator->() noexcept { return static_cast<pointer>(node_); } friend bool operator==(const Iterator &lhs, const Iterator &rhs) noexcept { return lhs.node_ == rhs.node_; } friend bool operator!=(const Iterator &lhs, const Iterator &rhs) noexcept { return !(lhs == rhs); } private: ListNode *node_; friend class ilist; }; ilist() noexcept : sentinel_(&sentinel_, &sentinel_) {} reference front() noexcept { return *begin(); } reference back() noexcept { return *--end(); } const_reference front() const noexcept { return *begin(); } const_reference back() const noexcept { return *--end(); } iterator begin() noexcept { return iterator(sentinel_.next); } const_iterator begin() const noexcept { return iterator(const_cast<ListNode *>(sentinel_.next)); } iterator end() noexcept { return iterator(&sentinel_); } const_iterator end() const noexcept { return iterator(const_cast<ListNode *>(&sentinel_)); } reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } const_reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } reverse_iterator rend() noexcept { return reverse_iterator(begin()); } const_reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } bool empty() const noexcept { return sentinel_.next == &sentinel_; } // Not implemented because it's O(N) // size_type size() const // { // return static_cast<size_type>(std::distance(begin(), end())); // } void clear() noexcept { sentinel_.next= &sentinel_; sentinel_.prev= &sentinel_; } iterator insert(iterator pos, reference value) noexcept { ListNode *curr= pos.node_; ListNode *prev= pos.node_->prev; prev->next= &value; curr->prev= &value; static_cast<ListNode &>(value).prev= prev; static_cast<ListNode &>(value).next= curr; return iterator(&value); } iterator erase(iterator pos) noexcept { ListNode *prev= pos.node_->prev; ListNode *next= pos.node_->next; DBUG_ASSERT(prev->next == pos.node_); DBUG_ASSERT(next->prev == pos.node_); prev->next= next; next->prev= prev; #ifndef DBUG_OFF ListNode *curr= pos.node_; curr->prev= nullptr; curr->next= nullptr; #endif return Iterator(next); } void push_back(reference value) noexcept { insert(end(), value); } void pop_back() noexcept { erase(--end()); } void push_front(reference value) noexcept { insert(begin(), value); } void pop_front() noexcept { erase(begin()); } // STL version is O(n) but this is O(1) because an element can't be inserted // several times in the same ilist. void remove(reference value) noexcept { erase(iterator(&value)); } private: ListNode sentinel_; }; // Similar to ilist but also has O(1) size() method. template <class T, class Tag= void> class sized_ilist : public ilist<T, Tag> { typedef ilist<T, Tag> BASE; public: // All containers in C++ should define these types to implement generic // container interface. typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type &reference; typedef const value_type &const_reference; typedef T *pointer; typedef const T *const_pointer; typedef typename BASE::Iterator iterator; typedef const typename BASE::Iterator const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const iterator> const_reverse_iterator; sized_ilist() noexcept : size_(0) {} size_type size() const noexcept { return size_; } void clear() noexcept { BASE::clear(); size_= 0; } iterator insert(iterator pos, reference value) noexcept { ++size_; return BASE::insert(pos, value); } iterator erase(iterator pos) noexcept { --size_; return BASE::erase(pos); } void push_back(reference value) noexcept { insert(BASE::end(), value); } void pop_back() noexcept { erase(BASE::end()); } void push_front(reference value) noexcept { insert(BASE::begin(), value); } void pop_front() noexcept { erase(BASE::begin()); } void remove(reference value) noexcept { erase(iterator(&value)); } private: size_type size_; }; #endif wsrep_applier.h 0000644 00000005217 15156036130 0007576 0 ustar 00 /* Copyright 2013-2019 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef WSREP_APPLIER_H #define WSREP_APPLIER_H #include "sql_class.h" // THD class #include "rpl_rli.h" // Relay_log_info #include "log_event.h" // Format_description_log_event int wsrep_apply_events(THD* thd, Relay_log_info* rli, const void* events_buf, size_t buf_len); /* Applier error codes, when nothing better is available. */ #define WSREP_RET_SUCCESS 0 // Success #define WSREP_ERR_GENERIC 1 // When in doubt (MySQL default error code) #define WSREP_ERR_BAD_EVENT 2 // Can't parse event #define WSREP_ERR_NOT_FOUND 3 // Key. table, schema not found #define WSREP_ERR_EXISTS 4 // Key, table, schema already exists #define WSREP_ERR_WRONG_TYPE 5 // Incompatible data type #define WSREP_ERR_FAILED 6 // Operation failed for some internal reason #define WSREP_ERR_ABORTED 7 // Operation was aborted externally /* Loops over THD diagnostic area and concatenates all error messages * and error codes to a single continuous buffer to create a unique * but consistent failure signature which provider can use for voting * between the nodes in the cluster. * * @param thd THD context * @param dst buffer to store the signature * @param include_msg whether to use MySQL error message in addition to * MySQL error code. Note that in the case of a TOI * operation the message may be not consistent between * the nodes e.g. due to a different client locale setting * and should be omitted */ void wsrep_store_error(const THD* thd, wsrep::mutable_buffer& buf, bool include_msg); class Format_description_log_event; void wsrep_set_apply_format(THD*, Format_description_log_event*); Format_description_log_event* wsrep_get_apply_format(THD* thd); #endif /* WSREP_APPLIER_H */ sql_debug.h 0000644 00000013016 15156036130 0006663 0 ustar 00 #ifndef SQL_DEBUG_INCLUDED #define SQL_DEBUG_INCLUDED /* Copyright (c) 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ class Debug_key: public String { public: Debug_key() = default; void print(THD *thd) const { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, "DBUG: %.*s", length(), ptr()); } bool append_key_type(ha_base_keytype type) { static LEX_CSTRING names[20]= { {STRING_WITH_LEN("END")}, {STRING_WITH_LEN("TEXT")}, {STRING_WITH_LEN("BINARY")}, {STRING_WITH_LEN("SHORT_INT")}, {STRING_WITH_LEN("LONG_INT")}, {STRING_WITH_LEN("FLOAT")}, {STRING_WITH_LEN("DOUBLE")}, {STRING_WITH_LEN("NUM")}, {STRING_WITH_LEN("USHORT_INT")}, {STRING_WITH_LEN("ULONG_INT")}, {STRING_WITH_LEN("LONGLONG")}, {STRING_WITH_LEN("ULONGLONG")}, {STRING_WITH_LEN("INT24")}, {STRING_WITH_LEN("UINT24")}, {STRING_WITH_LEN("INT8")}, {STRING_WITH_LEN("VARTEXT1")}, {STRING_WITH_LEN("VARBINARY1")}, {STRING_WITH_LEN("VARTEXT2")}, {STRING_WITH_LEN("VARBINARY2")}, {STRING_WITH_LEN("BIT")} }; if ((uint) type >= array_elements(names)) return append(STRING_WITH_LEN("???")); return append(names[(uint) type]); } bool append_KEY_flag_names(ulong flags) { static LEX_CSTRING names[17]= { {STRING_WITH_LEN("HA_NOSAME")}, // 1 {STRING_WITH_LEN("HA_PACK_KEY")}, // 2; also in HA_KEYSEG {STRING_WITH_LEN("HA_SPACE_PACK_USED")}, // 4 {STRING_WITH_LEN("HA_VAR_LENGTH_KEY")}, // 8 {STRING_WITH_LEN("HA_AUTO_KEY")}, // 16 {STRING_WITH_LEN("HA_BINARY_PACK_KEY")}, // 32 {STRING_WITH_LEN("HA_NULL_PART_KEY")}, // 64 {STRING_WITH_LEN("HA_FULLTEXT")}, // 128 {STRING_WITH_LEN("HA_UNIQUE_CHECK")}, // 256 {STRING_WITH_LEN("HA_SORT_ALLOWS_SAME")}, // 512 {STRING_WITH_LEN("HA_SPATIAL")}, // 1024 {STRING_WITH_LEN("HA_NULL_ARE_EQUAL")}, // 2048 {STRING_WITH_LEN("HA_USES_COMMENT")}, // 4096 {STRING_WITH_LEN("HA_GENERATED_KEY")}, // 8192 {STRING_WITH_LEN("HA_USES_PARSER")}, // 16384 {STRING_WITH_LEN("HA_USES_BLOCK_SIZE")}, // 32768 {STRING_WITH_LEN("HA_KEY_HAS_PART_KEY_SEG")}// 65536 }; return append_flag32_names((uint) flags, names, array_elements(names)); } bool append_HA_KEYSEG_flag_names(uint32 flags) { static LEX_CSTRING names[]= { {STRING_WITH_LEN("HA_SPACE_PACK")}, // 1 {STRING_WITH_LEN("HA_PACK_KEY")}, // 2; also in KEY/MI/KEY_DEF {STRING_WITH_LEN("HA_PART_KEY_SEG")}, // 4 {STRING_WITH_LEN("HA_VAR_LENGTH_PART")}, // 8 {STRING_WITH_LEN("HA_NULL_PART")}, // 16 {STRING_WITH_LEN("HA_BLOB_PART")}, // 32 {STRING_WITH_LEN("HA_SWAP_KEY")}, // 64 {STRING_WITH_LEN("HA_REVERSE_SORT")}, // 128 {STRING_WITH_LEN("HA_NO_SORT")}, // 256 {STRING_WITH_LEN("??? 512 ???")}, // 512 {STRING_WITH_LEN("HA_BIT_PART")}, // 1024 {STRING_WITH_LEN("HA_CAN_MEMCMP")} // 2048 }; return append_flag32_names(flags, names, array_elements(names)); } bool append_HA_KEYSEG_type(ha_base_keytype type) { return append_ulonglong(type) || append(' ') || append_key_type(type); } bool append_HA_KEYSEG_flags(uint32 flags) { return append_hex_uint32(flags) || append(' ') || append_HA_KEYSEG_flag_names(flags); } bool append_key(const LEX_CSTRING &name, uint32 flags) { return append_name_value(Lex_cstring(STRING_WITH_LEN("name")), name, '`') || append(Lex_cstring(STRING_WITH_LEN(" flags="))) || append_hex_uint32(flags) || append(' ') || append_KEY_flag_names(flags); } bool append_KEY(const KEY &key) { return append_key(key.name, key.flags); } static void print_keysegs(THD *thd, const HA_KEYSEG *seg, uint count) { for (uint i= 0; i < count; i++) { Debug_key tmp; if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) && !tmp.append_ulonglong(i) && !tmp.append(Lex_cstring(STRING_WITH_LEN("].type="))) && !tmp.append_HA_KEYSEG_type((ha_base_keytype) seg[i].type)) tmp.print(thd); tmp.length(0); if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) && !tmp.append_ulonglong(i) && !tmp.append(Lex_cstring(STRING_WITH_LEN("].flag="))) && !tmp.append_HA_KEYSEG_flags(seg[i].flag)) tmp.print(thd); } } static void print_keys(THD *thd, const char *where, const KEY *keys, uint key_count) { for (uint i= 0; i < key_count; i++) { Debug_key tmp; if (!tmp.append(where, strlen(where)) && !tmp.append_KEY(keys[i])) tmp.print(thd); } } }; #endif // SQL_DEBUG_INCLUDED filesort_utils.h 0000644 00000025043 15156036130 0007770 0 ustar 00 /* Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef FILESORT_UTILS_INCLUDED #define FILESORT_UTILS_INCLUDED #include "my_global.h" #include "my_base.h" #include "sql_array.h" #include "handler.h" class Sort_param; /** Calculate cost of merge sort @param num_rows Total number of rows. @param num_keys_per_buffer Number of keys per buffer. @param elem_size Size of each element. @param key_compare_cost Cost to compare two keys during QSort & merge Calculates cost of merge sort by simulating call to merge_many_buff(). @retval Computed cost of merge sort in disk seeks. @note Declared here in order to be able to unit test it, since library dependencies have not been sorted out yet. See also comments get_merge_many_buffs_cost(). */ double get_merge_many_buffs_cost_fast(ha_rows num_rows, ha_rows num_keys_per_buffer, size_t elem_size, double compare_cost, bool with_addon_fields); /** These are the current sorting algorithms we compute cost for: PQ_SORT_ALL_FIELDS Sort via priority queue, with addon fields. PQ_SORT_ORDER_BY_FIELDS Sort via priority queue, without addon fields. MERGE_SORT_ALL_FIELDS Sort via merge sort, with addon fields. MERGE_SORT_ORDER_BY_FIELDS Sort via merge sort, without addon fields. Note: There is the possibility to do merge-sorting with dynamic length fields. This is more expensive than if there are only fixed length fields, however we do not (yet) account for that extra cost. We can extend the cost computation in the future to cover that case as well. Effectively there are 4 possible combinations for merge sort: With/without addon fields With/without dynamic length fields. */ enum sort_type { PQ_SORT_ALL_FIELDS= 0, PQ_SORT_ORDER_BY_FIELDS, MERGE_SORT_ALL_FIELDS, MERGE_SORT_ORDER_BY_FIELDS, NO_SORT_POSSIBLE_OUT_OF_MEM, /* In case of errors */ FINAL_SORT_TYPE= NO_SORT_POSSIBLE_OUT_OF_MEM }; struct Sort_costs { Sort_costs() : fastest_sort(NO_SORT_POSSIBLE_OUT_OF_MEM), lowest_cost(DBL_MAX) {} void compute_sort_costs(Sort_param *param, ha_rows num_rows, size_t memory_available, bool with_addon_fields); /* Cache value for fastest_sort. */ enum sort_type fastest_sort; /* Cache value for lowest cost. */ double lowest_cost; private: /* Array to hold all computed costs. TODO(cvicentiu) This array is only useful for debugging. If it's not used in debugging code, it can be removed to reduce memory usage. */ double costs[FINAL_SORT_TYPE]; void compute_pq_sort_costs(Sort_param *param, ha_rows num_rows, size_t memory_available, bool with_addon_fields); void compute_merge_sort_costs(Sort_param *param, ha_rows num_rows, size_t memory_available, bool with_addon_fields); void compute_fastest_sort(); }; /** A wrapper class around the buffer used by filesort(). The sort buffer is a contiguous chunk of memory, containing both records to be sorted, and pointers to said records: <start of buffer | still unused | end of buffer> | rec0 | rec1 | rec2 | ............ |ptr to rec2|ptr to rec1|ptr to rec0| Records will be inserted "left-to-right". Records are not necessarily fixed-size, they can be packed and stored without any "gaps". Record pointers will be inserted "right-to-left", as a side-effect of inserting the actual records. We wrap the buffer in order to be able to do lazy initialization of the pointers: the buffer is often much larger than what we actually need. With this allocation scheme, and lazy initialization of the pointers, we are able to pack variable-sized records in the buffer, and thus possibly have space for more records than we initially estimated. The buffer must be kept available for multiple executions of the same sort operation, so we have explicit allocate and free functions, rather than doing alloc/free in CTOR/DTOR. */ class Filesort_buffer { public: Filesort_buffer() : m_next_rec_ptr(NULL), m_rawmem(NULL), m_record_pointers(NULL), m_sort_keys(NULL), m_num_records(0), m_record_length(0), m_sort_length(0), m_size_in_bytes(0), m_idx(0) {} /** Sort me... */ void sort_buffer(const Sort_param *param, uint count); /** Reverses the record pointer array, to avoid recording new results for non-deterministic mtr tests. */ void reverse_record_pointers() { if (m_idx < 2) // There is nothing to swap. return; uchar **keys= get_sort_keys(); const longlong count= m_idx - 1; for (longlong ix= 0; ix <= count/2; ++ix) { uchar *tmp= keys[count - ix]; keys[count - ix] = keys[ix]; keys[ix]= tmp; } } /** Initializes all the record pointers. */ void init_record_pointers() { init_next_record_pointer(); while (m_idx < m_num_records) (void) get_next_record_pointer(); reverse_record_pointers(); } /** Prepares the buffer for the next batch of records to process. */ void init_next_record_pointer() { m_idx= 0; m_next_rec_ptr= m_rawmem; m_sort_keys= NULL; } /** @returns the number of bytes currently in use for data. */ size_t space_used_for_data() const { return m_next_rec_ptr ? m_next_rec_ptr - m_rawmem : 0; } /** @returns the number of bytes left in the buffer. */ size_t spaceleft() const { DBUG_ASSERT(m_next_rec_ptr >= m_rawmem); const size_t spaceused= (m_next_rec_ptr - m_rawmem) + (static_cast<size_t>(m_idx) * sizeof(uchar*)); return m_size_in_bytes - spaceused; } /** Is the buffer full? */ bool isfull() const { if (m_idx < m_num_records) return false; return spaceleft() < (m_record_length + sizeof(uchar*)); } /** Where should the next record be stored? */ uchar *get_next_record_pointer() { uchar *retval= m_next_rec_ptr; // Save the return value in the record pointer array. m_record_pointers[-m_idx]= m_next_rec_ptr; // Prepare for the subsequent request. m_idx++; m_next_rec_ptr+= m_record_length; return retval; } /** Adjusts for actual record length. get_next_record_pointer() above was pessimistic, and assumed that the record could not be packed. */ void adjust_next_record_pointer(uint val) { m_next_rec_ptr-= (m_record_length - val); } /// Returns total size: pointer array + record buffers. size_t sort_buffer_size() const { return m_size_in_bytes; } bool is_allocated() const { return m_rawmem; } /** Allocates the buffer, but does *not* initialize pointers. Total size = (num_records * record_length) + (num_records * sizeof(pointer)) space for records space for pointer to records Caller is responsible for raising an error if allocation fails. @param num_records Number of records. @param record_length (maximum) size of each record. @returns Pointer to allocated area, or NULL in case of out-of-memory. */ uchar *alloc_sort_buffer(uint num_records, uint record_length); /// Frees the buffer. void free_sort_buffer(); void reset() { m_rawmem= NULL; } /** Used to access the "right-to-left" array of record pointers as an ordinary "left-to-right" array, so that we can pass it directly on to std::sort(). */ uchar **get_sort_keys() { if (m_idx == 0) return NULL; return &m_record_pointers[1 - m_idx]; } /** Gets sorted record number ix. @see get_sort_keys() Only valid after buffer has been sorted! */ uchar *get_sorted_record(uint ix) { return m_sort_keys[ix]; } /** @returns The entire buffer, as a character array. This is for reusing the memory for merge buffers. */ Bounds_checked_array<uchar> get_raw_buf() { return Bounds_checked_array<uchar>(m_rawmem, m_size_in_bytes); } /** We need an assignment operator, see filesort(). This happens to have the same semantics as the one that would be generated by the compiler. Note that this is a shallow copy. We have two objects sharing the same array. */ Filesort_buffer &operator=(const Filesort_buffer &rhs) = default; uint get_sort_length() const { return m_sort_length; } void set_sort_length(uint val) { m_sort_length= val; } private: uchar *m_next_rec_ptr; /// The next record will be inserted here. uchar *m_rawmem; /// The raw memory buffer. uchar **m_record_pointers; /// The "right-to-left" array of record pointers. uchar **m_sort_keys; /// Caches the value of get_sort_keys() uint m_num_records; /// Saved value from alloc_sort_buffer() uint m_record_length; /// Saved value from alloc_sort_buffer() uint m_sort_length; /// The length of the sort key. size_t m_size_in_bytes; /// Size of raw buffer, in bytes. /** This is the index in the "right-to-left" array of the next record to be inserted into the buffer. It is signed, because we use it in signed expressions like: m_record_pointers[-m_idx]; It is longlong rather than int, to ensure that it covers UINT_MAX32 without any casting/warning. */ longlong m_idx; }; /* Names for sort_type */ extern const LEX_CSTRING filesort_names[]; double cost_of_filesort(TABLE *table, ORDER *order_by, ha_rows rows_to_read, ha_rows limit_rows, enum sort_type *used_sort_type); double get_qsort_sort_cost(ha_rows num_rows, bool with_addon_fields); int compare_packed_sort_keys(void *sort_param, const void *a_ptr, const void *b_ptr); qsort_cmp2 get_packed_keys_compare_ptr(); #endif // FILESORT_UTILS_INCLUDED event_scheduler.h 0000644 00000006332 15156036130 0010100 0 ustar 00 #ifndef _EVENT_SCHEDULER_H_ #define _EVENT_SCHEDULER_H_ /* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @addtogroup Event_Scheduler @{ */ /** @file Declarations of the scheduler thread class and related functionality. This file is internal to Event_Scheduler module. Please do not include it directly. All public declarations of Event_Scheduler module are in events.h and event_data_objects.h. */ class Event_queue; class Event_job_data; class Event_db_repository; class Event_queue_element_for_exec; class Events; class THD; void pre_init_event_thread(THD* thd); bool post_init_event_thread(THD* thd); void deinit_event_thread(THD *thd); class Event_worker_thread { public: static void init(Event_db_repository *db_repository_arg) { db_repository= db_repository_arg; } void run(THD *thd, Event_queue_element_for_exec *event); private: void print_warnings(THD *thd, Event_job_data *et); static Event_db_repository *db_repository; }; class Event_scheduler { public: Event_scheduler(Event_queue *event_queue_arg); ~Event_scheduler(); /* State changing methods follow */ bool start(int *err_no); bool stop(); /* Need to be public because has to be called from the function passed to pthread_create. */ bool run(THD *thd); /* Information retrieving methods follow */ bool is_running(); void dump_internal_status(); private: uint workers_count(); /* helper functions */ bool execute_top(Event_queue_element_for_exec *event_name); /* helper functions for working with mutexes & conditionals */ void lock_data(const char *func, uint line); void unlock_data(const char *func, uint line); void cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, const char *src_func, const char *src_file, uint src_line); mysql_mutex_t LOCK_scheduler_state; enum enum_state { INITIALIZED = 0, RUNNING, STOPPING }; /* This is the current status of the life-cycle of the scheduler. */ enum enum_state state; THD *scheduler_thd; mysql_cond_t COND_state; Event_queue *queue; uint mutex_last_locked_at_line; uint mutex_last_unlocked_at_line; const char* mutex_last_locked_in_func; const char* mutex_last_unlocked_in_func; bool mutex_scheduler_data_locked; bool waiting_on_cond; ulonglong started_events; private: /* Prevent use of these */ Event_scheduler(const Event_scheduler &); void operator=(Event_scheduler &); }; /** @} (End of group Event_Scheduler) */ #endif /* _EVENT_SCHEDULER_H_ */ sql_udf.h 0000644 00000011362 15156036130 0006355 0 ustar 00 #ifndef SQL_UDF_INCLUDED #define SQL_UDF_INCLUDED /* Copyright (c) 2000, 2003-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file defines structures needed by udf functions */ #ifdef USE_PRAGMA_INTERFACE #pragma interface #endif enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE}; typedef void (*Udf_func_clear)(UDF_INIT *, uchar *, uchar *); typedef void (*Udf_func_add)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *); typedef void (*Udf_func_deinit)(UDF_INIT*); typedef my_bool (*Udf_func_init)(UDF_INIT *, UDF_ARGS *, char *); typedef void *Udf_func_any; typedef double (*Udf_func_double)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *); typedef longlong (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *); typedef struct st_udf_func { LEX_CSTRING name; Item_result returns; Item_udftype type; const char *dl; void *dlhandle; Udf_func_any func; Udf_func_init func_init; Udf_func_deinit func_deinit; Udf_func_clear func_clear; Udf_func_add func_add; Udf_func_add func_remove; ulong usage_count; } udf_func; class Item_result_field; class udf_handler :public Sql_alloc { protected: udf_func *u_d; String *buffers; UDF_ARGS f_args; UDF_INIT initid; char *num_buffer; uchar error, is_null; bool initialized; Item **args; public: bool not_original; udf_handler(udf_func *udf_arg) :u_d(udf_arg), buffers(0), error(0), is_null(0), initialized(0), not_original(0) {} ~udf_handler(); const char *name() const { return u_d ? u_d->name.str : "?"; } Item_result result_type () const { return u_d ? u_d->returns : STRING_RESULT;} bool get_arguments(); bool fix_fields(THD *thd, Item_func_or_sum *item, uint arg_count, Item **args); void cleanup(); double val(my_bool *null_value) { is_null= 0; if (get_arguments()) { *null_value=1; return 0.0; } Udf_func_double func= (Udf_func_double) u_d->func; double tmp=func(&initid, &f_args, &is_null, &error); if (is_null || error) { *null_value=1; return 0.0; } *null_value=0; return tmp; } longlong val_int(my_bool *null_value) { is_null= 0; if (get_arguments()) { *null_value=1; return 0; } Udf_func_longlong func= (Udf_func_longlong) u_d->func; longlong tmp=func(&initid, &f_args, &is_null, &error); if (is_null || error) { *null_value=1; return 0; } *null_value=0; return tmp; } my_decimal *val_decimal(my_bool *null_value, my_decimal *dec_buf); void clear() { is_null= 0; Udf_func_clear func= u_d->func_clear; func(&initid, &is_null, &error); } void add(my_bool *null_value) { if (get_arguments()) { *null_value=1; return; } Udf_func_add func= u_d->func_add; func(&initid, &f_args, &is_null, &error); *null_value= (my_bool) (is_null || error); } bool supports_removal() const { return MY_TEST(u_d->func_remove); } void remove(my_bool *null_value) { DBUG_ASSERT(u_d->func_remove); if (get_arguments()) { *null_value=1; return; } Udf_func_add func= u_d->func_remove; func(&initid, &f_args, &is_null, &error); *null_value= (my_bool) (is_null || error); } String *val_str(String *str,String *save_str); udf_handler(const udf_handler &orig) { u_d = orig.u_d; buffers = orig.buffers; f_args = orig.f_args; initid = orig.initid; num_buffer = orig.num_buffer; error = orig.error; is_null = orig.is_null; initialized = orig.initialized; args = orig.args; not_original = true; } }; #ifdef HAVE_DLOPEN void udf_init(void),udf_free(void); udf_func *find_udf(const char *name, size_t size, bool mark_used=0); void free_udf(udf_func *udf); int mysql_create_function(THD *thd,udf_func *udf); enum drop_udf_result { UDF_DEL_RESULT_ABSENT, UDF_DEL_RESULT_DELETED, UDF_DEL_RESULT_ERROR }; enum drop_udf_result mysql_drop_function(THD *thd, const LEX_CSTRING *name); #else static inline void udf_init(void) { } static inline void udf_free(void) { } #endif #endif /* SQL_UDF_INCLUDED */ simple_tokenizer.h 0000644 00000003735 15156036130 0010310 0 ustar 00 /* Copyright (c) 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SIMPLE_TOKENIZER_INCLUDED #define SIMPLE_TOKENIZER_INCLUDED class Simple_tokenizer { const char *m_ptr; const char *m_end; public: Simple_tokenizer(const char *str, size_t length) :m_ptr(str), m_end(str + length) { } const char *ptr() const { return m_ptr; } bool eof() const { return m_ptr >= m_end; } void get_spaces() { for ( ; !eof(); m_ptr++) { if (m_ptr[0] != ' ') break; } } bool is_ident_start(char ch) const { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; } bool is_ident_body(char ch) const { return is_ident_start(ch) || (ch >= '0' && ch <= '9'); } bool is_ident_start() const { return !eof() && is_ident_start(*m_ptr); } bool is_ident_body() const { return !eof() && is_ident_body(*m_ptr); } LEX_CSTRING get_ident() { get_spaces(); if (!is_ident_start()) return {m_ptr,0}; const char *start= m_ptr++; for ( ; is_ident_body(); m_ptr++) { } LEX_CSTRING res= {start, (size_t) (m_ptr - start)}; return res; } bool get_char(char ch) { get_spaces(); if (eof() || *m_ptr != ch) return true; m_ptr++; return false; } }; #endif // SIMPLE_TOKENIZER_INCLUDED my_rdtsc.h 0000644 00000023607 15156036130 0006551 0 ustar 00 /* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc. Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* rdtsc3 -- multi-platform timer code pgulutzan@mysql.com, 2005-08-29 modified 2008-11-02 */ #ifndef MY_RDTSC_H #define MY_RDTSC_H # ifndef __has_builtin # define __has_builtin(x) 0 /* Compatibility with non-clang compilers */ # endif # if __has_builtin(__builtin_readcyclecounter) # elif defined _WIN32 # include <intrin.h> # elif defined __i386__ || defined __x86_64__ # include <x86intrin.h> # elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) # include <ia64intrin.h> # elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) # include <sys/times.h> # endif /** Characteristics of a timer. */ struct my_timer_unit_info { /** Routine used for the timer. */ ulonglong routine; /** Overhead of the timer. */ ulonglong overhead; /** Frequency of the timer. */ ulonglong frequency; /** Resolution of the timer. */ ulonglong resolution; }; /** Characteristics of all the supported timers. @sa my_timer_init(). */ struct my_timer_info { /** Characteristics of the cycle timer. */ struct my_timer_unit_info cycles; /** Characteristics of the nanosecond timer. */ struct my_timer_unit_info nanoseconds; /** Characteristics of the microsecond timer. */ struct my_timer_unit_info microseconds; /** Characteristics of the millisecond timer. */ struct my_timer_unit_info milliseconds; /** Characteristics of the tick timer. */ struct my_timer_unit_info ticks; }; typedef struct my_timer_info MY_TIMER_INFO; #define MY_TIMER_ROUTINE_RDTSC 5 #define MY_TIMER_ROUTINE_ASM_IA64 6 #define MY_TIMER_ROUTINE_PPC_GET_TIMEBASE 7 #define MY_TIMER_ROUTINE_GETHRTIME 9 #define MY_TIMER_ROUTINE_READ_REAL_TIME 10 #define MY_TIMER_ROUTINE_CLOCK_GETTIME 11 #define MY_TIMER_ROUTINE_GETTIMEOFDAY 13 #define MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER 14 #define MY_TIMER_ROUTINE_GETTICKCOUNT 15 #define MY_TIMER_ROUTINE_TIME 16 #define MY_TIMER_ROUTINE_TIMES 17 #define MY_TIMER_ROUTINE_FTIME 18 #define MY_TIMER_ROUTINE_ASM_GCC_SPARC64 23 #define MY_TIMER_ROUTINE_ASM_GCC_SPARC32 24 #define MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME 25 #define MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME 26 #define MY_TIMER_ROUTINE_ASM_S390 28 #define MY_TIMER_ROUTINE_AARCH64 29 #define MY_TIMER_ROUTINE_RISCV 30 C_MODE_START /** A cycle timer. On clang we use __builtin_readcyclecounter(), except for AARCH64 and RISC-V. On other compilers: On IA-32 and AMD64, we use the RDTSC instruction. On IA-64, we read the ar.itc register. On SPARC, we read the tick register. On POWER, we read the Time Base Register (which is not really a cycle count but a separate counter with less than nanosecond resolution). On IBM S/390 System z we use the STCK instruction. On ARM, we probably should use the Generic Timer, but should figure out how to ensure that it can be accessed. On AARCH64, we use the generic timer base register. We override clang implementation for aarch64 as it access a PMU register which is not guaranteed to be active. On RISC-V, we use the rdtime instruction to read from mtime register. Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k, HP PA-RISC or other non-mainstream (or obsolete) processors. TODO: consider C++11 std::chrono::high_resolution_clock. We fall back to gethrtime() where available. On the platforms that do not have a CYCLE timer, "wait" events are initialized to use NANOSECOND instead of CYCLE during performance_schema initialization (at the server startup). Linux performance monitor (see "man perf_event_open") can provide cycle counter on the platforms that do not have other kinds of cycle counters. But we don't use it so far. ARM notes --------- Userspace high precision timing on CNTVCT_EL0 requires that CNTKCTL_EL1 is set to 1 for each CPU in privileged mode. During tests on ARMv7 Debian, perf_even_open() based cycle counter provided too low frequency with too high overhead: MariaDB [performance_schema]> SELECT * FROM performance_timers; +-------------+-----------------+------------------+----------------+ | TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD | +-------------+-----------------+------------------+----------------+ | CYCLE | 689368159 | 1 | 970 | | NANOSECOND | 1000000000 | 1 | 308 | | MICROSECOND | 1000000 | 1 | 417 | | MILLISECOND | 1000 | 1000 | 407 | | TICK | 127 | 1 | 612 | +-------------+-----------------+------------------+----------------+ Therefore, it was decided not to use perf_even_open() on ARM (i.e. go without CYCLE and have "wait" events use NANOSECOND by default). @return the current timer value, in cycles. */ static inline ulonglong my_timer_cycles(void) { # if __has_builtin(__builtin_readcyclecounter) && !defined (__aarch64__) && !(defined(__linux__) && defined(__riscv)) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 return __builtin_readcyclecounter(); # elif defined _M_IX86 || defined _M_X64 || defined __i386__ || defined __x86_64__ #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_RDTSC return __rdtsc(); #elif defined _M_ARM64 #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 return _ReadStatusReg(ARM64_CNTVCT); # elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_IA64 return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */ #elif defined(__GNUC__) && defined(__ia64__) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_IA64 { ulonglong result; __asm __volatile__ ("mov %0=ar.itc" : "=r" (result)); return result; } #elif defined __GNUC__ && defined __powerpc__ #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_PPC_GET_TIMEBASE return __builtin_ppc_get_timebase(); #elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_GCC_SPARC64 { ulonglong result; __asm __volatile__ ("rd %%tick,%0" : "=r" (result)); return result; } #elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_GCC_SPARC32 { union { ulonglong wholeresult; struct { ulong high; ulong low; } splitresult; } result; __asm __volatile__ ("rd %%tick,%1; srlx %1,32,%0" : "=r" (result.splitresult.high), "=r" (result.splitresult.low)); return result.wholeresult; } #elif defined(__GNUC__) && defined(__s390__) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_S390 /* covers both s390 and s390x */ { ulonglong result; __asm__ __volatile__ ("stck %0" : "=Q" (result) : : "cc"); return result; } #elif defined(__GNUC__) && defined (__aarch64__) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 { ulonglong result; __asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result)); return result; } #elif defined(__riscv) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_RISCV /* Use RDTIME (and RDTIMEH on riscv32) */ { # if __riscv_xlen == 32 ulong result_lo, result_hi0, result_hi1; /* Implemented in assembly because Clang insisted on branching. */ __asm __volatile__( "rdtimeh %0\n" "rdtime %1\n" "rdtimeh %2\n" "sub %0, %0, %2\n" "seqz %0, %0\n" "sub %0, zero, %0\n" "and %1, %1, %0\n" : "=r"(result_hi0), "=r"(result_lo), "=r"(result_hi1)); return (static_cast<ulonglong>(result_hi1) << 32) | result_lo; # else ulonglong result; __asm __volatile__("rdtime %0" : "=r"(result)); return result; # endif } #elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_GETHRTIME /* gethrtime may appear as either cycle or nanosecond counter */ return (ulonglong) gethrtime(); #else #define MY_TIMER_ROUTINE_CYCLES 0 return 0; #endif } #if MY_TIMER_ROUTINE_CYCLES == 0 static inline size_t my_pseudo_random(void) { /* In some platforms, pthread_self() might return a structure that cannot be converted to a number like this. Possible alternatives could include gettid() or sched_getcpu(). */ return ((size_t) pthread_self()) / 16; } #else # define my_pseudo_random my_timer_cycles #endif /** A nanosecond timer. @return the current timer value, in nanoseconds. */ ulonglong my_timer_nanoseconds(void); /** A microseconds timer. @return the current timer value, in microseconds. */ ulonglong my_timer_microseconds(void); /** A millisecond timer. @return the current timer value, in milliseconds. */ ulonglong my_timer_milliseconds(void); /** A ticks timer. @return the current timer value, in ticks. */ ulonglong my_timer_ticks(void); /** Timer initialization function. @param [out] mti the timer characteristics. */ void my_timer_init(MY_TIMER_INFO *mti); C_MODE_END #endif sql_statistics.h 0000644 00000040644 15156036130 0007776 0 ustar 00 /* Copyright 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_STATISTICS_H #define SQL_STATISTICS_H #include <vector> #include <string> /* For COMPLEMENTARY_FOR_QUERIES and PREFERABLY_FOR_QUERIES they are similar to the COMPLEMENTARY and PREFERABLY respectively except that with these values we would not be collecting EITS for queries like ANALYZE TABLE t1; To collect EITS with these values, we have to use PERSISITENT FOR analyze table t1 persistent for columns (col1,col2...) index (idx1, idx2...) or analyze table t1 persistent for all */ typedef enum enum_use_stat_tables_mode { NEVER, COMPLEMENTARY, PREFERABLY, COMPLEMENTARY_FOR_QUERIES, PREFERABLY_FOR_QUERIES } Use_stat_tables_mode; typedef enum enum_histogram_type { SINGLE_PREC_HB, DOUBLE_PREC_HB, JSON_HB, INVALID_HISTOGRAM } Histogram_type; enum enum_stat_tables { TABLE_STAT, COLUMN_STAT, INDEX_STAT, }; /* These enumeration types comprise the dictionary of three statistical tables table_stat, column_stat and index_stat as they defined in ../scripts/mysql_system_tables.sql. It would be nice if the declarations of these types were generated automatically by the table definitions. */ enum enum_table_stat_col { TABLE_STAT_DB_NAME, TABLE_STAT_TABLE_NAME, TABLE_STAT_CARDINALITY, TABLE_STAT_N_FIELDS }; enum enum_column_stat_col { COLUMN_STAT_DB_NAME, COLUMN_STAT_TABLE_NAME, COLUMN_STAT_COLUMN_NAME, COLUMN_STAT_MIN_VALUE, COLUMN_STAT_MAX_VALUE, COLUMN_STAT_NULLS_RATIO, COLUMN_STAT_AVG_LENGTH, COLUMN_STAT_AVG_FREQUENCY, COLUMN_STAT_HIST_SIZE, COLUMN_STAT_HIST_TYPE, COLUMN_STAT_HISTOGRAM, COLUMN_STAT_N_FIELDS }; enum enum_index_stat_col { INDEX_STAT_DB_NAME, INDEX_STAT_TABLE_NAME, INDEX_STAT_INDEX_NAME, INDEX_STAT_PREFIX_ARITY, INDEX_STAT_AVG_FREQUENCY, INDEX_STAT_N_FIELDS }; inline Use_stat_tables_mode get_use_stat_tables_mode(THD *thd) { return (Use_stat_tables_mode) (thd->variables.use_stat_tables); } inline bool check_eits_collection_allowed(THD *thd) { return (get_use_stat_tables_mode(thd) == COMPLEMENTARY || get_use_stat_tables_mode(thd) == PREFERABLY); } inline bool check_eits_preferred(THD *thd) { return (get_use_stat_tables_mode(thd) == PREFERABLY || get_use_stat_tables_mode(thd) == PREFERABLY_FOR_QUERIES); } int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables); int read_statistics_for_tables(THD *thd, TABLE_LIST *tables, bool force_reload); int collect_statistics_for_table(THD *thd, TABLE *table); int alloc_statistics_for_table(THD *thd, TABLE *table, MY_BITMAP *stat_fields); void free_statistics_for_table(TABLE *table); int update_statistics_for_table(THD *thd, TABLE *table); int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab); int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col); int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, bool ext_prefixes_only); int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab, const LEX_CSTRING *new_db, const LEX_CSTRING *new_tab); int rename_columns_in_stat_table(THD *thd, TABLE *tab, List<Alter_info::RENAME_COLUMN_STAT_PARAMS> *fields); int rename_indexes_in_stat_table(THD *thd, TABLE *tab, List<Alter_info::RENAME_INDEX_STAT_PARAMS> *indexes); void set_statistics_for_table(THD *thd, TABLE *table); double get_column_avg_frequency(Field * field); double get_column_range_cardinality(Field *field, key_range *min_endp, key_range *max_endp, uint range_flag); bool is_stat_table(const LEX_CSTRING *db, LEX_CSTRING *table); bool is_eits_usable(Field* field); class Histogram_builder; /* Common base for all histograms */ class Histogram_base :public Sql_alloc { public: Histogram_base() {} virtual ~Histogram_base()= default; virtual bool parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, Field *field, const char *hist_data, size_t hist_data_len)= 0; virtual void serialize(Field *to_field)= 0; virtual Histogram_type get_type()=0; virtual uint get_width()=0; /* The creation-time workflow is: * create a histogram * init_for_collection() * create_builder() * feed the data to the builder * serialize(); */ virtual void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, ulonglong size)=0; virtual Histogram_builder *create_builder(Field *col, uint col_len, ha_rows rows)=0; /* This function checks that histograms should be usable only when 1) the level of optimizer_use_condition_selectivity > 3 */ bool is_usable(THD *thd) { return thd->variables.optimizer_use_condition_selectivity > 3; } virtual double point_selectivity(Field *field, key_range *endpoint, double avg_sel)=0; virtual double range_selectivity(Field *field, key_range *min_endp, key_range *max_endp, double avg_sel)=0; /* Legacy: return the size of the histogram on disk. This will be stored in mysql.column_stats.hist_size column. The value is not really needed as one can look at LENGTH(mysql.column_stats.histogram) directly. */ virtual uint get_size()=0; }; /* A Height-balanced histogram that stores numeric fractions */ class Histogram_binary final : public Histogram_base { private: Histogram_type type; size_t size; /* Size of values array, in bytes */ uchar *values; uint prec_factor() { switch (type) { case SINGLE_PREC_HB: return ((uint) (1 << 8) - 1); case DOUBLE_PREC_HB: return ((uint) (1 << 16) - 1); default: DBUG_ASSERT(0); } return 1; } public: Histogram_binary(Histogram_type type_arg) : type(type_arg) {} uint get_width() override { switch (type) { case SINGLE_PREC_HB: return (uint) size; case DOUBLE_PREC_HB: return (uint) (size / 2); default: DBUG_ASSERT(0); } return 0; } private: uint get_value(uint i) { DBUG_ASSERT(i < get_width()); switch (type) { case SINGLE_PREC_HB: return (uint) (((uint8 *) values)[i]); case DOUBLE_PREC_HB: return (uint) uint2korr(values + i * 2); default: DBUG_ASSERT(0); } return 0; } /* Find the bucket which value 'pos' falls into. */ uint find_bucket(double pos, bool first) { size_t val= (size_t) (pos * prec_factor()); int lp= 0; int rp= get_width() - 1; int d= get_width() / 2; uint i= lp + d; for ( ; d; d= (rp - lp) / 2, i= lp + d) { if (val == get_value(i)) break; if (val < get_value(i)) rp= i; else if (val > get_value(i + 1)) lp= i + 1; else break; } if (val > get_value(i) && i < (get_width() - 1)) i++; if (val == get_value(i)) { if (first) { while(i && val == get_value(i - 1)) i--; } else { while(i + 1 < get_width() && val == get_value(i + 1)) i++; } } return i; } public: uint get_size() override {return (uint)size;} Histogram_type get_type() override { return type; } bool parse(MEM_ROOT *mem_root, const char*, const char*, Field*, const char *hist_data, size_t hist_data_len) override; void serialize(Field *to_field) override; void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, ulonglong size) override; Histogram_builder *create_builder(Field *col, uint col_len, ha_rows rows) override; void set_value(uint i, double val) { switch (type) { case SINGLE_PREC_HB: ((uint8 *) values)[i]= (uint8) (val * prec_factor()); return; case DOUBLE_PREC_HB: int2store(values + i * 2, val * prec_factor()); return; default: DBUG_ASSERT(0); return; } } void set_prev_value(uint i) { switch (type) { case SINGLE_PREC_HB: ((uint8 *) values)[i]= ((uint8 *) values)[i-1]; return; case DOUBLE_PREC_HB: int2store(values + i * 2, uint2korr(values + i * 2 - 2)); return; default: DBUG_ASSERT(0); return; } } double range_selectivity(Field *field, key_range *min_endp, key_range *max_endp, double avg_sel) override; /* Estimate selectivity of "col=const" using a histogram */ double point_selectivity(Field *field, key_range *endpoint, double avg_sel) override; }; /* This is used to collect the basic statistics from a Unique object: - count of values - count of distinct values - count of distinct values that have occurred only once */ class Basic_stats_collector { ulonglong count; /* number of values retrieved */ ulonglong count_distinct; /* number of distinct values retrieved */ /* number of distinct values that occurred only once */ ulonglong count_distinct_single_occurence; public: Basic_stats_collector() { count= 0; count_distinct= 0; count_distinct_single_occurence= 0; } ulonglong get_count_distinct() const { return count_distinct; } ulonglong get_count_single_occurence() const { return count_distinct_single_occurence; } ulonglong get_count() const { return count; } void next(void *elem, element_count elem_cnt) { count_distinct++; if (elem_cnt == 1) count_distinct_single_occurence++; count+= elem_cnt; } }; /* Histogram_builder is a helper class that is used to build histograms for columns. Do not create directly, call Histogram->get_builder(...); */ class Histogram_builder: public Sql_alloc { protected: Field *column; /* table field for which the histogram is built */ uint col_length; /* size of this field */ ha_rows records; /* number of records the histogram is built for */ Histogram_builder(Field *col, uint col_len, ha_rows rows) : column(col), col_length(col_len), records(rows) {} public: // A histogram builder will also collect the counters Basic_stats_collector counters; virtual int next(void *elem, element_count elem_cnt)=0; virtual void finalize()=0; virtual ~Histogram_builder(){} }; class Column_statistics; class Index_statistics; /* Statistical data on a table */ class Table_statistics { public: my_bool cardinality_is_null; /* TRUE if the cardinality is unknown */ uint columns; /* Number of columns in table */ ha_rows cardinality; /* Number of rows in the table */ uchar *min_max_record_buffers; /* Record buffers for min/max values */ Column_statistics *column_stats; /* Array of statistical data for columns */ Index_statistics *index_stats; /* Array of statistical data for indexes */ /* Array of records per key for index prefixes */ ulonglong *idx_avg_frequency; uchar *histograms; /* Sequence of histograms */ }; /* Statistical data on a column Note: objects of this class may be "empty", where they have almost all fields as zeros, for example, get_avg_frequency() will return 0. objects are allocated in alloc_statistics_for_table[_share]. */ class Column_statistics :public Sql_alloc { private: static const uint Scale_factor_nulls_ratio= 100000; static const uint Scale_factor_avg_length= 100000; static const uint Scale_factor_avg_frequency= 100000; public: ~Column_statistics() { delete histogram; } /* Bitmap indicating what statistical characteristics are available for the column */ uint32 column_stat_nulls; /* For the below two, see comments in get_column_range_cardinality() */ /* Minimum value for the column */ Field *min_value; /* Maximum value for the column */ Field *max_value; private: /* The ratio Z/N multiplied by the scale factor Scale_factor_nulls_ratio, where N is the total number of rows, Z is the number of nulls in the column */ ulong nulls_ratio; /* Average number of bytes occupied by the representation of a value of the column in memory buffers such as join buffer multiplied by the scale factor Scale_factor_avg_length. CHAR values are stripped of trailing spaces. Flexible values are stripped of their length prefixes. */ ulonglong avg_length; /* The ratio N/D multiplied by the scale factor Scale_factor_avg_frequency, where N is the number of rows with not null value in the column, D the number of distinct values among them */ ulonglong avg_frequency; public: Histogram_base *histogram; bool histogram_exists; uint32 no_values_provided_bitmap() { return ((1 << (COLUMN_STAT_HISTOGRAM-COLUMN_STAT_COLUMN_NAME))-1) << (COLUMN_STAT_COLUMN_NAME+1); } void set_all_nulls() { column_stat_nulls= no_values_provided_bitmap(); } void set_not_null(uint stat_field_no) { column_stat_nulls&= ~(1 << stat_field_no); } void set_null(uint stat_field_no) { column_stat_nulls|= (1 << stat_field_no); } bool is_null(uint stat_field_no) { return MY_TEST(column_stat_nulls & (1 << stat_field_no)); } double get_nulls_ratio() { return (double) nulls_ratio / Scale_factor_nulls_ratio; } double get_avg_length() { return (double) avg_length / Scale_factor_avg_length; } double get_avg_frequency() { return (double) avg_frequency / Scale_factor_avg_frequency; } void set_nulls_ratio (double val) { nulls_ratio= (ulong) (val * Scale_factor_nulls_ratio); } void set_avg_length (double val) { avg_length= (ulonglong) (val * Scale_factor_avg_length); } void set_avg_frequency (double val) { avg_frequency= (ulonglong) (val * Scale_factor_avg_frequency); } bool min_max_values_are_provided() { return !is_null(COLUMN_STAT_MIN_VALUE) && !is_null(COLUMN_STAT_MAX_VALUE); } /* This function checks whether the values for the fields of the statistical tables that were NULL by DEFAULT for a column have changed or not. @retval TRUE: Statistics are not present for a column FALSE: Statisitics are present for a column */ bool no_stat_values_provided() { return (column_stat_nulls == no_values_provided_bitmap()); } }; /* Statistical data on an index prefixes */ class Index_statistics { private: static const uint Scale_factor_avg_frequency= 100000; /* The k-th element of this array contains the ratio N/D multiplied by the scale factor Scale_factor_avg_frequency, where N is the number of index entries without nulls in the first k components, and D is the number of distinct k-component prefixes among them */ ulonglong *avg_frequency; bool stats_were_read; public: void init_avg_frequency(ulonglong *ptr) { avg_frequency= ptr; stats_were_read= false; } void mark_stats_as_read() { stats_were_read= true; } bool has_stats(THD *thd) const { if (TEST_NEW_MODE_FLAG(thd, NEW_MODE_FIX_INDEX_STATS_FOR_ALL_NULLS)) return stats_were_read; else return get_avg_frequency(0) > 0.5; } bool avg_frequency_is_inited() { return avg_frequency != NULL; } double get_avg_frequency(uint i) const { return (double) avg_frequency[i] / Scale_factor_avg_frequency; } void set_avg_frequency(uint i, double val) { avg_frequency[i]= (ulonglong) (val * Scale_factor_avg_frequency); } }; #endif /* SQL_STATISTICS_H */ pfs_thread_provider.h 0000644 00000012670 15156036130 0010754 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_THREAD_PROVIDER_H #define PFS_THREAD_PROVIDER_H /** @file include/pfs_thread_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_THREAD_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_MUTEX_CALL(M) pfs_ ## M ## _v1 #define PSI_RWLOCK_CALL(M) pfs_ ## M ## _v1 #define PSI_COND_CALL(M) pfs_ ## M ## _v1 #define PSI_THREAD_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_mutex_v1(const char *category, PSI_mutex_info_v1 *info, int count); void pfs_register_rwlock_v1(const char *category, PSI_rwlock_info_v1 *info, int count); void pfs_register_cond_v1(const char *category, PSI_cond_info_v1 *info, int count); void pfs_register_thread_v1(const char *category, PSI_thread_info_v1 *info, int count); PSI_mutex* pfs_init_mutex_v1(PSI_mutex_key key, void *identity); void pfs_destroy_mutex_v1(PSI_mutex* mutex); PSI_rwlock* pfs_init_rwlock_v1(PSI_rwlock_key key, void *identity); void pfs_destroy_rwlock_v1(PSI_rwlock* rwlock); PSI_cond* pfs_init_cond_v1(PSI_cond_key key, void *identity); void pfs_destroy_cond_v1(PSI_cond* cond); int pfs_spawn_thread_v1(PSI_thread_key key, pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); PSI_thread* pfs_new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id); void pfs_set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id); void pfs_set_thread_THD_v1(PSI_thread *thread, THD *thd); void pfs_set_thread_os_id_v1(PSI_thread *thread); PSI_thread* pfs_get_thread_v1(void); void pfs_set_thread_user_v1(const char *user, int user_len); void pfs_set_thread_account_v1(const char *user, int user_len, const char *host, int host_len); void pfs_set_thread_db_v1(const char* db, int db_len); void pfs_set_thread_command_v1(int command); void pfs_set_thread_start_time_v1(time_t start_time); void pfs_set_thread_state_v1(const char* state); void pfs_set_connection_type_v1(opaque_vio_type conn_type); void pfs_set_thread_info_v1(const char* info, uint info_len); void pfs_set_thread_v1(PSI_thread* thread); void pfs_set_thread_peer_port_v1(PSI_thread *thread, uint port); void pfs_delete_current_thread_v1(void); void pfs_delete_thread_v1(PSI_thread *thread); PSI_mutex_locker* pfs_start_mutex_wait_v1(PSI_mutex_locker_state *state, PSI_mutex *mutex, PSI_mutex_operation op, const char *src_file, uint src_line); PSI_rwlock_locker* pfs_start_rwlock_rdwait_v1(PSI_rwlock_locker_state *state, PSI_rwlock *rwlock, PSI_rwlock_operation op, const char *src_file, uint src_line); PSI_rwlock_locker* pfs_start_rwlock_wrwait_v1(PSI_rwlock_locker_state *state, PSI_rwlock *rwlock, PSI_rwlock_operation op, const char *src_file, uint src_line); PSI_cond_locker* pfs_start_cond_wait_v1(PSI_cond_locker_state *state, PSI_cond *cond, PSI_mutex *mutex, PSI_cond_operation op, const char *src_file, uint src_line); PSI_table_locker* pfs_start_table_io_wait_v1(PSI_table_locker_state *state, PSI_table *table, PSI_table_io_operation op, uint index, const char *src_file, uint src_line); PSI_table_locker* pfs_start_table_lock_wait_v1(PSI_table_locker_state *state, PSI_table *table, PSI_table_lock_operation op, ulong op_flags, const char *src_file, uint src_line); void pfs_unlock_mutex_v1(PSI_mutex *mutex); void pfs_unlock_rwlock_v1(PSI_rwlock *rwlock); void pfs_signal_cond_v1(PSI_cond* cond); void pfs_broadcast_cond_v1(PSI_cond* cond); void pfs_end_mutex_wait_v1(PSI_mutex_locker* locker, int rc); void pfs_end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc); void pfs_end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc); void pfs_end_cond_wait_v1(PSI_cond_locker* locker, int rc); int pfs_set_thread_connect_attrs_v1(const char *buffer, uint length, const void *from_cs); C_MODE_END #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_THREAD_INTERFACE */ #endif sql_type.h 0000644 00001107223 15156036131 0006564 0 ustar 00 #ifndef SQL_TYPE_H_INCLUDED #define SQL_TYPE_H_INCLUDED /* Copyright (c) 2015 MariaDB Foundation. Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "mysqld.h" #include "lex_string.h" #include "sql_type_timeofday.h" #include "sql_array.h" #include "sql_const.h" #include "sql_time.h" #include "sql_type_string.h" #include "sql_type_real.h" #include "compat56.h" #include "log_event_data_type.h" C_MODE_START #include <ma_dyncol.h> C_MODE_END class Field; class Column_definition; class Column_definition_attributes; class Key_part_spec; class Item; class Item_const; class Item_literal; class Item_param; class Item_cache; class Item_copy; class Item_func_or_sum; class Item_sum; class Item_sum_hybrid; class Item_sum_sum; class Item_sum_avg; class Item_sum_variance; class Item_func_hex; class Item_hybrid_func; class Item_func_min_max; class Item_func_hybrid_field_type; class Item_bool_func2; class Item_bool_rowready_func2; class Item_func_between; class Item_func_in; class Item_func_round; class Item_func_int_val; class Item_func_abs; class Item_func_neg; class Item_func_signed; class Item_func_unsigned; class Item_double_typecast; class Item_float_typecast; class Item_decimal_typecast; class Item_char_typecast; class Item_time_typecast; class Item_date_typecast; class Item_datetime_typecast; class Item_func_plus; class Item_func_minus; class Item_func_mul; class Item_func_div; class Item_func_mod; class Item_type_holder; class cmp_item; class in_vector; class Type_handler_data; class Type_handler_hybrid_field_type; class Sort_param; class Arg_comparator; class Spvar_definition; class st_value; class Protocol; class handler; struct TABLE; struct SORT_FIELD_ATTR; struct SORT_FIELD; class Vers_history_point; class Virtual_column_info; class Conv_source; class ST_FIELD_INFO; class Type_collection; class Create_func; #define my_charset_numeric my_charset_latin1 enum protocol_send_type_t { PROTOCOL_SEND_STRING, PROTOCOL_SEND_FLOAT, PROTOCOL_SEND_DOUBLE, PROTOCOL_SEND_TINY, PROTOCOL_SEND_SHORT, PROTOCOL_SEND_LONG, PROTOCOL_SEND_LONGLONG, PROTOCOL_SEND_DATETIME, PROTOCOL_SEND_DATE, PROTOCOL_SEND_TIME }; enum scalar_comparison_op { SCALAR_CMP_EQ, SCALAR_CMP_EQUAL, SCALAR_CMP_LT, SCALAR_CMP_LE, SCALAR_CMP_GE, SCALAR_CMP_GT }; /* This enum is intentionally defined as "class" to disallow its implicit cast as "bool". This is needed to avoid pre-MDEV-32203 constructs like: if (field->can_optimize_range(...)) do_optimization(); to merge automatically as such - that would change the meaning to the opposite. The pre-MDEV-32203 code must to be changed to: if (field->can_optimize_range(...) == Data_type_compatibility::OK) do_optimization(); */ enum class Data_type_compatibility { OK, INCOMPATIBLE_DATA_TYPE, INCOMPATIBLE_COLLATION }; static inline const LEX_CSTRING scalar_comparison_op_to_lex_cstring(scalar_comparison_op op) { switch (op) { case SCALAR_CMP_EQ: return LEX_CSTRING{STRING_WITH_LEN("=")}; case SCALAR_CMP_EQUAL: return LEX_CSTRING{STRING_WITH_LEN("<=>")}; case SCALAR_CMP_LT: return LEX_CSTRING{STRING_WITH_LEN("<")}; case SCALAR_CMP_LE: return LEX_CSTRING{STRING_WITH_LEN("<=")}; case SCALAR_CMP_GE: return LEX_CSTRING{STRING_WITH_LEN(">=")}; case SCALAR_CMP_GT: return LEX_CSTRING{STRING_WITH_LEN(">")}; } DBUG_ASSERT(0); return LEX_CSTRING{STRING_WITH_LEN("<?>")}; } class Hasher { ulong m_nr1; ulong m_nr2; public: Hasher(): m_nr1(1), m_nr2(4) { } void add_null() { m_nr1^= (m_nr1 << 1) | 1; } void add(CHARSET_INFO *cs, const uchar *str, size_t length) { cs->coll->hash_sort(cs, str, length, &m_nr1, &m_nr2); } void add(CHARSET_INFO *cs, const char *str, size_t length) { add(cs, (const uchar *) str, length); } uint32 finalize() const { return (uint32) m_nr1; } }; enum partition_value_print_mode_t { PARTITION_VALUE_PRINT_MODE_SHOW= 0, PARTITION_VALUE_PRINT_MODE_FRM= 1 }; enum column_definition_type_t { COLUMN_DEFINITION_TABLE_FIELD, COLUMN_DEFINITION_ROUTINE_PARAM, COLUMN_DEFINITION_ROUTINE_LOCAL, COLUMN_DEFINITION_FUNCTION_RETURN }; class Send_field_extended_metadata { LEX_CSTRING m_attr[MARIADB_FIELD_ATTR_LAST+1]; public: Send_field_extended_metadata() { bzero(this, sizeof(*this)); } bool set_data_type_name(const LEX_CSTRING &str) { m_attr[MARIADB_FIELD_ATTR_DATA_TYPE_NAME]= str; return false; } bool set_format_name(const LEX_CSTRING &str) { m_attr[MARIADB_FIELD_ATTR_FORMAT_NAME]= str; return false; } bool has_extended_metadata() const { for (uint i= 0; i <= MARIADB_FIELD_ATTR_LAST; i++) { if (m_attr[i].str) return true; } return false; } const LEX_CSTRING &attr(uint i) const { DBUG_ASSERT(i <= MARIADB_FIELD_ATTR_LAST); return m_attr[i]; } }; class Data_type_statistics { public: uint m_uneven_bit_length; uint m_fixed_string_total_length; uint m_fixed_string_count; uint m_variable_string_total_length; uint m_variable_string_count; uint m_blob_count; Data_type_statistics() :m_uneven_bit_length(0), m_fixed_string_total_length(0), m_fixed_string_count(0), m_variable_string_total_length(0), m_variable_string_count(0), m_blob_count(0) { } uint string_count() const { return m_fixed_string_count + m_variable_string_count; } uint string_total_length() const { return m_fixed_string_total_length + m_variable_string_total_length; } }; class Typelib: public TYPELIB { public: Typelib(uint count, const char **type_names, unsigned int *type_lengths) { TYPELIB::count= count; TYPELIB::name= ""; TYPELIB::type_names= type_names; TYPELIB::type_lengths= type_lengths; } uint max_octet_length() const { uint max_length= 0; for (uint i= 0; i < TYPELIB::count; i++) { const uint length= TYPELIB::type_lengths[i]; set_if_bigger(max_length, length); } return max_length; } }; template<uint sz> class TypelibBuffer: public Typelib { const char *m_type_names[sz + 1]; uint m_type_lengths[sz + 1]; public: TypelibBuffer(uint count, const LEX_CSTRING *values) :Typelib(count, m_type_names, m_type_lengths) { DBUG_ASSERT(sz >= count); for (uint i= 0; i < count; i++) { DBUG_ASSERT(values[i].str != NULL); m_type_names[i]= values[i].str; m_type_lengths[i]= (uint) values[i].length; } m_type_names[sz]= NullS; // End marker m_type_lengths[sz]= 0; // End marker } TypelibBuffer(const LEX_CSTRING *values) :TypelibBuffer(sz, values) { } }; /* A helper class to store column attributes that are inherited by columns (from the table level) when not specified explicitly. */ class Column_derived_attributes { /* Table level CHARACTER SET and COLLATE value: CREATE TABLE t1 (a VARCHAR(1), b CHAR(2)) CHARACTER SET latin1; All character string columns (CHAR, VARCHAR, TEXT) inherit CHARACTER SET from the table level. */ CHARSET_INFO *m_charset; public: explicit Column_derived_attributes(CHARSET_INFO *cs) :m_charset(cs) { } CHARSET_INFO *charset() const { return m_charset; } }; /* A helper class to store requests for changes in multiple column data types during ALTER. */ class Column_bulk_alter_attributes { /* Target CHARACTER SET specification in ALTER .. CONVERT, e.g. ALTER TABLE t1 CONVERT TO CHARACTER SET utf8; All character string columns (CHAR, VARCHAR, TEXT) get converted to the "CONVERT TO CHARACTER SET". */ CHARSET_INFO *m_alter_table_convert_to_charset; public: explicit Column_bulk_alter_attributes(CHARSET_INFO *convert) :m_alter_table_convert_to_charset(convert) { } CHARSET_INFO *alter_table_convert_to_charset() const { return m_alter_table_convert_to_charset; } }; class Native: public Binary_string { public: Native(char *str, size_t len) :Binary_string(str, len) { } }; template<size_t buff_sz> class NativeBuffer: public Native { char buff[buff_sz]; public: NativeBuffer() : Native(buff, buff_sz) { length(0); } }; class String_ptr { protected: String *m_string_ptr; public: String_ptr(String *str) :m_string_ptr(str) { } String_ptr(Item *item, String *buffer); const String *string() const { DBUG_ASSERT(m_string_ptr); return m_string_ptr; } bool is_null() const { return m_string_ptr == NULL; } }; class Ascii_ptr: public String_ptr { public: Ascii_ptr(Item *item, String *buffer); }; template<size_t buff_sz> class String_ptr_and_buffer: public StringBuffer<buff_sz>, public String_ptr { public: String_ptr_and_buffer(Item *item) :String_ptr(item, this) { } }; template<size_t buff_sz> class Ascii_ptr_and_buffer: public StringBuffer<buff_sz>, public Ascii_ptr { public: Ascii_ptr_and_buffer(Item *item) :Ascii_ptr(item, this) { } }; class Dec_ptr { protected: my_decimal *m_ptr; Dec_ptr() = default; public: Dec_ptr(my_decimal *ptr) :m_ptr(ptr) { } bool is_null() const { return m_ptr == NULL; } const my_decimal *ptr() const { return m_ptr; } const my_decimal *ptr_or(const my_decimal *def) const { return m_ptr ? m_ptr : def; } my_decimal *to_decimal(my_decimal *to) const { if (!m_ptr) return NULL; *to= *m_ptr; return to; } double to_double() const { return m_ptr ? m_ptr->to_double() : 0.0; } longlong to_longlong(bool unsigned_flag) { return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; } Longlong_null to_xlonglong_null() { return m_ptr ? Longlong_null(m_ptr->to_xlonglong()) : Longlong_null(); } bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; } String *to_string(String *to) const { return m_ptr ? m_ptr->to_string(to) : NULL; } String *to_string(String *to, uint prec, uint dec, char filler) { return m_ptr ? m_ptr->to_string(to, prec, dec, filler) : NULL; } int to_binary(uchar *bin, int prec, decimal_digits_t scale) const { return (m_ptr ? m_ptr : &decimal_zero)->to_binary(bin, prec, scale); } int cmp(const my_decimal *dec) const { DBUG_ASSERT(m_ptr); DBUG_ASSERT(dec); return m_ptr->cmp(dec); } int cmp(const Dec_ptr &other) const { return cmp(other.m_ptr); } }; // A helper class to handle results of val_decimal(), date_op(), etc. class Dec_ptr_and_buffer: public Dec_ptr { protected: my_decimal m_buffer; public: /* scale is int as it can be negative here */ int round_to(my_decimal *to, int scale, decimal_round_mode mode) { DBUG_ASSERT(m_ptr); return m_ptr->round_to(to, scale, mode); } int round_self(decimal_digits_t scale, decimal_round_mode mode) { return round_to(&m_buffer, scale, mode); } int round_self_if_needed(int scale, decimal_round_mode mode) { if (scale >= m_ptr->frac) return E_DEC_OK; int res= m_ptr->round_to(&m_buffer, scale, mode); m_ptr= &m_buffer; return res; } String *to_string_round(String *to, decimal_digits_t dec) { /* decimal_round() allows from==to So it's save even if m_ptr points to m_buffer before this call: */ return m_ptr ? m_ptr->to_string_round(to, dec, &m_buffer) : NULL; } }; // A helper class to handle val_decimal() results. class VDec: public Dec_ptr_and_buffer { public: VDec(): Dec_ptr_and_buffer() { } VDec(Item *item); void set(Item *a); }; // A helper class to handler decimal_op() results. class VDec_op: public Dec_ptr_and_buffer { public: VDec_op(Item_func_hybrid_field_type *item); }; /* Get and cache val_decimal() values for two items. If the first value appears to be NULL, the second value is not evaluated. */ class VDec2_lazy { public: VDec m_a; VDec m_b; VDec2_lazy(Item *a, Item *b) :m_a(a) { if (!m_a.is_null()) m_b.set(b); } bool has_null() const { return m_a.is_null() || m_b.is_null(); } }; /** Class Sec6 represents a fixed point value with 6 fractional digits. Used e.g. to convert double and my_decimal values to TIME/DATETIME. */ class Sec6 { protected: ulonglong m_sec; // The integer part, between 0 and LONGLONG_MAX ulong m_usec; // The fractional part, between 0 and 999999 bool m_neg; // false if positive, true of negative bool m_truncated; // Indicates if the constructor truncated the value void make_from_decimal(const my_decimal *d, ulong *nanoseconds); void make_from_double(double d, ulong *nanoseconds); void make_from_int(const Longlong_hybrid &nr) { m_neg= nr.neg(); m_sec= nr.abs(); m_usec= 0; m_truncated= false; } void reset() { m_sec= m_usec= m_neg= m_truncated= 0; } Sec6() = default; bool add_nanoseconds(uint nanoseconds) { DBUG_ASSERT(nanoseconds <= 1000000000); if (nanoseconds < 500) return false; m_usec+= (nanoseconds + 500) / 1000; if (m_usec < 1000000) return false; m_usec%= 1000000; return true; } public: explicit Sec6(double nr) { ulong nanoseconds; make_from_double(nr, &nanoseconds); } explicit Sec6(const my_decimal *d) { ulong nanoseconds; make_from_decimal(d, &nanoseconds); } explicit Sec6(const Longlong_hybrid &nr) { make_from_int(nr); } explicit Sec6(longlong nr, bool unsigned_val) { make_from_int(Longlong_hybrid(nr, unsigned_val)); } bool neg() const { return m_neg; } bool truncated() const { return m_truncated; } ulonglong sec() const { return m_sec; } long usec() const { return m_usec; } /** Converts Sec6 to MYSQL_TIME @param thd current thd @param [out] warn conversion warnings will be written here @param [out] ltime converted value will be written here @param fuzzydate conversion flags (TIME_INVALID_DATE, etc) @returns false for success, true for a failure */ bool convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const; protected: bool to_interval_hhmmssff_only(MYSQL_TIME *to, int *warn) const { return number_to_time_only(m_neg, m_sec, m_usec, TIME_MAX_INTERVAL_HOUR, to, warn); } bool to_datetime_or_to_interval_hhmmssff(MYSQL_TIME *to, int *warn) const { /* Convert a number to a time interval. The following formats are understood: - 0 <= x <= 999999995959 - parse as hhhhmmss - 999999995959 < x <= 99991231235959 - parse as YYYYMMDDhhmmss (YYMMDDhhmmss) (YYYYMMDDhhmmss) Note, these formats are NOT understood: - YYMMDD - overlaps with INTERVAL range - YYYYMMDD - overlaps with INTERVAL range - YYMMDDhhmmss - overlaps with INTERVAL range, partially (see TIME_MAX_INTERVAL_HOUR) If we ever need wider intervals, this code switching between full datetime and interval-only should be rewised. */ DBUG_ASSERT(TIME_MAX_INTERVAL_HOUR <= 999999995959); /* (YYMMDDhhmmss) */ if (m_sec > 999999995959ULL && m_sec <= 99991231235959ULL && m_neg == 0) return to_datetime_or_date(to, warn, TIME_INVALID_DATES); if (m_sec / 10000 > TIME_MAX_INTERVAL_HOUR) { *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; return true; } return to_interval_hhmmssff_only(to, warn); } public: // [-][DD]hhhmmss.ff, YYMMDDhhmmss.ff, YYYYMMDDhhmmss.ff bool to_datetime_or_time(MYSQL_TIME *to, int *warn, date_conv_mode_t mode) const { bool rc= m_sec > 9999999 && m_sec <= 99991231235959ULL && !m_neg ? ::number_to_datetime_or_date(m_sec, m_usec, to, ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE), warn) < 0 : ::number_to_time_only(m_neg, m_sec, m_usec, TIME_MAX_HOUR, to, warn); DBUG_ASSERT(*warn || !rc); return rc; } /* Convert a number in formats YYYYMMDDhhmmss.ff or YYMMDDhhmmss.ff to TIMESTAMP'YYYY-MM-DD hh:mm:ss.ff' */ bool to_datetime_or_date(MYSQL_TIME *to, int *warn, date_conv_mode_t flags) const { if (m_neg) { *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; return true; } bool rc= number_to_datetime_or_date(m_sec, m_usec, to, ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn) == -1; DBUG_ASSERT(*warn || !rc); return rc; } // Convert elapsed seconds to TIME bool sec_to_time(MYSQL_TIME *ltime, uint dec) const { set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); ltime->neg= m_neg; if (m_sec > TIME_MAX_VALUE_SECONDS) { // use check_time_range() to set ltime to the max value depending on dec int unused; ltime->hour= TIME_MAX_HOUR + 1; check_time_range(ltime, dec, &unused); return true; } DBUG_ASSERT(usec() <= TIME_MAX_SECOND_PART); ltime->hour= (uint) (m_sec / 3600); ltime->minute= (uint) (m_sec % 3600) / 60; ltime->second= (uint) m_sec % 60; ltime->second_part= m_usec; return false; } Sec6 &trunc(uint dec) { m_usec-= my_time_fraction_remainder(m_usec, dec); return *this; } size_t to_string(char *to, size_t nbytes) const { return m_usec ? my_snprintf(to, nbytes, "%s%llu.%06lu", m_neg ? "-" : "", m_sec, m_usec) : my_snprintf(to, nbytes, "%s%llu", m_neg ? "-" : "", m_sec); } void make_truncated_warning(THD *thd, const char *type_str) const; }; class Sec9: public Sec6 { protected: ulong m_nsec; // Nanoseconds 0..999 void make_from_int(const Longlong_hybrid &nr) { Sec6::make_from_int(nr); m_nsec= 0; } Sec9() = default; public: Sec9(const my_decimal *d) { Sec6::make_from_decimal(d, &m_nsec); } Sec9(double d) { Sec6::make_from_double(d, &m_nsec); } ulong nsec() const { return m_nsec; } Sec9 &trunc(uint dec) { m_nsec= 0; Sec6::trunc(dec); return *this; } Sec9 &round(uint dec); Sec9 &round(uint dec, time_round_mode_t mode) { return mode == TIME_FRAC_TRUNCATE ? trunc(dec) : round(dec); } }; class VSec9: protected Sec9 { bool m_is_null; Sec9& to_sec9() { DBUG_ASSERT(!is_null()); return *this; } public: VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit); bool is_null() const { return m_is_null; } const Sec9& to_const_sec9() const { DBUG_ASSERT(!is_null()); return *this; } bool neg() const { return to_const_sec9().neg(); } bool truncated() const { return to_const_sec9().truncated(); } ulonglong sec() const { return to_const_sec9().sec(); } long usec() const { return to_const_sec9().usec(); } bool sec_to_time(MYSQL_TIME *ltime, uint dec) const { return to_const_sec9().sec_to_time(ltime, dec); } void make_truncated_warning(THD *thd, const char *type_str) const { return to_const_sec9().make_truncated_warning(thd, type_str); } Sec9 &round(uint dec) { return to_sec9().round(dec); } Sec9 &round(uint dec, time_round_mode_t mode) { return to_sec9().round(dec, mode); } }; /* A heler class to perform additive operations between two MYSQL_TIME structures and return the result as a combination of seconds, microseconds and sign. */ class Sec6_add { ulonglong m_sec; // number of seconds ulong m_usec; // number of microseconds bool m_neg; // false if positive, true if negative bool m_error; // false if the value is OK, true otherwise void to_hh24mmssff(MYSQL_TIME *ltime, timestamp_type tstype) const { bzero(ltime, sizeof(*ltime)); ltime->neg= m_neg; calc_time_from_sec(ltime, (ulong) (m_sec % SECONDS_IN_24H), m_usec); ltime->time_type= tstype; } public: /* @param ltime1 - the first value to add (must be a valid DATE,TIME,DATETIME) @param ltime2 - the second value to add (must be a valid TIME) @param sign - the sign of the operation (+1 for addition, -1 for subtraction) */ Sec6_add(const MYSQL_TIME *ltime1, const MYSQL_TIME *ltime2, int sign) { DBUG_ASSERT(sign == -1 || sign == 1); DBUG_ASSERT(!ltime1->neg || ltime1->time_type == MYSQL_TIMESTAMP_TIME); if (!(m_error= (ltime2->time_type != MYSQL_TIMESTAMP_TIME))) { if (ltime1->neg != ltime2->neg) sign= -sign; m_neg= calc_time_diff(ltime1, ltime2, -sign, &m_sec, &m_usec); if (ltime1->neg && (m_sec || m_usec)) m_neg= !m_neg; // Swap sign } } bool to_time(THD *thd, MYSQL_TIME *ltime, uint decimals) const { if (m_error) return true; to_hh24mmssff(ltime, MYSQL_TIMESTAMP_TIME); ltime->hour+= static_cast<unsigned>(to_days_abs() * 24); return adjust_time_range_with_warn(thd, ltime, decimals); } bool to_datetime(MYSQL_TIME *ltime) const { if (m_error || m_neg) return true; to_hh24mmssff(ltime, MYSQL_TIMESTAMP_DATETIME); return get_date_from_daynr(to_days_abs(), <ime->year, <ime->month, <ime->day) || !ltime->day; } long to_days_abs() const { return (long) (m_sec / SECONDS_IN_24H); } }; class Year { protected: uint m_year; bool m_truncated; uint year_precision(const Item *item) const; public: Year(): m_year(0), m_truncated(false) { } Year(longlong value, bool unsigned_flag, uint length); uint year() const { return m_year; } uint to_YYYYMMDD() const { return m_year * 10000; } bool truncated() const { return m_truncated; } }; class Year_null: public Year, public Null_flag { public: Year_null(const Longlong_null &nr, bool unsigned_flag, uint length) :Year(nr.is_null() ? 0 : nr.value(), unsigned_flag, length), Null_flag(nr.is_null()) { } }; class VYear: public Year_null { public: VYear(Item *item); }; class VYear_op: public Year_null { public: VYear_op(Item_func_hybrid_field_type *item); }; class Double_null: public Null_flag { protected: double m_value; public: Double_null(double value, bool is_null) :Null_flag(is_null), m_value(value) { } double value() const { return m_value; } }; class Temporal: protected MYSQL_TIME { public: class Status: public MYSQL_TIME_STATUS { public: Status() { my_time_status_init(this); } }; class Warn: public ErrBuff, public Status { public: void push_conversion_warnings(THD *thd, bool totally_useless_value, date_mode_t mode, timestamp_type tstype, const char *db_name, const char *table_name, const char *name) { const char *typestr= tstype >= 0 ? type_name_by_timestamp_type(tstype) : mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ? "interval" : mode & TIME_TIME_ONLY ? "time" : "datetime"; Temporal::push_conversion_warnings(thd, totally_useless_value, warnings, typestr, db_name, table_name, name, ptr()); } }; class Warn_push: public Warn { THD * const m_thd; const char * const m_db_name; const char * const m_table_name; const char * const m_name; const MYSQL_TIME * const m_ltime; const date_mode_t m_mode; public: Warn_push(THD *thd, const char *db_name, const char *table_name, const char *name, const MYSQL_TIME *ltime, date_mode_t mode) : m_thd(thd), m_db_name(db_name), m_table_name(table_name), m_name(name), m_ltime(ltime), m_mode(mode) { } ~Warn_push() { if (warnings) push_conversion_warnings(m_thd, m_ltime->time_type < 0, m_mode, m_ltime->time_type, m_db_name, m_table_name, m_name); } }; public: static date_conv_mode_t sql_mode_for_dates(THD *thd); static time_round_mode_t default_round_mode(THD *thd); class Options: public date_mode_t { public: explicit Options(date_mode_t flags) :date_mode_t(flags) { } Options(date_conv_mode_t flags, time_round_mode_t round_mode) :date_mode_t(flags | round_mode) { DBUG_ASSERT(ulonglong(flags) <= UINT_MAX32); } Options(date_conv_mode_t flags, THD *thd) :Options(flags, default_round_mode(thd)) { } }; bool is_valid_temporal() const { DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); return time_type != MYSQL_TIMESTAMP_NONE; } static const char *type_name_by_timestamp_type(timestamp_type time_type) { switch (time_type) { case MYSQL_TIMESTAMP_DATE: return "date"; case MYSQL_TIMESTAMP_TIME: return "time"; case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH default: break; } return "datetime"; } static void push_conversion_warnings(THD *thd, bool totally_useless_value, int warn, const char *type_name, const char *db_name, const char *table_name, const char *field_name, const char *value); /* This method is used if the item was not null but convertion to TIME/DATE/DATETIME failed. We return a zero date if allowed, otherwise - null. */ void make_fuzzy_date(int *warn, date_conv_mode_t fuzzydate) { /* In the following scenario: - The caller expected to get a TIME value - Item returned a not NULL string or numeric value - But then conversion from string or number to TIME failed we need to change the default time_type from MYSQL_TIMESTAMP_DATE (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore return TIME'00:00:00' rather than DATE'0000-00-00'. If we don't do this, methods like Item::get_time_with_conversion() will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00' and return TIME'-838:59:59' instead of TIME'00:00:00' as a result. */ timestamp_type tstype= !(fuzzydate & TIME_FUZZY_DATES) ? MYSQL_TIMESTAMP_NONE : fuzzydate & TIME_TIME_ONLY ? MYSQL_TIMESTAMP_TIME : MYSQL_TIMESTAMP_DATETIME; set_zero_time(this, tstype); } protected: my_decimal *bad_to_decimal(my_decimal *to) const; my_decimal *to_decimal(my_decimal *to) const; static double to_double(bool negate, ulonglong num, ulong frac) { double d= static_cast<double>(num) + static_cast<double>(frac) / TIME_SECOND_PART_FACTOR; return negate ? -d : d; } longlong to_packed() const { return ::pack_time(this); } void make_from_out_of_range(int *warn) { *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; time_type= MYSQL_TIMESTAMP_NONE; } void make_from_sec6(THD *thd, MYSQL_TIME_STATUS *st, const Sec6 &nr, date_mode_t mode) { if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode)) make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); } void make_from_sec9(THD *thd, MYSQL_TIME_STATUS *st, const Sec9 &nr, date_mode_t mode) { if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode) || add_nanoseconds(thd, &st->warnings, mode, nr.nsec())) make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); } void make_from_str(THD *thd, Warn *warn, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate); void make_from_double(THD *thd, Warn *warn, double nr, date_mode_t mode) { make_from_sec9(thd, warn, Sec9(nr), mode); if (warn->warnings) warn->set_double(nr); } void make_from_longlong_hybrid(THD *thd, Warn *warn, const Longlong_hybrid &nr, date_mode_t mode) { /* Note: conversion from an integer to TIME can overflow to '838:59:59.999999', so the conversion result can have fractional digits. */ make_from_sec6(thd, warn, Sec6(nr), mode); if (warn->warnings) warn->set_longlong(nr); } void make_from_decimal(THD *thd, Warn *warn, const my_decimal *nr, date_mode_t mode) { make_from_sec9(thd, warn, Sec9(nr), mode); if (warn->warnings) warn->set_decimal(nr); } bool ascii_to_temporal(MYSQL_TIME_STATUS *st, const char *str, size_t length, date_mode_t mode) { if (mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY)) return ascii_to_datetime_or_date_or_interval_DDhhmmssff(st, str, length, mode); if (mode & TIME_TIME_ONLY) return ascii_to_datetime_or_date_or_time(st, str, length, mode); return ascii_to_datetime_or_date(st, str, length, mode); } bool ascii_to_datetime_or_date_or_interval_DDhhmmssff(MYSQL_TIME_STATUS *st, const char *str, size_t length, date_mode_t mode) { longlong cflags= ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE); bool rc= mode & TIME_INTERVAL_DAY ? ::str_to_datetime_or_date_or_interval_day(str, length, this, cflags, st, TIME_MAX_INTERVAL_HOUR, TIME_MAX_INTERVAL_HOUR) : ::str_to_datetime_or_date_or_interval_hhmmssff(str, length, this, cflags, st, TIME_MAX_INTERVAL_HOUR, TIME_MAX_INTERVAL_HOUR); DBUG_ASSERT(!rc || st->warnings); return rc; } bool ascii_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *status, const char *str, size_t length, date_mode_t fuzzydate) { ulonglong cflags= ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE); bool rc= ::str_to_datetime_or_date_or_time(str, length, this, cflags, status, TIME_MAX_HOUR, UINT_MAX32); DBUG_ASSERT(!rc || status->warnings); return rc; } bool ascii_to_datetime_or_date(MYSQL_TIME_STATUS *status, const char *str, size_t length, date_mode_t fuzzydate) { DBUG_ASSERT(bool(fuzzydate & TIME_TIME_ONLY) == false); bool rc= ::str_to_datetime_or_date(str, length, this, ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE), status); DBUG_ASSERT(!rc || status->warnings); return rc; } // Character set aware versions for string conversion routines bool str_to_temporal(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate); bool str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t mode); bool str_to_datetime_or_date(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t mode); bool has_valid_mmssff() const { return minute <= TIME_MAX_MINUTE && second <= TIME_MAX_SECOND && second_part <= TIME_MAX_SECOND_PART; } bool has_zero_YYYYMM() const { return year == 0 && month == 0; } bool has_zero_YYYYMMDD() const { return year == 0 && month == 0 && day == 0; } bool check_date(date_conv_mode_t flags, int *warn) const { return ::check_date(this, flags, warn); } void time_hhmmssff_set_max(uint max_hour) { hour= max_hour; minute= TIME_MAX_MINUTE; second= TIME_MAX_SECOND; second_part= TIME_MAX_SECOND_PART; } /* Add nanoseconds to ssff retval true if seconds overflowed (the caller should increment minutes) false if no overflow happened */ bool add_nanoseconds_ssff(uint nanoseconds) { DBUG_ASSERT(nanoseconds <= 1000000000); if (nanoseconds < 500) return false; second_part+= (nanoseconds + 500) / 1000; if (second_part < 1000000) return false; second_part%= 1000000; if (second < 59) { second++; return false; } second= 0; return true; } /* Add nanoseconds to mmssff retval true if hours overflowed (the caller should increment hours) false if no overflow happened */ bool add_nanoseconds_mmssff(uint nanoseconds) { if (!add_nanoseconds_ssff(nanoseconds)) return false; if (minute < 59) { minute++; return false; } minute= 0; return true; } void time_round_or_set_max(uint dec, int *warn, ulong max_hour, ulong nsec); bool datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec); bool datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec); bool add_nanoseconds_with_round(THD *thd, int *warn, date_conv_mode_t mode, ulong nsec); bool add_nanoseconds(THD *thd, int *warn, date_mode_t mode, ulong nsec) { date_conv_mode_t cmode= date_conv_mode_t(mode); return time_round_mode_t(mode) == TIME_FRAC_ROUND ? add_nanoseconds_with_round(thd, warn, cmode, nsec) : false; } public: static void *operator new(size_t size, MYSQL_TIME *ltime) throw() { DBUG_ASSERT(size == sizeof(MYSQL_TIME)); return ltime; } static void operator delete(void *ptr, MYSQL_TIME *ltime) { } long fraction_remainder(uint dec) const { return my_time_fraction_remainder(second_part, dec); } }; /* Use this class when you need to get a MYSQL_TIME from an Item using Item's native timestamp type, without automatic timestamp type conversion. */ class Temporal_hybrid: public Temporal { public: class Options: public Temporal::Options { public: Options(THD *thd) :Temporal::Options(sql_mode_for_dates(thd), default_round_mode(thd)) { } Options(date_conv_mode_t flags, time_round_mode_t round_mode) :Temporal::Options(flags, round_mode) { } explicit Options(const Temporal::Options &opt) :Temporal::Options(opt) { } explicit Options(date_mode_t fuzzydate) :Temporal::Options(fuzzydate) { } }; public: // Contructors for Item Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate); Temporal_hybrid(THD *thd, Item *item) :Temporal_hybrid(thd, item, Options(thd)) { } Temporal_hybrid(Item *item) :Temporal_hybrid(current_thd, item) { } // Constructors for non-NULL values Temporal_hybrid(THD *thd, Warn *warn, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate) { make_from_str(thd, warn, str, length, cs, fuzzydate); } Temporal_hybrid(THD *thd, Warn *warn, const Longlong_hybrid &nr, date_mode_t fuzzydate) { make_from_longlong_hybrid(thd, warn, nr, fuzzydate); } Temporal_hybrid(THD *thd, Warn *warn, double nr, date_mode_t fuzzydate) { make_from_double(thd, warn, nr, fuzzydate); } // Constructors for nullable values Temporal_hybrid(THD *thd, Warn *warn, const String *str, date_mode_t mode) { if (!str) time_type= MYSQL_TIMESTAMP_NONE; else make_from_str(thd, warn, str->ptr(), str->length(), str->charset(), mode); } Temporal_hybrid(THD *thd, Warn *warn, const Longlong_hybrid_null &nr, date_mode_t fuzzydate) { if (nr.is_null()) time_type= MYSQL_TIMESTAMP_NONE; else make_from_longlong_hybrid(thd, warn, nr, fuzzydate); } Temporal_hybrid(THD *thd, Warn *warn, const Double_null &nr, date_mode_t mode) { if (nr.is_null()) time_type= MYSQL_TIMESTAMP_NONE; else make_from_double(thd, warn, nr.value(), mode); } Temporal_hybrid(THD *thd, Warn *warn, const my_decimal *nr, date_mode_t mode) { if (!nr) time_type= MYSQL_TIMESTAMP_NONE; else make_from_decimal(thd, warn, nr, mode); } // End of constuctors bool copy_valid_value_to_mysql_time(MYSQL_TIME *ltime) const { DBUG_ASSERT(is_valid_temporal()); *ltime= *this; return false; } longlong to_longlong() const { if (!is_valid_temporal()) return 0; ulonglong v= TIME_to_ulonglong(this); return neg ? -(longlong) v : (longlong) v; } double to_double() const { return is_valid_temporal() ? TIME_to_double(this) : 0; } my_decimal *to_decimal(my_decimal *to) { return is_valid_temporal() ? Temporal::to_decimal(to) : bad_to_decimal(to); } String *to_string(String *str, uint dec) const { if (!is_valid_temporal()) return NULL; str->set_charset(&my_charset_numeric); if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) str->length(my_TIME_to_str(this, const_cast<char*>(str->ptr()), dec)); return str; } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_temporal()); return this; } }; /* This class resembles the SQL standard <extract source>, used in extract expressions, e.g: EXTRACT(DAY FROM dt) <extract expression> ::= EXTRACT <left paren> <extract field> FROM <extract source> <right paren> <extract source> ::= <datetime value expression> | <interval value expression> */ class Extract_source: public Temporal_hybrid { /* Convert a TIME value to DAY-TIME interval, e.g. for extraction: EXTRACT(DAY FROM x), EXTRACT(HOUR FROM x), etc. Moves full days from ltime->hour to ltime->day. */ void time_to_daytime_interval() { DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_TIME); DBUG_ASSERT(has_zero_YYYYMMDD()); MYSQL_TIME::day= MYSQL_TIME::hour / 24; MYSQL_TIME::hour%= 24; } bool is_valid_extract_source_slow() const { return is_valid_temporal() && MYSQL_TIME::hour < 24 && (has_zero_YYYYMM() || time_type != MYSQL_TIMESTAMP_TIME); } bool is_valid_value_slow() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_extract_source_slow(); } public: Extract_source(THD *thd, Item *item, date_mode_t mode) :Temporal_hybrid(thd, item, mode) { if (MYSQL_TIME::time_type == MYSQL_TIMESTAMP_TIME) time_to_daytime_interval(); DBUG_ASSERT(is_valid_value_slow()); } inline const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_extract_source_slow()); return this; } bool is_valid_extract_source() const { return is_valid_temporal(); } int sign() const { return get_mysql_time()->neg ? -1 : 1; } uint year() const { return get_mysql_time()->year; } uint month() const { return get_mysql_time()->month; } int day() const { return (int) get_mysql_time()->day * sign(); } int hour() const { return (int) get_mysql_time()->hour * sign(); } int minute() const { return (int) get_mysql_time()->minute * sign(); } int second() const { return (int) get_mysql_time()->second * sign(); } int microsecond() const { return (int) get_mysql_time()->second_part * sign(); } uint year_month() const { return year() * 100 + month(); } uint quarter() const { return (month() + 2)/3; } uint week(THD *thd) const; longlong second_microsecond() const { return (second() * 1000000LL + microsecond()); } // DAY TO XXX longlong day_hour() const { return (longlong) day() * 100LL + hour(); } longlong day_minute() const { return day_hour() * 100LL + minute(); } longlong day_second() const { return day_minute() * 100LL + second(); } longlong day_microsecond() const { return day_second() * 1000000LL + microsecond(); } // HOUR TO XXX int hour_minute() const { return hour() * 100 + minute(); } int hour_second() const { return hour_minute() * 100 + second(); } longlong hour_microsecond() const { return hour_second() * 1000000LL + microsecond(); } // MINUTE TO XXX int minute_second() const { return minute() * 100 + second(); } longlong minute_microsecond() const { return minute_second() * 1000000LL + microsecond(); } }; /* This class is used for the "time_interval" argument of these SQL functions: TIMESTAMP(tm,time_interval) ADDTIME(tm,time_interval) Features: - DATE and DATETIME formats are treated as errors - Preserves hours for TIME format as is, without limiting to TIME_MAX_HOUR */ class Interval_DDhhmmssff: public Temporal { static const LEX_CSTRING m_type_name; bool str_to_DDhhmmssff(MYSQL_TIME_STATUS *status, const char *str, size_t length, CHARSET_INFO *cs, ulong max_hour); void push_warning_wrong_or_truncated_value(THD *thd, const ErrConv &str, int warnings); bool is_valid_interval_DDhhmmssff_slow() const { return time_type == MYSQL_TIMESTAMP_TIME && has_zero_YYYYMMDD() && has_valid_mmssff(); } bool is_valid_value_slow() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_interval_DDhhmmssff_slow(); } public: // Get fractional second precision from an Item static decimal_digits_t fsp(THD *thd, Item *item); /* Maximum useful HOUR value: TIMESTAMP'0001-01-01 00:00:00' + '87649415:59:59' = '9999-12-31 23:59:59' This gives maximum possible interval values: - '87649415:59:59.999999' (in 'hh:mm:ss.ff' format) - '3652058 23:59:59.999999' (in 'DD hh:mm:ss.ff' format) */ static uint max_useful_hour() { return TIME_MAX_INTERVAL_HOUR; } static uint max_int_part_char_length() { // e.g. '+3652058 23:59:59' return 1/*sign*/ + TIME_MAX_INTERVAL_DAY_CHAR_LENGTH + 1 + 8/*hh:mm:ss*/; } static uint max_char_length(uint fsp) { DBUG_ASSERT(fsp <= TIME_SECOND_PART_DIGITS); return max_int_part_char_length() + (fsp ? 1 : 0) + fsp; } public: Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings, Item *item, ulong max_hour, time_round_mode_t mode, uint dec); Interval_DDhhmmssff(THD *thd, Item *item, uint dec) { Status st; new(this) Interval_DDhhmmssff(thd, &st, true, item, max_useful_hour(), default_round_mode(thd), dec); } Interval_DDhhmmssff(THD *thd, Item *item) :Interval_DDhhmmssff(thd, item, TIME_SECOND_PART_DIGITS) { } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_interval_DDhhmmssff_slow()); return this; } bool is_valid_interval_DDhhmmssff() const { return time_type == MYSQL_TIMESTAMP_TIME; } bool is_valid_value() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_interval_DDhhmmssff(); } String *to_string(String *str, uint dec) const { if (!is_valid_interval_DDhhmmssff()) return NULL; str->set_charset(&my_charset_numeric); if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) str->length(my_interval_DDhhmmssff_to_str(this, const_cast<char*>(str->ptr()), dec)); return str; } }; class Schema; /** Class Time is designed to store valid TIME values. 1. Valid value: a. MYSQL_TIMESTAMP_TIME - a valid TIME within the supported TIME range b. MYSQL_TIMESTAMP_NONE - an undefined value 2. Invalid value (internally only): a. MYSQL_TIMESTAMP_TIME outside of the supported TIME range a. MYSQL_TIMESTAMP_{DATE|DATETIME|ERROR} Temporarily Time is allowed to have an invalid value, but only internally, during initialization time. All constructors and modification methods must leave the Time value as described above (see "Valid values"). Time derives from MYSQL_TIME privately to make sure it is accessed externally only in the valid state. */ class Time: public Temporal { static uint binary_length_to_precision(uint length); public: enum datetime_to_time_mode_t { DATETIME_TO_TIME_DISALLOW, DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS, DATETIME_TO_TIME_YYYYMMDD_TRUNCATE, DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY, DATETIME_TO_TIME_MINUS_CURRENT_DATE }; class Options: public Temporal::Options { datetime_to_time_mode_t m_datetime_to_time_mode; public: Options(THD *thd) :Temporal::Options(default_flags_for_get_date(), default_round_mode(thd)), m_datetime_to_time_mode(default_datetime_to_time_mode()) { } Options(date_conv_mode_t flags, THD *thd) :Temporal::Options(flags, default_round_mode(thd)), m_datetime_to_time_mode(default_datetime_to_time_mode()) { } Options(date_conv_mode_t flags, THD *thd, datetime_to_time_mode_t dtmode) :Temporal::Options(flags, default_round_mode(thd)), m_datetime_to_time_mode(dtmode) { } Options(date_conv_mode_t fuzzydate, time_round_mode_t round_mode, datetime_to_time_mode_t datetime_to_time_mode) :Temporal::Options(fuzzydate, round_mode), m_datetime_to_time_mode(datetime_to_time_mode) { } datetime_to_time_mode_t datetime_to_time_mode() const { return m_datetime_to_time_mode; } static datetime_to_time_mode_t default_datetime_to_time_mode() { return DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS; } }; /* CAST(AS TIME) historically does not mix days to hours. This is different comparing to how implicit conversion in Field::store_time_dec() works (e.g. on INSERT). */ class Options_for_cast: public Options { public: Options_for_cast(THD *thd) :Options(default_flags_for_get_date(), default_round_mode(thd), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) { } Options_for_cast(date_mode_t mode, THD *thd) :Options(default_flags_for_get_date() | (mode & TIME_FUZZY_DATES), default_round_mode(thd), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) { } }; class Options_for_round: public Options { public: Options_for_round(time_round_mode_t round_mode= TIME_FRAC_TRUNCATE) :Options(Time::default_flags_for_get_date(), round_mode, Time::DATETIME_TO_TIME_DISALLOW) { } }; class Options_cmp: public Options { public: Options_cmp(THD *thd) :Options(comparison_flags_for_get_date(), thd) { } Options_cmp(THD *thd, datetime_to_time_mode_t dtmode) :Options(comparison_flags_for_get_date(), default_round_mode(thd), dtmode) { } }; private: bool is_valid_value_slow() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_time_slow(); } bool is_valid_time_slow() const { return time_type == MYSQL_TIMESTAMP_TIME && has_zero_YYYYMMDD() && has_valid_mmssff(); } void hhmmssff_copy(const MYSQL_TIME *from) { hour= from->hour; minute= from->minute; second= from->second; second_part= from->second_part; } void datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(int *warn, uint from_year, uint from_month, uint from_day) { if (from_year != 0 || from_month != 0) *warn|= MYSQL_TIME_NOTE_TRUNCATED; else hour+= from_day * 24; } /* The result is calculated effectively similar to: TIMEDIFF(dt, CAST(CURRENT_DATE AS DATETIME)) If the difference does not fit to the supported TIME range, it's truncated. */ void datetime_to_time_minus_current_date(THD *thd) { MYSQL_TIME current_date, tmp; set_current_date(thd, ¤t_date); calc_time_diff(this, ¤t_date, 1, &tmp, date_mode_t(0)); static_cast<MYSQL_TIME*>(this)[0]= tmp; int warnings= 0; (void) check_time_range(this, TIME_SECOND_PART_DIGITS, &warnings); DBUG_ASSERT(is_valid_time()); } /* Convert a valid DATE or DATETIME to TIME. Before this call, "this" must be a valid DATE or DATETIME value, e.g. returned from Item::get_date(), str_to_xxx(), number_to_xxx(). After this call, "this" is a valid TIME value. */ void valid_datetime_to_valid_time(THD *thd, int *warn, const Options opt) { DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE || time_type == MYSQL_TIMESTAMP_DATETIME); /* We're dealing with a DATE or DATETIME returned from str_to_xxx(), number_to_xxx() or unpack_time(). Do some asserts to make sure the result hour value after mixing days to hours does not go out of the valid TIME range. The maximum hour value after mixing days will be 31*24+23=767, which is within the supported TIME range. Thus no adjust_time_range_or_invalidate() is needed here. */ DBUG_ASSERT(day < 32); DBUG_ASSERT(hour < 24); if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_MINUS_CURRENT_DATE) { datetime_to_time_minus_current_date(thd); } else { if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(warn, year, month, day); year= month= day= 0; time_type= MYSQL_TIMESTAMP_TIME; } DBUG_ASSERT(is_valid_time_slow()); } /** Convert valid DATE/DATETIME to valid TIME if needed. This method is called after Item::get_date(), str_to_xxx(), number_to_xxx(). which can return only valid TIME/DATE/DATETIME values. Before this call, "this" is: - either a valid TIME/DATE/DATETIME value (within the supported range for the corresponding type), - or MYSQL_TIMESTAMP_NONE After this call, "this" is: - either a valid TIME (within the supported TIME range), - or MYSQL_TIMESTAMP_NONE */ void valid_MYSQL_TIME_to_valid_value(THD *thd, int *warn, const Options opt) { switch (time_type) { case MYSQL_TIMESTAMP_DATE: case MYSQL_TIMESTAMP_DATETIME: if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY && (year || month || day)) make_from_out_of_range(warn); else if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_DISALLOW) make_from_out_of_range(warn); else valid_datetime_to_valid_time(thd, warn, opt); break; case MYSQL_TIMESTAMP_NONE: break; case MYSQL_TIMESTAMP_ERROR: set_zero_time(this, MYSQL_TIMESTAMP_TIME); break; case MYSQL_TIMESTAMP_TIME: DBUG_ASSERT(is_valid_time_slow()); break; } } /* This method is called after number_to_xxx() and str_to_xxx(), which can return DATE or DATETIME values. Convert to TIME if needed. We trust that xxx_to_time() returns a valid TIME/DATE/DATETIME value, so here we need to do only simple validation. */ void xxx_to_time_result_to_valid_value(THD *thd, int *warn, const Options opt) { // str_to_xxx(), number_to_xxx() never return MYSQL_TIMESTAMP_ERROR DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); valid_MYSQL_TIME_to_valid_value(thd, warn, opt); } void adjust_time_range_or_invalidate(int *warn) { if (check_time_range(this, TIME_SECOND_PART_DIGITS, warn)) time_type= MYSQL_TIMESTAMP_NONE; DBUG_ASSERT(is_valid_value_slow()); } public: void round_or_set_max(uint dec, int *warn, ulong nsec); private: void round_or_set_max(uint dec, int *warn); /* All make_from_xxx() methods initialize *warn. The old value gets lost. */ void make_from_datetime_move_day_to_hour(int *warn, const MYSQL_TIME *from); void make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from, long curdays); void make_from_time(int *warn, const MYSQL_TIME *from); void make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays); void make_from_item(THD *thd, int *warn, Item *item, const Options opt); public: /* All constructors that accept an "int *warn" parameter initialize *warn. The old value gets lost. */ Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second); Time() { time_type= MYSQL_TIMESTAMP_NONE; } Time(const Native &native); Time(THD *thd, const MYSQL_TIME *ltime, const Options opt) { *(static_cast<MYSQL_TIME*>(this))= *ltime; DBUG_ASSERT(is_valid_temporal()); int warn= 0; valid_MYSQL_TIME_to_valid_value(thd, &warn, opt); } Time(Item *item) :Time(current_thd, item) { } Time(THD *thd, Item *item, const Options opt) { int warn; make_from_item(thd, &warn, item, opt); } Time(THD *thd, Item *item) :Time(thd, item, Options(thd)) { } Time(int *warn, const MYSQL_TIME *from, long curdays); Time(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const Options opt) { if (str_to_datetime_or_date_or_time(thd, status, str, len, cs, opt)) time_type= MYSQL_TIMESTAMP_NONE; // The below call will optionally add notes to already collected warnings: else xxx_to_time_result_to_valid_value(thd, &status->warnings, opt); } protected: Time(THD *thd, int *warn, const Sec6 &nr, const Options opt) { if (nr.to_datetime_or_time(this, warn, TIME_INVALID_DATES)) time_type= MYSQL_TIMESTAMP_NONE; xxx_to_time_result_to_valid_value(thd, warn, opt); } Time(THD *thd, int *warn, const Sec9 &nr, const Options &opt) :Time(thd, warn, static_cast<Sec6>(nr), opt) { if (is_valid_time() && time_round_mode_t(opt) == TIME_FRAC_ROUND) round_or_set_max(6, warn, nr.nsec()); } public: Time(THD *thd, int *warn, const Longlong_hybrid &nr, const Options &opt) :Time(thd, warn, Sec6(nr), opt) { } Time(THD *thd, int *warn, double nr, const Options &opt) :Time(thd, warn, Sec9(nr), opt) { } Time(THD *thd, int *warn, const my_decimal *d, const Options &opt) :Time(thd, warn, Sec9(d), opt) { } Time(THD *thd, Item *item, const Options opt, uint dec) :Time(thd, item, opt) { round(dec, time_round_mode_t(opt)); } Time(int *warn, const MYSQL_TIME *from, long curdays, const Time::Options &opt, uint dec) :Time(warn, from, curdays) { round(dec, time_round_mode_t(opt), warn); } Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec9 &second, time_round_mode_t mode, uint dec) :Time(warn, neg, hour, minute, second) { DBUG_ASSERT(is_valid_time()); if ((ulonglong) mode == (ulonglong) TIME_FRAC_ROUND) round_or_set_max(6, warn, second.nsec()); round(dec, mode, warn); } Time(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const Options &opt, uint dec) :Time(thd, status, str, len, cs, opt) { round(dec, time_round_mode_t(opt), &status->warnings); } Time(THD *thd, int *warn, const Longlong_hybrid &nr, const Options &opt, uint dec) :Time(thd, warn, nr, opt) { /* Decimal digit truncation is needed here in case if nr was out of the supported TIME range, so "this" was set to '838:59:59.999999'. We always do truncation (not rounding) here, independently from "opt". */ trunc(dec); } Time(THD *thd, int *warn, double nr, const Options &opt, uint dec) :Time(thd, warn, nr, opt) { round(dec, time_round_mode_t(opt), warn); } Time(THD *thd, int *warn, const my_decimal *d, const Options &opt, uint dec) :Time(thd, warn, d, opt) { round(dec, time_round_mode_t(opt), warn); } static date_conv_mode_t default_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES; } static date_conv_mode_t comparison_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES | TIME_FUZZY_DATES; } bool is_valid_time() const { DBUG_ASSERT(is_valid_value_slow()); return time_type == MYSQL_TIMESTAMP_TIME; } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_time_slow()); return this; } bool copy_to_mysql_time(MYSQL_TIME *ltime) const { if (time_type == MYSQL_TIMESTAMP_NONE) { ltime->time_type= MYSQL_TIMESTAMP_NONE; return true; } DBUG_ASSERT(is_valid_time_slow()); *ltime= *this; return false; } int cmp(const Time *other) const { DBUG_ASSERT(is_valid_time_slow()); DBUG_ASSERT(other->is_valid_time_slow()); longlong p0= to_packed(); longlong p1= other->to_packed(); if (p0 < p1) return -1; if (p0 > p1) return 1; return 0; } longlong to_seconds_abs() const { DBUG_ASSERT(is_valid_time_slow()); return hour * 3600L + minute * 60 + second; } longlong to_seconds() const { return neg ? -to_seconds_abs() : to_seconds_abs(); } bool to_bool() const { return is_valid_time() && (TIME_to_ulonglong_time(this) != 0 || second_part != 0); } longlong to_longlong() const { if (!is_valid_time()) return 0; ulonglong v= TIME_to_ulonglong_time(this); return neg ? -(longlong) v : (longlong) v; } double to_double() const { return !is_valid_time() ? 0 : Temporal::to_double(neg, TIME_to_ulonglong_time(this), second_part); } bool to_native(Native *to, uint decimals) const; String *to_string(String *str, uint dec) const { if (!is_valid_time()) return NULL; str->set_charset(&my_charset_numeric); if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) str->length(my_time_to_str(this, const_cast<char*>(str->ptr()), dec)); return str; } my_decimal *to_decimal(my_decimal *to) { return is_valid_time() ? Temporal::to_decimal(to) : bad_to_decimal(to); } longlong to_packed() const { return is_valid_time() ? Temporal::to_packed() : 0; } longlong valid_time_to_packed() const { DBUG_ASSERT(is_valid_time_slow()); return Temporal::to_packed(); } long fraction_remainder(uint dec) const { DBUG_ASSERT(is_valid_time()); return Temporal::fraction_remainder(dec); } Time &trunc(uint dec) { if (is_valid_time()) my_time_trunc(this, dec); DBUG_ASSERT(is_valid_value_slow()); return *this; } Time &ceiling(int *warn) { if (is_valid_time()) { if (neg) my_time_trunc(this, 0); else if (second_part) round_or_set_max(0, warn, 999999999); } DBUG_ASSERT(is_valid_value_slow()); return *this; } Time &ceiling() { int warn= 0; return ceiling(&warn); } Time &floor(int *warn) { if (is_valid_time()) { if (!neg) my_time_trunc(this, 0); else if (second_part) round_or_set_max(0, warn, 999999999); } DBUG_ASSERT(is_valid_value_slow()); return *this; } Time &floor() { int warn= 0; return floor(&warn); } Time &round(uint dec, int *warn) { if (is_valid_time()) round_or_set_max(dec, warn); DBUG_ASSERT(is_valid_value_slow()); return *this; } Time &round(uint dec, time_round_mode_t mode, int *warn) { switch (mode.mode()) { case time_round_mode_t::FRAC_NONE: DBUG_ASSERT(fraction_remainder(dec) == 0); return trunc(dec); case time_round_mode_t::FRAC_TRUNCATE: return trunc(dec); case time_round_mode_t::FRAC_ROUND: return round(dec, warn); } return *this; } Time &round(uint dec, time_round_mode_t mode) { int warn= 0; return round(dec, mode, &warn); } }; /** Class Temporal_with_date is designed to store valid DATE or DATETIME values. See also class Time. 1. Valid value: a. MYSQL_TIMESTAMP_{DATE|DATETIME} - a valid DATE or DATETIME value b. MYSQL_TIMESTAMP_NONE - an undefined value 2. Invalid value (internally only): a. MYSQL_TIMESTAMP_{DATE|DATETIME} - a DATE or DATETIME value, but with MYSQL_TIME members outside of the valid/supported range b. MYSQL_TIMESTAMP_TIME - a TIME value c. MYSQL_TIMESTAMP_ERROR - error Temporarily is allowed to have an invalid value, but only internally, during initialization time. All constructors and modification methods must leave the value as described above (see "Valid value"). Derives from MYSQL_TIME using "protected" inheritance to make sure it is accessed externally only in the valid state. */ class Temporal_with_date: public Temporal { public: class Options: public Temporal::Options { public: Options(date_conv_mode_t fuzzydate, time_round_mode_t mode): Temporal::Options(fuzzydate, mode) {} explicit Options(const Temporal::Options &opt) :Temporal::Options(opt) { } explicit Options(date_mode_t mode) :Temporal::Options(mode) { } }; protected: void check_date_or_invalidate(int *warn, date_conv_mode_t flags); void make_from_item(THD *thd, Item *item, date_mode_t flags); ulong daynr() const { return (ulong) ::calc_daynr((uint) year, (uint) month, (uint) day); } int weekday(bool sunday_first_day_of_week) const { return ::calc_weekday(daynr(), sunday_first_day_of_week); } ulong dayofyear() const { return (ulong) (daynr() - ::calc_daynr(year, 1, 1) + 1); } uint quarter() const { return (month + 2) / 3; } uint week(uint week_behaviour) const { uint year; return calc_week(this, week_behaviour, &year); } uint yearweek(uint week_behaviour) const { uint year; uint week= calc_week(this, week_behaviour, &year); return week + year * 100; } public: Temporal_with_date() { time_type= MYSQL_TIMESTAMP_NONE; } Temporal_with_date(THD *thd, Item *item, date_mode_t fuzzydate) { make_from_item(thd, item, fuzzydate); } Temporal_with_date(int *warn, const Sec6 &nr, date_mode_t flags) { DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); if (nr.to_datetime_or_date(this, warn, date_conv_mode_t(flags))) time_type= MYSQL_TIMESTAMP_NONE; } Temporal_with_date(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, date_mode_t flags) { DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); if (str_to_datetime_or_date(thd, status, str, len, cs, flags)) time_type= MYSQL_TIMESTAMP_NONE; } public: bool check_date_with_warn(THD *thd, date_conv_mode_t flags) { return ::check_date_with_warn(thd, this, flags, MYSQL_TIMESTAMP_ERROR); } bool check_date_with_warn(THD *thd) { return ::check_date_with_warn(thd, this, Temporal::sql_mode_for_dates(thd), MYSQL_TIMESTAMP_ERROR); } static date_conv_mode_t comparison_flags_for_get_date() { return TIME_INVALID_DATES | TIME_FUZZY_DATES; } }; /** Class Date is designed to store valid DATE values. All constructors and modification methods leave instances of this class in one of the following valid states: a. MYSQL_TIMESTAMP_DATE - a DATE with all MYSQL_TIME members properly set b. MYSQL_TIMESTAMP_NONE - an undefined value. Other MYSQL_TIMESTAMP_XXX are not possible. MYSQL_TIMESTAMP_DATE with MYSQL_TIME members improperly set is not possible. */ class Date: public Temporal_with_date { bool is_valid_value_slow() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_date_slow(); } bool is_valid_date_slow() const { DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE); return !check_datetime_range(this); } public: class Options: public Temporal_with_date::Options { public: explicit Options(date_conv_mode_t fuzzydate) :Temporal_with_date::Options(fuzzydate, TIME_FRAC_TRUNCATE) { } Options(THD *thd, time_round_mode_t mode) :Temporal_with_date::Options(sql_mode_for_dates(thd), mode) { } explicit Options(THD *thd) :Temporal_with_date::Options(sql_mode_for_dates(thd), TIME_FRAC_TRUNCATE) { } explicit Options(date_mode_t fuzzydate) :Temporal_with_date::Options(fuzzydate) { } }; public: Date(Item *item, date_mode_t fuzzydate) :Date(current_thd, item, fuzzydate) { } Date(THD *thd, Item *item, date_mode_t fuzzydate) :Temporal_with_date(thd, item, fuzzydate) { if (time_type == MYSQL_TIMESTAMP_DATETIME) datetime_to_date(this); DBUG_ASSERT(is_valid_value_slow()); } Date(THD *thd, Item *item, date_conv_mode_t fuzzydate) :Date(thd, item, Options(fuzzydate)) { } Date(THD *thd, Item *item) :Temporal_with_date(Date(thd, item, Options(thd, TIME_FRAC_TRUNCATE))) { } Date(Item *item) :Temporal_with_date(Date(current_thd, item)) { } Date(const Temporal_with_date *d) :Temporal_with_date(*d) { datetime_to_date(this); DBUG_ASSERT(is_valid_date_slow()); } explicit Date(const Temporal_hybrid *from) { from->copy_valid_value_to_mysql_time(this); DBUG_ASSERT(is_valid_date_slow()); } bool is_valid_date() const { DBUG_ASSERT(is_valid_value_slow()); return time_type == MYSQL_TIMESTAMP_DATE; } bool check_date(date_conv_mode_t flags, int *warnings) const { DBUG_ASSERT(is_valid_date_slow()); return ::check_date(this, (year || month || day), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warnings); } bool check_date(THD *thd, int *warnings) const { return check_date(Temporal::sql_mode_for_dates(thd), warnings); } bool check_date(date_conv_mode_t flags) const { int dummy; /* unused */ return check_date(flags, &dummy); } bool check_date(THD *thd) const { int dummy; return check_date(Temporal::sql_mode_for_dates(thd), &dummy); } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_date_slow()); return this; } bool copy_to_mysql_time(MYSQL_TIME *ltime) const { if (time_type == MYSQL_TIMESTAMP_NONE) { ltime->time_type= MYSQL_TIMESTAMP_NONE; return true; } DBUG_ASSERT(is_valid_date_slow()); *ltime= *this; return false; } ulong daynr() const { DBUG_ASSERT(is_valid_date_slow()); return Temporal_with_date::daynr(); } ulong dayofyear() const { DBUG_ASSERT(is_valid_date_slow()); return Temporal_with_date::dayofyear(); } uint quarter() const { DBUG_ASSERT(is_valid_date_slow()); return Temporal_with_date::quarter(); } uint week(uint week_behaviour) const { DBUG_ASSERT(is_valid_date_slow()); return Temporal_with_date::week(week_behaviour); } uint yearweek(uint week_behaviour) const { DBUG_ASSERT(is_valid_date_slow()); return Temporal_with_date::yearweek(week_behaviour); } longlong valid_date_to_packed() const { DBUG_ASSERT(is_valid_date_slow()); return Temporal::to_packed(); } bool to_bool() const { return to_longlong() != 0; } longlong to_longlong() const { return is_valid_date() ? (longlong) TIME_to_ulonglong_date(this) : 0LL; } double to_double() const { return (double) to_longlong(); } String *to_string(String *str) const { if (!is_valid_date()) return NULL; str->set_charset(&my_charset_numeric); if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) str->length(my_date_to_str(this, const_cast<char*>(str->ptr()))); return str; } my_decimal *to_decimal(my_decimal *to) { return is_valid_date() ? Temporal::to_decimal(to) : bad_to_decimal(to); } }; /** Class Datetime is designed to store valid DATETIME values. All constructors and modification methods leave instances of this class in one of the following valid states: a. MYSQL_TIMESTAMP_DATETIME - a DATETIME with all members properly set b. MYSQL_TIMESTAMP_NONE - an undefined value. Other MYSQL_TIMESTAMP_XXX are not possible. MYSQL_TIMESTAMP_DATETIME with MYSQL_TIME members improperly set is not possible. */ class Datetime: public Temporal_with_date { bool is_valid_value_slow() const { return time_type == MYSQL_TIMESTAMP_NONE || is_valid_datetime_slow(); } bool is_valid_datetime_slow() const { DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME); return !check_datetime_range(this); } bool add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) { DBUG_ASSERT(is_valid_datetime_slow()); bool rc= Temporal::datetime_add_nanoseconds_or_invalidate(thd, warn, nsec); DBUG_ASSERT(is_valid_value_slow()); return rc; } void date_to_datetime_if_needed() { if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime(this); } void make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, date_conv_mode_t flags); void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_conv_mode_t flags); bool round_or_invalidate(THD *thd, uint dec, int *warn); bool round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec) { DBUG_ASSERT(is_valid_datetime_slow()); bool rc= Temporal::datetime_round_or_invalidate(thd, dec, warn, nsec); DBUG_ASSERT(is_valid_value_slow()); return rc; } public: class Options: public Temporal_with_date::Options { public: Options(date_conv_mode_t fuzzydate, time_round_mode_t nanosecond_rounding) :Temporal_with_date::Options(fuzzydate, nanosecond_rounding) { } Options(THD *thd) :Temporal_with_date::Options(sql_mode_for_dates(thd), default_round_mode(thd)) { } Options(THD *thd, time_round_mode_t rounding_mode) :Temporal_with_date::Options(sql_mode_for_dates(thd), rounding_mode) { } Options(date_conv_mode_t fuzzydate, THD *thd) :Temporal_with_date::Options(fuzzydate, default_round_mode(thd)) { } }; class Options_cmp: public Options { public: Options_cmp(THD *thd) :Options(comparison_flags_for_get_date(), thd) { } }; static Datetime zero() { int warn; static Longlong_hybrid nr(0, false); return Datetime(&warn, nr, date_mode_t(0)); } public: Datetime() // NULL value :Temporal_with_date() { } Datetime(THD *thd, Item *item, date_mode_t fuzzydate) :Temporal_with_date(thd, item, fuzzydate) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } Datetime(THD *thd, Item *item) :Temporal_with_date(Datetime(thd, item, Options(thd))) { } Datetime(Item *item) :Datetime(current_thd, item) { } Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_conv_mode_t flags); Datetime(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const date_mode_t fuzzydate) :Temporal_with_date(thd, status, str, len, cs, fuzzydate) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } protected: Datetime(int *warn, const Sec6 &nr, date_mode_t flags) :Temporal_with_date(warn, nr, flags) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } Datetime(THD *thd, int *warn, const Sec9 &nr, date_mode_t fuzzydate) :Datetime(warn, static_cast<const Sec6>(nr), fuzzydate) { if (is_valid_datetime() && time_round_mode_t(fuzzydate) == TIME_FRAC_ROUND) round_or_invalidate(thd, 6, warn, nr.nsec()); DBUG_ASSERT(is_valid_value_slow()); } public: Datetime(int *warn, const Longlong_hybrid &nr, date_mode_t mode) :Datetime(warn, Sec6(nr), mode) { } Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate) :Datetime(thd, warn, Sec9(nr), fuzzydate) { } Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate) :Datetime(thd, warn, Sec9(d), fuzzydate) { } Datetime(THD *thd, const timeval &tv); Datetime(THD *thd, Item *item, date_mode_t fuzzydate, uint dec) :Datetime(thd, item, fuzzydate) { int warn= 0; round(thd, dec, time_round_mode_t(fuzzydate), &warn); } Datetime(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, date_mode_t fuzzydate, uint dec) :Datetime(thd, status, str, len, cs, fuzzydate) { round(thd, dec, time_round_mode_t(fuzzydate), &status->warnings); } Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate, uint dec) :Datetime(thd, warn, nr, fuzzydate) { round(thd, dec, time_round_mode_t(fuzzydate), warn); } Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate, uint dec) :Datetime(thd, warn, d, fuzzydate) { round(thd, dec, time_round_mode_t(fuzzydate), warn); } Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_mode_t fuzzydate, uint dec) :Datetime(thd, warn, from, date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY) { round(thd, dec, time_round_mode_t(fuzzydate), warn); } explicit Datetime(const Temporal_hybrid *from) { from->copy_valid_value_to_mysql_time(this); DBUG_ASSERT(is_valid_datetime_slow()); } explicit Datetime(const MYSQL_TIME *from) { *(static_cast<MYSQL_TIME*>(this))= *from; DBUG_ASSERT(is_valid_datetime_slow()); } Datetime(my_time_t unix_time, ulong second_part, const Time_zone* time_zone); Datetime(uint year_arg, uint month_arg, uint day_arg, const TimeOfDay6 &td) { neg= 0; year= year_arg; month= month_arg; day= day_arg; hour= td.hour(); minute= td.minute(); second= td.second(); second_part= td.usecond(); time_type= MYSQL_TIMESTAMP_DATETIME; if (!is_valid_datetime_slow()) time_type= MYSQL_TIMESTAMP_NONE; } bool is_valid_datetime() const { /* Here we quickly check for the type only. If the type is valid, the rest of value must also be valid. */ DBUG_ASSERT(is_valid_value_slow()); return time_type == MYSQL_TIMESTAMP_DATETIME; } bool check_date(date_conv_mode_t flags, int *warnings) const { DBUG_ASSERT(is_valid_datetime_slow()); return ::check_date(this, (year || month || day), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warnings); } bool check_date(date_conv_mode_t flags) const { int dummy; /* unused */ return check_date(flags, &dummy); } bool check_date(THD *thd) const { return check_date(Temporal::sql_mode_for_dates(thd)); } bool hhmmssff_is_zero() const { DBUG_ASSERT(is_valid_datetime_slow()); return hour == 0 && minute == 0 && second == 0 && second_part == 0; } ulong daynr() const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::daynr(); } int weekday(bool sunday_first_day_of_week) const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::weekday(sunday_first_day_of_week); } ulong dayofyear() const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::dayofyear(); } uint quarter() const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::quarter(); } uint week(uint week_behaviour) const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::week(week_behaviour); } uint yearweek(uint week_behaviour) const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::yearweek(week_behaviour); } longlong hhmmss_to_seconds_abs() const { DBUG_ASSERT(is_valid_datetime_slow()); return hour * 3600L + minute * 60 + second; } longlong hhmmss_to_seconds() const { return neg ? -hhmmss_to_seconds_abs() : hhmmss_to_seconds_abs(); } longlong to_seconds() const { return hhmmss_to_seconds() + (longlong) daynr() * 24L * 3600L; } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_datetime_slow()); return this; } bool copy_to_mysql_time(MYSQL_TIME *ltime) const { if (time_type == MYSQL_TIMESTAMP_NONE) { ltime->time_type= MYSQL_TIMESTAMP_NONE; return true; } DBUG_ASSERT(is_valid_datetime_slow()); *ltime= *this; return false; } /** Copy without data loss, with an optional DATETIME to DATE conversion. If the value of the "type" argument is MYSQL_TIMESTAMP_DATE, then "this" must be a datetime with a zero hhmmssff part. */ bool copy_to_mysql_time(MYSQL_TIME *ltime, timestamp_type type) { DBUG_ASSERT(type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME); if (copy_to_mysql_time(ltime)) return true; DBUG_ASSERT(type != MYSQL_TIMESTAMP_DATE || hhmmssff_is_zero()); ltime->time_type= type; return false; } bool to_bool() const { return is_valid_datetime() && (TIME_to_ulonglong_datetime(this) != 0 || second_part != 0); } longlong to_longlong() const { return is_valid_datetime() ? (longlong) TIME_to_ulonglong_datetime(this) : 0LL; } double to_double() const { return !is_valid_datetime() ? 0 : Temporal::to_double(neg, TIME_to_ulonglong_datetime(this), second_part); } String *to_string(String *str, uint dec) const { if (!is_valid_datetime()) return NULL; str->set_charset(&my_charset_numeric); if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) str->length(my_datetime_to_str(this, const_cast<char*>(str->ptr()), dec)); return str; } my_decimal *to_decimal(my_decimal *to) { return is_valid_datetime() ? Temporal::to_decimal(to) : bad_to_decimal(to); } longlong to_packed() const { return is_valid_datetime() ? Temporal::to_packed() : 0; } longlong valid_datetime_to_packed() const { DBUG_ASSERT(is_valid_datetime_slow()); return Temporal::to_packed(); } long fraction_remainder(uint dec) const { DBUG_ASSERT(is_valid_datetime()); return Temporal::fraction_remainder(dec); } Datetime time_of_day(const TimeOfDay6 &td) const { DBUG_ASSERT(is_valid_datetime()); // not SQL NULL return Datetime(year, month, day, td); } Datetime &trunc(uint dec) { if (is_valid_datetime()) my_datetime_trunc(this, dec); DBUG_ASSERT(is_valid_value_slow()); return *this; } Datetime &ceiling(THD *thd, int *warn) { if (is_valid_datetime() && second_part) round_or_invalidate(thd, 0, warn, 999999999); DBUG_ASSERT(is_valid_value_slow()); return *this; } Datetime &ceiling(THD *thd) { int warn= 0; return ceiling(thd, &warn); } Datetime &round(THD *thd, uint dec, int *warn) { if (is_valid_datetime()) round_or_invalidate(thd, dec, warn); DBUG_ASSERT(is_valid_value_slow()); return *this; } Datetime &round(THD *thd, uint dec, time_round_mode_t mode, int *warn) { switch (mode.mode()) { case time_round_mode_t::FRAC_NONE: DBUG_ASSERT(fraction_remainder(dec) == 0); return trunc(dec); case time_round_mode_t::FRAC_TRUNCATE: return trunc(dec); case time_round_mode_t::FRAC_ROUND: return round(thd, dec, warn); } return *this; } Datetime &round(THD *thd, uint dec, time_round_mode_t mode) { int warn= 0; return round(thd, dec, mode, &warn); } }; /* Datetime to be created from an Item who is known to be of a temporal data type. For temporal data types we don't need nanosecond rounding or truncation, as their precision is limited. */ class Datetime_from_temporal: public Datetime { public: // The constructor DBUG_ASSERTs on a proper Item data type. Datetime_from_temporal(THD *thd, Item *temporal, date_conv_mode_t flags); }; /* Datetime to be created from an Item who is known not to have digits outside of the specified scale. So it's not important which rounding method to use. TRUNCATE should work. Typically, Item is of a temporal data type, but this is not strictly required. */ class Datetime_truncation_not_needed: public Datetime { public: Datetime_truncation_not_needed(THD *thd, Item *item, date_conv_mode_t mode); Datetime_truncation_not_needed(THD *thd, Item *item, date_mode_t mode) :Datetime_truncation_not_needed(thd, item, date_conv_mode_t(mode)) { } }; class Timestamp: protected Timeval { static uint binary_length_to_precision(uint length); protected: void round_or_set_max(uint dec, int *warn); bool add_nanoseconds_usec(uint nanoseconds) { DBUG_ASSERT(nanoseconds <= 1000000000); if (nanoseconds < 500) return false; tv_usec+= (nanoseconds + 500) / 1000; if (tv_usec < 1000000) return false; tv_usec%= 1000000; return true; } public: static date_conv_mode_t sql_mode_for_timestamp(THD *thd); static time_round_mode_t default_round_mode(THD *thd); class DatetimeOptions: public date_mode_t { public: DatetimeOptions(date_conv_mode_t fuzzydate, time_round_mode_t round_mode) :date_mode_t(fuzzydate | round_mode) { } DatetimeOptions(THD *thd) :DatetimeOptions(sql_mode_for_timestamp(thd), default_round_mode(thd)) { } }; public: Timestamp(my_time_t timestamp, ulong sec_part) :Timeval(timestamp, sec_part) { } explicit Timestamp(const timeval &tv) :Timeval(tv) { } explicit Timestamp(const Native &native); Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code); const struct timeval &tv() const { return *this; } int cmp(const Timestamp &other) const { return tv_sec < other.tv_sec ? -1 : tv_sec > other.tv_sec ? +1 : tv_usec < other.tv_usec ? -1 : tv_usec > other.tv_usec ? +1 : 0; } bool to_TIME(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) const; bool to_native(Native *to, uint decimals) const; Datetime to_datetime(THD *thd) const { return Datetime(thd, *this); } long fraction_remainder(uint dec) const { return my_time_fraction_remainder(tv_usec, dec); } Timestamp &trunc(uint dec) { my_timeval_trunc(this, dec); return *this; } Timestamp &round(uint dec, int *warn) { round_or_set_max(dec, warn); return *this; } Timestamp &round(uint dec, time_round_mode_t mode, int *warn) { switch (mode.mode()) { case time_round_mode_t::FRAC_NONE: DBUG_ASSERT(fraction_remainder(dec) == 0); return trunc(dec); case time_round_mode_t::FRAC_TRUNCATE: return trunc(dec); case time_round_mode_t::FRAC_ROUND: return round(dec, warn); } return *this; } Timestamp &round(uint dec, time_round_mode_t mode) { int warn= 0; return round(dec, mode, &warn); } }; /** A helper class to store MariaDB TIMESTAMP values, which can be: - real TIMESTAMP (seconds and microseconds since epoch), or - zero datetime '0000-00-00 00:00:00.000000' */ class Timestamp_or_zero_datetime: protected Timestamp { bool m_is_zero_datetime; public: static Timestamp_or_zero_datetime zero() { return Timestamp_or_zero_datetime(Timestamp(0, 0), true); } public: Timestamp_or_zero_datetime() :Timestamp(0,0), m_is_zero_datetime(true) { } Timestamp_or_zero_datetime(const Native &native) :Timestamp(native.length() ? Timestamp(native) : Timestamp(0,0)), m_is_zero_datetime(native.length() == 0) { } Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime= false) :Timestamp(tm), m_is_zero_datetime(is_zero_datetime) { } Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code); Datetime to_datetime(THD *thd) const { if (is_zero_datetime()) return Datetime::zero(); return Timestamp::to_datetime(thd); } bool to_bool() const { return !m_is_zero_datetime; } bool is_zero_datetime() const { return m_is_zero_datetime; } void trunc(uint decimals) { if (!is_zero_datetime()) Timestamp::trunc(decimals); } int cmp(const Timestamp_or_zero_datetime &other) const { if (is_zero_datetime()) return other.is_zero_datetime() ? 0 : -1; if (other.is_zero_datetime()) return 1; return Timestamp::cmp(other); } const Timestamp &to_timestamp() const { DBUG_ASSERT(!is_zero_datetime()); return *this; } bool to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const; /* Convert to native format: - Real timestamps are encoded in the same way how Field_timestamp2 stores values (big endian seconds followed by big endian microseconds) - Zero datetime '0000-00-00 00:00:00.000000' is encoded as empty string. Two native values are binary comparable. */ bool to_native(Native *to, uint decimals) const; }; /** A helper class to store non-null MariaDB TIMESTAMP values in the native binary encoded representation. */ class Timestamp_or_zero_datetime_native: public NativeBuffer<STRING_BUFFER_TIMESTAMP_BINARY_SIZE> { public: Timestamp_or_zero_datetime_native() = default; Timestamp_or_zero_datetime_native(const Timestamp_or_zero_datetime &ts, uint decimals) { if (ts.to_native(this, decimals)) length(0); // safety } int save_in_field(Field *field, uint decimals) const; Datetime to_datetime(THD *thd) const { return is_zero_datetime() ? Datetime::zero() : Datetime(thd, Timestamp(*this).tv()); } bool is_zero_datetime() const { return length() == 0; } }; /** A helper class to store nullable MariaDB TIMESTAMP values in the native binary encoded representation. */ class Timestamp_or_zero_datetime_native_null: public Timestamp_or_zero_datetime_native, public Null_flag { public: // With optional data type conversion Timestamp_or_zero_datetime_native_null(THD *thd, Item *item, bool conv); // Without data type conversion: item is known to be of the TIMESTAMP type Timestamp_or_zero_datetime_native_null(THD *thd, Item *item) :Timestamp_or_zero_datetime_native_null(thd, item, false) { } Datetime to_datetime(THD *thd) const { return is_null() ? Datetime() : Timestamp_or_zero_datetime_native::to_datetime(thd); } void to_TIME(THD *thd, MYSQL_TIME *to) { DBUG_ASSERT(!is_null()); Datetime::Options opt(TIME_CONV_NONE, TIME_FRAC_NONE); Timestamp_or_zero_datetime(*this).to_TIME(thd, to, opt); } bool is_zero_datetime() const { DBUG_ASSERT(!is_null()); return Timestamp_or_zero_datetime_native::is_zero_datetime(); } }; /* Flags for collation aggregation modes, used in TDCollation::agg(): MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value (i.e. constant). MY_COLL_ALLOW_CONV - allow any kind of conversion (combination of the above two) MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to @@character_set_connection MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE (e.g. when aggregating for comparison) MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV and MY_COLL_DISALLOW_NONE */ #define MY_COLL_ALLOW_SUPERSET_CONV 1 #define MY_COLL_ALLOW_COERCIBLE_CONV 2 #define MY_COLL_DISALLOW_NONE 4 #define MY_COLL_ALLOW_NUMERIC_CONV 8 #define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV) #define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) #define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII static inline my_repertoire_t operator|(const my_repertoire_t a, const my_repertoire_t b) { return (my_repertoire_t) ((uint) a | (uint) b); } static inline my_repertoire_t &operator|=(my_repertoire_t &a, const my_repertoire_t b) { return a= (my_repertoire_t) ((uint) a | (uint) b); } enum Derivation { DERIVATION_IGNORABLE= 6, DERIVATION_NUMERIC= 5, DERIVATION_COERCIBLE= 4, DERIVATION_SYSCONST= 3, DERIVATION_IMPLICIT= 2, DERIVATION_NONE= 1, DERIVATION_EXPLICIT= 0 }; /** "Declared Type Collation" A combination of collation and its derivation. */ class DTCollation { public: CHARSET_INFO *collation; enum Derivation derivation; my_repertoire_t repertoire; void set_repertoire_from_charset(CHARSET_INFO *cs) { repertoire= cs->state & MY_CS_PUREASCII ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; } DTCollation() { collation= &my_charset_bin; derivation= DERIVATION_NONE; repertoire= MY_REPERTOIRE_UNICODE30; } DTCollation(CHARSET_INFO *collation_arg) { /* This constructor version is used in combination with Field constructors, to pass "CHARSET_INFO" instead of the full DTCollation. Therefore, derivation is set to DERIVATION_IMPLICIT, which is the proper derivation for table fields. We should eventually remove all code pieces that pass "CHARSET_INFO" (e.g. in storage engine sources) and fix to pass the full DTCollation instead. Then, this constructor can be removed. */ collation= collation_arg; derivation= DERIVATION_IMPLICIT; repertoire= my_charset_repertoire(collation_arg); } DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) { collation= collation_arg; derivation= derivation_arg; set_repertoire_from_charset(collation_arg); } DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg, my_repertoire_t repertoire_arg) :collation(collation_arg), derivation(derivation_arg), repertoire(repertoire_arg) { } void set(const DTCollation &dt) { *this= dt; } void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) { collation= collation_arg; derivation= derivation_arg; set_repertoire_from_charset(collation_arg); } void set(CHARSET_INFO *collation_arg, Derivation derivation_arg, my_repertoire_t repertoire_arg) { collation= collation_arg; derivation= derivation_arg; repertoire= repertoire_arg; } void set(CHARSET_INFO *collation_arg) { collation= collation_arg; set_repertoire_from_charset(collation_arg); } void set(Derivation derivation_arg) { derivation= derivation_arg; } bool aggregate(const DTCollation &dt, uint flags= 0); bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0) { set(dt1); return aggregate(dt2, flags); } bool merge_charset_and_collation(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs, const Lex_extended_collation_st &cl, my_repertoire_t repertoire); bool merge_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl, my_repertoire_t repertoire, bool allow_ignorable_with_context_collation); const char *derivation_name() const { switch(derivation) { case DERIVATION_NUMERIC: return "NUMERIC"; case DERIVATION_IGNORABLE: return "IGNORABLE"; case DERIVATION_COERCIBLE: return "COERCIBLE"; case DERIVATION_IMPLICIT: return "IMPLICIT"; case DERIVATION_SYSCONST: return "SYSCONST"; case DERIVATION_EXPLICIT: return "EXPLICIT"; case DERIVATION_NONE: return "NONE"; default: return "UNKNOWN"; } } int sortcmp(const Binary_string *s, const Binary_string *t) const { return collation->strnncollsp(s->ptr(), s->length(), t->ptr(), t->length()); } }; class DTCollation_numeric: public DTCollation { public: DTCollation_numeric() :DTCollation(charset_info(), DERIVATION_NUMERIC, MY_REPERTOIRE_NUMERIC) { } static const CHARSET_INFO *charset_info() { return &my_charset_numeric; } static const DTCollation & singleton(); }; static inline uint32 char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg) { ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg; return tmp > UINT_MAX32 ? (uint32) UINT_MAX32 : static_cast<uint32>(tmp); } class Type_numeric_attributes { public: static uint count_unsigned(Item **item, uint nitems); static uint32 find_max_char_length(Item **item, uint nitems); static uint32 find_max_octet_length(Item **item, uint nitems); static decimal_digits_t find_max_decimal_int_part(Item **item, uint nitems); static decimal_digits_t find_max_decimals(Item **item, uint nitems); public: /* The maximum value length in characters multiplied by collation->mbmaxlen. Almost always it's the maximum value length in bytes. */ uint32 max_length; decimal_digits_t decimals; bool unsigned_flag; public: Type_numeric_attributes() :max_length(0), decimals(0), unsigned_flag(false) { } Type_numeric_attributes(uint32 max_length_arg, decimal_digits_t decimals_arg, bool unsigned_flag_arg) :max_length(max_length_arg), decimals(decimals_arg), unsigned_flag(unsigned_flag_arg) { } protected: void aggregate_numeric_attributes_real(Item **item, uint nitems); void aggregate_numeric_attributes_decimal(Item **item, uint nitems, bool unsigned_arg); }; class Type_temporal_attributes: public Type_numeric_attributes { public: Type_temporal_attributes(uint32 int_part_length, decimal_digits_t dec, bool unsigned_arg) :Type_numeric_attributes(int_part_length + (dec ? 1 : 0), MY_MIN(dec, (decimal_digits_t) TIME_SECOND_PART_DIGITS), unsigned_arg) { max_length+= decimals; } }; class Type_temporal_attributes_not_fixed_dec: public Type_numeric_attributes { public: Type_temporal_attributes_not_fixed_dec(uint32 int_part_length, decimal_digits_t dec, bool unsigned_flag) :Type_numeric_attributes(int_part_length, dec, unsigned_flag) { if (decimals == NOT_FIXED_DEC) max_length+= TIME_SECOND_PART_DIGITS + 1; else if (decimals) { set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); max_length+= decimals + 1; } } }; /** A class to store type attributes for the standard data types. Does not include attributes for the extended data types such as ENUM, SET, GEOMETRY. */ class Type_std_attributes: public Type_numeric_attributes { public: DTCollation collation; Type_std_attributes() :collation(&my_charset_bin, DERIVATION_COERCIBLE) { } Type_std_attributes(const Type_numeric_attributes &nattr, const DTCollation &dtc) :Type_numeric_attributes(nattr), collation(dtc) { } void set(const Type_std_attributes *other) { *this= *other; } void set(const Type_std_attributes &other) { *this= other; } void set(const Type_numeric_attributes &nattr, const DTCollation &dtc) { *this= Type_std_attributes(nattr, dtc); } uint32 max_char_length() const { return max_length / collation.collation->mbmaxlen; } void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs) { max_length= char_to_byte_length_safe(max_char_length_arg, cs->mbmaxlen); collation.collation= cs; } void fix_char_length(uint32 max_char_length_arg) { max_length= char_to_byte_length_safe(max_char_length_arg, collation.collation->mbmaxlen); } void fix_attributes_temporal(uint32 int_part_length, decimal_digits_t dec) { *this= Type_std_attributes( Type_temporal_attributes(int_part_length, dec, false), DTCollation_numeric()); } void fix_attributes_date() { fix_attributes_temporal(MAX_DATE_WIDTH, 0); } void fix_attributes_time(decimal_digits_t dec) { fix_attributes_temporal(MIN_TIME_WIDTH, dec); } void fix_attributes_datetime(decimal_digits_t dec) { fix_attributes_temporal(MAX_DATETIME_WIDTH, dec); } void aggregate_attributes_int(Item **items, uint nitems) { collation= DTCollation_numeric(); fix_char_length(find_max_char_length(items, nitems)); unsigned_flag= count_unsigned(items, nitems) > 0; decimals= 0; } void aggregate_attributes_real(Item **items, uint nitems) { collation= DTCollation_numeric(); aggregate_numeric_attributes_real(items, nitems); } void aggregate_attributes_decimal(Item **items, uint nitems, bool unsigned_arg) { collation= DTCollation_numeric(); aggregate_numeric_attributes_decimal(items, nitems, (unsigned_flag= unsigned_arg)); } bool aggregate_attributes_string(const LEX_CSTRING &func_name, Item **item, uint nitems); void aggregate_attributes_temporal(uint int_part_length, Item **item, uint nitems) { fix_attributes_temporal(int_part_length, find_max_decimals(item, nitems)); } bool agg_item_collations(DTCollation &c, const LEX_CSTRING &name, Item **items, uint nitems, uint flags, int item_sep); struct Single_coll_err { const DTCollation& coll; bool first; }; bool agg_item_set_converter(const DTCollation &coll, const LEX_CSTRING &name, Item **args, uint nargs, uint flags, int item_sep, const Single_coll_err *single_item_err= NULL); /* Collect arguments' character sets together. We allow to apply automatic character set conversion in some cases. The conditions when conversion is possible are: - arguments A and B have different charsets - A wins according to coercibility rules (i.e. a column is stronger than a string constant, an explicit COLLATE clause is stronger than a column) - character set of A is either superset for character set of B, or B is a string constant which can be converted into the character set of A without data loss. If all of the above is true, then it's possible to convert B into the character set of A, and then compare according to the collation of A. For functions with more than two arguments: collect(A,B,C) ::= collect(collect(A,B),C) Since this function calls THD::change_item_tree() on the passed Item ** pointers, it is necessary to pass the original Item **'s, not copies. Otherwise their values will not be properly restored (see BUG#20769). If the items are not consecutive (eg. args[2] and args[5]), use the item_sep argument, ie. agg_item_charsets(coll, fname, &args[2], 2, flags, 3) */ bool agg_arg_charsets(DTCollation &c, const LEX_CSTRING &func_name, Item **items, uint nitems, uint flags, int item_sep) { if (agg_item_collations(c, func_name, items, nitems, flags, item_sep)) return true; return agg_item_set_converter(c, func_name, items, nitems, flags, item_sep); } /* Aggregate arguments for string result, e.g: CONCAT(a,b) - convert to @@character_set_connection if all arguments are numbers - allow DERIVATION_NONE */ bool agg_arg_charsets_for_string_result(DTCollation &c, const LEX_CSTRING &func_name, Item **items, uint nitems, int item_sep) { uint flags= MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV | MY_COLL_ALLOW_NUMERIC_CONV; return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep); } /* Aggregate arguments for string result, when some comparison is involved internally, e.g: REPLACE(a,b,c) - convert to @@character_set_connection if all arguments are numbers - disallow DERIVATION_NONE */ bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c, const LEX_CSTRING &func_name, Item **items, uint nitems, int item_sep) { uint flags= MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV | MY_COLL_ALLOW_NUMERIC_CONV | MY_COLL_DISALLOW_NONE; return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep); } /* Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b - don't convert to @@character_set_connection if all arguments are numbers - don't allow DERIVATION_NONE */ bool agg_arg_charsets_for_comparison(DTCollation &c, const LEX_CSTRING &func_name, Item **items, uint nitems, int item_sep) { uint flags= MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV | MY_COLL_DISALLOW_NONE; return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep); } }; class Type_all_attributes: public Type_std_attributes { public: Type_all_attributes() = default; Type_all_attributes(const Type_all_attributes &) = default; virtual ~Type_all_attributes() = default; virtual void set_type_maybe_null(bool maybe_null_arg)= 0; virtual uint32 character_octet_length() const { return max_length; } // Returns total number of decimal digits virtual decimal_digits_t decimal_precision() const= 0; virtual const TYPELIB *get_typelib() const= 0; virtual void set_typelib(const TYPELIB *typelib)= 0; }; class Type_cmp_attributes { public: virtual ~Type_cmp_attributes() = default; virtual CHARSET_INFO *compare_collation() const= 0; }; class Type_cast_attributes { CHARSET_INFO *m_charset; ulonglong m_length; ulonglong m_decimals; bool m_length_specified; bool m_decimals_specified; public: Type_cast_attributes(const Lex_length_and_dec_st &length_and_dec, CHARSET_INFO *cs) :m_charset(cs), m_length(0), m_decimals(0), m_length_specified(false), m_decimals_specified(false) { m_length= length_and_dec.length_overflowed() ? (ulonglong) UINT_MAX32 + 1 : length_and_dec.length(); m_decimals= length_and_dec.dec(); m_length_specified= length_and_dec.has_explicit_length(); m_decimals_specified= length_and_dec.has_explicit_dec(); } Type_cast_attributes(CHARSET_INFO *cs) :m_charset(cs), m_length(0), m_decimals(0), m_length_specified(false), m_decimals_specified(false) { } CHARSET_INFO *charset() const { return m_charset; } bool length_specified() const { return m_length_specified; } bool decimals_specified() const { return m_decimals_specified; } ulonglong length() const { return m_length; } ulonglong decimals() const { return m_decimals; } }; class Name: private LEX_CSTRING { public: constexpr Name(const char *str_arg, uint length_arg) : LEX_CSTRING({str_arg, length_arg}) { } constexpr Name(const LEX_CSTRING &lcs) : LEX_CSTRING(lcs) { } const char *ptr() const { return LEX_CSTRING::str; } uint length() const { return (uint) LEX_CSTRING::length; } const LEX_CSTRING &lex_cstring() const { return *this; } bool eq(const LEX_CSTRING &other) const { return !system_charset_info->strnncoll(LEX_CSTRING::str, LEX_CSTRING::length, other.str, other.length); } }; class Bit_addr { /** Byte where the bit is stored inside a record. If the corresponding Field is a NOT NULL field, this member is NULL. */ uchar *m_ptr; /** Offset of the bit inside m_ptr[0], in the range 0..7. */ uchar m_offs; public: Bit_addr() :m_ptr(NULL), m_offs(0) { } Bit_addr(uchar *ptr, uchar offs) :m_ptr(ptr), m_offs(offs) { DBUG_ASSERT(ptr || offs == 0); DBUG_ASSERT(offs < 8); } Bit_addr(bool maybe_null) :m_ptr(maybe_null ? (uchar *) "" : NULL), m_offs(0) { } uchar *ptr() const { return m_ptr; } uchar offs() const { return m_offs; } uchar bit() const { return static_cast<uchar>(m_ptr ? 1U << m_offs : 0); } void inc() { DBUG_ASSERT(m_ptr); m_ptr+= (m_offs == 7); m_offs= (m_offs + 1) & 7; } }; class Record_addr { uchar *m_ptr; // Position of the field in the record Bit_addr m_null; // Position and offset of the null bit public: Record_addr(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg) :m_ptr(ptr_arg), m_null(null_ptr_arg, null_bit_arg) { } Record_addr(uchar *ptr, const Bit_addr &null) :m_ptr(ptr), m_null(null) { } Record_addr(bool maybe_null) :m_ptr(NULL), m_null(maybe_null) { } uchar *ptr() const { return m_ptr; } const Bit_addr &null() const { return m_null; } uchar *null_ptr() const { return m_null.ptr(); } uchar null_bit() const { return m_null.bit(); } }; class Information_schema_numeric_attributes { enum enum_attr { ATTR_NONE= 0, ATTR_PRECISION= 1, ATTR_SCALE= 2, ATTR_PRECISION_AND_SCALE= (ATTR_PRECISION|ATTR_SCALE) }; uint m_precision; decimal_digits_t m_scale; enum_attr m_available_attributes; public: Information_schema_numeric_attributes() :m_precision(0), m_scale(0), m_available_attributes(ATTR_NONE) { } Information_schema_numeric_attributes(uint precision) :m_precision(precision), m_scale(0), m_available_attributes(ATTR_PRECISION) { } Information_schema_numeric_attributes(uint precision, decimal_digits_t scale) :m_precision(precision), m_scale(scale), m_available_attributes(ATTR_PRECISION_AND_SCALE) { } bool has_precision() const { return m_available_attributes & ATTR_PRECISION; } bool has_scale() const { return m_available_attributes & ATTR_SCALE; } uint precision() const { DBUG_ASSERT(has_precision()); return (uint) m_precision; } decimal_digits_t scale() const { DBUG_ASSERT(has_scale()); return m_scale; } }; class Information_schema_character_attributes { uint32 m_octet_length; uint32 m_char_length; bool m_is_set; public: Information_schema_character_attributes() :m_octet_length(0), m_char_length(0), m_is_set(false) { } Information_schema_character_attributes(uint32 octet_length, uint32 char_length) :m_octet_length(octet_length), m_char_length(char_length), m_is_set(true) { } bool has_octet_length() const { return m_is_set; } bool has_char_length() const { return m_is_set; } uint32 octet_length() const { DBUG_ASSERT(has_octet_length()); return m_octet_length; } uint char_length() const { DBUG_ASSERT(has_char_length()); return m_char_length; } }; enum vers_kind_t { VERS_UNDEFINED= 0, VERS_TIMESTAMP, VERS_TRX_ID }; class Vers_type_handler { protected: Vers_type_handler() = default; public: virtual ~Vers_type_handler() = default; virtual vers_kind_t kind() const { DBUG_ASSERT(0); return VERS_UNDEFINED; } virtual bool check_sys_fields(const LEX_CSTRING &table_name, const Column_definition *row_start, const Column_definition *row_end) const= 0; }; class Vers_type_timestamp: public Vers_type_handler { public: vers_kind_t kind() const override { return VERS_TIMESTAMP; } bool check_sys_fields(const LEX_CSTRING &table_name, const Column_definition *row_start, const Column_definition *row_end) const override; }; extern Vers_type_timestamp vers_type_timestamp; class Vers_type_trx: public Vers_type_handler { public: vers_kind_t kind() const override { return VERS_TRX_ID; } bool check_sys_fields(const LEX_CSTRING &table_name, const Column_definition *row_start, const Column_definition *row_end) const override; }; extern MYSQL_PLUGIN_IMPORT Vers_type_trx vers_type_trx; class Type_handler { Name m_name; protected: String *print_item_value_csstr(THD *thd, Item *item, String *str) const; String *print_item_value_temporal(THD *thd, Item *item, String *str, const Name &type_name, String *buf) const; void make_sort_key_longlong(uchar *to, bool maybe_null, bool null_value, bool unsigned_flag, longlong value) const; void store_sort_key_longlong(uchar *to, bool unsigned_flag, longlong value) const; uint make_packed_sort_key_longlong(uchar *to, bool maybe_null, bool null_value, bool unsigned_flag, longlong value, const SORT_FIELD_ATTR *sort_field) const; bool Item_func_or_sum_illegal_param(const LEX_CSTRING &name) const; bool Item_func_or_sum_illegal_param(const Item_func_or_sum *) const; bool check_null(const Item *item, st_value *value) const; bool Item_send_str(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_tiny(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_short(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_long(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_longlong(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_float(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_double(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_timestamp(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const; bool Column_definition_prepare_stage2_legacy(Column_definition *c, enum_field_types type) const; bool Column_definition_prepare_stage2_legacy_num(Column_definition *c, enum_field_types type) const; bool Column_definition_prepare_stage2_legacy_real(Column_definition *c, enum_field_types type) const; public: static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name); static const Type_handler *handler_by_name_or_error(THD *thd, const LEX_CSTRING &name); static const Type_handler *handler_by_log_event_data_type( THD *thd, const Log_event_data_type &type); static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str); static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); static const Type_handler *bit_and_int_mixture_handler(uint max_char_len); static const Type_handler *type_handler_long_or_longlong(uint max_char_len, bool unsigned_flag); /** Return a string type handler for Item If too_big_for_varchar() returns a BLOB variant, according to length. If max_length > 0 create a VARCHAR(n) If max_length == 0 create a CHAR(0) @param item - the Item to get the handler to. */ static const Type_handler *varstring_type_handler(const Item *item); static const Type_handler *blob_type_handler(const Item *item); static const Type_handler *get_handler_by_field_type(enum_field_types type); static const Type_handler *get_handler_by_real_type(enum_field_types type); static const Type_collection * type_collection_for_aggregation(const Type_handler *h1, const Type_handler *h2); virtual const Type_collection *type_collection() const; static const Type_handler *aggregate_for_result_traditional(const Type_handler *h1, const Type_handler *h2); virtual Schema *schema() const; static void partition_field_type_not_allowed(const LEX_CSTRING &field_name); static bool partition_field_check_result_type(Item *item, Item_result expected_type); static const Name & version_mysql56(); static const Name & version_mariadb53(); void set_name(Name n) { DBUG_ASSERT(!m_name.ptr()); m_name= n; } const Name name() const { return m_name; } virtual const Name version() const; virtual const Name &default_value() const= 0; virtual uint32 flags() const { return 0; } virtual ulong KEY_pack_flags(uint column_nr) const { return 0; } bool is_unsigned() const { return flags() & UNSIGNED_FLAG; } virtual enum_field_types field_type() const= 0; virtual enum_field_types real_field_type() const { return field_type(); } /** Type code which is used for merging of traditional data types for result (for UNION and for hybrid functions such as COALESCE). Mapping can be done both ways: old->new, new->old, depending on the particular data type implementation: - type_handler_var_string (MySQL-4.1 old VARCHAR) is converted to new VARCHAR before merging. field_type_merge_rules[][] returns new VARCHAR. - type_handler_newdate is converted to old DATE before merging. field_type_merge_rules[][] returns NEWDATE. - Temporal type_handler_xxx2 (new MySQL-5.6 types) are converted to corresponding old type codes before merging (e.g. TIME2->TIME). field_type_merge_rules[][] returns old type codes (e.g. TIME). Then old types codes are supposed to convert to new type codes somehow, but they do not. So UNION and COALESCE create old columns. This is a bug and should be fixed eventually. */ virtual enum_field_types traditional_merge_field_type() const { DBUG_ASSERT(is_traditional_scalar_type()); return field_type(); } virtual enum_field_types type_code_for_protocol() const { return field_type(); } virtual protocol_send_type_t protocol_send_type() const= 0; virtual bool Item_append_extended_type_info(Send_field_extended_metadata *to, const Item *item) const { return false; } virtual Item_result result_type() const= 0; virtual Item_result cmp_type() const= 0; virtual enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const= 0; virtual enum_mysql_timestamp_type mysql_timestamp_type() const { return MYSQL_TIMESTAMP_ERROR; } /* Return true if the native format is fully implemented for a data type: - Field_xxx::val_native() - Item_xxx::val_native() for all classes supporting this data type - Type_handler_xxx::cmp_native() */ virtual bool is_val_native_ready() const { return false; } /* If operations such as: UPDATE t1 SET binary_string_field=this_type_field; should store this_type_field->val_native() rather than this_type_field->val_str(). */ virtual bool convert_to_binary_using_val_native() const { return false; } virtual bool is_timestamp_type() const { return false; } virtual bool is_order_clause_position_type() const { return false; } virtual bool is_limit_clause_valid_type() const { return false; } /* Returns true if this data type supports a hack that WHERE notnull_column IS NULL finds zero values, e.g.: WHERE date_notnull_column IS NULL -> WHERE date_notnull_column = '0000-00-00' */ virtual bool cond_notnull_field_isnull_to_field_eq_zero() const { return false; } /** Check whether a field type can be partially indexed by a key. @param type field type @retval true Type can have a prefixed key @retval false Type can not have a prefixed key */ virtual bool type_can_have_key_part() const { return false; } virtual bool type_can_have_auto_increment_attribute() const { return false; } virtual uint max_octet_length() const { return 0; } /** Prepared statement long data: Check whether this parameter data type is compatible with long data. Used to detect whether a long data stream has been supplied to a incompatible data type. */ virtual bool is_param_long_data_type() const { return false; } /* The base type handler "this" is derived from. "This" inherits aggregation rules from the base type handler. */ virtual const Type_handler *type_handler_base() const { return NULL; } const Type_handler *type_handler_base_or_self() const { const Type_handler *res= type_handler_base(); return res ? res : this; } /* In 10.11.8 the semantics of this method has changed to the opposite. It used to be called with the old data type handler as "this". Now it's called with the new data type hander as "this". To avoid problems during merges, the method name was renamed. */ virtual const Type_handler *type_handler_for_implicit_upgrade() const { return this; } virtual const Type_handler *type_handler_for_comparison() const= 0; virtual const Type_handler *type_handler_for_native_format() const { return this; } virtual const Type_handler *type_handler_for_item_field() const { return this; } virtual const Type_handler *type_handler_for_tmp_table(const Item *) const { return this; } virtual const Type_handler *type_handler_for_union(const Item *) const { return this; } virtual const Type_handler *cast_to_int_type_handler() const { return this; } virtual const Type_handler *type_handler_unsigned() const { return this; } virtual const Type_handler *type_handler_signed() const { return this; } virtual bool partition_field_check(const LEX_CSTRING &field_name, Item *) const { partition_field_type_not_allowed(field_name); return true; } virtual bool partition_field_append_value(String *str, Item *item_expr, CHARSET_INFO *field_cs, partition_value_print_mode_t mode) const; virtual int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const= 0; virtual CHARSET_INFO *charset_for_protocol(const Item *item) const; virtual const Type_handler* type_handler_adjusted_to_max_octet_length(uint max_octet_length, CHARSET_INFO *cs) const { return this; } virtual bool adjust_spparam_type(Spvar_definition *def, Item *from) const { return false; } Type_handler() : m_name(0,0) {} virtual ~Type_handler() = default; /** Determines MariaDB traditional scalar data types that always present in the server. */ bool is_traditional_scalar_type() const; virtual bool is_scalar_type() const { return true; } virtual bool can_return_int() const { return true; } virtual bool can_return_decimal() const { return true; } virtual bool can_return_real() const { return true; } virtual bool can_return_str() const { return true; } virtual bool can_return_text() const { return true; } virtual bool can_return_date() const { return true; } virtual bool can_return_time() const { return true; } virtual bool can_return_extract_source(interval_type type) const; virtual bool is_bool_type() const { return false; } virtual bool is_general_purpose_string_type() const { return false; } virtual Type_std_attributes Item_type_std_attributes_generic( const Item *item) const; virtual decimal_digits_t Item_time_precision(THD *thd, Item *item) const; virtual decimal_digits_t Item_datetime_precision(THD *thd, Item *item) const; virtual decimal_digits_t Item_decimal_scale(const Item *item) const; virtual decimal_digits_t Item_decimal_precision(const Item *item) const= 0; /* Returns how many digits a divisor adds into a division result. See Item::divisor_precision_increment() in item.h for more comments. */ virtual decimal_digits_t Item_divisor_precision_increment(const Item *) const; /** Makes a temporary table Field to handle numeric aggregate functions, e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc. */ virtual Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; /** Makes a temporary table Field to handle RBR replication type conversion. @param TABLE - The conversion table the field is going to be added to. It's used to access to table->in_use->mem_root, to create the new field on the table memory root, as well as to increment statistics in table->share (e.g. table->s->blob_count). @param metadata - Metadata from the binary log. @param target - The field in the target table on the slave. Note, the data types of "target" and of "this" are not necessarily always the same, in general case it's possible that: this->field_type() != target->field_type() and/or this->real_type( ) != target->real_type() This method decodes metadata according to this->real_type() and creates a new field also according to this->real_type(). In some cases it lurks into "target", to get some extra information, e.g.: - unsigned_flag for numeric fields - charset() for string fields - typelib and field_length for SET and ENUM - geom_type and srid for GEOMETRY This information is not available in the binary log, so we assume that these fields are the same on the master and on the slave. */ virtual Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const= 0; virtual void show_binlog_type(const Conv_source &src, const Field &dst, String *str) const; virtual uint32 max_display_length_for_field(const Conv_source &src) const= 0; /* Performs the final data type validation for a UNION element, after the regular "aggregation for result" was done. */ virtual bool union_element_finalize(Item_type_holder* item) const { return false; } virtual Log_event_data_type user_var_log_event_data_type(uint charset_nr) const { return Log_event_data_type({NULL,0}/*data type name*/, result_type(), charset_nr, is_unsigned()); } virtual uint Column_definition_gis_options_image(uchar *buff, const Column_definition &def) const { return 0; } virtual bool Column_definition_data_type_info_image(Binary_string *to, const Column_definition &def) const; // Check if the implicit default value is Ok in the current sql_mode virtual bool validate_implicit_default_value(THD *thd, const Column_definition &def) const; /* Automatic upgrade, e.g. for REPAIR or ALTER TABLE t1 FORCE - from the data type specified in old->type_handler() - to the data type specified in "this" */ virtual void Column_definition_implicit_upgrade_to_this( Column_definition *old) const; // Validate CHECK constraint after the parser virtual bool Column_definition_validate_check_constraint(THD *thd, Column_definition *c) const; // Set attributes in the parser virtual bool Column_definition_set_attributes(THD *thd, Column_definition *def, const Lex_field_type_st &attr, column_definition_type_t type) const; // Fix attributes after the parser virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0; /* Fix attributes from an existing field. Used for: - ALTER TABLE (for columns that do not change) - DECLARE var TYPE OF t1.col1; (anchored SP variables) */ virtual void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *c, const Field *field) const { } virtual bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const; virtual bool Column_definition_bulk_alter(Column_definition *c, const Column_derived_attributes *derived_attr, const Column_bulk_alter_attributes *bulk_alter_attr) const { return false; } /* This method is called on queries like: CREATE TABLE t2 (a INT) AS SELECT a FROM t1; I.e. column "a" is queried from another table, but its data type is redefined. @param OUT def - The column definition to be redefined @param IN dup - The column definition to take the data type from (i.e. "a INT" in the above example). @param IN file - Table owner handler. If it does not support certain data types, some conversion can be applied. I.g. true BIT to BIT-AS-CHAR. @param IN schema - the owner schema definition, e.g. for the default character set and collation. @retval true - on error @retval false - on success */ virtual bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const; virtual bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const= 0; virtual bool Key_part_spec_init_primary(Key_part_spec *part, const Column_definition &def, const handler *file) const; virtual bool Key_part_spec_init_unique(Key_part_spec *part, const Column_definition &def, const handler *file, bool *has_key_needed) const; virtual bool Key_part_spec_init_multiple(Key_part_spec *part, const Column_definition &def, const handler *file) const; virtual bool Key_part_spec_init_foreign(Key_part_spec *part, const Column_definition &def, const handler *file) const; virtual bool Key_part_spec_init_spatial(Key_part_spec *part, const Column_definition &def) const; virtual bool Key_part_spec_init_ft(Key_part_spec *part, const Column_definition &def) const { return true; // Error } virtual Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const= 0; Field *make_and_init_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; virtual Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const { DBUG_ASSERT(0); return NULL; } virtual Field * make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const= 0; virtual void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const; virtual const Type_handler *type_handler_frm_unpack(const uchar *buffer) const { return this; } virtual bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const; /* Create a fixed size key part for a sort key */ virtual void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const= 0; /* create a compact size key part for a sort key */ virtual uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const=0; virtual void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const= 0; virtual bool is_packable() const { return false; } virtual uint32 max_display_length(const Item *item) const= 0; virtual uint32 Item_decimal_notation_int_digits(const Item *item) const { return 0; } virtual uint32 calc_pack_length(uint32 length) const= 0; virtual uint calc_key_length(const Column_definition &def) const; virtual void Item_update_null_value(Item *item) const= 0; virtual bool Item_save_in_value(THD *thd, Item *item, st_value *value) const= 0; virtual void Item_param_setup_conversion(THD *thd, Item_param *) const {} virtual void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; virtual bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const= 0; virtual bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const; virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0; virtual int Item_save_in_field(Item *item, Field *field, bool no_conversions) const= 0; /** Return a string representation of the Item value. @param thd thread handle @param str string buffer for representation of the value @note If the item has a string result type, the string is escaped according to its character set. @retval NULL on error @retval non-NULL a pointer to a valid string on success */ virtual String *print_item_value(THD *thd, Item *item, String *str) const= 0; /** Check if WHERE expr=value AND expr=const can be rewritten as: WHERE const=value AND expr=const "this" is the comparison handler that is used by "target". @param target - the predicate expr=value, whose "expr" argument will be replaced to "const". @param target_expr - the target's "expr" which will be replaced to "const". @param target_value - the target's second argument, it will remain unchanged. @param source - the equality predicate expr=const (or expr<=>const) that can be used to rewrite the "target" part (under certain conditions, see the code). @param source_expr - the source's "expr". It should be exactly equal to the target's "expr" to make condition rewrite possible. @param source_const - the source's "const" argument, it will be inserted into "target" instead of "expr". */ virtual bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const= 0; /* @brief Check if an IN subquery allows materialization or not @param inner expression on the inner side of the IN subquery outer expression on the outer side of the IN subquery is_in_predicate SET to true if IN subquery was converted from an IN predicate or we are checking if materialization strategy can be used for an IN predicate */ virtual bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const= 0; /** Make a simple constant replacement item for a constant "src", so the new item can futher be used for comparison with "cmp", e.g.: src = cmp -> replacement = cmp "this" is the type handler that is used to compare "src" and "cmp". @param thd - current thread, for mem_root @param src - The item that we want to replace. It's a const item, but it can be complex enough to calculate on every row. @param cmp - The src's comparand. @retval - a pointer to the created replacement Item @retval - NULL, if could not create a replacement (e.g. on EOM). NULL is also returned for ROWs, because instead of replacing a Item_row to a new Item_row, Type_handler_row just replaces its elements. */ virtual Item *make_const_item_for_comparison(THD *thd, Item *src, const Item *cmp) const= 0; /** When aggregating function arguments for comparison (e.g. for =, <, >, <=, >=, NULLIF), in some cases we rewrite arguments. For example, if the predicate timestamp_expr0 = datetime_const_expr1 decides to compare arguments as DATETIME, we can try to rewrite datetime_const_expr1 to a TIMESTAMP constant and perform the comparison as TIMESTAMP, which is faster because does not have to perform TIMESTAMP->DATETIME data type conversion per row. "this" is the type handler that is used to compare "subject" and "counterpart" (DATETIME in the above example). @param thd the current thread @param subject the comparison side that we want try to rewrite @param counterpart the other comparison side @retval subject, if the subject does not need to be rewritten @retval NULL in case of error (e.g. EOM) @retval Otherwise, a pointer to a new Item which can be used as a replacement for the subject. */ virtual Item *convert_item_for_comparison(THD *thd, Item *subject, const Item *counterpart) const { return subject; } virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0; virtual Item *make_constructor_item(THD *thd, List<Item> *args) const { return NULL; } /** A builder for literals with data type name prefix, e.g.: TIME'00:00:00', DATE'2001-01-01', TIMESTAMP'2001-01-01 00:00:00'. @param thd The current thread @param str Character literal @param length Length of str @param cs Character set of the string @param send_error Whether to generate an error on failure @retval A pointer to a new Item on success NULL on error (wrong literal value, EOM) */ virtual Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const { MY_ASSERT_UNREACHABLE(); return nullptr; } Item_literal *create_literal_item(THD *thd, const String *str, bool send_error) const { return create_literal_item(thd, str->ptr(), str->length(), str->charset(), send_error); } virtual Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const { MY_ASSERT_UNREACHABLE(); return nullptr; } virtual Item_copy *create_item_copy(THD *thd, Item *item) const; virtual int cmp_native(const Native &a, const Native &b) const { MY_ASSERT_UNREACHABLE(); return 0; } virtual bool set_comparator_func(THD *thd, Arg_comparator *cmp) const= 0; virtual bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const { return false; } virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const= 0; virtual bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, Item_bool_rowready_func2 *func) const; virtual bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const= 0; virtual bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const; virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0; virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0; virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0; virtual bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0; virtual bool Item_val_native_with_conversion(THD *thd, Item *item, Native *to) const { return true; } virtual bool Item_val_native_with_conversion_result(THD *thd, Item *item, Native *to) const { return true; } virtual bool Item_val_bool(Item *item) const= 0; virtual void Item_get_date(THD *thd, Item *item, Temporal::Warn *buff, MYSQL_TIME *ltime, date_mode_t fuzzydate) const= 0; bool Item_get_date_with_warn(THD *thd, Item *item, MYSQL_TIME *ltime, date_mode_t fuzzydate) const; virtual longlong Item_val_int_signed_typecast(Item *item) const= 0; virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0; virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const= 0; virtual String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const= 0; virtual double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const= 0; virtual longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const= 0; virtual my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const= 0; virtual void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; bool Item_func_hybrid_field_type_get_date_with_warn(THD *thd, Item_func_hybrid_field_type *, MYSQL_TIME *, date_mode_t) const; virtual String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0; virtual double Item_func_min_max_val_real(Item_func_min_max *) const= 0; virtual longlong Item_func_min_max_val_int(Item_func_min_max *) const= 0; virtual my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const= 0; virtual bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; virtual bool Item_func_between_fix_length_and_dec(Item_func_between *func) const= 0; virtual longlong Item_func_between_val_int(Item_func_between *func) const= 0; virtual cmp_item * make_cmp_item(THD *thd, CHARSET_INFO *cs) const= 0; virtual in_vector * make_in_vector(THD *thd, const Item_func_in *func, uint nargs) const= 0; virtual bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const= 0; virtual bool Item_func_round_fix_length_and_dec(Item_func_round *round) const= 0; virtual bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *func) const= 0; virtual bool Item_func_abs_fix_length_and_dec(Item_func_abs *func) const= 0; virtual bool Item_func_neg_fix_length_and_dec(Item_func_neg *func) const= 0; virtual bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const; virtual bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const; virtual bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const; virtual bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const; virtual bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const; virtual bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const; virtual bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const; virtual bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const; virtual bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const; virtual bool Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0; virtual bool Item_func_minus_fix_length_and_dec(Item_func_minus *func) const= 0; virtual bool Item_func_mul_fix_length_and_dec(Item_func_mul *func) const= 0; virtual bool Item_func_div_fix_length_and_dec(Item_func_div *func) const= 0; virtual bool Item_func_mod_fix_length_and_dec(Item_func_mod *func) const= 0; virtual const Vers_type_handler *vers() const { return NULL; } }; /* Special handler for ROW */ class Type_handler_row: public Type_handler { public: virtual ~Type_handler_row() = default; const Name &default_value() const override; bool validate_implicit_default_value(THD *, const Column_definition &) const override { MY_ASSERT_UNREACHABLE(); return true; } const Type_collection *type_collection() const override; bool is_scalar_type() const override { return false; } bool can_return_int() const override { return false; } bool can_return_decimal() const override { return false; } bool can_return_real() const override { return false; } bool can_return_str() const override { return false; } bool can_return_text() const override { return false; } bool can_return_date() const override { return false; } bool can_return_time() const override { return false; } enum_field_types field_type() const override { MY_ASSERT_UNREACHABLE(); return MYSQL_TYPE_NULL; }; protocol_send_type_t protocol_send_type() const override { MY_ASSERT_UNREACHABLE(); return PROTOCOL_SEND_STRING; } Item_result result_type() const override { return ROW_RESULT; } Item_result cmp_type() const override { return ROW_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *) const override { MY_ASSERT_UNREACHABLE(); return DYN_COL_NULL; } const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *, Field *, Item *) const override { MY_ASSERT_UNREACHABLE(); return 0; } bool subquery_type_allows_materialization(const Item *, const Item *, bool) const override { MY_ASSERT_UNREACHABLE(); return false; } Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } Field *make_conversion_table_field(MEM_ROOT *, TABLE *, uint, const Field *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } bool Column_definition_fix_attributes(Column_definition *) const override { return false; } void Column_definition_reuse_fix_attributes(THD *, Column_definition *, const Field *) const override { MY_ASSERT_UNREACHABLE(); } bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *, const Column_definition *, const handler *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Column_definition_prepare_stage2(Column_definition *, handler *, ulonglong) const override { return false; } Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *, const Record_addr &, const Type_all_attributes &, TABLE_SHARE *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override { MY_ASSERT_UNREACHABLE(); } uint make_packed_sort_key_part(uchar *, Item *, const SORT_FIELD_ATTR *, String *) const override { MY_ASSERT_UNREACHABLE(); return 0; } void sort_length(THD *, const Type_std_attributes *, SORT_FIELD_ATTR *) const override { MY_ASSERT_UNREACHABLE(); } uint32 max_display_length(const Item *) const override { MY_ASSERT_UNREACHABLE(); return 0; } uint32 max_display_length_for_field(const Conv_source &) const override { MY_ASSERT_UNREACHABLE(); return 0; } uint32 calc_pack_length(uint32) const override { MY_ASSERT_UNREACHABLE(); return 0; } bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; decimal_digits_t Item_decimal_precision(const Item *) const override { MY_ASSERT_UNREACHABLE(); return DECIMAL_MAX_PRECISION; } bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; bool Item_send(Item *, Protocol *, st_value *) const override { MY_ASSERT_UNREACHABLE(); return true; } void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *, Field *, bool) const override { MY_ASSERT_UNREACHABLE(); return 1; } String *print_item_value(THD *thd, Item *item, String *str) const override; bool can_change_cond_ref_to_const(Item_bool_func2 *, Item *, Item *, Item_bool_func2 *, Item *, Item *) const override { MY_ASSERT_UNREACHABLE(); return false; } Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; Item_copy *create_item_copy(THD *, Item *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_val_bool(Item *item) const override { MY_ASSERT_UNREACHABLE(); return false; } void Item_get_date(THD *, Item *, Temporal::Warn *, MYSQL_TIME *ltime, date_mode_t) const override { MY_ASSERT_UNREACHABLE(); set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } longlong Item_val_int_signed_typecast(Item *) const override { MY_ASSERT_UNREACHABLE(); return 0; } longlong Item_val_int_unsigned_typecast(Item *) const override { MY_ASSERT_UNREACHABLE(); return 0; } String *Item_func_hex_val_str_ascii(Item_func_hex *, String *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override { MY_ASSERT_UNREACHABLE(); return 0.0; } longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override { MY_ASSERT_UNREACHABLE(); return 0; } my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *ltime, date_mode_t) const override { MY_ASSERT_UNREACHABLE(); set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } double Item_func_min_max_val_real(Item_func_min_max *) const override { MY_ASSERT_UNREACHABLE(); return 0; } longlong Item_func_min_max_val_int(Item_func_min_max *) const override { MY_ASSERT_UNREACHABLE(); return 0; } my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override { MY_ASSERT_UNREACHABLE(); return nullptr; } bool Item_func_min_max_get_date(THD *, Item_func_min_max*, MYSQL_TIME *, date_mode_t) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_func_between_fix_length_and_dec(Item_func_between *) const override { MY_ASSERT_UNREACHABLE(); return true; } longlong Item_func_between_val_int(Item_func_between *func) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const override; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const override { MY_ASSERT_UNREACHABLE(); return true; } bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; }; /* A common parent class for numeric data type handlers */ class Type_handler_numeric: public Type_handler { public: const Name &default_value() const override; String *print_item_value(THD *thd, Item *item, String *str) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const override; virtual ~Type_handler_numeric() = default; bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const override; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override; bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const override; }; /*** Abstract classes for every XXX_RESULT */ class Type_handler_real_result: public Type_handler_numeric { public: Item_result result_type() const override{ return REAL_RESULT; } Item_result cmp_type() const override { return REAL_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_DOUBLE; } virtual ~Type_handler_real_result() = default; const Type_handler *type_handler_for_comparison() const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *c, const Field *field) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; decimal_digits_t Item_decimal_precision(const Item *item) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const override; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const override; bool Item_val_bool(Item *item) const override; void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; longlong Item_val_int_signed_typecast(Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; }; class Type_handler_decimal_result: public Type_handler_numeric { public: protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_STRING; } Item_result result_type() const override { return DECIMAL_RESULT; } Item_result cmp_type() const override { return DECIMAL_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *) const override { return DYN_COL_DECIMAL; } virtual ~Type_handler_decimal_result() = default; const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *, Field *field, Item *item) const override { VDec item_val(item); return item_val.is_null() ? 0 : my_decimal(field).cmp(item_val.ptr()); } bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const override; Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; uint32 max_display_length(const Item *item) const override; uint32 Item_decimal_notation_int_digits(const Item *item) const override; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override { VDec va(a), vb(b); return va.ptr() && vb.ptr() && !va.cmp(vb); } decimal_digits_t Item_decimal_precision(const Item *item) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_str(item, protocol, buf); } void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance*) const override; bool Item_val_bool(Item *item) const override { return VDec(item).to_bool(); } void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; longlong Item_val_int_signed_typecast(Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override { return VDec(item).to_longlong(true); } String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; }; class Type_limits_int { private: uint32 m_precision; uint32 m_char_length; public: Type_limits_int(uint32 prec, uint32 nchars) :m_precision(prec), m_char_length(nchars) { } uint32 precision() const { return m_precision; } uint32 char_length() const { return m_char_length; } }; /* UNDIGNED TINYINT: 0..255 digits=3 nchars=3 SIGNED TINYINT : -128..127 digits=3 nchars=4 */ class Type_limits_uint8: public Type_limits_int { public: Type_limits_uint8() :Type_limits_int(MAX_TINYINT_WIDTH, MAX_TINYINT_WIDTH) { } }; class Type_limits_sint8: public Type_limits_int { public: Type_limits_sint8() :Type_limits_int(MAX_TINYINT_WIDTH, MAX_TINYINT_WIDTH + 1) { } }; /* UNDIGNED SMALLINT: 0..65535 digits=5 nchars=5 SIGNED SMALLINT: -32768..32767 digits=5 nchars=6 */ class Type_limits_uint16: public Type_limits_int { public: Type_limits_uint16() :Type_limits_int(MAX_SMALLINT_WIDTH, MAX_SMALLINT_WIDTH) { } }; class Type_limits_sint16: public Type_limits_int { public: Type_limits_sint16() :Type_limits_int(MAX_SMALLINT_WIDTH, MAX_SMALLINT_WIDTH + 1) { } }; /* MEDIUMINT UNSIGNED 0 .. 16777215 digits=8 char_length=8 MEDIUMINT SIGNED: -8388608 .. 8388607 digits=7 char_length=8 */ class Type_limits_uint24: public Type_limits_int { public: Type_limits_uint24() :Type_limits_int(MAX_MEDIUMINT_WIDTH, MAX_MEDIUMINT_WIDTH) { } }; class Type_limits_sint24: public Type_limits_int { public: Type_limits_sint24() :Type_limits_int(MAX_MEDIUMINT_WIDTH - 1, MAX_MEDIUMINT_WIDTH) { } }; /* UNSIGNED INT: 0..4294967295 digits=10 nchars=10 SIGNED INT: -2147483648..2147483647 digits=10 nchars=11 */ class Type_limits_uint32: public Type_limits_int { public: Type_limits_uint32() :Type_limits_int(MAX_INT_WIDTH, MAX_INT_WIDTH) { } }; class Type_limits_sint32: public Type_limits_int { public: Type_limits_sint32() :Type_limits_int(MAX_INT_WIDTH, MAX_INT_WIDTH + 1) { } }; /* UNSIGNED BIGINT: 0..18446744073709551615 digits=20 nchars=20 SIGNED BIGINT: -9223372036854775808..9223372036854775807 digits=19 nchars=20 */ class Type_limits_uint64: public Type_limits_int { public: Type_limits_uint64(): Type_limits_int(MAX_BIGINT_WIDTH, MAX_BIGINT_WIDTH) { } }; class Type_limits_sint64: public Type_limits_int { public: Type_limits_sint64() :Type_limits_int(MAX_BIGINT_WIDTH - 1, MAX_BIGINT_WIDTH) { } }; class Type_handler_int_result: public Type_handler_numeric { public: Item_result result_type() const override { return INT_RESULT; } Item_result cmp_type() const override { return INT_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return attr->unsigned_flag ? DYN_COL_UINT : DYN_COL_INT; } bool is_order_clause_position_type() const override { return true; } bool is_limit_clause_valid_type() const override { return true; } virtual ~Type_handler_int_result() = default; const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const override; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; Type_std_attributes Item_type_std_attributes_generic( const Item *item) const override; decimal_digits_t Item_decimal_precision(const Item *item) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; bool Item_val_bool(Item *item) const override; void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; longlong Item_val_int_signed_typecast(Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; const Vers_type_handler *vers() const override { return &vers_type_trx; } }; class Type_handler_general_purpose_int: public Type_handler_int_result { public: bool type_can_have_auto_increment_attribute() const override { return true; } virtual const Type_limits_int *type_limits_int() const= 0; uint32 max_display_length(const Item *item) const override { return type_limits_int()->char_length(); } uint32 Item_decimal_notation_int_digits(const Item *item) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, INT_RESULT); } bool partition_field_append_value(String *str, Item *item_expr, CHARSET_INFO *field_cs, partition_value_print_mode_t) const override; const Vers_type_handler *vers() const override { return &vers_type_trx; } }; class Type_handler_temporal_result: public Type_handler { protected: decimal_digits_t Item_decimal_scale_with_seconds(const Item *item) const; decimal_digits_t Item_divisor_precision_increment_with_seconds(const Item *) const; public: Item_result result_type() const override { return STRING_RESULT; } Item_result cmp_type() const override { return TIME_RESULT; } virtual ~Type_handler_temporal_result() = default; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; uint32 max_display_length(const Item *item) const override; uint32 Item_decimal_notation_int_digits(const Item *item) const override; bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const override; bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const override; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *)const override; bool Item_val_bool(Item *item) const override; void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; longlong Item_val_int_signed_typecast(Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override; String *Item_func_hex_val_str_ascii(Item_func_hex *, String *)const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t) const override; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t) const override; bool Item_func_between_fix_length_and_dec(Item_func_between *)const override; bool Item_func_in_fix_comparator_compatible_types(THD *, Item_func_in *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; const Vers_type_handler *vers() const override; }; class Type_handler_string_result: public Type_handler { decimal_digits_t Item_temporal_precision(THD *thd, Item *item, bool is_time) const; public: const Name &default_value() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_STRING; } Item_result result_type() const override { return STRING_RESULT; } Item_result cmp_type() const override { return STRING_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *) const override { return DYN_COL_STRING; } CHARSET_INFO *charset_for_protocol(const Item *item) const override; virtual ~Type_handler_string_result() = default; const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; const Type_handler * type_handler_adjusted_to_max_octet_length(uint max_octet_length, CHARSET_INFO *cs) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool is_packable() const override { return true; } bool union_element_finalize(Item_type_holder* item) const override; uint calc_key_length(const Column_definition &def) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; uint32 max_display_length(const Item *item) const override; /* The next method returns 309 for long stringified doubles in scientific notation, e.g. FORMAT('1e308', 2). */ uint32 Item_decimal_notation_int_digits(const Item *item) const override { return 309; } bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; decimal_digits_t Item_time_precision(THD *thd, Item *item) const override { return Item_temporal_precision(thd, item, true); } decimal_digits_t Item_datetime_precision(THD *thd, Item *item) const override { return Item_temporal_precision(thd, item, false); } decimal_digits_t Item_decimal_precision(const Item *item) const override; void Item_update_null_value(Item *item) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; void Item_param_setup_conversion(THD *thd, Item_param *) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_str(item, protocol, buf); } int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; String *print_item_value(THD *thd, Item *item, String *str) const override { return print_item_value_csstr(thd, item, str); } bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const override; bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool is_in_predicate) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const override; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const override; bool Item_val_bool(Item *item) const override; void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; longlong Item_val_int_signed_typecast(Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const override; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const override; bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const override; bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const override; bool Item_func_div_fix_length_and_dec(Item_func_div *) const override; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const override; const Vers_type_handler *vers() const override; }; class Type_handler_general_purpose_string: public Type_handler_string_result { public: bool is_general_purpose_string_type() const override { return true; } bool Column_definition_bulk_alter(Column_definition *c, const Column_derived_attributes *derived_attr, const Column_bulk_alter_attributes *bulk_alter_attr) const override; }; /*** Instantiable classes for every MYSQL_TYPE_XXX There are no Type_handler_xxx for the following types: - MYSQL_TYPE_VAR_STRING (old VARCHAR) - mapped to MYSQL_TYPE_VARSTRING - MYSQL_TYPE_ENUM - mapped to MYSQL_TYPE_VARSTRING - MYSQL_TYPE_SET: - mapped to MYSQL_TYPE_VARSTRING because the functionality that currently uses Type_handler (e.g. hybrid type functions) does not need to distinguish between these types and VARCHAR. For example: CREATE TABLE t2 AS SELECT COALESCE(enum_column) FROM t1; creates a VARCHAR column. There most likely be Type_handler_enum and Type_handler_set later, when the Type_handler infrastructure gets used in more pieces of the code. */ class Type_handler_tiny: public Type_handler_general_purpose_int { public: virtual ~Type_handler_tiny() = default; enum_field_types field_type() const override { return MYSQL_TYPE_TINY; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_TINY; } const Type_limits_int *type_limits_int() const override; uint32 calc_pack_length(uint32 length) const override { return 1; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 4; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_tiny(item, protocol, buf); } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TINY); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_utiny: public Type_handler_tiny { public: uint flags() const override { return UNSIGNED_FLAG; } const Type_limits_int *type_limits_int() const override; }; class Type_handler_short: public Type_handler_general_purpose_int { public: virtual ~Type_handler_short() = default; enum_field_types field_type() const override { return MYSQL_TYPE_SHORT; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_SHORT; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_short(item, protocol, buf); } const Type_limits_int *type_limits_int() const override; uint32 max_display_length_for_field(const Conv_source &src) const override { return 6; } uint32 calc_pack_length(uint32 length) const override{ return 2; } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_SHORT); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_ushort: public Type_handler_short { public: uint flags() const override { return UNSIGNED_FLAG; } const Type_limits_int *type_limits_int() const override; }; class Type_handler_long: public Type_handler_general_purpose_int { public: virtual ~Type_handler_long() = default; enum_field_types field_type() const override { return MYSQL_TYPE_LONG; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_LONG; } const Type_limits_int *type_limits_int() const override; uint32 max_display_length_for_field(const Conv_source &src) const override { return 11; } uint32 calc_pack_length(uint32 length) const override { return 4; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_long(item, protocol, buf); } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONG); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; /* The expression of this type reports itself as signed, however it's known not to return negative values. Items of this data type count only digits in Item::max_length, without adding +1 for the sign. This allows expressions of this type convert nicely to VARCHAR and DECIMAL. For example, YEAR(now()) is: - VARCHAR(4) in a string context - DECIMAL(4,0) in a decimal context - but INT(5) in an integer context */ class Type_handler_long_ge0: public Type_handler_long { public: decimal_digits_t Item_decimal_precision(const Item *item) const override; bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const override; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_ulong: public Type_handler_long { public: uint flags() const override { return UNSIGNED_FLAG; } const Type_limits_int *type_limits_int() const override; }; class Type_handler_bool: public Type_handler_long { public: bool is_bool_type() const override { return true; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; void Item_update_null_value(Item *item) const override; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; }; class Type_handler_longlong: public Type_handler_general_purpose_int { public: virtual ~Type_handler_longlong() = default; enum_field_types field_type() const override{ return MYSQL_TYPE_LONGLONG; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_LONGLONG; } const Type_limits_int *type_limits_int() const override; uint32 max_display_length_for_field(const Conv_source &src) const override { return 20; } uint32 calc_pack_length(uint32 length) const override { return 8; } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_longlong(item, protocol, buf); } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONGLONG); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_ulonglong: public Type_handler_longlong { public: uint flags() const override { return UNSIGNED_FLAG; } const Type_limits_int *type_limits_int() const override; }; class Type_handler_vers_trx_id: public Type_handler_ulonglong { public: virtual ~Type_handler_vers_trx_id() = default; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; }; class Type_handler_int24: public Type_handler_general_purpose_int { public: virtual ~Type_handler_int24() = default; enum_field_types field_type() const override { return MYSQL_TYPE_INT24; } const Type_handler *type_handler_unsigned() const override; const Type_handler *type_handler_signed() const override; protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_LONG; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_long(item, protocol, buf); } const Type_limits_int *type_limits_int() const override; uint32 max_display_length_for_field(const Conv_source &src) const override { return 9; } uint32 calc_pack_length(uint32 length) const override { return 3; } Field *make_conversion_table_field(MEM_ROOT *mem_root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_INT24); } Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_uint24: public Type_handler_int24 { public: uint flags() const override { return UNSIGNED_FLAG; } const Type_limits_int *type_limits_int() const override; }; class Type_handler_year: public Type_handler_int_result { public: virtual ~Type_handler_year() = default; enum_field_types field_type() const override { return MYSQL_TYPE_YEAR; } uint flags() const override { return UNSIGNED_FLAG; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_SHORT; } uint32 max_display_length(const Item *item) const override; uint32 Item_decimal_notation_int_digits(const Item *item) const override { return 4; }; uint32 max_display_length_for_field(const Conv_source &src) const override { return 4; } uint32 calc_pack_length(uint32 length) const override { return 1; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_short(item, protocol, buf); } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *c, const Field *field) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_YEAR); } Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *)const override; void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *item, Temporal::Warn *, MYSQL_TIME *to, date_mode_t fuzzydate) const override; const Vers_type_handler *vers() const override { return NULL; } }; class Type_handler_bit: public Type_handler_int_result { public: virtual ~Type_handler_bit() = default; enum_field_types field_type() const override { return MYSQL_TYPE_BIT; } uint flags() const override { return UNSIGNED_FLAG; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_STRING; } uint32 max_display_length(const Item *item) const override; uint32 Item_decimal_notation_int_digits(const Item *item) const override; static uint32 Bit_decimal_notation_int_digits_by_nbits(uint nbits); uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override { return length / 8; } uint calc_key_length(const Column_definition &def) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_str(item, protocol, buf); } String *print_item_value(THD *thd, Item *item, String *str) const override { return print_item_value_csstr(thd, item, str); } void show_binlog_type(const Conv_source &src, const Field &, String *str) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_float: public Type_handler_real_result { public: virtual ~Type_handler_float() = default; enum_field_types field_type() const override { return MYSQL_TYPE_FLOAT; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_FLOAT; } bool type_can_have_auto_increment_attribute() const override { return true; } uint32 max_display_length(const Item *item) const override { return 25; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 12; } uint32 Item_decimal_notation_int_digits(const Item *item) const override { return 39; } uint32 calc_pack_length(uint32 length) const override { return sizeof(float); } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_float(item, protocol, buf); } Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_FLOAT); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; }; class Type_handler_double: public Type_handler_real_result { public: virtual ~Type_handler_double() = default; enum_field_types field_type() const override { return MYSQL_TYPE_DOUBLE; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_DOUBLE; } bool type_can_have_auto_increment_attribute() const override { return true; } uint32 max_display_length(const Item *item) const override { return 53; } uint32 Item_decimal_notation_int_digits(const Item *item) const override { return 309; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 22; } uint32 calc_pack_length(uint32 length) const override { return sizeof(double); } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_double(item, protocol, buf); } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_DOUBLE); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; }; class Type_handler_time_common: public Type_handler_temporal_result { public: virtual ~Type_handler_time_common() = default; const Name &default_value() const override; enum_field_types field_type() const override { return MYSQL_TYPE_TIME; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_TIME; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_TIME; } enum_mysql_timestamp_type mysql_timestamp_type() const override { return MYSQL_TIMESTAMP_TIME; } bool is_val_native_ready() const override { return true; } const Type_handler *type_handler_for_native_format() const override; int cmp_native(const Native &a, const Native &b) const override; bool Item_val_native_with_conversion(THD *thd, Item *, Native *to) const override; bool Item_val_native_with_conversion_result(THD *thd, Item *, Native *to) const override; bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const override; bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, STRING_RESULT); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const override; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; decimal_digits_t Item_decimal_scale(const Item *item) const override { return Item_decimal_scale_with_seconds(item); } decimal_digits_t Item_decimal_precision(const Item *item) const override; decimal_digits_t Item_divisor_precision_increment(const Item *item) const override { return Item_divisor_precision_increment_with_seconds(item); } const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; void Column_definition_implicit_upgrade_to_this( Column_definition *old) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_time(item, protocol, buf); } void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; String *print_item_value(THD *thd, Item *item, String *str) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; longlong Item_val_int_unsigned_typecast(Item *item) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const override; double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override; longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override; my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const override; void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *, date_mode_t fuzzydate) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_time: public Type_handler_time_common { /* number of bytes to store TIME(N) */ static uint m_hires_bytes[MAX_DATETIME_PRECISION+1]; public: static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; } virtual ~Type_handler_time() = default; const Name version() const override { return version_mariadb53(); } uint32 max_display_length_for_field(const Conv_source &src) const override { return MIN_TIME_WIDTH; } uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_time2: public Type_handler_time_common { public: virtual ~Type_handler_time2() = default; const Name version() const override { return version_mysql56(); } enum_field_types real_field_type() const override { return MYSQL_TYPE_TIME2; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME2); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_temporal_with_date: public Type_handler_temporal_result { public: virtual ~Type_handler_temporal_with_date() = default; Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_date(item, protocol, buf); } void Item_update_null_value(Item *item) const override; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; }; class Type_handler_date_common: public Type_handler_temporal_with_date { public: virtual ~Type_handler_date_common() = default; const Name &default_value() const override; const Type_handler *type_handler_for_comparison() const override; enum_field_types field_type() const override { return MYSQL_TYPE_DATE; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 3; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_DATE; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_DATE; } enum_mysql_timestamp_type mysql_timestamp_type() const override { return MYSQL_TIMESTAMP_DATE; } bool cond_notnull_field_isnull_to_field_eq_zero() const override { return true; } bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, STRING_RESULT); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const override; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool validate_implicit_default_value(THD *thd, const Column_definition &def) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; decimal_digits_t Item_decimal_precision(const Item *item) const override; String *print_item_value(THD *thd, Item *item, String *str) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_date: public Type_handler_date_common { public: virtual ~Type_handler_date() = default; uint32 calc_pack_length(uint32 length) const override { return 4; } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATE); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_newdate: public Type_handler_date_common { public: virtual ~Type_handler_newdate() = default; enum_field_types real_field_type() const override { return MYSQL_TYPE_NEWDATE; } uint32 calc_pack_length(uint32 length) const override { return 3; } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NEWDATE); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_datetime_common: public Type_handler_temporal_with_date { public: virtual ~Type_handler_datetime_common() = default; const Name &default_value() const override; const Type_handler *type_handler_for_comparison() const override; enum_field_types field_type() const override { return MYSQL_TYPE_DATETIME; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_DATETIME; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_DATETIME; } enum_mysql_timestamp_type mysql_timestamp_type() const override { return MYSQL_TIMESTAMP_DATETIME; } bool cond_notnull_field_isnull_to_field_eq_zero() const override { return true; } bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, STRING_RESULT); } Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; bool validate_implicit_default_value(THD *thd, const Column_definition &def) const override; void Column_definition_implicit_upgrade_to_this( Column_definition *old) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; decimal_digits_t Item_decimal_scale(const Item *item) const override { return Item_decimal_scale_with_seconds(item); } decimal_digits_t Item_decimal_precision(const Item *item) const override; decimal_digits_t Item_divisor_precision_increment(const Item *item) const override { return Item_divisor_precision_increment_with_seconds(item); } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_datetime(item, protocol, buf); } String *print_item_value(THD *thd, Item *item, String *str) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; Item *convert_item_for_comparison(THD *thd, Item *subject, const Item *counterpart) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_datetime: public Type_handler_datetime_common { /* number of bytes to store DATETIME(N) */ static uint m_hires_bytes[MAX_DATETIME_PRECISION + 1]; public: static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; } virtual ~Type_handler_datetime() = default; const Name version() const override { return version_mariadb53(); } uint32 max_display_length_for_field(const Conv_source &src) const override { return MAX_DATETIME_WIDTH; } uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_datetime2: public Type_handler_datetime_common { public: virtual ~Type_handler_datetime2() = default; const Name version() const override { return version_mysql56(); } enum_field_types real_field_type() const override { return MYSQL_TYPE_DATETIME2; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME2); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_timestamp_common: public Type_handler_temporal_with_date { protected: bool TIME_to_native(THD *, const MYSQL_TIME *from, Native *to, uint dec) const; public: virtual ~Type_handler_timestamp_common() = default; const Name &default_value() const override; const Type_handler *type_handler_for_comparison() const override; const Type_handler *type_handler_for_native_format() const override; enum_field_types field_type() const override { return MYSQL_TYPE_TIMESTAMP; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_DATETIME; } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_DATETIME; } enum_mysql_timestamp_type mysql_timestamp_type() const override { return MYSQL_TIMESTAMP_DATETIME; } bool is_val_native_ready() const override { return true; } bool is_timestamp_type() const override { return true; } void Column_definition_implicit_upgrade_to_this( Column_definition *old) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override; bool Item_val_native_with_conversion(THD *thd, Item *, Native *to) const override; bool Item_val_native_with_conversion_result(THD *thd, Item *, Native *to) const override; bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const override; int cmp_native(const Native &a, const Native &b) const override; longlong Item_func_between_val_int(Item_func_between *func) const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override; in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *tmp) const override; void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; decimal_digits_t Item_decimal_scale(const Item *item) const override { return Item_decimal_scale_with_seconds(item); } decimal_digits_t Item_decimal_precision(const Item *item) const override; decimal_digits_t Item_divisor_precision_increment(const Item *item) const override { return Item_divisor_precision_increment_with_seconds(item); } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override { return Item_send_timestamp(item, protocol, buf); } int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override; String *print_item_value(THD *thd, Item *item, String *str) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; Item_copy *create_item_copy(THD *thd, Item *item) const override; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override; double Item_func_min_max_val_real(Item_func_min_max *) const override; longlong Item_func_min_max_val_int(Item_func_min_max *) const override; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const override; bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const override; }; class Type_handler_timestamp: public Type_handler_timestamp_common { /* number of bytes to store second_part part of the TIMESTAMP(N) */ static uint m_sec_part_bytes[MAX_DATETIME_PRECISION + 1]; public: static uint sec_part_bytes(uint dec) { return m_sec_part_bytes[dec]; } virtual ~Type_handler_timestamp() = default; const Name version() const override { return version_mariadb53(); } uint32 max_display_length_for_field(const Conv_source &src) const override { return MAX_DATETIME_WIDTH; } uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_timestamp2: public Type_handler_timestamp_common { public: virtual ~Type_handler_timestamp2() = default; const Name version() const override { return version_mysql56(); } enum_field_types real_field_type() const override { return MYSQL_TYPE_TIMESTAMP2; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP2); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_olddecimal: public Type_handler_decimal_result { public: virtual ~Type_handler_olddecimal() = default; enum_field_types field_type() const override { return MYSQL_TYPE_DECIMAL; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override { return length; } const Type_handler *type_handler_for_tmp_table(const Item *item) const override; const Type_handler *type_handler_for_union(const Item *item) const override; void show_binlog_type(const Conv_source &src, const Field &, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_DECIMAL); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_newdecimal: public Type_handler_decimal_result { public: virtual ~Type_handler_newdecimal() = default; enum_field_types field_type() const override { return MYSQL_TYPE_NEWDECIMAL; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; uint calc_key_length(const Column_definition &def) const override; void show_binlog_type(const Conv_source &src, const Field &, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; class Type_handler_null: public Type_handler_general_purpose_string { public: virtual ~Type_handler_null() = default; enum_field_types field_type() const override { return MYSQL_TYPE_NULL; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_NULL; } const Type_handler *type_handler_for_comparison() const override; const Type_handler *type_handler_for_tmp_table(const Item *item) const override; const Type_handler *type_handler_for_union(const Item *) const override; uint32 max_display_length(const Item *item) const override { return 0; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 0; } uint32 calc_pack_length(uint32 length) const override { return 0; } bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override; bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool union_element_finalize(Item_type_holder* item) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NULL); } void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; class Type_handler_longstr: public Type_handler_general_purpose_string { public: bool type_can_have_key_part() const override { return true; } }; class Type_handler_string: public Type_handler_longstr { public: virtual ~Type_handler_string() = default; enum_field_types field_type() const override { return MYSQL_TYPE_STRING; } ulong KEY_pack_flags(uint column_nr) const override { return HA_PACK_KEY; } bool is_param_long_data_type() const override { return true; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override { return length; } const Type_handler *type_handler_for_tmp_table(const Item *item) const override { return varstring_type_handler(item); } bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, STRING_RESULT); } void show_binlog_type(const Conv_source &src, const Field &dst, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_set_attributes(THD *thd, Column_definition *def, const Lex_field_type_st &attr, column_definition_type_t type) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; bool Key_part_spec_init_ft(Key_part_spec *part, const Column_definition &def) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; /* Old varchar */ class Type_handler_var_string: public Type_handler_string { public: virtual ~Type_handler_var_string() = default; enum_field_types field_type() const override { return MYSQL_TYPE_VAR_STRING; } enum_field_types real_field_type() const override { return MYSQL_TYPE_STRING; } enum_field_types traditional_merge_field_type() const override { return MYSQL_TYPE_VARCHAR; } const Type_handler *type_handler_for_implicit_upgrade() const override; const Type_handler *type_handler_for_tmp_table(const Item *item) const override { return varstring_type_handler(item); } uint32 max_display_length_for_field(const Conv_source &src) const override; void show_binlog_type(const Conv_source &src, const Field &dst, String *str) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_STRING); } const Type_handler *type_handler_for_union(const Item *item) const override { return varstring_type_handler(item); } }; class Type_handler_varchar: public Type_handler_longstr { public: virtual ~Type_handler_varchar() = default; enum_field_types field_type() const override { return MYSQL_TYPE_VARCHAR; } ulong KEY_pack_flags(uint column_nr) const override { if (column_nr == 0) return HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY; return HA_PACK_KEY; } enum_field_types type_code_for_protocol() const override { return MYSQL_TYPE_VAR_STRING; // Keep things compatible for old clients } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override { return (length + (length < 256 ? 1: 2)); } const Type_handler *type_handler_for_tmp_table(const Item *item) const override { return varstring_type_handler(item); } const Type_handler *type_handler_for_union(const Item *item) const override { return varstring_type_handler(item); } bool is_param_long_data_type() const override { return true; } bool partition_field_check(const LEX_CSTRING &, Item *item_expr) const override { return partition_field_check_result_type(item_expr, STRING_RESULT); } void show_binlog_type(const Conv_source &src, const Field &dst, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_set_attributes(THD *thd, Column_definition *def, const Lex_field_type_st &attr, column_definition_type_t type) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; bool Key_part_spec_init_ft(Key_part_spec *part, const Column_definition &def) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; bool adjust_spparam_type(Spvar_definition *def, Item *from) const override; }; class Type_handler_hex_hybrid: public Type_handler_varchar { public: virtual ~Type_handler_hex_hybrid() = default; const Type_handler *cast_to_int_type_handler() const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; }; class Type_handler_varchar_compressed: public Type_handler_varchar { public: enum_field_types real_field_type() const override { return MYSQL_TYPE_VARCHAR_COMPRESSED; } ulong KEY_pack_flags(uint column_nr) const override { MY_ASSERT_UNREACHABLE(); return 0; } uint32 max_display_length_for_field(const Conv_source &src) const override; bool partition_field_check(const LEX_CSTRING &field_name, Item *) const override { partition_field_type_not_allowed(field_name); return true; } void show_binlog_type(const Conv_source &src, const Field &dst, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { DBUG_ASSERT(0); return DYN_COL_STRING; } }; class Type_handler_blob_common: public Type_handler_longstr { public: virtual ~Type_handler_blob_common() = default; virtual uint length_bytes() const= 0; ulong KEY_pack_flags(uint column_nr) const override { if (column_nr == 0) return HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY; return HA_PACK_KEY; } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; const Type_handler *type_handler_for_tmp_table(const Item *item) const override { return blob_type_handler(item); } const Type_handler *type_handler_for_union(const Item *item) const override { return blob_type_handler(item); } bool subquery_type_allows_materialization(const Item *, const Item *, bool) const override { return false; // Materialization does not work with BLOB columns } bool is_param_long_data_type() const override { return true; } uint calc_key_length(const Column_definition &def) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; bool Key_part_spec_init_ft(Key_part_spec *part, const Column_definition &def) const override; bool Key_part_spec_init_primary(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_unique(Key_part_spec *part, const Column_definition &def, const handler *file, bool *has_key_needed) const override; bool Key_part_spec_init_multiple(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_foreign(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; void Item_param_setup_conversion(THD *thd, Item_param *) const override; bool partition_field_check(const LEX_CSTRING &field_name, Item *item_expr) const override; Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; const Vers_type_handler *vers() const override; }; class Type_handler_tiny_blob: public Type_handler_blob_common { public: virtual ~Type_handler_tiny_blob() = default; uint length_bytes() const override { return 1; } enum_field_types field_type() const override { return MYSQL_TYPE_TINY_BLOB; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; uint max_octet_length() const override { return UINT_MAX8; } }; class Type_handler_medium_blob: public Type_handler_blob_common { public: virtual ~Type_handler_medium_blob() = default; uint length_bytes() const override { return 3; } enum_field_types field_type() const override { return MYSQL_TYPE_MEDIUM_BLOB; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; uint max_octet_length() const override { return UINT_MAX24; } }; class Type_handler_long_blob: public Type_handler_blob_common { public: virtual ~Type_handler_long_blob() = default; uint length_bytes() const override { return 4; } enum_field_types field_type() const override { return MYSQL_TYPE_LONG_BLOB; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; uint max_octet_length() const override { return UINT_MAX32; } }; class Type_handler_blob: public Type_handler_blob_common { public: virtual ~Type_handler_blob() = default; uint length_bytes() const override { return 2; } enum_field_types field_type() const override { return MYSQL_TYPE_BLOB; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; uint max_octet_length() const override { return UINT_MAX16; } }; class Type_handler_blob_compressed: public Type_handler_blob { public: enum_field_types real_field_type() const override { return MYSQL_TYPE_BLOB_COMPRESSED; } ulong KEY_pack_flags(uint) const override { MY_ASSERT_UNREACHABLE(); return 0; } uint32 max_display_length_for_field(const Conv_source &src) const override; void show_binlog_type(const Conv_source &src, const Field &, String *str) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; enum_dynamic_column_type dyncol_type(const Type_all_attributes *) const override { DBUG_ASSERT(0); return DYN_COL_STRING; } }; class Type_handler_typelib: public Type_handler_general_purpose_string { public: virtual ~Type_handler_typelib() = default; enum_field_types field_type() const override { return MYSQL_TYPE_STRING; } const Type_handler *type_handler_for_item_field() const override; const Type_handler *cast_to_int_type_handler() const override; bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val*) const override; uint32 max_display_length_for_field(const Conv_source &src) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const override; void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *c, const Field *field) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; const Vers_type_handler *vers() const override { return NULL; } }; class Type_handler_enum: public Type_handler_typelib { public: virtual ~Type_handler_enum() = default; enum_field_types real_field_type() const override { return MYSQL_TYPE_ENUM; } enum_field_types traditional_merge_field_type() const override { return MYSQL_TYPE_ENUM; } uint32 calc_pack_length(uint32 length) const override; uint calc_key_length(const Column_definition &def) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, const ST_FIELD_INFO &def) const override; }; class Type_handler_set: public Type_handler_typelib { public: virtual ~Type_handler_set() = default; enum_field_types real_field_type() const override { return MYSQL_TYPE_SET; } enum_field_types traditional_merge_field_type() const override { return MYSQL_TYPE_SET; } uint32 calc_pack_length(uint32 length) const override; uint calc_key_length(const Column_definition &def) const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; }; // A pseudo type handler, mostly for test purposes for now class Type_handler_interval_DDhhmmssff: public Type_handler_long_blob { public: Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; }; class Function_collection { public: virtual ~Function_collection() = default; virtual bool init()= 0; virtual void cleanup()= 0; virtual Create_func *find_native_function_builder(THD *thd, const LEX_CSTRING &name) const= 0; }; class Type_collection { public: virtual ~Type_collection() = default; virtual bool init(Type_handler_data *) { return false; } virtual const Type_handler *aggregate_for_result(const Type_handler *h1, const Type_handler *h2) const= 0; virtual const Type_handler *aggregate_for_comparison(const Type_handler *h1, const Type_handler *h2) const= 0; virtual const Type_handler *aggregate_for_min_max(const Type_handler *h1, const Type_handler *h2) const= 0; virtual const Type_handler *aggregate_for_num_op(const Type_handler *h1, const Type_handler *h2) const= 0; }; /** A handler for hybrid type functions, e.g. COALESCE(), IF(), IFNULL(), NULLIF(), CASE, numeric operators, UNIX_TIMESTAMP(), TIME_TO_SEC(). Makes sure that field_type(), cmp_type() and result_type() are always in sync to each other for hybrid functions. */ class Type_handler_hybrid_field_type { const Type_handler *m_type_handler; bool aggregate_for_min_max(const Type_handler *other); public: Type_handler_hybrid_field_type(); Type_handler_hybrid_field_type(const Type_handler *handler) :m_type_handler(handler) { } Type_handler_hybrid_field_type(const Type_handler_hybrid_field_type *other) :m_type_handler(other->m_type_handler) { } void swap(Type_handler_hybrid_field_type &other) { swap_variables(const Type_handler *, m_type_handler, other.m_type_handler); } const Type_handler *type_handler() const { return m_type_handler; } enum_field_types real_field_type() const { return m_type_handler->real_field_type(); } Item_result cmp_type() const { return m_type_handler->cmp_type(); } enum_mysql_timestamp_type mysql_timestamp_type() const { return m_type_handler->mysql_timestamp_type(); } bool is_timestamp_type() const { return m_type_handler->is_timestamp_type(); } void set_handler(const Type_handler *other) { m_type_handler= other; } const Type_handler *set_handler_by_field_type(enum_field_types type) { return (m_type_handler= Type_handler::get_handler_by_field_type(type)); } const Type_handler *set_handler_by_real_type(enum_field_types type) { return (m_type_handler= Type_handler::get_handler_by_real_type(type)); } bool aggregate_for_comparison(const Type_handler *other); bool aggregate_for_comparison(const LEX_CSTRING &funcname, Item **items, uint nitems, bool treat_int_to_uint_as_decimal); bool aggregate_for_result(const Type_handler *other); bool aggregate_for_result(const LEX_CSTRING &funcname, Item **item, uint nitems, bool treat_bit_as_number); bool aggregate_for_min_max(const LEX_CSTRING &funcname, Item **item, uint nitems); bool aggregate_for_num_op(const class Type_aggregator *aggregator, const Type_handler *h0, const Type_handler *h1); }; class Type_handler_pair { const Type_handler *m_a; const Type_handler *m_b; public: Type_handler_pair(const Type_handler *a, const Type_handler *b) :m_a(a), m_b(b) { } const Type_handler *a() const { return m_a; } const Type_handler *b() const { return m_b; } /* Change both handlers to their parent data type handlers, if available. For example, VARCHAR/JSON -> VARCHAR. @returns The number of handlers changed (0,1 or 2). */ bool to_base() { bool rc= false; const Type_handler *na= m_a->type_handler_base(); const Type_handler *nb= m_b->type_handler_base(); if (na) { m_a= na; rc= true; } if (nb) { m_b= nb; rc= true; } return rc; } }; /* Helper template to simplify creating builtin types with names. Plugin types inherit from Type_handler_xxx types that do not set the name in the constructor, as sql_plugin.cc sets the type name from the plugin name. */ template <typename TypeHandler> class Named_type_handler : public TypeHandler { public: Named_type_handler(const char *n) : TypeHandler() { Type_handler::set_name(Name(n, static_cast<uint>(strlen(n)))); } }; extern Named_type_handler<Type_handler_row> type_handler_row; extern Named_type_handler<Type_handler_null> type_handler_null; extern Named_type_handler<Type_handler_float> type_handler_float; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_double> type_handler_double; extern Named_type_handler<Type_handler_bit> type_handler_bit; extern Named_type_handler<Type_handler_enum> type_handler_enum; extern Named_type_handler<Type_handler_set> type_handler_set; extern Named_type_handler<Type_handler_string> type_handler_string; extern Named_type_handler<Type_handler_var_string> type_handler_var_string; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_varchar> type_handler_varchar; extern Named_type_handler<Type_handler_varchar_compressed> type_handler_varchar_compressed; extern Named_type_handler<Type_handler_hex_hybrid> type_handler_hex_hybrid; extern Named_type_handler<Type_handler_tiny_blob> type_handler_tiny_blob; extern Named_type_handler<Type_handler_medium_blob> type_handler_medium_blob; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_long_blob> type_handler_long_blob; extern Named_type_handler<Type_handler_blob> type_handler_blob; extern Named_type_handler<Type_handler_blob_compressed> type_handler_blob_compressed; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_bool> type_handler_bool; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_tiny> type_handler_stiny; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_short> type_handler_sshort; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_int24> type_handler_sint24; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_long> type_handler_slong; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_long_ge0> type_handler_slong_ge0; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_longlong> type_handler_slonglong; extern Named_type_handler<Type_handler_utiny> type_handler_utiny; extern Named_type_handler<Type_handler_ushort> type_handler_ushort; extern Named_type_handler<Type_handler_uint24> type_handler_uint24; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_ulong> type_handler_ulong; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_ulonglong> type_handler_ulonglong; extern Named_type_handler<Type_handler_vers_trx_id> type_handler_vers_trx_id; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_newdecimal> type_handler_newdecimal; extern Named_type_handler<Type_handler_olddecimal> type_handler_olddecimal; extern Named_type_handler<Type_handler_year> type_handler_year; extern Named_type_handler<Type_handler_year> type_handler_year2; extern Named_type_handler<Type_handler_newdate> type_handler_newdate; extern Named_type_handler<Type_handler_date> type_handler_date; extern Named_type_handler<Type_handler_time> type_handler_time; extern Named_type_handler<Type_handler_time2> type_handler_time2; extern Named_type_handler<Type_handler_datetime> type_handler_datetime; extern Named_type_handler<Type_handler_datetime2> type_handler_datetime2; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_timestamp> type_handler_timestamp; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_timestamp2> type_handler_timestamp2; extern Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff; class Type_aggregator { bool m_is_commutative; public: class Pair { public: const Type_handler *m_handler1; const Type_handler *m_handler2; const Type_handler *m_result; Pair() = default; Pair(const Type_handler *handler1, const Type_handler *handler2, const Type_handler *result) :m_handler1(handler1), m_handler2(handler2), m_result(result) { } bool eq(const Type_handler *handler1, const Type_handler *handler2) const { return m_handler1 == handler1 && m_handler2 == handler2; } }; static const Type_handler * find_handler_in_array(const Type_aggregator::Pair *pairs, const Type_handler *h1, const Type_handler *h2, bool commutative) { for (const Type_aggregator::Pair *p= pairs; p->m_result; p++) { if (p->eq(h1, h2)) return p->m_result; if (commutative && p->eq(h2, h1)) return p->m_result; } return NULL; } private: Dynamic_array<Pair> m_array; const Pair* find_pair(const Type_handler *handler1, const Type_handler *handler2) const; public: Type_aggregator(bool is_commutative= false) :m_is_commutative(is_commutative), m_array(PSI_INSTRUMENT_MEM) { } bool add(const Type_handler *handler1, const Type_handler *handler2, const Type_handler *result) { return m_array.append(Pair(handler1, handler2, result)); } const Type_handler *find_handler(const Type_handler *handler1, const Type_handler *handler2) const { const Pair* el= find_pair(handler1, handler2); return el ? el->m_result : NULL; } bool is_commutative() const { return m_is_commutative; } }; class Type_aggregator_commutative: public Type_aggregator { public: Type_aggregator_commutative() :Type_aggregator(true) { } }; class Type_handler_data { public: Type_aggregator_commutative m_type_aggregator_for_result; Type_aggregator_commutative m_type_aggregator_for_comparison; Type_aggregator_commutative m_type_aggregator_for_plus; Type_aggregator_commutative m_type_aggregator_for_mul; Type_aggregator m_type_aggregator_for_minus; Type_aggregator m_type_aggregator_for_div; Type_aggregator m_type_aggregator_for_mod; #ifndef DBUG_OFF // This is used for mtr purposes in debug builds Type_aggregator m_type_aggregator_non_commutative_test; #endif bool init(); }; extern Type_handler_data *type_handler_data; #endif /* SQL_TYPE_H_INCLUDED */ rpl_injector.h 0000644 00000022625 15156036131 0007417 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef INJECTOR_H #define INJECTOR_H /* Pull in 'byte', 'my_off_t', and 'uint32' */ #include <my_bitmap.h> #include "rpl_constants.h" #include "table.h" /* TABLE */ /* Forward declarations */ class handler; class MYSQL_BIN_LOG; struct TABLE; /* Injector to inject rows into the MySQL server. The injector class is used to notify the MySQL server of new rows that have appeared outside of MySQL control. The original purpose of this is to allow clusters---which handle replication inside the cluster through other means---to insert new rows into binary log. Note, however, that the injector should be used whenever rows are altered in any manner that is outside of MySQL server visibility and which therefore are not seen by the MySQL server. */ class injector { public: /* Get an instance of the injector. DESCRIPTION The injector is a Singleton, so this static function return the available instance of the injector. RETURN VALUE A pointer to the available injector object. */ static injector *instance(); /* Delete the singleton instance (if allocated). Used during server shutdown. */ static void free_instance(); /* A transaction where rows can be added. DESCRIPTION The transaction class satisfy the **CopyConstructible** and **Assignable** requirements. Note that the transaction is *not* default constructible. */ class transaction { friend class injector; public: /* Convenience definitions */ typedef uchar* record_type; typedef uint32 server_id_type; /* Table reference. RESPONSIBILITY The class contains constructors to handle several forms of references to tables. The constructors can implicitly be used to construct references from, e.g., strings containing table names. EXAMPLE The class is intended to be used *by value*. Please, do not try to construct objects of this type using 'new'; instead construct an object, possibly a temporary object. For example: injector::transaction::table tbl(share->table, true); MY_BITMAP cols; my_bitmap_init(&cols, NULL, (i + 7) / 8, false); inj->write_row(::server_id, tbl, &cols, row_data); or MY_BITMAP cols; my_bitmap_init(&cols, NULL, (i + 7) / 8, false); inj->write_row(::server_id, injector::transaction::table(share->table, true), &cols, row_data); This will work, be more efficient, and have greater chance of inlining, not run the risk of losing pointers. COLLABORATION injector::transaction Provide a flexible interface to the representation of tables. */ class table { public: table(TABLE *table, bool is_transactional_arg) : m_table(table), m_is_transactional(is_transactional_arg) { } char const *db_name() const { return m_table->s->db.str; } char const *table_name() const { return m_table->s->table_name.str; } TABLE *get_table() const { return m_table; } bool is_transactional() const { return m_is_transactional; } private: TABLE *m_table; bool m_is_transactional; }; /* Binlog position as a structure. */ class binlog_pos { friend class transaction; public: char const *file_name() const { return m_file_name; } my_off_t file_pos() const { return m_file_pos; } private: char const *m_file_name; my_off_t m_file_pos; }; transaction() : m_thd(NULL) { } ~transaction(); /* Clear transaction, i.e., make calls to 'good()' return false. */ void clear() { m_thd= NULL; } /* Is the transaction in a good state? */ bool good() const { return m_thd != NULL; } /* Default assignment operator: standard implementation */ transaction& operator=(transaction t) { swap(t); return *this; } /* DESCRIPTION Register table for use within the transaction. All tables that are going to be used need to be registered before being used below. The member function will fail with an error if use_table() is called after any *_row() function has been called for the transaction. RETURN VALUE 0 All OK >0 Failure */ #ifdef TO_BE_DELETED int use_table(server_id_type sid, table tbl); #endif /* Commit a transaction. This member function will clean up after a sequence of *_row calls by, for example, releasing resource and unlocking files. */ int commit(); /* Get the position for the start of the transaction. Returns the position in the binary log of the first event in this transaction. If no event is yet written, the position where the event *will* be written is returned. This position is known, since a new_transaction() will lock the binary log and prevent any other writes to the binary log. */ binlog_pos start_pos() const; private: /* Only the injector may construct these object */ transaction(MYSQL_BIN_LOG *, THD *); void swap(transaction& o) { /* std::swap(m_start_pos, o.m_start_pos); */ { binlog_pos const tmp= m_start_pos; m_start_pos= o.m_start_pos; o.m_start_pos= tmp; } /* std::swap(m_thd, o.m_thd); */ { THD* const tmp= m_thd; m_thd= o.m_thd; o.m_thd= tmp; } { enum_state const tmp= m_state; m_state= o.m_state; o.m_state= tmp; } } enum enum_state { START_STATE, /* Start state */ TABLE_STATE, /* At least one table has been registered */ ROW_STATE, /* At least one row has been registered */ STATE_COUNT /* State count and sink state */ } m_state; /* Check and update the state. PARAMETER(S) target_state The state we are moving to: TABLE_STATE if we are writing a table and ROW_STATE if we are writing a row. DESCRIPTION The internal state will be updated to the target state if and only if it is a legal move. The only legal moves are: START_STATE -> START_STATE START_STATE -> TABLE_STATE TABLE_STATE -> TABLE_STATE TABLE_STATE -> ROW_STATE That is: - It is not possible to write any row before having written at least one table - It is not possible to write a table after at least one row has been written RETURN VALUE 0 All OK -1 Incorrect call sequence */ int check_state(enum_state const target_state) { #ifdef DBUG_TRACE static char const *state_name[] = { "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT" }; DBUG_PRINT("info", ("In state %s", state_name[m_state])); #endif DBUG_ASSERT(target_state <= STATE_COUNT); if (m_state <= target_state && target_state <= m_state + 1 && m_state < STATE_COUNT) m_state= target_state; else m_state= STATE_COUNT; return m_state == STATE_COUNT ? 1 : 0; } binlog_pos m_start_pos; THD *m_thd; }; /* Create a new transaction. This member function will prepare for a sequence of *_row calls by, for example, reserving resources and locking files. There are two overloaded alternatives: one returning a transaction by value and one using placement semantics. The following two calls are equivalent, with the exception that the latter will overwrite the transaction. injector::transaction trans1= inj->new_trans(thd); injector::transaction trans2; inj->new_trans(thd, &trans); */ transaction new_trans(THD *); void new_trans(THD *, transaction *); int record_incident(THD*, Incident incident); int record_incident(THD*, Incident incident, const LEX_CSTRING *message); private: explicit injector(); ~injector() = default; /* Nothing needs to be done */ injector(injector const&); /* You're not allowed to copy injector instances. */ }; #endif /* INJECTOR_H */ lex_hash.h 0000644 00000433706 15156036131 0006526 0 ustar 00 /* Do not edit this file directly! */ /* Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. */ /* Do not edit this file! This is generated by gen_lex_hash.cc that seeks for a perfect hash function */ #include "lex.h" static uchar sql_functions_map[16544]= { 0, 0, 191, 2, '!', '|', 29, 0, '<', 'X', 157, 0, 'A', 'Y', 57, 1, 'A', 'W', 46, 3, 'A', 'W', 191, 4, 'A', 'W', 166, 6, 'C', 'Z', 9, 9, 'A', 'V', 28, 11, 'A', 'Y', 40, 12, 'C', 'U', 51, 13, 'C', 'V', 213, 13, 'C', 'W', 110, 14, 'A', 'U', 182, 14, 'A', 'S', 7, 15, 'D', 'U', 95, 15, 'C', 'S', 137, 15, 'C', 'S', 207, 15, 'E', 'S', 255, 15, 'M', 'M', 14, 16, 0, 0, 166, 0, 0, 0, 85, 1, 0, 0, 86, 1, 'M', 'M', 32, 16, 0, 0, 168, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 81, 1, 0, 0, 3, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 0, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, '<', '>', 121, 0, 0, 0, 191, 2, '=', '>', 124, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'T', 126, 0, 0, 0, 50, 0, 0, 0, 191, 2, 0, 0, 151, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'S', 128, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 130, 1, 'F', 'R', 144, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 120, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 185, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 190, 2, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 23, 0, 0, 0, 27, 0, 0, 0, 242, 0, 0, 0, 191, 2, 0, 0, 244, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 252, 0, 0, 0, 18, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 21, 1, 0, 0, 146, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 149, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 158, 1, 0, 0, 7, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'V', 186, 0, 0, 0, 42, 0, 0, 0, 104, 0, 'A', 'I', 227, 0, 0, 0, 170, 0, 0, 0, 211, 0, 0, 0, 223, 0, 0, 0, 191, 2, 'N', 'P', 236, 0, 0, 0, 191, 2, 0, 0, 30, 1, 0, 0, 238, 255, 'A', 'O', 239, 0, 'O', 'O', 9, 1, 'N', 'U', 14, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 22, 1, 'E', 'U', 37, 1, 0, 0, 191, 2, 0, 0, 147, 2, 0, 0, 164, 2, 0, 0, 191, 2, 'M', 'O', 54, 1, 0, 0, 11, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 16, 0, 0, 0, 191, 2, 'D', 'Y', 205, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 24, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 33, 0, 0, 0, 21, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 0, 0, 0, 124, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 130, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 150, 0, 0, 0, 8, 1, 0, 0, 191, 2, 0, 0, 20, 1, 0, 0, 236, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'N', 254, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 112, 1, 0, 0, 234, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 233, 255, 'T', 'W', 10, 1, 0, 0, 139, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 232, 255, 0, 0, 150, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 162, 1, 0, 0, 208, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 5, 2, 0, 0, 30, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 56, 2, 0, 0, 191, 2, 0, 0, 77, 2, 0, 0, 223, 255, 0, 0, 216, 255, 0, 0, 186, 2, 0, 0, 191, 2, 0, 0, 184, 2, 0, 0, 30, 0, 'L', 'Y', 82, 1, 'A', 'U', 113, 1, 'A', 'U', 158, 1, 'A', 'X', 185, 1, 'A', 'U', 227, 1, 0, 0, 225, 0, 'A', 'O', 248, 1, 'N', 'N', 12, 2, 'O', 'S', 45, 2, 'E', 'I', 50, 2, 'A', 'O', 55, 2, 0, 0, 113, 1, 'A', 'U', 113, 2, 'N', 'V', 134, 2, 'A', 'R', 143, 2, 0, 0, 191, 2, 'A', 'O', 175, 2, 'H', 'T', 212, 2, 'E', 'Y', 233, 2, 'N', 'S', 25, 3, 0, 0, 165, 2, 'A', 'O', 31, 3, 0, 0, 183, 2, 0, 0, 187, 2, 0, 0, 43, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'T', 96, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 51, 0, 0, 0, 45, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 46, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 0, 'L', 'S', 134, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 62, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 71, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 74, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 0, 0, 0, 53, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'T', 142, 1, 0, 0, 56, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 251, 255, 'T', 'T', 179, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 139, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 147, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 154, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 155, 0, 'A', 'E', 180, 1, 0, 0, 118, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 122, 0, 0, 0, 159, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 160, 0, 0, 0, 191, 2, 'D', 'U', 209, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 0, 0, 0, 171, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 174, 0, 0, 0, 197, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 202, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 216, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 217, 0, 'R', 'S', 7, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 233, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'U', 9, 2, 0, 0, 230, 0, 0, 0, 231, 0, 0, 0, 236, 0, 0, 0, 191, 2, 0, 0, 238, 0, 'T', 'T', 13, 2, '1', 'O', 14, 2, 0, 0, 9, 1, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0, 12, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 13, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 17, 1, 0, 0, 27, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 28, 1, 0, 0, 31, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 33, 1, 0, 0, 35, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'S', 70, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'K', 'S', 89, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 98, 2, 0, 0, 237, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 41, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 42, 1, 0, 0, 44, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 1, 0, 0, 49, 1, 0, 0, 191, 2, 0, 0, 53, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 57, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 58, 1, 0, 0, 61, 1, 0, 0, 121, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 138, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 142, 1, 0, 0, 152, 1, 0, 0, 191, 2, 0, 0, 153, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 165, 1, 'G', 'T', 161, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 185, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 192, 1, 0, 0, 170, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 174, 1, 0, 0, 225, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 190, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 200, 2, 'D', 'L', 191, 2, 0, 0, 209, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 213, 1, 0, 0, 1, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 8, 2, 0, 0, 33, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 38, 2, 0, 0, 42, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'F', 'M', 225, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 86, 2, 0, 0, 46, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 47, 2, 0, 0, 109, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'E', 254, 2, 'E', 'M', 3, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'U', 12, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 129, 2, 0, 0, 110, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 2, 0, 0, 112, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 113, 2, 0, 0, 214, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 127, 2, 0, 0, 135, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 148, 2, 0, 0, 169, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 171, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 173, 2, 0, 0, 177, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 180, 2, 'D', 'S', 69, 3, 'E', 'T', 85, 3, 'A', 'Y', 101, 3, 0, 0, 191, 2, 'L', 'V', 131, 3, 'A', 'O', 148, 3, 'R', 'R', 181, 3, 0, 0, 237, 0, 'N', 'N', 197, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 210, 3, 'A', 'Y', 1, 4, 'A', 'T', 26, 4, 'R', 'W', 46, 4, 'H', 'U', 52, 4, 'U', 'U', 66, 4, 'A', 'T', 72, 4, 'H', 'W', 119, 4, 0, 0, 101, 2, 'N', 'S', 148, 4, 0, 0, 156, 2, 'H', 'R', 175, 4, 0, 0, 12, 0, 0, 0, 191, 2, 0, 0, 13, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 18, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 0, 0, 0, 37, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 44, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 49, 0, 0, 0, 52, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'E', 126, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 250, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 106, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 117, 0, 0, 0, 58, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 65, 0, 0, 0, 162, 0, 0, 0, 163, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'E', 142, 3, 'N', 'R', 143, 3, 0, 0, 179, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 0, 0, 0, 196, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 200, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'X', 163, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'U', 170, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'U', 177, 3, 0, 0, 203, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 204, 0, 0, 0, 205, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 208, 0, 0, 0, 212, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 215, 0, 'A', 'O', 182, 3, 0, 0, 226, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 228, 0, 'D', 'O', 198, 3, 0, 0, 254, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 2, 1, 0, 0, 3, 1, 'A', 'V', 221, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'M', 'N', 243, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'C', 245, 3, 0, 0, 39, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 43, 1, 0, 0, 45, 1, 0, 0, 47, 1, 'A', 'K', 246, 3, 0, 0, 50, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 55, 1, 0, 0, 87, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 101, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 106, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 117, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 118, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 119, 1, 0, 0, 122, 1, 0, 0, 191, 2, 0, 0, 125, 1, 0, 0, 191, 2, 0, 0, 127, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 230, 255, 0, 0, 159, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 163, 1, 0, 0, 191, 2, 0, 0, 167, 1, 0, 0, 182, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 201, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 202, 1, 'E', 'I', 67, 4, 0, 0, 204, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 205, 1, 'I', 'N', 92, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'U', 98, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 255, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 0, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 13, 2, 0, 0, 206, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 207, 1, 0, 0, 212, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 222, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 242, 1, 0, 0, 191, 2, 0, 0, 252, 1, 0, 0, 32, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 39, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 135, 4, 0, 0, 94, 2, 0, 0, 191, 2, 0, 0, 96, 2, 'G', 'R', 136, 4, 0, 0, 51, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 78, 2, 'I', 'T', 154, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 166, 4, 0, 0, 137, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 143, 2, 0, 0, 146, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 151, 2, 'E', 'I', 186, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 182, 2, 0, 0, 174, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 2, 'C', 'T', 214, 4, 'A', 'I', 232, 4, 'H', 'U', 11, 5, 'E', 'O', 27, 5, 'L', 'X', 38, 5, 'A', 'O', 79, 5, 'L', 'R', 102, 5, 0, 0, 232, 0, 'G', 'S', 109, 5, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 141, 5, 'A', 'O', 152, 5, 'E', 'U', 199, 5, 'F', 'T', 216, 5, 'A', 'L', 231, 5, 0, 0, 191, 2, 'E', 'O', 243, 5, 'C', 'Y', 38, 6, 0, 0, 103, 2, 'N', 'P', 151, 6, 0, 0, 157, 2, 'I', 'I', 158, 6, 0, 0, 10, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 19, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 28, 0, 0, 0, 35, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 36, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'T', 241, 4, 0, 0, 39, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'L', 255, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 253, 255, 0, 0, 40, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 41, 0, 0, 0, 59, 0, 0, 0, 68, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 70, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'M', 25, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 105, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 115, 0, 0, 0, 77, 0, 0, 0, 86, 0, 0, 0, 137, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 152, 0, 0, 0, 161, 0, 0, 0, 191, 2, 'A', 'G', 51, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 176, 0, 0, 0, 177, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 180, 0, 0, 0, 191, 2, 'C', 'P', 58, 5, 0, 0, 164, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 172, 0, 0, 0, 183, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 188, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'O', 72, 5, 0, 0, 191, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 192, 0, 0, 0, 198, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 201, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'O', 94, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 214, 0, 'A', 'A', 95, 5, 'T', 'T', 96, 5, '4', '8', 97, 5, 0, 0, 206, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 207, 0, 0, 0, 224, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 227, 0, 0, 0, 245, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 250, 0, 'F', 'S', 122, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'S', 136, 5, 0, 0, 0, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 5, 1, 0, 0, 23, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 24, 1, 0, 0, 40, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 46, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 54, 1, 0, 0, 63, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'M', 167, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 115, 1, 'I', 'I', 177, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 100, 1, 'A', 'U', 178, 5, 0, 0, 235, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 96, 1, 0, 0, 126, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 136, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 143, 1, 0, 0, 147, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 151, 1, 0, 0, 191, 2, 0, 0, 156, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 161, 1, 0, 0, 172, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 183, 1, 'G', 'V', 254, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 26, 6, 0, 0, 221, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 228, 1, 0, 0, 229, 1, 0, 0, 230, 1, 0, 0, 191, 2, 'A', 'L', 14, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 247, 1, 0, 0, 249, 1, 0, 0, 191, 2, 0, 0, 254, 1, 0, 0, 232, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 240, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 235, 1, 0, 0, 3, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 7, 2, 0, 0, 16, 2, 0, 0, 191, 2, 'C', 'T', 61, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'M', 93, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 40, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'U', 106, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'R', 130, 6, 0, 0, 218, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 99, 2, 0, 0, 19, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'V', 79, 6, 0, 0, 191, 2, 0, 0, 31, 2, 0, 0, 26, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 29, 2, 'N', 'N', 100, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 37, 2, 'A', 'E', 101, 6, 0, 0, 35, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 36, 2, 0, 0, 45, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'R', 125, 6, 0, 0, 49, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 50, 2, 'R', 'T', 148, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 222, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 52, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 89, 2, 0, 0, 80, 2, 0, 0, 191, 2, 0, 0, 85, 2, 'I', 'L', 154, 6, 0, 0, 191, 2, 0, 0, 144, 2, 0, 0, 138, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 2, 'N', 'T', 159, 6, 0, 0, 176, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 178, 2, 'C', 'U', 189, 6, 'E', 'O', 208, 6, 'A', 'U', 245, 6, 'E', 'Y', 62, 7, 'N', 'X', 110, 7, 'O', 'O', 139, 7, 0, 0, 220, 0, 'A', 'I', 147, 7, 'G', 'T', 156, 7, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 189, 7, 'I', 'O', 204, 7, 'A', 'U', 211, 7, 'P', 'U', 30, 8, 'A', 'R', 36, 8, 0, 0, 203, 1, 'E', 'O', 85, 8, 'C', 'Y', 146, 8, 'H', 'R', 194, 8, 'N', 'S', 205, 8, 'A', 'I', 214, 8, 'I', 'R', 255, 8, 0, 0, 9, 0, 0, 0, 255, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 14, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 20, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 29, 0, 0, 0, 38, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'T', 'T', 219, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 47, 0, '_', '_', 220, 6, 'A', 'X', 221, 6, 0, 0, 254, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 252, 255, 0, 0, 54, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 10, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 24, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 44, 7, 'N', 'R', 11, 7, 'G', 'N', 16, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 64, 0, 0, 0, 60, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 61, 0, 'L', 'U', 27, 7, 'M', 'P', 37, 7, 'T', 'V', 41, 7, 0, 0, 75, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 79, 0, 0, 0, 85, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 0, 0, 0, 100, 0, 0, 0, 191, 2, 0, 0, 103, 0, 'D', 'T', 45, 7, 0, 0, 248, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 0, 0, 0, 191, 2, 0, 0, 247, 255, 'C', 'L', 83, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 106, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 158, 0, 'I', 'L', 93, 7, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 97, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 135, 0, 0, 0, 131, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 132, 0, 0, 0, 133, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 134, 0, 'A', 'C', 107, 7, 0, 0, 145, 0, 0, 0, 191, 2, 0, 0, 146, 0, 0, 0, 173, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 178, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'T', 121, 7, 0, 0, 185, 0, 0, 0, 191, 2, 0, 0, 186, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 193, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 243, 255, 'L', 'R', 140, 7, 0, 0, 210, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 213, 0, 0, 0, 229, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 235, 0, 0, 0, 246, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'V', 170, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 1, 0, 0, 255, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 7, 1, 0, 0, 14, 1, 0, 0, 191, 2, 0, 0, 26, 1, 0, 0, 37, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 38, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 56, 1, 0, 0, 105, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 116, 1, 0, 0, 124, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 129, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', '_', 232, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 144, 1, 'A', 'Y', 5, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 135, 1, 0, 0, 133, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 134, 1, 0, 0, 155, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 164, 1, 'C', 'R', 54, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 184, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 186, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 70, 8, 0, 0, 168, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 176, 1, 0, 0, 190, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 194, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'F', 81, 8, 0, 0, 197, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 199, 1, 'B', 'V', 96, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'U', 'W', 143, 8, 0, 0, 214, 1, 0, 0, 215, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 227, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'L', 117, 8, 0, 0, 241, 1, 0, 0, 191, 2, 'T', 'T', 127, 8, 0, 0, 251, 1, 0, 0, 191, 2, 0, 0, 253, 1, 'A', 'I', 118, 8, 0, 0, 234, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 236, 1, 'A', 'O', 128, 8, 0, 0, 244, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 245, 1, 0, 0, 4, 2, 0, 0, 191, 2, 0, 0, 9, 2, 0, 0, 18, 2, 0, 0, 191, 2, 0, 0, 28, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 53, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 87, 2, 'B', 'S', 169, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 98, 2, 'D', 'J', 187, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 95, 2, 0, 0, 219, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 91, 2, 0, 0, 124, 2, 0, 0, 118, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 125, 2, 'I', 'K', 211, 8, 0, 0, 191, 2, 0, 0, 145, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 150, 2, 0, 0, 136, 2, 0, 0, 191, 2, 0, 0, 139, 2, 'R', 'R', 223, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'S', 253, 8, 'C', '_', 224, 8, 0, 0, 159, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 163, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 211, 255, 0, 0, 166, 2, 0, 0, 167, 2, 0, 0, 179, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 2, 'A', 'O', 33, 9, 'A', 'U', 72, 9, 'N', 'X', 140, 9, 'U', 'U', 171, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 15, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 175, 9, 'A', 'O', 211, 9, 'A', 'V', 250, 9, 'P', 'V', 16, 10, 'A', 'R', 23, 10, 0, 0, 191, 2, 'E', 'O', 72, 10, 'C', 'W', 123, 10, 'I', 'R', 159, 10, 'N', 'T', 211, 10, 'A', 'A', 253, 10, 0, 0, 170, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 2, 0, 0, 55, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 67, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'N', 48, 9, 0, 0, 73, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'T', 'T', 62, 9, 'A', 'I', 63, 9, 0, 0, 99, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 101, 0, 'T', 'Y', 93, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 148, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 156, 0, 'A', 'E', 99, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 125, 0, 'B', 'F', 104, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'T', '_', 109, 9, 0, 0, 119, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 121, 0, 0, 0, 123, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'S', 121, 9, 0, 0, 246, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 245, 255, 0, 0, 169, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'T', 151, 9, 0, 0, 182, 0, 0, 0, 191, 2, 0, 0, 184, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 194, 0, 'L', 'N', 172, 9, 0, 0, 218, 0, 0, 0, 191, 2, 0, 0, 219, 0, 0, 0, 34, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'N', 190, 9, 'G', 'G', 191, 9, 'B', 'T', 192, 9, 0, 0, 59, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 60, 1, 'X', 'X', 226, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'N', 239, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 114, 1, 'V', '_', 227, 9, 0, 0, 95, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'S', 237, 9, 0, 0, 90, 1, 0, 0, 91, 1, 'V', '_', 240, 9, 0, 0, 110, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 1, 0, 0, 123, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 145, 1, 0, 0, 154, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 166, 1, 0, 0, 180, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 229, 255, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 41, 10, 'C', 'V', 52, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 200, 1, 0, 0, 187, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 193, 1, 'D', 'S', 83, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 111, 10, 0, 0, 218, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 223, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 237, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'T', 99, 10, 0, 0, 243, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 246, 1, 0, 0, 2, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 6, 2, 0, 0, 15, 2, 0, 0, 191, 2, 'C', 'Q', 144, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 34, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 44, 2, 0, 0, 43, 2, 0, 0, 191, 2, 0, 0, 54, 2, 0, 0, 58, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 79, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 97, 2, 0, 0, 21, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 2, 'N', 'N', 169, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'U', 190, 10, 'Y', 'Y', 170, 10, 'B', 'T', 171, 10, 0, 0, 117, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 119, 2, 0, 0, 121, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 126, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 2, 'D', 'S', 218, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'C', 234, 10, 0, 0, 134, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 142, 2, '_', '_', 235, 10, 'D', 'T', 236, 10, 0, 0, 152, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 153, 2, 'R', 'R', 254, 10, 'C', '_', 255, 10, 0, 0, 161, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 212, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 210, 255, 'G', 'L', 50, 11, 0, 0, 191, 2, 'H', 'U', 56, 11, 'A', 'U', 73, 11, 'X', 'X', 94, 11, 'E', 'O', 109, 11, 0, 0, 221, 0, 0, 0, 191, 2, 'M', 'S', 120, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 51, 1, 'E', 'I', 147, 11, 'O', 'T', 152, 11, 0, 0, 191, 2, 'A', 'R', 158, 11, 0, 0, 191, 2, 'E', 'O', 209, 11, 'A', 'U', 240, 11, 'E', 'I', 8, 12, 'N', 'N', 21, 12, 'A', 'A', 30, 12, 0, 0, 15, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 17, 0, 0, 0, 63, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 70, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 249, 255, 0, 0, 76, 0, 0, 0, 87, 0, 0, 0, 92, 0, 0, 0, 120, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 144, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 157, 0, 'C', 'P', 95, 11, 0, 0, 187, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 190, 0, 0, 0, 199, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 209, 0, 0, 0, 249, 0, 'C', 'V', 127, 11, 0, 0, 19, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 1, 0, 0, 253, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 251, 0, 0, 0, 191, 2, 0, 0, 16, 1, 0, 0, 98, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 104, 1, 0, 0, 137, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 231, 255, 'C', 'R', 176, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 192, 11, 0, 0, 169, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 177, 1, 'C', 'C', 203, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 196, 1, 'E', 'I', 204, 11, 0, 0, 188, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 1, 'A', 'T', 220, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 10, 2, 0, 0, 210, 1, 0, 0, 191, 2, 0, 0, 216, 1, 0, 0, 219, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 250, 1, 0, 0, 14, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'P', 5, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 41, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 64, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 81, 2, 0, 0, 217, 255, 0, 0, 23, 2, 0, 0, 191, 2, 0, 0, 24, 2, 'M', 'M', 13, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 114, 2, 'P', 'P', 14, 12, 'O', 'T', 15, 12, 0, 0, 106, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 2, 'B', 'I', 22, 12, 0, 0, 130, 2, 0, 0, 191, 2, 0, 0, 132, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 141, 2, 'R', 'R', 31, 12, 'B', 'I', 32, 12, 0, 0, 158, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 162, 2, 'C', 'S', 65, 12, 0, 0, 191, 2, 'H', 'O', 82, 12, 'A', 'E', 141, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 222, 0, 0, 0, 191, 2, 0, 0, 243, 0, 0, 0, 29, 1, 0, 0, 191, 2, 0, 0, 36, 1, 'A', 'E', 169, 12, 'O', 'O', 197, 12, 'P', 'R', 208, 12, 'A', 'R', 211, 12, 0, 0, 191, 2, 'E', 'O', 229, 12, 'Q', 'T', 11, 13, 'A', 'E', 25, 13, 0, 0, 191, 2, 'A', 'E', 46, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 188, 2, 0, 0, 8, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 26, 0, 0, 0, 66, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 90, 12, 'U', 'U', 93, 12, 'P', 'P', 104, 12, 'C', 'S', 112, 12, 'M', 'M', 94, 12, 'N', 'N', 95, 12, '_', '_', 96, 12, 'A', 'G', 97, 12, 0, 0, 80, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 84, 0, 'L', 'R', 105, 12, 0, 0, 89, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 93, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'T', 129, 12, 0, 0, 94, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 95, 0, 'Y', 'Y', 146, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'N', 155, 12, '_', '_', 147, 12, 'M', 'S', 148, 12, 0, 0, 127, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 0, 0, 0, 129, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 244, 255, 0, 0, 73, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'D', 174, 12, 'I', 'I', 175, 12, 'U', 'U', 176, 12, 'M', 'M', 177, 12, 'B', 'T', 178, 12, 0, 0, 97, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 99, 1, 'M', 'M', 198, 12, 'A', 'I', 199, 12, 0, 0, 131, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 132, 1, 0, 0, 157, 1, 0, 0, 191, 2, 0, 0, 160, 1, 0, 0, 179, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 195, 1, 'A', 'P', 240, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'W', 'W', 0, 13, 0, 0, 211, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 220, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 231, 1, 0, 0, 233, 1, '_', '_', 1, 13, 'F', 'N', 2, 13, 0, 0, 11, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 12, 2, 'L', 'L', 15, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 221, 255, 'W', '_', 16, 13, 0, 0, 59, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 68, 2, 'B', 'B', 30, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 2, 'L', 'L', 31, 13, 'E', 'E', 32, 13, 'S', '_', 33, 13, 0, 0, 104, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 102, 2, 0, 0, 155, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 168, 2, 'O', 'U', 70, 13, 'I', 'I', 80, 13, 0, 0, 195, 0, 0, 0, 242, 255, 0, 0, 191, 2, 'O', 'O', 100, 13, 0, 0, 4, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'Y', 111, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 198, 1, 0, 0, 191, 2, 'E', 'E', 155, 13, 'C', 'Y', 173, 13, 'R', 'R', 203, 13, 0, 0, 131, 2, 0, 0, 78, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 77, 13, 'R', 'S', 78, 13, 0, 0, 110, 0, 0, 0, 116, 0, 'A', 'S', 81, 13, 0, 0, 143, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 149, 0, 'U', 'U', 101, 13, 'R', 'R', 102, 13, '_', '_', 103, 13, 'M', 'S', 104, 13, 0, 0, 240, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 241, 0, 'S', 'S', 136, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 103, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 120, 1, 'T', 'T', 137, 13, 'E', 'E', 138, 13, 'R', 'R', 139, 13, '_', '_', 140, 13, 'H', 'U', 141, 13, 0, 0, 67, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 71, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 82, 1, 'P', 'P', 156, 13, 'L', 'L', 157, 13, 'I', 'I', 158, 13, 'C', 'C', 159, 13, 'A', 'A', 160, 13, 'T', '_', 161, 13, 0, 0, 239, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 238, 1, 0, 0, 17, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 220, 255, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 196, 13, 'T', 'T', 197, 13, 'E', 'E', 198, 13, 'M', 'M', 199, 13, '_', '_', 200, 13, 'T', 'U', 201, 13, 0, 0, 100, 2, 0, 0, 215, 255, 'A', 'I', 204, 13, 0, 0, 122, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 213, 255, 'A', 'U', 233, 13, 0, 0, 141, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 241, 255, 0, 0, 191, 2, 0, 0, 1, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 62, 1, 'A', 'E', 25, 14, 0, 0, 191, 2, 0, 0, 148, 1, 'A', 'E', 30, 14, 0, 0, 191, 2, 0, 0, 226, 1, 'E', 'U', 35, 14, 0, 0, 115, 2, 0, 0, 191, 2, 0, 0, 160, 2, 0, 0, 57, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 69, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 254, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 1, 14, 0, 0, 81, 0, 0, 0, 191, 2, 0, 0, 102, 0, 'R', 'R', 2, 14, 'E', 'E', 3, 14, 'N', 'N', 4, 14, 'T', 'T', 5, 14, '_', '_', 6, 14, 'D', 'U', 7, 14, 0, 0, 109, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 0, 0, 0, 191, 2, 0, 0, 112, 0, 0, 0, 114, 0, 0, 0, 65, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 102, 1, 0, 0, 178, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 228, 255, 'R', 'S', 52, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'L', 54, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 92, 2, 0, 0, 27, 2, 0, 0, 224, 255, 'E', '_', 55, 14, 0, 0, 57, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'T', 82, 14, 0, 0, 66, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 89, 14, 'I', 'I', 90, 14, '_', '_', 91, 14, 'H', 'Y', 92, 14, 0, 0, 71, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 73, 2, 0, 0, 191, 2, 0, 0, 76, 2, 'O', 'O', 131, 14, 'E', 'O', 139, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 234, 0, 0, 0, 6, 1, 0, 0, 240, 255, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 150, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 171, 1, 0, 0, 191, 2, 'E', 'E', 159, 14, 'Q', 'U', 167, 14, 'I', 'R', 172, 14, 0, 0, 154, 2, 0, 0, 191, 2, 0, 0, 172, 2, 'L', 'L', 132, 14, 'U', 'U', 133, 14, 'M', 'M', 134, 14, 'N', 'N', 135, 14, '_', '_', 136, 14, 'C', 'D', 137, 14, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 142, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 153, 0, 0, 0, 74, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 109, 1, 'F', 'L', 160, 14, 0, 0, 55, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 225, 1, 0, 0, 74, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 2, 0, 0, 93, 2, 0, 0, 116, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 123, 2, 'U', 'V', 203, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 239, 255, 0, 0, 32, 1, 0, 0, 52, 1, 'A', 'A', 205, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 224, 1, 'Q', 'Q', 231, 14, 0, 0, 105, 2, 0, 0, 149, 2, 0, 0, 31, 0, 0, 0, 34, 0, 'S', 'S', 206, 14, 'T', 'T', 207, 14, 'E', 'E', 208, 14, 'R', 'R', 209, 14, '_', '_', 210, 14, 'L', 'S', 211, 14, 0, 0, 69, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 219, 14, 'L', 'L', 220, 14, '_', '_', 221, 14, 'C', 'K', 222, 14, 0, 0, 78, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 80, 1, 'L', 'L', 232, 14, '_', '_', 233, 14, 'B', 'T', 234, 14, 0, 0, 62, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 253, 14, 'I', 'I', 254, 14, '_', '_', 255, 14, 'M', 'S', 0, 15, 0, 0, 70, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 69, 2, 0, 0, 32, 0, 0, 0, 191, 2, 0, 0, 97, 0, 'A', 'E', 26, 15, 0, 0, 165, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 31, 15, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'E', 52, 15, 0, 0, 191, 2, 0, 0, 191, 2, 'Q', 'U', 68, 15, 0, 0, 126, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 136, 0, 'S', 'S', 32, 15, 'T', 'T', 33, 15, 'E', 'E', 34, 15, 'R', 'R', 35, 15, '_', '_', 36, 15, 'G', 'U', 37, 15, 0, 0, 66, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 68, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 70, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 76, 1, 0, 0, 191, 2, 0, 0, 83, 1, 0, 0, 173, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 57, 15, 'C', 'C', 58, 15, 'E', 'E', 59, 15, 'N', 'N', 60, 15, 'T', 'T', 61, 15, 'I', 'I', 62, 15, 'L', 'L', 63, 15, 'E', 'E', 64, 15, '_', '_', 65, 15, 'C', 'D', 66, 15, 0, 0, 227, 255, 0, 0, 226, 255, 'L', 'L', 73, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 90, 2, '_', '_', 74, 15, 'A', 'T', 75, 15, 0, 0, 60, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 75, 2, 0, 0, 138, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 239, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 217, 1, 'Q', 'T', 113, 15, 0, 0, 191, 2, 0, 0, 133, 2, 'L', 'L', 117, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 83, 2, '_', '_', 118, 15, 'B', 'S', 119, 15, 0, 0, 61, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 67, 2, 'O', 'U', 154, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'G', 161, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 183, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 248, 1, 'Q', 'T', 203, 15, 0, 0, 98, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 113, 0, 'N', 'N', 162, 15, 'O', 'O', 163, 15, 'R', 'R', 164, 15, 'E', 'E', 165, 15, '_', '_', 166, 15, 'D', 'S', 167, 15, 0, 0, 247, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 248, 0, 'S', 'S', 184, 15, 'T', 'T', 185, 15, 'E', 'E', 186, 15, 'R', 'R', 187, 15, '_', '_', 188, 15, 'S', 'S', 189, 15, 'S', 'S', 190, 15, 'L', 'L', 191, 15, '_', '_', 192, 15, 'C', 'C', 193, 15, 'A', 'I', 194, 15, 0, 0, 75, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 77, 1, 0, 0, 63, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 82, 2, 0, 0, 96, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 224, 15, 0, 0, 141, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'T', 239, 15, 'S', 'X', 233, 15, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 1, 0, 0, 79, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 92, 1, 0, 0, 20, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 84, 2, 0, 0, 167, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 65, 2, 'A', 'A', 15, 16, 'S', 'X', 16, 16, 0, 0, 64, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, '_', '_', 22, 16, 'Q', 'U', 23, 16, 0, 0, 89, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'P', 'S', 28, 16, 0, 0, 93, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 94, 1, 'A', 'A', 33, 16, 'S', 'X', 34, 16, 0, 0, 84, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 1, }; static uchar symbols_map[15316]= { 0, 0, 191, 2, '!', '|', 29, 0, '<', 'X', 157, 0, 'A', 'Y', 24, 1, 'A', 'W', 231, 2, 'A', 'W', 105, 4, 'A', 'W', 52, 6, 'C', 'Z', 90, 8, 'A', 'V', 47, 10, 'A', 'Y', 46, 11, 'C', 'U', 40, 12, 'C', 'V', 185, 12, 'C', 'W', 75, 13, 'A', 'U', 147, 13, 'A', 'S', 228, 13, 'D', 'U', 44, 14, 'C', 'S', 86, 14, 'C', 'S', 156, 14, 'E', 'S', 204, 14, 'M', 'M', 219, 14, 0, 0, 166, 0, 0, 0, 85, 1, 0, 0, 86, 1, 'M', 'M', 237, 14, 0, 0, 168, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 81, 1, 0, 0, 3, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 0, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, '<', '>', 121, 0, 0, 0, 191, 2, '=', '>', 124, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'T', 126, 0, 0, 0, 50, 0, 0, 0, 191, 2, 0, 0, 151, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'S', 128, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 130, 1, 'F', 'R', 144, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 120, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 185, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 190, 2, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 23, 0, 0, 0, 27, 0, 0, 0, 242, 0, 0, 0, 191, 2, 0, 0, 244, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 252, 0, 0, 0, 18, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 21, 1, 0, 0, 146, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 149, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 158, 1, 0, 0, 7, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'V', 186, 0, 0, 0, 42, 0, 0, 0, 104, 0, 'A', 'I', 227, 0, 0, 0, 170, 0, 0, 0, 211, 0, 0, 0, 223, 0, 0, 0, 191, 2, 'N', 'P', 236, 0, 0, 0, 191, 2, 0, 0, 30, 1, 0, 0, 191, 2, 0, 0, 112, 1, 0, 0, 139, 1, 'N', 'U', 239, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 247, 0, 'E', 'S', 6, 1, 0, 0, 191, 2, 0, 0, 147, 2, 0, 0, 164, 2, 0, 0, 191, 2, 'M', 'O', 21, 1, 0, 0, 11, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 16, 0, 0, 0, 191, 2, 'D', 'Y', 205, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 24, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 33, 0, 0, 0, 21, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 0, 0, 0, 124, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 130, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 150, 0, 0, 0, 8, 1, 0, 0, 191, 2, 0, 0, 20, 1, 0, 0, 150, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 162, 1, 0, 0, 208, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 5, 2, 0, 0, 30, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 56, 2, 0, 0, 191, 2, 0, 0, 77, 2, 0, 0, 186, 2, 0, 0, 191, 2, 0, 0, 184, 2, 0, 0, 30, 0, 'L', 'Y', 49, 1, 'A', 'U', 80, 1, 'A', 'U', 109, 1, 'A', 'X', 136, 1, 'A', 'U', 178, 1, 0, 0, 225, 0, 'A', 'O', 199, 1, 'N', 'N', 219, 1, 'O', 'S', 252, 1, 'E', 'I', 1, 2, 'A', 'O', 6, 2, 0, 0, 113, 1, 'A', 'U', 59, 2, 'N', 'V', 80, 2, 'A', 'R', 89, 2, 0, 0, 191, 2, 'E', 'O', 121, 2, 'H', 'T', 154, 2, 'E', 'Y', 175, 2, 'N', 'S', 210, 2, 0, 0, 165, 2, 'A', 'O', 216, 2, 0, 0, 183, 2, 0, 0, 187, 2, 0, 0, 43, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'T', 63, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 51, 0, 0, 0, 45, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 46, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 0, 'L', 'S', 101, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 62, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 71, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 74, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 0, 0, 0, 53, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 56, 0, 'T', 'T', 130, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 139, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 147, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 154, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 155, 0, 'A', 'E', 131, 1, 0, 0, 118, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 122, 0, 0, 0, 159, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 160, 0, 0, 0, 191, 2, 'D', 'U', 160, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 0, 0, 0, 171, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 174, 0, 0, 0, 197, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 202, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 216, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 217, 0, 'R', 'S', 214, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 233, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'U', 216, 1, 0, 0, 230, 0, 0, 0, 231, 0, 0, 0, 236, 0, 0, 0, 191, 2, 0, 0, 238, 0, 'T', 'T', 220, 1, '1', 'O', 221, 1, 0, 0, 9, 1, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0, 12, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 13, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 17, 1, 0, 0, 27, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 28, 1, 0, 0, 31, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 33, 1, 0, 0, 35, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'F', 'S', 21, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'K', 'S', 35, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 44, 2, 0, 0, 41, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 42, 1, 0, 0, 44, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 1, 0, 0, 49, 1, 0, 0, 191, 2, 0, 0, 53, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 57, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 58, 1, 0, 0, 61, 1, 0, 0, 121, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 138, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 142, 1, 0, 0, 152, 1, 0, 0, 191, 2, 0, 0, 153, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 165, 1, 'G', 'T', 107, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 185, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 192, 1, 0, 0, 170, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 174, 1, 'A', 'A', 132, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 142, 2, 'D', 'L', 133, 2, 0, 0, 209, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 213, 1, 0, 0, 1, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 8, 2, 0, 0, 33, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 38, 2, 0, 0, 42, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'F', 'M', 167, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 86, 2, 0, 0, 46, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 47, 2, 0, 0, 109, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'E', 196, 2, 'E', 'M', 201, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 127, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 129, 2, 0, 0, 110, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 2, 0, 0, 112, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 113, 2, 0, 0, 135, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 148, 2, 0, 0, 169, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 171, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 173, 2, 0, 0, 177, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 180, 2, 'D', 'S', 254, 2, 'E', 'T', 14, 3, 'A', 'Y', 30, 3, 0, 0, 191, 2, 'L', 'V', 60, 3, 'A', 'O', 77, 3, 'R', 'R', 110, 3, 0, 0, 237, 0, 'N', 'N', 126, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 139, 3, 'A', 'Y', 186, 3, 'A', 'E', 211, 3, 'R', 'W', 216, 3, 'H', 'U', 222, 3, 'U', 'U', 236, 3, 'A', 'T', 242, 3, 'H', 'W', 33, 4, 0, 0, 101, 2, 'N', 'S', 62, 4, 0, 0, 156, 2, 'H', 'R', 89, 4, 0, 0, 12, 0, 0, 0, 191, 2, 0, 0, 13, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 18, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 0, 0, 0, 37, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 44, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 49, 0, 0, 0, 52, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'E', 55, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 106, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 117, 0, 0, 0, 58, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 65, 0, 0, 0, 162, 0, 0, 0, 163, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'E', 71, 3, 'N', 'R', 72, 3, 0, 0, 179, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 0, 0, 0, 196, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 200, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'X', 92, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'U', 99, 3, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'U', 106, 3, 0, 0, 203, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 204, 0, 0, 0, 205, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 208, 0, 0, 0, 212, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 215, 0, 'A', 'O', 111, 3, 0, 0, 226, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 228, 0, 'D', 'O', 127, 3, 0, 0, 254, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 2, 1, 0, 0, 3, 1, 'A', 'V', 150, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'M', 'N', 172, 3, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'C', 174, 3, 0, 0, 39, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 43, 1, 0, 0, 45, 1, 0, 0, 47, 1, 'A', 'K', 175, 3, 0, 0, 50, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 55, 1, 0, 0, 87, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 101, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 106, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 117, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 118, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 119, 1, 0, 0, 122, 1, 0, 0, 191, 2, 0, 0, 125, 1, 0, 0, 191, 2, 0, 0, 127, 1, 0, 0, 159, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 163, 1, 0, 0, 191, 2, 0, 0, 167, 1, 0, 0, 182, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 201, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 202, 1, 'E', 'I', 237, 3, 0, 0, 204, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 205, 1, 'I', 'N', 6, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'U', 12, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 255, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 0, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 13, 2, 0, 0, 206, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 207, 1, 0, 0, 212, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 222, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 242, 1, 0, 0, 191, 2, 0, 0, 252, 1, 0, 0, 32, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 39, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 49, 4, 0, 0, 94, 2, 0, 0, 191, 2, 0, 0, 96, 2, 'G', 'R', 50, 4, 0, 0, 51, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 78, 2, 'I', 'T', 68, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 80, 4, 0, 0, 137, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 143, 2, 0, 0, 146, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 151, 2, 'E', 'I', 100, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 182, 2, 0, 0, 174, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 2, 'C', 'T', 128, 4, 'A', 'I', 146, 4, 'H', 'U', 175, 4, 'E', 'O', 191, 4, 'L', 'X', 202, 4, 'A', 'O', 243, 4, 'L', 'R', 10, 5, 0, 0, 232, 0, 'G', 'S', 17, 5, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 49, 5, 'A', 'O', 60, 5, 'E', 'U', 85, 5, 'F', 'T', 102, 5, 'A', 'L', 117, 5, 0, 0, 191, 2, 'E', 'O', 129, 5, 'C', 'Y', 180, 5, 0, 0, 103, 2, 'N', 'P', 37, 6, 0, 0, 157, 2, 'I', 'I', 44, 6, 0, 0, 10, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 19, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 28, 0, 0, 0, 35, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 36, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'N', 155, 4, 0, 0, 39, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'L', 163, 4, 0, 0, 40, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 41, 0, 0, 0, 59, 0, 0, 0, 68, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 70, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'M', 189, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 105, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 115, 0, 0, 0, 77, 0, 0, 0, 86, 0, 0, 0, 137, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 152, 0, 0, 0, 161, 0, 0, 0, 191, 2, 'A', 'G', 215, 4, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 176, 0, 0, 0, 177, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 180, 0, 0, 0, 191, 2, 'C', 'P', 222, 4, 0, 0, 164, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 172, 0, 0, 0, 183, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 188, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'O', 236, 4, 0, 0, 191, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 192, 0, 0, 0, 198, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 201, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'O', 2, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 214, 0, 'A', 'A', 3, 5, 'T', 'T', 4, 5, '4', '8', 5, 5, 0, 0, 206, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 207, 0, 0, 0, 224, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 227, 0, 0, 0, 245, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 250, 0, 'F', 'S', 30, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'S', 44, 5, 0, 0, 0, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 5, 1, 0, 0, 23, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 24, 1, 0, 0, 40, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 46, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 54, 1, 0, 0, 63, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'M', 75, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 115, 1, 0, 0, 96, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 100, 1, 0, 0, 126, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 136, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 143, 1, 0, 0, 147, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 151, 1, 0, 0, 191, 2, 0, 0, 156, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 161, 1, 0, 0, 172, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 175, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 183, 1, 'G', 'V', 140, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 168, 5, 0, 0, 221, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 228, 1, 0, 0, 229, 1, 0, 0, 230, 1, 0, 0, 191, 2, 'A', 'L', 156, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 247, 1, 0, 0, 249, 1, 0, 0, 191, 2, 0, 0, 254, 1, 0, 0, 232, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 240, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 235, 1, 0, 0, 3, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 7, 2, 0, 0, 16, 2, 0, 0, 191, 2, 'C', 'T', 203, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'M', 235, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 40, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'U', 248, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'R', 16, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 99, 2, 0, 0, 19, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'V', 221, 5, 0, 0, 191, 2, 0, 0, 31, 2, 0, 0, 26, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 29, 2, 'N', 'N', 242, 5, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 37, 2, 'A', 'E', 243, 5, 0, 0, 35, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 36, 2, 0, 0, 45, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 48, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'R', 11, 6, 0, 0, 49, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 50, 2, 'R', 'T', 34, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 52, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 89, 2, 0, 0, 80, 2, 0, 0, 191, 2, 0, 0, 85, 2, 'I', 'L', 40, 6, 0, 0, 191, 2, 0, 0, 144, 2, 0, 0, 138, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 2, 'N', 'T', 45, 6, 0, 0, 176, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 178, 2, 'C', 'U', 75, 6, 'E', 'O', 94, 6, 'A', 'U', 105, 6, 'E', 'Y', 160, 6, 'N', 'X', 208, 6, 'O', 'O', 233, 6, 0, 0, 220, 0, 'A', 'I', 241, 6, 'G', 'T', 250, 6, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 27, 7, 'I', 'O', 42, 7, 'A', 'U', 49, 7, 'P', 'U', 124, 7, 'A', 'R', 130, 7, 0, 0, 203, 1, 'E', 'O', 179, 7, 'C', 'Y', 240, 7, 'H', 'R', 25, 8, 'N', 'S', 36, 8, 'A', 'I', 45, 8, 'I', 'R', 80, 8, 0, 0, 9, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 14, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 20, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 29, 0, 0, 0, 38, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 47, 0, 0, 0, 54, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 126, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 140, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 0, 'N', 'R', 127, 6, 'G', 'N', 132, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 64, 0, 0, 0, 60, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 61, 0, 'L', 'U', 143, 6, 'M', 'P', 153, 6, 'T', 'V', 157, 6, 0, 0, 75, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 79, 0, 0, 0, 85, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 0, 0, 0, 100, 0, 0, 0, 191, 2, 0, 0, 103, 0, 'C', 'L', 181, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 204, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 158, 0, 'I', 'L', 191, 6, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 195, 6, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 135, 0, 0, 0, 131, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 132, 0, 0, 0, 133, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 134, 0, 'A', 'C', 205, 6, 0, 0, 145, 0, 0, 0, 191, 2, 0, 0, 146, 0, 0, 0, 173, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 178, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'P', 219, 6, 0, 0, 185, 0, 0, 0, 191, 2, 0, 0, 186, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 193, 0, 'L', 'R', 234, 6, 0, 0, 210, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 213, 0, 0, 0, 229, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 235, 0, 0, 0, 246, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'V', 8, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 1, 0, 0, 255, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 7, 1, 0, 0, 14, 1, 0, 0, 191, 2, 0, 0, 26, 1, 0, 0, 37, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 38, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 56, 1, 0, 0, 105, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 116, 1, 0, 0, 124, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 129, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', '_', 70, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 144, 1, 'A', 'Y', 99, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 135, 1, 0, 0, 133, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 134, 1, 0, 0, 155, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 164, 1, 'C', 'R', 148, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 184, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 186, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 164, 7, 0, 0, 168, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 176, 1, 0, 0, 190, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 194, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'F', 175, 7, 0, 0, 197, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 199, 1, 'B', 'V', 190, 7, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'U', 'W', 237, 7, 0, 0, 214, 1, 0, 0, 215, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 227, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'L', 211, 7, 0, 0, 241, 1, 0, 0, 191, 2, 'T', 'T', 221, 7, 0, 0, 251, 1, 0, 0, 191, 2, 0, 0, 253, 1, 'A', 'I', 212, 7, 0, 0, 234, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 236, 1, 'A', 'O', 222, 7, 0, 0, 244, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 245, 1, 0, 0, 4, 2, 0, 0, 191, 2, 0, 0, 9, 2, 0, 0, 18, 2, 0, 0, 191, 2, 0, 0, 28, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 53, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 87, 2, 'B', 'S', 7, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 98, 2, 0, 0, 91, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 95, 2, 0, 0, 124, 2, 0, 0, 118, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 125, 2, 'I', 'K', 42, 8, 0, 0, 191, 2, 0, 0, 145, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 150, 2, 0, 0, 136, 2, 0, 0, 191, 2, 0, 0, 139, 2, 'R', 'R', 54, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'S', 78, 8, 'C', 'Y', 55, 8, 0, 0, 159, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 163, 2, 0, 0, 166, 2, 0, 0, 167, 2, 0, 0, 179, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 2, 'A', 'O', 114, 8, 'A', 'U', 153, 8, 'N', 'X', 190, 8, 'U', 'U', 221, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 15, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'O', 225, 8, 'A', 'O', 5, 9, 'A', 'V', 44, 9, 'P', 'V', 66, 9, 'A', 'R', 73, 9, 0, 0, 191, 2, 'E', 'O', 122, 9, 'C', 'W', 173, 9, 'I', 'R', 209, 9, 'N', 'T', 5, 10, 0, 0, 161, 2, 0, 0, 170, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 2, 0, 0, 55, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 67, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'N', 129, 8, 0, 0, 73, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'T', 'T', 143, 8, 'A', 'I', 144, 8, 0, 0, 99, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 101, 0, 'T', 'Y', 174, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 148, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 156, 0, 'A', 'E', 180, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 125, 0, 'B', 'F', 185, 8, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 123, 0, 0, 0, 119, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 121, 0, 0, 0, 169, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'T', 201, 8, 0, 0, 182, 0, 0, 0, 191, 2, 0, 0, 184, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 194, 0, 'L', 'N', 222, 8, 0, 0, 218, 0, 0, 0, 191, 2, 0, 0, 219, 0, 0, 0, 34, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'N', 240, 8, 'G', 'G', 241, 8, 'B', 'T', 242, 8, 0, 0, 59, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 60, 1, 'X', 'X', 20, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'N', 33, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 114, 1, 'V', '_', 21, 9, 0, 0, 95, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'S', 31, 9, 0, 0, 90, 1, 0, 0, 91, 1, 'V', '_', 34, 9, 0, 0, 110, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 1, 0, 0, 123, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 140, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 145, 1, 0, 0, 154, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 166, 1, 0, 0, 180, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 91, 9, 'C', 'V', 102, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 200, 1, 0, 0, 187, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 193, 1, 'D', 'S', 133, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'W', 161, 9, 0, 0, 218, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 223, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 237, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'T', 149, 9, 0, 0, 243, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 246, 1, 0, 0, 2, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 6, 2, 0, 0, 15, 2, 0, 0, 191, 2, 'C', 'Q', 194, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 34, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 44, 2, 0, 0, 43, 2, 0, 0, 191, 2, 0, 0, 54, 2, 0, 0, 58, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 79, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 97, 2, 0, 0, 21, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 25, 2, 'N', 'N', 219, 9, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'U', 240, 9, 'Y', 'Y', 220, 9, 'B', 'T', 221, 9, 0, 0, 117, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 119, 2, 0, 0, 121, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 126, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 2, 'D', 'S', 12, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'C', 'C', 28, 10, 0, 0, 134, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 142, 2, '_', '_', 29, 10, 'D', 'T', 30, 10, 0, 0, 152, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 153, 2, 'G', 'L', 69, 10, 0, 0, 191, 2, 'H', 'O', 75, 10, 'A', 'U', 86, 10, 'X', 'X', 107, 10, 'E', 'O', 122, 10, 0, 0, 221, 0, 0, 0, 191, 2, 'M', 'S', 133, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 51, 1, 'E', 'I', 160, 10, 0, 0, 137, 1, 0, 0, 191, 2, 'A', 'R', 165, 10, 0, 0, 191, 2, 'E', 'O', 216, 10, 'A', 'T', 247, 10, 'E', 'I', 14, 11, 'N', 'N', 27, 11, 'A', 'A', 36, 11, 0, 0, 15, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 17, 0, 0, 0, 63, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 83, 10, 0, 0, 76, 0, 0, 0, 87, 0, 0, 0, 92, 0, 0, 0, 120, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 144, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 157, 0, 'C', 'P', 108, 10, 0, 0, 187, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 190, 0, 0, 0, 199, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 209, 0, 0, 0, 249, 0, 'C', 'V', 140, 10, 0, 0, 19, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 22, 1, 0, 0, 253, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 251, 0, 0, 0, 191, 2, 0, 0, 16, 1, 0, 0, 98, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 104, 1, 'C', 'R', 183, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'O', 199, 10, 0, 0, 169, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 177, 1, 'C', 'C', 210, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 196, 1, 'E', 'I', 211, 10, 0, 0, 188, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 189, 1, 'A', 'T', 227, 10, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 10, 2, 0, 0, 210, 1, 0, 0, 191, 2, 0, 0, 216, 1, 0, 0, 219, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 250, 1, 0, 0, 14, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'P', 11, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 41, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 64, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 81, 2, 0, 0, 23, 2, 0, 0, 191, 2, 0, 0, 24, 2, 'M', 'M', 19, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 114, 2, 'P', 'P', 20, 11, 'O', 'T', 21, 11, 0, 0, 106, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 107, 2, 'B', 'I', 28, 11, 0, 0, 130, 2, 0, 0, 191, 2, 0, 0, 132, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 141, 2, 'R', 'R', 37, 11, 'B', 'I', 38, 11, 0, 0, 158, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 162, 2, 'C', 'S', 71, 11, 0, 0, 191, 2, 'H', 'O', 88, 11, 'A', 'E', 147, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 222, 0, 0, 0, 191, 2, 0, 0, 243, 0, 0, 0, 29, 1, 0, 0, 191, 2, 0, 0, 36, 1, 'A', 'E', 161, 11, 'O', 'O', 189, 11, 'P', 'R', 200, 11, 'A', 'R', 203, 11, 0, 0, 191, 2, 'E', 'O', 221, 11, 'Q', 'Q', 3, 12, 'A', 'E', 14, 12, 0, 0, 191, 2, 'A', 'E', 35, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 188, 2, 0, 0, 8, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 26, 0, 0, 0, 66, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 96, 11, 'U', 'U', 99, 11, 'P', 'P', 110, 11, 'C', 'S', 118, 11, 'M', 'M', 100, 11, 'N', 'N', 101, 11, '_', '_', 102, 11, 'A', 'G', 103, 11, 0, 0, 80, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 84, 0, 'L', 'R', 111, 11, 0, 0, 89, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 93, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'I', 'T', 135, 11, 0, 0, 94, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 95, 0, 'Y', 'Y', 152, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 129, 0, '_', '_', 153, 11, 'M', 'S', 154, 11, 0, 0, 127, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 128, 0, 0, 0, 73, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'D', 'D', 166, 11, 'I', 'I', 167, 11, 'U', 'U', 168, 11, 'M', 'M', 169, 11, 'B', 'T', 170, 11, 0, 0, 97, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 99, 1, 'M', 'M', 190, 11, 'A', 'I', 191, 11, 0, 0, 131, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 132, 1, 0, 0, 157, 1, 0, 0, 191, 2, 0, 0, 160, 1, 0, 0, 179, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 181, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 195, 1, 'A', 'P', 232, 11, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'W', 'W', 248, 11, 0, 0, 211, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 220, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 231, 1, 0, 0, 233, 1, '_', '_', 249, 11, 'F', 'N', 250, 11, 0, 0, 11, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 12, 2, 'L', 'L', 4, 12, 'W', '_', 5, 12, 0, 0, 59, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 68, 2, 'B', 'B', 19, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 2, 'L', 'L', 20, 12, 'E', 'E', 21, 12, 'S', '_', 22, 12, 0, 0, 104, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 102, 2, 0, 0, 155, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 168, 2, 'O', 'U', 59, 12, 'I', 'I', 69, 12, 0, 0, 195, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'O', 'O', 89, 12, 0, 0, 4, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'Y', 100, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 198, 1, 0, 0, 191, 2, 'E', 'E', 144, 12, 'C', 'Y', 162, 12, 0, 0, 122, 2, 0, 0, 131, 2, 0, 0, 78, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 66, 12, 'R', 'S', 67, 12, 0, 0, 110, 0, 0, 0, 116, 0, 'A', 'S', 70, 12, 0, 0, 143, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 149, 0, 'U', 'U', 90, 12, 'R', 'R', 91, 12, '_', '_', 92, 12, 'M', 'S', 93, 12, 0, 0, 240, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 241, 0, 'S', 'S', 125, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 103, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 120, 1, 'T', 'T', 126, 12, 'E', 'E', 127, 12, 'R', 'R', 128, 12, '_', '_', 129, 12, 'H', 'U', 130, 12, 0, 0, 67, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 71, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 82, 1, 'P', 'P', 145, 12, 'L', 'L', 146, 12, 'I', 'I', 147, 12, 'C', 'C', 148, 12, 'A', 'A', 149, 12, 'T', '_', 150, 12, 0, 0, 239, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 238, 1, 0, 0, 17, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 100, 2, 'A', 'U', 205, 12, 0, 0, 141, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 1, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 62, 1, 'A', 'E', 253, 12, 0, 0, 191, 2, 0, 0, 148, 1, 0, 0, 178, 1, 0, 0, 191, 2, 0, 0, 226, 1, 'E', 'U', 2, 13, 0, 0, 115, 2, 0, 0, 191, 2, 0, 0, 160, 2, 0, 0, 57, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 69, 0, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'N', 226, 12, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'R', 'R', 229, 12, 0, 0, 81, 0, 0, 0, 191, 2, 0, 0, 102, 0, 'R', 'R', 230, 12, 'E', 'E', 231, 12, 'N', 'N', 232, 12, 'T', 'T', 233, 12, '_', '_', 234, 12, 'D', 'U', 235, 12, 0, 0, 109, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 111, 0, 0, 0, 191, 2, 0, 0, 112, 0, 0, 0, 114, 0, 0, 0, 65, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 102, 1, 0, 0, 27, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'L', 'L', 19, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 92, 2, 'E', '_', 20, 13, 0, 0, 57, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'N', 'T', 47, 13, 0, 0, 66, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 54, 13, 'I', 'I', 55, 13, '_', '_', 56, 13, 'H', 'Y', 57, 13, 0, 0, 71, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 73, 2, 0, 0, 191, 2, 0, 0, 76, 2, 'O', 'O', 96, 13, 'E', 'O', 104, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 234, 0, 0, 0, 6, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 115, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 171, 1, 0, 0, 191, 2, 'E', 'E', 124, 13, 'Q', 'U', 132, 13, 'I', 'R', 137, 13, 0, 0, 154, 2, 0, 0, 191, 2, 0, 0, 172, 2, 'L', 'L', 97, 13, 'U', 'U', 98, 13, 'M', 'M', 99, 13, 'N', 'N', 100, 13, '_', '_', 101, 13, 'C', 'D', 102, 13, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 142, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 153, 0, 0, 0, 74, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 109, 1, 'F', 'L', 125, 13, 0, 0, 55, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 225, 1, 0, 0, 74, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 2, 0, 0, 93, 2, 0, 0, 116, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 123, 2, 'U', 'V', 168, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 32, 1, 0, 0, 52, 1, 'A', 'A', 170, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 224, 1, 'Q', 'Q', 196, 13, 0, 0, 105, 2, 0, 0, 149, 2, 0, 0, 31, 0, 0, 0, 34, 0, 'S', 'S', 171, 13, 'T', 'T', 172, 13, 'E', 'E', 173, 13, 'R', 'R', 174, 13, '_', '_', 175, 13, 'L', 'S', 176, 13, 0, 0, 69, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 184, 13, 'L', 'L', 185, 13, '_', '_', 186, 13, 'C', 'K', 187, 13, 0, 0, 78, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 80, 1, 'L', 'L', 197, 13, '_', '_', 198, 13, 'B', 'T', 199, 13, 0, 0, 62, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'S', 'S', 218, 13, 'I', 'I', 219, 13, '_', '_', 220, 13, 'M', 'S', 221, 13, 0, 0, 70, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 69, 2, 0, 0, 32, 0, 0, 0, 191, 2, 0, 0, 97, 0, 'A', 'E', 247, 13, 0, 0, 165, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 252, 13, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 173, 1, 0, 0, 191, 2, 0, 0, 191, 2, 'Q', 'U', 17, 14, 0, 0, 126, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 136, 0, 'S', 'S', 253, 13, 'T', 'T', 254, 13, 'E', 'E', 255, 13, 'R', 'R', 0, 14, '_', '_', 1, 14, 'G', 'U', 2, 14, 0, 0, 66, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 68, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 70, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 76, 1, 0, 0, 191, 2, 0, 0, 83, 1, 'L', 'L', 22, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 90, 2, '_', '_', 23, 14, 'A', 'T', 24, 14, 0, 0, 60, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 75, 2, 0, 0, 138, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 239, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 72, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 217, 1, 'Q', 'T', 62, 14, 0, 0, 191, 2, 0, 0, 133, 2, 'L', 'L', 66, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 83, 2, '_', '_', 67, 14, 'B', 'S', 68, 14, 0, 0, 61, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 67, 2, 'O', 'U', 103, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'G', 'G', 110, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'A', 132, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 248, 1, 'Q', 'T', 152, 14, 0, 0, 98, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 113, 0, 'N', 'N', 111, 14, 'O', 'O', 112, 14, 'R', 'R', 113, 14, 'E', 'E', 114, 14, '_', '_', 115, 14, 'D', 'S', 116, 14, 0, 0, 247, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 248, 0, 'S', 'S', 133, 14, 'T', 'T', 134, 14, 'E', 'E', 135, 14, 'R', 'R', 136, 14, '_', '_', 137, 14, 'S', 'S', 138, 14, 'S', 'S', 139, 14, 'L', 'L', 140, 14, '_', '_', 141, 14, 'C', 'C', 142, 14, 'A', 'I', 143, 14, 0, 0, 75, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 77, 1, 0, 0, 63, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 82, 2, 0, 0, 96, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'A', 'I', 173, 14, 0, 0, 141, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'E', 'T', 188, 14, 'S', 'X', 182, 14, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 108, 1, 0, 0, 79, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 92, 1, 0, 0, 20, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 84, 2, 0, 0, 167, 0, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 65, 2, 'A', 'A', 220, 14, 'S', 'X', 221, 14, 0, 0, 64, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, '_', '_', 227, 14, 'Q', 'U', 228, 14, 0, 0, 89, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 'P', 'S', 233, 14, 0, 0, 93, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 94, 1, 'A', 'A', 238, 14, 'S', 'X', 239, 14, 0, 0, 84, 1, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 191, 2, 0, 0, 88, 1, }; static unsigned int sql_functions_max_len=29; static unsigned int symbols_max_len=29; static SYMBOL *get_hash_symbol(const char *s, unsigned int len,bool function) { uchar *hash_map; const char *cur_str= s; if (len == 0) { DBUG_PRINT("warning", ("get_hash_symbol() received a request for a zero-length symbol, which is probably a mistake.")); return(NULL); } if (function){ if (len>sql_functions_max_len) return 0; hash_map= sql_functions_map; uint32 cur_struct= uint4korr(hash_map+((len-1)*4)); for (;;){ uchar first_char= (uchar)cur_struct; if (first_char == 0) { int16 ires= (int16)(cur_struct>>16); if (ires==array_elements(symbols)) return 0; SYMBOL *res; if (ires>=0) res= symbols+ires; else res= sql_functions-ires-1; uint count= (uint) (cur_str - s); return lex_casecmp(cur_str,res->name+count,len-count) ? 0 : res; } uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str]; if (cur_char<first_char) return 0; cur_struct>>=8; if (cur_char>(uchar)cur_struct) return 0; cur_struct>>=8; cur_struct= uint4korr(hash_map+ (((uint16)cur_struct + cur_char - first_char)*4)); cur_str++; } }else{ if (len>symbols_max_len) return 0; hash_map= symbols_map; uint32 cur_struct= uint4korr(hash_map+((len-1)*4)); for (;;){ uchar first_char= (uchar)cur_struct; if (first_char==0) { int16 ires= (int16)(cur_struct>>16); if (ires==array_elements(symbols)) return 0; SYMBOL *res= symbols+ires; uint count= (uint) (cur_str - s); return lex_casecmp(cur_str,res->name+count,len-count)!=0 ? 0 : res; } uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str]; if (cur_char<first_char) return 0; cur_struct>>=8; if (cur_char>(uchar)cur_struct) return 0; cur_struct>>=8; cur_struct= uint4korr(hash_map+ (((uint16)cur_struct + cur_char - first_char)*4)); cur_str++; } } } sql_time.h 0000644 00000016363 15156036131 0006544 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. Copyright (c) 2011, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TIME_INCLUDED #define SQL_TIME_INCLUDED #include "sql_basic_types.h" #include "my_time.h" #include "mysql_time.h" /* timestamp_type */ #include "sql_error.h" /* Sql_condition */ #include "structs.h" /* INTERVAL */ typedef enum enum_mysql_timestamp_type timestamp_type; typedef struct st_date_time_format DATE_TIME_FORMAT; typedef struct st_known_date_time_format KNOWN_DATE_TIME_FORMAT; /* Flags for calc_week() function. */ #define WEEK_MONDAY_FIRST 1 #define WEEK_YEAR 2 #define WEEK_FIRST_WEEKDAY 4 ulong convert_period_to_month(ulong period); ulong convert_month_to_period(ulong month); void set_current_date(THD *thd, MYSQL_TIME *to); bool time_to_datetime(MYSQL_TIME *ltime); bool get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code); bool str_to_datetime_with_warn(THD *thd, CHARSET_INFO *cs, const char *str, size_t length, MYSQL_TIME *l_time, date_mode_t flags); bool double_to_datetime_with_warn(THD *thd, double value, MYSQL_TIME *ltime, date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); bool decimal_to_datetime_with_warn(THD *thd, const my_decimal *value, MYSQL_TIME *ltime, date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr, MYSQL_TIME *ltime, date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); bool time_to_datetime(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt); bool time_to_datetime_with_warn(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt, date_conv_mode_t fuzzydate); inline void datetime_to_date(MYSQL_TIME *ltime) { DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE || ltime->time_type == MYSQL_TIMESTAMP_DATETIME); DBUG_ASSERT(ltime->neg == 0); ltime->second_part= ltime->hour= ltime->minute= ltime->second= 0; ltime->time_type= MYSQL_TIMESTAMP_DATE; } inline void date_to_datetime(MYSQL_TIME *ltime) { DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE || ltime->time_type == MYSQL_TIMESTAMP_DATETIME); DBUG_ASSERT(ltime->neg == 0); ltime->time_type= MYSQL_TIMESTAMP_DATETIME; } void make_truncated_value_warning(THD *thd, Sql_condition::enum_warning_level level, const ErrConv *str_val, timestamp_type time_type, const char *db_name, const char *table_name, const char *field_name); const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, timestamp_type type); bool my_TIME_to_str(const MYSQL_TIME *ltime, String *str, uint dec); /* MYSQL_TIME operations */ bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, const INTERVAL &interval, bool push_warn= true); bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, int l_sign, ulonglong *seconds_out, ulong *microseconds_out); int append_interval(String *str, interval_type int_type, const INTERVAL &interval); /** Calculate time difference between two MYSQL_TIME values and store the result as an out MYSQL_TIME value in MYSQL_TIMESTAMP_TIME format. The result can be outside of the supported TIME range. For example, calc_time_diff('2002-01-01 00:00:00', '2001-01-01 00:00:00') returns '8760:00:00'. So the caller might want to do check_time_range() or adjust_time_range_with_warn() on the result of a calc_time_diff() call. @param l_time1 - the minuend (TIME/DATE/DATETIME value) @param l_time2 - the subtrahend TIME/DATE/DATETIME value @param l_sign - +1 if absolute values are to be subtracted, or -1 if absolute values are to be added. @param[out] l_time3 - the result @param fuzzydate - flags @return true - if TIME_NO_ZERO_DATE was passed in flags and the result appeared to be '00:00:00.000000'. This is important when calc_time_diff() is called when calculating DATE_ADD(TIMEDIFF(...),...) @return false - otherwise */ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, int lsign, MYSQL_TIME *l_time3, date_mode_t fuzzydate); int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); void calc_time_from_sec(MYSQL_TIME *to, ulong seconds, ulong microseconds); uint calc_week(const MYSQL_TIME *l_time, uint week_behaviour, uint *year); int calc_weekday(long daynr,bool sunday_first_day_of_week); extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; extern LEX_CSTRING interval_type_to_name[]; static inline bool non_zero_hhmmssuu(const MYSQL_TIME *ltime) { return ltime->hour || ltime->minute || ltime->second || ltime->second_part; } static inline bool non_zero_YYMMDD(const MYSQL_TIME *ltime) { return ltime->year || ltime->month || ltime->day; } static inline bool non_zero_date(const MYSQL_TIME *ltime) { return non_zero_YYMMDD(ltime) || (ltime->time_type == MYSQL_TIMESTAMP_DATETIME && non_zero_hhmmssuu(ltime)); } static inline bool check_date(const MYSQL_TIME *ltime, date_conv_mode_t flags, int *was_cut) { return check_date(ltime, non_zero_date(ltime), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), was_cut); } bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_conv_mode_t fuzzy_date, timestamp_type ts_type); static inline bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzydate, timestamp_type ts_type) { return check_date_with_warn(thd, ltime, date_conv_mode_t(fuzzydate), ts_type); } bool adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec); longlong pack_time(const MYSQL_TIME *my_time); void unpack_time(longlong packed, MYSQL_TIME *my_time, enum_mysql_timestamp_type ts_type); #endif /* SQL_TIME_INCLUDED */ sql_used.h 0000644 00000002023 15156036131 0006532 0 ustar 00 /* Copyright (c) 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_USED_INCLUDED #define SQL_USED_INCLUDED class Sql_used { public: typedef uint used_t; enum { RAND_USED=1, TIME_ZONE_USED=2, QUERY_START_SEC_PART_USED=4, THREAD_SPECIFIC_USED=8, CHARACTER_SET_COLLATIONS_USED= 16 }; used_t used; Sql_used() :used(0) { } }; #endif // SQL_USED_INCLUDED myisamchk.h 0000644 00000011176 15156036131 0006711 0 ustar 00 /* Copyright (C) 2006 MySQL AB Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Definitions needed for myisamchk/mariachk.c */ #ifndef _myisamchk_h #define _myisamchk_h #include <my_stack_alloc.h> /* Flags used by xxxxchk.c or/and ha_xxxx.cc that are NOT passed to xxxcheck.c follows: */ #define TT_USEFRM 1U #define TT_FOR_UPGRADE 2U #define TT_FROM_MYSQL 4U /* Bits set in out_flag */ #define O_NEW_DATA 2U #define O_DATA_LOST 4U /* MARIA/MYISAM supports several statistics collection methods. Currently statistics collection method is not stored in MARIA file and has to be specified for each table analyze/repair operation in MI_CHECK::stats_method. */ typedef enum { /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ MI_STATS_METHOD_NULLS_NOT_EQUAL, /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ MI_STATS_METHOD_NULLS_EQUAL, /* Ignore NULLs - count only tuples without NULLs in the index components */ MI_STATS_METHOD_IGNORE_NULLS } enum_handler_stats_method; struct st_myisam_info; typedef struct st_handler_check_param { char *isam_file_name; MY_TMPDIR *tmpdir; void *thd; const char *db_name, *table_name, *op_name; ulonglong auto_increment_value; ulonglong max_data_file_length; ulonglong keys_in_use; ulonglong max_record_length; /* The next two are used to collect statistics, see update_key_parts for description. */ ulonglong unique_count[HA_MAX_KEY_SEG + 1]; ulonglong notnull_count[HA_MAX_KEY_SEG + 1]; ulonglong max_allowed_lsn; my_off_t search_after_block; my_off_t new_file_pos, key_file_blocks; my_off_t keydata, totaldata, key_blocks, start_check_pos; my_off_t used, empty, splits, del_length, link_used, lost; ha_rows total_records, total_deleted, records,del_blocks; ha_rows full_page_count, tail_count; ha_checksum record_checksum, glob_crc; ha_checksum key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_record_checksum; ulonglong org_key_map; ulonglong testflag; /* Following is used to check if rows are visible */ ulonglong max_trid, max_found_trid; ulonglong not_visible_rows_found; ulonglong sort_buffer_length, orig_sort_buffer_length; ulonglong use_buffers; /* Used as param to getopt() */ size_t read_buffer_length, write_buffer_length, sort_key_blocks; time_t backup_time; /* To sign backup files */ ulong rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; double new_rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; uint out_flag, error_printed, verbose; uint opt_sort_key, total_files, max_level; uint key_cache_block_size, pagecache_block_size; uint skip_lsn_error_count; int tmpfile_createflag, err_count; myf myf_rw; uint16 language; my_bool warning_printed, note_printed, wrong_trd_printed; my_bool using_global_keycache, opt_lock_memory, opt_follow_links; my_bool retry_repair, force_sort, calc_checksum, static_row_size; char temp_filename[FN_REFLEN]; IO_CACHE read_cache; void **stack_end_ptr; enum_handler_stats_method stats_method; /* For reporting progress */ uint stage, max_stage; uint progress_counter; /* How often to call _report_progress() */ ulonglong progress, max_progress; void (*init_fix_record)(void *); int (*fix_record)(struct st_myisam_info *info, uchar *record, int keynum); mysql_mutex_t print_msg_mutex; my_bool need_print_msg_lock, status_reporting; myf malloc_flags; } HA_CHECK; typedef struct st_buffpek { my_off_t file_pos; /* Where we are in the sort file */ uchar *base, *key; /* Key pointers */ ha_rows count; /* Number of rows in table */ ha_rows mem_count; /* Numbers of keys in memory */ ha_rows max_keys; /* Max keys in buffert */ } BUFFPEK; #endif /* _myisamchk_h */ sql_list.h 0000644 00000053567 15156036132 0006571 0 ustar 00 #ifndef INCLUDES_MYSQL_SQL_LIST_H #define INCLUDES_MYSQL_SQL_LIST_H /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_alloc.h" #include <iterator> /** Simple intrusive linked list. @remark Similar in nature to base_list, but intrusive. It keeps a a pointer to the first element in the list and a indirect reference to the last element. */ template <typename T> class SQL_I_List :public Sql_alloc { public: uint elements; /** The first element in the list. */ T *first; /** A reference to the next element in the list. */ T **next; SQL_I_List() { empty(); } SQL_I_List(const SQL_I_List &tmp) : Sql_alloc() { elements= tmp.elements; first= tmp.first; next= elements ? tmp.next : &first; } SQL_I_List& operator=(const SQL_I_List &tmp) { elements= tmp.elements; first= tmp.first; next= elements ? tmp.next : &first;; return *this; } inline void empty() { elements= 0; first= NULL; next= &first; } inline void link_in_list(T *element, T **next_ptr) { elements++; (*next)= element; next= next_ptr; *next= NULL; } inline void save_and_clear(SQL_I_List<T> *save) { *save= *this; empty(); } inline void push_front(SQL_I_List<T> *save) { /* link current list last */ *save->next= first; first= save->first; elements+= save->elements; } inline void push_back(SQL_I_List<T> *save) { if (save->first) { *next= save->first; next= save->next; elements+= save->elements; } } }; /* Basic single linked list Used for item and item_buffs. All list ends with a pointer to the 'end_of_list' element, which data pointer is a null pointer and the next pointer points to itself. This makes it very fast to traverse lists as we don't have to test for a specialend condition for list that can't contain a null pointer. */ /** list_node - a node of a single-linked list. @note We never call a destructor for instances of this class. */ struct list_node :public Sql_alloc { list_node *next; void *info; list_node(const void *info_par, list_node *next_par) :next(next_par), info(const_cast<void *>(info_par)) {} list_node() /* For end_of_list */ { info= 0; next= this; } }; extern MYSQL_PLUGIN_IMPORT list_node end_of_list; class base_list :public Sql_alloc { protected: list_node *first,**last; public: uint elements; bool operator==(const base_list &rhs) const { return elements == rhs.elements && first == rhs.first && last == rhs.last; } base_list& operator=(const base_list &rhs) { elements= rhs.elements; first= rhs.first; last= elements ? rhs.last : &first; return *this; } inline void empty() { elements=0; first= &end_of_list; last=&first;} inline base_list() { empty(); } /** This is a shallow copy constructor that implicitly passes the ownership from the source list to the new instance. The old instance is not updated, so both objects end up sharing the same nodes. If one of the instances then adds or removes a node, the other becomes out of sync ('last' pointer), while still operational. Some old code uses and relies on this behaviour. This logic is quite tricky: please do not use it in any new code. */ inline base_list(const base_list &tmp) :Sql_alloc() { *this= tmp; } /** Construct a deep copy of the argument in memory root mem_root. The elements themselves are copied by pointer. If you also need to copy elements by value, you should employ list_copy_and_replace_each_value after creating a copy. */ bool copy(const base_list *rhs, MEM_ROOT *mem_root); base_list(const base_list &rhs, MEM_ROOT *mem_root) { copy(&rhs, mem_root); } inline base_list(bool) {} inline bool push_back(void *info) { if (((*last)=new list_node(info, &end_of_list))) { last= &(*last)->next; elements++; return 0; } return 1; } inline bool push_back(void *info, MEM_ROOT *mem_root) { if (((*last)=new (mem_root) list_node(info, &end_of_list))) { last= &(*last)->next; elements++; return 0; } return 1; } bool push_front_impl(list_node *node) { if (node) { if (last == &first) last= &node->next; first=node; elements++; return 0; } return 1; } inline bool push_front(void *info) { return push_front_impl(new list_node(info, first)); } inline bool push_front(void *info, MEM_ROOT *mem_root) { return push_front_impl(new (mem_root) list_node(info,first)); } void remove(list_node **prev) { list_node *node=(*prev)->next; if (!--elements) last= &first; else if (last == &(*prev)->next) last= prev; delete *prev; *prev=node; } inline void append(base_list *list) { if (!list->is_empty()) { if (is_empty()) { *this= *list; return; } *last= list->first; last= list->last; elements+= list->elements; } } inline void *pop(void) { if (first == &end_of_list) return 0; list_node *tmp=first; first=first->next; if (!--elements) last= &first; return tmp->info; } /* Remove from this list elements that are contained in the passed list. We assume that the passed list is a tail of this list (that is, the whole list_node* elements are shared). */ inline void disjoin(const base_list *list) { list_node **prev= &first; list_node *node= first; list_node *list_first= list->first; elements=0; while (node != &end_of_list && node != list_first) { prev= &node->next; node= node->next; elements++; if (node == &end_of_list) return; } *prev= &end_of_list; last= prev; } inline void prepend(base_list *list) { if (!list->is_empty()) { if (is_empty()) last= list->last; *list->last= first; first= list->first; elements+= list->elements; } } /** Swap two lists. */ inline void swap(base_list &rhs) { list_node **rhs_last=rhs.last; swap_variables(list_node *, first, rhs.first); swap_variables(uint, elements, rhs.elements); rhs.last= last == &first ? &rhs.first : last; last = rhs_last == &rhs.first ? &first : rhs_last; } inline list_node* last_node() { return *last; } inline list_node* first_node() { return first;} inline void *head() { return first->info; } inline void **head_ref() { return first != &end_of_list ? &first->info : 0; } inline bool is_empty() { return first == &end_of_list ; } inline list_node *last_ref() { return &end_of_list; } template <typename T= void> inline bool add_unique(T *info, bool (*eq)(T *a, T *b)) { list_node *node= first; for (; node != &end_of_list && (!(*eq)(static_cast<T *>(node->info), info)); node= node->next) ; if (node == &end_of_list) return push_back(info); return 1; } friend class base_list_iterator; friend class error_list; friend class error_list_iterator; /* Return N-th element in the list, or NULL if the list has less than N elements. */ void *elem(uint n) { list_node *node= first; void *data= NULL; for (uint i= 0; i <= n; i++) { if (node == &end_of_list) { data= NULL; break; } data= node->info; node= node->next; } return data; } #ifdef LIST_EXTRA_DEBUG /* Check list invariants and print results into trace. Invariants are: - (*last) points to end_of_list - There are no NULLs in the list. - base_list::elements is the number of elements in the list. SYNOPSIS check_list() name Name to print to trace file RETURN 1 The list is Ok. 0 List invariants are not met. */ bool check_list(const char *name) { base_list *list= this; list_node *node= first; uint cnt= 0; while (node->next != &end_of_list) { if (!node->info) { DBUG_PRINT("list_invariants",("%s: error: NULL element in the list", name)); return FALSE; } node= node->next; cnt++; } if (last != &(node->next)) { DBUG_PRINT("list_invariants", ("%s: error: wrong last pointer", name)); return FALSE; } if (cnt+1 != elements) { DBUG_PRINT("list_invariants", ("%s: error: wrong element count", name)); return FALSE; } DBUG_PRINT("list_invariants", ("%s: list is ok", name)); return TRUE; } #endif // LIST_EXTRA_DEBUG protected: void after(const void *info, list_node *node) { list_node *new_node=new list_node(info,node->next); node->next=new_node; elements++; if (last == &(node->next)) last= &new_node->next; } }; class base_list_iterator { protected: base_list *list; list_node **el,**prev,*current; void sublist(base_list &ls, uint elm) { ls.first= *el; ls.last= list->last; ls.elements= elm; } public: base_list_iterator() :list(0), el(0), prev(0), current(0) {} base_list_iterator(base_list &list_par) { init(list_par); } inline void init(base_list &list_par) { list= &list_par; el= &list_par.first; prev= 0; current= 0; } inline void *next(void) { prev=el; current= *el; el= ¤t->next; return current->info; } /* Get what calling next() would return, without moving the iterator */ inline void *peek() { return (*el)->info; } inline void *next_fast(void) { list_node *tmp; tmp= *el; el= &tmp->next; return tmp->info; } inline void rewind(void) { el= &list->first; } inline void *replace(const void *element) { // Return old element void *tmp=current->info; DBUG_ASSERT(current->info != 0); current->info= const_cast<void *>(element); return tmp; } void *replace(base_list &new_list) { void *ret_value=current->info; if (!new_list.is_empty()) { *new_list.last=current->next; current->info=new_list.first->info; current->next=new_list.first->next; if ((list->last == ¤t->next) && (new_list.elements > 1)) list->last= new_list.last; list->elements+=new_list.elements-1; } return ret_value; // return old element } inline void remove(void) // Remove current { list->remove(prev); el=prev; current=0; // Safeguard } void after(const void *element) // Insert element after current { list->after(element,current); current=current->next; el= ¤t->next; } inline void **ref(void) // Get reference pointer { return ¤t->info; } inline bool is_last(void) { return el == &list->last_ref()->next; } inline bool at_end() { return current == &end_of_list; } friend class error_list_iterator; }; template <class T> class List :public base_list { public: inline List() :base_list() {} inline List(const List<T> &tmp, MEM_ROOT *mem_root) : base_list(tmp, mem_root) {} inline bool push_back(T *a) { return base_list::push_back(a); } inline bool push_back(T *a, MEM_ROOT *mem_root) { return base_list::push_back((void*) a, mem_root); } inline bool push_front(T *a) { return base_list::push_front(a); } inline bool push_front(T *a, MEM_ROOT *mem_root) { return base_list::push_front((void*) a, mem_root); } inline T* head() {return (T*) base_list::head(); } inline T** head_ref() {return (T**) base_list::head_ref(); } inline T* pop() {return (T*) base_list::pop(); } inline void append(List<T> *list) { base_list::append(list); } inline void prepend(List<T> *list) { base_list::prepend(list); } inline void disjoin(List<T> *list) { base_list::disjoin(list); } inline bool add_unique(T *a, bool (*eq)(T *a, T *b)) { return base_list::add_unique<T>(a, eq); } inline bool copy(const List<T> *list, MEM_ROOT *root) { return base_list::copy(list, root); } void delete_elements(void) { list_node *element,*next; for (element=first; element != &end_of_list; element=next) { next=element->next; delete (T*) element->info; } empty(); } T *elem(uint n) { return (T*) base_list::elem(n); } // Create a new list with one element static List<T> *make(MEM_ROOT *mem_root, T *first) { List<T> *res= new (mem_root) List<T>; return res == NULL || res->push_back(first, mem_root) ? NULL : res; } class Iterator; using value_type= T; using iterator= Iterator; iterator begin() const { return iterator(first); } iterator end() const { return iterator(); } class Iterator { public: using iterator_category= std::forward_iterator_tag; using value_type= T; using difference_type= std::ptrdiff_t; using pointer= T *; using reference= T &; Iterator(list_node *p= &end_of_list) : node{p} {} Iterator &operator++() { DBUG_ASSERT(node != &end_of_list); node= node->next; return *this; } Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } T &operator*() { return *static_cast<T *>(node->info); } T *operator->() { return static_cast<T *>(node->info); } bool operator==(const typename List<T>::iterator &rhs) { return node == rhs.node; } bool operator!=(const typename List<T>::iterator &rhs) { return node != rhs.node; } private: list_node *node{&end_of_list}; }; }; template <class T> class List_iterator :public base_list_iterator { public: List_iterator(List<T> &a) : base_list_iterator(a) {} List_iterator() : base_list_iterator() {} inline void init(List<T> &a) { base_list_iterator::init(a); } inline T* operator++(int) { return (T*) base_list_iterator::next(); } inline T* peek() { return (T*) base_list_iterator::peek(); } inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); } inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); } inline void rewind(void) { base_list_iterator::rewind(); } inline void remove() { base_list_iterator::remove(); } inline void after(T *a) { base_list_iterator::after(a); } inline T** ref(void) { return (T**) base_list_iterator::ref(); } }; template <class T> class List_iterator_fast :public base_list_iterator { protected: inline T *replace(T *) { return (T*) 0; } inline T *replace(List<T> &) { return (T*) 0; } inline void remove(void) {} inline void after(T *) {} inline T** ref(void) { return (T**) 0; } public: inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {} inline List_iterator_fast() : base_list_iterator() {} inline void init(List<T> &a) { base_list_iterator::init(a); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline void rewind(void) { base_list_iterator::rewind(); } void sublist(List<T> &list_arg, uint el_arg) { base_list_iterator::sublist(list_arg, el_arg); } }; /* Bubble sort algorithm for List<T>. This sort function is supposed to be used only for very short list. Currently it is used for the lists of Item_equal objects and for some lists in the table elimination algorithms. In both cases the sorted lists are very short. */ template <class T> inline void bubble_sort(List<T> *list_to_sort, int (*sort_func)(T *a, T *b, void *arg), void *arg) { bool swap; T **ref1= 0; T **ref2= 0; List_iterator<T> it(*list_to_sort); do { T **last_ref= ref1; T *item1= it++; ref1= it.ref(); T *item2; swap= FALSE; while ((item2= it++) && (ref2= it.ref()) != last_ref) { if (sort_func(item1, item2, arg) > 0) { *ref1= item2; *ref2= item1; swap= TRUE; } else item1= item2; ref1= ref2; } it.rewind(); } while (swap); } /* A simple intrusive list which automaticly removes element from list on delete (for THD element) */ struct ilink { struct ilink **prev,*next; static void *operator new(size_t size) throw () { return (void*)my_malloc(PSI_INSTRUMENT_ME, (uint)size, MYF(MY_WME | MY_FAE | ME_FATAL)); } static void operator delete(void* ptr_arg, size_t) { my_free(ptr_arg); } inline ilink() { prev=0; next=0; } inline void unlink() { /* Extra tests because element doesn't have to be linked */ if (prev) *prev= next; if (next) next->prev=prev; prev=0 ; next=0; } inline void assert_linked() { DBUG_ASSERT(prev != 0 && next != 0); } inline void assert_not_linked() { DBUG_ASSERT(prev == 0 && next == 0); } virtual ~ilink() { unlink(); } /*lint -e1740 */ }; /* Needed to be able to have an I_List of char* strings in mysqld.cc. */ class i_string: public ilink { public: const char* ptr; i_string():ptr(0) { } i_string(const char* s) : ptr(s) {} }; /* needed for linked list of two strings for replicate-rewrite-db */ class i_string_pair: public ilink { public: const char* key; const char* val; i_string_pair():key(0),val(0) { } i_string_pair(const char* key_arg, const char* val_arg) : key(key_arg),val(val_arg) {} }; template <class T> class I_List_iterator; class base_ilist { struct ilink *first; struct ilink last; public: inline void empty() { first= &last; last.prev= &first; } base_ilist() { empty(); } inline bool is_empty() { return first == &last; } // Returns true if p is the last "real" object in the list, // i.e. p->next points to the sentinel. inline bool is_last(ilink *p) { return p->next == NULL || p->next == &last; } inline void append(ilink *a) { first->prev= &a->next; a->next=first; a->prev= &first; first=a; } inline void push_back(ilink *a) { *last.prev= a; a->next= &last; a->prev= last.prev; last.prev= &a->next; } inline struct ilink *get() { struct ilink *first_link=first; if (first_link == &last) return 0; first_link->unlink(); // Unlink from list return first_link; } inline struct ilink *head() { return (first != &last) ? first : 0; } /** Moves list elements to new owner, and empties current owner (i.e. this). @param[in,out] new_owner The new owner of the list elements. Should be empty in input. */ void move_elements_to(base_ilist *new_owner) { DBUG_ASSERT(new_owner->is_empty()); new_owner->first= first; new_owner->last= last; empty(); } friend class base_ilist_iterator; private: /* We don't want to allow copying of this class, as that would give us two list heads containing the same elements. So we declare, but don't define copy CTOR and assignment operator. */ base_ilist(const base_ilist&); void operator=(const base_ilist&); }; class base_ilist_iterator { base_ilist *list; struct ilink **el; protected: struct ilink *current; public: base_ilist_iterator(base_ilist &list_par) :list(&list_par), el(&list_par.first),current(0) {} void *next(void) { /* This is coded to allow push_back() while iterating */ current= *el; if (current == &list->last) return 0; el= ¤t->next; return current; } /* Unlink element returned by last next() call */ inline void unlink(void) { struct ilink **tmp= current->prev; current->unlink(); el= tmp; } }; template <class T> class I_List :private base_ilist { public: I_List() :base_ilist() {} inline bool is_last(T *p) { return base_ilist::is_last(p); } inline void empty() { base_ilist::empty(); } inline bool is_empty() { return base_ilist::is_empty(); } inline void append(T* a) { base_ilist::append(a); } inline void push_back(T* a) { base_ilist::push_back(a); } inline T* get() { return (T*) base_ilist::get(); } inline T* head() { return (T*) base_ilist::head(); } inline void move_elements_to(I_List<T>* new_owner) { base_ilist::move_elements_to(new_owner); } friend class I_List_iterator<T>; }; template <class T> class I_List_iterator :public base_ilist_iterator { public: I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {} inline T* operator++(int) { return (T*) base_ilist_iterator::next(); } /* Remove element returned by last next() call */ inline void remove(void) { unlink(); delete (T*) current; current= 0; // Safety } }; /** Make a deep copy of each list element. @note A template function and not a template method of class List is employed because of explicit template instantiation: in server code there are explicit instantiations of List<T> and an explicit instantiation of a template requires that any method of the instantiated class used in the template can be resolved. Evidently not all template arguments have clone() method with the right signature. @return You must query the error state in THD for out-of-memory situation after calling this function. */ template <typename T> inline void list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root) { /* Make a deep copy of each element */ List_iterator<T> it(list); T *el; while ((el= it++)) it.replace(el->clone(mem_root)); } void free_list(I_List <i_string> *list); #endif // INCLUDES_MYSQL_SQL_LIST_H sql_priv.h 0000644 00000036124 15156036132 0006564 0 ustar 00 /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. Copyright (c) 2010, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file @details Mostly this file is used in the server. But a little part of it is used in mysqlbinlog too (definition of SELECT_DISTINCT and others). The consequence is that 90% of the file is wrapped in \#ifndef MYSQL_CLIENT, except the part which must be in the server and in the client. */ #ifndef SQL_PRIV_INCLUDED #define SQL_PRIV_INCLUDED /* This is included in the server and in the client. Options for select set by the yacc parser (stored in lex->options). NOTE log_event.h defines OPTIONS_WRITTEN_TO_BIN_LOG to specify what THD options list are written into binlog. These options can NOT change their values, or it will break replication between version. context is encoded as following: SELECT - SELECT_LEX_NODE::options THD - THD::options intern - neither. used only as func(..., select_node->options | thd->options | OPTION_XXX, ...) TODO: separate three contexts above, move them to separate bitfields. */ #define SELECT_DISTINCT (1ULL << 0) // SELECT, user #define SELECT_STRAIGHT_JOIN (1ULL << 1) // SELECT, user #define SELECT_DESCRIBE (1ULL << 2) // SELECT, user #define SELECT_SMALL_RESULT (1ULL << 3) // SELECT, user #define SELECT_BIG_RESULT (1ULL << 4) // SELECT, user #define OPTION_FOUND_ROWS (1ULL << 5) // SELECT, user #define OPTION_TO_QUERY_CACHE (1ULL << 6) // SELECT, user #define SELECT_NO_JOIN_CACHE (1ULL << 7) // intern /** always the opposite of OPTION_NOT_AUTOCOMMIT except when in fix_autocommit() */ #define OPTION_AUTOCOMMIT (1ULL << 8) // THD, user #define OPTION_BIG_SELECTS (1ULL << 9) // THD, user #define OPTION_LOG_OFF (1ULL << 10) // THD, user #define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user #define TMP_TABLE_ALL_COLUMNS (1ULL << 12) // SELECT, intern #define OPTION_WARNINGS (1ULL << 13) // THD, user #define OPTION_AUTO_IS_NULL (1ULL << 14) // THD, user, binlog #define OPTION_NO_CHECK_CONSTRAINT_CHECKS (1ULL << 15) #define OPTION_SAFE_UPDATES (1ULL << 16) // THD, user #define OPTION_BUFFER_RESULT (1ULL << 17) // SELECT, user #define OPTION_BIN_LOG (1ULL << 18) // THD, user #define OPTION_NOT_AUTOCOMMIT (1ULL << 19) // THD, user #define OPTION_BEGIN (1ULL << 20) // THD, intern #define OPTION_TABLE_LOCK (1ULL << 21) // THD, intern #define OPTION_QUICK (1ULL << 22) // SELECT (for DELETE) #define OPTION_BINLOG_THIS_TRX (1ULL << 23) // THD #define OPTION_EXPLICIT_DEF_TIMESTAMP (1ULL << 24) // THD, user #define OPTION_GTID_BEGIN (1ULL << 25) // GTID BEGIN found in log /** The following can be set when importing tables in a 'wrong order' to suppress foreign key checks */ #define OPTION_NO_FOREIGN_KEY_CHECKS (1ULL << 26) // THD, user, binlog /** The following speeds up inserts to InnoDB tables by suppressing unique key checks in some cases */ #define OPTION_RELAXED_UNIQUE_CHECKS (1ULL << 27) // THD, user, binlog #define OPTION_IF_EXISTS (1ULL << 28) // binlog #define OPTION_SCHEMA_TABLE (1ULL << 29) // SELECT, intern #define OPTION_INSERT_HISTORY (1ULL << 30) /** If not set then the thread will ignore all warnings with level notes. */ #define OPTION_SQL_NOTES (1ULL << 31) // THD, user /** Force the used temporary table to be a MyISAM table (because we will use fulltext functions when reading from it. */ #define TMP_TABLE_FORCE_MYISAM (1ULL << 32) #define OPTION_PROFILING (1ULL << 33) /** Indicates that this is a HIGH_PRIORITY SELECT. Currently used only for printing of such selects. Type of locks to be acquired is specified directly. */ #define SELECT_HIGH_PRIORITY (1ULL << 34) // SELECT, user /** Is set in slave SQL thread when there was an error on master, which, when is not reproducible on slave (i.e. the query succeeds on slave), is not terminal to the state of repliation, and should be ignored. The slave SQL thread, however, needs to rollback the effects of the succeeded statement to keep replication consistent. */ #define OPTION_MASTER_SQL_ERROR (1ULL << 35) #define OPTION_BINLOG_THIS_STMT (1ULL << 36) // THD #define OPTION_BINLOG_THIS (OPTION_BINLOG_THIS_STMT | OPTION_BINLOG_THIS_TRX) #define OPTION_SKIP_REPLICATION (1ULL << 37) // THD, user #define OPTION_RPL_SKIP_PARALLEL (1ULL << 38) #define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user #define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage #define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern #define OPTION_BIN_TMP_LOG_OFF (1ULL << 42) // disable binlog, intern /* Disable commit of binlog. Used to combine many DDL's and DML's as one */ #define OPTION_BIN_COMMIT_OFF (1ULL << 43) /* The following is used to detect a conflict with DISTINCT */ #define SELECT_ALL (1ULL << 44) // SELECT, user, parser /** Flag set if setup_tables already done */ #define OPTION_SETUP_TABLES_DONE (1ULL << 45) // intern #define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT /* @@optimizer_switch flags. These must be in sync with optimizer_switch_names */ #define OPTIMIZER_SWITCH_INDEX_MERGE (1ULL << 0) #define OPTIMIZER_SWITCH_INDEX_MERGE_UNION (1ULL << 1) #define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION (1ULL << 2) #define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT (1ULL << 3) #define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_INTERSECT (1ULL << 4) #define OPTIMIZER_SWITCH_INDEX_COND_PUSHDOWN (1ULL << 5) #define OPTIMIZER_SWITCH_DERIVED_MERGE (1ULL << 6) #define OPTIMIZER_SWITCH_DERIVED_WITH_KEYS (1ULL << 7) #define OPTIMIZER_SWITCH_FIRSTMATCH (1ULL << 8) #define OPTIMIZER_SWITCH_LOOSE_SCAN (1ULL << 9) #define OPTIMIZER_SWITCH_MATERIALIZATION (1ULL << 10) #define OPTIMIZER_SWITCH_IN_TO_EXISTS (1ULL << 11) #define OPTIMIZER_SWITCH_SEMIJOIN (1ULL << 12) #define OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE (1ULL << 13) #define OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN (1ULL << 14) #define OPTIMIZER_SWITCH_SUBQUERY_CACHE (1ULL << 15) /** If this is off, MRR is never used. */ #define OPTIMIZER_SWITCH_MRR (1ULL << 16) /** If OPTIMIZER_SWITCH_MRR is on and this is on, MRR is used depending on a cost-based choice ("automatic"). If OPTIMIZER_SWITCH_MRR is on and this is off, MRR is "forced" (i.e. used as long as the storage engine is capable of doing it). */ #define OPTIMIZER_SWITCH_MRR_COST_BASED (1ULL << 17) #define OPTIMIZER_SWITCH_MRR_SORT_KEYS (1ULL << 18) #define OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE (1ULL << 19) #define OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE (1ULL << 20) #define OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL (1ULL << 21) #define OPTIMIZER_SWITCH_JOIN_CACHE_HASHED (1ULL << 22) #define OPTIMIZER_SWITCH_JOIN_CACHE_BKA (1ULL << 23) #define OPTIMIZER_SWITCH_OPTIMIZE_JOIN_BUFFER_SIZE (1ULL << 24) #define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 25) #define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 26) #define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 27) #define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 28) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 29) #define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 30) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 31) #define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 32) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 33) #define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 34) #define OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY (1ULL << 35) #define OPTIMIZER_SWITCH_CSET_NARROWING (1ULL << 36) #define OPTIMIZER_SWITCH_SARGABLE_CASEFOLD (1ULL << 37) #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT | \ OPTIMIZER_SWITCH_INDEX_COND_PUSHDOWN | \ OPTIMIZER_SWITCH_DERIVED_MERGE | \ OPTIMIZER_SWITCH_DERIVED_WITH_KEYS | \ OPTIMIZER_SWITCH_TABLE_ELIMINATION | \ OPTIMIZER_SWITCH_EXTENDED_KEYS | \ OPTIMIZER_SWITCH_IN_TO_EXISTS | \ OPTIMIZER_SWITCH_MATERIALIZATION | \ OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\ OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\ OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE | \ OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE | \ OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL | \ OPTIMIZER_SWITCH_JOIN_CACHE_HASHED | \ OPTIMIZER_SWITCH_JOIN_CACHE_BKA | \ OPTIMIZER_SWITCH_SUBQUERY_CACHE | \ OPTIMIZER_SWITCH_SEMIJOIN | \ OPTIMIZER_SWITCH_FIRSTMATCH | \ OPTIMIZER_SWITCH_LOOSE_SCAN | \ OPTIMIZER_SWITCH_EXISTS_TO_IN | \ OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \ OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY |\ OPTIMIZER_SWITCH_USE_ROWID_FILTER | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING | \ OPTIMIZER_SWITCH_OPTIMIZE_JOIN_BUFFER_SIZE |\ OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY |\ OPTIMIZER_SWITCH_SARGABLE_CASEFOLD) #define OPTIMIZER_ADJ_DEFAULT (OPTIMIZER_ADJ_FIX_REUSE_RANGE_FOR_REF | \ OPTIMIZER_ADJ_FIX_CARD_MULT) /* Replication uses 8 bytes to store SQL_MODE in the binary log. The day you use strictly more than 64 bits by adding one more define above, you should contact the replication team because the replication code should then be updated (to store more bytes on disk). NOTE: When adding new SQL_MODE types, make sure to also add them to the scripts used for creating the MySQL system tables in scripts/mysql_system_tables.sql and scripts/mysql_system_tables_fix.sql */ /* Flags below are set when we perform context analysis of the statement and make subqueries non-const. It prevents subquery evaluation at context analysis stage. */ /* Don't evaluate this subquery during statement prepare even if it's a constant one. The flag is switched off in the end of mysqld_stmt_prepare. */ #define CONTEXT_ANALYSIS_ONLY_PREPARE 1 /* Special JOIN::prepare mode: changing of query is prohibited. When creating a view, we need to just check its syntax omitting any optimizations: afterwards definition of the view will be reconstructed by means of ::print() methods and written to to an .frm file. We need this definition to stay untouched. */ #define CONTEXT_ANALYSIS_ONLY_VIEW 2 /* Don't evaluate this subquery during derived table prepare even if it's a constant one. */ #define CONTEXT_ANALYSIS_ONLY_DERIVED 4 /* Don't evaluate constant sub-expressions of virtual column expressions when opening tables */ #define CONTEXT_ANALYSIS_ONLY_VCOL_EXPR 8 /* Uncachable causes: */ /* This subquery has fields from outer query (put by user) */ #define UNCACHEABLE_DEPENDENT_GENERATED 1 /* This subquery contains functions with random result. Something that is uncacheable is by default unmergeable. */ #define UNCACHEABLE_RAND 2 /* This subquery contains functions with side effect */ #define UNCACHEABLE_SIDEEFFECT 4 /* Forcing to save JOIN tables for explain */ #define UNCACHEABLE_EXPLAIN 8 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */ #define UNCACHEABLE_UNITED 16 #define UNCACHEABLE_CHECKOPTION 32 /* This subquery has fields from outer query injected during transformation process */ #define UNCACHEABLE_DEPENDENT_INJECTED 64 /* This subquery has fields from outer query (any nature) */ #define UNCACHEABLE_DEPENDENT (UNCACHEABLE_DEPENDENT_GENERATED | \ UNCACHEABLE_DEPENDENT_INJECTED) #define FAKE_SELECT_LEX_ID UINT_MAX /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define UNDEF_POS (-1) #define IN_SUBQUERY_CONVERSION_THRESHOLD 1000 #endif /* !MYSQL_CLIENT */ /* BINLOG_DUMP options */ #define BINLOG_DUMP_NON_BLOCK 1 #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2 #ifndef MYSQL_CLIENT /* Field::is_equal() return codes. */ #define IS_EQUAL_NO 0 #define IS_EQUAL_YES 1 /** new_field has compatible packed representation with old type, so it is theoretically possible to perform change by only updating data dictionary without changing table rows */ #define IS_EQUAL_PACK_LENGTH 2 enum enum_parsing_place { NO_MATTER, IN_HAVING, SELECT_LIST, IN_WHERE, IN_ON, IN_GROUP_BY, IN_ORDER_BY, IN_UPDATE_ON_DUP_KEY, IN_PART_FUNC, BEFORE_OPT_LIST, AFTER_LIST, FOR_LOOP_BOUND, IN_RETURNING, PARSING_PLACE_SIZE /* always should be the last */ }; class sys_var; enum enum_yes_no_unknown { TVL_YES, TVL_NO, TVL_UNKNOWN }; #ifdef MYSQL_SERVER /* External variables */ /* yy_*.cc */ #ifndef DBUG_OFF extern void turn_parser_debug_on_MYSQLparse(); extern void turn_parser_debug_on_ORAparse(); #endif /** convert a hex digit into number. */ inline int hexchar_to_int(char c) { if (c <= '9' && c >= '0') return c-'0'; c|=32; if (c <= 'f' && c >= 'a') return c-'a'+10; return -1; } /* This must match the path length limit in the ER_NOT_RW_DIR error msg. */ #define ER_NOT_RW_DIR_PATHSIZE 200 bool db_name_is_in_ignore_db_dirs_list(const char *dbase); #endif /* MYSQL_SERVER */ #endif /* MYSQL_CLIENT */ #endif /* SQL_PRIV_INCLUDED */ sql_base.h 0000644 00000063573 15156036132 0006526 0 ustar 00 /* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2011, 2018, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_BASE_INCLUDED #define SQL_BASE_INCLUDED #include "sql_class.h" /* enum_column_usage */ #include "sql_trigger.h" /* trg_event_type */ #include "mysqld.h" /* key_map */ #include "table_cache.h" class Item_ident; struct Name_resolution_context; class Open_table_context; class Open_tables_state; class Prelocking_strategy; class DML_prelocking_strategy; struct TABLE_LIST; class THD; struct handlerton; struct TABLE; typedef class st_select_lex SELECT_LEX; typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE; /* This enumeration type is used only by the function find_item_in_list to return the info on how an item has been resolved against a list of possibly aliased items. The item can be resolved: - against an alias name of the list's element (RESOLVED_AGAINST_ALIAS) - against non-aliased field name of the list (RESOLVED_WITH_NO_ALIAS) - against an aliased field name of the list (RESOLVED_BEHIND_ALIAS) - ignoring the alias name in cases when SQL requires to ignore aliases (e.g. when the resolved field reference contains a table name or when the resolved item is an expression) (RESOLVED_IGNORING_ALIAS) */ enum enum_resolution_type { NOT_RESOLVED=0, RESOLVED_IGNORING_ALIAS, RESOLVED_BEHIND_ALIAS, RESOLVED_WITH_NO_ALIAS, RESOLVED_AGAINST_ALIAS }; /* Argument to flush_tables() of what to flush */ enum flush_tables_type { FLUSH_ALL, FLUSH_NON_TRANS_TABLES, FLUSH_SYS_TABLES }; enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE, IGNORE_EXCEPT_NON_UNIQUE}; /* Flag bits for unique_table() */ #define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1 #define CHECK_DUP_FOR_CREATE 2 #define CHECK_DUP_SKIP_TEMP_TABLE 4 uint get_table_def_key(const TABLE_LIST *table_list, const char **key); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, uint lock_flags); /* mysql_lock_tables() and open_table() flags bits */ #define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK 0x0001 #define MYSQL_OPEN_IGNORE_FLUSH 0x0002 /* MYSQL_OPEN_TEMPORARY_ONLY (0x0004) is not used anymore. */ #define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008 #define MYSQL_LOCK_LOG_TABLE 0x0010 /** Do not try to acquire a metadata lock on the table: we already have one. */ #define MYSQL_OPEN_HAS_MDL_LOCK 0x0020 /** If in locked tables mode, ignore the locked tables and get a new instance of the table. */ #define MYSQL_OPEN_GET_NEW_TABLE 0x0040 /* 0x0080 used to be MYSQL_OPEN_SKIP_TEMPORARY */ /** Fail instead of waiting when conficting metadata lock is discovered. */ #define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100 /** Open tables using MDL_SHARED lock instead of one specified in parser. */ #define MYSQL_OPEN_FORCE_SHARED_MDL 0x0200 /** Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified in parser. */ #define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0400 /** When opening or locking the table, use the maximum timeout (LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value. */ #define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800 /** When acquiring "strong" (SNW, SNRW, X) metadata locks on tables to be open do not acquire global and schema-scope IX locks. */ #define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK 0x1000 #define MYSQL_LOCK_NOT_TEMPORARY 0x2000 #define MYSQL_LOCK_USE_MALLOC 0x4000 /** Only check THD::killed if waits happen (e.g. wait on MDL, wait on table flush, wait on thr_lock.c locks) while opening and locking table. */ #define MYSQL_OPEN_IGNORE_KILLED 0x8000 /** Don't try to auto-repair table */ #define MYSQL_OPEN_IGNORE_REPAIR 0x10000 /** Don't call decide_logging_format. Used for statistic tables etc */ #define MYSQL_OPEN_IGNORE_LOGGING_FORMAT 0x20000 /* Don't use statistics tables */ #define MYSQL_OPEN_IGNORE_ENGINE_STATS 0x40000 /** Please refer to the internals manual. */ #define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\ MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\ MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\ MYSQL_LOCK_IGNORE_TIMEOUT |\ MYSQL_OPEN_GET_NEW_TABLE |\ MYSQL_OPEN_HAS_MDL_LOCK) bool is_locked_view(THD *thd, TABLE_LIST *t); bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx); bool get_key_map_from_key_list(key_map *map, TABLE *table, List<String> *index_list); TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name); TABLE *find_write_locked_table(TABLE *list, const char *db, const char *table_name); thr_lock_type read_lock_type_for_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool routine_modifies_data); my_bool mysql_rm_tmp_tables(void); void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, const MDL_savepoint &start_of_statement_svp, bool remove_indirect); bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db, LEX_CSTRING *table, thr_lock_type lock_type); TABLE_LIST *find_table_in_list(TABLE_LIST *table, TABLE_LIST *TABLE_LIST::*link, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name); int close_thread_tables(THD *thd); int close_thread_tables_for_query(THD *thd); void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *); void switch_defaults_to_nullable_trigger_fields(TABLE *table); bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields, List<Item> &values, bool ignore_errors, enum trg_event_type event); bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **field, List<Item> &values, bool ignore_errors, enum trg_event_type event); bool insert_fields(THD *thd, Name_resolution_context *context, const LEX_CSTRING &db_name, const LEX_CSTRING &table_name, List_iterator<Item> *it, bool any_privileges, uint *hidden_bit_fields, bool returning_field); void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables, bool full_table_list, TABLE_LIST *boundary); int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, List<Item> *sum_func_list, SELECT_LEX *sl, bool returning_field); int setup_returning_fields(THD* thd, TABLE_LIST* table_list); bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &item, enum_column_usage column_usage, List<Item> *sum_func_list, List<Item> *pre_fix, bool allow_sum_func, THD_WHERE where= THD_WHERE::DEFAULT_WHERE); void unfix_fields(List<Item> &items); bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, bool ignore_errors, bool update); bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values, bool ignore_errors, bool use_value, bool check_for_evaluability); Field * find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *first_table, TABLE_LIST *last_table, ignored_tables_list_t ignored_tables, Item **ref, find_item_error_report_type report_error, bool check_privileges, bool register_tree_change); Field * find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, const char *name, size_t length, const char *item_name, const char *db_name, const char *table_name, ignored_tables_list_t ignored_tables, Item **ref, bool check_privileges, bool allow_rowid, field_index_t *cached_field_index_ptr, bool register_tree_change, TABLE_LIST **actual_table); Field * find_field_in_table(THD *thd, TABLE *table, const char *name, size_t length, bool allow_rowid, field_index_t *cached_field_index_ptr); Field * find_field_in_table_sef(TABLE *table, const char *name); Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, find_item_error_report_type report_error, enum_resolution_type *resolution, uint limit= 0); bool setup_tables(THD *thd, Name_resolution_context *context, List<TABLE_LIST> *from_clause, TABLE_LIST *tables, List<TABLE_LIST> &leaves, bool select_insert, bool full_table_list); bool setup_tables_and_check_access(THD *thd, Name_resolution_context *context, List<TABLE_LIST> *from_clause, TABLE_LIST *tables, List<TABLE_LIST> &leaves, bool select_insert, privilege_t want_access_first, privilege_t want_access, bool full_table_list); bool wait_while_table_is_used(THD *thd, TABLE *table, enum ha_extra_function function); void drop_open_table(THD *thd, TABLE *table, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name); void update_non_unique_table_error(TABLE_LIST *update, const char *operation, TABLE_LIST *duplicate); int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, COND **conds); void wrap_ident(THD *thd, Item **conds); int setup_ftfuncs(SELECT_LEX* select); void cleanup_ftfuncs(SELECT_LEX *select_lex); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); bool lock_table_names(THD *thd, const DDL_options_st &options, TABLE_LIST *table_list, TABLE_LIST *table_list_end, ulong lock_wait_timeout, uint flags); static inline bool lock_table_names(THD *thd, TABLE_LIST *table_list, TABLE_LIST *table_list_end, ulong lock_wait_timeout, uint flags) { return lock_table_names(thd, thd->lex->create_info, table_list, table_list_end, lock_wait_timeout, flags); } bool open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **tables, uint *counter, uint flags, Prelocking_strategy *prelocking_strategy); static inline bool open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags, Prelocking_strategy *prelocking_strategy) { return open_tables(thd, thd->lex->create_info, tables, counter, flags, prelocking_strategy); } /* open_and_lock_tables with optional derived handling */ bool open_and_lock_tables(THD *thd, const DDL_options_st &options, TABLE_LIST *tables, bool derived, uint flags, Prelocking_strategy *prelocking_strategy); static inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, bool derived, uint flags, Prelocking_strategy *prelocking_strategy) { return open_and_lock_tables(thd, thd->lex->create_info, tables, derived, flags, prelocking_strategy); } /* simple open_and_lock_tables without derived handling for single table */ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, thr_lock_type lock_type, uint flags, Prelocking_strategy *prelocking_strategy); bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags, uint dt_phases); bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables, bool can_deadlock); bool open_and_lock_internal_tables(TABLE *table, bool lock); bool open_tables_for_query(THD *thd, TABLE_LIST *tables, uint *table_count, uint flags, DML_prelocking_strategy *prelocking_strategy); bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags); int decide_logging_format(THD *thd, TABLE_LIST *tables); void close_thread_table(THD *thd, TABLE **table_ptr); TABLE_LIST* unique_table_in_insert_returning_subselect(THD *thd, TABLE_LIST *table, SELECT_LEX *sel); TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, uint check_flag); bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b); class Open_tables_backup; /* Functions to work with system tables. */ bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list); void close_system_tables(THD *thd); void close_mysql_tables(THD *thd); TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table); TABLE *open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup); void close_log_table(THD *thd, Open_tables_backup *backup); bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool wait_for_refresh, ulong timeout); void purge_tables(); bool flush_tables(THD *thd, flush_tables_type flag); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, ha_extra_function extra, TABLE *skip_table); OPEN_TABLE_LIST *list_open_tables(THD *thd, const LEX_CSTRING &db, const char *wild); bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags); TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, const char *table_name, int *p_error); void mark_tmp_table_for_reuse(TABLE *table); int dynamic_column_error_message(enum_dyncol_func_result rc); /* open_and_lock_tables with optional derived handling */ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived); extern "C" qsort_cmp2 simple_raw_key_cmp; extern "C" int count_distinct_walk(void *elem, element_count count, void *arg); int simple_str_key_cmp(void *arg, const void *key1, const void *key2); extern Item **not_found_item; extern Field *not_found_field; extern Field *view_ref_found; /** clean/setup table fields and map. @param table TABLE structure pointer (which should be setup) @param table_list TABLE_LIST structure pointer (owner of TABLE) @param tablenr table number */ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) { table->used_fields= 0; table_list->reset_const_table(); table->null_row= 0; table->status= STATUS_NO_RECORD; table->maybe_null= table_list->outer_join; TABLE_LIST *embedding= table_list->embedding; while (!table->maybe_null && embedding) { table->maybe_null= embedding->outer_join; embedding= embedding->embedding; } DBUG_ASSERT(tablenr <= MAX_TABLES); table->tablenr= tablenr; table->map= (table_map) 1 << tablenr; table->force_index= table->force_index_join= 0; table->force_index_order= table->force_index_group= 0; table->covering_keys= table->s->keys_for_keyread; } inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table, LEX_CSTRING *db_name, LEX_CSTRING *table_name) { return find_table_in_list(table, &TABLE_LIST::next_global, db_name, table_name); } inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &item, enum_column_usage column_usage, List<Item> *sum_func_list, bool allow_sum_func, THD_WHERE where= THD_WHERE::DEFAULT_WHERE) { bool res; SELECT_LEX *first= thd->lex->first_select_lex(); DBUG_ASSERT(thd->lex->current_select == first); first->no_wrap_view_item= TRUE; res= setup_fields(thd, ref_pointer_array, item, column_usage, sum_func_list, NULL, allow_sum_func, where); first->no_wrap_view_item= FALSE; return res; } /** An abstract class for a strategy specifying how the prelocking algorithm should extend the prelocking set while processing already existing elements in the set. */ class Prelocking_strategy { public: virtual ~Prelocking_strategy() = default; virtual void reset(THD *thd) { }; virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, Sroutine_hash_entry *rt, sp_head *sp, bool *need_prelocking) = 0; virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) = 0; virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking)= 0; virtual bool handle_end(THD *thd) { return 0; }; }; /** A Strategy for prelocking algorithm suitable for DML statements. Ensures that all tables used by all statement's SF/SP/triggers and required for foreign key checks are prelocked and SF/SPs used are cached. */ class DML_prelocking_strategy : public Prelocking_strategy { public: bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, Sroutine_hash_entry *rt, sp_head *sp, bool *need_prelocking) override; bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; }; class Multiupdate_prelocking_strategy : public DML_prelocking_strategy { bool done; bool has_prelocking_list; public: void reset(THD *thd) override; bool handle_end(THD *thd) override; }; /** A strategy for prelocking algorithm to be used for LOCK TABLES statement. */ class Lock_tables_prelocking_strategy : public DML_prelocking_strategy { bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; }; /** Strategy for prelocking algorithm to be used for ALTER TABLE statements. Unlike DML or LOCK TABLES strategy, it doesn't prelock triggers, views or stored routines, since they are not used during ALTER. */ class Alter_table_prelocking_strategy : public Prelocking_strategy { public: bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, Sroutine_hash_entry *rt, sp_head *sp, bool *need_prelocking) override; bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; }; inline bool open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **tables, uint *counter, uint flags) { DML_prelocking_strategy prelocking_strategy; return open_tables(thd, options, tables, counter, flags, &prelocking_strategy); } inline bool open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags) { DML_prelocking_strategy prelocking_strategy; return open_tables(thd, thd->lex->create_info, tables, counter, flags, &prelocking_strategy); } inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, thr_lock_type lock_type, uint flags) { DML_prelocking_strategy prelocking_strategy; return open_n_lock_single_table(thd, table_l, lock_type, flags, &prelocking_strategy); } /* open_and_lock_tables with derived handling */ inline bool open_and_lock_tables(THD *thd, const DDL_options_st &options, TABLE_LIST *tables, bool derived, uint flags) { DML_prelocking_strategy prelocking_strategy; return open_and_lock_tables(thd, options, tables, derived, flags, &prelocking_strategy); } inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, bool derived, uint flags) { DML_prelocking_strategy prelocking_strategy; return open_and_lock_tables(thd, thd->lex->create_info, tables, derived, flags, &prelocking_strategy); } bool restart_trans_for_tables(THD *thd, TABLE_LIST *table); bool extend_table_list(THD *thd, TABLE_LIST *tables, Prelocking_strategy *prelocking_strategy, bool has_prelocking_list); /** A context of open_tables() function, used to recover from a failed open_table() or open_routine() attempt. */ class Open_table_context { public: enum enum_open_table_action { OT_NO_ACTION= 0, OT_BACKOFF_AND_RETRY, OT_REOPEN_TABLES, OT_DISCOVER, OT_REPAIR, OT_ADD_HISTORY_PARTITION }; Open_table_context(THD *thd, uint flags); bool recover_from_failed_open(); bool request_backoff_action(enum_open_table_action action_arg, TABLE_LIST *table); bool can_recover_from_failed_open() const { return m_action != OT_NO_ACTION; } /** When doing a back-off, we close all tables acquired by this statement. Return an MDL savepoint taken at the beginning of the statement, so that we can rollback to it before waiting on locks. */ const MDL_savepoint &start_of_statement_svp() const { return m_start_of_statement_svp; } inline ulong get_timeout() const { return m_timeout; } uint get_flags() const { return m_flags; } /** Set flag indicating that we have already acquired metadata lock protecting this statement against GRL while opening tables. */ void set_has_protection_against_grl(enum_mdl_type mdl_type) { m_has_protection_against_grl|= MDL_BIT(mdl_type); } bool has_protection_against_grl(enum_mdl_type mdl_type) const { return (bool) (m_has_protection_against_grl & MDL_BIT(mdl_type)); } private: /* THD for which tables are opened. */ THD *m_thd; /** For OT_DISCOVER and OT_REPAIR actions, the table list element for the table which definition should be re-discovered or which should be repaired. */ TABLE_LIST *m_failed_table; MDL_savepoint m_start_of_statement_svp; /** Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system tables or to the "lock_wait_timeout" system variable for regular tables. */ ulong m_timeout; /* open_table() flags. */ uint m_flags; /** Back off action. */ enum enum_open_table_action m_action; /** Whether we had any locks when this context was created. If we did, they are from the previous statement of a transaction, and we can't safely do back-off (and release them). */ bool m_has_locks; /** Indicates that in the process of opening tables we have acquired protection against global read lock. */ mdl_bitmap_t m_has_protection_against_grl; public: uint vers_create_count; }; /** Check if a TABLE_LIST instance represents a pre-opened temporary table. */ inline bool is_temporary_table(TABLE_LIST *tl) { if (tl->view || tl->schema_table) return FALSE; if (!tl->table) return FALSE; /* NOTE: 'table->s' might be NULL for specially constructed TABLE instances. See SHOW TRIGGERS for example. */ if (!tl->table->s) return FALSE; return tl->table->s->tmp_table != NO_TMP_TABLE; } /** This internal handler is used to trap ER_NO_SUCH_TABLE. */ class No_such_table_error_handler : public Internal_error_handler { public: No_such_table_error_handler() : m_handled_errors(0), m_unhandled_errors(0), first_error(0) {} bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) override; /** Returns TRUE if one or more ER_NO_SUCH_TABLE errors have been trapped and no other errors have been seen. FALSE otherwise. */ bool safely_trapped_errors(); uint got_error() { return first_error; } private: int m_handled_errors; int m_unhandled_errors; uint first_error; }; #endif /* SQL_BASE_INCLUDED */ sql_digest.h 0000644 00000007353 15156036132 0007065 0 ustar 00 /* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DIGEST_H #define SQL_DIGEST_H #include <string.h> class String; #include "my_md5.h" #define MAX_DIGEST_STORAGE_SIZE (1024*1024) /** Structure to store token count/array for a statement on which digest is to be calculated. */ struct sql_digest_storage { bool m_full; uint m_byte_count; unsigned char m_md5[MD5_HASH_SIZE]; /** Character set number. */ uint m_charset_number; /** Token array. Token array is an array of bytes to store tokens received during parsing. Following is the way token array is formed. ... <non-id-token> <non-id-token> <id-token> <id_len> <id_text> ... For Example: SELECT * FROM T1; <SELECT_TOKEN> <*> <FROM_TOKEN> <ID_TOKEN> <2> <T1> @note Only the first @c m_byte_count bytes are initialized, out of @c m_token_array_length. */ unsigned char *m_token_array; /* Length of the token array to be considered for DIGEST_TEXT calculation. */ uint m_token_array_length; sql_digest_storage() { reset(NULL, 0); } inline void reset(unsigned char *token_array, size_t length) { m_token_array= token_array; m_token_array_length= (uint)length; reset(); } inline void reset() { m_full= false; m_byte_count= 0; m_charset_number= 0; memset(m_md5, 0, MD5_HASH_SIZE); } inline bool is_empty() { return (m_byte_count == 0); } inline void copy(const sql_digest_storage *from) { /* Keep in mind this is a dirty copy of something that may change, as the thread producing the digest is executing concurrently, without any lock enforced. */ uint byte_count_copy= m_token_array_length < from->m_byte_count ? m_token_array_length : from->m_byte_count; if (byte_count_copy > 0) { m_full= from->m_full; m_byte_count= byte_count_copy; m_charset_number= from->m_charset_number; memcpy(m_token_array, from->m_token_array, m_byte_count); memcpy(m_md5, from->m_md5, MD5_HASH_SIZE); } else { m_full= false; m_byte_count= 0; m_charset_number= 0; } } }; typedef struct sql_digest_storage sql_digest_storage; /** Compute a digest hash. @param digest_storage The digest @param [out] md5 The computed digest hash. This parameter is a buffer of size @c MD5_HASH_SIZE. */ void compute_digest_md5(const sql_digest_storage *digest_storage, unsigned char *md5); /** Compute a digest text. A 'digest text' is a textual representation of a query, where: - comments are removed, - non significant spaces are removed, - literal values are replaced with a special '?' marker, - lists of values are collapsed using a shorter notation @param digest_storage The digest @param [out] digest_text @param digest_text_length Size of @c digest_text. @param [out] truncated true if the text representation was truncated */ void compute_digest_text(const sql_digest_storage *digest_storage, String *digest_text); #endif wsrep_trans_observer.h 0000644 00000043376 15156036132 0011212 0 ustar 00 /* Copyright 2016-2025 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #ifndef WSREP_TRANS_OBSERVER_H #define WSREP_TRANS_OBSERVER_H #include "my_global.h" #include "mysql/service_wsrep.h" #include "wsrep_applier.h" /* wsrep_apply_error */ #include "wsrep_xid.h" #include "wsrep_thd.h" #include "wsrep_binlog.h" /* register/deregister group commit */ #include "my_dbug.h" class THD; void wsrep_commit_empty(THD* thd, bool all); /* Return true if THD has active wsrep transaction. */ static inline bool wsrep_is_active(THD* thd) { return (thd->wsrep_cs().state() != wsrep::client_state::s_none && thd->wsrep_cs().transaction().active() && !thd->internal_transaction()); } /* Return true if transaction is ordered. */ static inline bool wsrep_is_ordered(THD* thd) { return thd->wsrep_trx().ordered(); } /* Return true if transaction has been BF aborted but has not been rolled back yet. It is required that the caller holds thd->LOCK_thd_data. */ static inline bool wsrep_must_abort(THD* thd) { mysql_mutex_assert_owner(&thd->LOCK_thd_data); return (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort); } /* Return true if the transaction must be replayed. */ static inline bool wsrep_must_replay(THD* thd) { return (thd->wsrep_trx().state() == wsrep::transaction::s_must_replay); } /* Return true if transaction has not been committed. Note that we don't require thd->LOCK_thd_data here. Calling this method makes sense only from codepaths which are past ordered_commit state and the wsrep transaction is immune to BF aborts at that point. */ static inline bool wsrep_not_committed(THD* thd) { return (thd->wsrep_trx().state() != wsrep::transaction::s_committed); } /* Return true if THD is either committing a transaction or statement is autocommit. */ static inline bool wsrep_is_real(THD* thd, bool all) { return (all || thd->transaction->all.ha_list == 0); } /* Check if a transaction has generated changes. */ static inline bool wsrep_has_changes(THD* thd) { // Transaction has changes to replicate if it // has appended one or more certification keys, // and has actual changes to replicate in binlog // cache. Except for streaming replication, // where commit message may have no payload. return !thd->wsrep_trx().is_empty() && (!wsrep_is_binlog_cache_empty(thd) || thd->wsrep_trx().is_streaming()); } /* Check if an active transaction has been BF aborted. */ static inline bool wsrep_is_bf_aborted(THD* thd) { return (thd->wsrep_trx().active() && thd->wsrep_trx().bf_aborted()); } static inline int wsrep_check_pk(THD* thd) { if (!wsrep_certify_nonPK) { for (TABLE* table= thd->open_tables; table != NULL; table= table->next) { if (table->key_info == NULL || table->s->primary_key == MAX_KEY) { WSREP_DEBUG("No primary key found for table %s.%s", table->s->db.str, table->s->table_name.str); wsrep_override_error(thd, ER_LOCK_DEADLOCK); return 1; } } } return 0; } static inline bool wsrep_streaming_enabled(THD* thd) { return (thd->wsrep_sr().fragment_size() > 0); } /* Return number of fragments successfully certified for the current statement. */ static inline size_t wsrep_fragments_certified_for_stmt(THD* thd) { return thd->wsrep_trx().fragments_certified_for_statement(); } static inline int wsrep_start_transaction(THD* thd, wsrep_trx_id_t trx_id) { if (thd->wsrep_cs().state() != wsrep::client_state::s_none) { if (wsrep_is_active(thd) == false) return thd->wsrep_cs().start_transaction(wsrep::transaction_id(trx_id)); } return 0; } /**/ static inline int wsrep_start_trx_if_not_started(THD* thd) { int ret= 0; DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_local); if (thd->wsrep_trx().active() == false) { ret= wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); } return ret; } /* Called after each row operation. Return zero on succes, non-zero on failure. */ static inline int wsrep_after_row_internal(THD* thd) { if (thd->wsrep_cs().state() != wsrep::client_state::s_none && wsrep_thd_is_local(thd)) { if (wsrep_check_pk(thd)) { return 1; } else if (wsrep_streaming_enabled(thd)) { return thd->wsrep_cs().after_row(); } } return 0; } /* Helper method to determine whether commit time hooks should be run for the transaction. Commit hooks must be run in the following cases: - The transaction is local and has generated write set and is committing. - The transaction has been BF aborted - Is running in high priority mode and is ordered. This can be replayer, applier or storage access. */ static inline bool wsrep_run_commit_hook(THD* thd, bool all) { DBUG_ENTER("wsrep_run_commit_hook"); DBUG_PRINT("wsrep", ("Is_active: %d is_real %d has_changes %d is_applying %d " "is_ordered: %d", wsrep_is_active(thd), wsrep_is_real(thd, all), wsrep_has_changes(thd), wsrep_thd_is_applying(thd), wsrep_is_ordered(thd))); /* skipping non-wsrep threads */ if (!WSREP(thd)) DBUG_RETURN(false); /* Is MST commit or autocommit? */ bool ret= wsrep_is_active(thd) && wsrep_is_real(thd, all); /* Do not commit if we are aborting */ ret= ret && (thd->wsrep_trx().state() != wsrep::transaction::s_aborting); if (ret && !(wsrep_has_changes(thd) || /* Has generated write set */ /* Is high priority (replay, applier, storage) and the transaction is scheduled for commit ordering */ (wsrep_thd_is_applying(thd) && wsrep_is_ordered(thd)))) { mysql_mutex_lock(&thd->LOCK_thd_data); DBUG_PRINT("wsrep", ("state: %s", wsrep::to_c_string(thd->wsrep_trx().state()))); /* Transaction is local but has no changes, the commit hooks will be skipped and the wsrep transaction is terminated in wsrep_commit_empty() */ if (thd->wsrep_trx().state() == wsrep::transaction::s_executing) { ret= false; } mysql_mutex_unlock(&thd->LOCK_thd_data); } mysql_mutex_lock(&thd->LOCK_thd_data); /* Transaction creating sequence is TOI or RSU, CREATE SEQUENCE = CREATE + INSERT (initial value) and replicated using statement based replication, thus the commit hooks will be skipped. For TEMPORARY SEQUENCES commit hooks will be done as CREATE + INSERT is not replicated and needs to be committed locally. */ if (ret && (thd->wsrep_cs().mode() == wsrep::client_state::m_toi || thd->wsrep_cs().mode() == wsrep::client_state::m_rsu) && thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE && !thd->lex->tmp_table()) ret= false; mysql_mutex_unlock(&thd->LOCK_thd_data); DBUG_PRINT("wsrep", ("return: %d", ret)); DBUG_RETURN(ret); } /* Called before the transaction is prepared. Return zero on succes, non-zero on failure. */ static inline int wsrep_before_prepare(THD* thd, bool all) { DBUG_ENTER("wsrep_before_prepare"); WSREP_DEBUG("wsrep_before_prepare: %d", wsrep_is_real(thd, all)); int ret= 0; DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); if ((ret= thd->wsrep_parallel_slave_wait_for_prior_commit())) { DBUG_RETURN(ret); } if ((ret= thd->wsrep_cs().before_prepare()) == 0) { DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined()); /* Here we init xid with UUID and wsrep seqno. GTID is set to undefined because commit order is decided later in wsrep_before_commit(). wsrep_before_prepare() is executed out of order. */ wsrep_xid_init(&thd->wsrep_xid, thd->wsrep_trx().ws_meta().gtid(), wsrep_gtid_server.undefined()); } mysql_mutex_lock(&thd->LOCK_thd_kill); if (thd->killed) wsrep_backup_kill_for_commit(thd); mysql_mutex_unlock(&thd->LOCK_thd_kill); DBUG_RETURN(ret); } /* Called after the transaction has been prepared. Return zero on succes, non-zero on failure. */ static inline int wsrep_after_prepare(THD* thd, bool all) { DBUG_ENTER("wsrep_after_prepare"); WSREP_DEBUG("wsrep_after_prepare: %d", wsrep_is_real(thd, all)); DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); int ret= thd->wsrep_cs().after_prepare(); DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error() || thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay); DBUG_RETURN(ret); } /* Called before the transaction is committed. This function must be called from both client and applier contexts before commit. Return zero on succes, non-zero on failure. */ static inline int wsrep_before_commit(THD* thd, bool all) { DBUG_ENTER("wsrep_before_commit"); WSREP_DEBUG("wsrep_before_commit: %d, %lld", wsrep_is_real(thd, all), (long long)wsrep_thd_trx_seqno(thd)); THD_STAGE_INFO(thd, stage_waiting_certification); int ret= 0; DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); if ((ret= thd->wsrep_cs().before_commit()) == 0) { DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined()); if (!thd->variables.gtid_seq_no && (thd->wsrep_trx().ws_meta().flags() & wsrep::provider::flag::commit)) { uint64 seqno= 0; if (thd->variables.wsrep_gtid_seq_no && thd->variables.wsrep_gtid_seq_no > wsrep_gtid_server.seqno()) { seqno= thd->variables.wsrep_gtid_seq_no; wsrep_gtid_server.seqno(thd->variables.wsrep_gtid_seq_no); } else { seqno= wsrep_gtid_server.seqno_inc(); } thd->variables.wsrep_gtid_seq_no= 0; thd->wsrep_current_gtid_seqno= seqno; if (mysql_bin_log.is_open() && wsrep_gtid_mode) { thd->variables.gtid_seq_no= seqno; thd->variables.gtid_domain_id= wsrep_gtid_server.domain_id; thd->variables.server_id= wsrep_gtid_server.server_id; } } wsrep_xid_init(&thd->wsrep_xid, thd->wsrep_trx().ws_meta().gtid(), wsrep_gtid_server.gtid()); wsrep_register_for_group_commit(thd); } mysql_mutex_lock(&thd->LOCK_thd_kill); if (thd->killed) wsrep_backup_kill_for_commit(thd); mysql_mutex_unlock(&thd->LOCK_thd_kill); DBUG_RETURN(ret); } /* Called after the transaction has been ordered for commit. This function must be called from both client and applier contexts after the commit has been ordered. @param thd Pointer to THD @param all @param err Error buffer in case of applying error Return zero on succes, non-zero on failure. */ static inline int wsrep_ordered_commit(THD* thd, bool all) { DBUG_ENTER("wsrep_ordered_commit"); WSREP_DEBUG("wsrep_ordered_commit: %d %lld", wsrep_is_real(thd, all), (long long) wsrep_thd_trx_seqno(thd)); DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); DBUG_RETURN(thd->wsrep_cs().ordered_commit()); } /* Called after the transaction has been committed. Return zero on succes, non-zero on failure. */ static inline int wsrep_after_commit(THD* thd, bool all) { DBUG_ENTER("wsrep_after_commit"); WSREP_DEBUG("wsrep_after_commit: %d, %d, %lld, %d", wsrep_is_real(thd, all), wsrep_is_active(thd), (long long)wsrep_thd_trx_seqno(thd), wsrep_has_changes(thd)); DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); if (thd->internal_transaction()) DBUG_RETURN(0); int ret= 0; if (thd->wsrep_trx().state() == wsrep::transaction::s_committing) { ret= thd->wsrep_cs().ordered_commit(); } wsrep_unregister_from_group_commit(thd); thd->wsrep_xid.null(); DBUG_RETURN(ret || thd->wsrep_cs().after_commit()); } /* Called before the transaction is rolled back. Return zero on succes, non-zero on failure. */ static inline int wsrep_before_rollback(THD* thd, bool all) { DBUG_ENTER("wsrep_before_rollback"); int ret= 0; if (wsrep_is_active(thd)) { if (!all && thd->in_active_multi_stmt_transaction()) { if (wsrep_emulate_bin_log) { wsrep_thd_binlog_stmt_rollback(thd); } if (thd->wsrep_trx().is_streaming() && (wsrep_fragments_certified_for_stmt(thd) > 0)) { /* Non-safe statement rollback during SR multi statement transaction. A statement rollback is considered unsafe, if the same statement has already replicated one or more fragments. Self abort the transaction, the actual rollback and error handling will be done in after statement phase. */ WSREP_DEBUG("statement rollback is not safe for streaming replication"); wsrep_thd_self_abort(thd); ret= 0; } } else if (wsrep_is_real(thd, all) && thd->wsrep_trx().state() != wsrep::transaction::s_aborted) { /* Real transaction rolling back and wsrep abort not completed yet */ /* Reset XID so that it does not trigger writing serialization history in InnoDB. This needs to be avoided because rollback may happen out of order and replay may follow. */ thd->wsrep_xid.null(); ret= thd->wsrep_cs().before_rollback(); } } DBUG_RETURN(ret); } /* Called after the transaction has been rolled back. Return zero on succes, non-zero on failure. */ static inline int wsrep_after_rollback(THD* thd, bool all) { DBUG_ENTER("wsrep_after_rollback"); DBUG_RETURN((wsrep_is_real(thd, all) && wsrep_is_active(thd) && thd->wsrep_cs().transaction().state() != wsrep::transaction::s_aborted) ? thd->wsrep_cs().after_rollback() : 0); } static inline int wsrep_before_statement(THD* thd) { return (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction() ? thd->wsrep_cs().before_statement() : 0); } static inline int wsrep_after_statement(THD* thd) { DBUG_ENTER("wsrep_after_statement"); int ret= ((thd->wsrep_cs().state() != wsrep::client_state::s_none && thd->wsrep_cs().mode() == Wsrep_client_state::m_local) && !thd->internal_transaction() ? thd->wsrep_cs().after_statement() : 0); if (wsrep_is_active(thd)) { mysql_mutex_lock(&thd->LOCK_thd_kill); wsrep_restore_kill_after_commit(thd); mysql_mutex_unlock(&thd->LOCK_thd_kill); } DBUG_RETURN(ret); } static inline void wsrep_after_apply(THD* thd) { DBUG_ASSERT(wsrep_thd_is_applying(thd)); WSREP_DEBUG("wsrep_after_apply %lld", thd->thread_id); if (!thd->internal_transaction()) thd->wsrep_cs().after_applying(); } static inline void wsrep_open(THD* thd) { DBUG_ENTER("wsrep_open"); if (WSREP_ON_) { /* WSREP_PROVIDER_EXISTS_ cannot be set if WSREP_ON_ is not set */ DBUG_ASSERT(WSREP_PROVIDER_EXISTS_); thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); thd->wsrep_cs().debug_log_level(wsrep_debug); if (!thd->wsrep_applier && thd->variables.wsrep_trx_fragment_size) { thd->wsrep_cs().enable_streaming( wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit), size_t(thd->variables.wsrep_trx_fragment_size)); } } DBUG_VOID_RETURN; } static inline void wsrep_close(THD* thd) { DBUG_ENTER("wsrep_close"); if (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction()) { thd->wsrep_cs().close(); } DBUG_VOID_RETURN; } static inline void wsrep_cleanup(THD* thd) { DBUG_ENTER("wsrep_cleanup"); if (thd->wsrep_cs().state() != wsrep::client_state::s_none) { thd->wsrep_cs().cleanup(); } DBUG_VOID_RETURN; } static inline void wsrep_wait_rollback_complete_and_acquire_ownership(THD *thd) { DBUG_ENTER("wsrep_wait_rollback_complete_and_acquire_ownership"); if (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction()) { thd->wsrep_cs().wait_rollback_complete_and_acquire_ownership(); } DBUG_VOID_RETURN; } static inline int wsrep_before_command(THD* thd, bool keep_command_error) { return (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction() ? thd->wsrep_cs().before_command(keep_command_error) : 0); } static inline int wsrep_before_command(THD* thd) { return wsrep_before_command(thd, false); } /* Called after each command. Return zero on success, non-zero on failure. */ static inline void wsrep_after_command_before_result(THD* thd) { if (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction()) { thd->wsrep_cs().after_command_before_result(); } } static inline void wsrep_after_command_after_result(THD* thd) { if (thd->wsrep_cs().state() != wsrep::client_state::s_none && !thd->internal_transaction()) { thd->wsrep_cs().after_command_after_result(); } } static inline void wsrep_after_command_ignore_result(THD* thd) { wsrep_after_command_before_result(thd); DBUG_ASSERT(!thd->wsrep_cs().current_error()); wsrep_after_command_after_result(thd); } static inline enum wsrep::client_error wsrep_current_error(THD* thd) { return thd->wsrep_cs().current_error(); } static inline enum wsrep::provider::status wsrep_current_error_status(THD* thd) { return thd->wsrep_cs().current_error_status(); } #endif /* WSREP_TRANS_OBSERVER */ protocol.h 0000644 00000030431 15156036133 0006562 0 ustar 00 #ifndef PROTOCOL_INCLUDED #define PROTOCOL_INCLUDED /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_error.h" #include "my_decimal.h" /* my_decimal */ #include "sql_type.h" class i_string; class Field; class Send_field; class THD; class Item_param; struct TABLE_LIST; typedef struct st_mysql_field MYSQL_FIELD; typedef struct st_mysql_rows MYSQL_ROWS; class Protocol { protected: String *packet; /* Used by net_store_data() for charset conversions */ String *convert; uint field_pos; #ifndef DBUG_OFF const Type_handler **field_handlers; bool valid_handler(uint pos, protocol_send_type_t type) const { return field_handlers == 0 || field_handlers[field_pos]->protocol_send_type() == type; } #endif uint field_count; virtual bool net_store_data(const uchar *from, size_t length); virtual bool net_store_data_cs(const uchar *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); virtual bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, bool); virtual bool net_send_error_packet(THD *, uint, const char *, const char *); #ifdef EMBEDDED_LIBRARY char **next_field; MYSQL_FIELD *next_mysql_field; MEM_ROOT *alloc; #endif bool needs_conversion(CHARSET_INFO *fromcs, CHARSET_INFO *tocs) const { // 'tocs' is set 0 when client issues SET character_set_results=NULL return tocs && !my_charset_same(fromcs, tocs) && fromcs != &my_charset_bin && tocs != &my_charset_bin; } /* The following two are low-level functions that are invoked from higher-level store_xxx() funcs. The data is stored into this->packet. */ bool store_string_aux(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); virtual bool send_ok(uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong last_insert_id, const char *message); virtual bool send_eof(uint server_status, uint statement_warn_count); virtual bool send_error(uint sql_errno, const char *err_msg, const char *sql_state); CHARSET_INFO *character_set_results() const; public: THD *thd; Protocol(THD *thd_arg) { init(thd_arg); } virtual ~Protocol() = default; void init(THD* thd_arg); enum { SEND_NUM_ROWS= 1, SEND_EOF= 2, SEND_FORCE_COLUMN_INFO= 4 }; virtual bool send_result_set_metadata(List<Item> *list, uint flags); bool send_list_fields(List<Field> *list, const TABLE_LIST *table_list); bool send_result_set_row(List<Item> *row_items); bool store(I_List<i_string> *str_list); bool store(I_List<i_string_pair> *str_list); bool store_string_or_null(const char *from, CHARSET_INFO *cs); bool store_warning(const char *from, size_t length); String *storage_packet() { return packet; } inline void free() { packet->free(); } virtual bool write(); inline bool store(int from) { return store_long((longlong) from); } inline bool store(uint32 from) { return store_long((longlong) from); } inline bool store(longlong from) { return store_longlong((longlong) from, 0); } inline bool store(ulonglong from) { return store_longlong((longlong) from, 1); } inline bool store(String *str) { return store((char*) str->ptr(), str->length(), str->charset()); } inline bool store(const LEX_CSTRING *from, CHARSET_INFO *cs) { return store(from->str, from->length, cs); } virtual bool prepare_for_send(uint num_columns) { field_count= num_columns; return 0; } virtual bool flush(); virtual void end_partial_result_set(THD *thd); virtual void prepare_for_resend()=0; virtual bool store_null()=0; virtual bool store_tiny(longlong from)=0; virtual bool store_short(longlong from)=0; virtual bool store_long(longlong from)=0; virtual bool store_longlong(longlong from, bool unsigned_flag)=0; virtual bool store_decimal(const my_decimal *)=0; virtual bool store_str(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0; virtual bool store_float(float from, uint32 decimals)=0; virtual bool store_double(double from, uint32 decimals)=0; virtual bool store_datetime(MYSQL_TIME *time, int decimals)=0; virtual bool store_date(MYSQL_TIME *time)=0; virtual bool store_time(MYSQL_TIME *time, int decimals)=0; virtual bool store(Field *field)=0; // Various useful wrappers for the virtual store*() methods. // Backward wrapper for store_str() bool store(const char *from, size_t length, CHARSET_INFO *cs) { return store_str(from, length, cs, character_set_results()); } bool store_lex_cstring(const LEX_CSTRING &s, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { return store_str(s.str, (uint) s.length, fromcs, tocs); } bool store_binary_string(const char *str, size_t length) { return store_str(str, (uint) length, &my_charset_bin, &my_charset_bin); } bool store_ident(const LEX_CSTRING &s) { return store_lex_cstring(s, system_charset_info, character_set_results()); } // End of wrappers virtual bool send_out_parameters(List<Item_param> *sp_params)=0; #ifdef EMBEDDED_LIBRARY bool begin_dataset(); bool begin_dataset(THD *thd, uint numfields); virtual void remove_last_row() {} #else void remove_last_row() {} #endif enum enum_protocol_type { /* Before adding a new type, please make sure there is enough storage for it in Query_cache_query_flags. */ PROTOCOL_TEXT= 0, PROTOCOL_BINARY= 1, PROTOCOL_LOCAL= 2, PROTOCOL_DISCARD= 3 /* Should be last, not used by Query_cache */ }; virtual enum enum_protocol_type type()= 0; virtual bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); bool net_send_error(THD *thd, uint sql_errno, const char *err, const char* sqlstate); void end_statement(); }; /** Class used for the old (MySQL 4.0 protocol). */ class Protocol_text :public Protocol { StringBuffer<FLOATING_POINT_BUFFER> buffer; bool store_numeric_string_aux(const char *from, size_t length); public: Protocol_text(THD *thd_arg) :Protocol(thd_arg) {}; bool __attribute__((warn_unused_result)) allocate(size_t size) { return packet->alloc(size); } void prepare_for_resend() override; bool store_null() override; bool store_tiny(longlong from) override; bool store_short(longlong from) override; bool store_long(longlong from) override; bool store_longlong(longlong from, bool unsigned_flag) override; bool store_decimal(const my_decimal *) override; bool store_str(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) override; bool store_datetime(MYSQL_TIME *time, int decimals) override; bool store_date(MYSQL_TIME *time) override; bool store_time(MYSQL_TIME *time, int decimals) override; bool store_float(float nr, uint32 decimals) override; bool store_double(double from, uint32 decimals) override; bool store(Field *field) override; bool send_out_parameters(List<Item_param> *sp_params) override; bool store_numeric_zerofill_str(const char *from, size_t length, protocol_send_type_t send_type); #ifdef EMBEDDED_LIBRARY void remove_last_row() override; #endif bool store_field_metadata(const THD *thd, const Send_field &field, CHARSET_INFO *charset_for_protocol, uint pos); bool store_item_metadata(THD *thd, Item *item, uint pos); bool store_field_metadata_for_list_fields(const THD *thd, Field *field, const TABLE_LIST *table_list, uint pos); enum enum_protocol_type type() override { return PROTOCOL_TEXT; }; }; class Protocol_binary final :public Protocol { private: uint bit_fields; public: Protocol_binary(THD *thd_arg) :Protocol(thd_arg) {} bool prepare_for_send(uint num_columns) override; void prepare_for_resend() override; #ifdef EMBEDDED_LIBRARY bool write() override; bool net_store_data(const uchar *from, size_t length) override; bool net_store_data_cs(const uchar *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) override; #endif bool store_null() override; bool store_tiny(longlong from) override; bool store_short(longlong from) override; bool store_long(longlong from) override; bool store_longlong(longlong from, bool unsigned_flag) override; bool store_decimal(const my_decimal *) override; bool store_str(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) override; bool store_datetime(MYSQL_TIME *time, int decimals) override; bool store_date(MYSQL_TIME *time) override; bool store_time(MYSQL_TIME *time, int decimals) override; bool store_float(float nr, uint32 decimals) override; bool store_double(double from, uint32 decimals) override; bool store(Field *field) override; bool send_out_parameters(List<Item_param> *sp_params) override; enum enum_protocol_type type() override { return PROTOCOL_BINARY; }; }; /* A helper for "ANALYZE $stmt" which looks a real network procotol but doesn't write results to the network. At first glance, class select_send looks like a more appropriate place to implement the "write nothing" hook. This is not true, because - we need to evaluate the value of every item, and do it the way select_send does it (i.e. call item->val_int() or val_real() or...) - select_send::send_data() has some other code, like telling the storage engine that the row can be unlocked. We want to keep that also. as a result, "ANALYZE $stmt" uses a select_send_analyze which still uses select_send::send_data() & co., and also uses Protocol_discard object. */ class Protocol_discard final : public Protocol { public: Protocol_discard(THD *thd_arg) : Protocol(thd_arg) {} bool write() override { return 0; } bool send_result_set_metadata(List<Item> *, uint) override { return 0; } bool send_eof(uint, uint) override { return 0; } void prepare_for_resend() override { IF_DBUG(field_pos= 0,); } bool send_out_parameters(List<Item_param> *sp_params) override { return false; } /* Provide dummy overrides for any storage methods so that we avoid allocating and copying of data */ bool store_null() override { return false; } bool store_tiny(longlong) override { return false; } bool store_short(longlong) override { return false; } bool store_long(longlong) override { return false; } bool store_longlong(longlong, bool) override { return false; } bool store_decimal(const my_decimal *) override { return false; } bool store_str(const char *, size_t, CHARSET_INFO *, CHARSET_INFO *) override { return false; } bool store_datetime(MYSQL_TIME *, int) override { return false; } bool store_date(MYSQL_TIME *) override { return false; } bool store_time(MYSQL_TIME *, int) override { return false; } bool store_float(float, uint32) override { return false; } bool store_double(double, uint32) override { return false; } bool store(Field *) override { return false; } enum enum_protocol_type type() override { return PROTOCOL_DISCARD; }; }; void send_warning(THD *thd, uint sql_errno, const char *err=0); void net_send_progress_packet(THD *thd); uchar *net_store_data(uchar *to,const uchar *from, size_t length); uchar *net_store_data(uchar *to,int32 from); uchar *net_store_data(uchar *to,longlong from); #endif /* PROTOCOL_INCLUDED */ mem_root_array.h 0000644 00000015702 15156036133 0007744 0 ustar 00 /* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MEM_ROOT_ARRAY_INCLUDED #define MEM_ROOT_ARRAY_INCLUDED #include <my_alloc.h> /** A typesafe replacement for DYNAMIC_ARRAY. We use MEM_ROOT for allocating storage, rather than the C++ heap. The interface is chosen to be similar to std::vector. @remark Unlike DYNAMIC_ARRAY, elements are properly copied (rather than memcpy()d) if the underlying array needs to be expanded. @remark Depending on has_trivial_destructor, we destroy objects which are removed from the array (including when the array object itself is destroyed). @remark Note that MEM_ROOT has no facility for reusing free space, so don't use this if multiple re-expansions are likely to happen. @param Element_type The type of the elements of the container. Elements must be copyable. @param has_trivial_destructor If true, we don't destroy elements. We could have used type traits to determine this. __has_trivial_destructor is supported by some (but not all) compilers we use. */ template<typename Element_type, bool has_trivial_destructor> class Mem_root_array { public: /// Convenience typedef, same typedef name as std::vector typedef Element_type value_type; Mem_root_array(MEM_ROOT *root) : m_root(root), m_array(NULL), m_size(0), m_capacity(0) { DBUG_ASSERT(m_root != NULL); } Mem_root_array(MEM_ROOT *root, size_t n, const value_type &val= value_type()) : m_root(root), m_array(NULL), m_size(0), m_capacity(0) { resize(n, val); } ~Mem_root_array() { clear(); } Element_type &at(size_t n) { DBUG_ASSERT(n < size()); return m_array[n]; } const Element_type &at(size_t n) const { DBUG_ASSERT(n < size()); return m_array[n]; } Element_type &operator[](size_t n) { return at(n); } const Element_type &operator[](size_t n) const { return at(n); } Element_type &back() { return at(size() - 1); } const Element_type &back() const { return at(size() - 1); } // Returns a pointer to the first element in the array. Element_type *begin() { return &m_array[0]; } const Element_type *begin() const { return &m_array[0]; } // Returns a pointer to the past-the-end element in the array. Element_type *end() { return &m_array[size()]; } const Element_type *end() const { return &m_array[size()]; } // Erases all of the elements. void clear() { if (!empty()) chop(0); } /* Chops the tail off the array, erasing all tail elements. @param pos Index of first element to erase. */ void chop(const size_t pos) { DBUG_ASSERT(pos < m_size); if (!has_trivial_destructor) { for (size_t ix= pos; ix < m_size; ++ix) { Element_type *p= &m_array[ix]; p->~Element_type(); // Destroy discarded element. } } m_size= pos; } /* Reserves space for array elements. Copies over existing elements, in case we are re-expanding the array. @param n number of elements. @retval true if out-of-memory, false otherwise. */ bool reserve(size_t n) { if (n <= m_capacity) return false; void *mem= alloc_root(m_root, n * element_size()); if (!mem) return true; Element_type *array= static_cast<Element_type*>(mem); // Copy all the existing elements into the new array. for (size_t ix= 0; ix < m_size; ++ix) { Element_type *new_p= &array[ix]; Element_type *old_p= &m_array[ix]; new (new_p) Element_type(*old_p); // Copy into new location. if (!has_trivial_destructor) old_p->~Element_type(); // Destroy the old element. } // Forget the old array. m_array= array; m_capacity= n; return false; } /* Adds a new element at the end of the array, after its current last element. The content of this new element is initialized to a copy of the input argument. @param element Object to copy. @retval true if out-of-memory, false otherwise. */ bool push_back(const Element_type &element) { const size_t min_capacity= 20; const size_t expansion_factor= 2; if (0 == m_capacity && reserve(min_capacity)) return true; if (m_size == m_capacity && reserve(m_capacity * expansion_factor)) return true; Element_type *p= &m_array[m_size++]; new (p) Element_type(element); return false; } /** Removes the last element in the array, effectively reducing the container size by one. This destroys the removed element. */ void pop_back() { DBUG_ASSERT(!empty()); if (!has_trivial_destructor) back().~Element_type(); m_size-= 1; } /** Resizes the container so that it contains n elements. If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them). If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized. If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place. Notice that this function changes the actual content of the container by inserting or erasing elements from it. */ void resize(size_t n, const value_type &val= value_type()) { if (n == m_size) return; if (n > m_size) { if (!reserve(n)) { while (n != m_size) push_back(val); } return; } if (!has_trivial_destructor) { while (n != m_size) pop_back(); } m_size= n; } size_t capacity() const { return m_capacity; } size_t element_size() const { return sizeof(Element_type); } bool empty() const { return size() == 0; } size_t size() const { return m_size; } const MEM_ROOT *mem_root() const { return m_root; } private: MEM_ROOT *const m_root; Element_type *m_array; size_t m_size; size_t m_capacity; // Not (yet) implemented. Mem_root_array(const Mem_root_array&); Mem_root_array &operator=(const Mem_root_array&); }; #endif // MEM_ROOT_ARRAY_INCLUDED wsrep_client_service.h 0000644 00000005000 15156036133 0011131 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @file wsrep_client_service.h This file provides declaratios for client service implementation. See wsrep/client_service.hpp for interface documentation. */ #ifndef WSREP_CLIENT_SERVICE_H #define WSREP_CLIENT_SERVICE_H /* wsrep-lib */ #include "wsrep/client_service.hpp" #include "wsrep/client_state.hpp" #include "wsrep/exception.hpp" /* not_implemented_error, remove when finished */ class THD; class Wsrep_client_state; class Wsrep_high_priority_context; class Wsrep_client_service : public wsrep::client_service { public: Wsrep_client_service(THD*, Wsrep_client_state&); bool interrupted(wsrep::unique_lock<wsrep::mutex>&) const override; void reset_globals() override; void store_globals() override; int prepare_data_for_replication() override; void cleanup_transaction() override; bool statement_allowed_for_streaming() const override; size_t bytes_generated() const override; int prepare_fragment_for_replication(wsrep::mutable_buffer&, size_t&) override; int remove_fragments() override; void emergency_shutdown() override { throw wsrep::not_implemented_error(); } void will_replay() override; void signal_replayed() override; enum wsrep::provider::status replay() override; enum wsrep::provider::status replay_unordered() override; void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&) override; enum wsrep::provider::status commit_by_xid() override; bool is_explicit_xa() override { return false; } bool is_prepared_xa() override { return false; } bool is_xa_rollback() override { return false; } void debug_sync(const char*) override; void debug_crash(const char*) override; int bf_rollback() override; private: friend class Wsrep_server_service; THD* m_thd; Wsrep_client_state& m_client_state; }; #endif /* WSREP_CLIENT_SERVICE_H */ gcalc_slicescan.h 0000644 00000041570 15156036133 0010024 0 ustar 00 /* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved. Copyright (C) 2011 Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef GCALC_SLICESCAN_INCLUDED #define GCALC_SLICESCAN_INCLUDED #ifndef DBUG_OFF // #define GCALC_CHECK_WITH_FLOAT #else #define GCALC_DBUG_OFF #endif /*DBUG_OFF*/ #ifndef GCALC_DBUG_OFF #define GCALC_DBUG_PRINT(b) DBUG_PRINT("Gcalc", b) #define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc " a) #define GCALC_DBUG_RETURN(r) DBUG_RETURN(r) #define GCALC_DBUG_VOID_RETURN DBUG_VOID_RETURN #define GCALC_DBUG_ASSERT(r) DBUG_ASSERT(r) #else #define GCALC_DBUG_PRINT(b) do {} while(0) #define GCALC_DBUG_ENTER(a) do {} while(0) #define GCALC_DBUG_RETURN(r) return (r) #define GCALC_DBUG_VOID_RETURN do {} while(0) #define GCALC_DBUG_ASSERT(r) do {} while(0) #endif /*GCALC_DBUG_OFF*/ #define GCALC_TERMINATED(state_var) (state_var && (*state_var)) #define GCALC_SET_TERMINATED(state_var, val) state_var= val #define GCALC_DECL_TERMINATED_STATE(varname) \ volatile int *varname; /* Gcalc_dyn_list class designed to manage long lists of same-size objects with the possible efficiency. It allocates fixed-size blocks of memory (blk_size specified at the time of creation). When new object is added to the list, it occupies part of this block until it's full. Then the new block is allocated. Freed objects are chained to the m_free list, and if it's not empty, the newly added object is taken from this list instead the block. */ class Gcalc_dyn_list { public: class Item { public: Item *next; }; Gcalc_dyn_list(size_t blk_size, size_t sizeof_item); Gcalc_dyn_list(const Gcalc_dyn_list &dl); ~Gcalc_dyn_list(); Item *new_item() { Item *result; if (m_free) { result= m_free; m_free= m_free->next; } else result= alloc_new_blk(); return result; } inline void free_item(Item *item) { item->next= m_free; m_free= item; } inline void free_list(Item **list, Item **hook) { *hook= m_free; m_free= *list; } void free_list(Item *list) { Item **hook= &list; while (*hook) hook= &(*hook)->next; free_list(&list, hook); } void reset(); void cleanup(); protected: size_t m_blk_size; size_t m_sizeof_item; unsigned int m_points_per_blk; void *m_first_blk; void **m_blk_hook; Item *m_free; Item *m_keep; Item *alloc_new_blk(); void format_blk(void* block); inline Item *ptr_add(Item *ptr, int n_items) { return (Item *)(((char*)ptr) + n_items * m_sizeof_item); } }; /* Internal Gcalc coordinates to provide the precise calculations */ #define GCALC_DIG_BASE 1000000000 typedef uint32 gcalc_digit_t; typedef unsigned long long gcalc_coord2; typedef gcalc_digit_t Gcalc_internal_coord; #define GCALC_COORD_BASE 2 #define GCALC_COORD_BASE2 4 #define GCALC_COORD_BASE3 6 #define GCALC_COORD_BASE4 8 #define GCALC_COORD_BASE5 10 typedef gcalc_digit_t Gcalc_coord1[GCALC_COORD_BASE]; typedef gcalc_digit_t Gcalc_coord2[GCALC_COORD_BASE*2]; typedef gcalc_digit_t Gcalc_coord3[GCALC_COORD_BASE*3]; void gcalc_mul_coord(Gcalc_internal_coord *result, int result_len, const Gcalc_internal_coord *a, int a_len, const Gcalc_internal_coord *b, int b_len); void gcalc_add_coord(Gcalc_internal_coord *result, int result_len, const Gcalc_internal_coord *a, const Gcalc_internal_coord *b); void gcalc_sub_coord(Gcalc_internal_coord *result, int result_len, const Gcalc_internal_coord *a, const Gcalc_internal_coord *b); int gcalc_cmp_coord(const Gcalc_internal_coord *a, const Gcalc_internal_coord *b, int len); /* Internal coordinates declarations end. */ typedef uint gcalc_shape_info; /* Gcalc_heap represents the 'dynamic list' of Info objects, that contain information about vertexes of all the shapes that take part in some spatial calculation. Can become quite long. After filled, the list is usually sorted and then walked through in the slicescan algorithm. The Gcalc_heap and the algorithm can only operate with two kinds of shapes - polygon and polyline. So all the spatial objects should be represented as sets of these two. */ class Gcalc_heap : public Gcalc_dyn_list { public: enum node_type { nt_shape_node, nt_intersection, nt_eq_node }; class Info : public Gcalc_dyn_list::Item { public: node_type type; union { struct { /* nt_shape_node */ gcalc_shape_info shape; Info *left; Info *right; double x,y; Gcalc_coord1 ix, iy; int top_node; } shape; struct { /* nt_intersection */ /* Line p1-p2 supposed to intersect line p3-p4 */ const Info *p1; const Info *p2; const Info *p3; const Info *p4; void *data; int equal; } intersection; struct { /* nt_eq_node */ const Info *node; void *data; } eq; } node; bool is_bottom() const { GCALC_DBUG_ASSERT(type == nt_shape_node); return !node.shape.left; } bool is_top() const { GCALC_DBUG_ASSERT(type == nt_shape_node); return node.shape.top_node; } bool is_single_node() const { return is_bottom() && is_top(); } void calc_xy(double *x, double *y) const; int equal_pi(const Info *pi) const; #ifdef GCALC_CHECK_WITH_FLOAT void calc_xy_ld(long double *x, long double *y) const; #endif /*GCALC_CHECK_WITH_FLOAT*/ Info *get_next() { return (Info *)next; } const Info *get_next() const { return (const Info *)next; } }; Gcalc_heap(size_t blk_size=8192) : Gcalc_dyn_list(blk_size, sizeof(Info)), m_hook(&m_first), m_n_points(0) {} Gcalc_heap(const Gcalc_heap &gh) : Gcalc_dyn_list(gh), m_hook(&m_first), m_n_points(0) {} void set_extent(double xmin, double xmax, double ymin, double ymax); Info *new_point_info(double x, double y, gcalc_shape_info shape); void free_point_info(Info *i, Gcalc_dyn_list::Item **i_hook); Info *new_intersection(const Info *p1, const Info *p2, const Info *p3, const Info *p4); void prepare_operation(); inline bool ready() const { return m_hook == NULL; } Info *get_first() { return (Info *)m_first; } const Info *get_first() const { return (const Info *)m_first; } Gcalc_dyn_list::Item **get_last_hook() { return m_hook; } void reset(); #ifdef GCALC_CHECK_WITH_FLOAT long double get_double(const Gcalc_internal_coord *c) const; #endif /*GCALC_CHECK_WITH_FLOAT*/ double coord_extent; Gcalc_dyn_list::Item **get_cur_hook() { return m_hook; } private: Gcalc_dyn_list::Item *m_first; Gcalc_dyn_list::Item **m_hook; int m_n_points; }; /* the spatial object has to be represented as a set of simple polygones and polylines to be sent to the slicescan. Gcalc_shape_transporter class and his descendants are used to simplify storing the information about the shape into necessary structures. This base class only fills the Gcalc_heap with the information about shapes and vertices. Normally the Gcalc_shape_transporter family object is sent as a parameter to the 'get_shapes' method of an 'spatial' object so it can pass the spatial information about itself. The virtual methods are treating this data in a way the caller needs. */ class Gcalc_shape_transporter { private: Gcalc_heap::Info *m_first; Gcalc_heap::Info *m_prev; Gcalc_dyn_list::Item **m_prev_hook; int m_shape_started; void int_complete(); protected: Gcalc_heap *m_heap; int int_single_point(gcalc_shape_info Info, double x, double y); int int_add_point(gcalc_shape_info Info, double x, double y); void int_start_line() { DBUG_ASSERT(!m_shape_started); m_shape_started= 1; m_first= m_prev= NULL; } void int_complete_line() { DBUG_ASSERT(m_shape_started== 1); int_complete(); m_shape_started= 0; } void int_start_ring() { DBUG_ASSERT(m_shape_started== 2); m_shape_started= 3; m_first= m_prev= NULL; } void int_complete_ring() { DBUG_ASSERT(m_shape_started== 3); int_complete(); m_shape_started= 2; } void int_start_poly() { DBUG_ASSERT(!m_shape_started); m_shape_started= 2; } void int_complete_poly() { DBUG_ASSERT(m_shape_started== 2); m_shape_started= 0; } bool line_started() { return m_shape_started == 1; }; public: Gcalc_shape_transporter(Gcalc_heap *heap) : m_shape_started(0), m_heap(heap) {} virtual int single_point(double x, double y)=0; virtual int start_line()=0; virtual int complete_line()=0; virtual int start_poly()=0; virtual int complete_poly()=0; virtual int start_ring()=0; virtual int complete_ring()=0; virtual int add_point(double x, double y)=0; virtual int start_collection(int n_objects) { return 0; } virtual int empty_shape() { return 0; } int start_simple_poly() { return start_poly() || start_ring(); } int complete_simple_poly() { return complete_ring() || complete_poly(); } virtual ~Gcalc_shape_transporter() = default; }; enum Gcalc_scan_events { scev_none= 0, scev_point= 1, /* Just a new point in thread */ scev_thread= 2, /* Start of the new thread */ scev_two_threads= 4, /* A couple of new threads started */ scev_intersection= 8, /* Intersection happened */ scev_end= 16, /* Single thread finished */ scev_two_ends= 32, /* A couple of threads finished */ scev_single_point= 64 /* Got single point */ }; /* Gcalc_scan_iterator incapsulates the slicescan algorithm. It takes filled Gcalc_heap as a datasource. Then can be iterated through the vertexes and intersection points with the step() method. After the 'step()' one usually observes the current 'slice' to do the necessary calculations, like looking for intersections, calculating the area, whatever. */ class Gcalc_scan_iterator : public Gcalc_dyn_list { public: class point : public Gcalc_dyn_list::Item { public: Gcalc_coord1 dx; Gcalc_coord1 dy; Gcalc_heap::Info *pi; Gcalc_heap::Info *next_pi; Gcalc_heap::Info *ev_pi; const Gcalc_coord1 *l_border; const Gcalc_coord1 *r_border; point *ev_next; Gcalc_scan_events event; inline const point *c_get_next() const { return (const point *)next; } inline bool is_bottom() const { return !next_pi; } gcalc_shape_info get_shape() const { return pi->node.shape.shape; } inline point *get_next() { return (point *)next; } inline const point *get_next() const { return (const point *)next; } /* Compare the dx_dy parameters regarding the horiz_dir */ /* returns -1 if less, 0 if equal, 1 if bigger */ static int cmp_dx_dy(const Gcalc_coord1 dx_a, const Gcalc_coord1 dy_a, const Gcalc_coord1 dx_b, const Gcalc_coord1 dy_b); static int cmp_dx_dy(const Gcalc_heap::Info *p1, const Gcalc_heap::Info *p2, const Gcalc_heap::Info *p3, const Gcalc_heap::Info *p4); int cmp_dx_dy(const point *p) const; point **next_ptr() { return (point **) &next; } #ifndef GCALC_DBUG_OFF unsigned int thread; #endif /*GCALC_DBUG_OFF*/ #ifdef GCALC_CHECK_WITH_FLOAT void calc_x(long double *x, long double y, long double ix) const; #endif /*GCALC_CHECK_WITH_FLOAT*/ }; /* That class introduced mostly for the 'typecontrol' reason. */ /* only difference from the point classis the get_next() function. */ class event_point : public point { public: inline const event_point *get_next() const { return (const event_point*) ev_next; } int simple_event() const { return !ev_next ? (event & (scev_point | scev_end)) : (!ev_next->ev_next && event == scev_two_ends); } }; class intersection_info : public Gcalc_dyn_list::Item { public: point *edge_a; point *edge_b; Gcalc_coord2 t_a; Gcalc_coord2 t_b; int t_calculated; Gcalc_coord3 x_exp; int x_calculated; Gcalc_coord3 y_exp; int y_calculated; void calc_t() {if (!t_calculated) do_calc_t(); } void calc_y_exp() { if (!y_calculated) do_calc_y(); } void calc_x_exp() { if (!x_calculated) do_calc_x(); } void do_calc_t(); void do_calc_x(); void do_calc_y(); }; class slice_state { public: point *slice; point **event_position_hook; point *event_end; const Gcalc_heap::Info *pi; }; public: Gcalc_scan_iterator(size_t blk_size= 8192); GCALC_DECL_TERMINATED_STATE(killed) void init(Gcalc_heap *points); /* Iterator can be reused */ void reset(); int step(); Gcalc_heap::Info *more_points() { return m_cur_pi; } bool more_trapezoids() { return m_cur_pi && m_cur_pi->next; } const point *get_bottom_points() const { return m_bottom_points; } const point *get_event_position() const { return *state.event_position_hook; } const point *get_event_end() const { return state.event_end; } const event_point *get_events() const { return (const event_point *) (*state.event_position_hook == state.event_end ? m_bottom_points : *state.event_position_hook); } const point *get_b_slice() const { return state.slice; } double get_h() const; double get_y() const; double get_event_x() const; double get_sp_x(const point *sp) const; int intersection_step() const { return state.pi->type == Gcalc_heap::nt_intersection; } const Gcalc_heap::Info *get_cur_pi() const { return state.pi; } private: Gcalc_heap *m_heap; Gcalc_heap::Info *m_cur_pi; slice_state state; #ifndef GCALC_DBUG_OFF unsigned int m_cur_thread; #endif /*GCALC_DBUG_OFF*/ point *m_bottom_points; point **m_bottom_hook; int node_scan(); void eq_scan(); void intersection_scan(); void remove_bottom_node(); int insert_top_node(); int add_intersection(point *sp_a, point *sp_b, Gcalc_heap::Info *pi_from); int add_eq_node(Gcalc_heap::Info *node, point *sp); int add_events_for_node(point *sp_node); point *new_slice_point() { point *new_point= (point *)new_item(); return new_point; } intersection_info *new_intersection_info(point *a, point *b) { intersection_info *ii= (intersection_info *)new_item(); ii->edge_a= a; ii->edge_b= b; ii->t_calculated= ii->x_calculated= ii->y_calculated= 0; return ii; } int arrange_event(int do_sorting, int n_intersections); static double get_pure_double(const Gcalc_internal_coord *d, int d_len); }; /* Gcalc_trapezoid_iterator simplifies the calculations on the current slice of the Gcalc_scan_iterator. One can walk through the trapezoids formed between previous and current slices. */ #ifdef TMP_BLOCK class Gcalc_trapezoid_iterator { protected: const Gcalc_scan_iterator::point *sp0; const Gcalc_scan_iterator::point *sp1; public: Gcalc_trapezoid_iterator(const Gcalc_scan_iterator *scan_i) : sp0(scan_i->get_b_slice()), sp1(scan_i->get_t_slice()) {} inline bool more() const { return sp1 && sp1->next; } const Gcalc_scan_iterator::point *lt() const { return sp1; } const Gcalc_scan_iterator::point *lb() const { return sp0; } const Gcalc_scan_iterator::point *rb() const { const Gcalc_scan_iterator::point *result= sp0; while ((result= result->c_get_next())->is_bottom()) {} return result; } const Gcalc_scan_iterator::point *rt() const { return sp1->c_get_next(); } void operator++() { sp0= rb(); sp1= rt(); } }; #endif /*TMP_BLOCK*/ /* Gcalc_point_iterator simplifies the calculations on the current slice of the Gcalc_scan_iterator. One can walk through the points on the current slice. */ class Gcalc_point_iterator { protected: const Gcalc_scan_iterator::point *sp; public: Gcalc_point_iterator(const Gcalc_scan_iterator *scan_i): sp(scan_i->get_b_slice()) {} inline bool more() const { return sp != NULL; } inline void operator++() { sp= sp->c_get_next(); } inline const Gcalc_scan_iterator::point *point() const { return sp; } inline const Gcalc_heap::Info *get_pi() const { return sp->pi; } inline gcalc_shape_info get_shape() const { return sp->get_shape(); } inline void restart(const Gcalc_scan_iterator *scan_i) { sp= scan_i->get_b_slice(); } }; #endif /*GCALC_SLICESCAN_INCLUDED*/ myisampack.h 0000644 00000035121 15156036133 0007060 0 ustar 00 #ifndef MYISAMPACK_INCLUDED #define MYISAMPACK_INCLUDED /* Copyright (c) 2000-2002, 2004 MySQL AB, 2009 Sun Microsystems, Inc. Copyright (c) 2020, MariaDB Corporation. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Storing of values in high byte first order. integer keys and file pointers are stored with high byte first to get better compression */ /* these two are for uniformity */ #define mi_sint1korr(A) ((int8)(*A)) #define mi_uint1korr(A) ((uint8)(*A)) #define mi_sint2korr(A) ((int16) (((int16) (((const uchar*) (A))[1])) |\ ((int16) ((uint16) ((const uchar*) (A))[0]) << 8))) #define mi_sint3korr(A) ((int32) (((((const uchar*) (A))[0]) & 128) ? \ (((uint32) 255L << 24) | \ (((uint32) ((const uchar*) (A))[0]) << 16) |\ (((uint32) ((const uchar*) (A))[1]) << 8) | \ ((uint32) ((const uchar*) (A))[2])) : \ (((uint32) ((const uchar*) (A))[0]) << 16) |\ (((uint32) ((const uchar*) (A))[1]) << 8) | \ ((uint32) ((const uchar*) (A))[2]))) #define mi_sint4korr(A) ((int32) (((uint32) (((const uchar*) (A))[3])) |\ ((uint32) (((const uchar*) (A))[2]) << 8) |\ ((uint32) (((const uchar*) (A))[1]) << 16) |\ ((uint32) (((const uchar*) (A))[0]) << 24))) #define mi_sint8korr(A) ((longlong) mi_uint8korr(A)) #define mi_uint2korr(A) ((uint16) (((uint16) (((const uchar*) (A))[1])) |\ ((uint16) (((const uchar*) (A))[0]) << 8))) #define mi_uint3korr(A) ((uint32) (((uint32) (((const uchar*) (A))[2])) |\ (((uint32) (((const uchar*) (A))[1])) << 8) |\ (((uint32) (((const uchar*) (A))[0])) << 16))) #define mi_uint4korr(A) ((uint32) (((uint32) (((const uchar*) (A))[3])) |\ (((uint32) (((const uchar*) (A))[2])) << 8) |\ (((uint32) (((const uchar*) (A))[1])) << 16) |\ (((uint32) (((const uchar*) (A))[0])) << 24))) #ifndef HAVE_mi_uint5korr #define mi_uint5korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[4])) |\ (((uint32) (((const uchar*) (A))[3])) << 8) |\ (((uint32) (((const uchar*) (A))[2])) << 16) |\ (((uint32) (((const uchar*) (A))[1])) << 24)) |\ (((ulonglong) (((const uchar*) (A))[0])) << 32)) #endif /* HAVE_mi_uint5korr */ #ifndef HAVE_mi_uint6korr #define mi_uint6korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[5])) |\ (((uint32) (((const uchar*) (A))[4])) << 8) |\ (((uint32) (((const uchar*) (A))[3])) << 16) |\ (((uint32) (((const uchar*) (A))[2])) << 24)) |\ (((ulonglong) (((uint32) (((const uchar*) (A))[1])) |\ (((uint32) (((const uchar*) (A))[0]) << 8)))) <<\ 32)) #endif /* HAVE_mi_uint6korr */ #ifndef HAVE_mi_uint7korr #define mi_uint7korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[6])) |\ (((uint32) (((const uchar*) (A))[5])) << 8) |\ (((uint32) (((const uchar*) (A))[4])) << 16) |\ (((uint32) (((const uchar*) (A))[3])) << 24)) |\ (((ulonglong) (((uint32) (((const uchar*) (A))[2])) |\ (((uint32) (((const uchar*) (A))[1])) << 8) |\ (((uint32) (((const uchar*) (A))[0])) << 16))) <<\ 32)) #endif /* HAVE_mi_uint7korr */ #ifndef HAVE_mi_uint8korr #define mi_uint8korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[7])) |\ (((uint32) (((const uchar*) (A))[6])) << 8) |\ (((uint32) (((const uchar*) (A))[5])) << 16) |\ (((uint32) (((const uchar*) (A))[4])) << 24)) |\ (((ulonglong) (((uint32) (((const uchar*) (A))[3])) |\ (((uint32) (((const uchar*) (A))[2])) << 8) |\ (((uint32) (((const uchar*) (A))[1])) << 16) |\ (((uint32) (((const uchar*) (A))[0])) << 24))) <<\ 32)) #endif /* HAVE_mi_uint8korr */ /* This one is for uniformity */ #define mi_int1store(T,A) *((uchar*)(T))= (uchar) (A) #define mi_int2store(T,A) { uint def_temp= (uint) (A) ;\ ((uchar*) (T))[1]= (uchar) (def_temp);\ ((uchar*) (T))[0]= (uchar) (def_temp >> 8); } #define mi_int3store(T,A) { /*lint -save -e734 */\ ulong def_temp= (ulong) (A);\ ((uchar*) (T))[2]= (uchar) (def_temp);\ ((uchar*) (T))[1]= (uchar) (def_temp >> 8);\ ((uchar*) (T))[0]= (uchar) (def_temp >> 16);\ /*lint -restore */} #define mi_int4store(T,A) { ulong def_temp= (ulong) (A);\ ((uchar*) (T))[3]= (uchar) (def_temp);\ ((uchar*) (T))[2]= (uchar) (def_temp >> 8);\ ((uchar*) (T))[1]= (uchar) (def_temp >> 16);\ ((uchar*) (T))[0]= (uchar) (def_temp >> 24); } #define mi_int5store(T,A) { ulong def_temp= (ulong) (A),\ def_temp2= (ulong) ((A) >> 32);\ ((uchar*) (T))[4]= (uchar) (def_temp);\ ((uchar*) (T))[3]= (uchar) (def_temp >> 8);\ ((uchar*) (T))[2]= (uchar) (def_temp >> 16);\ ((uchar*) (T))[1]= (uchar) (def_temp >> 24);\ ((uchar*) (T))[0]= (uchar) (def_temp2); } #define mi_int6store(T,A) { ulong def_temp= (ulong) (A),\ def_temp2= (ulong) ((A) >> 32);\ ((uchar*) (T))[5]= (uchar) (def_temp);\ ((uchar*) (T))[4]= (uchar) (def_temp >> 8);\ ((uchar*) (T))[3]= (uchar) (def_temp >> 16);\ ((uchar*) (T))[2]= (uchar) (def_temp >> 24);\ ((uchar*) (T))[1]= (uchar) (def_temp2);\ ((uchar*) (T))[0]= (uchar) (def_temp2 >> 8); } #define mi_int7store(T,A) { ulong def_temp= (ulong) (A),\ def_temp2= (ulong) ((A) >> 32);\ ((uchar*) (T))[6]= (uchar) (def_temp);\ ((uchar*) (T))[5]= (uchar) (def_temp >> 8);\ ((uchar*) (T))[4]= (uchar) (def_temp >> 16);\ ((uchar*) (T))[3]= (uchar) (def_temp >> 24);\ ((uchar*) (T))[2]= (uchar) (def_temp2);\ ((uchar*) (T))[1]= (uchar) (def_temp2 >> 8);\ ((uchar*) (T))[0]= (uchar) (def_temp2 >> 16); } #define mi_int8store(T,A) { ulong def_temp3= (ulong) (A),\ def_temp4= (ulong) ((A) >> 32);\ mi_int4store((uchar*) (T) + 0, def_temp4);\ mi_int4store((uchar*) (T) + 4, def_temp3); } #ifdef WORDS_BIGENDIAN #define mi_float4store(T,A) { ((uchar*) (T))[0]= ((uchar*) &A)[0];\ ((uchar*) (T))[1]= ((uchar*) &A)[1];\ ((uchar*) (T))[2]= ((uchar*) &A)[2];\ ((uchar*) (T))[3]= ((uchar*) &A)[3]; } #define mi_float4get(V,M) { float def_temp;\ ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1]; \ ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ (V)= def_temp; } #define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[0];\ ((uchar*) (T))[1]= ((const uchar*) &V)[1];\ ((uchar*) (T))[2]= ((const uchar*) &V)[2];\ ((uchar*) (T))[3]= ((const uchar*) &V)[3];\ ((uchar*) (T))[4]= ((const uchar*) &V)[4];\ ((uchar*) (T))[5]= ((const uchar*) &V)[5];\ ((uchar*) (T))[6]= ((const uchar*) &V)[6];\ ((uchar*) (T))[7]= ((const uchar*) &V)[7]; } #define mi_float8get(V,M) { double def_temp;\ ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1];\ ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ ((uchar*) &def_temp)[4]= ((const uchar*) (M))[4];\ ((uchar*) &def_temp)[5]= ((const uchar*) (M))[5];\ ((uchar*) &def_temp)[6]= ((const uchar*) (M))[6];\ ((uchar*) &def_temp)[7]= ((const uchar*) (M))[7]; \ (V)= def_temp; } #else #define mi_float4store(T,A) { ((uchar*) (T))[0]= ((const uchar*) &A)[3];\ ((uchar*) (T))[1]= ((const uchar*) &A)[2];\ ((uchar*) (T))[2]= ((const uchar*) &A)[1];\ ((uchar*) (T))[3]= ((const uchar*) &A)[0]; } #define mi_float4get(V,M) { float def_temp;\ ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ (V)= def_temp; } #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) #define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[3];\ ((uchar*) (T))[1]= ((const uchar*) &V)[2];\ ((uchar*) (T))[2]= ((const uchar*) &V)[1];\ ((uchar*) (T))[3]= ((const uchar*) &V)[0];\ ((uchar*) (T))[4]= ((const uchar*) &V)[7];\ ((uchar*) (T))[5]= ((const uchar*) &V)[6];\ ((uchar*) (T))[6]= ((const uchar*) &V)[5];\ ((uchar*) (T))[7]= ((const uchar*) &V)[4];} #define mi_float8get(V,M) { double def_temp;\ ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ ((uchar*) &def_temp)[4]= ((const uchar*) (M))[7];\ ((uchar*) &def_temp)[5]= ((const uchar*) (M))[6];\ ((uchar*) &def_temp)[6]= ((const uchar*) (M))[5];\ ((uchar*) &def_temp)[7]= ((const uchar*) (M))[4];\ (V)= def_temp; } #else #define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[7];\ ((uchar*) (T))[1]= ((const uchar*) &V)[6];\ ((uchar*) (T))[2]= ((const uchar*) &V)[5];\ ((uchar*) (T))[3]= ((const uchar*) &V)[4];\ ((uchar*) (T))[4]= ((const uchar*) &V)[3];\ ((uchar*) (T))[5]= ((const uchar*) &V)[2];\ ((uchar*) (T))[6]= ((const uchar*) &V)[1];\ ((uchar*) (T))[7]= ((const uchar*) &V)[0];} #define mi_float8get(V,M) { double def_temp;\ ((uchar*) &def_temp)[0]= ((const uchar*) (M))[7];\ ((uchar*) &def_temp)[1]= ((const uchar*) (M))[6];\ ((uchar*) &def_temp)[2]= ((const uchar*) (M))[5];\ ((uchar*) &def_temp)[3]= ((const uchar*) (M))[4];\ ((uchar*) &def_temp)[4]= ((const uchar*) (M))[3];\ ((uchar*) &def_temp)[5]= ((const uchar*) (M))[2];\ ((uchar*) &def_temp)[6]= ((const uchar*) (M))[1];\ ((uchar*) &def_temp)[7]= ((const uchar*) (M))[0];\ (V)= def_temp; } #endif /* __FLOAT_WORD_ORDER */ #endif /* WORDS_BIGENDIAN */ /* Fix to avoid warnings when sizeof(ha_rows) == sizeof(long) */ #ifdef BIG_TABLES #define mi_rowstore(T,A) mi_int8store(T, A) #define mi_rowkorr(T) mi_uint8korr(T) #else #define mi_rowstore(T,A) { mi_int4store(T, 0);\ mi_int4store(((uchar*) (T) + 4), A); } #define mi_rowkorr(T) mi_uint4korr((const uchar*) (T) + 4) #endif #if SIZEOF_OFF_T > 4 #define mi_sizestore(T,A) mi_int8store(T, A) #define mi_sizekorr(T) mi_uint8korr(T) #else #define mi_sizestore(T,A) { if ((A) == HA_OFFSET_ERROR)\ bfill((char*) (T), 8, 255);\ else { mi_int4store((T), 0);\ mi_int4store(((T) + 4), A); }} #define mi_sizekorr(T) mi_uint4korr((const uchar*) (T) + 4) #endif #endif /* MYISAMPACK_INCLUDED */ compat56.h 0000644 00000004350 15156036134 0006361 0 ustar 00 #ifndef COMPAT56_H_INCLUDED #define COMPAT56_H_INCLUDED /* Copyright (c) 2004, 2012, Oracle and/or its affiliates. Copyright (c) 2013 MariaDB Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** MySQL56 routines and macros **/ /* Buffer size for a native TIMESTAMP representation, for use with NativBuffer. 4 bytes for seconds 3 bytes for microseconds 1 byte for the trailing '\0' (class Native reserves extra 1 byte for '\0') */ #define STRING_BUFFER_TIMESTAMP_BINARY_SIZE 8 /* 4 + 3 + 1 */ #define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24) #define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24)) #define MY_PACKED_TIME_MAKE(i, f) ((((ulonglong) (i)) << 24) + (f)) #define MY_PACKED_TIME_MAKE_INT(i) ((((ulonglong) (i)) << 24)) longlong TIME_to_longlong_datetime_packed(const MYSQL_TIME *); longlong TIME_to_longlong_time_packed(const MYSQL_TIME *); void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong nr); void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, longlong nr); void my_datetime_packed_to_binary(longlong nr, uchar *ptr, uint dec); longlong my_datetime_packed_from_binary(const uchar *ptr, uint dec); uint my_datetime_binary_length(uint dec); void my_time_packed_to_binary(longlong nr, uchar *ptr, uint dec); longlong my_time_packed_from_binary(const uchar *ptr, uint dec); uint my_time_binary_length(uint dec); void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec); void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec); uint my_timestamp_binary_length(uint dec); /** End of MySQL routines and macros **/ #endif /* COMPAT56_H_INCLUDED */ sql_digest_stream.h 0000644 00000003037 15156036134 0010435 0 ustar 00 /* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DIGEST_STREAM_H #define SQL_DIGEST_STREAM_H #include "sql_digest.h" /** State data storage for @c digest_start, @c digest_add_token. This structure extends the @c sql_digest_storage structure with temporary state used only during parsing. */ struct sql_digest_state { /** Index, in the digest token array, of the last identifier seen. Reduce rules used in the digest computation can not apply to tokens seen before an identifier. @sa digest_add_token */ int m_last_id_index; sql_digest_storage m_digest_storage; inline void reset(unsigned char *token_array, uint length) { m_last_id_index= 0; m_digest_storage.reset(token_array, length); } inline bool is_empty() { return m_digest_storage.is_empty(); } }; typedef struct sql_digest_state sql_digest_state; #endif my_compare.h 0000644 00000025577 15156036134 0007074 0 ustar 00 /* Copyright (c) 2011, Oracle and/or its affiliates. Copyright (c) 1991, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_compare_h #define _my_compare_h #include "myisampack.h" #ifdef __cplusplus extern "C" { #endif #include "m_ctype.h" /* CHARSET_INFO */ /* There is a hard limit for the maximum number of keys as there are only 8 bits in the index file header for the number of keys in a table. This means that 0..255 keys can exist for a table. The idea of HA_MAX_POSSIBLE_KEY is to ensure that one can use myisamchk & tools on a MyISAM table for which one has more keys than MyISAM is normally compiled for. If you don't have this, you will get a core dump when running myisamchk compiled for 128 keys on a table with 255 keys. */ #define HA_MAX_POSSIBLE_KEY 255 /* For myisamchk */ /* The following defines can be increased if necessary. But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and HA_MAX_KEY_LENGTH. */ #define HA_MAX_KEY_LENGTH 1000 /* Max length in bytes */ #define HA_MAX_KEY_SEG 32 /* Max segments for key */ #define HA_MAX_POSSIBLE_KEY_BUFF (HA_MAX_KEY_LENGTH + 24+ 6+6) #define HA_MAX_KEY_BUFF (HA_MAX_KEY_LENGTH+HA_MAX_KEY_SEG*6+8+8) typedef struct st_HA_KEYSEG /* Key-portion */ { CHARSET_INFO *charset; uint32 start; /* Start of key in record */ uint32 null_pos; /* position to NULL indicator */ uint16 bit_pos; /* Position to bit part */ uint16 flag; uint16 length; /* Keylength */ uint16 language; uint8 type; /* Type of key (for sort) */ uint8 null_bit; /* bitmask to test for NULL */ uint8 bit_start; uint8 bit_length; /* Length of bit part */ } HA_KEYSEG; #define get_key_length(length,key) \ { if (*(const uchar*) (key) != 255) \ length= (uint) *(const uchar*) ((key)++); \ else \ { length= mi_uint2korr((key)+1); (key)+=3; } \ } #define get_key_length_rdonly(length,key) \ { if (*(const uchar*) (key) != 255) \ length= ((uint) *(const uchar*) ((key))); \ else \ { length= mi_uint2korr((key)+1); } \ } #define get_key_pack_length(length,length_pack,key) \ { if (*(const uchar*) (key) != 255) \ { length= (uint) *(const uchar*) ((key)++); length_pack= 1; }\ else \ { length=mi_uint2korr((key)+1); (key)+= 3; length_pack= 3; } \ } #define store_key_length_inc(key,length) \ { if ((length) < 255) \ { *(key)++= (uchar)(length); } \ else \ { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \ } #define size_to_store_key_length(length) ((length) < 255 ? 1 : 3) static inline uchar get_rec_bits(const uchar *ptr, uchar ofs, uint len) { uint16 val= ptr[0]; if (ofs + len > 8) val|= (uint16)(((uint) ptr[1]) << 8); return (uchar) ((val >> ofs) & ((1 << len) - 1)); } static inline void set_rec_bits(uint16 bits, uchar *ptr, uchar ofs, uint len) { ptr[0]= (uchar) ((ptr[0] & ~(((1 << len) - 1) << ofs)) | (bits << ofs)); if (ofs + len > 8) ptr[1]= (uchar) ((ptr[1] & ~((1 << (len - 8 + ofs)) - 1)) | bits >> (8 - ofs)); } #define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \ set_rec_bits(0, bit_ptr, bit_ofs, bit_len) /* Compare two VARCHAR values. @param charset_info - The character set and collation @param a - The pointer to the first string @param a_length - The length of the first string @param b - The pointer to the second string @param b_length - The length of the second string @param b_is_prefix - Whether "b" is a prefix of "a", e.g. in a prefix key (partial length key). @returns - The result of comparison - If "b_is_prefix" is FALSE, then the two strings are compared taking into account the PAD SPACE/NO PAD attribute of the collation. - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. This is done e.g. when we compare a column value to its prefix key value (the value of "a" to the value of "key_a"): CREATE TABLE t1 (a VARCHAR(10), KEY(key_a(5)); */ static inline int ha_compare_char_varying(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, const uchar *b, size_t b_length, my_bool b_is_prefix) { if (!b_is_prefix) return charset_info->coll->strnncollsp(charset_info, a, a_length, b, b_length); return charset_info->coll->strnncoll(charset_info, a, a_length, b, b_length, TRUE/*prefix*/); } /* Compare two CHAR values of the same declared character length, e.g. CHAR(5) to CHAR(5). @param charset_info - The character set and collation @param a - The pointer to the first string @param a_length - The length of the first string @param b - The pointer to the second string @param b_length - The length of the second string @param nchars - The declared length (in characters) @param b_is_prefix - Whether "b" is a prefix of "a", e.g. in a prefix key (partial length key). @returns - The result of comparison - If "b_is_prefix" is FALSE, then the two strings are compared taking into account the PAD SPACE/NO PAD attribute of the collation. Additionally, this function assumes that the underlying storage could optionally apply trailing space compression, so values can come into this comparison function in different states: - all trailing spaces removed - some trailing spaced removed - no trailing spaces removed (exactly "nchars" characters on the two sides) This function virtually reconstructs trailing spaces up to the defined length specified in "nchars". If either of the sides have more than "nchar" characters, then only leftmost "nchar" characters are compared. - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. This is done e.g. when we compare a column value to its prefix key value (the value of "a" to the value of "key_a"): CREATE TABLE t1 (a CHAR(10), KEY(key_a(5)); */ static inline int ha_compare_char_fixed(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, const uchar *b, size_t b_length, size_t nchars, my_bool b_is_prefix) { if (!b_is_prefix) return charset_info->coll->strnncollsp_nchars(charset_info, a, a_length, b, b_length, nchars, MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); return charset_info->coll->strnncoll(charset_info, a, a_length, b, b_length, TRUE/*prefix*/); } /* A function to compare words of a text. This is a common operation in full-text search: SELECT MATCH (title) AGAINST ('word') FROM t1; */ static inline int ha_compare_word(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, const uchar *b, size_t b_length) { return charset_info->coll->strnncollsp(charset_info, a, a_length, b, b_length); } /* A function to compare a word of a text to a word prefix. This is a common operation in full-text search: SELECT MATCH (title) AGAINST ('wor*' IN BOOLEAN MODE) FROM t1; */ static inline int ha_compare_word_prefix(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, const uchar *b, size_t b_length) { return charset_info->coll->strnncoll(charset_info, a, a_length, b, b_length, TRUE/*b_is_prefix*/); } /* Compare words (full match or prefix match), e.g. for full-text search. */ static inline int ha_compare_word_or_prefix(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, const uchar *b, size_t b_length, my_bool b_is_prefix) { if (!b_is_prefix) return ha_compare_word(charset_info, a, a_length, b, b_length); return ha_compare_word_prefix(charset_info, a, a_length, b, b_length); } extern int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, const uchar *b, uint key_length, uint nextflag, uint *diff_pos); extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a); /* Inside an in-memory data record, memory pointers to pieces of the record (like BLOBs) are stored in their native byte order and in this amount of bytes. */ #define portable_sizeof_char_ptr 8 #ifdef __cplusplus } #endif /** Return values for pushed index condition or rowid filter check functions. 0=CHECK_NEG - The filter is not satisfied. The engine should discard this index tuple and continue the scan. 1=CHECK_POS - The filter is satisfied. Current index tuple should be returned to the SQL layer. 2=CHECK_OUT_OF_RANGE - the index tuple is outside of the range that we're scanning. (Example: if we're scanning "t.key BETWEEN 10 AND 20" and got a "t.key=21" tuple) Tthe engine should stop scanning and return HA_ERR_END_OF_FILE right away). 3=CHECK_ABORTED_BY_USER - the engine must stop scanning and should return HA_ERR_ABORTED_BY_USER right away -1=CHECK_ERROR - Reserved for internal errors in engines. Should not be returned by ICP or rowid filter check functions. */ typedef enum check_result { CHECK_ERROR=-1, CHECK_NEG=0, CHECK_POS=1, CHECK_OUT_OF_RANGE=2, CHECK_ABORTED_BY_USER=3 } check_result_t; typedef check_result_t (*index_cond_func_t)(void *param); typedef check_result_t (*rowid_filter_func_t)(void *param); #endif /* _my_compare_h */ sql_truncate.h 0000644 00000004037 15156036134 0007431 0 ustar 00 #ifndef SQL_TRUNCATE_INCLUDED #define SQL_TRUNCATE_INCLUDED /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ class THD; struct TABLE_LIST; /** Sql_cmd_truncate_table represents the TRUNCATE statement. */ class Sql_cmd_truncate_table : public Sql_cmd { private: /* Set if a lock must be downgraded after truncate is done. */ MDL_ticket *m_ticket_downgrade; public: /** Constructor, used to represent a TRUNCATE statement. */ Sql_cmd_truncate_table() = default; virtual ~Sql_cmd_truncate_table() = default; /** Execute a TRUNCATE statement at runtime. @param thd the current thread. @return false on success. */ bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_TRUNCATE; } protected: enum truncate_result{ TRUNCATE_OK=0, TRUNCATE_FAILED_BUT_BINLOG, TRUNCATE_FAILED_SKIP_BINLOG }; /** Handle locking a base table for truncate. */ bool lock_table(THD *, TABLE_LIST *, bool *); /** Truncate table via the handler method. */ enum truncate_result handler_truncate(THD *, TABLE_LIST *, bool); /** Optimized delete of all rows by doing a full regenerate of the table. Depending on the storage engine, it can be accomplished through a drop and recreate or via the handler truncate method. */ bool truncate_table(THD *, TABLE_LIST *); }; #endif semisync_master.h 0000644 00000062246 15156036134 0010140 0 ustar 00 /* Copyright (C) 2007 Google Inc. Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SEMISYNC_MASTER_H #define SEMISYNC_MASTER_H #include "semisync.h" #include "semisync_master_ack_receiver.h" #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_LOCK_rpl_semi_sync_master_enabled; extern PSI_mutex_key key_LOCK_binlog; extern PSI_cond_key key_COND_binlog_send; #endif struct Tranx_node { char log_name[FN_REFLEN]; bool thd_valid; /* thd is valid for signalling */ my_off_t log_pos; THD *thd; /* The thread awaiting an ACK */ struct Tranx_node *next; /* the next node in the sorted list */ struct Tranx_node *hash_next; /* the next node during hash collision */ }; /** @class Tranx_node_allocator This class provides memory allocating and freeing methods for Tranx_node. The main target is performance. @section ALLOCATE How to allocate a node The pointer of the first node after 'last_node' in current_block is returned. current_block will move to the next free Block when all nodes of it are in use. A new Block is allocated and is put into the rear of the Block link table if no Block is free. The list starts up empty (ie, there is no allocated Block). After some nodes are freed, there probably are some free nodes before the sequence of the allocated nodes, but we do not reuse it. It is better to keep the allocated nodes are in the sequence, for it is more efficient for allocating and freeing Tranx_node. @section FREENODE How to free nodes There are two methods for freeing nodes. They are free_all_nodes and free_nodes_before. 'A Block is free' means all of its nodes are free. @subsection free_nodes_before As all allocated nodes are in the sequence, 'Before one node' means all nodes before given node in the same Block and all Blocks before the Block which containing the given node. As such, all Blocks before the given one ('node') are free Block and moved into the rear of the Block link table. The Block containing the given 'node', however, is not. For at least the given 'node' is still in use. This will waste at most one Block, but it is more efficient. */ #define BLOCK_TRANX_NODES 16 class Tranx_node_allocator { public: /** @param reserved_nodes The number of reserved Tranx_nodes. It is used to set 'reserved_blocks' which can contain at least 'reserved_nodes' number of Tranx_nodes. When freeing memory, we will reserve at least reserved_blocks of Blocks not freed. */ Tranx_node_allocator(uint reserved_nodes) : reserved_blocks(reserved_nodes/BLOCK_TRANX_NODES + (reserved_nodes%BLOCK_TRANX_NODES > 1 ? 2 : 1)), first_block(NULL), last_block(NULL), current_block(NULL), last_node(-1), block_num(0) {} ~Tranx_node_allocator() { Block *block= first_block; while (block != NULL) { Block *next= block->next; free_block(block); block= next; } } /** The pointer of the first node after 'last_node' in current_block is returned. current_block will move to the next free Block when all nodes of it are in use. A new Block is allocated and is put into the rear of the Block link table if no Block is free. @return Return a Tranx_node *, or NULL if an error occurred. */ Tranx_node *allocate_node() { Tranx_node *trx_node; Block *block= current_block; if (last_node == BLOCK_TRANX_NODES-1) { current_block= current_block->next; last_node= -1; } if (current_block == NULL && allocate_block()) { current_block= block; if (current_block) last_node= BLOCK_TRANX_NODES-1; return NULL; } trx_node= &(current_block->nodes[++last_node]); trx_node->log_name[0] = '\0'; trx_node->thd_valid= false; trx_node->log_pos= 0; trx_node->thd= nullptr; trx_node->next= 0; trx_node->hash_next= 0; return trx_node; } /** All nodes are freed. @return Return 0, or 1 if an error occurred. */ int free_all_nodes() { current_block= first_block; last_node= -1; free_blocks(); return 0; } /** All Blocks before the given 'node' are free Block and moved into the rear of the Block link table. @param node All nodes before 'node' will be freed @return Return 0, or 1 if an error occurred. */ int free_nodes_before(Tranx_node* node) { Block *block; Block *prev_block= NULL; block= first_block; while (block != current_block->next) { /* Find the Block containing the given node */ if (&(block->nodes[0]) <= node && &(block->nodes[BLOCK_TRANX_NODES]) >= node) { /* All Blocks before the given node are put into the rear */ if (first_block != block) { last_block->next= first_block; first_block= block; last_block= prev_block; last_block->next= NULL; free_blocks(); } return 0; } prev_block= block; block= block->next; } /* Node does not find should never happen */ DBUG_ASSERT(0); return 1; } private: uint reserved_blocks; /** A sequence memory which contains BLOCK_TRANX_NODES Tranx_nodes. BLOCK_TRANX_NODES The number of Tranx_nodes which are in a Block. next Every Block has a 'next' pointer which points to the next Block. These linking Blocks constitute a Block link table. */ struct Block { Block *next; Tranx_node nodes[BLOCK_TRANX_NODES]; }; /** The 'first_block' is the head of the Block link table; */ Block *first_block; /** The 'last_block' is the rear of the Block link table; */ Block *last_block; /** current_block always points the Block in the Block link table in which the last allocated node is. The Blocks before it are all in use and the Blocks after it are all free. */ Block *current_block; /** It always points to the last node which has been allocated in the current_block. */ int last_node; /** How many Blocks are in the Block link table. */ uint block_num; /** Allocate a block and then assign it to current_block. */ int allocate_block() { Block *block= (Block *)my_malloc(PSI_INSTRUMENT_ME, sizeof(Block), MYF(0)); if (block) { block->next= NULL; if (first_block == NULL) first_block= block; else last_block->next= block; /* New Block is always put into the rear */ last_block= block; /* New Block is always the current_block */ current_block= block; ++block_num; return 0; } return 1; } /** Free a given Block. @param block The Block will be freed. */ void free_block(Block *block) { my_free(block); --block_num; } /** If there are some free Blocks and the total number of the Blocks in the Block link table is larger than the 'reserved_blocks', Some free Blocks will be freed until the total number of the Blocks is equal to the 'reserved_blocks' or there is only one free Block behind the 'current_block'. */ void free_blocks() { if (current_block == NULL || current_block->next == NULL) return; /* One free Block is always kept behind the current block */ Block *block= current_block->next->next; while (block_num > reserved_blocks && block != NULL) { Block *next= block->next; free_block(block); block= next; } current_block->next->next= block; if (block == NULL) last_block= current_block->next; } }; /** Function pointer type to run on the contents of an Active_tranx node. Return 0 for success, 1 for error. Note Repl_semi_sync_master::LOCK_binlog is not guaranteed to be held for its invocation. See the context in which it is called to know. */ typedef int (*active_tranx_action)(THD *trx_thd, bool thd_valid, const char *log_file_name, my_off_t trx_log_file_pos); /** This class manages memory for active transaction list. We record each active transaction with a Tranx_node, each session can have only one open transaction. Because of EVENT, the total active transaction nodes can exceed the maximum allowed connections. */ class Active_tranx :public Trace { private: Tranx_node_allocator m_allocator; /* These two record the active transaction list in sort order. */ Tranx_node *m_trx_front, *m_trx_rear; Tranx_node **m_trx_htb; /* A hash table on active transactions. */ int m_num_entries; /* maximum hash table entries */ mysql_mutex_t *m_lock; /* mutex lock */ mysql_cond_t *m_cond_empty; /* signalled when cleared all Tranx_node */ inline void assert_lock_owner(); inline unsigned int calc_hash(const unsigned char *key, size_t length); unsigned int get_hash_value(const char *log_file_name, my_off_t log_file_pos); int compare(const char *log_file_name1, my_off_t log_file_pos1, const Tranx_node *node2) { return compare(log_file_name1, log_file_pos1, node2->log_name, node2->log_pos); } int compare(const Tranx_node *node1, const char *log_file_name2, my_off_t log_file_pos2) { return compare(node1->log_name, node1->log_pos, log_file_name2, log_file_pos2); } int compare(const Tranx_node *node1, const Tranx_node *node2) { return compare(node1->log_name, node1->log_pos, node2->log_name, node2->log_pos); } public: Active_tranx(mysql_mutex_t *lock, mysql_cond_t *cond, unsigned long trace_level); ~Active_tranx(); /* Insert an active transaction node with the specified position. * * Return: * 0: success; non-zero: error */ int insert_tranx_node(THD *thd_to_wait, const char *log_file_name, my_off_t log_file_pos); /* Clear the active transaction nodes until(inclusive) the specified * position. * If log_file_name is NULL, everything will be cleared: the sorted * list and the hash table will be reset to empty. * * The pre_delete_hook parameter is a function pointer that will be invoked * for each Active_tranx node, in order, from m_trx_front to m_trx_rear, * e.g. to signal their wakeup condition. Repl_semi_sync_binlog::LOCK_binlog * is held while this is invoked. */ void clear_active_tranx_nodes(const char *log_file_name, my_off_t log_file_pos, active_tranx_action pre_delete_hook); /* Unlinks a thread from a Tranx_node, so it will not be referenced/signalled * if it is separately killed. Note that this keeps the Tranx_node itself in * the cache so it can still be awaited by await_all_slave_replies(), e.g. * as is done by SHUTDOWN WAIT FOR ALL SLAVES. */ void unlink_thd_as_waiter(const char *log_file_name, my_off_t log_file_pos); /* Uses DBUG_ASSERT statements to ensure that the argument thd_to_check * matches the thread of the respective Tranx_node::thd of the passed in * log_file_name and log_file_pos. */ Tranx_node * is_thd_waiter(THD *thd_to_check, const char *log_file_name, my_off_t log_file_pos); /* Given a position, check to see whether the position is an active * transaction's ending position by probing the hash table. */ bool is_tranx_end_pos(const char *log_file_name, my_off_t log_file_pos); /* Given two binlog positions, compare which one is bigger based on * (file_name, file_position). */ static int compare(const char *log_file_name1, my_off_t log_file_pos1, const char *log_file_name2, my_off_t log_file_pos2); /* Check if there are no transactions actively awaiting ACKs. Returns true * if the internal linked list has no entries, false otherwise. */ bool is_empty() { return m_trx_front == NULL; } }; /** The extension class for the master of semi-synchronous replication */ class Repl_semi_sync_master :public Repl_semi_sync_base { Active_tranx *m_active_tranxs; /* active transaction list: the list will be cleared when semi-sync switches off. */ /* True when init_object has been called */ bool m_init_done; /* This cond variable is signaled when enough binlog has been sent to slave, * so that a waiting trx can return the 'ok' to the client for a commit. */ mysql_cond_t COND_binlog_send; /* Mutex that protects the following state variables and the active * transaction list. * Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are * already holding m_LOCK_binlog because it can cause deadlocks. */ mysql_mutex_t LOCK_binlog; /* This is set to true when m_reply_file_name contains meaningful data. */ bool m_reply_file_name_inited; /* The binlog name up to which we have received replies from any slaves. */ char m_reply_file_name[FN_REFLEN]; /* The position in that file up to which we have the reply from any slaves. */ my_off_t m_reply_file_pos; /* This is set to true when we know the 'smallest' wait position. */ bool m_wait_file_name_inited; /* NULL, or the 'smallest' filename that a transaction is waiting for * slave replies. */ char m_wait_file_name[FN_REFLEN]; /* The smallest position in that file that a trx is waiting for: the trx * can proceed and send an 'ok' to the client when the master has got the * reply from the slave indicating that it already got the binlog events. */ my_off_t m_wait_file_pos; /* This is set to true when we know the 'largest' transaction commit * position in the binlog file. * We always maintain the position no matter whether semi-sync is switched * on switched off. When a transaction wait timeout occurs, semi-sync will * switch off. Binlog-dump thread can use the three fields to detect when * slaves catch up on replication so that semi-sync can switch on again. */ bool m_commit_file_name_inited; /* The 'largest' binlog filename that a commit transaction is seeing. */ char m_commit_file_name[FN_REFLEN]; /* The 'largest' position in that file that a commit transaction is seeing. */ my_off_t m_commit_file_pos; /* All global variables which can be set by parameters. */ volatile bool m_master_enabled; /* semi-sync is enabled on the master */ unsigned long m_wait_timeout; /* timeout period(ms) during tranx wait */ bool m_state; /* whether semi-sync is switched */ /*Waiting for ACK before/after innodb commit*/ ulong m_wait_point; void lock(); void unlock(); /* Is semi-sync replication on? */ bool is_on() { return (m_state); } void set_master_enabled(bool enabled) { m_master_enabled = enabled; } /* Switch semi-sync off because of timeout in transaction waiting. */ void switch_off(); /* Switch semi-sync on when slaves catch up. */ int try_switch_on(int server_id, const char *log_file_name, my_off_t log_file_pos); public: Repl_semi_sync_master(); ~Repl_semi_sync_master() = default; void cleanup(); bool get_master_enabled() { return m_master_enabled; } void set_trace_level(unsigned long trace_level) { m_trace_level = trace_level; if (m_active_tranxs) m_active_tranxs->m_trace_level = trace_level; } /* Set the transaction wait timeout period, in milliseconds. */ void set_wait_timeout(unsigned long wait_timeout) { m_wait_timeout = wait_timeout; } /* Calculates a timeout that is m_wait_timeout after start_arg and saves it in out. If start_arg is NULL, the timeout is m_wait_timeout after the current system time. */ void create_timeout(struct timespec *out, struct timespec *start_arg); /* Blocks the calling thread until the ack_receiver either receives ACKs for all transactions awaiting ACKs, or times out (from rpl_semi_sync_master_timeout). If info_msg is provided, it will be output via sql_print_information when there are transactions awaiting ACKs; info_msg is not output if there are no transasctions to await. */ void await_all_slave_replies(const char *msg); /*set the ACK point, after binlog sync or after transaction commit*/ void set_wait_point(unsigned long ack_point) { m_wait_point = ack_point; } ulong wait_point() //no cover line { return m_wait_point; //no cover line } /* Initialize this class after MySQL parameters are initialized. this * function should be called once at bootstrap time. */ int init_object(); /* Enable the object to enable semi-sync replication inside the master. */ int enable_master(); /* Disable the object to disable semi-sync replication inside the master. */ void disable_master(); /* Add a semi-sync replication slave */ void add_slave(); /* Remove a semi-sync replication slave */ void remove_slave(); /* It parses a reply packet and call report_reply_binlog to handle it. */ int report_reply_packet(uint32 server_id, const uchar *packet, ulong packet_len); /* In semi-sync replication, reports up to which binlog position we have * received replies from the slave indicating that it already get the events. * * Input: * server_id - (IN) master server id number * log_file_name - (IN) binlog file name * end_offset - (IN) the offset in the binlog file up to which we have * the replies from the slave * * Return: * 0: success; non-zero: error */ int report_reply_binlog(uint32 server_id, const char* log_file_name, my_off_t end_offset); /* Commit a transaction in the final step. This function is called from * InnoDB before returning from the low commit. If semi-sync is switch on, * the function will wait to see whether binlog-dump thread get the reply for * the events of the transaction. Remember that this is not a direct wait, * instead, it waits to see whether the binlog-dump thread has reached the * point. If the wait times out, semi-sync status will be switched off and * all other transaction would not wait either. * * Input: (the transaction events' ending binlog position) * trx_wait_binlog_name - (IN) ending position's file name * trx_wait_binlog_pos - (IN) ending position's file offset * * Return: * 0: success; non-zero: error */ int commit_trx(const char* trx_wait_binlog_name, my_off_t trx_wait_binlog_pos); /*Wait for ACK after writing/sync binlog to file*/ int wait_after_sync(const char* log_file, my_off_t log_pos); /*Wait for ACK after commting the transaction*/ int wait_after_commit(THD* thd, bool all); /*Wait after the transaction is rollback*/ int wait_after_rollback(THD *thd, bool all); /* Store the current binlog position in m_active_tranxs. This position should * be acked by slave. * * Inputs: * trans_thd Thread of the transaction which is executing the * transaction. * waiter_thd Thread that will wait for the ACK from the replica, * which depends on the semi-sync wait point. If AFTER_SYNC, * and also using binlog group commit, this will be the leader * thread of the binlog commit. Otherwise, it is the thread that * is executing the transaction, i.e. the same as trans_thd. * log_file Name of the binlog file that the transaction is written into * log_pos Offset within the binlog file that the transaction is written * at */ int report_binlog_update(THD *trans_thd, THD *waiter_thd, const char *log_file, my_off_t log_pos); int dump_start(THD* thd, const char *log_file, my_off_t log_pos); void dump_end(THD* thd); /* Reserve space in the replication event packet header: * . slave semi-sync off: 1 byte - (0) * . slave semi-sync on: 3 byte - (0, 0xef, 0/1} * * Input: * packet - (IN) the header buffer * * Return: * size of the bytes reserved for header */ int reserve_sync_header(String* packet); /* Update the sync bit in the packet header to indicate to the slave whether * the master will wait for the reply of the event. If semi-sync is switched * off and we detect that the slave is catching up, we switch semi-sync on. * * Input: * THD - (IN) current dump thread * packet - (IN) the packet containing the replication event * log_file_name - (IN) the event ending position's file name * log_file_pos - (IN) the event ending position's file offset * need_sync - (IN) identify if flush_net is needed to call. * server_id - (IN) master server id number * * Return: * 0: success; non-zero: error */ int update_sync_header(THD* thd, unsigned char *packet, const char *log_file_name, my_off_t log_file_pos, bool* need_sync); /* Called when a transaction finished writing binlog events. * . update the 'largest' transactions' binlog event position * . insert the ending position in the active transaction list if * semi-sync is on * * Input: (the transaction events' ending binlog position) * THD - (IN) thread that will wait for an ACK. This can be the * binlog leader thread when using wait_point * AFTER_SYNC with binlog group commit. In all other * cases, this is the user thread executing the * transaction. * log_file_name - (IN) transaction ending position's file name * log_file_pos - (IN) transaction ending position's file offset * * Return: * 0: success; non-zero: error */ int write_tranx_in_binlog(THD *thd, const char *log_file_name, my_off_t log_file_pos); /* Read the slave's reply so that we know how much progress the slave makes * on receive replication events. */ int flush_net(THD* thd, const char *event_buf); /* Export internal statistics for semi-sync replication. */ void set_export_stats(); /* 'reset master' command is issued from the user and semi-sync need to * go off for that. */ int after_reset_master(); /*called before reset master*/ int before_reset_master(); mysql_mutex_t LOCK_rpl_semi_sync_master_enabled; }; enum rpl_semi_sync_master_wait_point_t { SEMI_SYNC_MASTER_WAIT_POINT_AFTER_BINLOG_SYNC, SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT, }; extern Repl_semi_sync_master repl_semisync_master; extern Ack_receiver ack_receiver; /* System and status variables for the master component */ extern my_bool rpl_semi_sync_master_enabled; extern my_bool rpl_semi_sync_master_status; extern ulong rpl_semi_sync_master_wait_point; extern ulong rpl_semi_sync_master_clients; extern ulong rpl_semi_sync_master_timeout; extern ulong rpl_semi_sync_master_trace_level; extern ulong rpl_semi_sync_master_yes_transactions; extern ulong rpl_semi_sync_master_no_transactions; extern ulong rpl_semi_sync_master_off_times; extern ulong rpl_semi_sync_master_wait_timeouts; extern ulong rpl_semi_sync_master_timefunc_fails; extern ulong rpl_semi_sync_master_num_timeouts; extern ulong rpl_semi_sync_master_wait_sessions; extern ulong rpl_semi_sync_master_wait_pos_backtraverse; extern ulong rpl_semi_sync_master_avg_trx_wait_time; extern ulong rpl_semi_sync_master_avg_net_wait_time; extern ulonglong rpl_semi_sync_master_net_wait_num; extern ulonglong rpl_semi_sync_master_trx_wait_num; extern ulonglong rpl_semi_sync_master_net_wait_time; extern ulonglong rpl_semi_sync_master_trx_wait_time; extern unsigned long long rpl_semi_sync_master_request_ack; extern unsigned long long rpl_semi_sync_master_get_ack; /* This indicates whether we should keep waiting if no semi-sync slave is available. 0 : stop waiting if detected no avaialable semi-sync slave. 1 (default) : keep waiting until timeout even no available semi-sync slave. */ extern char rpl_semi_sync_master_wait_no_slave; extern Repl_semi_sync_master repl_semisync_master; extern PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave; extern PSI_stage_info stage_reading_semi_sync_ack; extern PSI_stage_info stage_waiting_for_semi_sync_slave; void semi_sync_master_deinit(); #endif /* SEMISYNC_MASTER_H */ field_comp.h 0000644 00000002226 15156036135 0007025 0 ustar 00 #ifndef FIELD_COMP_H_INCLUDED #define FIELD_COMP_H_INCLUDED /* Copyright (C) 2017 MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define MAX_COMPRESSION_METHODS 16 struct Compression_method { const char *name; uint (*compress)(THD *thd, char *to, const char *from, uint length); int (*uncompress)(String *to, const uchar *from, uint from_length, uint field_length); }; extern Compression_method compression_methods[MAX_COMPRESSION_METHODS]; #define zlib_compression_method (&compression_methods[8]) #endif sys_vars_shared.h 0000644 00000005251 15156036135 0010124 0 ustar 00 #ifndef SYS_VARS_SHARED_INCLUDED #define SYS_VARS_SHARED_INCLUDED /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file "protected" interface to sys_var - server configuration variables. This header is included by files implementing support and utility functions of sys_var's (set_var.cc) and files implementing classes in the sys_var hierarchy (sql_plugin.cc) */ #include <sql_priv.h> #include "set_var.h" extern bool throw_bounds_warning(THD *thd, const char *name,const char *v); extern bool throw_bounds_warning(THD *thd, const char *name, bool fixed, bool is_unsigned, longlong v); extern bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v); extern sys_var *intern_find_sys_var(const char *str, size_t length); extern sys_var_chain all_sys_vars; /** wrapper to hide a mutex and an rwlock under a common interface */ class PolyLock { public: virtual void rdlock()= 0; virtual void wrlock()= 0; virtual void unlock()= 0; virtual ~PolyLock() = default; }; class PolyLock_mutex: public PolyLock { mysql_mutex_t *mutex; public: PolyLock_mutex(mysql_mutex_t *arg): mutex(arg) {} void rdlock() override { mysql_mutex_lock(mutex); } void wrlock() override { mysql_mutex_lock(mutex); } void unlock() override { mysql_mutex_unlock(mutex); } }; class PolyLock_rwlock: public PolyLock { mysql_rwlock_t *rwlock; public: PolyLock_rwlock(mysql_rwlock_t *arg): rwlock(arg) {} void rdlock() override { mysql_rwlock_rdlock(rwlock); } void wrlock() override { mysql_rwlock_wrlock(rwlock); } void unlock() override { mysql_rwlock_unlock(rwlock); } }; class AutoWLock { PolyLock *lock; public: AutoWLock(PolyLock *l) : lock(l) { if (lock) lock->wrlock(); } ~AutoWLock() { if (lock) lock->unlock(); } }; class AutoRLock { PolyLock *lock; public: AutoRLock(PolyLock *l) : lock(l) { if (lock) lock->rdlock(); } ~AutoRLock() { if (lock) lock->unlock(); } }; #endif /* SYS_VARS_SHARED_INCLUDED */ rpl_record.h 0000644 00000002765 15156036135 0007067 0 ustar 00 /* Copyright (c) 2007, 2013, Oracle and/or its affiliates. Copyright (c) 2008, 2013, SkySQL Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_RECORD_H #define RPL_RECORD_H #include <rpl_reporting.h> struct rpl_group_info; struct TABLE; typedef struct st_bitmap MY_BITMAP; #if !defined(MYSQL_CLIENT) size_t pack_row(TABLE* table, MY_BITMAP const* cols, uchar *row_data, const uchar *data); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int unpack_row(const rpl_group_info *rgi, TABLE *table, uint const colcnt, uchar const *const row_data, MY_BITMAP const *cols, uchar const **const curr_row_end, ulong *const master_reclength, uchar const *const row_end); // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check); #endif #endif providers/snappy-c.h 0000644 00000004311 15156036135 0010470 0 ustar 00 /** @file snappy-c.h This service provides dynamic access to Snappy as a C header. */ #ifndef SNAPPY_C_INCLUDED #ifdef __cplusplus extern "C" { #endif #ifndef MYSQL_ABI_CHECK #include <stddef.h> #include <stdbool.h> #endif #ifndef MYSQL_DYNAMIC_PLUGIN #define provider_service_snappy provider_service_snappy_static #endif #ifndef SNAPPY_C typedef enum { SNAPPY_OK = 0, SNAPPY_INVALID_INPUT = 1, SNAPPY_BUFFER_TOO_SMALL = 2 } snappy_status; #define snappy_max_compressed_length(...) provider_service_snappy->snappy_max_compressed_length_ptr (__VA_ARGS__) #define snappy_compress(...) provider_service_snappy->snappy_compress_ptr (__VA_ARGS__) #define snappy_uncompressed_length(...) provider_service_snappy->snappy_uncompressed_length_ptr (__VA_ARGS__) #define snappy_uncompress(...) provider_service_snappy->snappy_uncompress_ptr (__VA_ARGS__) #endif #define DEFINE_snappy_max_compressed_length(NAME) NAME( \ size_t source_length \ ) #define DEFINE_snappy_compress(NAME) NAME( \ const char *input, \ size_t input_length, \ char *compressed, \ size_t *compressed_length \ ) #define DEFINE_snappy_uncompressed_length(NAME) NAME( \ const char *compressed, \ size_t compressed_length, \ size_t *result \ ) #define DEFINE_snappy_uncompress(NAME) NAME( \ const char *compressed, \ size_t compressed_length, \ char *uncompressed, \ size_t *uncompressed_length \ ) struct provider_service_snappy_st { size_t DEFINE_snappy_max_compressed_length((*snappy_max_compressed_length_ptr)); snappy_status DEFINE_snappy_compress((*snappy_compress_ptr)); snappy_status DEFINE_snappy_uncompressed_length((*snappy_uncompressed_length_ptr)); snappy_status DEFINE_snappy_uncompress((*snappy_uncompress_ptr)); bool is_loaded; }; extern struct provider_service_snappy_st *provider_service_snappy; #ifdef __cplusplus } #endif #define SNAPPY_C_INCLUDED #endif providers/lz4.h 0000644 00000003173 15156036136 0007455 0 ustar 00 /** @file lz4.h This service provides dynamic access to LZ4. */ #ifndef LZ4_INCLUDED #ifdef __cplusplus extern "C" { #endif #ifndef MYSQL_ABI_CHECK #include <stdbool.h> #include <stddef.h> #include <stdint.h> #endif #ifndef MYSQL_DYNAMIC_PLUGIN #define provider_service_lz4 provider_service_lz4_static #endif #ifndef LZ4_VERSION_NUMBER #define LZ4_MAX_INPUT_SIZE 0x7E000000 #define LZ4_compressBound(...) provider_service_lz4->LZ4_compressBound_ptr (__VA_ARGS__) #define LZ4_compress_default(...) provider_service_lz4->LZ4_compress_default_ptr (__VA_ARGS__) #define LZ4_decompress_safe(...) provider_service_lz4->LZ4_decompress_safe_ptr (__VA_ARGS__) #endif #define DEFINE_LZ4_compressBound(NAME) NAME( \ int inputSize \ ) #define DEFINE_LZ4_compress_default(NAME) NAME( \ const char *src, \ char *dst, \ int srcSize, \ int dstCapacity \ ) #define DEFINE_LZ4_decompress_safe(NAME) NAME( \ const char *src, \ char *dst, \ int compressedSize, \ int dstCapacity \ ) struct provider_service_lz4_st { int DEFINE_LZ4_compressBound((*LZ4_compressBound_ptr)); int DEFINE_LZ4_compress_default((*LZ4_compress_default_ptr)); int DEFINE_LZ4_decompress_safe((*LZ4_decompress_safe_ptr)); bool is_loaded; }; extern struct provider_service_lz4_st *provider_service_lz4; #ifdef __cplusplus } #endif #define LZ4_INCLUDED #endif providers/lzo/lzo1x.h 0000644 00000003124 15156036136 0010621 0 ustar 00 /** @file lzo/lzo1x.h This service provides dynamic access to LZO. */ #ifndef LZO_INCLUDED #ifdef __cplusplus extern "C" { #endif #ifndef MYSQL_ABI_CHECK #include <stdbool.h> #endif #ifndef MYSQL_DYNAMIC_PLUGIN #define provider_service_lzo provider_service_lzo_static #endif #ifndef LZO_E_OK #define LZO_E_OK 0 #define LZO_E_INTERNAL_ERROR (-99) #define LZO1X_1_15_MEM_COMPRESS ((unsigned int) (32768L * ((unsigned) sizeof(unsigned char *)))) typedef size_t lzo_uint; #define lzo1x_1_15_compress(...) provider_service_lzo->lzo1x_1_15_compress_ptr (__VA_ARGS__) #define lzo1x_decompress_safe(...) provider_service_lzo->lzo1x_decompress_safe_ptr (__VA_ARGS__) #endif #define DEFINE_lzo1x_1_15_compress(NAME) NAME( \ const unsigned char *src, \ lzo_uint src_len, \ unsigned char *dst, \ lzo_uint *dst_len, \ void *wrkmem \ ) #define DEFINE_lzo1x_decompress_safe(NAME) NAME( \ const unsigned char *src, \ lzo_uint src_len, \ unsigned char *dst, \ lzo_uint *dst_len, \ void *wrkmem \ ) struct provider_service_lzo_st { int DEFINE_lzo1x_1_15_compress((*lzo1x_1_15_compress_ptr)); int DEFINE_lzo1x_decompress_safe((*lzo1x_decompress_safe_ptr)); bool is_loaded; }; extern struct provider_service_lzo_st *provider_service_lzo; #ifdef __cplusplus } #endif #define LZO_INCLUDED #endif providers/bzlib.h 0000644 00000007777 15156036136 0010064 0 ustar 00 /** @file bzlib.h This service provides dynamic access to BZip2. */ #ifndef BZIP2_INCLUDED #ifdef __cplusplus extern "C" { #endif #ifndef MYSQL_ABI_CHECK #include <stdbool.h> #endif #ifndef MYSQL_DYNAMIC_PLUGIN #define provider_service_bzip2 provider_service_bzip2_static #endif #ifndef BZ_RUN #define BZ_RUN 0 #define BZ_FINISH 2 #define BZ_OK 0 #define BZ_RUN_OK 1 #define BZ_FINISH_OK 3 #define BZ_STREAM_END 4 typedef struct { char *next_in; unsigned int avail_in; unsigned int total_in_lo32; unsigned int total_in_hi32; char *next_out; unsigned int avail_out; unsigned int total_out_lo32; unsigned int total_out_hi32; void *state; void *(*bzalloc)(void *, int, int); void (*bzfree)(void *, void *); void *opaque; } bz_stream; #define BZ2_bzBuffToBuffCompress(...) provider_service_bzip2->BZ2_bzBuffToBuffCompress_ptr (__VA_ARGS__) #define BZ2_bzBuffToBuffDecompress(...) provider_service_bzip2->BZ2_bzBuffToBuffDecompress_ptr (__VA_ARGS__) #define BZ2_bzCompress(...) provider_service_bzip2->BZ2_bzCompress_ptr (__VA_ARGS__) #define BZ2_bzCompressEnd(...) provider_service_bzip2->BZ2_bzCompressEnd_ptr (__VA_ARGS__) #define BZ2_bzCompressInit(...) provider_service_bzip2->BZ2_bzCompressInit_ptr (__VA_ARGS__) #define BZ2_bzDecompress(...) provider_service_bzip2->BZ2_bzDecompress_ptr (__VA_ARGS__) #define BZ2_bzDecompressEnd(...) provider_service_bzip2->BZ2_bzDecompressEnd_ptr (__VA_ARGS__) #define BZ2_bzDecompressInit(...) provider_service_bzip2->BZ2_bzDecompressInit_ptr (__VA_ARGS__) #endif #define DEFINE_BZ2_bzBuffToBuffCompress(NAME) NAME( \ char *dest, \ unsigned int *destLen, \ char *source, \ unsigned int sourceLen, \ int blockSize100k, \ int verbosity, \ int workFactor \ ) #define DEFINE_BZ2_bzBuffToBuffDecompress(NAME) NAME( \ char *dest, \ unsigned int *destLen, \ char *source, \ unsigned int sourceLen, \ int small, \ int verbosity \ ) #define DEFINE_BZ2_bzCompress(NAME) NAME( \ bz_stream *strm, \ int action \ ) #define DEFINE_BZ2_bzCompressEnd(NAME) NAME( \ bz_stream *strm \ ) #define DEFINE_BZ2_bzCompressInit(NAME) NAME( \ bz_stream *strm, \ int blockSize100k, \ int verbosity, \ int workFactor \ ) #define DEFINE_BZ2_bzDecompress(NAME) NAME( \ bz_stream *strm \ ) #define DEFINE_BZ2_bzDecompressEnd(NAME) NAME( \ bz_stream *strm \ ) #define DEFINE_BZ2_bzDecompressInit(NAME) NAME( \ bz_stream *strm, \ int verbosity, \ int small \ ) struct provider_service_bzip2_st{ int DEFINE_BZ2_bzBuffToBuffCompress((*BZ2_bzBuffToBuffCompress_ptr)); int DEFINE_BZ2_bzBuffToBuffDecompress((*BZ2_bzBuffToBuffDecompress_ptr)); int DEFINE_BZ2_bzCompress((*BZ2_bzCompress_ptr)); int DEFINE_BZ2_bzCompressEnd((*BZ2_bzCompressEnd_ptr)); int DEFINE_BZ2_bzCompressInit((*BZ2_bzCompressInit_ptr)); int DEFINE_BZ2_bzDecompress((*BZ2_bzDecompress_ptr)); int DEFINE_BZ2_bzDecompressEnd((*BZ2_bzDecompressEnd_ptr)); int DEFINE_BZ2_bzDecompressInit((*BZ2_bzDecompressInit_ptr)); bool is_loaded; }; extern struct provider_service_bzip2_st *provider_service_bzip2; #ifdef __cplusplus } #endif #define BZIP2_INCLUDED #endif providers/lzma.h 0000644 00000005355 15156036136 0007713 0 ustar 00 /** @file lzma.h This service provides dynamic access to LZMA. */ #ifndef LZMA_INCLUDED #ifdef __cplusplus extern "C" { #endif #ifndef MYSQL_ABI_CHECK #include <stdbool.h> #include <stdint.h> #include <stddef.h> #endif #ifndef MYSQL_DYNAMIC_PLUGIN #define provider_service_lzma provider_service_lzma_static #endif #ifndef LZMA_VERSION typedef enum { LZMA_OK = 0, LZMA_STREAM_END = 1, LZMA_NO_CHECK = 2, LZMA_UNSUPPORTED_CHECK = 3, LZMA_GET_CHECK = 4, LZMA_MEM_ERROR = 5, LZMA_MEMLIMIT_ERROR = 6, LZMA_FORMAT_ERROR = 7, LZMA_OPTIONS_ERROR = 8, LZMA_DATA_ERROR = 9, LZMA_BUF_ERROR = 10, LZMA_PROG_ERROR = 11, } lzma_ret; typedef struct { void *(*alloc)(void *opaque, size_t nmemb, size_t size); void (*free)(void *opaque, void *ptr); void *opaque; } lzma_allocator; typedef enum { LZMA_CHECK_NONE = 0, LZMA_CHECK_CRC32 = 1, LZMA_CHECK_CRC64 = 4, LZMA_CHECK_SHA256 = 10 } lzma_check; #define lzma_stream_buffer_decode(...) provider_service_lzma->lzma_stream_buffer_decode_ptr (__VA_ARGS__) #define lzma_easy_buffer_encode(...) provider_service_lzma->lzma_easy_buffer_encode_ptr (__VA_ARGS__) #elif LZMA_VERSION < 50010030 #define lzma_maybe_const #endif #ifndef lzma_maybe_const #define lzma_maybe_const const #endif #define DEFINE_lzma_stream_buffer_decode(NAME) NAME( \ uint64_t *memlimit, \ uint32_t flags, \ lzma_maybe_const lzma_allocator *allocator, \ const uint8_t *in, \ size_t *in_pos, \ size_t in_size, \ uint8_t *out, \ size_t *out_pos, \ size_t out_size \ ) #define DEFINE_lzma_easy_buffer_encode(NAME) NAME( \ uint32_t preset, \ lzma_check check, \ lzma_maybe_const lzma_allocator *allocator, \ const uint8_t *in, \ size_t in_size, \ uint8_t *out, \ size_t *out_pos, \ size_t out_size \ ) struct provider_service_lzma_st { lzma_ret DEFINE_lzma_stream_buffer_decode((*lzma_stream_buffer_decode_ptr)); lzma_ret DEFINE_lzma_easy_buffer_encode((*lzma_easy_buffer_encode_ptr)); bool is_loaded; }; extern struct provider_service_lzma_st *provider_service_lzma; #ifdef __cplusplus } #endif #define LZMA_INCLUDED #endif sql_partition.h 0000644 00000030602 15156036136 0007614 0 ustar 00 #ifndef SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED /* Copyright (c) 2006, 2017, Oracle and/or its affiliates. Copyright (c) 2011, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_list.h" /* List */ #include "table.h" /* TABLE_LIST */ class Alter_info; class Alter_table_ctx; class Field; class String; class handler; class partition_info; struct TABLE; struct TABLE_LIST; typedef struct st_bitmap MY_BITMAP; typedef struct st_key KEY; typedef struct st_key_range key_range; /* Flags for partition handlers */ #define HA_CAN_PARTITION (1 << 0) /* Partition support */ #define HA_CAN_UPDATE_PARTITION_KEY (1 << 1) #define HA_CAN_PARTITION_UNIQUE (1 << 2) #define HA_USE_AUTO_PARTITION (1 << 3) #define HA_ONLY_VERS_PARTITION (1 << 4) #define NORMAL_PART_NAME 0 #define TEMP_PART_NAME 1 #define RENAMED_PART_NAME 2 typedef struct st_lock_param_type { TABLE_LIST *table_list; ulonglong copied; ulonglong deleted; THD *thd; HA_CREATE_INFO *create_info; Alter_info *alter_info; Alter_table_ctx *alter_ctx; TABLE *table; KEY *key_info_buffer; LEX_CUSTRING org_tabledef_version; uchar *pack_frm_data; uint key_count; uint db_options; size_t pack_frm_len; // TODO: remove duplicate data: part_info can be accessed via table->part_info partition_info *part_info; } ALTER_PARTITION_PARAM_TYPE; typedef struct { longlong list_value; uint32 partition_id; } LIST_PART_ENTRY; typedef struct { uint32 start_part; uint32 end_part; } part_id_range; class String_list; struct st_partition_iter; #define NOT_A_PARTITION_ID UINT_MAX32 bool is_partition_in_list(char *part_name, List<char> list_part_names); char *are_partitions_in_table(partition_info *new_part_info, partition_info *old_part_info); bool check_reorganise_list(partition_info *new_part_info, partition_info *old_part_info, List<char> list_part_names); handler *get_ha_partition(partition_info *part_info); int get_part_for_buf(const uchar *buf, const uchar *rec0, partition_info *part_info, uint32 *part_id); void prune_partition_set(const TABLE *table, part_id_range *part_spec); bool check_partition_info(partition_info *part_info,handlerton **eng_type, TABLE *table, handler *file, HA_CREATE_INFO *info); void set_linear_hash_mask(partition_info *part_info, uint num_parts); bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind); void get_partition_set(const TABLE *table, uchar *buf, const uint index, const key_range *key_spec, part_id_range *part_spec); uint get_partition_field_store_length(Field *field); void get_full_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, part_id_range *part_spec); bool mysql_unpack_partition(THD *thd, char *part_buf, uint part_info_len, TABLE *table, bool is_create_table_ind, handlerton *default_db_type, bool *work_part_info_used); void make_used_partitions_str(MEM_ROOT *mem_root, partition_info *part_info, String *parts_str, String_list &used_partitions_list); uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); bool check_part_func_fields(Field **ptr, bool ok_with_charsets); bool field_is_partition_charset(Field *field); Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs); /** Append all fields in read_set to string @param[in,out] str String to append to. @param[in] row Row to append. @param[in] table Table containing read_set and fields for the row. */ void append_row_to_str(String &str, const uchar *row, TABLE *table); void truncate_partition_filename(char *path); /* A "Get next" function for partition iterator. SYNOPSIS partition_iter_func() part_iter Partition iterator, you call only "iter.get_next(&iter)" DESCRIPTION Depending on whether partitions or sub-partitions are iterated, the function returns next subpartition id/partition number. The sequence of returned numbers is not ordered and may contain duplicates. When the end of sequence is reached, NOT_A_PARTITION_ID is returned, and the iterator resets itself (so next get_next() call will start to enumerate the set all over again). RETURN NOT_A_PARTITION_ID if there are no more partitions. [sub]partition_id of the next partition */ typedef uint32 (*partition_iter_func)(st_partition_iter* part_iter); /* Partition set iterator. Used to enumerate a set of [sub]partitions obtained in partition interval analysis (see get_partitions_in_range_iter). For the user, the only meaningful field is get_next, which may be used as follows: part_iterator.get_next(&part_iterator); Initialization is done by any of the following calls: - get_partitions_in_range_iter-type function call - init_single_partition_iterator() - init_all_partitions_iterator() Cleanup is not needed. */ typedef struct st_partition_iter { partition_iter_func get_next; /* Valid for "Interval mapping" in LIST partitioning: if true, let the iterator also produce id of the partition that contains NULL value. */ bool ret_null_part, ret_null_part_orig; /* We should return DEFAULT partition. */ bool ret_default_part, ret_default_part_orig; struct st_part_num_range { uint32 start; uint32 cur; uint32 end; }; struct st_field_value_range { longlong start; longlong cur; longlong end; }; union { struct st_part_num_range part_nums; struct st_field_value_range field_vals; }; partition_info *part_info; } PARTITION_ITERATOR; /* Get an iterator for set of partitions that match given field-space interval SYNOPSIS get_partitions_in_range_iter() part_info Partitioning info is_subpart store_length_array Length of fields packed in opt_range_key format min_val Left edge, field value in opt_range_key format max_val Right edge, field value in opt_range_key format min_len Length of minimum value max_len Length of maximum value flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE, NO_MAX_RANGE part_iter Iterator structure to be initialized DESCRIPTION Functions with this signature are used to perform "Partitioning Interval Analysis". This analysis is applicable for any type of [sub]partitioning by some function of a single fieldX. The idea is as follows: Given an interval "const1 <=? fieldX <=? const2", find a set of partitions that may contain records with value of fieldX within the given interval. The min_val, max_val and flags parameters specify the interval. The set of partitions is returned by initializing an iterator in *part_iter NOTES There are currently three functions of this type: - get_part_iter_for_interval_via_walking - get_part_iter_for_interval_cols_via_map - get_part_iter_for_interval_via_mapping RETURN 0 - No matching partitions, iterator not initialized 1 - Some partitions would match, iterator intialized for traversing them -1 - All partitions would match, iterator not initialized */ typedef int (*get_partitions_in_range_iter)(partition_info *part_info, bool is_subpart, uint32 *store_length_array, uchar *min_val, uchar *max_val, uint min_len, uint max_len, uint flags, PARTITION_ITERATOR *part_iter); #include "partition_info.h" #ifdef WITH_PARTITION_STORAGE_ENGINE uint fast_alter_partition_table(THD *thd, TABLE *table, Alter_info *alter_info, Alter_table_ctx *alter_ctx, HA_CREATE_INFO *create_info, TABLE_LIST *table_list); bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info, enum partition_state part_state); uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, bool *partition_changed, bool *fast_alter_table); char *generate_partition_syntax(THD *thd, partition_info *part_info, uint *buf_length, bool show_partition_options, HA_CREATE_INFO *create_info, Alter_info *alter_info); char *generate_partition_syntax_for_frm(THD *thd, partition_info *part_info, uint *buf_length, HA_CREATE_INFO *create_info, Alter_info *alter_info); bool verify_data_with_partition(TABLE *table, TABLE *part_table, uint32 part_id); bool compare_partition_options(HA_CREATE_INFO *table_create_info, partition_element *part_elem); bool compare_table_with_partition(THD *thd, TABLE *table, TABLE *part_table, partition_element *part_elem, uint part_id); bool partition_key_modified(TABLE *table, const MY_BITMAP *fields); bool write_log_replace_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint next_entry, const char *from_path, const char *to_path); #else #define partition_key_modified(X,Y) 0 #endif int __attribute__((warn_unused_result)) create_partition_name(char *out, size_t outlen, const char *in1, const char *in2, uint name_variant, bool translate); int __attribute__((warn_unused_result)) create_subpartition_name(char *out, size_t outlen, const char *in1, const char *in2, const char *in3, uint name_variant); void set_key_field_ptr(KEY *key_info, const uchar *new_buf, const uchar *old_buf); /** Set up table for creating a partition. Copy info from partition to the table share so the created partition has the correct info. @param thd THD object @param share Table share to be updated. @param info Create info to be updated. @param part_elem partition_element containing the info. @return status @retval TRUE Error @retval FALSE Success @details Set up 1) Comment on partition 2) MAX_ROWS, MIN_ROWS on partition 3) Index file name on partition 4) Data file name on partition */ bool set_up_table_before_create(THD *thd, TABLE_SHARE *share, const char *partition_name_with_path, HA_CREATE_INFO *info, partition_element *part_elem); #endif /* SQL_PARTITION_INCLUDED */ sql_parse.h 0000644 00000021464 15156036136 0006723 0 ustar 00 /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_PARSE_INCLUDED #define SQL_PARSE_INCLUDED #include "sql_acl.h" /* GLOBAL_ACLS */ class Comp_creator; class Item; class Object_creation_ctx; class Parser_state; struct TABLE_LIST; class THD; class Table_ident; struct LEX; enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6 }; extern "C" int path_starts_from_data_home_dir(const char *dir); int test_if_data_home_dir(const char *dir); int error_if_data_home_dir(const char *path, const char *what); my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); int mysql_multi_update_prepare(THD *thd); int mysql_multi_delete_prepare(THD *thd); int mysql_insert_select_prepare(THD *thd,select_result *sel_res); bool update_precheck(THD *thd, TABLE_LIST *tables); bool delete_precheck(THD *thd, TABLE_LIST *tables); bool insert_precheck(THD *thd, TABLE_LIST *tables); bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); bool check_fk_parent_table_access(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, const LEX_CSTRING &create_db); bool parse_sql(THD *thd, Parser_state *parser_state, Object_creation_ctx *creation_ctx, bool do_pfs_digest=false); void free_items(Item *item); void cleanup_items(Item *item); Comp_creator *comp_eq_creator(bool invert); Comp_creator *comp_ge_creator(bool invert); Comp_creator *comp_gt_creator(bool invert); Comp_creator *comp_le_creator(bool invert); Comp_creator *comp_lt_creator(bool invert); Comp_creator *comp_ne_creator(bool invert); int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, enum enum_schema_tables schema_table_idx); void get_default_definer(THD *thd, LEX_USER *definer, bool role); LEX_USER *create_default_definer(THD *thd, bool role); LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name, LEX_CSTRING *host_name); LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock=true); bool sp_process_definer(THD *thd); bool check_string_byte_length(const LEX_CSTRING *str, uint err_msg, size_t max_byte_length); bool check_string_char_length(const LEX_CSTRING *str, uint err_msg, size_t max_char_length, CHARSET_INFO *cs, bool no_error); bool check_ident_length(const LEX_CSTRING *ident); bool check_host_name(LEX_CSTRING *str); bool check_identifier_name(LEX_CSTRING *str, uint max_char_length, uint err_code, const char *param_for_err_msg); bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); bool sqlcom_can_generate_row_events(const THD *thd); bool stmt_causes_implicit_commit(THD *thd, uint mask); bool is_update_query(enum enum_sql_command command); bool is_log_table_write_query(enum enum_sql_command command); bool alloc_query(THD *thd, const char *packet, size_t packet_length); void mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state); bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); void create_select_for_variable(THD *thd, LEX_CSTRING *var_name); void create_table_set_open_action_and_adjust_tables(LEX *lex); void mysql_init_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex); bool multi_delete_set_locks_and_link_aux_tables(LEX *lex); void create_table_set_open_action_and_adjust_tables(LEX *lex); int bootstrap(MYSQL_FILE *file); bool run_set_statement_if_requested(THD *thd, LEX *lex); int mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt=false); enum dispatch_command_return { DISPATCH_COMMAND_SUCCESS=0, DISPATCH_COMMAND_CLOSE_CONNECTION= 1, DISPATCH_COMMAND_WOULDBLOCK= 2 }; dispatch_command_return do_command(THD *thd, bool blocking = true); dispatch_command_return dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length, bool blocking = true); void log_slow_statement(THD *thd); bool append_file_to_dir(THD *thd, const char **filename_ptr, const LEX_CSTRING *table_name); void execute_init_command(THD *thd, LEX_STRING *init_command, mysql_rwlock_t *var_lock); bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *group, bool asc); void add_join_on(THD *thd, TABLE_LIST *b, Item *expr); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields, SELECT_LEX *lex); bool add_proc_to_list(THD *thd, Item *item); bool push_new_name_resolution_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op); void init_update_queries(void); Item *normalize_cond(THD *thd, Item *cond); Item *negate_expression(THD *thd, Item *expr); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); /* Variables */ extern const Lex_ident_db any_db; extern uint sql_command_flags[]; extern uint server_command_flags[]; extern const LEX_CSTRING command_name[]; extern uint server_command_flags[]; /* Inline functions */ inline bool check_identifier_name(LEX_CSTRING *str, uint err_code) { return check_identifier_name(str, NAME_CHAR_LEN, err_code, ""); } inline bool check_identifier_name(LEX_CSTRING *str) { return check_identifier_name(str, NAME_CHAR_LEN, 0, ""); } #ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_one_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables); bool check_single_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables, bool no_errors); bool check_routine_access(THD *thd, privilege_t want_access, const LEX_CSTRING *db, const LEX_CSTRING *name, const Sp_handler *sph, bool no_errors); bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table); bool check_some_routine_access(THD *thd, const char *db, const char *name, const Sp_handler *sph); bool check_table_access(THD *thd, privilege_t requirements,TABLE_LIST *tables, bool any_combination_of_privileges_will_do, uint number, bool no_errors); #else inline bool check_one_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables) { return false; } inline bool check_single_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables, bool no_errors) { return false; } inline bool check_routine_access(THD *thd, privilege_t want_access, const LEX_CSTRING *db, const LEX_CSTRING *name, const Sp_handler *sph, bool no_errors) { return false; } inline bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table) { table->grant.privilege= want_access; return false; } inline bool check_some_routine_access(THD *thd, const char *db, const char *name, const Sp_handler *sph) { return false; } inline bool check_table_access(THD *thd, privilege_t requirements,TABLE_LIST *tables, bool any_combination_of_privileges_will_do, uint number, bool no_errors) { return false; } #endif /*NO_EMBEDDED_ACCESS_CHECKS*/ /** Due to an issue with the bison parser, we need to use a different name. This is a workaround! If we use the global charset variable name we get a warning in the bison parser stderr : suspicious sequence in the output: b4_bin [-Wother] So we work around by having this define that doesn't have 'b4_bin' in it. This has been reported, but not fixed yet: https://lists.gnu.org/archive/html/bug-bison/2021-10/msg00027.html */ #define MY_CHARSET_UTF8MB4_BIN my_charset_utf8mb4_bin #endif /* SQL_PARSE_INCLUDED */ sql_cursor.h 0000644 00000010217 15156036137 0007121 0 ustar 00 /* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _sql_cursor_h_ #define _sql_cursor_h_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class interface */ #endif #include "sql_class.h" /* Query_arena */ class JOIN; /** @file Declarations for implementation of server side cursors. Only read-only non-scrollable cursors are currently implemented. */ /** Server_side_cursor -- an interface for materialized implementation of cursors. All cursors are self-contained (created in their own memory root). For that reason they must be deleted only using a pointer to Server_side_cursor, not to its base class. */ class Server_side_cursor: protected Query_arena { protected: /** Row destination used for fetch */ select_result *result; public: Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg) :Query_arena(mem_root_arg, STMT_INITIALIZED), result(result_arg) {} virtual bool is_open() const= 0; virtual int open(JOIN *top_level_join)= 0; virtual void fetch(ulong num_rows)= 0; virtual void close()= 0; virtual bool export_structure(THD *thd, Row_definition_list *defs) { DBUG_ASSERT(0); return true; } virtual ~Server_side_cursor(); static void *operator new(size_t size, MEM_ROOT *mem_root) { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size); static void operator delete(void *, MEM_ROOT *){} }; /** Materialized_cursor -- an insensitive materialized server-side cursor. The result set of this cursor is saved in a temporary table at open. The cursor itself is simply an interface for the handler of the temporary table. */ class Materialized_cursor: public Server_side_cursor { MEM_ROOT main_mem_root; /* A fake unit to supply to select_send when fetching */ SELECT_LEX_UNIT fake_unit; TABLE *table; List<Item> item_list; ulong fetch_limit; ulong fetch_count; bool is_rnd_inited; public: Materialized_cursor(select_result *result, TABLE *table); int send_result_set_metadata(THD *thd, List<Item> &send_result_set_metadata); bool is_open() const override { return table != 0; } int open(JOIN *join __attribute__((unused))) override; void fetch(ulong num_rows) override; void close() override; bool export_structure(THD *thd, Row_definition_list *defs) override { return table->export_structure(thd, defs); } ~Materialized_cursor() override; void on_table_fill_finished(); }; /** Select_materialize -- a mediator between a cursor query and the protocol. In case we were not able to open a non-materialzed cursor, it creates an internal temporary HEAP table, and insert all rows into it. When the table reaches max_heap_table_size, it's converted to a MyISAM table. Later this table is used to create a Materialized_cursor. */ class Select_materialize: public select_unit { select_result *result; /**< the result object of the caller (PS or SP) */ public: Materialized_cursor *materialized_cursor; Select_materialize(THD *thd_arg, select_result *result_arg): select_unit(thd_arg), result(result_arg), materialized_cursor(0) {} bool send_result_set_metadata(List<Item> &list, uint flags) override; bool send_eof() override { return false; } bool view_structure_only() const override { return result->view_structure_only(); } }; int mysql_open_cursor(THD *thd, select_result *result, Server_side_cursor **res); #endif /* _sql_cusor_h_ */ my_default.h 0000644 00000003530 15156036137 0007056 0 ustar 00 /* Copyright (C) 2013 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Definitions for mysys/my_default.c */ #ifndef MY_DEFAULT_INCLUDED #define MY_DEFAULT_INCLUDED C_MODE_START extern MYSQL_PLUGIN_IMPORT const char *my_defaults_extra_file; extern const char *my_defaults_group_suffix; extern MYSQL_PLUGIN_IMPORT const char *my_defaults_file; extern my_bool my_defaults_mark_files; extern int get_defaults_options(char **argv); extern int my_load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv, const char ***); extern int load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv); extern void free_defaults(char **argv); extern void my_print_default_files(const char *conf_file); extern void print_defaults(const char *conf_file, const char **groups); /** Simplify load_defaults() common use */ #define load_defaults_or_exit(A, B, C, D) switch (load_defaults(A, B, C, D)) { \ case 0: break; \ case 4: my_end(0); exit(0); \ default: my_end(0); exit(1); } C_MODE_END #endif /* MY_DEFAULT_INCLUDED */ probes_mysql_nodtrace.h 0000644 00000013707 15156036137 0011332 0 ustar 00 /* * Generated by dheadgen(1). */ #ifndef _PROBES_MYSQL_D #define _PROBES_MYSQL_D #ifdef __cplusplus extern "C" { #define MYSQL_DTRACE_DISABLED false #else #define MYSQL_DTRACE_DISABLED 0 #endif #define MYSQL_CONNECTION_START(arg0, arg1, arg2) #define MYSQL_CONNECTION_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_CONNECTION_DONE(arg0, arg1) #define MYSQL_CONNECTION_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_COMMAND_START(arg0, arg1, arg2, arg3) #define MYSQL_COMMAND_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_COMMAND_DONE(arg0) #define MYSQL_COMMAND_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_START(arg0, arg1, arg2, arg3, arg4) #define MYSQL_QUERY_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_DONE(arg0) #define MYSQL_QUERY_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_PARSE_START(arg0) #define MYSQL_QUERY_PARSE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_PARSE_DONE(arg0) #define MYSQL_QUERY_PARSE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_CACHE_HIT(arg0, arg1) #define MYSQL_QUERY_CACHE_HIT_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_CACHE_MISS(arg0) #define MYSQL_QUERY_CACHE_MISS_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_EXEC_START(arg0, arg1, arg2, arg3, arg4, arg5) #define MYSQL_QUERY_EXEC_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_QUERY_EXEC_DONE(arg0) #define MYSQL_QUERY_EXEC_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_ROW_START(arg0, arg1) #define MYSQL_INSERT_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_ROW_DONE(arg0) #define MYSQL_INSERT_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_UPDATE_ROW_START(arg0, arg1) #define MYSQL_UPDATE_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_UPDATE_ROW_DONE(arg0) #define MYSQL_UPDATE_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_DELETE_ROW_START(arg0, arg1) #define MYSQL_DELETE_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_DELETE_ROW_DONE(arg0) #define MYSQL_DELETE_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_READ_ROW_START(arg0, arg1, arg2) #define MYSQL_READ_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_READ_ROW_DONE(arg0) #define MYSQL_READ_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INDEX_READ_ROW_START(arg0, arg1) #define MYSQL_INDEX_READ_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INDEX_READ_ROW_DONE(arg0) #define MYSQL_INDEX_READ_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_RDLOCK_START(arg0, arg1) #define MYSQL_HANDLER_RDLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_WRLOCK_START(arg0, arg1) #define MYSQL_HANDLER_WRLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_UNLOCK_START(arg0, arg1) #define MYSQL_HANDLER_UNLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_RDLOCK_DONE(arg0) #define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_WRLOCK_DONE(arg0) #define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_HANDLER_UNLOCK_DONE(arg0) #define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_FILESORT_START(arg0, arg1) #define MYSQL_FILESORT_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_FILESORT_DONE(arg0, arg1) #define MYSQL_FILESORT_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_SELECT_START(arg0) #define MYSQL_SELECT_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_SELECT_DONE(arg0, arg1) #define MYSQL_SELECT_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_START(arg0) #define MYSQL_INSERT_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_DONE(arg0, arg1) #define MYSQL_INSERT_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_SELECT_START(arg0) #define MYSQL_INSERT_SELECT_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_INSERT_SELECT_DONE(arg0, arg1) #define MYSQL_INSERT_SELECT_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_UPDATE_START(arg0) #define MYSQL_UPDATE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_UPDATE_DONE(arg0, arg1, arg2) #define MYSQL_UPDATE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_MULTI_UPDATE_START(arg0) #define MYSQL_MULTI_UPDATE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_MULTI_UPDATE_DONE(arg0, arg1, arg2) #define MYSQL_MULTI_UPDATE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_DELETE_START(arg0) #define MYSQL_DELETE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_DELETE_DONE(arg0, arg1) #define MYSQL_DELETE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_MULTI_DELETE_START(arg0) #define MYSQL_MULTI_DELETE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_MULTI_DELETE_DONE(arg0, arg1) #define MYSQL_MULTI_DELETE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_NET_READ_START() #define MYSQL_NET_READ_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_NET_READ_DONE(arg0, arg1) #define MYSQL_NET_READ_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_NET_WRITE_START(arg0) #define MYSQL_NET_WRITE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_NET_WRITE_DONE(arg0) #define MYSQL_NET_WRITE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_READ_START(arg0, arg1, arg2, arg3) #define MYSQL_KEYCACHE_READ_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_READ_BLOCK(arg0) #define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_READ_HIT() #define MYSQL_KEYCACHE_READ_HIT_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_READ_MISS() #define MYSQL_KEYCACHE_READ_MISS_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_READ_DONE(arg0, arg1) #define MYSQL_KEYCACHE_READ_DONE_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_WRITE_START(arg0, arg1, arg2, arg3) #define MYSQL_KEYCACHE_WRITE_START_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_WRITE_BLOCK(arg0) #define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() MYSQL_DTRACE_DISABLED #define MYSQL_KEYCACHE_WRITE_DONE(arg0, arg1) #define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() MYSQL_DTRACE_DISABLED #ifdef __cplusplus } #endif #endif /* _PROBES_MYSQL_D */ sql_class.h 0000644 00001041112 15156036137 0006710 0 ustar 00 /* Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_CLASS_INCLUDED #define SQL_CLASS_INCLUDED /* Classes in mysql */ #include <atomic> #include <thread> #include "dur_prop.h" #include <waiting_threads.h> #include "sql_const.h" #include "lex_ident.h" #include "sql_used.h" #include <mysql/plugin_audit.h> #include "log.h" #include "rpl_tblmap.h" #include "mdl.h" #include "field.h" // Create_field #include "opt_trace_context.h" #include "probes_mysql.h" #include "sql_locale.h" /* my_locale_st */ #include "sql_profile.h" /* PROFILING */ #include "scheduler.h" /* thd_scheduler */ #include "protocol.h" /* Protocol_text, Protocol_binary */ #include "violite.h" /* vio_is_connected */ #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA, THR_LOCK_INFO */ #include "thr_timer.h" #include "thr_malloc.h" #include "log_slow.h" /* LOG_SLOW_DISABLE_... */ #include <my_tree.h> #include "sql_digest_stream.h" // sql_digest_state #include <mysql/psi/mysql_stage.h> #include <mysql/psi/mysql_statement.h> #include <mysql/psi/mysql_idle.h> #include <mysql/psi/mysql_table.h> #include <mysql_com_server.h> #include "session_tracker.h" #include "backup.h" #include "xa.h" #include "scope.h" #include "ddl_log.h" /* DDL_LOG_STATE */ #include "ha_handler_stats.h" // ha_handler_stats */ extern "C" void set_thd_stage_info(void *thd, const PSI_stage_info *new_stage, PSI_stage_info *old_stage, const char *calling_func, const char *calling_file, const unsigned int calling_line); #define THD_STAGE_INFO(thd, stage) \ (thd)->enter_stage(&stage, __func__, __FILE__, __LINE__) #include "my_apc.h" #include "rpl_gtid.h" #include "wsrep.h" #include "wsrep_on.h" #include <inttypes.h> #include <ilist.h> #ifdef WITH_WSREP /* wsrep-lib */ #include "wsrep_client_service.h" #include "wsrep_client_state.h" #include "wsrep_mutex.h" #include "wsrep_condition_variable.h" class Wsrep_applier_service; enum wsrep_consistency_check_mode { NO_CONSISTENCY_CHECK, CONSISTENCY_CHECK_DECLARED, CONSISTENCY_CHECK_RUNNING, }; #endif /* WITH_WSREP */ class Reprepare_observer; class Relay_log_info; struct rpl_group_info; struct rpl_parallel_thread; class Rpl_filter; class Query_log_event; class Log_event_writer; class sp_rcontext; class sp_cache; class Lex_input_stream; class Parser_state; class Rows_log_event; class Sroutine_hash_entry; class user_var_entry; struct Trans_binlog_info; class rpl_io_thread_info; class rpl_sql_thread_info; #ifdef HAVE_REPLICATION struct Slave_info; #endif enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE }; enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT, SLAVE_EXEC_MODE_IDEMPOTENT, SLAVE_EXEC_MODE_LAST_BIT }; enum enum_slave_run_triggers_for_rbr { SLAVE_RUN_TRIGGERS_FOR_RBR_NO, SLAVE_RUN_TRIGGERS_FOR_RBR_YES, SLAVE_RUN_TRIGGERS_FOR_RBR_LOGGING, SLAVE_RUN_TRIGGERS_FOR_RBR_ENFORCE}; enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY, SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY}; /* COLUMNS_READ: A column is goind to be read. COLUMNS_WRITE: A column is going to be written to. MARK_COLUMNS_READ: A column is goind to be read. A bit in read set is set to inform handler that the field is to be read. If field list contains duplicates, then thd->dup_field is set to point to the last found duplicate. MARK_COLUMNS_WRITE: A column is going to be written to. A bit is set in write set to inform handler that it needs to update this field in write_row and update_row. */ enum enum_column_usage { COLUMNS_READ, COLUMNS_WRITE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE}; static inline bool should_mark_column(enum_column_usage column_usage) { return column_usage >= MARK_COLUMNS_READ; } enum enum_filetype { FILETYPE_CSV, FILETYPE_XML }; enum enum_binlog_row_image { /** PKE in the before image and changed columns in the after image */ BINLOG_ROW_IMAGE_MINIMAL= 0, /** Whenever possible, before and after image contain all columns except blobs. */ BINLOG_ROW_IMAGE_NOBLOB= 1, /** All columns in both before and after image. */ BINLOG_ROW_IMAGE_FULL= 2, /** All columns in before image, but only updated columns in after image */ BINLOG_ROW_IMAGE_FULL_NODUP= 3 }; /* Bits for different SQL modes modes (including ANSI mode) */ #define MODE_REAL_AS_FLOAT (1ULL << 0) #define MODE_PIPES_AS_CONCAT (1ULL << 1) #define MODE_ANSI_QUOTES (1ULL << 2) #define MODE_IGNORE_SPACE (1ULL << 3) #define MODE_IGNORE_BAD_TABLE_OPTIONS (1ULL << 4) #define MODE_ONLY_FULL_GROUP_BY (1ULL << 5) #define MODE_NO_UNSIGNED_SUBTRACTION (1ULL << 6) #define MODE_NO_DIR_IN_CREATE (1ULL << 7) #define MODE_POSTGRESQL (1ULL << 8) #define MODE_ORACLE (1ULL << 9) #define MODE_MSSQL (1ULL << 10) #define MODE_DB2 (1ULL << 11) #define MODE_MAXDB (1ULL << 12) #define MODE_NO_KEY_OPTIONS (1ULL << 13) #define MODE_NO_TABLE_OPTIONS (1ULL << 14) #define MODE_NO_FIELD_OPTIONS (1ULL << 15) #define MODE_MYSQL323 (1ULL << 16) #define MODE_MYSQL40 (1ULL << 17) #define MODE_ANSI (1ULL << 18) #define MODE_NO_AUTO_VALUE_ON_ZERO (1ULL << 19) #define MODE_NO_BACKSLASH_ESCAPES (1ULL << 20) #define MODE_STRICT_TRANS_TABLES (1ULL << 21) #define MODE_STRICT_ALL_TABLES (1ULL << 22) #define MODE_NO_ZERO_IN_DATE (1ULL << 23) #define MODE_NO_ZERO_DATE (1ULL << 24) #define MODE_INVALID_DATES (1ULL << 25) #define MODE_ERROR_FOR_DIVISION_BY_ZERO (1ULL << 26) #define MODE_TRADITIONAL (1ULL << 27) #define MODE_NO_AUTO_CREATE_USER (1ULL << 28) #define MODE_HIGH_NOT_PRECEDENCE (1ULL << 29) #define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30) #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) /* SQL mode bits defined above are common for MariaDB and MySQL */ #define MODE_MASK_MYSQL_COMPATIBLE 0xFFFFFFFFULL /* The following modes are specific to MariaDB */ #define MODE_EMPTY_STRING_IS_NULL (1ULL << 32) #define MODE_SIMULTANEOUS_ASSIGNMENT (1ULL << 33) #define MODE_TIME_ROUND_FRACTIONAL (1ULL << 34) /* The following modes are specific to MySQL */ #define MODE_MYSQL80_TIME_TRUNCATE_FRACTIONAL (1ULL << 32) #define WAS_ORACLE (1ULL << 35) #define IS_OR_WAS_ORACLE (MODE_ORACLE | WAS_ORACLE) /* Bits for different old style modes */ #define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) #define OLD_MODE_NO_PROGRESS_INFO (1 << 1) #define OLD_MODE_ZERO_DATE_TIME_CAST (1 << 2) #define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3) #define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4) #define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5) #define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6) #define OLD_MODE_LOCK_ALTER_TABLE_COPY (1 << 7) #define OLD_MODE_DEFAULT_VALUE OLD_MODE_UTF8_IS_UTF8MB3 void old_mode_deprecated_warnings(THD *thd, ulonglong v); /* Bits for @@new_mode -> thd->variables.new_behaviour system variable See sys_vars.cc /new_mode_all_names */ #define NEW_MODE_FIX_INDEX_STATS_FOR_ALL_NULLS (1ULL << 0) #define NEW_MODE_FIX_INDEX_LOOKUP_COST (1ULL << 1) #define NEW_MODE_MAX 2 /* Definitions above that have transitioned from new behaviour to default */ #define NOW_DEFAULT -1 #define NEW_MODE_TEST_WARNING1 NOW_DEFAULT #define NEW_MODE_TEST_WARNING2 NOW_DEFAULT #define TEST_NEW_MODE_FLAG(thd, flag) \ (flag == NOW_DEFAULT ? TRUE : thd->variables.new_behavior & flag) extern char internal_table_name[2]; extern char empty_c_string[1]; extern MYSQL_PLUGIN_IMPORT const char **errmesg; extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd); extern "C" unsigned long long thd_query_id(const MYSQL_THD thd); extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen); extern "C" const char *thd_priv_user(MYSQL_THD thd, size_t *length); extern "C" const char *thd_priv_host(MYSQL_THD thd, size_t *length); extern "C" const char *thd_user_name(MYSQL_THD thd); extern "C" const char *thd_client_host(MYSQL_THD thd); extern "C" const char *thd_client_ip(MYSQL_THD thd); extern "C" LEX_CSTRING *thd_current_db(MYSQL_THD thd); extern "C" int thd_current_status(MYSQL_THD thd); extern "C" enum enum_server_command thd_current_command(MYSQL_THD thd); extern "C" int thd_double_innodb_cardinality(MYSQL_THD thd); /** @class CSET_STRING @brief Character set armed LEX_STRING */ class CSET_STRING { private: LEX_STRING string; CHARSET_INFO *cs; public: CSET_STRING() : cs(&my_charset_bin) { string.str= NULL; string.length= 0; } CSET_STRING(char *str_arg, size_t length_arg, CHARSET_INFO *cs_arg) : cs(cs_arg) { DBUG_ASSERT(cs_arg != NULL); string.str= str_arg; string.length= length_arg; } inline char *str() const { return string.str; } inline size_t length() const { return string.length; } CHARSET_INFO *charset() const { return cs; } friend LEX_STRING * thd_query_string (MYSQL_THD thd); }; class Recreate_info { ha_rows m_records_copied; ha_rows m_records_duplicate; public: Recreate_info() :m_records_copied(0), m_records_duplicate(0) { } Recreate_info(ha_rows records_copied, ha_rows records_duplicate) :m_records_copied(records_copied), m_records_duplicate(records_duplicate) { } ha_rows records_copied() const { return m_records_copied; } ha_rows records_duplicate() const { return m_records_duplicate; } ha_rows records_processed() const { return m_records_copied + m_records_duplicate; } }; #define TC_HEURISTIC_RECOVER_COMMIT 1 #define TC_HEURISTIC_RECOVER_ROLLBACK 2 extern ulong tc_heuristic_recover; typedef struct st_user_var_events { user_var_entry *user_var_event; char *value; size_t length; const Type_handler *th; uint charset_number; } BINLOG_USER_VAR_EVENT; /* The COPY_INFO structure is used by INSERT/REPLACE code. The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY UPDATE code: If a row is inserted then the copied variable is incremented. If a row is updated by the INSERT ... ON DUPLICATE KEY UPDATE and the new data differs from the old one then the copied and the updated variables are incremented. The touched variable is incremented if a row was touched by the update part of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row was actually changed or not. */ typedef struct st_copy_info { ha_rows records; /**< Number of processed records */ ha_rows deleted; /**< Number of deleted records */ ha_rows updated; /**< Number of updated records */ ha_rows copied; /**< Number of copied records */ ha_rows accepted_rows; /**< Number of accepted original rows (same as number of rows in RETURNING) */ ha_rows error_count; ha_rows touched; /* Number of touched records */ enum enum_duplicates handle_duplicates; int escape_char, last_errno; bool ignore; /* for INSERT ... UPDATE */ List<Item> *update_fields; List<Item> *update_values; /* for VIEW ... WITH CHECK OPTION */ TABLE_LIST *view; TABLE_LIST *table_list; /* Normal table */ } COPY_INFO; class Key_part_spec :public Sql_alloc { public: Lex_ident field_name; uint length; bool generated, asc; Key_part_spec(const LEX_CSTRING *name, uint len, bool gen= false) : field_name(*name), length(len), generated(gen), asc(1) {} bool operator==(const Key_part_spec& other) const; /** Construct a copy of this Key_part_spec. field_name is copied by-pointer as it is known to never change. At the same time 'length' may be reset in mysql_prepare_create_table, and this is why we supply it with a copy. @return If out of memory, 0 is returned and an error is set in THD. */ Key_part_spec *clone(MEM_ROOT *mem_root) const { return new (mem_root) Key_part_spec(*this); } bool check_key_for_blob(const class handler *file) const; bool check_key_length_for_blob() const; bool check_primary_key_for_blob(const class handler *file) const { return check_key_for_blob(file) || check_key_length_for_blob(); } bool check_foreign_key_for_blob(const class handler *file) const { return check_key_for_blob(file) || check_key_length_for_blob(); } bool init_multiple_key_for_blob(const class handler *file); }; class Alter_drop :public Sql_alloc { public: enum drop_type { KEY, COLUMN, FOREIGN_KEY, CHECK_CONSTRAINT, PERIOD }; const char *name; enum drop_type type; bool drop_if_exists; Alter_drop(enum drop_type par_type,const char *par_name, bool par_exists) :name(par_name), type(par_type), drop_if_exists(par_exists) { DBUG_ASSERT(par_name != NULL); } /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone */ Alter_drop *clone(MEM_ROOT *mem_root) const { return new (mem_root) Alter_drop(*this); } const char *type_name() { return type == COLUMN ? "COLUMN" : type == CHECK_CONSTRAINT ? "CONSTRAINT" : type == PERIOD ? "PERIOD" : type == KEY ? "INDEX" : "FOREIGN KEY"; } }; class Alter_column :public Sql_alloc { public: LEX_CSTRING name; LEX_CSTRING new_name; Virtual_column_info *default_value; bool alter_if_exists; Alter_column(LEX_CSTRING par_name, Virtual_column_info *expr, bool par_exists) :name(par_name), new_name{NULL, 0}, default_value(expr), alter_if_exists(par_exists) {} Alter_column(LEX_CSTRING par_name, LEX_CSTRING _new_name, bool exists) :name(par_name), new_name(_new_name), default_value(NULL), alter_if_exists(exists) {} /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone */ Alter_column *clone(MEM_ROOT *mem_root) const { return new (mem_root) Alter_column(*this); } bool is_rename() { DBUG_ASSERT(!new_name.str || !default_value); return new_name.str; } }; class Alter_rename_key : public Sql_alloc { public: LEX_CSTRING old_name; LEX_CSTRING new_name; bool alter_if_exists; Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg, bool exists) : old_name(old_name_arg), new_name(new_name_arg), alter_if_exists(exists) {} Alter_rename_key *clone(MEM_ROOT *mem_root) const { return new (mem_root) Alter_rename_key(*this); } }; /* An ALTER INDEX operation that changes the ignorability of an index. */ class Alter_index_ignorability: public Sql_alloc { public: Alter_index_ignorability(const char *name, bool is_ignored, bool if_exists) : m_name(name), m_is_ignored(is_ignored), m_if_exists(if_exists) { assert(name != NULL); } const char *name() const { return m_name; } bool if_exists() const { return m_if_exists; } /* The ignorability after the operation is performed. */ bool is_ignored() const { return m_is_ignored; } Alter_index_ignorability *clone(MEM_ROOT *mem_root) const { return new (mem_root) Alter_index_ignorability(*this); } private: const char *m_name; bool m_is_ignored; bool m_if_exists; }; class Key :public Sql_alloc, public DDL_options { public: enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY, IGNORE_KEY}; enum Keytype type; KEY_CREATE_INFO key_create_info; List<Key_part_spec> columns; LEX_CSTRING name; engine_option_value *option_list; bool generated; bool invisible; bool without_overlaps; bool old; uint length; Lex_ident period; Key(enum Keytype type_par, const LEX_CSTRING *name_arg, ha_key_alg algorithm_arg, bool generated_arg, DDL_options_st ddl_options) :DDL_options(ddl_options), type(type_par), key_create_info(default_key_create_info), name(*name_arg), option_list(NULL), generated(generated_arg), invisible(false), without_overlaps(false), old(false), length(0) { key_create_info.algorithm= algorithm_arg; } Key(enum Keytype type_par, const LEX_CSTRING *name_arg, KEY_CREATE_INFO *key_info_arg, bool generated_arg, List<Key_part_spec> *cols, engine_option_value *create_opt, DDL_options_st ddl_options) :DDL_options(ddl_options), type(type_par), key_create_info(*key_info_arg), columns(*cols), name(*name_arg), option_list(create_opt), generated(generated_arg), invisible(false), without_overlaps(false), old(false), length(0) {} Key(const Key &rhs, MEM_ROOT *mem_root); virtual ~Key() = default; /* Equality comparison of keys (ignoring name) */ friend bool is_foreign_key_prefix(Key *a, Key *b); /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone */ virtual Key *clone(MEM_ROOT *mem_root) const { return new (mem_root) Key(*this, mem_root); } }; class Foreign_key: public Key { public: enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL, FK_MATCH_PARTIAL, FK_MATCH_SIMPLE}; LEX_CSTRING constraint_name; LEX_CSTRING ref_db; LEX_CSTRING ref_table; List<Key_part_spec> ref_columns; enum enum_fk_option delete_opt, update_opt; enum fk_match_opt match_opt; Foreign_key(const LEX_CSTRING *name_arg, List<Key_part_spec> *cols, const LEX_CSTRING *constraint_name_arg, const LEX_CSTRING *ref_db_arg, const LEX_CSTRING *ref_table_arg, List<Key_part_spec> *ref_cols, enum_fk_option delete_opt_arg, enum_fk_option update_opt_arg, fk_match_opt match_opt_arg, DDL_options ddl_options) :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL, ddl_options), constraint_name(*constraint_name_arg), ref_db(*ref_db_arg), ref_table(*ref_table_arg), ref_columns(*ref_cols), delete_opt(delete_opt_arg), update_opt(update_opt_arg), match_opt(match_opt_arg) { } Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root); /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone */ Key *clone(MEM_ROOT *mem_root) const override { return new (mem_root) Foreign_key(*this, mem_root); } /* Used to validate foreign key options */ bool validate(List<Create_field> &table_fields); }; typedef struct st_mysql_lock { TABLE **table; THR_LOCK_DATA **locks; uint table_count,lock_count; uint flags; } MYSQL_LOCK; class LEX_COLUMN : public Sql_alloc { public: String column; privilege_t rights; LEX_COLUMN (const String& x,const privilege_t & y ): column (x),rights (y) {} }; class MY_LOCALE; /** Query_cache_tls -- query cache thread local data. */ struct Query_cache_block; struct Query_cache_tls { /* 'first_query_block' should be accessed only via query cache functions and methods to maintain proper locking. */ Query_cache_block *first_query_block; void set_first_query_block(Query_cache_block *first_query_block_arg) { first_query_block= first_query_block_arg; } Query_cache_tls() :first_query_block(NULL) {} }; /* SIGNAL / RESIGNAL / GET DIAGNOSTICS */ /** This enumeration list all the condition item names of a condition in the SQL condition area. */ typedef enum enum_diag_condition_item_name { /* Conditions that can be set by the user (SIGNAL/RESIGNAL), and by the server implementation. */ DIAG_CLASS_ORIGIN= 0, FIRST_DIAG_SET_PROPERTY= DIAG_CLASS_ORIGIN, DIAG_SUBCLASS_ORIGIN= 1, DIAG_CONSTRAINT_CATALOG= 2, DIAG_CONSTRAINT_SCHEMA= 3, DIAG_CONSTRAINT_NAME= 4, DIAG_CATALOG_NAME= 5, DIAG_SCHEMA_NAME= 6, DIAG_TABLE_NAME= 7, DIAG_COLUMN_NAME= 8, DIAG_CURSOR_NAME= 9, DIAG_MESSAGE_TEXT= 10, DIAG_MYSQL_ERRNO= 11, DIAG_ROW_NUMBER= 12, LAST_DIAG_SET_PROPERTY= DIAG_ROW_NUMBER } Diag_condition_item_name; /** Name of each diagnostic condition item. This array is indexed by Diag_condition_item_name. */ extern const LEX_CSTRING Diag_condition_item_names[]; /** These states are bit coded with HARD. For each state there must be a pair <state_even_num>, and <state_odd_num>_HARD. */ enum killed_state { NOT_KILLED= 0, KILL_HARD_BIT= 1, /* Bit for HARD KILL */ KILL_BAD_DATA= 2, KILL_BAD_DATA_HARD= 3, KILL_QUERY= 4, KILL_QUERY_HARD= 5, /* ABORT_QUERY signals to the query processor to stop execution ASAP without issuing an error. Instead a warning is issued, and when possible a partial query result is returned to the client. */ ABORT_QUERY= 6, ABORT_QUERY_HARD= 7, KILL_TIMEOUT= 8, KILL_TIMEOUT_HARD= 9, /* When binlog reading thread connects to the server it kills all the binlog threads with the same ID. */ KILL_SLAVE_SAME_ID= 10, /* All of the following killed states will kill the connection KILL_CONNECTION must be the first of these and it must start with an even number (becasue of HARD bit)! */ KILL_CONNECTION= 12, KILL_CONNECTION_HARD= 13, KILL_SYSTEM_THREAD= 14, KILL_SYSTEM_THREAD_HARD= 15, KILL_SERVER= 16, KILL_SERVER_HARD= 17, /* Used in threadpool to signal wait timeout. */ KILL_WAIT_TIMEOUT= 18, KILL_WAIT_TIMEOUT_HARD= 19 }; #define killed_mask_hard(killed) ((killed_state) ((killed) & ~KILL_HARD_BIT)) enum killed_type { KILL_TYPE_ID, KILL_TYPE_USER, KILL_TYPE_QUERY }; #define SECONDS_TO_WAIT_FOR_KILL 2 #define SECONDS_TO_WAIT_FOR_DUMP_THREAD_KILL 10 #if !defined(_WIN32) && defined(HAVE_SELECT) /* my_sleep() can wait for sub second times */ #define WAIT_FOR_KILL_TRY_TIMES 20 #else #define WAIT_FOR_KILL_TRY_TIMES 2 #endif #include "sql_lex.h" /* Must be here */ class Delayed_insert; class select_result; class Time_zone; #define THD_SENTRY_MAGIC 0xfeedd1ff #define THD_SENTRY_GONE 0xdeadbeef #define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC) typedef struct system_variables { /* How dynamically allocated system variables are handled: The global_system_variables and max_system_variables are "authoritative" They both should have the same 'version' and 'size'. When attempting to access a dynamic variable, if the session version is out of date, then the session version is updated and realloced if neccessary and bytes copied from global to make up for missing data. Note that one should use my_bool instead of bool here, as the variables are used with my_getopt.c */ ulong dynamic_variables_version; char* dynamic_variables_ptr; uint dynamic_variables_head; /* largest valid variable offset */ uint dynamic_variables_size; /* how many bytes are in use */ ulonglong max_heap_table_size; ulonglong tmp_memory_table_size; ulonglong tmp_disk_table_size; ulonglong long_query_time; ulonglong max_statement_time; ulonglong optimizer_switch; ulonglong optimizer_trace; sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled sql_mode_t new_behavior; ///< which new SQL behaviour should be enabled ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING ulonglong join_buff_space_limit; ulonglong log_slow_filter; ulonglong log_slow_verbosity; ulonglong log_slow_disabled_statements; ulonglong log_disabled_statements; ulonglong note_verbosity; ulonglong bulk_insert_buff_size; ulonglong join_buff_size; ulonglong sortbuff_size; ulonglong default_regex_flags; ulonglong max_mem_used; ulonglong max_rowid_filter_size; /** Place holders to store Multi-source variables in sys_var.cc during update and show of variables. */ ulonglong slave_skip_counter; ulonglong max_relay_log_size; double optimizer_where_cost, optimizer_scan_setup_cost; double long_query_time_double, max_statement_time_double; double sample_percentage; ha_rows select_limit; ha_rows max_join_size; ha_rows expensive_subquery_limit; #ifdef WITH_WSREP /* Stored values of the auto_increment_increment and auto_increment_offset that are will be restored when wsrep_auto_increment_control will be set to 'OFF', because the setting it to 'ON' leads to overwriting of the original values (which are set by the user) by calculated ones (which are based on the cluster size): */ ulonglong wsrep_gtid_seq_no; ulong saved_auto_increment_increment, saved_auto_increment_offset; ulong saved_lock_wait_timeout; #endif /* WITH_WSREP */ uint analyze_max_length; ulong auto_increment_increment, auto_increment_offset; ulong column_compression_zlib_strategy; ulong lock_wait_timeout; ulong join_cache_level; ulong max_allowed_packet; ulong max_error_count; ulong max_length_for_sort_data; ulong max_recursive_iterations; ulong max_sort_length; ulong max_insert_delayed_threads; ulong min_examined_row_limit; ulong net_buffer_length; ulong net_interactive_timeout; ulong net_read_timeout; ulong net_retry_count; ulong net_wait_timeout; ulong net_write_timeout; ulong optimizer_extra_pruning_depth; ulonglong optimizer_join_limit_pref_ratio; ulong optimizer_prune_level; ulong optimizer_search_depth; ulong optimizer_selectivity_sampling_limit; ulong optimizer_use_condition_selectivity; ulong optimizer_max_sel_arg_weight; ulong optimizer_max_sel_args; ulong optimizer_trace_max_mem_size; ulong optimizer_adjust_secondary_key_costs; ulong use_stat_tables; ulong histogram_size; ulong histogram_type; ulong preload_buff_size; ulong profiling_history_size; ulong read_buff_size; ulong read_rnd_buff_size; ulong mrr_buff_size; ulong div_precincrement; /* Total size of all buffers used by the subselect_rowid_merge_engine. */ ulong rowid_merge_buff_size; ulong max_sp_recursion_depth; ulong default_week_format; ulong max_seeks_for_key; ulong range_alloc_block_size; ulong query_alloc_block_size; ulong query_prealloc_size; ulong trans_alloc_block_size; ulong trans_prealloc_size; ulong log_warnings; ulong block_encryption_mode; ulong log_slow_max_warnings; /* Flags for slow log filtering */ ulong log_slow_rate_limit; ulong binlog_format; ///< binlog format for this thd (see enum_binlog_format) ulong binlog_row_image; ulong progress_report_time; ulong completion_type; ulong query_cache_type; ulong tx_isolation; ulong updatable_views_with_limit; ulong alter_algorithm; ulong server_id; ulong session_track_transaction_info; ulong threadpool_priority; ulong vers_alter_history; /* deadlock detection */ ulong wt_timeout_short, wt_deadlock_search_depth_short; ulong wt_timeout_long, wt_deadlock_search_depth_long; /** In slave thread we need to know in behalf of which thread the query is being run to replicate temp tables properly */ my_thread_id pseudo_thread_id; /** When replicating an event group with GTID, keep these values around so slave binlog can receive the same GTID as the original. */ uint64 gtid_seq_no; uint32 gtid_domain_id; uint group_concat_max_len; uint eq_range_index_dive_limit; uint idle_transaction_timeout; uint idle_readonly_transaction_timeout; uint idle_write_transaction_timeout; uint column_compression_threshold; uint column_compression_zlib_level; uint in_subquery_conversion_threshold; int max_user_connections; /** Default transaction access mode. READ ONLY (true) or READ WRITE (false). */ my_bool tx_read_only; my_bool low_priority_updates; my_bool query_cache_wlock_invalidate; my_bool keep_files_on_create; my_bool old_mode; my_bool old_passwords; my_bool big_tables; my_bool only_standard_compliant_cte; my_bool query_cache_strip_comments; my_bool sql_log_slow; my_bool sql_log_bin; my_bool binlog_annotate_row_events; my_bool binlog_direct_non_trans_update; my_bool column_compression_zlib_wrap; my_bool sysdate_is_now; my_bool wsrep_on; my_bool wsrep_dirty_reads; my_bool pseudo_slave_mode; my_bool session_track_schema; my_bool session_track_state_change; #ifdef USER_VAR_TRACKING my_bool session_track_user_variables; #endif // USER_VAR_TRACKING my_bool tcp_nodelay; plugin_ref table_plugin; plugin_ref tmp_table_plugin; plugin_ref enforced_table_plugin; /* Only charset part of these variables is sensible */ CHARSET_INFO *character_set_filesystem; CHARSET_INFO *character_set_client; CHARSET_INFO *character_set_results; /* Both charset and collation parts of these variables are important */ CHARSET_INFO *collation_server; CHARSET_INFO *collation_database; CHARSET_INFO *collation_connection; /* Names. These will be allocated in buffers in thd */ LEX_CSTRING default_master_connection; /* Error messages */ MY_LOCALE *lc_messages; const char ***errmsgs; /* lc_messages->errmsg->errmsgs */ /* Locale Support */ MY_LOCALE *lc_time_names; Time_zone *time_zone; char *session_track_system_variables; char *redirect_url; /* Some wsrep variables */ ulonglong wsrep_trx_fragment_size; ulong wsrep_retry_autocommit; ulong wsrep_trx_fragment_unit; ulong wsrep_OSU_method; uint wsrep_sync_wait; vers_asof_timestamp_t vers_asof_timestamp; my_bool binlog_alter_two_phase; Charset_collation_map_st character_set_collations; } SV; /** Per thread status variables. Must be long/ulong up to last_system_status_var so that add_to_status/add_diff_to_status can work. */ typedef struct system_status_var { ulong column_compressions; ulong column_decompressions; ulong com_stat[(uint) SQLCOM_END]; ulong com_create_tmp_table; ulong com_drop_tmp_table; ulong com_other; ulong com_stmt_prepare; ulong com_stmt_reprepare; ulong com_stmt_execute; ulong com_stmt_send_long_data; ulong com_stmt_fetch; ulong com_stmt_reset; ulong com_stmt_close; ulong com_register_slave; ulong created_tmp_disk_tables_; ulong created_tmp_tables_; ulong ha_commit_count; ulong ha_delete_count; ulong ha_read_first_count; ulong ha_read_last_count; ulong ha_read_key_count; ulong ha_read_next_count; ulong ha_read_prev_count; ulong ha_read_retry_count; ulong ha_read_rnd_count; ulong ha_read_rnd_next_count; ulong ha_read_rnd_deleted_count; /* This number doesn't include calls to the default implementation and calls made by range access. The intent is to count only calls made by BatchedKeyAccess. */ ulong ha_mrr_init_count; ulong ha_mrr_key_refills_count; ulong ha_mrr_rowid_refills_count; ulong ha_rollback_count; ulong ha_update_count; ulong ha_write_count; /* The following are for internal temporary tables */ ulong ha_tmp_update_count; ulong ha_tmp_write_count; ulong ha_tmp_delete_count; ulong ha_prepare_count; ulong ha_icp_attempts; ulong ha_icp_match; ulong ha_discover_count; ulong ha_savepoint_count; ulong ha_savepoint_rollback_count; ulong ha_external_lock_count; ulong opened_tables; ulong opened_shares; ulong opened_views; /* +1 opening a view */ ulong select_full_join_count_; ulong select_full_range_join_count_; ulong select_range_count_; ulong select_range_check_count_; ulong select_scan_count_; ulong update_scan_count; ulong delete_scan_count; ulong executed_triggers; ulong long_query_count; ulong filesort_merge_passes_; ulong filesort_range_count_; ulong filesort_rows_; ulong filesort_scan_count_; ulong filesort_pq_sorts_; ulong optimizer_join_prefixes_check_calls; /* Features used */ ulong feature_custom_aggregate_functions; /* +1 when custom aggregate functions are used */ ulong feature_dynamic_columns; /* +1 when creating a dynamic column */ ulong feature_fulltext; /* +1 when MATCH is used */ ulong feature_gis; /* +1 opening table with GIS features */ ulong feature_invisible_columns; /* +1 opening table with invisible column */ ulong feature_json; /* +1 when JSON function is used */ ulong feature_locale; /* +1 when LOCALE is set */ ulong feature_subquery; /* +1 when subqueries are used */ ulong feature_system_versioning; /* +1 opening table WITH SYSTEM VERSIONING */ ulong feature_application_time_periods; /* +1 opening a table with application-time period */ ulong feature_insert_returning; /* +1 when INSERT...RETURNING is used */ ulong feature_timezone; /* +1 when XPATH is used */ ulong feature_trigger; /* +1 opening a table with triggers */ ulong feature_xml; /* +1 when XPATH is used */ ulong feature_window_functions; /* +1 when window functions are used */ ulong feature_into_outfile; /* +1 when INTO OUTFILE is used */ ulong feature_into_variable; /* +1 when INTO VARIABLE is used */ /* From MASTER_GTID_WAIT usage */ ulong master_gtid_wait_timeouts; /* Number of timeouts */ ulong master_gtid_wait_time; /* Time in microseconds */ ulong master_gtid_wait_count; ulong empty_queries; ulong access_denied_errors; ulong lost_connections; ulong max_statement_time_exceeded; /* Number of times where column info was not sent with prepared statement metadata. */ ulong skip_metadata_count; /* Number of statements sent from the client */ ulong questions; /* IMPORTANT! SEE last_system_status_var DEFINITION BELOW. Below 'last_system_status_var' are all variables that cannot be handled automatically by add_to_status()/add_diff_to_status(). */ ulonglong bytes_received; ulonglong bytes_sent; ulonglong rows_read; ulonglong rows_sent; ulonglong rows_tmp_read; ulonglong binlog_bytes_written; ulonglong table_open_cache_hits; ulonglong table_open_cache_misses; ulonglong table_open_cache_overflows; ulonglong cpu_time, busy_time, query_time; double last_query_cost; uint32 threads_running; /* Don't initialize */ /* Memory used for thread local storage */ int64 max_local_memory_used; volatile int64 local_memory_used; /* Memory allocated for global usage */ volatile int64 global_memory_used; } STATUS_VAR; /* This is used for 'SHOW STATUS'. It must be updated to the last ulong variable in system_status_var which is makes sense to add to the global counter */ #define last_system_status_var questions #define last_cleared_system_status_var local_memory_used /** Number of contiguous global status variables */ constexpr int COUNT_GLOBAL_STATUS_VARS= int(offsetof(STATUS_VAR, last_system_status_var) / sizeof(ulong)) + 1; /* Global status variables */ extern ulong feature_files_opened_with_delayed_keys, feature_check_constraint; void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var); void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var); uint calc_sum_of_all_status(STATUS_VAR *to); static inline void calc_sum_of_all_status_if_needed(STATUS_VAR *to) { if (to->local_memory_used == 0) { mysql_mutex_lock(&LOCK_status); *to= global_status_var; mysql_mutex_unlock(&LOCK_status); calc_sum_of_all_status(to); DBUG_ASSERT(to->local_memory_used); } } /* Update global_memory_used. We have to do this with atomic_add as the global value can change outside of LOCK_status. */ static inline void update_global_memory_status(int64 size) { DBUG_PRINT("info", ("global memory_used: %lld size: %lld", (longlong) global_status_var.global_memory_used, size)); // workaround for gcc 4.2.4-1ubuntu4 -fPIE (from DEB_BUILD_HARDENING=1) int64 volatile * volatile ptr= &global_status_var.global_memory_used; my_atomic_add64_explicit(ptr, size, MY_MEMORY_ORDER_RELAXED); } static inline bool is_supported_parser_charset(CHARSET_INFO *cs) { return MY_TEST(cs->mbminlen == 1 && cs->number != 17 /* filename */); } /** THD registry */ class THD_list_iterator { protected: I_List<THD> threads; mutable mysql_rwlock_t lock; public: /** Iterates registered threads. @param action called for every element @param argument opque argument passed to action @return @retval 0 iteration completed successfully @retval 1 iteration was interrupted (action returned 1) */ template <typename T> int iterate(my_bool (*action)(THD *thd, T *arg), T *arg= 0) { int res= 0; mysql_rwlock_rdlock(&lock); I_List_iterator<THD> it(threads); while (auto tmp= it++) if ((res= action(tmp, arg))) break; mysql_rwlock_unlock(&lock); return res; } static THD_list_iterator *iterator(); }; /** A counter of THDs It must be specified as a first base class of THD, so that increment is done before any other THD constructors and decrement - after any other THD destructors. Destructor unblocks close_conneciton() if there are no more THD's left. */ struct THD_count { static Atomic_counter<uint32_t> count; static uint value() { return static_cast<uint>(count); } static uint connection_thd_count(); THD_count() { count++; } ~THD_count() { count--; } }; #ifdef MYSQL_SERVER void free_tmp_table(THD *thd, TABLE *entry); /* The following macro is to make init of Query_arena simpler */ #ifdef DBUG_ASSERT_EXISTS #define INIT_ARENA_DBUG_INFO is_backup_arena= 0; is_reprepared= FALSE; #else #define INIT_ARENA_DBUG_INFO #endif class Query_arena { public: /* List of items created in the parser for this query. Every item puts itself to the list on creation (see Item::Item() for details)) */ Item *free_list; MEM_ROOT *mem_root; // Pointer to current memroot #ifdef DBUG_ASSERT_EXISTS bool is_backup_arena; /* True if this arena is used for backup. */ bool is_reprepared; #endif /* The states relfects three diffrent life cycles for three different types of statements: Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED. Stored procedure: STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED. Other statements: STMT_CONVENTIONAL_EXECUTION never changes. Special case for stored procedure arguments: STMT_SP_QUERY_ARGUMENTS This state never changes and used for objects whose lifetime is whole duration of function call (sp_rcontext, it's tables and items. etc). Such objects should be deallocated after every execution of a stored routine. Caller's arena/memroot can't be used for placing such objects since memory allocated on caller's arena not freed until termination of user's session. */ enum enum_state { STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2, STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_SP_QUERY_ARGUMENTS= 5, STMT_ERROR= -1 }; enum_state state; public: /* We build without RTTI, so dynamic_cast can't be used. */ enum Type { STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE }; Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : free_list(0), mem_root(mem_root_arg), state(state_arg) { INIT_ARENA_DBUG_INFO; } /* This constructor is used only when Query_arena is created as backup storage for another instance of Query_arena. */ Query_arena() { INIT_ARENA_DBUG_INFO; } virtual Type type() const; virtual ~Query_arena() = default; inline bool is_stmt_prepare() const { return state == STMT_INITIALIZED; } inline bool is_stmt_prepare_or_first_sp_execute() const { return (int)state < (int)STMT_PREPARED; } inline bool is_stmt_prepare_or_first_stmt_execute() const { return (int)state <= (int)STMT_PREPARED; } inline bool is_stmt_execute() const { return state == STMT_PREPARED || state == STMT_EXECUTED; } inline bool is_conventional() const { return state == STMT_CONVENTIONAL_EXECUTION; } inline void* alloc(size_t size) const { return alloc_root(mem_root,size); } inline void* calloc(size_t size) const { void *ptr; if (likely((ptr=alloc_root(mem_root,size)))) bzero(ptr, size); return ptr; } inline char *strdup(const char *str) const { return strdup_root(mem_root,str); } inline char *strmake(const char *str, size_t size) const { return strmake_root(mem_root,str,size); } inline LEX_CSTRING strcat(const LEX_CSTRING &a, const LEX_CSTRING &b) const { char *buf= (char*)alloc(a.length + b.length + 1); if (unlikely(!buf)) return null_clex_str; memcpy(buf, a.str, a.length); memcpy(buf + a.length, b.str, b.length); buf[a.length + b.length] = 0; return {buf, a.length + b.length}; } inline void *memdup(const void *str, size_t size) const { return memdup_root(mem_root,str,size); } inline void *memdup_w_gap(const void *str, size_t size, size_t gap) const { void *ptr; if (likely((ptr= alloc_root(mem_root,size+gap)))) memcpy(ptr,str,size); return ptr; } /* Methods to copy a string to the memory root and return the value as a LEX_CSTRING. */ LEX_CSTRING strmake_lex_cstring(const char *str, size_t length) const { const char *tmp= strmake_root(mem_root, str, length); if (!tmp) return {0,0}; return {tmp, length}; } LEX_CSTRING strmake_lex_cstring(const LEX_CSTRING &from) const { return strmake_lex_cstring(from.str, from.length); } LEX_CSTRING strmake_lex_cstring_trim_whitespace(const LEX_CSTRING &from, CHARSET_INFO *cs) { return strmake_lex_cstring(Lex_cstring(from).trim_whitespace(cs)); } /* Methods to copy a string to memory root, write the result to the out parameter, and return as a LEX_STRING/LEX_CSTRING pointer. */ LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, size_t length) const { if (!(lex_str->str= strmake_root(mem_root, str, length))) { lex_str->length= 0; return 0; } lex_str->length= length; return lex_str; } LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str, const char* str, size_t length) const { if (!(lex_str->str= strmake_root(mem_root, str, length))) { lex_str->length= 0; return 0; } lex_str->length= length; return lex_str; } /* Methods to copy a string value on memory root, but also allocate on memory root LEX_CSTRING itself and return a pointer to it. */ LEX_CSTRING *make_clex_string(const char* str, size_t length) const { LEX_CSTRING *lex_str; char *tmp; if (unlikely(!(lex_str= (LEX_CSTRING *)alloc_root(mem_root, sizeof(LEX_CSTRING) + length+1)))) return 0; tmp= (char*) (lex_str+1); lex_str->str= tmp; memcpy(tmp, str, length); tmp[length]= 0; lex_str->length= length; return lex_str; } LEX_CSTRING *make_clex_string(const LEX_CSTRING from) const { return make_clex_string(from.str, from.length); } // Allocate LEX_STRING for character set conversion bool alloc_lex_string(LEX_STRING *dst, size_t length) const { if (likely((dst->str= (char*) alloc(length)))) return false; dst->length= 0; // Safety return true; // EOM } // Remove double quotes: aaa""bbb -> aaa"bbb bool quote_unescape(LEX_CSTRING *dst, const LEX_CSTRING *src, char quote) const { const char *tmp= src->str; const char *tmpend= src->str + src->length; char *to; if (!(dst->str= to= (char *) alloc(src->length + 1))) { dst->length= 0; // Safety return true; } for ( ; tmp < tmpend; ) { if ((*to++= *tmp++) == quote) tmp++; // Skip double quotes } *to= 0; // End null for safety dst->length= to - dst->str; return false; } /* Make a lower-cased copy of an identifier on mem_root. @param src - The original identifier (usually coming from the parser) @return - {NULL,0} in case of EOM, or a non-NULL LEX_STRING with the lower-cased identifier copy. */ LEX_STRING make_ident_casedn(const LEX_CSTRING &src) { return lex_string_casedn_root(mem_root, &my_charset_utf8mb3_general_ci, src.str, src.length); } /* Make an exact copy or a lower-cased copy of an identifier on mem_root. @param src - The original identifier (usually coming from the parser) @param casedn - If the name should be converted to lower case @return - {NULL,0} in case of EOM, or a non-NULL LEX_STRING with the identifier copy. */ LEX_STRING make_ident_opt_casedn(const LEX_CSTRING &src, bool casedn) { return casedn ? make_ident_casedn(src) : lex_string_strmake_root(mem_root, src.str, src.length); } /* Convert a LEX_CSTRING to a valid internal database name: - validated with Lex_ident_fs::check_db_name() - optionally lower-cased when lower_case_table_names==1 The lower-cased copy is created on Query_arena::mem_root, when needed. @param name - The name to normalize. Must not be {NULL,0}. @return - {NULL,0} on EOM or a bad database name (with an errror is raised, or a good database name otherwise. */ Lex_ident_db to_ident_db_internal_with_error(const LEX_CSTRING &name); void set_query_arena(Query_arena *set); void free_items(); /* Close the active state associated with execution of this statement */ virtual bool cleanup_stmt(bool /*restore_set_statement_vars*/); }; class Query_arena_memroot: public Query_arena, public Sql_alloc { public: Query_arena_memroot(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : Query_arena(mem_root_arg, state_arg) {} Query_arena_memroot() : Query_arena() {} virtual ~Query_arena_memroot() = default; }; class Query_arena_stmt { THD *thd; Query_arena backup; Query_arena *arena; public: Query_arena_stmt(THD *_thd); ~Query_arena_stmt(); bool arena_replaced() { return arena != NULL; } }; class Server_side_cursor; /* Struct to catch changes in column metadata that is sent to client. in the "result set metadata". Used to support MARIADB_CLIENT_CACHE_METADATA. */ struct send_column_info_state { /* Last client charset (affects metadata) */ CHARSET_INFO *last_charset= nullptr; /* Checksum, only used to check changes if 'immutable' is false*/ uint32 checksum= 0; /* Column info can only be changed by PreparedStatement::reprepare() There is a class of "weird" prepared statements like SELECT ? or SELECT @a that are not immutable, and depend on input parameters or user variables */ bool immutable= false; bool initialized= false; /* Used by PreparedStatement::reprepare()*/ void reset() { initialized= false; checksum= 0; } }; extern uint sql_command_flags[]; /** @class Statement @brief State of a single command executed against this connection. One connection can contain a lot of simultaneously running statements, some of which could be: - prepared, that is, contain placeholders, - opened as cursors. We maintain 1 to 1 relationship between statement and cursor - if user wants to create another cursor for his query, we create another statement for it. To perform some action with statement we reset THD part to the state of that statement, do the action, and then save back modified state from THD to the statement. It will be changed in near future, and Statement will be used explicitly. */ class Statement: public ilink, public Query_arena { Statement(const Statement &rhs); /* not implemented: */ Statement &operator=(const Statement &rhs); /* non-copyable */ public: /* Uniquely identifies each statement object in thread scope; change during statement lifetime. FIXME: must be const */ ulong id; enum enum_column_usage column_usage; LEX_CSTRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor my_hrtime_t hr_prepare_time; // time of preparation in microseconds /* Points to the query associated with this statement. It's const, but we need to declare it char * because all table handlers are written in C and need to point to it. Note that if we set query = NULL, we must at the same time set query_length = 0, and protect the whole operation with LOCK_thd_data mutex. To avoid crashes in races, if we do not know that thd->query cannot change at the moment, we should print thd->query like this: (1) reserve the LOCK_thd_data mutex; (2) print or copy the value of query and query_length (3) release LOCK_thd_data mutex. This printing is needed at least in SHOW PROCESSLIST and SHOW ENGINE INNODB STATUS. */ CSET_STRING query_string; /* If opt_query_cache_strip_comments is set, this contains query without comments. If not set, it contains pointer to query_string. */ String base_query; inline char *query() const { return query_string.str(); } inline uint32 query_length() const { return static_cast<uint32>(query_string.length()); } inline char *query_end() const { return query_string.str() + query_string.length(); } CHARSET_INFO *query_charset() const { return query_string.charset(); } void set_query_inner(const CSET_STRING &string_arg) { query_string= string_arg; } void set_query_inner(char *query_arg, uint32 query_length_arg, CHARSET_INFO *cs_arg) { set_query_inner(CSET_STRING(query_arg, query_length_arg, cs_arg)); } void reset_query_inner() { set_query_inner(CSET_STRING()); } ulong sql_command_flags() const { return ::sql_command_flags[lex->sql_command]; } /** Name of the current (default) database. If there is the current (default) database, "db.str" contains its name. If there is no current (default) database, "db.str" is NULL and "db.length" is 0. In other words, db must either be NULL, or contain a valid database name. */ LEX_CSTRING db; send_column_info_state column_info_state; /* This is set to 1 of last call to send_result_to_client() was ok */ my_bool query_cache_is_applicable; /* This constructor is called for backup statements */ Statement() = default; Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, enum enum_state state_arg, ulong id_arg); virtual ~Statement(); /* Assign execution context (note: not all members) of given stmt to self */ virtual void set_statement(Statement *stmt); void set_n_backup_statement(Statement *stmt, Statement *backup); void restore_backup_statement(Statement *stmt, Statement *backup); /* return class type */ Type type() const override; }; /** Container for all statements created/used in a connection. Statements in Statement_map have unique Statement::id (guaranteed by id assignment in Statement::Statement) Non-empty statement names are unique too: attempt to insert a new statement with duplicate name causes older statement to be deleted Statements are auto-deleted when they are removed from the map and when the map is deleted. */ class Statement_map { public: Statement_map(); int insert(THD *thd, Statement *statement); Statement *find_by_name(const LEX_CSTRING *name) { Statement *stmt; stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str, name->length); return stmt; } Statement *find(ulong id) { if (last_found_statement == 0 || id != last_found_statement->id) { Statement *stmt; stmt= (Statement *) my_hash_search(&st_hash, (uchar *) &id, sizeof(id)); if (stmt && stmt->name.str) return NULL; last_found_statement= stmt; } return last_found_statement; } /* Close all cursors of this connection that use tables of a storage engine that has transaction-specific state and therefore can not survive COMMIT or ROLLBACK. Currently all but MyISAM cursors are closed. */ void close_transient_cursors(); void erase(Statement *statement); /* Erase all statements (calls Statement destructor) */ void reset(); ~Statement_map(); private: HASH st_hash; HASH names_hash; I_List<Statement> transient_cursor_list; Statement *last_found_statement; }; struct st_savepoint { struct st_savepoint *prev; char *name; uint length; Ha_trx_info *ha_list; /** State of metadata locks before this savepoint was set. */ MDL_savepoint mdl_savepoint; }; /** @class Security_context @brief A set of THD members describing the current authenticated user. */ class Security_context { public: Security_context() :master_access(NO_ACL), db_access(NO_ACL) {} /* Remove gcc warning */ /* host - host of the client user - user of the client, set to NULL until the user has been read from the connection priv_user - The user privilege we are using. May be "" for anonymous user. ip - client IP */ const char *host; const char *user, *ip; char priv_user[USERNAME_LENGTH]; char proxy_user[USERNAME_LENGTH + MAX_HOSTNAME + 5]; /* The host privilege we are using */ char priv_host[MAX_HOSTNAME]; /* The role privilege we are using */ char priv_role[USERNAME_LENGTH]; /* The external user (if available) */ char *external_user; /* points to host if host is available, otherwise points to ip */ const char *host_or_ip; privilege_t master_access; /* Global privileges from mysql.user */ privilege_t db_access; /* Privileges for current db */ bool password_expired; void init(); void destroy(); void skip_grants(); inline char *priv_host_name() { return (*priv_host ? priv_host : (char *)"%"); } bool set_user(char *user_arg); #ifndef NO_EMBEDDED_ACCESS_CHECKS bool change_security_context(THD *thd, LEX_CSTRING *definer_user, LEX_CSTRING *definer_host, LEX_CSTRING *db, Security_context **backup); void restore_security_context(THD *thd, Security_context *backup); #endif bool user_matches(Security_context *); /** Check global access @param want_access The required privileges @param match_any if the security context must match all or any of the req. * privileges. @return True if the security context fulfills the access requirements. */ bool check_access(const privilege_t want_access, bool match_any = false); bool is_priv_user(const char *user, const char *host); bool is_user_defined() const { return user && user != delayed_user && user != slave_user && user != wsrep_user; }; }; /** A registry for item tree transformations performed during query optimization. We register only those changes which require a rollback to re-execute a prepared statement or stored procedure yet another time. */ struct Item_change_record; class Item_change_list { I_List<Item_change_record> change_list; public: void nocheck_register_item_tree_change(Item **place, Item *old_value, MEM_ROOT *runtime_memroot); void check_and_register_item_tree_change(Item **place, Item **new_value, MEM_ROOT *runtime_memroot); void rollback_item_tree_changes(); void move_elements_to(Item_change_list *to) { change_list.move_elements_to(&to->change_list); } bool is_empty() { return change_list.is_empty(); } }; class Item_change_list_savepoint: public Item_change_list { public: Item_change_list_savepoint(Item_change_list *list) { list->move_elements_to(this); } void rollback(Item_change_list *list) { list->rollback_item_tree_changes(); move_elements_to(list); } ~Item_change_list_savepoint() { DBUG_ASSERT(is_empty()); } }; /** Type of locked tables mode. See comment for THD::locked_tables_mode for complete description. */ enum enum_locked_tables_mode { LTM_NONE= 0, LTM_LOCK_TABLES, LTM_PRELOCKED, /* TODO: remove LTM_PRELOCKED_UNDER_LOCK_TABLES: it is never used apart from LTM_LOCK_TABLES. */ LTM_PRELOCKED_UNDER_LOCK_TABLES, LTM_always_last }; /** The following structure is an extension to TABLE_SHARE and is exclusively for temporary tables. @note: Although, TDC_element has data members (like next, prev & all_tables) to store the list of TABLE_SHARE & TABLE objects related to a particular TABLE_SHARE, they cannot be moved to TABLE_SHARE in order to be reused for temporary tables. This is because, as concurrent threads iterating through hash of TDC_element's may need access to all_tables, but if all_tables is made part of TABLE_SHARE, then TDC_element->share->all_tables is not always guaranteed to be valid, as TDC_element can live longer than TABLE_SHARE. */ struct TMP_TABLE_SHARE : public TABLE_SHARE { private: /* Link to all temporary table shares. Declared as private to avoid direct manipulation with those objects. One should use methods of I_P_List template instead. */ TMP_TABLE_SHARE *tmp_next; TMP_TABLE_SHARE **tmp_prev; friend struct All_tmp_table_shares; public: /* Doubly-linked (back-linked) lists of used and unused TABLE objects for this share. */ All_share_tables_list all_tmp_tables; }; /** Helper class which specifies which members of TMP_TABLE_SHARE are used for participation in the list of temporary tables. */ struct All_tmp_table_shares { static inline TMP_TABLE_SHARE **next_ptr(TMP_TABLE_SHARE *l) { return &l->tmp_next; } static inline TMP_TABLE_SHARE ***prev_ptr(TMP_TABLE_SHARE *l) { return &l->tmp_prev; } }; /* Also used in rpl_rli.h. */ typedef I_P_List <TMP_TABLE_SHARE, All_tmp_table_shares> All_tmp_tables_list; /** Class that holds information about tables which were opened and locked by the thread. It is also used to save/restore this information in push_open_tables_state()/pop_open_tables_state(). */ class Open_tables_state { public: /** As part of class THD, this member is set during execution of a prepared statement. When it is set, it is used by the locking subsystem to report a change in table metadata. When Open_tables_state part of THD is reset to open a system or INFORMATION_SCHEMA table, the member is cleared to avoid spurious ER_NEED_REPREPARE errors -- system and INFORMATION_SCHEMA tables are not subject to metadata version tracking. @sa check_and_update_table_version() */ Reprepare_observer *m_reprepare_observer; /** List of regular tables in use by this thread. Contains temporary and base tables that were opened with @see open_tables(). */ TABLE *open_tables; /** A list of temporary tables used by this thread. This includes user-level temporary tables, created with CREATE TEMPORARY TABLE, and internal temporary tables, created, e.g., to resolve a SELECT, or for an intermediate table used in ALTER. */ All_tmp_tables_list *temporary_tables; /* Derived tables. */ TABLE *derived_tables; /* Temporary tables created for recursive table references. */ TABLE *rec_tables; /* During a MySQL session, one can lock tables in two modes: automatic or manual. In automatic mode all necessary tables are locked just before statement execution, and all acquired locks are stored in 'lock' member. Unlocking takes place automatically as well, when the statement ends. Manual mode comes into play when a user issues a 'LOCK TABLES' statement. In this mode the user can only use the locked tables. Trying to use any other tables will give an error. The locked tables are also stored in this member, however, thd->locked_tables_mode is turned on. Manual locking is described in the 'LOCK_TABLES' chapter of the MySQL manual. See also lock_tables() for details. */ MYSQL_LOCK *lock; /* CREATE-SELECT keeps an extra lock for the table being created. This field is used to keep the extra lock available for lower level routines, which would otherwise miss that lock. */ MYSQL_LOCK *extra_lock; /* Enum enum_locked_tables_mode and locked_tables_mode member are used to indicate whether the so-called "locked tables mode" is on, and what kind of mode is active. Locked tables mode is used when it's necessary to open and lock many tables at once, for usage across multiple (sub-)statements. This may be necessary either for queries that use stored functions and triggers, in which case the statements inside functions and triggers may be executed many times, or for implementation of LOCK TABLES, in which case the opened tables are reused by all subsequent statements until a call to UNLOCK TABLES. The kind of locked tables mode employed for stored functions and triggers is also called "prelocked mode". In this mode, first open_tables() call to open the tables used in a statement analyses all functions used by the statement and adds all indirectly used tables to the list of tables to open and lock. It also marks the parse tree of the statement as requiring prelocking. After that, lock_tables() locks the entire list of tables and changes THD::locked_tables_modeto LTM_PRELOCKED. All statements executed inside functions or triggers use the prelocked tables, instead of opening their own ones. Prelocked mode is turned off automatically once close_thread_tables() of the main statement is called. */ enum enum_locked_tables_mode locked_tables_mode; uint current_tablenr; enum enum_flags { BACKUPS_AVAIL = (1U << 0) /* There are backups available */ }; /* Flags with information about the open tables state. */ uint state_flags; /** This constructor initializes Open_tables_state instance which can only be used as backup storage. To prepare Open_tables_state instance for operations which open/lock/close tables (e.g. open_table()) one has to call init_open_tables_state(). */ Open_tables_state() : state_flags(0U) { } void set_open_tables_state(Open_tables_state *state) { *this= *state; } void reset_open_tables_state() { open_tables= 0; temporary_tables= 0; derived_tables= 0; rec_tables= 0; extra_lock= 0; lock= 0; locked_tables_mode= LTM_NONE; state_flags= 0U; m_reprepare_observer= NULL; } }; /** Storage for backup of Open_tables_state. Must be used only to open system tables (TABLE_CATEGORY_SYSTEM and TABLE_CATEGORY_LOG). */ class Open_tables_backup: public Open_tables_state { public: /** When we backup the open tables state to open a system table or tables, we want to save state of metadata locks which were acquired before the backup. It is used to release metadata locks on system tables after they are no longer used. */ MDL_savepoint mdl_system_tables_svp; }; /** @class Sub_statement_state @brief Used to save context when executing a function or trigger operations on stat tables aren't technically a sub-statement, but they are similar in a sense that they cannot change the transaction status. */ /* Defines used for Sub_statement_state::in_sub_stmt */ #define SUB_STMT_TRIGGER 1 #define SUB_STMT_FUNCTION 2 #define SUB_STMT_STAT_TABLES 4 class Sub_statement_state { public: Discrete_interval auto_inc_interval_for_cur_row; Discrete_intervals_list auto_inc_intervals_forced; SAVEPOINT *savepoints; ulonglong option_bits; ulonglong first_successful_insert_id_in_prev_stmt; ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row; ulonglong limit_found_rows; ulonglong tmp_tables_size; ulonglong client_capabilities; ulonglong cuted_fields, sent_row_count, examined_row_count; ulonglong sent_row_count_for_statement, examined_row_count_for_statement; ulonglong affected_rows; ulonglong bytes_sent_old; ha_handler_stats handler_stats; ulong tmp_tables_used; ulong tmp_tables_disk_used; ulong query_plan_fsort_passes; ulong query_plan_flags; uint in_sub_stmt; /* 0, SUB_STMT_TRIGGER or SUB_STMT_FUNCTION */ bool enable_slow_log; bool last_insert_id_used; bool in_stored_procedure; enum enum_check_fields count_cuted_fields; }; /* Flags for the THD::system_thread variable */ enum enum_thread_type { NON_SYSTEM_THREAD= 0, SYSTEM_THREAD_DELAYED_INSERT= 1, SYSTEM_THREAD_SLAVE_IO= 2, SYSTEM_THREAD_SLAVE_SQL= 4, SYSTEM_THREAD_EVENT_SCHEDULER= 8, SYSTEM_THREAD_EVENT_WORKER= 16, SYSTEM_THREAD_BINLOG_BACKGROUND= 32, SYSTEM_THREAD_SLAVE_BACKGROUND= 64, SYSTEM_THREAD_GENERIC= 128, SYSTEM_THREAD_SEMISYNC_MASTER_BACKGROUND= 256 }; inline char const * show_system_thread(enum_thread_type thread) { #define RETURN_NAME_AS_STRING(NAME) case (NAME): return #NAME switch (thread) { static char buf[64]; RETURN_NAME_AS_STRING(NON_SYSTEM_THREAD); RETURN_NAME_AS_STRING(SYSTEM_THREAD_DELAYED_INSERT); RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_IO); RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_SQL); RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_SCHEDULER); RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_WORKER); RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_BACKGROUND); RETURN_NAME_AS_STRING(SYSTEM_THREAD_SEMISYNC_MASTER_BACKGROUND); default: snprintf(buf, sizeof(buf), "<UNKNOWN SYSTEM THREAD: %d>", thread); return buf; } #undef RETURN_NAME_AS_STRING } /** This class represents the interface for internal error handlers. Internal error handlers are exception handlers used by the server implementation. */ class Internal_error_handler { protected: Internal_error_handler() : m_prev_internal_handler(NULL) {} virtual ~Internal_error_handler() = default; public: /** Handle a sql condition. This method can be implemented by a subclass to achieve any of the following: - mask a warning/error internally, prevent exposing it to the user, - mask a warning/error and throw another one instead. When this method returns true, the sql condition is considered 'handled', and will not be propagated to upper layers. It is the responsability of the code installing an internal handler to then check for trapped conditions, and implement logic to recover from the anticipated conditions trapped during runtime. This mechanism is similar to C++ try/throw/catch: - 'try' correspond to <code>THD::push_internal_handler()</code>, - 'throw' correspond to <code>my_error()</code>, which invokes <code>my_message_sql()</code>, - 'catch' correspond to checking how/if an internal handler was invoked, before removing it from the exception stack with <code>THD::pop_internal_handler()</code>. @param thd the calling thread @param cond the condition raised. @return true if the condition is handled */ virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) = 0; private: Internal_error_handler *m_prev_internal_handler; friend class THD; }; /** Implements the trivial error handler which cancels all error states and prevents an SQLSTATE to be set. Remembers the first error */ class Dummy_error_handler : public Internal_error_handler { uint m_unhandled_errors; uint first_error; public: Dummy_error_handler() : m_unhandled_errors(0), first_error(0) {} bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) override { m_unhandled_errors++; if (!first_error) first_error= sql_errno; return TRUE; // Ignore error } bool any_error() { return m_unhandled_errors != 0; } uint got_error() { return first_error; } }; /** Implements the trivial error handler which counts errors as they happen. */ class Counting_error_handler : public Internal_error_handler { public: int errors; bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) override { if (*level == Sql_condition::WARN_LEVEL_ERROR) errors++; return false; } Counting_error_handler() : errors(0) {} }; extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); /** Error handler that captures and postpones errors. Warnings and notes are passed through to the next handler. Stored errors can be re-emitted later via emit_errors(). */ class Postponed_error_handler : public Internal_error_handler { struct Error_entry { uint sql_errno; char message[MYSQL_ERRMSG_SIZE]; Error_entry *next; }; Error_entry *m_first; Error_entry *m_last; MEM_ROOT *m_mem_root; public: Postponed_error_handler(MEM_ROOT *mem_root) : m_first(nullptr), m_last(nullptr), m_mem_root(mem_root) {} bool handle_condition(THD *thd, uint sql_errno, const char *sqlstate, Sql_condition::enum_warning_level *level, const char *msg, Sql_condition **cond_hdl) override { /* Only capture errors, let warnings and notes pass through */ if (*level != Sql_condition::WARN_LEVEL_ERROR) return false; Error_entry *entry= (Error_entry*) alloc_root(m_mem_root, sizeof(Error_entry)); if (!entry) return false; // Can't store, let error propagate entry->sql_errno= sql_errno; strmake(entry->message, msg, sizeof(entry->message) - 1); entry->next= nullptr; if (m_last) m_last->next= entry; else m_first= entry; m_last= entry; return true; } bool has_errors() const { return m_first != nullptr; } void emit_errors() { for (Error_entry *e= m_first; e; e= e->next) my_message_sql(e->sql_errno, e->message, MYF(0)); } void clear() { m_first= m_last= nullptr; } }; /** This class is an internal error handler implementation for DROP TABLE statements. The thing is that there may be warnings during execution of these statements, which should not be exposed to the user. This class is intended to silence such warnings. */ class Drop_table_error_handler : public Internal_error_handler { public: Drop_table_error_handler() = default; public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) override; private: }; /** Internal error handler to process an error from MDL_context::upgrade_lock() and mysql_lock_tables(). Used by implementations of HANDLER READ and LOCK TABLES LOCAL. */ class MDL_deadlock_and_lock_abort_error_handler: public Internal_error_handler { public: virtual bool handle_condition(THD *thd, uint sql_errno, const char *sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition **cond_hdl) override; bool need_reopen() const { return m_need_reopen; }; void init() { m_need_reopen= FALSE; }; private: bool m_need_reopen; }; class Turn_errors_to_warnings_handler : public Internal_error_handler { public: Turn_errors_to_warnings_handler() = default; bool handle_condition(THD *, uint, const char*, Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) override { *cond_hdl= NULL; if (*level == Sql_condition::WARN_LEVEL_ERROR) *level= Sql_condition::WARN_LEVEL_WARN; return(0); } }; struct Suppress_warnings_error_handler : public Internal_error_handler { bool handle_condition(THD *, uint, const char *, Sql_condition::enum_warning_level *level, const char *, Sql_condition **) override { return *level == Sql_condition::WARN_LEVEL_WARN; } }; /** Tables that were locked with LOCK TABLES statement. Encapsulates a list of TABLE_LIST instances for tables locked by LOCK TABLES statement, memory root for metadata locks, and, generally, the context of LOCK TABLES statement. In LOCK TABLES mode, the locked tables are kept open between statements. Therefore, we can't allocate metadata locks on execution memory root -- as well as tables, the locks need to stay around till UNLOCK TABLES is called. The locks are allocated in the memory root encapsulated in this class. Some SQL commands, like FLUSH TABLE or ALTER TABLE, demand that the tables they operate on are closed, at least temporarily. This class encapsulates a list of TABLE_LIST instances, one for each base table from LOCK TABLES list, which helps conveniently close the TABLEs when it's necessary and later reopen them. Implemented in sql_base.cc */ class Locked_tables_list { public: MEM_ROOT m_locked_tables_root; private: TABLE_LIST *m_locked_tables; TABLE_LIST **m_locked_tables_last; /** An auxiliary array used only in reopen_tables(). */ TABLE_LIST **m_reopen_array; /** Count the number of tables in m_locked_tables list. We can't rely on thd->lock->table_count because it excludes non-transactional temporary tables. We need to know an exact number of TABLE objects. */ uint m_locked_tables_count; public: bool some_table_marked_for_reopen; Locked_tables_list() :m_locked_tables(NULL), m_locked_tables_last(&m_locked_tables), m_reopen_array(NULL), m_locked_tables_count(0), some_table_marked_for_reopen(0) { init_sql_alloc(key_memory_locked_table_list, &m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); } int unlock_locked_tables(THD *thd); int unlock_locked_table(THD *thd, MDL_ticket *mdl_ticket); ~Locked_tables_list() { reset(); } void reset(); bool init_locked_tables(THD *thd); TABLE_LIST *locked_tables() { return m_locked_tables; } void unlink_from_list(THD *thd, TABLE_LIST *table_list, bool remove_from_locked_tables); void unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count); bool reopen_tables(THD *thd, bool need_reopen); bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table, MYSQL_LOCK *lock); void add_back_last_deleted_lock(TABLE_LIST *dst_table_list); void mark_table_for_reopen(TABLE *table); }; /** Storage engine specific thread local data. */ struct Ha_data { /** Storage engine specific thread local data. Lifetime: one user connection. */ void *ha_ptr; /** 0: Life time: one statement within a transaction. If @@autocommit is on, also represents the entire transaction. @sa trans_register_ha() 1: Life time: one transaction within a connection. If the storage engine does not participate in a transaction, this should not be used. @sa trans_register_ha() */ Ha_trx_info ha_info[2]; /** NULL: engine is not bound to this thread non-NULL: engine is bound to this thread, engine shutdown forbidden */ plugin_ref lock; Ha_data() :ha_ptr(NULL) {} void reset() { ha_ptr= nullptr; for (auto &info : ha_info) info.reset(); lock= nullptr; } }; /** An instance of the global read lock in a connection. Implemented in lock.cc. */ class Global_read_lock { public: enum enum_grl_state { GRL_NONE, GRL_ACQUIRED, GRL_ACQUIRED_AND_BLOCKS_COMMIT }; Global_read_lock() : m_state(GRL_NONE), m_mdl_global_read_lock(NULL) {} bool lock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd); bool make_global_read_lock_block_commit(THD *thd); bool is_acquired() const { return m_state != GRL_NONE; } void set_explicit_lock_duration(THD *thd); private: enum_grl_state m_state; /** Global read lock is acquired in two steps: 1. acquire MDL_BACKUP_FTWRL1 in BACKUP namespace to prohibit DDL and DML 2. upgrade to MDL_BACKUP_FTWRL2 to prohibit commits */ MDL_ticket *m_mdl_global_read_lock; }; /* Class to facilitate the commit of one transactions waiting for the commit of another transaction to complete first. This is used during (parallel) replication, to allow different transactions to be applied in parallel, but still commit in order. The transaction that wants to wait for a prior commit must first register to wait with register_wait_for_prior_commit(waitee). Such registration must be done holding the waitee->LOCK_wait_commit, to prevent the other THD from disappearing during the registration. Then during commit, if a THD is registered to wait, it will call wait_for_prior_commit() as part of ha_commit_trans(). If no wait is registered, or if the waitee for has already completed commit, then wait_for_prior_commit() returns immediately. And when a THD that may be waited for has completed commit (more precisely commit_ordered()), then it must call wakeup_subsequent_commits() to wake up any waiters. Note that this must be done at a point that is guaranteed to be later than any waiters registering themselves. It is safe to call wakeup_subsequent_commits() multiple times, as waiters are removed from registration as part of the wakeup. The reason for separate register and wait calls is that this allows to register the wait early, at a point where the waited-for THD is known to exist. And then the actual wait can be done much later, where the waited-for THD may have been long gone. By registering early, the waitee can signal before disappearing. */ struct wait_for_commit { /* The LOCK_wait_commit protects the fields subsequent_commits_list and wakeup_subsequent_commits_running (for a waitee), and the pointer waitee and associated COND_wait_commit (for a waiter). */ mysql_mutex_t LOCK_wait_commit; mysql_cond_t COND_wait_commit; /* List of threads that did register_wait_for_prior_commit() on us. */ wait_for_commit *subsequent_commits_list; /* Link field for entries in subsequent_commits_list. */ wait_for_commit *next_subsequent_commit; /* Our waitee, if we did register_wait_for_prior_commit(), and were not yet woken up. Else NULL. When this is cleared for wakeup, the COND_wait_commit condition is signalled. This pointer is protected by LOCK_wait_commit. But there is also a "fast path" where the waiter compares this to NULL without holding the lock. Such read must be done with acquire semantics (and all corresponding writes done with release semantics). This ensures that a wakeup with error is reliably detected as (waitee==NULL && wakeup_error != 0). */ std::atomic<wait_for_commit *> waitee; /* Generic pointer for use by the transaction coordinator to optimise the waiting for improved group commit. Currently used by binlog TC to signal that a waiter is ready to commit, so that the waitee can grab it and group commit it directly. It is free to be used by another transaction coordinator for similar purposes. */ void *opaque_pointer; /* The wakeup error code from the waitee. 0 means no error. */ int wakeup_error; /* Flag set when wakeup_subsequent_commits_running() is active, see comments on that function for details. */ bool wakeup_subsequent_commits_running; /* This flag can be set when a commit starts, but has not completed yet. It is used by binlog group commit to allow a waiting transaction T2 to join the group commit of an earlier transaction T1. When T1 has queued itself for group commit, it will set the commit_started flag. Then when T2 becomes ready to commit and needs to wait for T1 to commit first, T2 can queue itself before waiting, and thereby participate in the same group commit as T1. */ bool commit_started; /* Set to temporarily ignore calls to wakeup_subsequent_commits(). The caller must arrange that another wakeup_subsequent_commits() gets called later after wakeup_blocked has been set back to false. This is used for parallel replication with temporary tables. Temporary tables require strict single-threaded operation. The normal optimization, of doing wakeup_subsequent_commits early and overlapping part of the commit with the following transaction, is not safe. Thus when temporary tables are replicated, wakeup is blocked until the event group is fully done. */ bool wakeup_blocked; void register_wait_for_prior_commit(wait_for_commit *waitee); int wait_for_prior_commit(THD *thd, bool allow_kill=true) { /* Quick inline check, to avoid function call and locking in the common case where no wakeup is registered, or a registered wait was already signalled. */ if (waitee.load(std::memory_order_acquire)) return wait_for_prior_commit2(thd, allow_kill); else { if (unlikely(wakeup_error)) prior_commit_error(thd); return wakeup_error; } } void wakeup_subsequent_commits(int wakeup_error_arg) { /* Do the check inline, so only the wakeup case takes the cost of a function call for every commmit. Note that the check is done without locking. It is the responsibility of the user of the wakeup facility to ensure that no waiters can register themselves after the last call to wakeup_subsequent_commits(). This avoids having to take another lock for every commit, which would be pointless anyway - even if we check under lock, there is nothing to prevent a waiter from arriving just after releasing the lock. */ if (subsequent_commits_list) wakeup_subsequent_commits2(wakeup_error_arg); } void unregister_wait_for_prior_commit() { if (waitee.load(std::memory_order_relaxed)) unregister_wait_for_prior_commit2(); else wakeup_error= 0; } /* Remove a waiter from the list in the waitee. Used to unregister a wait. The caller must be holding the locks of both waiter and waitee. */ void remove_from_list(wait_for_commit **next_ptr_ptr) { wait_for_commit *cur; while ((cur= *next_ptr_ptr) != NULL) { if (cur == this) { *next_ptr_ptr= this->next_subsequent_commit; break; } next_ptr_ptr= &cur->next_subsequent_commit; } waitee.store(NULL, std::memory_order_relaxed); } void wakeup(int wakeup_error); int wait_for_prior_commit2(THD *thd, bool allow_kill); void prior_commit_error(THD *thd); void wakeup_subsequent_commits2(int wakeup_error); void unregister_wait_for_prior_commit2(); wait_for_commit(); ~wait_for_commit(); void reinit(); }; class Sp_caches { protected: ulong m_sp_cache_version; public: sp_cache *sp_proc_cache; sp_cache *sp_func_cache; sp_cache *sp_package_spec_cache; sp_cache *sp_package_body_cache; Sp_caches() :m_sp_cache_version(0), sp_proc_cache(NULL), sp_func_cache(NULL), sp_package_spec_cache(NULL), sp_package_body_cache(NULL) { } ~Sp_caches() { // All caches must be freed by the caller explicitly DBUG_ASSERT(sp_proc_cache == NULL); DBUG_ASSERT(sp_func_cache == NULL); DBUG_ASSERT(sp_package_spec_cache == NULL); DBUG_ASSERT(sp_package_body_cache == NULL); } void sp_caches_clear(); /** Clear content of sp related caches. Don't delete cache objects itself. */ void sp_caches_empty(); ulong sp_cache_version() const { DBUG_ASSERT(m_sp_cache_version); return m_sp_cache_version; } void set_sp_cache_version_if_needed(ulong version) { if (!m_sp_cache_version) m_sp_cache_version= version; } }; extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); class Gap_time_tracker; /* Thread context for Gap_time_tracker class. */ class Gap_time_tracker_data { public: Gap_time_tracker_data(): bill_to(NULL) {} Gap_time_tracker *bill_to; ulonglong start_time; void init() { bill_to = NULL; } }; /** Support structure for asynchronous group commit, or more generally any asynchronous operation that needs to finish before server writes response to client. An engine, or any other server component, can signal that there is a pending operation by incrementing a counter, i.e inc_pending_ops() and that pending operation is finished by decrementing that counter dec_pending_ops(). NOTE: Currently, pending operations can not fail, i.e there is no way to pass a return code in dec_pending_ops() The server does not write response to the client before the counter becomes 0. In case of group commit it ensures that data is persistent before success reported to client, i.e durability in ACID. */ struct thd_async_state { enum class enum_async_state { NONE, SUSPENDED, /* do_command() did not finish, and needs to be resumed */ RESUMED /* do_command() is resumed*/ }; enum_async_state m_state{enum_async_state::NONE}; /* Stuff we need to resume do_command where we finished last time*/ enum enum_server_command m_command{COM_SLEEP}; LEX_STRING m_packet{0,0}; mysql_mutex_t m_mtx; mysql_cond_t m_cond; /** Pending counter*/ Atomic_counter<int> m_pending_ops=0; #ifndef DBUG_OFF /* Checks */ pthread_t m_dbg_thread; #endif thd_async_state() { mysql_mutex_init(PSI_NOT_INSTRUMENTED, &m_mtx, 0); mysql_cond_init(PSI_INSTRUMENT_ME, &m_cond, 0); } /* Currently only used with threadpool, one can "suspend" and "resume" a THD. Suspend only means leaving do_command earlier, after saving some state. Resume is continuing suspended THD's do_command(), from where it finished last time. */ bool try_suspend() { bool ret; mysql_mutex_lock(&m_mtx); DBUG_ASSERT(m_state == enum_async_state::NONE); DBUG_ASSERT(m_pending_ops >= 0); if(m_pending_ops) { ret=true; m_state= enum_async_state::SUSPENDED; } else { /* If there is no pending operations, can't suspend, since nobody can resume it. */ ret=false; } mysql_mutex_unlock(&m_mtx); return ret; } ~thd_async_state() { wait_for_pending_ops(); mysql_mutex_destroy(&m_mtx); mysql_cond_destroy(&m_cond); } /* Increment pending asynchronous operations. The client response may not be written if this count > 0. So, without threadpool query needs to wait for the operations to finish. With threadpool, THD can be suspended and resumed when this counter goes to 0. */ void inc_pending_ops() { mysql_mutex_lock(&m_mtx); #ifndef DBUG_OFF /* Check that increments are always done by the same thread. */ if (!m_pending_ops) m_dbg_thread= pthread_self(); else DBUG_ASSERT(pthread_equal(pthread_self(),m_dbg_thread)); #endif m_pending_ops++; mysql_mutex_unlock(&m_mtx); } int dec_pending_ops(enum_async_state* state) { int ret; mysql_mutex_lock(&m_mtx); ret= --m_pending_ops; if (!ret) mysql_cond_signal(&m_cond); *state = m_state; mysql_mutex_unlock(&m_mtx); return ret; } /* This is used for "dirty" reading pending ops, when dirty read is OK. */ int pending_ops() { return m_pending_ops; } /* Wait for pending operations to finish.*/ void wait_for_pending_ops() { /* It is fine to read m_pending_ops and compare it with 0, without mutex protection. The value is only incremented by the current thread, and will be decremented by another one, thus "dirty" may show positive number when it is really 0, but this is not a problem, and the only bad thing from that will be rechecking under mutex. */ if (!pending_ops()) return; mysql_mutex_lock(&m_mtx); DBUG_ASSERT(m_pending_ops >= 0); while (m_pending_ops) mysql_cond_wait(&m_cond, &m_mtx); mysql_mutex_unlock(&m_mtx); } }; enum class THD_WHERE { NOWHERE = 0, CHECKING_TRANSFORMED_SUBQUERY, IN_ALL_ANY_SUBQUERY, JSON_TABLE_ARGUMENT, FIELD_LIST, PARTITION_FUNCTION, FROM_CLAUSE, DEFAULT_WHERE, ON_CLAUSE, WHERE_CLAUSE, SET_LIST, INSERT_LIST, VALUES_CLAUSE, UPDATE_CLAUSE, RETURNING, FOR_SYSTEM_TIME, ORDER_CLAUSE, HAVING_CLAUSE, GROUP_STATEMENT, PROCEDURE_LIST, CHECK_OPTION, DO_STATEMENT, HANDLER_STATEMENT, USE_WHERE_STRING, // ugh, a compromise for vcol... }; class THD; const char *thd_where(THD *thd); /** @class THD For each client connection we create a separate thread with THD serving as a thread/connection descriptor */ class THD: public THD_count, /* this must be first */ public Sql_used, public Statement, /* This is to track items changed during execution of a prepared statement/stored procedure. It's created by nocheck_register_item_tree_change() in memory root of THD, and freed in rollback_item_tree_changes(). For conventional execution it's always empty. */ public Item_change_list, public MDL_context_owner, public Open_tables_state, public Sp_caches { private: inline bool is_stmt_prepare() const { DBUG_ASSERT(0); return Statement::is_stmt_prepare(); } inline bool is_stmt_prepare_or_first_sp_execute() const { DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_sp_execute(); } inline bool is_stmt_prepare_or_first_stmt_execute() const { DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_stmt_execute(); } inline bool is_conventional() const { DBUG_ASSERT(0); return Statement::is_conventional(); } public: MDL_context mdl_context; /* Used to execute base64 coded binlog events in MySQL server */ Relay_log_info* rli_fake; rpl_group_info* rgi_fake; /* Slave applier execution context */ rpl_group_info* rgi_slave; union { rpl_io_thread_info *rpl_io_info; rpl_sql_thread_info *rpl_sql_info; } system_thread_info; /* Used for BACKUP LOCK */ MDL_ticket *mdl_backup_ticket, *mdl_backup_lock; /* Used to register that thread has a MDL_BACKUP_WAIT_COMMIT lock */ MDL_request *backup_commit_lock; void reset_for_next_command(bool do_clear_errors= 1); #ifdef EMBEDDED_LIBRARY struct st_mysql *mysql; unsigned long client_stmt_id; unsigned long client_param_count; struct st_mysql_bind *client_params; char *extra_data; ulong extra_length; struct st_mysql_data *cur_data; struct st_mysql_data *first_data; struct st_mysql_data **data_tail; void clear_data_list(); struct st_mysql_data *alloc_new_dataset(); /* In embedded server it points to the statement that is processed in the current query. We store some results directly in statement fields then. */ struct st_mysql_stmt *current_stmt; #endif #ifdef HAVE_QUERY_CACHE Query_cache_tls query_cache_tls; #endif NET net; // client connection descriptor /** Aditional network instrumentation for the server only. */ NET_SERVER m_net_server_extension; scheduler_functions *scheduler; // Scheduler for this connection Protocol *protocol; // Current protocol Protocol_text protocol_text; // Normal protocol Protocol_binary protocol_binary; // Binary protocol HASH user_vars; // hash for user variables String packet; // dynamic buffer for network I/O String convert_buffer; // buffer for charset conversions struct my_rnd_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars struct system_status_var org_status_var; // For user statistics struct system_status_var *initial_status_var; /* used by show status */ ha_handler_stats handler_stats; // Handler statistics THR_LOCK_INFO lock_info; // Locking info of this thread /** Protects THD data accessed from other threads: - thd->query and thd->query_length (used by SHOW ENGINE INNODB STATUS and SHOW PROCESSLIST - thd->db (used in SHOW PROCESSLIST) Is locked when THD is deleted. */ mutable mysql_mutex_t LOCK_thd_data; /* Protects: - kill information - mysys_var (used by KILL statement and shutdown). - Also ensures that THD is not deleted while mutex is hold */ mutable mysql_mutex_t LOCK_thd_kill; /* all prepared statements and cursors of this connection */ Statement_map stmt_map; /* Last created prepared statement */ Statement *last_stmt; Statement *cur_stmt= 0; inline void set_last_stmt(Statement *stmt) { last_stmt= (is_error() ? NULL : stmt); } inline void clear_last_stmt() { last_stmt= NULL; } /* A pointer to the stack frame of handle_one_connection(), which is called first in the thread for handling a client */ void *thread_stack; /** Currently selected catalog. */ char *catalog; /** @note Some members of THD (currently 'Statement::db', 'catalog' and 'query') are set and alloced by the slave SQL thread (for the THD of that thread); that thread is (and must remain, for now) the only responsible for freeing these 3 members. If you add members here, and you add code to set them in replication, don't forget to free_them_and_set_them_to_0 in replication properly. For details see the 'err:' label of the handle_slave_sql() in sql/slave.cc. @see handle_slave_sql */ Security_context main_security_ctx; Security_context *security_ctx; Security_context *security_context() const { return security_ctx; } void set_security_context(Security_context *sctx) { security_ctx = sctx; } /* Points to info-string that we show in SHOW PROCESSLIST You are supposed to update thd->proc_info only if you have coded a time-consuming piece that MySQL can get stuck in for a long time. Set it using the thd_proc_info(THD *thread, const char *message) macro/function. This member is accessed and assigned without any synchronization. Therefore, it may point only to constant (statically allocated) strings, which memory won't go away over time. */ const char *proc_info; void set_psi(PSI_thread *psi) { my_atomic_storeptr((void*volatile*)&m_psi, psi); } PSI_thread* get_psi() { return static_cast<PSI_thread*>(my_atomic_loadptr((void*volatile*)&m_psi)); } private: unsigned int m_current_stage_key; /** Performance schema thread instrumentation for this session. */ PSI_thread *m_psi; public: void enter_stage(const PSI_stage_info *stage, const char *calling_func, const char *calling_file, const unsigned int calling_line) { DBUG_PRINT("THD::enter_stage", ("%s at %s:%d", stage->m_name, calling_file, calling_line)); DBUG_ASSERT(stage); m_current_stage_key= stage->m_key; proc_info= stage->m_name; #if defined(ENABLED_PROFILING) profiling.status_change(proc_info, calling_func, calling_file, calling_line); #endif #ifdef HAVE_PSI_THREAD_INTERFACE m_stage_progress_psi= MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line); #endif } void backup_stage(PSI_stage_info *stage) { stage->m_key= m_current_stage_key; stage->m_name= proc_info; } const char *get_proc_info() const { return proc_info; } // Used by thd_where() when where==USE_WHERE_STRING const char *where_str; /* Used in error messages to tell user in what part of MySQL we found an error. E. g. when where= "having clause", if fix_fields() fails, user will know that the error was in having clause. */ THD_WHERE where; /* Needed by MariaDB semi sync replication */ Trans_binlog_info *semisync_info; #ifndef DBUG_OFF /* If Active_tranx is missing an entry for a transaction which is planning to await an ACK, this ensures that the reason is because semi-sync was turned off then on in-between the binlogging of the transaction, and before it had started waiting for the ACK. */ ulong expected_semi_sync_offs; #endif /* If this is a semisync slave connection. */ bool semi_sync_slave; ulonglong client_capabilities; /* What the client supports */ ulong max_client_packet_length; HASH handler_tables_hash; /* A thread can hold named user-level locks. This variable contains granted tickets if a lock is present. See item_func.cc and chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK. */ HASH ull_hash; /* Hash of used seqeunces (for PREVIOUS value) */ HASH sequences; #ifdef DBUG_ASSERT_EXISTS uint dbug_sentry; // watch out for memory corruption #endif struct st_my_thread_var *mysys_var; /* Original charset number from the first client packet, or COM_CHANGE_USER*/ CHARSET_INFO *org_charset; private: /* Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from first byte of the packet in do_command() */ enum enum_server_command m_command; public: uint32 file_id; // for LOAD DATA INFILE /* remote (peer) port */ uint16 peer_port; my_time_t start_time; // start_time and its sec_part ulong start_time_sec_part; // are almost always used separately my_hrtime_t user_time; // track down slow pthread_create ulonglong prior_thr_create_utime, thr_create_utime; ulonglong start_utime, utime_after_lock, utime_after_query; /* This can be used by handlers to send signals to the SQL level */ ulonglong replication_flags; // Process indicator struct { /* true, if the currently running command can send progress report packets to a client. Set by mysql_execute_command() for safe commands See CF_REPORT_PROGRESS */ bool report_to_client; /* true, if we will send progress report packets to a client (client has requested them, see MARIADB_CLIENT_PROGRESS; report_to_client is true; not in sub-statement) */ bool report; uint stage, max_stage; ulonglong counter, max_counter; ulonglong next_report_time; Query_arena *arena; } progress; thr_lock_type update_lock_default; Delayed_insert *di; /* <> 0 if we are inside of trigger or stored function. */ uint in_sub_stmt; /* True when opt_userstat_running is set at start of query */ bool userstat_running; /* True if we have to log all errors. Are set by some engines to temporary force errors to the error log. */ bool log_all_errors; /* Do not set socket timeouts for wait_timeout (used with threadpool) */ bool skip_wait_timeout; bool prepare_derived_at_open; /* Set to 1 if status of this THD is already in global status */ bool status_in_global; /* To signal that the tmp table to be created is created for materialized derived table or a view. */ bool create_tmp_table_for_derived; bool save_prep_leaf_list; /** The data member reset_sp_cache is to signal that content of sp_cache must be reset (all items be removed from it). */ bool reset_sp_cache; /* container for handler's private per-connection data */ Ha_data ha_data[MAX_HA]; /** Bit field for the state of binlog warnings. The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of unsafeness that the current statement has. This must be a member of THD and not of LEX, because warnings are detected and issued in different places (@c decide_logging_format() and @c binlog_query(), respectively). Between these calls, the THD->lex object may change; e.g., if a stored routine is invoked. Only THD persists between the calls. */ uint32 binlog_unsafe_warning_flags; #ifndef MYSQL_CLIENT binlog_cache_mngr * binlog_setup_trx_data(); /* If set, tell binlog to store the value as query 'xid' in the next Query_log_event */ ulonglong binlog_xid; /* Public interface to write RBR events to the binlog */ void binlog_start_trans_and_stmt(); void binlog_set_stmt_begin(); int binlog_write_row(TABLE* table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, const uchar *buf); int binlog_delete_row(TABLE* table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, enum_binlog_row_image row_image, const uchar *buf); int binlog_update_row(TABLE* table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, enum_binlog_row_image row_image, const uchar *old_data, const uchar *new_data); bool prepare_handlers_for_update(uint flag); bool binlog_write_annotated_row(bool use_trans_cache); void binlog_prepare_for_row_logging(); bool binlog_write_table_maps(); void set_server_id(uint32 sid) { variables.server_id = sid; } /* Member functions to handle pending event for row-level logging. */ binlog_cache_mngr *binlog_get_cache_mngr() const; inline int binlog_flush_pending_rows_event(bool stmt_end) { return (binlog_flush_pending_rows_event(stmt_end, FALSE) || binlog_flush_pending_rows_event(stmt_end, TRUE)); } int binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional); bool binlog_need_stmt_format(bool is_transactional) const { if (!log_current_statement()) return false; auto *cache_mngr= binlog_get_cache_mngr(); if (!cache_mngr) return true; return !binlog_get_pending_rows_event(cache_mngr, use_trans_cache(this, is_transactional)); } bool binlog_for_noop_dml(bool transactional_table); /** Determine the binlog format of the current statement. @retval 0 if the current statement will be logged in statement format. @retval nonzero if the current statement will be logged in row format. */ int is_current_stmt_binlog_format_row() const { DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || current_stmt_binlog_format == BINLOG_FORMAT_ROW); return current_stmt_binlog_format == BINLOG_FORMAT_ROW; } /** Determine if binlogging is disabled for this session @retval 0 if the current statement binlogging is disabled (could be because of binlog closed/binlog option is set to false). @retval 1 if the current statement will be binlogged */ inline bool is_current_stmt_binlog_disabled() const { return (!(variables.option_bits & OPTION_BIN_LOG) || !mysql_bin_log.is_open()); } enum binlog_filter_state { BINLOG_FILTER_UNKNOWN, BINLOG_FILTER_CLEAR, BINLOG_FILTER_SET }; inline void reset_binlog_local_stmt_filter() { m_binlog_filter_state= BINLOG_FILTER_UNKNOWN; } inline void clear_binlog_local_stmt_filter() { DBUG_ASSERT(m_binlog_filter_state == BINLOG_FILTER_UNKNOWN); m_binlog_filter_state= BINLOG_FILTER_CLEAR; } inline void set_binlog_local_stmt_filter() { DBUG_ASSERT(m_binlog_filter_state == BINLOG_FILTER_UNKNOWN); m_binlog_filter_state= BINLOG_FILTER_SET; } inline binlog_filter_state get_binlog_local_stmt_filter() { return m_binlog_filter_state; } /** Checks if a user connection is read-only */ inline bool is_read_only_ctx() { return opt_readonly && !(security_ctx->master_access & PRIV_IGNORE_READ_ONLY) && !slave_thread; } private: /** Indicate if the current statement should be discarded instead of written to the binlog. This is used to discard special statements, such as DML or DDL that affects only 'local' (non replicated) tables, such as performance_schema.* */ binlog_filter_state m_binlog_filter_state; /** Indicates the format in which the current statement will be logged. This can only be set from @c decide_logging_format(). */ enum_binlog_format current_stmt_binlog_format; public: /* 1 if binlog table maps has been written */ bool binlog_table_maps; void issue_unsafe_warnings(); void reset_unsafe_warnings() { binlog_unsafe_warning_flags= 0; } void reset_binlog_for_next_statement() { binlog_table_maps= 0; } bool binlog_table_should_be_logged(const LEX_CSTRING *db); // Accessors and setters of two-phase loggable ALTER binlog properties uchar get_binlog_flags_for_alter(); void set_binlog_flags_for_alter(uchar); uint64 get_binlog_start_alter_seq_no(); void set_binlog_start_alter_seq_no(uint64); #endif /* MYSQL_CLIENT */ public: struct st_transactions { SAVEPOINT *savepoints; THD_TRANS all; // Trans since BEGIN WORK THD_TRANS stmt; // Trans for current statement bool on; // see ha_enable_transaction() XID_STATE xid_state; XID implicit_xid; WT_THD wt; ///< for deadlock detection Rows_log_event *m_pending_rows_event; struct st_trans_time : public timeval { void reset(THD *thd) { tv_sec= thd->query_start(); tv_usec= (long) thd->query_start_sec_part(); } } start_time; /* Tables changed in transaction (that must be invalidated in query cache). List contain only transactional tables, that not invalidated in query cache (instead of full list of changed in transaction tables). */ CHANGED_TABLE_LIST* changed_tables; MEM_ROOT mem_root; // Transaction-life memory allocation pool void cleanup() { DBUG_ENTER("THD::st_transactions::cleanup"); changed_tables= 0; savepoints= 0; implicit_xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_VOID_RETURN; } void free() { free_root(&mem_root,MYF(0)); } bool is_active() { return (all.ha_list != NULL); } bool is_empty() { return all.is_empty() && stmt.is_empty(); } st_transactions() { bzero((char*)this, sizeof(*this)); implicit_xid.null(); init_sql_alloc(key_memory_thd_transactions, &mem_root, DEFAULT_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); } } default_transaction, *transaction; Global_read_lock global_read_lock; Field *dup_field; #ifndef _WIN32 sigset_t signals; #endif #ifdef SIGNAL_WITH_VIO_CLOSE Vio* active_vio; #endif /* A permanent memory area of the statement. For conventional execution, the parsed tree and execution runtime reside in the same memory root. In this case stmt_arena points to THD. In case of a prepared statement or a stored procedure statement, thd->mem_root conventionally points to runtime memory, and thd->stmt_arena points to the memory of the PS/SP, where the parsed tree of the statement resides. Whenever you need to perform a permanent transformation of a parsed tree, you should allocate new memory in stmt_arena, to allow correct re-execution of PS/SP. Note: in the parser, stmt_arena == thd, even for PS/SP. */ Query_arena *stmt_arena; /** Get either call or statement arena. In case some function is called from within a query the call arena has to be used for a memory allocation, else use the statement arena. */ Query_arena *active_stmt_arena_to_use() { return (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) ? this : stmt_arena; } void *bulk_param; /* map for tables that will be updated for a multi-table update query statement, for other query statements, this will be zero. */ table_map table_map_for_update; /* Tells if LAST_INSERT_ID(#) was called for the current statement */ bool arg_of_last_insert_id_function; /* ALL OVER THIS FILE, "insert_id" means "*automatically generated* value for insertion into an auto_increment column". */ /* This is the first autogenerated insert id which was *successfully* inserted by the previous statement (exactly, if the previous statement didn't successfully insert an autogenerated insert id, then it's the one of the statement before, etc). It can also be set by SET LAST_INSERT_ID=# or SELECT LAST_INSERT_ID(#). It is returned by LAST_INSERT_ID(). */ ulonglong first_successful_insert_id_in_prev_stmt; /* Variant of the above, used for storing in statement-based binlog. The difference is that the one above can change as the execution of a stored function progresses, while the one below is set once and then does not change (which is the value which statement-based binlog needs). */ ulonglong first_successful_insert_id_in_prev_stmt_for_binlog; /* This is the first autogenerated insert id which was *successfully* inserted by the current statement. It is maintained only to set first_successful_insert_id_in_prev_stmt when statement ends. */ ulonglong first_successful_insert_id_in_cur_stmt; /* We follow this logic: - when stmt starts, first_successful_insert_id_in_prev_stmt contains the first insert id successfully inserted by the previous stmt. - as stmt makes progress, handler::insert_id_for_cur_row changes; every time get_auto_increment() is called, auto_inc_intervals_in_cur_stmt_for_binlog is augmented with the reserved interval (if statement-based binlogging). - at first successful insertion of an autogenerated value, first_successful_insert_id_in_cur_stmt is set to handler::insert_id_for_cur_row. - when stmt goes to binlog, auto_inc_intervals_in_cur_stmt_for_binlog is binlogged if non-empty. - when stmt ends, first_successful_insert_id_in_prev_stmt is set to first_successful_insert_id_in_cur_stmt. */ /* stmt_depends_on_first_successful_insert_id_in_prev_stmt is set when LAST_INSERT_ID() is used by a statement. If it is set, first_successful_insert_id_in_prev_stmt_for_binlog will be stored in the statement-based binlog. This variable is CUMULATIVE along the execution of a stored function or trigger: if one substatement sets it to 1 it will stay 1 until the function/trigger ends, thus making sure that first_successful_insert_id_in_prev_stmt_for_binlog does not change anymore and is propagated to the caller for binlogging. */ bool stmt_depends_on_first_successful_insert_id_in_prev_stmt; /* List of auto_increment intervals reserved by the thread so far, for storage in the statement-based binlog. Note that its minimum is not first_successful_insert_id_in_cur_stmt: assuming a table with an autoinc column, and this happens: INSERT INTO ... VALUES(3); SET INSERT_ID=3; INSERT IGNORE ... VALUES (NULL); then the latter INSERT will insert no rows (first_successful_insert_id_in_cur_stmt == 0), but storing "INSERT_ID=3" in the binlog is still needed; the list's minimum will contain 3. This variable is cumulative: if several statements are written to binlog as one (stored functions or triggers are used) this list is the concatenation of all intervals reserved by all statements. */ Discrete_intervals_list auto_inc_intervals_in_cur_stmt_for_binlog; /* Used by replication and SET INSERT_ID */ Discrete_intervals_list auto_inc_intervals_forced; /* There is BUG#19630 where statement-based replication of stored functions/triggers with two auto_increment columns breaks. We however ensure that it works when there is 0 or 1 auto_increment column; our rules are a) on master, while executing a top statement involving substatements, first top- or sub- statement to generate auto_increment values wins the exclusive right to see its values be written to binlog (the write will be done by the statement or its caller), and the losers won't see their values be written to binlog. b) on slave, while replicating a top statement involving substatements, first top- or sub- statement to need to read auto_increment values from the master's binlog wins the exclusive right to read them (so the losers won't read their values from binlog but instead generate on their own). a) implies that we mustn't backup/restore auto_inc_intervals_in_cur_stmt_for_binlog. b) implies that we mustn't backup/restore auto_inc_intervals_forced. If there are more than 1 auto_increment columns, then intervals for different columns may mix into the auto_inc_intervals_in_cur_stmt_for_binlog list, which is logically wrong, but there is no point in preventing this mixing by preventing intervals from the secondly inserted column to come into the list, as such prevention would be wrong too. What will happen in the case of INSERT INTO t1 (auto_inc) VALUES(NULL); where t1 has a trigger which inserts into an auto_inc column of t2, is that in binlog we'll store the interval of t1 and the interval of t2 (when we store intervals, soon), then in slave, t1 will use both intervals, t2 will use none; if t1 inserts the same number of rows as on master, normally the 2nd interval will not be used by t1, which is fine. t2's values will be wrong if t2's internal auto_increment counter is different from what it was on master (which is likely). In 5.1, in mixed binlogging mode, row-based binlogging is used for such cases where two auto_increment columns are inserted. */ inline void record_first_successful_insert_id_in_cur_stmt(ulonglong id_arg) { if (first_successful_insert_id_in_cur_stmt == 0) first_successful_insert_id_in_cur_stmt= id_arg; } inline ulonglong read_first_successful_insert_id_in_prev_stmt(void) { if (!stmt_depends_on_first_successful_insert_id_in_prev_stmt) { /* It's the first time we read it */ first_successful_insert_id_in_prev_stmt_for_binlog= first_successful_insert_id_in_prev_stmt; stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1; } return first_successful_insert_id_in_prev_stmt; } /* Used by Intvar_log_event::do_apply_event() and by "SET INSERT_ID=#" (mysqlbinlog). We'll soon add a variant which can take many intervals in argument. */ inline void force_one_auto_inc_interval(ulonglong next_id) { auto_inc_intervals_forced.empty(); // in case of multiple SET INSERT_ID auto_inc_intervals_forced.append(next_id, ULONGLONG_MAX, 0); } inline void set_binlog_bit() { if (variables.sql_log_bin) variables.option_bits |= OPTION_BIN_LOG; else variables.option_bits &= ~OPTION_BIN_LOG; } ulonglong limit_found_rows; private: /** Stores the result of ROW_COUNT() function. ROW_COUNT() function is a MySQL extention, but we try to keep it similar to ROW_COUNT member of the GET DIAGNOSTICS stack of the SQL standard (see SQL99, part 2, search for ROW_COUNT). It's value is implementation defined for anything except INSERT, DELETE, UPDATE. ROW_COUNT is assigned according to the following rules: - In my_ok(): - for DML statements: to the number of affected rows; - for DDL statements: to 0. - In my_eof(): to -1 to indicate that there was a result set. We derive this semantics from the JDBC specification, where int java.sql.Statement.getUpdateCount() is defined to (sic) "return the current result as an update count; if the result is a ResultSet object or there are no more results, -1 is returned". - In my_error(): to -1 to be compatible with the MySQL C API and MySQL ODBC driver. - For SIGNAL statements: to 0 per WL#2110 specification (see also sql_signal.cc comment). Zero is used since that's the "default" value of ROW_COUNT in the diagnostics area. */ longlong m_row_count_func; /* For the ROW_COUNT() function */ public: inline longlong get_row_count_func() const { return m_row_count_func; } inline void set_row_count_func(longlong row_count_func) { m_row_count_func= row_count_func; } inline void set_affected_rows(longlong row_count_func) { /* We have to add to affected_rows (used by slow log), as otherwise information for 'call' will be wrong */ affected_rows+= (row_count_func >= 0 ? row_count_func : 0); } ha_rows cuted_fields; /* number of rows we actually sent to the client, including "synthetic" rows in ROLLUP etc. */ ha_rows m_sent_row_count; /* Number of rows for the total statement */ ha_rows sent_row_count_for_statement; /** Number of rows read and/or evaluated for a statement. Used for slow log reporting. An examined row is defined as a row that is read and/or evaluated according to a statement condition, including in create_sort_index(). Rows may be counted more than once, e.g., a statement including ORDER BY could possibly evaluate the row in filesort() before reading it for e.g. update. */ ha_rows m_examined_row_count; /* Number of rows for the top level query */ ha_rows examined_row_count_for_statement; ha_rows get_sent_row_count() const { return m_sent_row_count; } ha_rows get_examined_row_count() const { DBUG_EXECUTE_IF("debug_huge_number_of_examined_rows", return (ULONGLONG_MAX - 1000000);); return m_examined_row_count; } ulonglong get_affected_rows() const { return affected_rows; } void set_sent_row_count(ha_rows count); inline void inc_sent_row_count(ha_rows count) { m_sent_row_count+= count; sent_row_count_for_statement+= count; MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); } inline void inc_examined_row_count_fast(ha_rows count= 1) { m_examined_row_count+= count; examined_row_count_for_statement+= count; } inline void inc_examined_row_count(ha_rows count= 1) { inc_examined_row_count_fast(); MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count); } void ps_report_examined_row_count(); void inc_status_created_tmp_disk_tables(); void inc_status_created_tmp_files(); void inc_status_created_tmp_tables(); void inc_status_select_full_join(); void inc_status_select_full_range_join(); void inc_status_select_range(); void inc_status_select_range_check(); void inc_status_select_scan(); void inc_status_sort_merge_passes(); void inc_status_sort_range(); void inc_status_sort_rows(ha_rows count); void inc_status_sort_scan(); void set_status_no_index_used(); void set_status_no_good_index_used(); /** The number of rows and/or keys examined by the query, both read, changed or written. */ ulonglong accessed_rows_and_keys; /** Check if the number of rows accessed by a statement exceeded LIMIT ROWS EXAMINED. If so, signal the query engine to stop execution. */ inline void check_limit_rows_examined() { if (++accessed_rows_and_keys > lex->limit_rows_examined_cnt) set_killed(ABORT_QUERY); } USER_CONN *user_connect; CHARSET_INFO *db_charset; #if defined(ENABLED_PROFILING) PROFILING profiling; #endif /** Current stage progress instrumentation. */ PSI_stage_progress *m_stage_progress_psi; /** Current statement digest. */ sql_digest_state *m_digest; /** Current statement digest token array. */ unsigned char *m_token_array; /** Top level statement digest. */ sql_digest_state m_digest_state; /** Current statement instrumentation. */ PSI_statement_locker *m_statement_psi; #ifdef HAVE_PSI_STATEMENT_INTERFACE /** Current statement instrumentation state. */ PSI_statement_locker_state m_statement_state; #endif /* HAVE_PSI_STATEMENT_INTERFACE */ /** Current transaction instrumentation. */ PSI_transaction_locker *m_transaction_psi; #ifdef HAVE_PSI_TRANSACTION_INTERFACE /** Current transaction instrumentation state. */ PSI_transaction_locker_state m_transaction_state; #endif /* HAVE_PSI_TRANSACTION_INTERFACE */ /** Idle instrumentation. */ PSI_idle_locker *m_idle_psi; #ifdef HAVE_PSI_IDLE_INTERFACE /** Idle instrumentation state. */ PSI_idle_locker_state m_idle_state; #endif /* HAVE_PSI_IDLE_INTERFACE */ /* Id of current query. Statement can be reused to execute several queries query_id is global in context of the whole MySQL server. ID is automatically generated from mutex-protected counter. It's used in handler code for various purposes: to check which columns from table are necessary for this select, to check if it's necessary to update auto-updatable fields (like auto_increment and timestamp). */ query_id_t query_id; privilege_t col_access; /* Statement id is thread-wide. This counter is used to generate ids */ ulong statement_id_counter; ulong rand_saved_seed1, rand_saved_seed2; /* The following variables are used when printing to slow log */ ulong query_plan_flags; ulong query_plan_fsort_passes; ulong tmp_tables_used; ulong tmp_tables_disk_used; ulonglong tmp_tables_size; ulonglong bytes_sent_old; ulonglong affected_rows; /* Number of changed rows */ Opt_trace_context opt_trace; pthread_t real_id; /* For debugging */ my_thread_id thread_id, thread_dbug_id; uint32 os_thread_id; uint tmp_table, global_disable_checkpoint; uint server_status,open_options; enum enum_thread_type system_thread; enum backup_stages current_backup_stage; #ifdef WITH_WSREP bool wsrep_desynced_backup_stage; #endif /* WITH_WSREP */ /* Current or next transaction isolation level. When a connection is established, the value is taken from @@session.transaction_isolation (default transaction isolation for the session), which is in turn taken from @@global.transaction_isolation (the global value). If there is no transaction started, this variable holds the value of the next transaction's isolation level. When a transaction starts, the value stored in this variable becomes "actual". At transaction commit or rollback, we assign this variable again from @@session.transaction_isolation. The only statement that can otherwise change the value of this variable is SET TRANSACTION ISOLATION LEVEL. Its purpose is to effect the isolation level of the next transaction in this session. When this statement is executed, the value in this variable is changed. However, since this statement is only allowed when there is no active transaction, this assignment (naturally) only affects the upcoming transaction. At the end of the current active transaction the value is be reset again from @@session.transaction_isolation, as described above. */ enum_tx_isolation tx_isolation; /* Current or next transaction access mode. See comment above regarding transaction_isolation. */ bool tx_read_only; enum_check_fields count_cuted_fields; DYNAMIC_ARRAY user_var_events; /* For user variables replication */ MEM_ROOT *user_var_events_alloc; /* Allocate above array elements here */ /* Define durability properties that engines may check to improve performance. Not yet used in MariaDB */ enum durability_properties durability_property; /* If checking this in conjunction with a wait condition, please include a check after enter_cond() if you want to avoid a race condition. For details see the implementation of awake(), especially the "broadcast" part. */ killed_state volatile killed; /* The following is used if one wants to have a specific error number and text for the kill */ struct err_info { int no; const char msg[256]; } *killed_err; /* See also thd_killed() */ inline bool check_killed(bool dont_send_error_message= 0) { if (unlikely(killed)) { if (!dont_send_error_message) send_kill_message(); return TRUE; } if (apc_target.have_apc_requests()) apc_target.process_apc_requests(false); return FALSE; } /* scramble - random string sent to client on handshake */ char scramble[SCRAMBLE_LENGTH+1]; /* If this is a slave, the name of the connection stored here. This is used for taging error messages in the log files. */ LEX_CSTRING connection_name; uint8 password; /* 0, 1 or 2 */ uint8 failed_com_change_user; bool slave_thread; bool no_errors; /** Set to TRUE if execution of the current compound statement can not continue. In particular, disables activation of CONTINUE or EXIT handlers of stored routines. Reset in the end of processing of the current user request, in @see THD::reset_for_next_command(). */ bool is_fatal_error; /** Set by a storage engine to request the entire transaction (that possibly spans multiple engines) to rollback. Reset in ha_rollback. */ bool transaction_rollback_request; /** TRUE if we are in a sub-statement and the current error can not be safely recovered until we left the sub-statement mode. In particular, disables activation of CONTINUE and EXIT handlers inside sub-statements. E.g. if it is a deadlock error and requires a transaction-wide rollback, this flag is raised (traditionally, MySQL first has to close all the reads via @see handler::ha_index_or_rnd_end() and only then perform the rollback). Reset to FALSE when we leave the sub-statement mode. */ bool is_fatal_sub_stmt_error; /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; bool in_lock_tables; bool bootstrap, cleanup_done, free_connection_done; /** is set if a statement accesses a temporary table created through CREATE TEMPORARY TABLE. */ private: bool charset_is_system_charset, charset_is_collation_connection; bool charset_is_character_set_filesystem; public: bool enable_slow_log; /* Enable slow log for current statement */ bool abort_on_warning; bool got_warning; /* Set on call to push_warning() */ /* set during loop of derived table processing */ bool derived_tables_processing; bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */ bool log_current_statement() const { return variables.option_bits & OPTION_BINLOG_THIS_STMT; } /** True if a slave error. Causes the slave to stop. Not the same as the statement execution error (is_error()), since a statement may be expected to return an error, e.g. because it returned an error on master, and this is OK on the slave. */ bool is_slave_error; /* True if we have printed something to the error log for this statement */ bool error_printed_to_log; /* True when a transaction is queued up for binlog group commit. Used so that if another transaction needs to wait for a row lock held by this transaction, it can signal to trigger the group commit immediately, skipping the normal --binlog-commit-wait-count wait. */ bool waiting_on_group_commit; /* Set true when another transaction goes to wait on a row lock held by this transaction. Used together with waiting_on_group_commit. */ bool has_waiter; /* In case of a slave, set to the error code the master got when executing the query. 0 if no error on the master. The stored into variable master error code may get reset inside execution stack when the event turns out to be ignored. */ int slave_expected_error; enum_sql_command last_sql_command; // Last sql_command exceuted in mysql_execute_command() sp_rcontext *spcont; // SP runtime context sp_rcontext *get_rcontext(const sp_rcontext_addr &addr); Item_field *get_variable(const sp_rcontext_addr &addr); /** number of name_const() substitutions, see sp_head.cc:subst_spvars() */ uint query_name_consts; NET* slave_net; // network connection from slave -> m. /* Used to update global user stats. The global user stats are updated occasionally with the 'diff' variables. After the update, the 'diff' variables are reset to 0. */ /* Time when the current thread connected to MySQL. */ time_t current_connect_time; /* Last time when THD stats were updated in global_user_stats. */ time_t last_global_update_time; /* Number of commands not reflected in global_user_stats yet. */ uint select_commands, update_commands, other_commands; ulonglong start_cpu_time; ulonglong start_bytes_received; /* Used by the sys_var class to store temporary values */ union { my_bool my_bool_value; int int_value; uint uint_value; long long_value; ulong ulong_value; ulonglong ulonglong_value; double double_value; void *ptr_value; } sys_var_tmp; struct { /* If true, mysql_bin_log::write(Log_event) call will not write events to binlog, and maintain 2 below variables instead (use mysql_bin_log.start_union_events to turn this on) */ bool do_union; /* If TRUE, at least one mysql_bin_log::write(Log_event) call has been made after last mysql_bin_log.start_union_events() call. */ bool unioned_events; /* If TRUE, at least one mysql_bin_log::write(Log_event e), where e.cache_stmt == TRUE call has been made after last mysql_bin_log.start_union_events() call. */ bool unioned_events_trans; /* 'queries' (actually SP statements) that run under inside this binlog union have thd->query_id >= first_query_id. */ query_id_t first_query_id; } binlog_evt_union; /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser state here. This member is valid only when executing code during parsing. */ Parser_state *m_parser_state; Locked_tables_list locked_tables_list; #ifdef WITH_PARTITION_STORAGE_ENGINE partition_info *work_part_info; #endif #ifndef EMBEDDED_LIBRARY /** Array of active audit plugins which have been used by this THD. This list is later iterated to invoke release_thd() on those plugins. */ DYNAMIC_ARRAY audit_class_plugins; /** Array of bits indicating which audit classes have already been added to the list of audit plugins which are currently in use. */ unsigned long audit_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; int audit_plugin_version; #endif #if defined(ENABLED_DEBUG_SYNC) /* Debug Sync facility. See debug_sync.cc. */ struct st_debug_sync_control *debug_sync_control; #endif /* defined(ENABLED_DEBUG_SYNC) */ /** @param id thread identifier @param is_wsrep_applier thread type */ THD(my_thread_id id, bool is_wsrep_applier= false); ~THD(); void init(); /* Initialize memory roots necessary for query processing and (!) pre-allocate memory for it. We can't do that in THD constructor because there are use cases (acl_init, delayed inserts, watcher threads, killing mysqld) where it's vital to not allocate excessive and not used memory. Note, that we still don't return error from init_for_queries(): if preallocation fails, we should notice that at the first call to alloc_root. */ void init_for_queries(); void update_all_stats(); void update_stats(void); void change_user(void); void cleanup(void); void cleanup_after_query(); void free_connection(); void reset_for_reuse(); void store_globals(); void reset_stack() { thread_stack= 0; } void reset_globals(); bool trace_started() { return opt_trace.is_started(); } #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { mysql_mutex_lock(&LOCK_thd_data); active_vio = vio; mysql_mutex_unlock(&LOCK_thd_data); } inline void clear_active_vio() { mysql_mutex_lock(&LOCK_thd_data); active_vio = 0; mysql_mutex_unlock(&LOCK_thd_data); } void close_active_vio(); #endif void awake_no_mutex(killed_state state_to_set); void awake(killed_state state_to_set) { mysql_mutex_lock(&LOCK_thd_kill); mysql_mutex_lock(&LOCK_thd_data); awake_no_mutex(state_to_set); mysql_mutex_unlock(&LOCK_thd_data); mysql_mutex_unlock(&LOCK_thd_kill); } void abort_current_cond_wait(bool force); /** Disconnect the associated communication endpoint. */ void disconnect(); /* Allows this thread to serve as a target for others to schedule Async Procedure Calls on. It's possible to schedule any code to be executed this way, by inheriting from the Apc_call object. Currently, only Show_explain_request uses this. */ Apc_target apc_target; Gap_time_tracker_data gap_tracker_data; #ifndef MYSQL_CLIENT enum enum_binlog_query_type { /* The query can be logged in row format or in statement format. */ ROW_QUERY_TYPE, /* The query has to be logged in statement format. */ STMT_QUERY_TYPE, QUERY_TYPE_COUNT }; int binlog_query(enum_binlog_query_type qtype, char const *query, ulong query_len, bool is_trans, bool direct, bool suppress_use, int errcode); bool binlog_current_query_unfiltered(); #endif inline void enter_cond(mysql_cond_t *cond, mysql_mutex_t* mutex, const PSI_stage_info *stage, PSI_stage_info *old_stage, const char *src_function, const char *src_file, int src_line) override { mysql_mutex_assert_owner(mutex); mysys_var->current_mutex = mutex; mysys_var->current_cond = cond; if (old_stage) backup_stage(old_stage); if (stage) enter_stage(stage, src_function, src_file, src_line); } inline void exit_cond(const PSI_stage_info *stage, const char *src_function, const char *src_file, int src_line) override { /* Putting the mutex unlock in thd->exit_cond() ensures that mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is locked (if that would not be the case, you'll get a deadlock if someone does a THD::awake() on you). */ mysql_mutex_unlock(mysys_var->current_mutex); mysql_mutex_lock(&mysys_var->mutex); mysys_var->current_mutex = 0; mysys_var->current_cond = 0; if (stage) enter_stage(stage, src_function, src_file, src_line); mysql_mutex_unlock(&mysys_var->mutex); return; } int is_killed() override { return killed; } THD* get_thd() override { return this; } /** A callback to the server internals that is used to address special cases of the locking protocol. Invoked when acquiring an exclusive lock, for each thread that has a conflicting shared metadata lock. This function: - aborts waiting of the thread on a data lock, to make it notice the pending exclusive lock and back off. - if the thread is an INSERT DELAYED thread, sends it a KILL signal to terminate it. @note This function does not wait for the thread to give away its locks. Waiting is done outside for all threads at once. @param ctx_in_use The MDL context owner (thread) to wake up. @param needs_thr_lock_abort Indicates that to wake up thread this call needs to abort its waiting on table-level lock. @retval TRUE if the thread was woken up @retval FALSE otherwise. */ bool notify_shared_lock(MDL_context_owner *ctx_in_use, bool needs_thr_lock_abort) override; // End implementation of MDL_context_owner interface. inline bool is_strict_mode() const { return (bool) (variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); } inline bool backslash_escapes() const { return !MY_TEST(variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES); } const Type_handler *type_handler_for_datetime() const; bool timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts, ulong sec_part, date_mode_t fuzzydate); inline my_time_t query_start() { return start_time; } inline ulong query_start_sec_part() { used|= QUERY_START_SEC_PART_USED; return start_time_sec_part; } MYSQL_TIME query_start_TIME(); time_round_mode_t temporal_round_mode() const { return variables.sql_mode & MODE_TIME_ROUND_FRACTIONAL ? TIME_FRAC_ROUND : TIME_FRAC_TRUNCATE; } private: struct { my_hrtime_t start; my_time_t sec; ulong sec_part; } system_time; void set_system_time() { my_hrtime_t hrtime= my_hrtime(); my_time_t sec= hrtime_to_my_time(hrtime); ulong sec_part= hrtime_sec_part(hrtime); if (sec > system_time.sec || (sec == system_time.sec && sec_part > system_time.sec_part) || hrtime.val < system_time.start.val) { system_time.sec= sec; system_time.sec_part= sec_part; system_time.start= hrtime; } else { if (system_time.sec_part < TIME_MAX_SECOND_PART) system_time.sec_part++; else { system_time.sec++; system_time.sec_part= 0; } } } public: timeval transaction_time() { if (!in_multi_stmt_transaction_mode()) transaction->start_time.reset(this); return transaction->start_time; } inline void set_start_time() { if (user_time.val) { start_time= hrtime_to_my_time(user_time); start_time_sec_part= hrtime_sec_part(user_time); } else { set_system_time(); start_time= system_time.sec; start_time_sec_part= system_time.sec_part; } PSI_CALL_set_thread_start_time(start_time); } inline void set_time() { set_start_time(); start_utime= utime_after_lock= microsecond_interval_timer(); } /* only used in SET @@timestamp=... */ inline void set_time(my_hrtime_t t) { user_time= t; set_time(); } inline void force_set_time(my_time_t t, ulong sec_part) { start_time= system_time.sec= t; start_time_sec_part= system_time.sec_part= sec_part; } /* this is only used by replication and BINLOG command. usecs > TIME_MAX_SECOND_PART means "was not in binlog" */ inline void set_time(my_time_t t, ulong sec_part) { if (opt_secure_timestamp > (slave_thread ? SECTIME_REPL : SECTIME_SUPER)) set_time(); // note that BINLOG itself requires SUPER else { if (sec_part <= TIME_MAX_SECOND_PART) force_set_time(t, sec_part); else if (t != system_time.sec) force_set_time(t, 0); else { start_time= t; start_time_sec_part= ++system_time.sec_part; } user_time.val= hrtime_from_time(start_time) + start_time_sec_part; PSI_CALL_set_thread_start_time(start_time); start_utime= utime_after_lock= microsecond_interval_timer(); } } void set_time_after_lock() { utime_after_lock= microsecond_interval_timer(); MYSQL_SET_STATEMENT_LOCK_TIME(m_statement_psi, (utime_after_lock - start_utime)); } ulonglong current_utime() { return microsecond_interval_timer(); } /* Tell SHOW PROCESSLIST to show time from this point */ inline void set_time_for_next_stage() { utime_after_query= current_utime(); } Timeval_null safe_timeval_replacement_for_nonzero_datetime(const Datetime &); /** Update server status after execution of a top level statement. Currently only checks if a query was slow, and assigns the status accordingly. Evaluate the current time, and if it exceeds the long-query-time setting, mark the query as slow. */ void update_server_status() { set_time_for_next_stage(); if (utime_after_query >= utime_after_lock + variables.long_query_time) server_status|= SERVER_QUERY_WAS_SLOW; } inline ulonglong found_rows(void) { return limit_found_rows; } /** Returns TRUE if session is in a multi-statement transaction mode. OPTION_NOT_AUTOCOMMIT: When autocommit is off, a multi-statement transaction is implicitly started on the first statement after a previous transaction has been ended. OPTION_BEGIN: Regardless of the autocommit status, a multi-statement transaction can be explicitly started with the statements "START TRANSACTION", "BEGIN [WORK]", "[COMMIT | ROLLBACK] AND CHAIN", etc. Note: this doesn't tell you whether a transaction is active. A session can be in multi-statement transaction mode, and yet have no active transaction, e.g., in case of: set @@autocommit=0; set @a= 3; <-- these statements don't set transaction isolation level serializable; <-- start an active flush tables; <-- transaction I.e. for the above scenario this function returns TRUE, even though no active transaction has begun. @sa in_active_multi_stmt_transaction() */ inline bool in_multi_stmt_transaction_mode() { return variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN); } /** TRUE if the session is in a multi-statement transaction mode (@sa in_multi_stmt_transaction_mode()) *and* there is an active transaction, i.e. there is an explicit start of a transaction with BEGIN statement, or implicit with a statement that uses a transactional engine. For example, these scenarios don't start an active transaction (even though the server is in multi-statement transaction mode): set @@autocommit=0; select * from nontrans_table; set @var=TRUE; flush tables; Note, that even for a statement that starts a multi-statement transaction (i.e. select * from trans_table), this flag won't be set until we open the statement's tables and the engines register themselves for the transaction (see trans_register_ha()), hence this method is reliable to use only after open_tables() has completed. Why do we need a flag? ---------------------- We need to maintain a (at first glance redundant) session flag, rather than looking at thd->transaction.all.ha_list because of explicit start of a transaction with BEGIN. I.e. in case of BEGIN; select * from nontrans_t1; <-- in_active_multi_stmt_transaction() is true */ inline bool in_active_multi_stmt_transaction() { return server_status & SERVER_STATUS_IN_TRANS; } /* Commit both statement and full transaction */ int commit_whole_transaction_and_close_tables(); void give_protection_error(); /* Give an error if any of the following is true for this connection - BACKUP STAGE is active - FLUSH TABLE WITH READ LOCK is active - BACKUP LOCK table_name is active */ inline bool has_read_only_protection() { if (current_backup_stage == BACKUP_FINISHED && !global_read_lock.is_acquired() && !mdl_backup_lock) return FALSE; give_protection_error(); return TRUE; } inline bool fill_information_schema_tables() { return !stmt_arena->is_stmt_prepare(); } inline void* trans_alloc(size_t size) const { return alloc_root(&transaction->mem_root,size); } LEX_CSTRING strmake_lex_cstring_trim_whitespace(const LEX_CSTRING &from) { return Query_arena::strmake_lex_cstring_trim_whitespace(from, charset()); } bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, const char *from, size_t from_length, CHARSET_INFO *from_cs) const; bool reinterpret_string_from_binary(LEX_CSTRING *to, CHARSET_INFO *to_cs, const char *from, size_t from_length) const; bool convert_string(LEX_CSTRING *to, CHARSET_INFO *to_cs, const char *from, size_t from_length, CHARSET_INFO *from_cs) const { LEX_STRING tmp; bool rc= convert_string(&tmp, to_cs, from, from_length, from_cs); to->str= tmp.str; to->length= tmp.length; return rc; } bool convert_string(LEX_CSTRING *to, CHARSET_INFO *tocs, const LEX_CSTRING *from, CHARSET_INFO *fromcs, bool simple_copy_is_possible) const { if (!simple_copy_is_possible) return unlikely(convert_string(to, tocs, from->str, from->length, fromcs)); if (fromcs == &my_charset_bin) return reinterpret_string_from_binary(to, tocs, from->str, from->length); *to= *from; return false; } /* Convert a strings between character sets. Uses my_convert_fix(), which uses an mb_wc .. mc_mb loop internally. dstcs and srccs cannot be &my_charset_bin. */ bool convert_fix(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length, String_copier *status) const; /* Same as above, but additionally sends ER_INVALID_CHARACTER_STRING in case of bad byte sequences or Unicode conversion problems. */ bool convert_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length) const; /* If either "dstcs" or "srccs" is &my_charset_bin, then performs native copying using copy_fix(). Otherwise, performs Unicode conversion using convert_fix(). */ bool copy_fix(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length, String_copier *status) const; /* Same as above, but additionally sends ER_INVALID_CHARACTER_STRING in case of bad byte sequences or Unicode conversion problems. */ bool copy_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length) const; bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs); /* Check if the string is wellformed, raise an error if not wellformed. @param str - The string to check. @param length - the string length. */ bool check_string_for_wellformedness(const char *str, size_t length, CHARSET_INFO *cs) const; bool to_ident_sys_alloc(Lex_ident_sys_st *to, const Lex_ident_cli_st *from) const; /* Create a string literal with optional client->connection conversion. @param str - the string in the client character set @param length - length of the string @param repertoire - the repertoire of the string */ Item_basic_constant *make_string_literal(const char *str, size_t length, my_repertoire_t repertoire); Item_basic_constant * make_string_literal(const Lex_string_with_metadata_st &str) { my_repertoire_t repertoire= str.repertoire(variables.character_set_client); return make_string_literal(str.str, str.length, repertoire); } Item_basic_constant *make_string_literal_nchar(const Lex_string_with_metadata_st &str); Item_basic_constant *make_string_literal_charset(const Lex_string_with_metadata_st &str, CHARSET_INFO *cs); bool make_text_string_sys(LEX_CSTRING *to, const Lex_string_with_metadata_st *from) { return convert_string(to, system_charset_info, from, charset(), charset_is_system_charset); } bool make_text_string_connection(LEX_CSTRING *to, const Lex_string_with_metadata_st *from) { return convert_string(to, variables.collation_connection, from, charset(), charset_is_collation_connection); } bool make_text_string_filesystem(LEX_CSTRING *to, const Lex_string_with_metadata_st *from) { return convert_string(to, variables.character_set_filesystem, from, charset(), charset_is_character_set_filesystem); } void add_changed_table(TABLE *table); void add_changed_table(const char *key, size_t key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, size_t key_length); int prepare_explain_fields(select_result *result, List<Item> *field_list, uint8 explain_flags, bool is_analyze); int send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze); void make_explain_field_list(List<Item> &field_list, uint8 explain_flags, bool is_analyze); void make_explain_json_field_list(List<Item> &field_list, bool is_analyze); /** Clear the current error, if any. We do not clear is_fatal_error or is_fatal_sub_stmt_error since we assume this is never called if the fatal error is set. @todo: To silence an error, one should use Internal_error_handler mechanism. Issuing an error that can be possibly later "cleared" is not compatible with other installed error handlers and audit plugins. */ inline void clear_error(bool clear_diagnostics= 0) { DBUG_ENTER("clear_error"); if (get_stmt_da()->is_error() || clear_diagnostics) get_stmt_da()->reset_diagnostics_area(); is_slave_error= 0; if (killed == KILL_BAD_DATA) reset_killed(); my_errno= 0; DBUG_VOID_RETURN; } #ifndef EMBEDDED_LIBRARY inline bool vio_ok() const { return net.vio != 0; } /** Return FALSE if connection to client is broken. */ bool is_connected() { /* All system threads (e.g., the slave IO thread) are connected but not using vio. So this function always returns true for all system threads. */ return system_thread || (vio_ok() ? vio_is_connected(net.vio) : FALSE); } #else inline bool vio_ok() const { return TRUE; } inline bool is_connected() { return TRUE; } #endif void my_ok_with_recreate_info(const Recreate_info &info, ulong warn_count); /** Mark the current error as fatal. Warning: this does not set any error, it sets a property of the error, so must be followed or prefixed with my_error(). */ inline void fatal_error() { DBUG_ASSERT(get_stmt_da()->is_error() || killed); is_fatal_error= 1; DBUG_PRINT("error",("Fatal error set")); } /** TRUE if there is an error in the error stack. Please use this method instead of direct access to net.report_error. If TRUE, the current (sub)-statement should be aborted. The main difference between this member and is_fatal_error is that a fatal error can not be handled by a stored procedure continue handler, whereas a normal error can. To raise this flag, use my_error(). */ inline bool is_error() const { return m_stmt_da->is_error(); } void set_bulk_execution(void *bulk) { bulk_param= bulk; m_stmt_da->set_bulk_execution(MY_TEST(bulk)); } bool is_bulk_op() const { return MY_TEST(bulk_param); } /// Returns Diagnostics-area for the current statement. Diagnostics_area *get_stmt_da() { return m_stmt_da; } /// Returns Diagnostics-area for the current statement. const Diagnostics_area *get_stmt_da() const { return m_stmt_da; } /// Sets Diagnostics-area for the current statement. void set_stmt_da(Diagnostics_area *da) { m_stmt_da= da; } inline CHARSET_INFO *charset() const { return variables.character_set_client; } void update_charset(); void update_charset(CHARSET_INFO *character_set_client, CHARSET_INFO *collation_connection) { variables.character_set_client= character_set_client; variables.collation_connection= collation_connection; update_charset(); } void update_charset(CHARSET_INFO *character_set_client, CHARSET_INFO *collation_connection, CHARSET_INFO *character_set_results) { variables.character_set_client= character_set_client; variables.collation_connection= collation_connection; variables.character_set_results= character_set_results; update_charset(); } inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup) { if (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) /* Caller uses the arena with state STMT_SP_QUERY_ARGUMENTS for stored routine's parameters. Lifetime of these objects spans a lifetime of stored routine call and freed every time the stored routine execution has been completed. That is the reason why switching to statement's arena is not performed for arguments, else we would observe increasing of memory usage while a stored routine be called over and over again. */ return NULL; /* Use the persistent arena if we are in a prepared statement or a stored procedure statement and we have not already changed to use this arena. */ if (!stmt_arena->is_conventional() && mem_root != stmt_arena->mem_root) { set_n_backup_active_arena(stmt_arena, backup); return stmt_arena; } return 0; } bool is_item_tree_change_register_required() { return !stmt_arena->is_conventional(); } void register_item_tree_change(Item **place) { /* TODO: check for OOM condition here */ if (is_item_tree_change_register_required()) nocheck_register_item_tree_change(place, *place, mem_root); } void change_item_tree(Item **place, Item *new_value) { DBUG_ENTER("THD::change_item_tree"); DBUG_PRINT("enter", ("Register: %p (%p) <- %p", *place, place, new_value)); register_item_tree_change(place); *place= new_value; DBUG_VOID_RETURN; } /** Make change in item tree after checking whether it needs registering @param place place where we should assign new value @param new_value place of the new value @details see check_and_register_item_tree_change details */ void check_and_register_item_tree(Item **place, Item **new_value) { if (!stmt_arena->is_conventional()) check_and_register_item_tree_change(place, new_value, mem_root); /* We have to use memcpy instead of *place= *new_value merge to avoid problems with strict aliasing. */ memcpy((char*) place, new_value, sizeof(*new_value)); } /* Cleanup statement parse state (parse tree, lex) and execution state after execution of a non-prepared SQL statement. */ void end_statement(); /* Mark thread to be killed, with optional error number and string. string is not released, so it has to be allocted on thd mem_root or be a global string Ensure that we don't replace a kill with a lesser one. For example if user has done 'kill_connection' we shouldn't replace it with KILL_QUERY. */ inline void set_killed(killed_state killed_arg, int killed_errno_arg= 0, const char *killed_err_msg_arg= 0) { mysql_mutex_lock(&LOCK_thd_kill); set_killed_no_mutex(killed_arg, killed_errno_arg, killed_err_msg_arg); mysql_mutex_unlock(&LOCK_thd_kill); } /* This is only used by THD::awake where we need to keep the lock mutex locked over some time. It's ok to have this inline, as in most cases killed_errno_arg will be a constant 0 and most of the function will disappear. */ inline void set_killed_no_mutex(killed_state killed_arg, int killed_errno_arg= 0, const char *killed_err_msg_arg= 0) { if (killed <= killed_arg) { killed= killed_arg; if (killed_errno_arg) { /* If alloc fails, we only remember the killed flag. The worst things that can happen is that we get a suboptimal error message. */ if (!killed_err) killed_err= (err_info*) my_malloc(PSI_INSTRUMENT_ME, sizeof(*killed_err), MYF(MY_WME)); if (likely(killed_err)) { killed_err->no= killed_errno_arg; ::strmake((char*) killed_err->msg, killed_err_msg_arg, sizeof(killed_err->msg)-1); } } } } int killed_errno(); void reset_killed(); inline void reset_kill_query() { if (killed < KILL_CONNECTION) { reset_killed(); mysys_var->abort= 0; } } inline void send_kill_message() { mysql_mutex_lock(&LOCK_thd_kill); int err= killed_errno(); if (err) my_message(err, killed_err ? killed_err->msg : ER_THD(this, err), MYF(0)); mysql_mutex_unlock(&LOCK_thd_kill); } /* return TRUE if we will abort query if we make a warning now */ inline bool really_abort_on_warning() { return (abort_on_warning && (!transaction->stmt.modified_non_trans_table || (variables.sql_mode & MODE_STRICT_ALL_TABLES))); } void set_status_var_init(); void reset_n_backup_open_tables_state(Open_tables_backup *backup); void restore_backup_open_tables_state(Open_tables_backup *backup); void reset_sub_statement_state(Sub_statement_state *backup, uint new_state); void restore_sub_statement_state(Sub_statement_state *backup); void store_slow_query_state(Sub_statement_state *backup); void reset_slow_query_state(Sub_statement_state *backup); void add_slow_query_state(Sub_statement_state *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup); inline void get_binlog_format(enum_binlog_format *format, enum_binlog_format *current_format) { *format= (enum_binlog_format) variables.binlog_format; *current_format= current_stmt_binlog_format; } inline enum_binlog_format get_current_stmt_binlog_format() { return current_stmt_binlog_format; } inline void set_binlog_format(enum_binlog_format format, enum_binlog_format current_format) { DBUG_ENTER("set_binlog_format"); variables.binlog_format= format; current_stmt_binlog_format= current_format; DBUG_VOID_RETURN; } inline void set_binlog_format_stmt() { DBUG_ENTER("set_binlog_format_stmt"); variables.binlog_format= BINLOG_FORMAT_STMT; current_stmt_binlog_format= BINLOG_FORMAT_STMT; DBUG_VOID_RETURN; } /* @todo Make these methods private or remove them completely. Only decide_logging_format should call them. /Sven */ inline void set_current_stmt_binlog_format_row_if_mixed() { DBUG_ENTER("set_current_stmt_binlog_format_row_if_mixed"); /* This should only be called from decide_logging_format. @todo Once we have ensured this, uncomment the following statement, remove the big comment below that, and remove the in_sub_stmt==0 condition from the following 'if'. */ /* DBUG_ASSERT(in_sub_stmt == 0); */ /* If in a stored/function trigger, the caller should already have done the change. We test in_sub_stmt to prevent introducing bugs where people wouldn't ensure that, and would switch to row-based mode in the middle of executing a stored function/trigger (which is too late, see also reset_current_stmt_binlog_format_row()); this condition will make their tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ if ((wsrep_binlog_format(variables.binlog_format) == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) set_current_stmt_binlog_format_row(); DBUG_VOID_RETURN; } inline void set_current_stmt_binlog_format(enum_binlog_format format) { current_stmt_binlog_format= format; } inline void set_current_stmt_binlog_format_row() { DBUG_ENTER("set_current_stmt_binlog_format_row"); current_stmt_binlog_format= BINLOG_FORMAT_ROW; DBUG_VOID_RETURN; } /* Set binlog format temporarily to statement. Returns old format */ inline enum_binlog_format set_current_stmt_binlog_format_stmt() { enum_binlog_format orig_format= current_stmt_binlog_format; DBUG_ENTER("set_current_stmt_binlog_format_stmt"); current_stmt_binlog_format= BINLOG_FORMAT_STMT; DBUG_RETURN(orig_format); } inline void restore_stmt_binlog_format(enum_binlog_format format) { DBUG_ENTER("restore_stmt_binlog_format"); DBUG_ASSERT(!is_current_stmt_binlog_format_row()); current_stmt_binlog_format= format; DBUG_VOID_RETURN; } inline void reset_current_stmt_binlog_format_row() { DBUG_ENTER("reset_current_stmt_binlog_format_row"); /* If there are temporary tables, don't reset back to statement-based. Indeed it could be that: CREATE TEMPORARY TABLE t SELECT UUID(); # row-based # and row-based does not store updates to temp tables # in the binlog. INSERT INTO u SELECT * FROM t; # stmt-based and then the INSERT will fail as data inserted into t was not logged. So we continue with row-based until the temp table is dropped. If we are in a stored function or trigger, we mustn't reset in the middle of its execution (as the binary logging way of a stored function or trigger is decided when it starts executing, depending for example on the caller (for a stored function: if caller is SELECT or INSERT/UPDATE/DELETE...). */ DBUG_PRINT("debug", ("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s", YESNO(has_temporary_tables()), YESNO(in_sub_stmt), show_system_thread(system_thread))); if (in_sub_stmt == 0) { if (wsrep_binlog_format(variables.binlog_format) == BINLOG_FORMAT_ROW) set_current_stmt_binlog_format_row(); else if (!has_temporary_tables()) set_current_stmt_binlog_format_stmt(); } DBUG_VOID_RETURN; } /** Set the current database; use deep copy of C-string. @param new_db a pointer to the new database name. @param new_db_len length of the new database name. Initialize the current database from a NULL-terminated string with length. If we run out of memory, we free the current database and return TRUE. This way the user will notice the error as there will be no current database selected (in addition to the error message set by malloc). @note This operation just sets {db, db_length}. Switching the current database usually involves other actions, like switching other database attributes including security context. In the future, this operation will be made private and more convenient interface will be provided. @return Operation status @retval FALSE Success @retval TRUE Out-of-memory error */ bool set_db(const LEX_CSTRING *new_db); /** Set the current database, without copying */ void reset_db(const LEX_CSTRING *new_db); /* Copy the current database to the argument. Use the current arena to allocate memory for a deep copy: current database may be freed after a statement is parsed but before it's executed. Can only be called by owner of thd (no mutex protection) */ bool copy_db_to(LEX_CSTRING *to) { if (db.str) { to->str= strmake(db.str, db.length); to->length= db.length; return to->str == NULL; /* True on error */ } /* No default database is set. In this case if it's guaranteed that no CTE can be used in the statement then we can throw an error right now at the parser stage. Otherwise the decision about throwing such a message must be postponed until a post-parser stage when we are able to resolve all CTE names as we don't need this message to be thrown for any CTE references. */ if (!lex->with_cte_resolution) my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); return TRUE; } /* Get db name or "". */ const char *get_db() { return safe_str(db.str); } thd_scheduler event_scheduler; public: inline Internal_error_handler *get_internal_handler() { return m_internal_handler; } /** Add an internal error handler to the thread execution context. @param handler the exception handler to add */ void push_internal_handler(Internal_error_handler *handler); private: /** Handle a sql condition. @param sql_errno the condition error number @param sqlstate the condition sqlstate @param level the condition level @param msg the condition message text @param[out] cond_hdl the sql condition raised, if any @return true if the condition is handled */ bool handle_condition(uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); public: /** Remove the error handler last pushed. */ Internal_error_handler *pop_internal_handler(); /** Raise an exception condition. @param code the MYSQL_ERRNO error code of the error */ void raise_error(uint code); /** Raise an exception condition, with a formatted message. @param code the MYSQL_ERRNO error code of the error */ void raise_error_printf(uint code, ...); /** Raise a completion condition (warning). @param code the MYSQL_ERRNO error code of the warning */ void raise_warning(uint code); /** Raise a completion condition (warning), with a formatted message. @param code the MYSQL_ERRNO error code of the warning */ void raise_warning_printf(uint code, ...); /** Raise a completion condition (note), with a fixed message. @param code the MYSQL_ERRNO error code of the note */ void raise_note(uint code); /** Raise an completion condition (note), with a formatted message. @param code the MYSQL_ERRNO error code of the note */ void raise_note_printf(uint code, ...); /** @brief Push an error message into MySQL error stack with line and position information. This function provides semantic action implementers with a way to push the famous "You have a syntax error near..." error message into the error stack, which is normally produced only if a parse error is discovered internally by the Bison generated parser. */ void parse_error(const char *err_text, const char *yytext) { Lex_input_stream *lip= &m_parser_state->m_lip; if (!yytext && !(yytext= lip->get_tok_start())) yytext= ""; /* Push an error into the error stack */ ErrConvString err(yytext, strlen(yytext), variables.character_set_client); my_printf_error(ER_PARSE_ERROR, ER_THD(this, ER_PARSE_ERROR), MYF(0), err_text, err.ptr(), lip->yylineno); } void parse_error(uint err_number, const char *yytext= 0) { parse_error(ER_THD(this, err_number), yytext); } void parse_error() { parse_error(ER_SYNTAX_ERROR); } #ifdef mysqld_error_find_printf_error_used void parse_error(const char *t) { } #endif private: /* Only the implementation of the SIGNAL and RESIGNAL statements is permitted to raise SQL conditions in a generic way, or to raise them by bypassing handlers (RESIGNAL). To raise a SQL condition, the code should use the public raise_error() or raise_warning() methods provided by class THD. */ friend class Sql_cmd_common_signal; friend class Sql_cmd_signal; friend class Sql_cmd_resignal; friend void push_warning(THD*, Sql_condition::enum_warning_level, uint, const char*); friend void my_message_sql(uint, const char *, myf); /** Raise a generic SQL condition. @param sql_errno the condition error number @param sqlstate the condition SQLSTATE @param level the condition level @param msg the condition message text @return The condition raised, or NULL */ Sql_condition* raise_condition(uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level level, const char* msg) { Sql_condition cond(NULL, // don't strdup the msg Sql_condition_identity(sql_errno, sqlstate, level, Sql_user_condition_identity()), msg, get_stmt_da()->current_row_for_warning()); return raise_condition(&cond); } Sql_condition* raise_condition(const Sql_condition *cond); private: void push_warning_truncated_priv(Sql_condition::enum_warning_level level, uint sql_errno, const char *type_str, const char *val) { DBUG_ASSERT(sql_errno == ER_TRUNCATED_WRONG_VALUE || sql_errno == ER_WRONG_VALUE); char buff[MYSQL_ERRMSG_SIZE]; CHARSET_INFO *cs= &my_charset_latin1; cs->cset->snprintf(cs, buff, sizeof(buff), ER_THD(this, sql_errno), type_str, val); /* Note: the format string can vary between ER_TRUNCATED_WRONG_VALUE and ER_WRONG_VALUE, but the code passed to push_warning() is always ER_TRUNCATED_WRONG_VALUE. This is intentional. */ push_warning(this, level, ER_TRUNCATED_WRONG_VALUE, buff); } public: void push_warning_truncated_wrong_value(Sql_condition::enum_warning_level level, const char *type_str, const char *val) { return push_warning_truncated_priv(level, ER_TRUNCATED_WRONG_VALUE, type_str, val); } void push_warning_wrong_value(Sql_condition::enum_warning_level level, const char *type_str, const char *val) { return push_warning_truncated_priv(level, ER_WRONG_VALUE, type_str, val); } void push_warning_truncated_wrong_value(const char *type_str, const char *val) { return push_warning_truncated_wrong_value(Sql_condition::WARN_LEVEL_WARN, type_str, val); } void push_warning_truncated_value_for_field(Sql_condition::enum_warning_level level, const char *type_str, const char *val, const char *db_name, const char *table_name, const char *name) { DBUG_ASSERT(name); char buff[MYSQL_ERRMSG_SIZE]; CHARSET_INFO *cs= &my_charset_latin1; if (!db_name) db_name= ""; if (!table_name) table_name= ""; cs->cset->snprintf(cs, buff, sizeof(buff), ER_THD(this, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), type_str, val, db_name, table_name, name, (ulong) get_stmt_da()->current_row_for_warning()); push_warning(this, level, ER_TRUNCATED_WRONG_VALUE, buff); } void push_warning_wrong_or_truncated_value(Sql_condition::enum_warning_level level, bool totally_useless_value, const char *type_str, const char *val, const char *db_name, const char *table_name, const char *field_name) { if (field_name) push_warning_truncated_value_for_field(level, type_str, val, db_name, table_name, field_name); else if (totally_useless_value) push_warning_wrong_value(level, type_str, val); else push_warning_truncated_wrong_value(level, type_str, val); } public: /** Overloaded to guard query/query_length fields */ void set_statement(Statement *stmt) override; inline void set_command(enum enum_server_command command) { DBUG_ASSERT(command != COM_SLEEP); m_command= command; #ifdef HAVE_PSI_THREAD_INTERFACE PSI_STATEMENT_CALL(set_thread_command)(m_command); #endif } /* As sleep needs a bit of special handling, we have a special case for it */ inline void mark_connection_idle() { proc_info= 0; m_command= COM_SLEEP; #ifdef HAVE_PSI_THREAD_INTERFACE PSI_STATEMENT_CALL(set_thread_command)(m_command); #endif } inline enum enum_server_command get_command() const { return m_command; } /** Assign a new value to thd->query and thd->query_id and mysys_var. Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, size_t query_length_arg, CHARSET_INFO *cs_arg) { set_query(CSET_STRING(query_arg, query_length_arg, cs_arg)); } void set_query(char *query_arg, size_t query_length_arg) /*Mutex protected*/ { set_query(CSET_STRING(query_arg, query_length_arg, charset())); } void set_query(const CSET_STRING &string_arg) { mysql_mutex_lock(&LOCK_thd_data); set_query_inner(string_arg); mysql_mutex_unlock(&LOCK_thd_data); PSI_CALL_set_thread_info(query(), query_length()); } void reset_query() /* Mutex protected */ { set_query(CSET_STRING()); } void set_query_and_id(char *query_arg, uint32 query_length_arg, CHARSET_INFO *cs, query_id_t new_query_id); void set_query_id(query_id_t new_query_id) { query_id= new_query_id; #ifdef WITH_WSREP if (WSREP_NNULL(this)) { set_wsrep_next_trx_id(query_id); WSREP_DEBUG("assigned new next trx id: %" PRIu64, wsrep_next_trx_id()); } #endif /* WITH_WSREP */ } void set_open_tables(TABLE *open_tables_arg) { mysql_mutex_lock(&LOCK_thd_data); open_tables= open_tables_arg; mysql_mutex_unlock(&LOCK_thd_data); } void set_mysys_var(struct st_my_thread_var *new_mysys_var); void enter_locked_tables_mode(enum_locked_tables_mode mode_arg) { DBUG_ASSERT(locked_tables_mode == LTM_NONE); if (mode_arg == LTM_LOCK_TABLES) { /* When entering LOCK TABLES mode we should set explicit duration for all metadata locks acquired so far in order to avoid releasing them till UNLOCK TABLES statement. We don't do this when entering prelocked mode since sub-statements don't release metadata locks and restoring status-quo after leaving prelocking mode gets complicated. */ mdl_context.set_explicit_duration_for_all_locks(); } locked_tables_mode= mode_arg; } void leave_locked_tables_mode(); /* Relesae transactional locks if there are no active transactions */ void release_transactional_locks() { if (!in_active_multi_stmt_transaction()) mdl_context.release_transactional_locks(this); } int decide_logging_format(TABLE_LIST *tables); /* In Some cases when decide_logging_format is called it does not have all information to decide the logging format. So that cases we call decide_logging_format_2 at later stages in execution. One example would be binlog format for insert on duplicate key (IODKU) but column with unique key is not inserted. We do not have inserted columns info when we call decide_logging_format so on later stage we call reconsider_logging_format_for_iodup() */ void reconsider_logging_format_for_iodup(TABLE *table); enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE}; void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; } enum need_invoker need_binlog_invoker() { return m_binlog_invoker; } void get_definer(LEX_USER *definer, bool role); void set_invoker(const LEX_CSTRING *user, const LEX_CSTRING *host) { invoker.user= *user; invoker.host= *host; } LEX_CSTRING get_invoker_user() { return invoker.user; } LEX_CSTRING get_invoker_host() { return invoker.host; } bool has_invoker() { return invoker.user.length > 0; } void print_aborted_warning(uint threshold, const char *reason) { if (global_system_variables.log_warnings > threshold) { char real_ip_str[64]; real_ip_str[0]= 0; /* For proxied connections, add the real IP to the warning message */ if (net.using_proxy_protocol && net.vio) { if(net.vio->localhost) snprintf(real_ip_str, sizeof(real_ip_str), " real ip: 'localhost'"); else { char buf[INET6_ADDRSTRLEN]; if (!vio_getnameinfo((sockaddr *)&(net.vio->remote), buf, sizeof(buf),NULL, 0, NI_NUMERICHOST)) { snprintf(real_ip_str, sizeof(real_ip_str), " real ip: '%s'",buf); } } } Security_context *sctx= &main_security_ctx; sql_print_warning(ER_THD(this, ER_NEW_ABORTING_CONNECTION), thread_id, (db.str ? db.str : "unconnected"), sctx->user ? sctx->user : "unauthenticated", sctx->host_or_ip, real_ip_str, reason); } } public: void clear_wakeup_ready() { wakeup_ready= false; } /* Sleep waiting for others to wake us up with signal_wakeup_ready(). Must call clear_wakeup_ready() before waiting. */ void wait_for_wakeup_ready(); /* Wake this thread up from wait_for_wakeup_ready(). */ void signal_wakeup_ready(); void add_status_to_global() { DBUG_ASSERT(status_in_global == 0); mysql_mutex_lock(&LOCK_status); add_to_status(&global_status_var, &status_var); /* Mark that this THD status has already been added in global status */ status_var.global_memory_used= 0; status_in_global= 1; mysql_mutex_unlock(&LOCK_status); } wait_for_commit *wait_for_commit_ptr; int wait_for_prior_commit(bool allow_kill=true) { if (wait_for_commit_ptr) return wait_for_commit_ptr->wait_for_prior_commit(this, allow_kill); return 0; } void wakeup_subsequent_commits(int wakeup_error) { if (wait_for_commit_ptr) wait_for_commit_ptr->wakeup_subsequent_commits(wakeup_error); } wait_for_commit *suspend_subsequent_commits() { wait_for_commit *suspended= wait_for_commit_ptr; wait_for_commit_ptr= NULL; return suspended; } void resume_subsequent_commits(wait_for_commit *suspended) { DBUG_ASSERT(!wait_for_commit_ptr); wait_for_commit_ptr= suspended; } void mark_transaction_to_rollback(bool all); bool internal_transaction() { return transaction != &default_transaction; } private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; /** The lex to hold the parsed tree of conventional (non-prepared) queries. Whereas for prepared and stored procedure statements we use an own lex instance for each new query, for conventional statements we reuse the same lex. (@see mysql_parse for details). */ LEX main_lex; /** This memory root is used for two purposes: - for conventional queries, to allocate structures stored in main_lex during parsing, and allocate runtime data (execution plan, etc.) during execution. - for prepared queries, only to allocate runtime data. The parsed tree itself is reused between executions and thus is stored elsewhere. */ MEM_ROOT main_mem_root; Diagnostics_area main_da; Diagnostics_area *m_stmt_da; /** It will be set if CURRENT_USER() or CURRENT_ROLE() is called in account management statements or default definer is set in CREATE/ALTER SP, SF, Event, TRIGGER or VIEW statements. Current user or role will be binlogged into Query_log_event if m_binlog_invoker is not NONE; It will be stored into invoker_host and invoker_user by SQL thread. */ enum need_invoker m_binlog_invoker; /** It points to the invoker in the Query_log_event. SQL thread use it as the default definer in CREATE/ALTER SP, SF, Event, TRIGGER or VIEW statements or current user in account management statements if it is not NULL. */ AUTHID invoker; public: Session_tracker session_tracker; /* Flag, mutex and condition for a thread to wait for a signal from another thread. Currently used to wait for group commit to complete, and COND_wakeup_ready is used for threads to wait on semi-sync ACKs (though is protected by Repl_semi_sync_master::LOCK_binlog). Note the following relationships between these two use-cases when using rpl_semi_sync_master_wait_point=AFTER_SYNC during group commit: 1) Non-leader threads use COND_wakeup_ready to wait for the leader thread to complete binlog commit. 2) The leader thread uses COND_wakeup_ready to await ACKs from the replica before signalling the non-leader threads to wake up. With wait_point=AFTER_COMMIT, there is no overlap as binlogging has finished, so COND_wakeup_ready is safe to re-use. */ bool wakeup_ready; mysql_mutex_t LOCK_wakeup_ready; mysql_cond_t COND_wakeup_ready; /* The GTID assigned to the last commit. If no GTID was assigned to any commit so far, this is indicated by last_commit_gtid.seq_no == 0. */ private: rpl_gtid m_last_commit_gtid; public: rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; } void set_last_commit_gtid(rpl_gtid >id); LF_PINS *tdc_hash_pins; LF_PINS *xid_hash_pins; bool fix_xid_hash_pins(); const XID *get_xid() const { #ifdef WITH_WSREP if (!wsrep_xid.is_null()) return &wsrep_xid; #endif /* WITH_WSREP */ return (transaction->xid_state.is_explicit_XA() ? transaction->xid_state.get_xid() : &transaction->implicit_xid); } /* Members related to temporary tables. */ public: /* Opened table states. */ enum Temporary_table_state { TMP_TABLE_IN_USE, TMP_TABLE_NOT_IN_USE, TMP_TABLE_ANY }; bool has_thd_temporary_tables(); bool has_temporary_tables(); TABLE *create_and_open_tmp_table(LEX_CUSTRING *frm, const char *path, const char *db, const char *table_name, bool open_internal_tables); TABLE *find_temporary_table(const char *db, const char *table_name, Temporary_table_state state= TMP_TABLE_IN_USE); TABLE *find_temporary_table(const TABLE_LIST *tl, Temporary_table_state state= TMP_TABLE_IN_USE); TMP_TABLE_SHARE *find_tmp_table_share_w_base_key(const char *key, uint key_length); TMP_TABLE_SHARE *find_tmp_table_share(const char *db, const char *table_name); TMP_TABLE_SHARE *find_tmp_table_share(const TABLE_LIST *tl); TMP_TABLE_SHARE *find_tmp_table_share(const char *key, size_t key_length); bool open_temporary_table(TABLE_LIST *tl); bool check_and_open_tmp_table(TABLE_LIST *tl); bool open_temporary_tables(TABLE_LIST *tl); bool close_temporary_tables(); bool rename_temporary_table(TABLE *table, const LEX_CSTRING *db, const LEX_CSTRING *table_name); bool drop_temporary_table(TABLE *table, bool *is_trans, bool delete_table); bool rm_temporary_table(handlerton *hton, const char *path); void mark_tmp_tables_as_free_for_reuse(); void mark_tmp_table_as_free_for_reuse(TABLE *table); TMP_TABLE_SHARE* save_tmp_table_share(TABLE *table); void restore_tmp_table_share(TMP_TABLE_SHARE *share); void close_unused_temporary_table_instances(const TABLE_LIST *tl); private: /* Whether a lock has been acquired? */ bool m_tmp_tables_locked; uint create_tmp_table_def_key(char *key, const char *db, const char *table_name); TMP_TABLE_SHARE *create_temporary_table(LEX_CUSTRING *frm, const char *path, const char *db, const char *table_name); TABLE *find_temporary_table(const char *key, uint key_length, Temporary_table_state state); TABLE *open_temporary_table(TMP_TABLE_SHARE *share, const char *alias); bool find_and_use_tmp_table(const TABLE_LIST *tl, TABLE **out_table); bool use_temporary_table(TABLE *table, TABLE **out_table); void close_temporary_table(TABLE *table); bool log_events_and_free_tmp_shares(); bool free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table); void free_temporary_table(TABLE *table); bool lock_temporary_tables(); void unlock_temporary_tables(); inline uint tmpkeyval(TMP_TABLE_SHARE *share) { return uint4korr(share->table_cache_key.str + share->table_cache_key.length - 4); } inline TMP_TABLE_SHARE *tmp_table_share(TABLE *table) { DBUG_ASSERT(table->s->tmp_table); return static_cast<TMP_TABLE_SHARE *>(table->s); } public: thd_async_state async_state; #ifdef HAVE_REPLICATION /* If we do a purge of binary logs, log index info of the threads that are currently reading it needs to be adjusted. To do that each thread that is using LOG_INFO needs to adjust the pointer to it */ LOG_INFO *current_linfo; Slave_info *slave_info; void set_current_linfo(LOG_INFO *linfo); void reset_current_linfo() { set_current_linfo(0); } int register_slave(uchar *packet, size_t packet_length); void unregister_slave(); bool is_binlog_dump_thread(); #endif bool check_slave_ignored_db_with_error(const Lex_ident_db &db) const; inline ulong wsrep_binlog_format(ulong binlog_format) const { #ifdef WITH_WSREP // During CTAS we force ROW format if (wsrep_ctas) return BINLOG_FORMAT_ROW; else return ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? wsrep_forced_binlog_format : binlog_format); #else return (binlog_format); #endif } #ifdef WITH_WSREP bool wsrep_applier; /* dedicated slave applier thread */ bool wsrep_applier_closing; /* applier marked to close */ bool wsrep_client_thread; /* to identify client threads*/ query_id_t wsrep_last_query_id; XID wsrep_xid; /** This flag denotes that record locking should be skipped during INSERT, gap locking during SELECT, and write-write conflicts due to innodb snapshot isolation during DELETE. Only used by the streaming replication thread that only modifies the mysql.wsrep_streaming_log table. */ my_bool wsrep_skip_locking; mysql_cond_t COND_wsrep_thd; // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 uint32 wsrep_rand; rpl_group_info *wsrep_rgi; bool wsrep_converted_lock_session; ulong wsrep_retry_counter; // of autocommit bool wsrep_PA_safe; char* wsrep_retry_query; size_t wsrep_retry_query_len; enum enum_server_command wsrep_retry_command; enum wsrep_consistency_check_mode wsrep_consistency_check; std::vector<wsrep::provider::status_variable> wsrep_status_vars; int wsrep_mysql_replicated; const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; wsrep_po_handle_t wsrep_po_handle; size_t wsrep_po_cnt; void *wsrep_apply_format; uchar* wsrep_rbr_buf; wsrep_gtid_t wsrep_sync_wait_gtid; uint64 wsrep_last_written_gtid_seqno; uint64 wsrep_current_gtid_seqno; ulong wsrep_affected_rows; bool wsrep_has_ignored_error; /* true if wsrep_on was ON in last wsrep_on_update */ bool wsrep_was_on; /* When enabled, do not replicate/binlog updates from the current table that's being processed. At the moment, it is used to keep mysql.gtid_slave_pos table updates from being replicated to other nodes via galera replication. */ bool wsrep_ignore_table; /* thread who has started kill for this THD protected by LOCK_thd_data*/ my_thread_id wsrep_aborter; /* Kill signal used, if thread was killed by manual KILL. Protected by LOCK_thd_kill. */ std::atomic<killed_state> wsrep_abort_by_kill; /* */ struct err_info* wsrep_abort_by_kill_err; #ifndef DBUG_OFF int wsrep_killed_state; #endif /* DBUG_OFF */ /* true if BF abort is observed in do_command() right after reading client's packet, and if the client has sent PS execute command. */ bool wsrep_delayed_BF_abort; // true if this transaction is CREATE TABLE AS SELECT (CTAS) bool wsrep_ctas; /* Transaction id: * m_wsrep_next_trx_id is assigned on the first query after wsrep_next_trx_id() return WSREP_UNDEFINED_TRX_ID * Each storage engine must assign value of wsrep_next_trx_id() when the transaction starts. * Effective transaction id is returned via wsrep_trx_id() */ /* Return effective transaction id */ wsrep_trx_id_t wsrep_trx_id() const { return m_wsrep_client_state.transaction().id().get(); } /* Set next trx id */ void set_wsrep_next_trx_id(query_id_t query_id) { m_wsrep_next_trx_id = (wsrep_trx_id_t) query_id; } /* Return next trx id */ wsrep_trx_id_t wsrep_next_trx_id() const { return m_wsrep_next_trx_id; } /* If node is async slave and have parallel execution, wait for prior commits. */ bool wsrep_parallel_slave_wait_for_prior_commit(); private: wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */ /* wsrep-lib */ Wsrep_mutex m_wsrep_mutex; Wsrep_condition_variable m_wsrep_cond; Wsrep_client_service m_wsrep_client_service; Wsrep_client_state m_wsrep_client_state; public: Wsrep_client_state& wsrep_cs() { return m_wsrep_client_state; } const Wsrep_client_state& wsrep_cs() const { return m_wsrep_client_state; } const wsrep::transaction& wsrep_trx() const { return m_wsrep_client_state.transaction(); } const wsrep::streaming_context& wsrep_sr() const { return m_wsrep_client_state.transaction().streaming_context(); } /* Pointer to applier service for streaming THDs. This is needed to be able to delete applier service object in case of background rollback. */ Wsrep_applier_service* wsrep_applier_service; /* wait_for_commit struct for binlog group commit */ wait_for_commit wsrep_wfc; #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ thr_timer_t query_timer; public: void set_query_timer() { #ifndef EMBEDDED_LIBRARY /* Slave vs user threads have timeouts configured via different variables, so pick the appropriate one to use. */ ulonglong timeout_val= slave_thread ? slave_max_statement_time : variables.max_statement_time; /* Don't start a query timer if - If timeouts are not set - if we are in a stored procedure or sub statement - If we already have set a timeout (happens when running prepared statements that calls mysql_execute_command()) */ if (!timeout_val || spcont || in_sub_stmt || query_timer.expired == 0) return; thr_timer_settime(&query_timer, timeout_val); #endif } void reset_query_timer() { #ifndef EMBEDDED_LIBRARY if (spcont || in_sub_stmt) return; if (!query_timer.expired) thr_timer_end(&query_timer); #endif } bool restore_set_statement_var() { return main_lex.restore_set_statement_var(); } /* Copy relevant `stmt` transaction flags to `all` transaction. */ void merge_unsafe_rollback_flags() { if (transaction->stmt.modified_non_trans_table) transaction->all.modified_non_trans_table= TRUE; transaction->all.m_unsafe_rollback_flags|= (transaction->stmt.m_unsafe_rollback_flags & (THD_TRANS::MODIFIED_NON_TRANS_TABLE | THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE | THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL | THD_TRANS::EXECUTED_TABLE_ADMIN_CMD)); } uint get_net_wait_timeout() { if (in_active_multi_stmt_transaction()) { if (transaction->all.is_trx_read_write()) { if (variables.idle_write_transaction_timeout > 0) return variables.idle_write_transaction_timeout; } else { if (variables.idle_readonly_transaction_timeout > 0) return variables.idle_readonly_transaction_timeout; } if (variables.idle_transaction_timeout > 0) return variables.idle_transaction_timeout; } return uint(variables.net_wait_timeout); } /** Switch to a sublex, to parse a substatement or an expression. */ void set_local_lex(sp_lex_local *sublex) { DBUG_ASSERT(lex->sphead); lex= sublex; /* Reset part of parser state which needs this. */ m_parser_state->m_yacc.reset_before_substatement(); } /** Switch back from a sublex (currently pointed by this->lex) to the old lex. Sublex is merged to "oldlex" and this->lex is set to "oldlex". This method is called after parsing a substatement or an expression. set_local_lex() must be previously called. @param oldlex - The old lex which was active before set_local_lex(). @returns - false on success, true on error (failed to merge LEX's). See also sp_head::merge_lex(). */ bool restore_from_local_lex_to_old_lex(LEX *oldlex); Item *sp_fix_func_item(Item **it_addr); Item *sp_fix_func_item_for_assignment(const Field *to, Item **it_addr); Item *sp_prepare_func_item(Item **it_addr, uint cols); bool sp_eval_expr(Field *result_field, Item **expr_item_ptr); bool sql_parser(LEX *old_lex, LEX *lex, char *str, uint str_len, bool stmt_prepare_mode); myf get_utf8_flag() const { return (variables.old_behavior & OLD_MODE_UTF8_IS_UTF8MB3 ? MY_UTF8_IS_UTF8MB3 : 0); } Charset_collation_context charset_collation_context_create_db() const { return Charset_collation_context(variables.collation_server, variables.collation_server); } Charset_collation_context charset_collation_context_alter_db(const char *db); Charset_collation_context charset_collation_context_create_table_in_db(const char *db); Charset_collation_context charset_collation_context_alter_table(const TABLE_SHARE *s); /** Save current lex to the output parameter and reset it to point to main_lex. This method is called from mysql_client_binlog_statement() to temporary @param[out] backup_lex original value of current lex */ void backup_and_reset_current_lex(LEX **backup_lex) { *backup_lex= lex; lex= &main_lex; } /** Restore current lex to its original value it had before calling the method backup_and_reset_current_lex(). @param backup_lex original value of current lex */ void restore_current_lex(LEX *backup_lex) { lex= backup_lex; } bool should_collect_handler_stats() { /* We update handler_stats.active to ensure that we have the same value across the whole statement. This function is only called from TABLE::init() so the value will be the same for the whole statement. */ handler_stats.active= ((variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_ENGINE) || lex->analyze_stmt); return handler_stats.active; } /* Return true if we should create a note when an unusable key is found */ bool give_notes_for_unusable_keys() { return ((variables.note_verbosity & (NOTE_VERBOSITY_UNUSABLE_KEYS)) || (lex->describe && // Is EXPLAIN (variables.note_verbosity & NOTE_VERBOSITY_EXPLAIN))); } bool vers_insert_history_fast(const TABLE *table) { DBUG_ASSERT(table->versioned()); return table->versioned(VERS_TIMESTAMP) && (variables.option_bits & OPTION_INSERT_HISTORY) && lex->duplicates == DUP_ERROR; } bool vers_insert_history(const Field *field) { if (!field->vers_sys_field()) return false; if (!vers_insert_history_fast(field->table)) return false; if (lex->sql_command != SQLCOM_INSERT && lex->sql_command != SQLCOM_INSERT_SELECT && lex->sql_command != SQLCOM_LOAD) return false; return !is_set_timestamp_forbidden(this); } /** @brief Return true if current statement uses cursor protocol for execution. @details Cursor protocol execution is determined by checking if lex->result is a Select_materialize object, which is exclusively used by the server for cursor result set materialization. */ bool is_cursor_execution() const; /* Return true if we are in stored procedure, not in a function or trigger. */ bool in_stored_procedure() { return (lex->sphead != 0 && !(in_sub_stmt & (SUB_STMT_FUNCTION | SUB_STMT_TRIGGER))); } bool reparsing_sp_stmt= {false}; }; /* Start a new independent transaction for the THD. The old one is stored in this object and restored when calling restore_old_transaction() or when the object is freed */ class start_new_trans { /* container for handler's private per-connection data */ Ha_data old_ha_data[MAX_HA]; struct THD::st_transactions *old_transaction, new_transaction; Open_tables_backup open_tables_state_backup; MDL_savepoint mdl_savepoint; PSI_transaction_locker *m_transaction_psi; THD *org_thd; uint in_sub_stmt; uint server_status; my_bool wsrep_on; public: start_new_trans(THD *thd); ~start_new_trans() { destroy(); } void destroy() { if (org_thd) // Safety restore_old_transaction(); new_transaction.free(); } void restore_old_transaction(); }; /** A short cut for thd->get_stmt_da()->set_ok_status(). */ inline void my_ok(THD *thd, ulonglong affected_rows_arg= 0, ulonglong id= 0, const char *message= NULL) { thd->set_row_count_func(affected_rows_arg); thd->set_affected_rows(affected_rows_arg); thd->get_stmt_da()->set_ok_status(affected_rows_arg, id, message); } /** A short cut for thd->get_stmt_da()->set_eof_status(). */ inline void my_eof(THD *thd) { thd->set_row_count_func(-1); thd->get_stmt_da()->set_eof_status(thd); TRANSACT_TRACKER(add_trx_state(thd, TX_RESULT_SET)); } #define tmp_disable_binlog(A) \ {ulonglong tmp_disable_binlog__save_options= (A)->variables.option_bits; \ (A)->variables.option_bits&= ~OPTION_BIN_LOG; \ (A)->variables.option_bits|= OPTION_BIN_TMP_LOG_OFF; #define reenable_binlog(A) \ (A)->variables.option_bits= tmp_disable_binlog__save_options; } inline date_conv_mode_t sql_mode_for_dates(THD *thd) { static_assert((ulonglong(date_conv_mode_t::KNOWN_MODES) & ulonglong(time_round_mode_t::KNOWN_MODES)) == 0, "date_conv_mode_t and time_round_mode_t must use different " "bit values"); static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE && MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE && MODE_INVALID_DATES == date_mode_t::INVALID_DATES, "sql_mode_t and date_mode_t values must be equal"); return date_conv_mode_t(thd->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_INVALID_DATES)); } /* Used to hold information about file and file structure in exchange via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) XXX: We never call destructor for objects of this class. */ class sql_exchange :public Sql_alloc { public: enum enum_filetype filetype; /* load XML, Added by Arnold & Erik */ const char *file_name; String *field_term,*enclosed,*line_term,*line_start,*escaped; bool opt_enclosed; bool dumpfile; ulong skip_lines; CHARSET_INFO *cs; sql_exchange(const char *name, bool dumpfile_flag, enum_filetype filetype_arg= FILETYPE_CSV); bool escaped_given(void) const; }; /* This is used to get result from a select */ class JOIN; /* Pure interface for sending tabular data */ class select_result_sink: public Sql_alloc { public: THD *thd; select_result_sink(THD *thd_arg): thd(thd_arg) {} inline int send_data_with_check(List<Item> &items, SELECT_LEX_UNIT *u, ha_rows sent) { if (u->lim.check_offset(sent)) return 0; if (u->thd->killed == ABORT_QUERY) return 0; return send_data(items); } /* send_data returns 0 on ok, 1 on error and -1 if data was ignored, for example for a duplicate row entry written to a temp table. */ virtual int send_data(List<Item> &items)=0; virtual ~select_result_sink() = default; // Used in cursors to initialize and reset void reinit(THD *thd_arg) { thd= thd_arg; } }; class select_result_interceptor; /* Interface for sending tabular data, together with some other stuff: - Primary purpose seems to be seding typed tabular data: = the DDL is sent with send_fields() = the rows are sent with send_data() Besides that, - there seems to be an assumption that the sent data is a result of SELECT_LEX_UNIT *unit, - nest_level is used by SQL parser */ class select_result :public select_result_sink { protected: /* All descendant classes have their send_data() skip the first unit->offset_limit_cnt rows sent. Select_materialize also uses unit->get_column_types(). */ SELECT_LEX_UNIT *unit; /* Something used only by the parser: */ public: ha_rows est_records; /* estimated number of records in the result */ select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {} void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } virtual ~select_result() = default; /** Change wrapped select_result. Replace the wrapped result object with new_result and call prepare() and prepare2() on new_result. This base class implementation doesn't wrap other select_results. @param new_result The new result object to wrap around @retval false Success @retval true Error */ virtual bool change_result(select_result *new_result) { return false; } virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u) { unit= u; return 0; } virtual int prepare2(JOIN *join) { return 0; } /* Because of peculiarities of prepared statements protocol we need to know number of columns in the result set (if there is a result set) apart from sending columns metadata. */ virtual uint field_count(List<Item> &fields) const { return fields.elements; } virtual bool send_result_set_metadata(List<Item> &list, uint flags)=0; virtual bool initialize_tables (JOIN *join) { return 0; } virtual bool send_eof()=0; /** Check if this query returns a result set and therefore is allowed in cursors and set an error message if it is not the case. @retval FALSE success @retval TRUE error, an error message is set */ virtual bool check_simple_select() const; virtual void abort_result_set() {} virtual void reset_for_next_ps_execution(); void set_thd(THD *thd_arg) { thd= thd_arg; } void reinit(THD *thd_arg) { select_result_sink::reinit(thd_arg); unit= NULL; } #ifdef EMBEDDED_LIBRARY virtual void begin_dataset() {} #else void begin_dataset() {} #endif virtual void update_used_tables() {} /* this method is called just before the first row of the table can be read */ virtual void prepare_to_read_rows() {} void remove_offset_limit() { unit->lim.remove_offset(); } /* This returns - NULL if the class sends output row to the client - this if the output is set elsewhere (a file, @variable, or table). */ virtual select_result_interceptor *result_interceptor()=0; /* This method is used to distinguish an normal SELECT from the cursor structure discovery for cursor%ROWTYPE routine variables. If this method returns "true", then a SELECT execution performs only all preparation stages, but does not fetch any rows. */ virtual bool view_structure_only() const { return false; } }; /* This is a select_result_sink which simply writes all data into a (temporary) table. Creation/deletion of the table is outside of the scope of the class It is aimed at capturing SHOW EXPLAIN output, so: - Unlike select_result class, we don't assume that the sent data is an output of a SELECT_LEX_UNIT (and so we don't apply "LIMIT x,y" from the unit) - We don't try to convert the target table to MyISAM */ class select_result_explain_buffer : public select_result_sink { public: select_result_explain_buffer(THD *thd_arg, TABLE *table_arg) : select_result_sink(thd_arg), dst_table(table_arg) {}; TABLE *dst_table; /* table to write into */ /* The following is called in the child thread: */ int send_data(List<Item> &items) override; }; /* This is a select_result_sink which stores the data in text form. It is only used to save EXPLAIN output. */ class select_result_text_buffer : public select_result_sink { public: select_result_text_buffer(THD *thd_arg): select_result_sink(thd_arg) {} int send_data(List<Item> &items) override; bool send_result_set_metadata(List<Item> &fields, uint flag); void save_to(String *res); private: int append_row(List<Item> &items, bool send_names); List<char*> rows; int n_columns; }; /* Base class for select_result descendands which intercept and transform result set rows. As the rows are not sent to the client, sending of result set metadata should be suppressed as well. */ class select_result_interceptor: public select_result { public: select_result_interceptor(THD *thd_arg): select_result(thd_arg), suppress_my_ok(false) { DBUG_ENTER("select_result_interceptor::select_result_interceptor"); DBUG_PRINT("enter", ("this %p", this)); DBUG_VOID_RETURN; } /* Remove gcc warning */ uint field_count(List<Item> &fields) const override { return 0; } bool send_result_set_metadata(List<Item> &fields, uint flag) override { return FALSE; } select_result_interceptor *result_interceptor() override { return this; } /* Instruct the object to not call my_ok(). Client output will be handled elsewhere. (this is used by ANALYZE $stmt feature). */ void disable_my_ok_calls() { suppress_my_ok= true; } void reinit(THD *thd_arg) { select_result::reinit(thd_arg); suppress_my_ok= false; } protected: bool suppress_my_ok; }; class sp_cursor_statistics { protected: ulonglong m_fetch_count; // Number of FETCH commands since last OPEN ulonglong m_row_count; // Number of successful FETCH since last OPEN bool m_found; // If last FETCH fetched a row public: sp_cursor_statistics() :m_fetch_count(0), m_row_count(0), m_found(false) { } bool found() const { return m_found; } ulonglong row_count() const { return m_row_count; } ulonglong fetch_count() const { return m_fetch_count; } void reset() { *this= sp_cursor_statistics(); } }; class sp_instr_cpush; /* A mediator between stored procedures and server side cursors */ class sp_lex_keeper; class sp_cursor: public sp_cursor_statistics { private: /// An interceptor of cursor result set used to implement /// FETCH <cname> INTO <varlist>. class Select_fetch_into_spvars: public select_result_interceptor { List<sp_fetch_target> *m_fetch_target_list; uint field_count; bool m_view_structure_only; bool send_data_to_variable_list(List<sp_fetch_target> &vars, List<Item> &items); public: Select_fetch_into_spvars(THD *thd_arg, bool view_structure_only) :select_result_interceptor(thd_arg), m_view_structure_only(view_structure_only) {} void reset(THD *thd_arg) { select_result_interceptor::reinit(thd_arg); m_fetch_target_list= NULL; field_count= 0; } uint get_field_count() { return field_count; } void set_spvar_list(List<sp_fetch_target> *vars) { m_fetch_target_list= vars; } bool send_eof() override { return FALSE; } int send_data(List<Item> &items) override; int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; bool view_structure_only() const override { return m_view_structure_only; } }; public: sp_cursor() :result(NULL, false), server_side_cursor(NULL) { } sp_cursor(THD *thd_arg, bool view_structure_only) :result(thd_arg, view_structure_only), server_side_cursor(NULL) {} virtual ~sp_cursor() { destroy(); } virtual sp_lex_keeper *get_lex_keeper() { return nullptr; } int open(THD *thd); int close(THD *thd); my_bool is_open() { return MY_TEST(server_side_cursor); } int fetch(THD *, List<sp_fetch_target> *vars, bool error_on_no_data); bool export_structure(THD *thd, Row_definition_list *list); void reset(THD *thd_arg) { sp_cursor_statistics::reset(); result.reinit(thd_arg); server_side_cursor= NULL; } virtual sp_instr_cpush *get_push_instr() { return nullptr; } private: Select_fetch_into_spvars result; Server_side_cursor *server_side_cursor; void destroy(); }; class select_send :public select_result { /** True if we have sent result set metadata to the client. In this case the client always expects us to end the result set with an eof or error packet */ bool is_result_set_started; public: select_send(THD *thd_arg): select_result(thd_arg), is_result_set_started(FALSE) {} bool send_result_set_metadata(List<Item> &list, uint flags) override; int send_data(List<Item> &items) override; bool send_eof() override; bool check_simple_select() const override { return FALSE; } void abort_result_set() override; void reset_for_next_ps_execution() override; select_result_interceptor *result_interceptor() override { return NULL; } }; /* We need this class, because select_send::send_eof() will call ::my_eof. See also class Protocol_discard. */ class select_send_analyze : public select_send { bool send_result_set_metadata(List<Item> &list, uint flags) override { return 0; } bool send_eof() override { return 0; } void abort_result_set() override {} public: select_send_analyze(THD *thd_arg): select_send(thd_arg) {} }; class select_to_file :public select_result_interceptor { protected: sql_exchange *exchange; File file; IO_CACHE cache; ha_rows row_count; char path[FN_REFLEN]; public: select_to_file(THD *thd_arg, sql_exchange *ex): select_result_interceptor(thd_arg), exchange(ex), file(-1),row_count(0L) { path[0]=0; } ~select_to_file(); bool send_eof() override; void abort_result_set() override; void reset_for_next_ps_execution() override; bool free_recources(); }; #define ESCAPE_CHARS "ntrb0ZN" // keep synchronous with READ_INFO::unescape /* List of all possible characters of a numeric value text representation. */ #define NUMERIC_CHARS ".0123456789e+-" class select_export :public select_to_file { uint field_term_length; int field_sep_char,escape_char,line_sep_char; int field_term_char; // first char of FIELDS TERMINATED BY or MAX_INT /* The is_ambiguous_field_sep field is true if a value of the field_sep_char field is one of the 'n', 't', 'r' etc characters (see the READ_INFO::unescape method and the ESCAPE_CHARS constant value). */ bool is_ambiguous_field_sep; /* The is_ambiguous_field_term is true if field_sep_char contains the first char of the FIELDS TERMINATED BY (ENCLOSED BY is empty), and items can contain this character. */ bool is_ambiguous_field_term; /* The is_unsafe_field_sep field is true if a value of the field_sep_char field is one of the '0'..'9', '+', '-', '.' and 'e' characters (see the NUMERIC_CHARS constant value). */ bool is_unsafe_field_sep; bool fixed_row_size; CHARSET_INFO *write_cs; // output charset public: select_export(THD *thd_arg, sql_exchange *ex): select_to_file(thd_arg, ex) {} ~select_export(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int send_data(List<Item> &items) override; }; class select_dump :public select_to_file { public: select_dump(THD *thd_arg, sql_exchange *ex): select_to_file(thd_arg, ex) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int send_data(List<Item> &items) override; }; class Write_record; // defined in sql_insert.h class select_insert :public select_result_interceptor { public: select_result *sel_result; TABLE_LIST *table_list; TABLE *table; List<Item> *fields; Write_record *write; ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not COPY_INFO info; bool insert_into_view; select_insert(THD *thd_arg, TABLE_LIST *table_list_par, TABLE *table_par, List<Item> *fields_par, List<Item> *update_fields, List<Item> *update_values, enum_duplicates duplic, bool ignore, select_result *sel_ret_list, Write_record *write); ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int prepare2(JOIN *join) override; int send_data(List<Item> &items) override; virtual bool store_values(List<Item> &values); virtual bool can_rollback_data() { return 0; } bool prepare_eof(); bool send_ok_packet(); bool send_eof() override; void abort_result_set() override; /* not implemented: select_insert is never re-used in prepared statements */ void reset_for_next_ps_execution() override; }; class select_create: public select_insert { Table_specification_st *create_info; TABLE_LIST *select_tables; Alter_info *alter_info; Field **field; /* lock data for tmp table */ MYSQL_LOCK *m_lock; /* m_lock or thd->extra_lock */ MYSQL_LOCK **m_plock; bool exit_done; TMP_TABLE_SHARE *saved_tmp_table_share; DDL_LOG_STATE ddl_log_state_create, ddl_log_state_rm; public: select_create(THD *thd_arg, TABLE_LIST *table_arg, Table_specification_st *create_info_par, Alter_info *alter_info_arg, List<Item> &select_fields,enum_duplicates duplic, bool ignore, TABLE_LIST *select_tables_arg, Write_record *write): select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic, ignore, NULL, write), create_info(create_info_par), select_tables(select_tables_arg), alter_info(alter_info_arg), m_plock(NULL), exit_done(0), saved_tmp_table_share(0) { DBUG_ASSERT(create_info->default_table_charset); bzero(&ddl_log_state_create, sizeof(ddl_log_state_create)); bzero(&ddl_log_state_rm, sizeof(ddl_log_state_rm)); } int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int binlog_show_create_table(TABLE **tables, uint count); bool store_values(List<Item> &values) override; bool send_eof() override; void abort_result_set() override; bool can_rollback_data() override { return 1; } // Needed for access from local class MY_HOOKS in prepare(), since thd is proteted. const THD *get_thd(void) { return thd; } const HA_CREATE_INFO *get_create_info() { return create_info; }; int prepare2(JOIN *join) override { return 0; } private: TABLE *create_table_from_items(THD *thd, List<Item> *items, MYSQL_LOCK **lock); int postlock(THD *thd, TABLE **tables); }; #include <myisam.h> #ifdef WITH_ARIA_STORAGE_ENGINE #include <maria.h> #else #undef USE_ARIA_FOR_TMP_TABLES #endif #ifdef USE_ARIA_FOR_TMP_TABLES #define TMP_ENGINE_COLUMNDEF MARIA_COLUMNDEF #define TMP_ENGINE_HTON maria_hton #define TMP_ENGINE_NAME "Aria" inline uint tmp_table_max_key_length() { return maria_max_key_length(); } inline uint tmp_table_max_key_parts() { return maria_max_key_segments(); } #else #define TMP_ENGINE_COLUMNDEF MI_COLUMNDEF #define TMP_ENGINE_HTON myisam_hton #define TMP_ENGINE_NAME "MyISAM" inline uint tmp_table_max_key_length() { return MI_MAX_KEY_LENGTH; } inline uint tmp_table_max_key_parts() { return MI_MAX_KEY_SEG; } #endif /* Param to create temporary tables when doing SELECT:s NOTE This structure is copied using memcpy as a part of JOIN. */ class TMP_TABLE_PARAM :public Sql_alloc { public: List<Item> copy_funcs; Copy_field *copy_field, *copy_field_end; uchar *group_buff; const char *tmp_name; Item **items_to_copy; /* Fields in tmp table */ TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo; KEY *keyinfo; ulong *rec_per_key; ha_rows end_write_records; /** Number of normal fields in the query, including those referred to from aggregate functions. Hence, "SELECT `field1`, SUM(`field2`) from t1" sets this counter to 2. @see count_field_types */ uint field_count; /** Number of fields in the query that have functions. Includes both aggregate functions (e.g., SUM) and non-aggregates (e.g., RAND). Also counts functions referred to from aggregate functions, i.e., "SELECT SUM(RAND())" sets this counter to 2. @see count_field_types */ uint func_count; /** Number of fields in the query that have aggregate functions. Note that the optimizer may choose to optimize away these fields by replacing them with constants, in which case sum_func_count will need to be updated. @see opt_sum_query, count_field_types */ uint sum_func_count; uint copy_func_count; // Allocated copy fields uint hidden_field_count; uint group_parts,group_length,group_null_parts; /* If we're doing a GROUP BY operation, shows which one is used: true TemporaryTableWithPartialSums algorithm (see end_update()). false OrderedGroupBy algorithm (see end_write_group()). */ uint quick_group; /** Enabled when we have atleast one outer_sum_func. Needed when used along with distinct. @see create_tmp_table */ bool using_outer_summary_function; CHARSET_INFO *table_charset; bool schema_table; /* TRUE if the temp table is created for subquery materialization. */ bool materialized_subquery; /* TRUE if all columns of the table are guaranteed to be non-nullable */ bool force_not_null_cols; /* True if GROUP BY and its aggregate functions are already computed by a table access method (e.g. by loose index scan). In this case query execution should not perform aggregation and should treat aggregate functions as normal functions. */ bool precomputed_group_by; bool group_concat; bool force_copy_fields; /* If TRUE, create_tmp_field called from create_tmp_table will convert all BIT fields to 64-bit longs. This is a workaround the limitation that MEMORY tables cannot index BIT columns. */ bool bit_fields_as_long; /* Whether to create or postpone actual creation of this temporary table. TRUE <=> create_tmp_table will create only the TABLE structure. */ bool skip_create_table; TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0), group_null_parts(0), using_outer_summary_function(0), schema_table(0), materialized_subquery(0), force_not_null_cols(0), precomputed_group_by(0), group_concat(0), force_copy_fields(0), bit_fields_as_long(0), skip_create_table(0) { init(); } ~TMP_TABLE_PARAM() { cleanup(); } void init(void); inline void cleanup(void) { if (copy_field) /* Fix for Intel compiler */ { delete [] copy_field; copy_field= NULL; copy_field_end= NULL; } } }; class select_unit :public select_result_interceptor { protected: uint curr_step, prev_step, curr_sel; enum sub_select_type step; public: TMP_TABLE_PARAM tmp_table_param; /* Number of additional (hidden) field of the used temporary table */ int addon_cnt; int write_err; /* Error code from the last send_data->ha_write_row call. */ TABLE *table; select_unit(THD *thd_arg): select_result_interceptor(thd_arg), addon_cnt(0), table(0) { init(); tmp_table_param.init(); } int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; /** Do prepare() and prepare2() if they have been postponed until column type information is computed (used by select_union_direct). @param types Column types @return false on success, true on failure */ virtual bool postponed_prepare(List<Item> &types) { return false; } int send_data(List<Item> &items) override; int write_record(); int update_counter(Field *counter, longlong value); int delete_record(); bool send_eof() override; virtual bool flush(); void reset_for_next_ps_execution() override; virtual bool create_result_table(THD *thd, List<Item> *column_types, bool is_distinct, ulonglong options, const LEX_CSTRING *alias, bool bit_fields_as_long, bool create_table, bool keep_row_order, uint hidden); TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; } void init() { curr_step= prev_step= 0; curr_sel= UINT_MAX; step= UNION_TYPE; write_err= 0; } virtual void change_select(); virtual bool force_enable_index_if_needed() { return false; } }; /** @class select_unit_ext The class used when processing rows produced by operands of query expressions containing INTERSECT ALL and/or EXCEPT all operations. One or two extra fields of the temporary to store the rows of the partial and final result can be employed. Both of them contain counters. The second additional field is used only when the processed query expression contains INTERSECT ALL. Consider how these extra fields are used. Let table t1 (f char(8)) table t2 (f char(8)) table t3 (f char(8)) contain the following sets: ("b"),("a"),("d"),("c"),("b"),("a"),("c"),("a") ("c"),("b"),("c"),("c"),("a"),("b"),("g") ("c"),("a"),("b"),("d"),("b"),("e") - Let's demonstrate how the set operation INTERSECT ALL is proceesed for the query SELECT f FROM t1 INTERSECT ALL SELECT f FROM t2 When send_data() is called for the rows of the first operand we put the processed record into the temporary table if there was no such record setting dup_cnt field to 1 and add_cnt field to 0 and increment the counter in the dup_cnt field by one otherwise. We get |add_cnt|dup_cnt| f | |0 |2 |b | |0 |3 |a | |0 |1 |d | |0 |2 |c | The call of send_eof() for the first operand swaps the values stored in dup_cnt and add_cnt. After this, we'll see the following rows in the temporary table |add_cnt|dup_cnt| f | |2 |0 |b | |3 |0 |a | |1 |0 |d | |2 |0 |c | When send_data() is called for the rows of the second operand we increment the counter in dup_cnt if the processed row is found in the table and do nothing otherwise. As a result we get |add_cnt|dup_cnt| f | |2 |2 |b | |3 |1 |a | |1 |0 |d | |2 |3 |c | At the call of send_eof() for the second operand first we disable index. Then for each record, the minimum of counters from dup_cnt and add_cnt m is taken. If m == 0 then the record is deleted. Otherwise record is replaced with m copies of it. Yet the counter in this copies are set to 1 for dup_cnt and to 0 for add_cnt |add_cnt|dup_cnt| f | |0 |1 |b | |0 |1 |b | |0 |1 |a | |0 |1 |c | |0 |1 |c | - Let's demonstrate how the set operation EXCEPT ALL is proceesed for the query SELECT f FROM t1 EXCEPT ALL SELECT f FROM t3 Only one additional counter field dup_cnt is used for EXCEPT ALL. After the first operand has been processed we have in the temporary table |dup_cnt| f | |2 |b | |3 |a | |1 |d | |2 |c | When send_data() is called for the rows of the second operand we decrement the counter in dup_cnt if the processed row is found in the table and do nothing otherwise. If the counter becomes 0 we delete the record |dup_cnt| f | |2 |a | |1 |c | Finally at the call of send_eof() for the second operand we disable index unfold rows adding duplicates |dup_cnt| f | |1 |a | |1 |a | |1 |c | */ class select_unit_ext :public select_unit { public: select_unit_ext(THD *thd_arg): select_unit(thd_arg), increment(0), is_index_enabled(TRUE), curr_op_type(UNSPECIFIED) { }; int send_data(List<Item> &items) override; void change_select() override; int unfold_record(ha_rows cnt); bool send_eof() override; bool force_enable_index_if_needed() override { is_index_enabled= true; return true; } bool disable_index_if_needed(SELECT_LEX *curr_sl); /* How to change increment/decrement the counter in duplicate_cnt field when processing a record produced by the current operand in send_data(). The value can be 1 or -1 */ int increment; /* TRUE <=> the index of the result temporary table is enabled */ bool is_index_enabled; /* The type of the set operation currently executed */ enum set_op_type curr_op_type; /* Points to the extra field of the temporary table where duplicate counters are stored */ Field *duplicate_cnt; /* Points to the extra field of the temporary table where additional counters used only for INTERSECT ALL operations are stored */ Field *additional_cnt; }; class select_union_recursive :public select_unit { public: /* The temporary table with the new records generated by one iterative step */ TABLE *incr_table; /* The TMP_TABLE_PARAM structure used to create incr_table */ TMP_TABLE_PARAM incr_table_param; /* One of tables from the list rec_tables (determined dynamically) */ TABLE *first_rec_table_to_update; /* The list of all recursive table references to the CTE for whose specification this select_union_recursive was created */ List<TABLE_LIST> rec_table_refs; /* The count of how many times reset_for_next_ps_execution() was called with cleaned==false for the unit specifying the recursive CTE for which this object was created or for the unit specifying a CTE that mutually recursive with this CTE. */ uint cleanup_count; long row_counter; select_union_recursive(THD *thd_arg): select_unit(thd_arg), incr_table(0), first_rec_table_to_update(0), cleanup_count(0), row_counter(0) { incr_table_param.init(); }; int send_data(List<Item> &items) override; bool create_result_table(THD *thd, List<Item> *column_types, bool is_distinct, ulonglong options, const LEX_CSTRING *alias, bool bit_fields_as_long, bool create_table, bool keep_row_order, uint hidden) override; void reset_for_next_ps_execution() override; }; /** UNION result that is passed directly to the receiving select_result without filling a temporary table. Function calls are forwarded to the wrapped select_result, but some functions are expected to be called only once for each query, so they are only executed for the first SELECT in the union (execept for send_eof(), which is executed only for the last SELECT). This select_result is used when a UNION is not DISTINCT and doesn't have a global ORDER BY clause. @see st_select_lex_unit::prepare(). */ class select_union_direct :public select_unit { private: /* Result object that receives all rows */ select_result *result; /* The last SELECT_LEX of the union */ SELECT_LEX *last_select_lex; /* Wrapped result has received metadata */ bool done_send_result_set_metadata; /* Wrapped result has initialized tables */ bool done_initialize_tables; /* Accumulated limit_found_rows */ ulonglong limit_found_rows; /* Number of rows offset */ ha_rows offset; /* Number of rows limit + offset, @see select_union_direct::send_data() */ ha_rows limit; public: /* Number of rows in the union */ ha_rows send_records; select_union_direct(THD *thd_arg, select_result *result_arg, SELECT_LEX *last_select_lex_arg): select_unit(thd_arg), result(result_arg), last_select_lex(last_select_lex_arg), done_send_result_set_metadata(false), done_initialize_tables(false), limit_found_rows(0) { send_records= 0; } bool change_result(select_result *new_result) override; uint field_count(List<Item> &fields) const override { // Only called for top-level select_results, usually select_send DBUG_ASSERT(false); /* purecov: inspected */ return 0; /* purecov: inspected */ } bool postponed_prepare(List<Item> &types) override; bool send_result_set_metadata(List<Item> &list, uint flags) override; int send_data(List<Item> &items) override; bool initialize_tables (JOIN *join) override; bool send_eof() override; bool flush() override { return false; } bool check_simple_select() const override { /* Only called for top-level select_results, usually select_send */ DBUG_ASSERT(false); /* purecov: inspected */ return false; /* purecov: inspected */ } void abort_result_set() override { result->abort_result_set(); /* purecov: inspected */ } void reset_for_next_ps_execution() override { send_records= 0; } void set_thd(THD *thd_arg) { /* Only called for top-level select_results, usually select_send, and for the results of subquery engines (select_<something>_subselect). */ DBUG_ASSERT(false); /* purecov: inspected */ } void remove_offset_limit() { // EXPLAIN should never output to a select_union_direct DBUG_ASSERT(false); /* purecov: inspected */ } #ifdef EMBEDDED_LIBRARY void begin_dataset() override #else void begin_dataset() #endif { // Only called for sp_cursor::Select_fetch_into_spvars DBUG_ASSERT(false); /* purecov: inspected */ } }; /* Base subselect interface class */ class select_subselect :public select_result_interceptor { protected: Item_subselect *item; public: select_subselect(THD *thd_arg, Item_subselect *item_arg): select_result_interceptor(thd_arg), item(item_arg) {} int send_data(List<Item> &items) override=0; bool send_eof() override { return 0; }; }; /* Single value subselect interface class */ class select_singlerow_subselect :public select_subselect { public: select_singlerow_subselect(THD *thd_arg, Item_subselect *item_arg): select_subselect(thd_arg, item_arg) {} int send_data(List<Item> &items) override; }; /* This class specializes select_union to collect statistics about the data stored in the temp table. Currently the class collects statistcs about NULLs. */ class select_materialize_with_stats : public select_unit { protected: class Column_statistics { public: /* Count of NULLs per column. */ ha_rows null_count; /* The row number that contains the first NULL in a column. */ ha_rows min_null_row; /* The row number that contains the last NULL in a column. */ ha_rows max_null_row; }; /* Array of statistics data per column. */ Column_statistics* col_stat; /* The number of columns in the biggest sub-row that consists of only NULL values. */ uint max_nulls_in_row; /* Count of rows writtent to the temp table. This is redundant as it is already stored in handler::stats.records, however that one is relatively expensive to compute (given we need that for evry row). */ ha_rows count_rows; protected: void reset(); public: select_materialize_with_stats(THD *thd_arg): select_unit(thd_arg) { tmp_table_param.init(); } bool create_result_table(THD *thd, List<Item> *column_types, bool is_distinct, ulonglong options, const LEX_CSTRING *alias, bool bit_fields_as_long, bool create_table, bool keep_row_order, uint hidden) override; bool init_result_table(ulonglong select_options); int send_data(List<Item> &items) override; void reset_for_next_ps_execution() override; ha_rows get_null_count_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); return col_stat[idx].null_count; } ha_rows get_max_null_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); return col_stat[idx].max_null_row; } ha_rows get_min_null_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); return col_stat[idx].min_null_row; } uint get_max_nulls_in_row() { return max_nulls_in_row; } }; /* used in independent ALL/ANY optimisation */ class select_max_min_finder_subselect :public select_subselect { Item_cache *cache; bool (select_max_min_finder_subselect::*op)(); bool fmax; bool is_all; void set_op(const Type_handler *ha); public: select_max_min_finder_subselect(THD *thd_arg, Item_subselect *item_arg, bool mx, bool all): select_subselect(thd_arg, item_arg), cache(0), fmax(mx), is_all(all) {} void reset_for_next_ps_execution() override; int send_data(List<Item> &items) override; bool cmp_real(); bool cmp_int(); bool cmp_decimal(); bool cmp_str(); bool cmp_time(); bool cmp_native(); }; /* EXISTS subselect interface class */ class select_exists_subselect :public select_subselect { public: select_exists_subselect(THD *thd_arg, Item_subselect *item_arg): select_subselect(thd_arg, item_arg) {} int send_data(List<Item> &items) override; }; /* Optimizer and executor structure for the materialized semi-join info. This structure contains - The sj-materialization temporary table - Members needed to make index lookup or a full scan of the temptable. */ class POSITION; class SJ_MATERIALIZATION_INFO : public Sql_alloc { public: /* Optimal join sub-order */ POSITION *positions; uint tables; /* Number of tables in the sj-nest */ /* Number of rows in the materialized table, before the de-duplication */ double rows_with_duplicates; /* Expected #rows in the materialized table, after de-duplication */ double rows; /* Cost to materialize - execute the sub-join and write rows into temp.table */ double materialization_cost; /* Cost to make one lookup in the temptable */ double lookup_cost; /* Cost of scanning the materialized table */ double scan_cost; /* --- Execution structures ---------- */ /* TRUE <=> This structure is used for execution. We don't necessarily pick sj-materialization, so some of SJ_MATERIALIZATION_INFO structures are not used by materialization */ bool is_used; bool materialized; /* TRUE <=> materialization already performed */ /* TRUE - the temptable is read with full scan FALSE - we use the temptable for index lookups */ bool is_sj_scan; /* The temptable and its related info */ TMP_TABLE_PARAM sjm_table_param; List<Item> sjm_table_cols; TABLE *table; /* Structure used to make index lookups */ struct st_table_ref *tab_ref; Item *in_equality; /* See create_subq_in_equalities() */ Item *join_cond; /* See comments in make_join_select() */ Copy_field *copy_field; /* Needed for SJ_Materialization scan */ }; /* Structs used when sorting */ struct SORT_FIELD_ATTR { /* If using mem-comparable fixed-size keys: length of the mem-comparable image of the field, in bytes. If using packed keys: still the same? Not clear what is the use of it. */ uint length; /* For most datatypes, this is 0. The exception are the VARBINARY columns. For those columns, the comparison actually compares (value_prefix(N), suffix=length(value)) Here value_prefix is either the whole value or its prefix if it was too long, and the suffix is the length of the original value. (this way, for values X and Y: if X=prefix(Y) then X compares as less than Y */ uint suffix_length; /* If using packed keys, number of bytes that are used to store the length of the packed key. */ uint length_bytes; /* Max. length of the original value, in bytes */ uint original_length; enum Type { FIXED_SIZE, VARIABLE_SIZE } type; /* TRUE : if the item or field is NULLABLE FALSE : otherwise */ bool maybe_null; CHARSET_INFO *cs; uint pack_sort_string(uchar *to, const Binary_string *str, CHARSET_INFO *cs) const; int compare_packed_fixed_size_vals(const uchar *a, size_t *a_len, const uchar *b, size_t *b_len); int compare_packed_varstrings(const uchar *a, size_t *a_len, const uchar *b, size_t *b_len); bool check_if_packing_possible(THD *thd) const; bool is_variable_sized() { return type == VARIABLE_SIZE; } void set_length_and_original_length(THD *thd, uint length_arg); }; struct SORT_FIELD: public SORT_FIELD_ATTR { Field *field; /* Field to sort */ Item *item; /* Item if not sorting fields */ bool reverse; /* if descending sort */ }; typedef struct st_sort_buffer { uint index; /* 0 or 1 */ uint sort_orders; uint change_pos; /* If sort-fields changed */ char **buff; SORT_FIELD *sortorder; } SORT_BUFFER; /* Structure for db & table in sql_yacc */ class Table_ident :public Sql_alloc { public: LEX_CSTRING db; LEX_CSTRING table; SELECT_LEX_UNIT *sel; inline Table_ident(THD *thd, const LEX_CSTRING *db_arg, const LEX_CSTRING *table_arg, bool force) :table(*table_arg), sel((SELECT_LEX_UNIT *)0) { if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA)) db= null_clex_str; else db= *db_arg; } inline Table_ident(const LEX_CSTRING *table_arg) :table(*table_arg), sel((SELECT_LEX_UNIT *)0) { db= null_clex_str; } /* This constructor is used only for the case when we create a derived table. A derived table has no name and doesn't belong to any database. Later, if there was an alias specified for the table, it will be set by add_table_to_list. */ inline Table_ident(SELECT_LEX_UNIT *s) : sel(s) { /* We must have a table name here as this is used with add_table_to_list */ db.str= empty_c_string; /* a subject to casedn_str */ db.length= 0; table.str= internal_table_name; table.length=1; } bool is_derived_table() const { return MY_TEST(sel); } inline void change_db(LEX_CSTRING *db_name) { db= *db_name; } bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs); bool append_to(THD *thd, String *to) const; /* Convert Table_ident::m_db to a valid internal database name: - validated with Lex_ident_fs::check_db_name() - optionally lower-cased when lower_case_table_names==1 @param arena - the arena to allocate the lower-cased copy on, when needed. @return {NULL,0} in case of EOM or invalid database name, or a good identifier otherwise. */ Lex_ident_db to_ident_db_internal_with_error(Query_arena *arena) const; }; class Qualified_column_ident: public Table_ident { public: LEX_CSTRING m_column; public: Qualified_column_ident(const LEX_CSTRING *column) :Table_ident(&null_clex_str), m_column(*column) { } Qualified_column_ident(const LEX_CSTRING *table, const LEX_CSTRING *column) :Table_ident(table), m_column(*column) { } Qualified_column_ident(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table, const LEX_CSTRING *column) :Table_ident(thd, db, table, false), m_column(*column) { } bool resolve_type_ref(THD *thd, Column_definition *def) const; bool append_to(THD *thd, String *to) const; }; // this is needed for user_vars hash class user_var_entry: public Type_handler_hybrid_field_type { CHARSET_INFO *m_charset; public: user_var_entry() = default; /* Remove gcc warning */ LEX_CSTRING name; char *value; size_t length; query_id_t update_query_id, used_query_id; double val_real(bool *null_value); longlong val_int(bool *null_value) const; String *val_str(bool *null_value, String *str, uint decimals) const; my_decimal *val_decimal(bool *null_value, my_decimal *result); CHARSET_INFO *charset() const { return m_charset; } void set_charset(CHARSET_INFO *cs) { m_charset= cs; } }; user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, bool create_if_not_exists); class SORT_INFO; class multi_delete :public select_result_interceptor { TABLE_LIST *delete_tables, *table_being_deleted; Unique **tempfiles; ha_rows deleted, found; uint num_of_tables; int error; bool do_delete; /* True if at least one table we delete from is transactional */ bool transactional_tables; /* True if at least one table we delete from is not transactional */ bool normal_tables; bool delete_while_scanning; /* error handling (rollback and binlogging) can happen in send_eof() so that afterward abort_result_set() needs to find out that. */ bool error_handled; public: // Methods used by ColumnStore uint get_num_of_tables() const { return num_of_tables; } TABLE_LIST* get_tables() const { return delete_tables; } public: multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int send_data(List<Item> &items) override; bool initialize_tables (JOIN *join) override; int do_deletes(); int do_table_deletes(TABLE *table, SORT_INFO *sort_info, bool ignore); bool send_eof() override; inline ha_rows num_deleted() const { return deleted; } void abort_result_set() override; void prepare_to_read_rows() override; }; class multi_update :public select_result_interceptor { TABLE_LIST *all_tables; /* query/update command tables */ List<TABLE_LIST> *leaves; /* list of leaves of join table tree */ List<TABLE_LIST> updated_leaves; /* list of updated leaves */ TABLE_LIST *update_tables; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; ha_rows updated, found; List <Item> *fields, *values; List <Item> **fields_for_table, **values_for_table; uint table_count; /* List of tables referenced in the CHECK OPTION condition of the updated view excluding the updated table. */ List <TABLE> unupdated_check_opt_tables; Copy_field *copy_field; enum enum_duplicates handle_duplicates; bool do_update, trans_safe; /* True if the update operation has made a change in a transactional table */ bool transactional_tables; bool ignore; /* error handling (rollback and binlogging) can happen in send_eof() so that afterward abort_result_set() needs to find out that. */ bool error_handled; /* Need this to protect against multiple prepare() calls */ bool prepared; // For System Versioning (may need to insert new fields to a table). ha_rows updated_sys_ver; bool has_vers_fields; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List<TABLE_LIST> *leaves_list, List<Item> *fields, List<Item> *values, enum_duplicates handle_duplicates, bool ignore); ~multi_update(); bool init(THD *thd); bool init_for_single_table(THD *thd); int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int send_data(List<Item> &items) override; bool initialize_tables (JOIN *join) override; int prepare2(JOIN *join) override; int do_updates(); bool send_eof() override; inline ha_rows num_found() const { return found; } inline ha_rows num_updated() const { return updated; } inline void set_found (ha_rows n) { found= n; } inline void set_updated (ha_rows n) { updated= n; } virtual void abort_result_set() override; void update_used_tables() override; void prepare_to_read_rows() override; }; class my_var_sp; class my_var : public Sql_alloc { public: const LEX_CSTRING name; enum type { SESSION_VAR, LOCAL_VAR, PARAM_VAR }; type scope; my_var(const LEX_CSTRING *j, enum type s) : name(*j), scope(s) { } virtual ~my_var() = default; virtual bool set(THD *thd, Item *val) = 0; virtual my_var_sp *get_my_var_sp() { return NULL; } }; class my_var_sp: public my_var { const Sp_rcontext_handler *m_rcontext_handler; const Type_handler *m_type_handler; public: uint offset; /* Routine to which this Item_splocal belongs. Used for checking if correct runtime context is used for variable handling. */ sp_head *sp; my_var_sp(const Sp_rcontext_handler *rcontext_handler, const LEX_CSTRING *j, uint o, const Type_handler *type_handler, sp_head *s) : my_var(j, LOCAL_VAR), m_rcontext_handler(rcontext_handler), m_type_handler(type_handler), offset(o), sp(s) { } ~my_var_sp() = default; bool set(THD *thd, Item *val) override; my_var_sp *get_my_var_sp() override { return this; } const Type_handler *type_handler() const { return m_type_handler; } sp_rcontext *get_rcontext(sp_rcontext *local_ctx) const; }; /* This class handles fields of a ROW SP variable when it's used as a OUT parameter in a stored procedure. */ class my_var_sp_row_field: public my_var_sp { uint m_field_offset; public: my_var_sp_row_field(const Sp_rcontext_handler *rcontext_handler, const LEX_CSTRING *varname, const LEX_CSTRING *fieldname, uint var_idx, uint field_idx, sp_head *s) :my_var_sp(rcontext_handler, varname, var_idx, &type_handler_double/*Not really used*/, s), m_field_offset(field_idx) { } bool set(THD *thd, Item *val) override; }; class my_var_user: public my_var { public: my_var_user(const LEX_CSTRING *j) : my_var(j, SESSION_VAR) { } ~my_var_user() = default; bool set(THD *thd, Item *val) override; }; class select_dumpvar :public select_result_interceptor { ha_rows row_count; my_var_sp *m_var_sp_row; // Not NULL if SELECT INTO row_type_sp_variable bool send_data_to_var_list(List<Item> &items); public: List<my_var> var_list; select_dumpvar(THD *thd_arg) :select_result_interceptor(thd_arg), row_count(0), m_var_sp_row(NULL) { var_list.empty(); } ~select_dumpvar() = default; int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override; int send_data(List<Item> &items) override; bool send_eof() override; bool check_simple_select() const override; void reset_for_next_ps_execution() override; }; /* Bits in sql_command_flags */ #define CF_CHANGES_DATA (1U << 0) #define CF_REPORT_PROGRESS (1U << 1) #define CF_STATUS_COMMAND (1U << 2) #define CF_SHOW_TABLE_COMMAND (1U << 3) #define CF_WRITE_LOGS_COMMAND (1U << 4) /** Must be set for SQL statements that may contain Item expressions and/or use joins and tables. Indicates that the parse tree of such statement may contain rule-based optimizations that depend on metadata (i.e. number of columns in a table), and consequently that the statement must be re-prepared whenever referenced metadata changes. Must not be set for statements that themselves change metadata, e.g. RENAME, ALTER and other DDL, since otherwise will trigger constant reprepare. Consequently, complex item expressions and joins are currently prohibited in these statements. */ #define CF_REEXECUTION_FRAGILE (1U << 5) /** Implicitly commit before the SQL statement is executed. Statements marked with this flag will cause any active transaction to end (commit) before proceeding with the command execution. This flag should be set for statements that probably can't be rolled back or that do not expect any previously metadata locked tables. */ #define CF_IMPLICIT_COMMIT_BEGIN (1U << 6) /** Implicitly commit after the SQL statement. Statements marked with this flag are automatically committed at the end of the statement. This flag should be set for statements that will implicitly open and take metadata locks on system tables that should not be carried for the whole duration of a active transaction. */ #define CF_IMPLICIT_COMMIT_END (1U << 7) /** CF_IMPLICT_COMMIT_BEGIN and CF_IMPLICIT_COMMIT_END are used to ensure that the active transaction is implicitly committed before and after every DDL statement and any statement that modifies our currently non-transactional system tables. */ #define CF_AUTO_COMMIT_TRANS (CF_IMPLICIT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END) /** Diagnostic statement. Diagnostic statements: - SHOW WARNING - SHOW ERROR - GET DIAGNOSTICS (WL#2111) do not modify the diagnostics area during execution. */ #define CF_DIAGNOSTIC_STMT (1U << 8) /** Identifies statements that may generate row events and that may end up in the binary log. */ #define CF_CAN_GENERATE_ROW_EVENTS (1U << 9) /** Identifies statements which may deal with temporary tables and for which temporary tables should be pre-opened to simplify privilege checks. */ #define CF_PREOPEN_TMP_TABLES (1U << 10) /** Identifies statements for which open handlers should be closed in the beginning of the statement. */ #define CF_HA_CLOSE (1U << 11) /** Identifies statements that can be explained with EXPLAIN. */ #define CF_CAN_BE_EXPLAINED (1U << 12) /** Identifies statements which may generate an optimizer trace */ #define CF_OPTIMIZER_TRACE (1U << 14) /** Identifies statements that should always be disallowed in read only transactions. */ #define CF_DISALLOW_IN_RO_TRANS (1U << 15) /** Statement that need the binlog format to be unchanged. */ #define CF_FORCE_ORIGINAL_BINLOG_FORMAT (1U << 16) /** Statement that inserts new rows (INSERT, REPLACE, LOAD, ALTER TABLE) */ #define CF_INSERTS_DATA (1U << 17) /** Statement that updates existing rows (UPDATE, multi-update) */ #define CF_UPDATES_DATA (1U << 18) /** Not logged into slow log as "admin commands" */ #define CF_ADMIN_COMMAND (1U << 19) /** SP Bulk execution safe */ #define CF_PS_ARRAY_BINDING_SAFE (1U << 20) /** SP Bulk execution optimized */ #define CF_PS_ARRAY_BINDING_OPTIMIZED (1U << 21) /** If command creates or drops a table */ #define CF_SCHEMA_CHANGE (1U << 22) /** If command creates or drops a database */ #define CF_DB_CHANGE (1U << 23) /** Statement that deletes existing rows (DELETE, DELETE_MULTI) */ #define CF_DELETES_DATA (1U << 24) #ifdef WITH_WSREP /** DDL statement that may be subject to error filtering. */ #define CF_WSREP_MAY_IGNORE_ERRORS (1U << 25) /** Basic DML statements that create writeset. */ #define CF_WSREP_BASIC_DML (1u << 26) #endif /* WITH_WSREP */ /* Bits in server_command_flags */ /** Skip the increase of the global query id counter. Commonly set for commands that are stateless (won't cause any change on the server internal states). */ #define CF_SKIP_QUERY_ID (1U << 0) /** Skip the increase of the number of statements that clients have sent to the server. Commonly used for commands that will cause a statement to be executed but the statement might have not been sent by the user (ie: stored procedure). */ #define CF_SKIP_QUESTIONS (1U << 1) #ifdef WITH_WSREP /** Do not check that wsrep snapshot is ready before allowing this command */ #define CF_SKIP_WSREP_CHECK (1U << 2) #else #define CF_SKIP_WSREP_CHECK 0 #endif /* WITH_WSREP */ /* Inline functions */ inline bool add_item_to_list(THD *thd, Item *item) { bool res; LEX *lex= thd->lex; if (lex->current_select->parsing_place == IN_RETURNING) res= lex->returning()->add_item_to_list(thd, item); else res= lex->current_select->add_item_to_list(thd, item); return res; } inline bool add_value_to_list(THD *thd, Item *value) { return thd->lex->value_list.push_back(value, thd->mem_root); } inline bool add_order_to_list(THD *thd, Item *item, bool asc) { return thd->lex->current_select->add_order_to_list(thd, item, asc); } inline bool add_gorder_to_list(THD *thd, Item *item, bool asc) { return thd->lex->current_select->add_gorder_to_list(thd, item, asc); } inline bool add_group_to_list(THD *thd, Item *item, bool asc) { return thd->lex->current_select->add_group_to_list(thd, item, asc); } inline Item *and_conds(THD *thd, Item *a, Item *b) { if (!b) return a; if (!a) return b; return new (thd->mem_root) Item_cond_and(thd, a, b); } /* inline handler methods that need to know TABLE and THD structures */ inline void handler::increment_statistics(ulong SSV::*offset) const { status_var_increment(table->in_use->status_var.*offset); table->in_use->check_limit_rows_examined(); } inline void handler::fast_increment_statistics(ulong SSV::*offset) const { status_var_increment(table->in_use->status_var.*offset); } inline void handler::decrement_statistics(ulong SSV::*offset) const { status_var_decrement(table->in_use->status_var.*offset); } /* Update references in the handler to the table */ inline void handler::set_table(TABLE* table_arg) { table= table_arg; costs= &table_arg->s->optimizer_costs; } inline bool handler::pk_is_clustering_key(uint index) const { /* We have to check for MAX_INDEX as table->s->primary_key can be MAX_KEY in the case where there is no primary key. */ return index != MAX_KEY && is_clustering_key(index); } inline bool handler::is_clustering_key(uint index) const { DBUG_ASSERT(index != MAX_KEY); return table->is_clustering_key(index); } inline int handler::ha_ft_read(uchar *buf) { int error= ft_read(buf); if (!error) { update_rows_read(); if (table->vfield && buf == table->record[0]) table->update_virtual_fields(this, VCOL_UPDATE_FOR_READ); } table->status=error ? STATUS_NOT_FOUND: 0; return error; } inline int handler::ha_rnd_pos_by_record(uchar *buf) { int error= rnd_pos_by_record(buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; } inline int handler::ha_read_first_row(uchar *buf, uint primary_key) { int error= read_first_row(buf, primary_key); if (!error) update_rows_read(); table->status=error ? STATUS_NOT_FOUND: 0; return error; } inline int handler::ha_write_tmp_row(uchar *buf) { int error; MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str); increment_statistics(&SSV::ha_tmp_write_count); TABLE_IO_WAIT(tracker, PSI_TABLE_WRITE_ROW, MAX_KEY, error, { error= write_row(buf); }) MYSQL_INSERT_ROW_DONE(error); return error; } inline int handler::ha_delete_tmp_row(uchar *buf) { int error; MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str); increment_statistics(&SSV::ha_tmp_delete_count); TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, MAX_KEY, error, { error= delete_row(buf); }) MYSQL_DELETE_ROW_DONE(error); return error; } inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data) { int error; MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str); increment_statistics(&SSV::ha_tmp_update_count); TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, error, { error= update_row(old_data, new_data);}) MYSQL_UPDATE_ROW_DONE(error); return error; } inline bool handler::has_long_unique() { return table->s->long_unique_table; } /** Return whether the handler is root. @return false if table is maintained by different handlerton, true otherwise. @note The implementation supposes that the same handler can't be found as both root and non-root. There are two known cases when it's non-root: 1. under partition's ha_write_row() (also true for copy_partitions()) 2. under ha_mroonga::wrapper_write_row(); same applies for ha_delete_row/ha_update_row. */ inline bool handler::is_root_handler() const { return ht == table->file->ht; } extern pthread_attr_t *get_connection_attrib(void); /** Set thread entering a condition This function should be called before putting a thread to wait for a condition. @a mutex should be held before calling this function. After being waken up, @f thd_exit_cond should be called. @param thd The thread entering the condition, NULL means current thread @param cond The condition the thread is going to wait for @param mutex The mutex associated with the condition, this must be held before call this function @param stage The new process message for the thread @param old_stage The old process message for the thread @param src_function The caller source function name @param src_file The caller source file name @param src_line The caller source line number */ void thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, mysql_mutex_t *mutex, const PSI_stage_info *stage, PSI_stage_info *old_stage, const char *src_function, const char *src_file, int src_line); #define THD_ENTER_COND(P1, P2, P3, P4, P5) \ thd_enter_cond(P1, P2, P3, P4, P5, __func__, __FILE__, __LINE__) /** Set thread leaving a condition This function should be called after a thread being waken up for a condition. @param thd The thread entering the condition, NULL means current thread @param stage The process message, ususally this should be the old process message before calling @f thd_enter_cond @param src_function The caller source function name @param src_file The caller source file name @param src_line The caller source line number */ void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage, const char *src_function, const char *src_file, int src_line); #define THD_EXIT_COND(P1, P2) \ thd_exit_cond(P1, P2, __func__, __FILE__, __LINE__) inline bool binlog_should_compress(size_t len) { return opt_bin_log_compress && len >= opt_bin_log_compress_min_len; } void binlog_prepare_row_images(TABLE* table, enum_binlog_row_image row_image); /** Save thd sql_mode on instantiation. On destruction it resets the mode to the previously stored value. */ class Sql_mode_save { public: Sql_mode_save(THD *thd) : thd(thd), old_mode(thd->variables.sql_mode) {} ~Sql_mode_save() { thd->variables.sql_mode = old_mode; } protected: THD *thd; sql_mode_t old_mode; // SQL mode saved at construction time. }; /* Save the current sql_mode. Switch off sql_mode flags which can prevent normal parsing of VIEWs, expressions in generated columns. Restore the old sql_mode on destructor. */ class Sql_mode_save_for_frm_handling: public Sql_mode_save { public: Sql_mode_save_for_frm_handling(THD *thd) :Sql_mode_save(thd) { if (thd->variables.sql_mode & MODE_ORACLE) thd->variables.sql_mode|= IS_OR_WAS_ORACLE; /* - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing + MODE_PIPES_AS_CONCAT affect expression parsing + MODE_ANSI_QUOTES affect expression parsing + MODE_IGNORE_SPACE affect expression parsing - MODE_IGNORE_BAD_TABLE_OPTIONS affect only CREATE/ALTER TABLE parsing * MODE_ONLY_FULL_GROUP_BY affect execution * MODE_NO_UNSIGNED_SUBTRACTION affect execution - MODE_NO_DIR_IN_CREATE affect table creation only - MODE_POSTGRESQL compounded from other modes + MODE_ORACLE affects Item creation (e.g for CONCAT) - MODE_MSSQL compounded from other modes - MODE_DB2 compounded from other modes - MODE_MAXDB affect only CREATE TABLE parsing - MODE_NO_KEY_OPTIONS affect only SHOW - MODE_NO_TABLE_OPTIONS affect only SHOW - MODE_NO_FIELD_OPTIONS affect only SHOW - MODE_MYSQL323 affect only SHOW - MODE_MYSQL40 affect only SHOW - MODE_ANSI compounded from other modes (+ transaction mode) ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs + MODE_NO_BACKSLASH_ESCAPES affect expression parsing + MODE_EMPTY_STRING_IS_NULL affect expression parsing */ thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL); }; ~Sql_mode_save_for_frm_handling() { if (thd->variables.sql_mode & IS_OR_WAS_ORACLE) thd->variables.sql_mode&= ~IS_OR_WAS_ORACLE; } }; class Switch_to_definer_security_ctx { public: Switch_to_definer_security_ctx(THD *thd, TABLE_LIST *table) : m_thd(thd), m_sctx(thd->security_ctx) { if (table->security_ctx) thd->security_ctx= table->security_ctx; } ~Switch_to_definer_security_ctx() { m_thd->security_ctx = m_sctx; } private: THD *m_thd; Security_context *m_sctx; }; class Sql_mode_instant_set: public Sql_mode_save { public: Sql_mode_instant_set(THD *thd, sql_mode_t temporary_value) :Sql_mode_save(thd) { thd->variables.sql_mode= temporary_value; } }; class Sql_mode_instant_remove: public Sql_mode_save { public: Sql_mode_instant_remove(THD *thd, sql_mode_t temporary_remove_flags) :Sql_mode_save(thd) { thd->variables.sql_mode&= ~temporary_remove_flags; } }; class Abort_on_warning_instant_set { THD *m_thd; bool m_save_abort_on_warning; public: Abort_on_warning_instant_set(THD *thd, bool temporary_value) :m_thd(thd), m_save_abort_on_warning(thd->abort_on_warning) { thd->abort_on_warning= temporary_value; } ~Abort_on_warning_instant_set() { m_thd->abort_on_warning= m_save_abort_on_warning; } }; class Check_level_instant_set { THD *m_thd; enum_check_fields m_check_level; public: Check_level_instant_set(THD *thd, enum_check_fields temporary_value) :m_thd(thd), m_check_level(thd->count_cuted_fields) { thd->count_cuted_fields= temporary_value; } ~Check_level_instant_set() { m_thd->count_cuted_fields= m_check_level; } }; class Use_relaxed_field_copy: public Sql_mode_save, public Check_level_instant_set, public Abort_on_warning_instant_set { public: Use_relaxed_field_copy(THD *thd) : Sql_mode_save(thd), Check_level_instant_set(thd, CHECK_FIELD_IGNORE), Abort_on_warning_instant_set(thd, 0) { thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->variables.sql_mode|= MODE_INVALID_DATES; } }; class Identifier_chain2 { LEX_CSTRING m_name[2]; public: Identifier_chain2() :m_name{Lex_cstring(), Lex_cstring()} { } Identifier_chain2(const LEX_CSTRING &a, const LEX_CSTRING &b) :m_name{a, b} { } const LEX_CSTRING& operator [] (size_t i) const { return m_name[i]; } static Identifier_chain2 split(const LEX_CSTRING &txt) { DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input const char *dot= strchr(txt.str, '.'); if (!dot) return Identifier_chain2(Lex_cstring(), txt); size_t length0= dot - txt.str; Lex_cstring name0(txt.str, length0); Lex_cstring name1(txt.str + length0 + 1, txt.length - length0 - 1); return Identifier_chain2(name0, name1); } // Export as a qualified name string: 'db.name' size_t make_qname(char *dst, size_t dstlen, bool casedn_part1) const { size_t res= my_snprintf(dst, dstlen, "%.*s.%.*s", (int) m_name[0].length, m_name[0].str, (int) m_name[1].length, m_name[1].str); if (casedn_part1 && dstlen > m_name[0].length) my_casedn_str(system_charset_info, dst + m_name[0].length + 1); return res; } // Export as a qualified name string, allocate on mem_root. LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_part1) const { LEX_STRING dst; /* format: [pkg + dot] + name + '\0' */ size_t dst_size= m_name[0].length + 1 /*dot*/ + m_name[1].length + 1/*\0*/; if (unlikely(!(dst.str= (char*) alloc_root(mem_root, dst_size)))) return {NULL, 0}; if (!m_name[0].length) { DBUG_ASSERT(!casedn_part1); // Should not be called this way dst.length= my_snprintf(dst.str, dst_size, "%.*s", (int) m_name[1].length, m_name[1].str); return {dst.str, dst.length}; } dst.length= make_qname(dst.str, dst_size, casedn_part1); return {dst.str, dst.length}; } }; /** This class resembles the SQL Standard schema qualified object name: <schema qualified name> ::= [ <schema name> <period> ] <qualified identifier> */ class Database_qualified_name { public: LEX_CSTRING m_db; LEX_CSTRING m_name; Database_qualified_name() { } Database_qualified_name(const LEX_CSTRING *db, const LEX_CSTRING *name) :m_db(*db), m_name(*name) { } Database_qualified_name(const LEX_CSTRING &db, const LEX_CSTRING &name) :m_db(db), m_name(name) { } Database_qualified_name(const char *db, size_t db_length, const char *name, size_t name_length) { m_db.str= db; m_db.length= db_length; m_name.str= name; m_name.length= name_length; } bool eq(const Database_qualified_name *other) const { CHARSET_INFO *cs= lower_case_table_names ? &my_charset_utf8mb3_general_ci : &my_charset_utf8mb3_bin; return m_db.length == other->m_db.length && m_name.length == other->m_name.length && !cs->strnncoll(m_db.str, m_db.length, other->m_db.str, other->m_db.length) && !cs->strnncoll(m_name.str, m_name.length, other->m_name.str, other->m_name.length); } /* Make copies of "db" and "name" on the memory root in internal format: - Lower-case "db" if lower-case-table-names==1. - Preserve "name" as is. */ bool copy_sp_name_internal(MEM_ROOT *mem_root, const LEX_CSTRING &db, const LEX_CSTRING &name); // Export db and name as a qualified name string: 'db.name' size_t make_qname(char *dst, size_t dstlen, bool casedn_name) const { return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen, casedn_name); } // Export db and name as a qualified name string, allocate on mem_root. LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_name) const { return Identifier_chain2(m_db, m_name).make_qname(mem_root, casedn_name); } bool make_package_routine_name(MEM_ROOT *mem_root, const LEX_CSTRING &package, const LEX_CSTRING &routine) { char *tmp; size_t length= package.length + 1 + routine.length + 1; if (unlikely(!(tmp= (char *) alloc_root(mem_root, length)))) return true; m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length, false); m_name.str= tmp; return false; } bool make_package_routine_name(MEM_ROOT *mem_root, const LEX_CSTRING &db, const LEX_CSTRING &package, const LEX_CSTRING &routine) { if (unlikely(make_package_routine_name(mem_root, package, routine))) return true; if (unlikely(!(m_db.str= strmake_root(mem_root, db.str, db.length)))) return true; m_db.length= db.length; return false; } }; class ErrConvDQName: public ErrConv { const Database_qualified_name *m_name; public: ErrConvDQName(const Database_qualified_name *name) :m_name(name) { } LEX_CSTRING lex_cstring() const override { size_t length= m_name->make_qname(err_buffer, sizeof(err_buffer), false); return {err_buffer, length}; } }; class Type_holder: public Sql_alloc, public Item_args, public Type_handler_hybrid_field_type, public Type_all_attributes { const TYPELIB *m_typelib; bool m_maybe_null; public: Type_holder() :m_typelib(NULL), m_maybe_null(false) { } void set_type_maybe_null(bool maybe_null_arg) override { m_maybe_null= maybe_null_arg; } bool get_maybe_null() const { return m_maybe_null; } decimal_digits_t decimal_precision() const override { /* Type_holder is not used directly to create fields, so its virtual decimal_precision() is never called. We should eventually extend create_result_table() to accept an array of Type_holders directly, without having to allocate Item_type_holder's and put them into List<Item>. */ DBUG_ASSERT(0); return 0; } void set_typelib(const TYPELIB *typelib) override { m_typelib= typelib; } const TYPELIB *get_typelib() const override { return m_typelib; } bool aggregate_attributes(THD *thd) { static LEX_CSTRING union_name= { STRING_WITH_LEN("UNION") }; for (uint i= 0; i < arg_count; i++) m_maybe_null|= args[i]->maybe_null(); return type_handler()->Item_hybrid_func_fix_attributes(thd, union_name, this, this, args, arg_count); } }; /* A helper class to set THD flags to emit warnings/errors in case of overflow/type errors during assigning values into the SP variable fields. Saves original flags values in constructor. Restores original flags in destructor. */ class Sp_eval_expr_state { THD *m_thd; enum_check_fields m_count_cuted_fields; bool m_abort_on_warning; bool m_stmt_modified_non_trans_table; void start() { m_thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; m_thd->abort_on_warning= m_thd->is_strict_mode(); m_thd->transaction->stmt.modified_non_trans_table= false; } void stop() { m_thd->count_cuted_fields= m_count_cuted_fields; m_thd->abort_on_warning= m_abort_on_warning; m_thd->transaction->stmt.modified_non_trans_table= m_stmt_modified_non_trans_table; } public: Sp_eval_expr_state(THD *thd) :m_thd(thd), m_count_cuted_fields(thd->count_cuted_fields), m_abort_on_warning(thd->abort_on_warning), m_stmt_modified_non_trans_table(thd->transaction->stmt. modified_non_trans_table) { start(); } ~Sp_eval_expr_state() { stop(); } }; #ifndef DBUG_OFF void dbug_serve_apcs(THD *thd, int n_calls); #endif class StatementBinlog { const enum_binlog_format saved_binlog_format; THD *const thd; public: StatementBinlog(THD *thd, bool need_stmt) : saved_binlog_format(thd->get_current_stmt_binlog_format()), thd(thd) { if (need_stmt && saved_binlog_format != BINLOG_FORMAT_STMT) { thd->set_current_stmt_binlog_format_stmt(); } } ~StatementBinlog() { thd->set_current_stmt_binlog_format(saved_binlog_format); } }; /** THD registry */ class THD_list: public THD_list_iterator { public: /** Constructor replacement. Unfortunately we can't use fair constructor to initialize mutex for two reasons: PFS and embedded. The former can probably be fixed, the latter can probably be dropped. */ void init() { mysql_rwlock_init(key_rwlock_THD_list, &lock); } /** Destructor replacement. */ void destroy() { mysql_rwlock_destroy(&lock); } /** Inserts thread to registry. @param thd thread Thread becomes accessible via server_threads. */ void insert(THD *thd) { mysql_rwlock_wrlock(&lock); threads.append(thd); mysql_rwlock_unlock(&lock); } /** Removes thread from registry. @param thd thread Thread becomes not accessible via server_threads. */ void erase(THD *thd) { thd->assert_linked(); mysql_rwlock_wrlock(&lock); thd->unlink(); mysql_rwlock_unlock(&lock); } }; extern THD_list server_threads; void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count); C_MODE_START void mariadb_sleep_for_space(unsigned int seconds); C_MODE_END #ifdef WITH_WSREP extern void wsrep_to_isolation_end(THD*); #endif /* RAII utility class to ease binlogging with temporary setting THD etc context and restoring the original one upon logger execution. */ class Write_log_with_flags { THD* m_thd; #ifdef WITH_WSREP bool wsrep_to_isolation; #endif public: ~Write_log_with_flags() { m_thd->set_binlog_flags_for_alter(0); m_thd->set_binlog_start_alter_seq_no(0); #ifdef WITH_WSREP if (wsrep_to_isolation) wsrep_to_isolation_end(m_thd); #endif } Write_log_with_flags(THD *thd, uchar flags, bool do_wsrep_iso __attribute__((unused))= false) : m_thd(thd) { m_thd->set_binlog_flags_for_alter(flags); #ifdef WITH_WSREP wsrep_to_isolation= do_wsrep_iso && WSREP(m_thd); #endif } }; /** Make a new string allocated on THD's mem-root. @param thd thread handler. @param start_ptr start of the new string. @param end_ptr end of the new string. @return LEX_CSTRING object, containing a pointer to a newly constructed/allocated string, and its length. The data member LEX_CSTRING::str has the value nullptr in case of out-of-memory error. */ LEX_CSTRING make_string(THD *thd, const char *start_ptr, const char *end_ptr); #include "deprecation.h" #endif /* MYSQL_SERVER */ #endif /* SQL_CLASS_INCLUDED */ pfs_socket_provider.h 0000644 00000004322 15156036137 0010777 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_SOCKET_PROVIDER_H #define PFS_SOCKET_PROVIDER_H /** @file include/pfs_socket_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_SOCKET_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_SOCKET_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_socket_v1(const char *category, PSI_socket_info_v1 *info, int count); PSI_socket* pfs_init_socket_v1(PSI_socket_key key, const my_socket *fd, const struct sockaddr *addr, socklen_t addr_len); void pfs_destroy_socket_v1(PSI_socket *socket); PSI_socket_locker* pfs_start_socket_wait_v1(PSI_socket_locker_state *state, PSI_socket *socket, PSI_socket_operation op, size_t count, const char *src_file, uint src_line); void pfs_end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count); void pfs_set_socket_state_v1(PSI_socket *socket, PSI_socket_state state); void pfs_set_socket_info_v1(PSI_socket *socket, const my_socket *fd, const struct sockaddr *addr, socklen_t addr_len); void pfs_set_socket_thread_owner_v1(PSI_socket *socket); C_MODE_END #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_SOCKET_INTERFACE */ #endif rpl_gtid.h 0000644 00000073720 15156036137 0006541 0 ustar 00 /* Copyright (c) 2013, Kristian Nielsen and MariaDB Services Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_GTID_H #define RPL_GTID_H #include "hash.h" #include "queues.h" #include <atomic> /* Definitions for MariaDB global transaction ID (GTID). */ extern const LEX_CSTRING rpl_gtid_slave_state_table_name; class String; #ifdef MYSQL_SERVER struct TABLE; #endif struct slave_connection_state; #define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no #define GTID_MAX_STR_LENGTH (10+1+10+1+20) #define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no struct rpl_gtid { uint32 domain_id; uint32 server_id; uint64 seq_no; }; inline bool operator==(const rpl_gtid& lhs, const rpl_gtid& rhs) { return lhs.domain_id == rhs.domain_id && lhs.server_id == rhs.server_id && lhs.seq_no == rhs.seq_no; }; inline bool operator<(const rpl_gtid& lhs, const rpl_gtid& rhs) { return (lhs.domain_id == rhs.domain_id) ? lhs.seq_no < rhs.seq_no : lhs.domain_id < rhs.domain_id; }; inline bool operator>(const rpl_gtid& lhs, const rpl_gtid& rhs) { return (lhs.domain_id == rhs.domain_id) ? lhs.seq_no > rhs.seq_no : lhs.domain_id > rhs.domain_id; }; enum enum_gtid_skip_type { GTID_SKIP_NOT, GTID_SKIP_STANDALONE, GTID_SKIP_TRANSACTION }; /* Structure to keep track of threads waiting in MASTER_GTID_WAIT(). Since replication is (mostly) single-threaded, we want to minimise the performance impact on that from MASTER_GTID_WAIT(). To achieve this, we are careful to keep the common lock between replication threads and MASTER_GTID_WAIT threads held for as short as possible. We keep only a single thread waiting to be notified by the replication threads; this thread then handles all the (potentially heavy) lifting of dealing with all current waiting threads. */ struct gtid_waiting { /* Elements in the hash, basically a priority queue for each domain. */ struct hash_element { QUEUE queue; uint32 domain_id; }; /* A priority queue to handle waiters in one domain in seq_no order. */ struct queue_element { uint64 wait_seq_no; THD *thd; int queue_idx; /* do_small_wait is true if we have responsibility for ensuring that there is a small waiter. */ bool do_small_wait; /* The flag `done' is set when the wait is completed (either due to reaching the position waited for, or due to timeout or kill). The queue_element is in the queue if and only if `done' is true. */ bool done; }; mysql_mutex_t LOCK_gtid_waiting; HASH hash; void init(); void destroy(); hash_element *get_entry(uint32 domain_id); int wait_for_pos(THD *thd, String *gtid_str, longlong timeout_us); void promote_new_waiter(gtid_waiting::hash_element *he); int wait_for_gtid(THD *thd, rpl_gtid *wait_gtid, struct timespec *wait_until); void process_wait_hash(uint64 wakeup_seq_no, gtid_waiting::hash_element *he); int register_in_wait_queue(THD *thd, rpl_gtid *wait_gtid, hash_element *he, queue_element *elem); void remove_from_wait_queue(hash_element *he, queue_element *elem); }; class Relay_log_info; struct rpl_group_info; class Gtid_list_log_event; /* Replication slave state. For every independent replication stream (identified by domain_id), this remembers the last gtid applied on the slave within this domain. Since events are always committed in-order within a single domain, this is sufficient to maintain the state of the replication slave. */ struct rpl_slave_state { /* Elements in the list of GTIDs kept for each domain_id. */ struct list_element { struct list_element *next; uint64 sub_id; uint32 domain_id; uint32 server_id; uint64 seq_no; /* hton of mysql.gtid_slave_pos* table used to record this GTID. Can be NULL if the gtid table failed to load (eg. missing mysql.gtid_slave_pos table following an upgrade). */ void *hton; }; /* Elements in the HASH that hold the state for one domain_id. */ struct element { struct list_element *list; uint32 domain_id; /* Highest seq_no seen so far in this domain. */ uint64 highest_seq_no; /* If this is non-NULL, then it is the waiter responsible for the small wait in MASTER_GTID_WAIT(). */ gtid_waiting::queue_element *gtid_waiter; /* If gtid_waiter is non-NULL, then this is the seq_no that its MASTER_GTID_WAIT() is waiting on. When we reach this seq_no, we need to signal the waiter on COND_wait_gtid. */ uint64 min_wait_seq_no; mysql_cond_t COND_wait_gtid; /* For --gtid-ignore-duplicates. The Relay_log_info that currently owns this domain, and the number of worker threads that are active in it. The idea is that only one of multiple master connections is allowed to actively apply events for a given domain. Other connections must either discard the events (if the seq_no in GTID shows they have already been applied), or wait to see if the current owner will apply it. */ const Relay_log_info *owner_rli; uint32 owner_count; mysql_cond_t COND_gtid_ignore_duplicates; list_element *grab_list() { list_element *l= list; list= NULL; return l; } void add(list_element *l) { l->next= list; list= l; } }; /* Descriptor for mysql.gtid_slave_posXXX table in specific engine. */ enum gtid_pos_table_state { GTID_POS_AUTO_CREATE, GTID_POS_CREATE_REQUESTED, GTID_POS_CREATE_IN_PROGRESS, GTID_POS_AVAILABLE }; struct gtid_pos_table { struct gtid_pos_table *next; /* Use a void * here, rather than handlerton *, to make explicit that we are not using the value to access any functionality in the engine. It is just used as an opaque value to identify which engine we are using for each GTID row. */ void *table_hton; LEX_CSTRING table_name; uint8 state; }; /* Mapping from domain_id to its element. */ HASH hash; /* GTIDs added since last purge of old mysql.gtid_slave_pos rows. */ uint32 pending_gtid_count; /* Mutex protecting access to the state. */ mysql_mutex_t LOCK_slave_state; /* Auxiliary buffer to sort gtid list. */ DYNAMIC_ARRAY gtid_sort_array; uint64 last_sub_id; /* List of tables available for durably storing the slave GTID position. Accesses to this table is protected by LOCK_slave_state. However for efficiency, there is also a provision for read access to it from a running slave without lock. An element can be added at the head of a list by storing the new gtid_pos_tables pointer atomically with release semantics, to ensure that the next pointer of the new element is visible to readers of the new list. Other changes (like deleting or replacing elements) must happen only while all SQL driver threads are stopped. LOCK_slave_state must be held in any case. The list can be read without lock by an SQL driver thread or worker thread by reading the gtid_pos_tables pointer atomically with acquire semantics, to ensure that it will see the correct next pointer of a new head element. */ std::atomic<gtid_pos_table*> gtid_pos_tables; /* The default entry in gtid_pos_tables, mysql.gtid_slave_pos. */ std::atomic<gtid_pos_table*> default_gtid_pos_table; bool loaded; rpl_slave_state(); ~rpl_slave_state(); void truncate_hash(); ulong count() const { return hash.records; } int update(uint32 domain_id, uint32 server_id, uint64 sub_id, uint64 seq_no, void *hton, rpl_group_info *rgi); int update_nolock(uint32 domain_id, uint32 server_id, uint64 sub_id, uint64 seq_no, void *hton, rpl_group_info *rgi); int truncate_state_table(THD *thd); void select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename); int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, bool in_transaction, bool in_statement, void **out_hton); list_element *gtid_grab_pending_delete_list(); LEX_CSTRING *select_gtid_pos_table(void *hton); void gtid_delete_pending(THD *thd, rpl_slave_state::list_element **list_ptr); uint64 next_sub_id(uint32 domain_id); int iterate(int (*cb)(rpl_gtid *, void *), void *data, rpl_gtid *extra_gtids, uint32 num_extra, bool sort); int tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra); bool domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid); int load(THD *thd, const char *state_from_master, size_t len, bool reset, bool in_statement); bool is_empty(); element *get_element(uint32 domain_id); int put_back_list(list_element *list); void update_state_hash(uint64 sub_id, rpl_gtid *gtid, void *hton, rpl_group_info *rgi); int record_and_update_gtid(THD *thd, struct rpl_group_info *rgi); int check_duplicate_gtid(rpl_gtid *gtid, rpl_group_info *rgi); void release_domain_owner(rpl_group_info *rgi); void set_gtid_pos_tables_list(gtid_pos_table *new_list, gtid_pos_table *default_entry); void add_gtid_pos_table(gtid_pos_table *entry); struct gtid_pos_table *alloc_gtid_pos_table(LEX_CSTRING *table_name, void *hton, rpl_slave_state::gtid_pos_table_state state); void free_gtid_pos_tables(struct gtid_pos_table *list); }; /* Binlog state. This keeps the last GTID written to the binlog for every distinct (domain_id, server_id) pair. This will be logged at the start of the next binlog file as a Gtid_list_log_event; this way, it is easy to find the binlog file containing a given GTID, by simply scanning backwards from the newest one until a lower seq_no is found in the Gtid_list_log_event at the start of a binlog for the given domain_id and server_id. We also remember the last logged GTID for every domain_id. This is used to know where to start when a master is changed to a slave. As a side effect, it also allows to skip a hash lookup in the very common case of logging a new GTID with same server id as last GTID. The base class rpl_binlog_state_base contains just be basic data operations to insert/update GTIDs, and is used eg. from Gtid_index_*. The main class rpl_binlog_state builds server logic on top of that like mutex locking, gtid_strict_mode handling, etc. */ struct rpl_binlog_state_base { struct element { uint32 domain_id; HASH hash; /* Containing all server_id for one domain_id */ /* The most recent entry in the hash. */ rpl_gtid *last_gtid; /* Counter to allocate next seq_no for this domain. */ uint64 seq_no_counter; int update_element(const rpl_gtid *gtid); }; /* Mapping from domain_id to collection of elements. */ HASH hash; my_bool initialized; rpl_binlog_state_base() : initialized(0) {} ~rpl_binlog_state_base(); void init(); void reset_nolock(); void free(); bool load_nolock(struct rpl_gtid *list, uint32 count); bool load_nolock(rpl_binlog_state_base *orig_state); int update_nolock(const struct rpl_gtid *gtid); int alloc_element_nolock(const rpl_gtid *gtid); uint32 count_nolock(); int get_gtid_list_nolock(rpl_gtid *gtid_list, uint32 list_size); rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id); bool is_before_pos(slave_connection_state *pos); }; struct rpl_binlog_state : public rpl_binlog_state_base { /* Mutex protecting access to the state. */ mysql_mutex_t LOCK_binlog_state; /* Auxiliary buffer to sort gtid list. */ DYNAMIC_ARRAY gtid_sort_array; rpl_binlog_state() {} ~rpl_binlog_state(); void init(); void reset(); void free(); bool load(struct rpl_gtid *list, uint32 count); bool load(rpl_slave_state *slave_pos); int update(const struct rpl_gtid *gtid, bool strict); int update_with_next_gtid(uint32 domain_id, uint32 server_id, rpl_gtid *gtid); bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no, bool no_error= false); int bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no); int write_to_iocache(IO_CACHE *dest); int read_from_iocache(IO_CACHE *src); uint32 count(); int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size); int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); bool append_pos(String *str); bool append_state(String *str); rpl_gtid *find(uint32 domain_id, uint32 server_id); rpl_gtid *find_most_recent(uint32 domain_id); const char* drop_domain(DYNAMIC_ARRAY *ids, Gtid_list_log_event *glev, char*); }; /* Represent the GTID state that a slave connection to a master requests the master to start sending binlog events from. */ struct slave_connection_state { struct entry { rpl_gtid gtid; uint32 flags; }; /* Bits for 'flags' */ enum start_flags { START_OWN_SLAVE_POS= 0x1, START_ON_EMPTY_DOMAIN= 0x2 }; /* Mapping from domain_id to the entry with GTID requested for that domain. */ HASH hash; /* Auxiliary buffer to sort gtid list. */ DYNAMIC_ARRAY gtid_sort_array; slave_connection_state(); ~slave_connection_state(); void reset() { my_hash_reset(&hash); } int load(const char *slave_request, size_t len); int load(const rpl_gtid *gtid_list, uint32 count); int load(rpl_slave_state *state, rpl_gtid *extra_gtids, uint32 num_extra); rpl_gtid *find(uint32 domain_id); entry *find_entry(uint32 domain_id); int update(const rpl_gtid *in_gtid); void remove(const rpl_gtid *gtid); void remove_if_present(const rpl_gtid *in_gtid); ulong count() const { return hash.records; } int to_string(String *out_str); int append_to_string(String *out_str); int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size); bool is_pos_reached(); }; extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid, bool *first); extern int gtid_check_rpl_slave_state_table(TABLE *table); extern rpl_gtid *gtid_parse_string_to_list(const char *p, size_t len, uint32 *out_len); extern rpl_gtid *gtid_unpack_string_to_list(const char *p, size_t len, uint32 *out_len); /* This class ensures that the GTID state of an event stream is consistent with the set of provided binary log files. In particular, it has two concerns: 1) Ensuring that GTID events are monotonically increasing within each domain 2) Ensuring that the GTID state of the specified binary logs is consistent both with the initial state that a user provides, and between binary logs (if multiple are specified) */ class Binlog_gtid_state_validator { public: struct audit_elem { uint32 domain_id; /* Holds the largest GTID received, and is indexed by domain_id */ rpl_gtid last_gtid; /* Holds the largest GTID received, and is indexed by domain_id */ rpl_gtid start_gtid; /* List of the problematic GTIDs received which were out of order */ DYNAMIC_ARRAY late_gtids_real; /* For each problematic GTID in late_gtids_real, this list contains the last GTID of the domain at the time of receiving the out of order GTID. */ DYNAMIC_ARRAY late_gtids_previous; }; Binlog_gtid_state_validator(); ~Binlog_gtid_state_validator(); /* Initialize where we should start monitoring for invalid GTID entries in the event stream. Note that these start positions must occur at or after a given binary logs GTID state (from Gtid_list_log_event) */ void initialize_start_gtids(rpl_gtid *start_gtids, size_t n_gtids); /* Initialize our current state so we know where to expect GTIDs to start increasing from. Error if the state exists after our expected start_gtid positions, because we know we will be missing event data (possibly from a purged log). */ my_bool initialize_gtid_state(FILE *out, rpl_gtid *gtids, size_t n_gtids); /* Ensures that the expected stop GTID positions exist within the specified binary logs. */ my_bool verify_stop_state(FILE *out, rpl_gtid *stop_gtids, size_t n_stop_gtids); /* Ensure a GTID state (e.g., from a Gtid_list_log_event) is consistent with the current state of our auditing. For example, if we see a GTID from a Gtid_list_log_event that is ahead of our current state for that domain, we have missed events (perhaps from a missing log). */ my_bool verify_gtid_state(FILE *out, rpl_gtid *gtid_state_cur); /* Take note of a new GTID being processed. returns TRUE if the GTID is invalid, FALSE on success */ my_bool record(rpl_gtid *gtid); /* Writes warnings/errors (if any) during GTID processing Returns TRUE if any findings were reported, FALSE otherwise */ my_bool report(FILE *out, my_bool is_strict_mode); static void report_details(FILE *out, const char *format, va_list args) { vfprintf(out, format, args); fprintf(out, "\n"); } static void warn(FILE *out, const char *format,...) { va_list args; va_start(args, format); fprintf(out, "WARNING: "); report_details(out, format, args); } static void error(FILE *out, const char *format,...) { va_list args; va_start(args, format); fprintf(out, "ERROR: "); report_details(out, format, args); } private: /* Holds the records for each domain id we are monitoring. Elements are of type `struct audit_elem` and indexed by domian_id. */ HASH m_audit_elem_domain_lookup; }; /* Interface to support different methods of filtering log events by GTID */ class Gtid_event_filter { public: Gtid_event_filter() {}; virtual ~Gtid_event_filter() {}; enum gtid_event_filter_type { DELEGATING_GTID_FILTER_TYPE = 1, WINDOW_GTID_FILTER_TYPE = 2, ACCEPT_ALL_GTID_FILTER_TYPE = 3, REJECT_ALL_GTID_FILTER_TYPE = 4, INTERSECTING_GTID_FILTER_TYPE = 5 }; enum class id_restriction_mode { MODE_NOT_SET, WHITELIST_MODE, BLACKLIST_MODE, }; /* Run the filter on an input gtid to test if the corresponding log events should be excluded from a result Returns TRUE when the event group corresponding to the input GTID should be excluded. Returns FALSE when the event group should be included. */ virtual my_bool exclude(rpl_gtid *) = 0; /* The gtid_event_filter_type that corresponds to the underlying filter implementation */ virtual uint32 get_filter_type() = 0; /* For filters that can maintain their own state, this tests if the filter implementation has completed. Returns TRUE when completed, and FALSE when the filter has not finished. */ virtual my_bool has_finished() = 0; /** Check that this filter implementation is at a final, completed state, and warn if it is not. For a filter that can maintain their own state, this not only validates if the filter ::has_finished(), but may also print specific warnings for its variety of non-final states. For a filter that manage multiple subfilters, this should iterate through all of those to have each self-report any ineffectiveness. This cumulative result may not correlate with the ::has_finished() state. @return `false` if the filter is at a completed state, or `true` if it warned incompleteness (This scheme is the opposite of has_finished()!) */ virtual bool verify_final_state() { return false; } }; /* Filter implementation which will include any and all input GTIDs. This is used to set default behavior for GTIDs that do not have explicit filters set on their domain_id, e.g. when a Window_gtid_event_filter is used for a specific domain, then all other domain_ids will be accepted using this filter implementation. */ class Accept_all_gtid_filter : public Gtid_event_filter { public: Accept_all_gtid_filter() {} ~Accept_all_gtid_filter() {} my_bool exclude(rpl_gtid *) override { return FALSE; } uint32 get_filter_type() override { return ACCEPT_ALL_GTID_FILTER_TYPE; } my_bool has_finished() override { return FALSE; } }; /* Filter implementation to exclude all tested GTIDs. */ class Reject_all_gtid_filter : public Gtid_event_filter { public: Reject_all_gtid_filter() {} ~Reject_all_gtid_filter() {} my_bool exclude(rpl_gtid *) override { return TRUE; } uint32 get_filter_type() override { return REJECT_ALL_GTID_FILTER_TYPE; } my_bool has_finished() override { return FALSE; } }; /* A filter implementation that includes events that exist between two GTID positions, m_start (exclusive) and m_stop (inclusive), within a domain. This filter is stateful, such that it expects GTIDs to be an increasing stream, and internally, the window will activate and deactivate when the start and stop positions of the event stream have passed through, respectively. */ class Window_gtid_event_filter : public Gtid_event_filter { public: Window_gtid_event_filter(); ~Window_gtid_event_filter() {} my_bool exclude(rpl_gtid*) override; my_bool has_finished() override; bool verify_final_state() override; /* Set the GTID that begins this window (exclusive) Returns 0 on ok, non-zero on error */ int set_start_gtid(rpl_gtid *start); /* Set the GTID that ends this window (inclusive) Returns 0 on ok, non-zero on error */ int set_stop_gtid(rpl_gtid *stop); uint32 get_filter_type() override { return WINDOW_GTID_FILTER_TYPE; } /* Validates the underlying range is correct, and writes an error if not, i.e. m_start >= m_stop. Returns FALSE on ok, TRUE if range is invalid */ my_bool is_range_invalid(); /* Getter/setter methods */ my_bool has_start() { return m_has_start; } my_bool has_stop() { return m_has_stop; } rpl_gtid get_start_gtid() { return m_start; } rpl_gtid get_stop_gtid() { return m_stop; } void clear_start_pos() { m_has_start= FALSE; m_start= {0, 0, 0}; } void clear_stop_pos() { m_has_stop= FALSE; m_stop= {0, 0, 0}; } private: enum warning_flags { WARN_GTID_SEQUENCE_NUMBER_OUT_OF_ORDER= 0x1 }; /* m_has_start : Indicates if a start to this window has been explicitly provided. A window starts immediately if not provided. */ my_bool m_has_start; /* m_has_stop : Indicates if a stop to this window has been explicitly provided. A window continues indefinitely if not provided. */ my_bool m_has_stop; /* m_is_active : Indicates whether or not the program is currently reading events from within this window. When TRUE, events with different server ids than those specified by m_start or m_stop will be passed through. */ my_bool m_is_active; /* m_has_passed : Indicates whether or not the program is currently reading events from beyond this window. */ my_bool m_has_passed; /* m_start : marks the GTID that begins the window (exclusive). */ rpl_gtid m_start; /* m_stop : marks the GTID that ends the range (inclusive). */ rpl_gtid m_stop; }; template <typename T> struct gtid_filter_element { Gtid_event_filter *filter; T identifier; /* Used for HASH lookup */ }; /* Gtid_event_filter subclass which has no specific implementation, but rather delegates the filtering to specific identifiable/mapped implementations. A default filter is used for GTIDs that are passed through which no explicit filter can be identified. This class should be subclassed, where the get_id_from_gtid function specifies how to extract the filter identifier from a GTID. The type of the filter identifier is a template for the class. */ template <typename T> class Id_delegating_gtid_event_filter : public Gtid_event_filter { public: Id_delegating_gtid_event_filter(); ~Id_delegating_gtid_event_filter(); my_bool exclude(rpl_gtid *gtid) override; my_bool has_finished() override; bool verify_final_state() override; void set_default_filter(Gtid_event_filter *default_filter); uint32 get_filter_type() override { return DELEGATING_GTID_FILTER_TYPE; } virtual T get_id_from_gtid(rpl_gtid *) = 0; virtual const char* get_id_type_name() = 0; /* Sets restrictions on entire ids using the corresponding mode (i.e. either whitelist or blacklist, refer to Gtid_event_filter::id_restriction_mode) A blacklist will allow all ids except for the ones provided in the input list. A whitelist will only allow ids provided in the input list. Returns 0 on ok, non-zero on error. */ int set_id_restrictions(T *id_list, size_t n_ids, Gtid_event_filter::id_restriction_mode mode); protected: uint32 m_num_stateful_filters; uint32 m_num_completed_filters; Gtid_event_filter *m_default_filter; HASH m_filters_by_id_hash; Gtid_event_filter::id_restriction_mode m_id_restriction_mode; gtid_filter_element<T> *find_or_create_filter_element_for_id(T); }; /* A subclass of Id_delegating_gtid_event_filter which identifies filters using the domain id of a GTID. Additional helper functions include: add_start_gtid(GTID) : adds a start GTID position to this filter, to be identified by its domain id add_stop_gtid(GTID) : adds a stop GTID position to this filter, to be identified by its domain id clear_start_gtids() : removes existing GTID start positions clear_stop_gtids() : removes existing GTID stop positions get_start_gtids() : gets all added GTID start positions get_stop_gtids() : gets all added GTID stop positions get_num_start_gtids() : gets the count of added GTID start positions get_num_stop_gtids() : gets the count of added GTID stop positions */ class Domain_gtid_event_filter : public Id_delegating_gtid_event_filter<decltype(rpl_gtid::domain_id)> { public: Domain_gtid_event_filter() { my_init_dynamic_array(PSI_INSTRUMENT_ME, &m_start_filters, sizeof(decltype(rpl_gtid::domain_id) *), 8, 8, MYF(0)); my_init_dynamic_array(PSI_INSTRUMENT_ME, &m_stop_filters, sizeof(decltype(rpl_gtid::domain_id) *), 8, 8, MYF(0)); } ~Domain_gtid_event_filter() { delete_dynamic(&m_start_filters); delete_dynamic(&m_stop_filters); } /* Returns the domain id of from the input GTID */ decltype(rpl_gtid::domain_id) get_id_from_gtid(rpl_gtid *gtid) override { return gtid->domain_id; } const char* get_id_type_name() override { return "domain"; } /* Override Id_delegating_gtid_event_filter to extend with domain specific filtering logic */ my_bool exclude(rpl_gtid*) override; /* Validates that window filters with both a start and stop GTID satisfy stop_gtid > start_gtid Returns 0 on ok, non-zero if any windows are invalid. */ int validate_window_filters(); /* Helper function to start a GTID window filter at the given GTID Returns 0 on ok, non-zero on error */ int add_start_gtid(rpl_gtid *gtid); /* Helper function to end a GTID window filter at the given GTID Returns 0 on ok, non-zero on error */ int add_stop_gtid(rpl_gtid *gtid); /* If start or stop position is respecified, we remove all existing values and start over with the new specification. */ void clear_start_gtids(); void clear_stop_gtids(); /* Return list of all GTIDs used as start position. Note that this list is allocated and it is up to the user to free it */ rpl_gtid *get_start_gtids(); /* Return list of all GTIDs used as stop position. Note that this list is allocated and it is up to the user to free it */ rpl_gtid *get_stop_gtids(); size_t get_num_start_gtids() { return m_start_filters.elements; } size_t get_num_stop_gtids() { return m_stop_filters.elements; } private: DYNAMIC_ARRAY m_start_filters; DYNAMIC_ARRAY m_stop_filters; Window_gtid_event_filter * find_or_create_window_filter_for_id(decltype(rpl_gtid::domain_id)); }; /* A subclass of Id_delegating_gtid_event_filter which identifies filters using the server id of a GTID. */ class Server_gtid_event_filter : public Id_delegating_gtid_event_filter<decltype(rpl_gtid::server_id)> { public: /* Returns the server id of from the input GTID */ decltype(rpl_gtid::server_id) get_id_from_gtid(rpl_gtid *gtid) override { return gtid->server_id; } const char* get_id_type_name() override { return "server"; } }; /* A Gtid_event_filter implementation that delegates the filtering to other filters, where the result is the intersection between them all. */ class Intersecting_gtid_event_filter : public Gtid_event_filter { public: Intersecting_gtid_event_filter(Gtid_event_filter *filter1, Gtid_event_filter *filter2); ~Intersecting_gtid_event_filter(); /* Returns TRUE if any filers exclude the gtid, returns FALSE otherwise, i.e. all filters must allow the GTID. */ my_bool exclude(rpl_gtid *gtid) override; /* Returns true if any filters have finished. To elaborate, as this filter performs an intersection, if any filter has finished, the result would be excluded regardless. */ my_bool has_finished() override; bool verify_final_state() override; uint32 get_filter_type() override { return INTERSECTING_GTID_FILTER_TYPE; } /* Adds a new filter to the intersection */ my_bool add_filter(Gtid_event_filter *filter) { return insert_dynamic(&m_filters, (void *) &filter); } protected: DYNAMIC_ARRAY m_filters; }; #endif /* RPL_GTID_H */ handler.h 0000644 00000634515 15156036137 0006357 0 ustar 00 #ifndef HANDLER_INCLUDED #define HANDLER_INCLUDED /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. Copyright (c) 2009, 2023, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Definitions for parameters to do with handler-routines */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_const.h" #include "sql_basic_types.h" #include "mysqld.h" /* server_id */ #include "optimizer_costs.h" #include "sql_plugin.h" /* plugin_ref, st_plugin_int, plugin */ #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA */ #include "sql_cache.h" #include "structs.h" /* SHOW_COMP_OPTION */ #include "sql_array.h" /* Dynamic_array<> */ #include "mdl.h" #include "vers_string.h" #include "ha_handler_stats.h" #include "optimizer_costs.h" #include "sql_analyze_stmt.h" // for Exec_time_tracker #include <my_compare.h> #include <ft_global.h> #include <keycache.h> #include <mysql/psi/mysql_table.h> #include "sql_sequence.h" #include "mem_root_array.h" #include <utility> // pair #include <my_attribute.h> /* __attribute__ */ class Alter_info; class Virtual_column_info; class sequence_definition; class Rowid_filter; class Field_string; class Field_varstring; class Field_blob; class Column_definition; class select_result; // the following is for checking tables #define HA_ADMIN_ALREADY_DONE 1 #define HA_ADMIN_OK 0 #define HA_ADMIN_NOT_IMPLEMENTED -1 #define HA_ADMIN_FAILED -2 #define HA_ADMIN_CORRUPT -3 #define HA_ADMIN_INTERNAL_ERROR -4 #define HA_ADMIN_INVALID -5 #define HA_ADMIN_REJECT -6 #define HA_ADMIN_TRY_ALTER -7 #define HA_ADMIN_WRONG_CHECKSUM -8 #define HA_ADMIN_NOT_BASE_TABLE -9 #define HA_ADMIN_NEEDS_UPGRADE -10 #define HA_ADMIN_NEEDS_ALTER -11 #define HA_ADMIN_NEEDS_CHECK -12 #define HA_ADMIN_COMMIT_ERROR -13 /** Return values for check_if_supported_inplace_alter(). @see check_if_supported_inplace_alter() for description of the individual values. */ enum enum_alter_inplace_result { HA_ALTER_ERROR, HA_ALTER_INPLACE_COPY_NO_LOCK, HA_ALTER_INPLACE_COPY_LOCK, HA_ALTER_INPLACE_NOCOPY_LOCK, HA_ALTER_INPLACE_NOCOPY_NO_LOCK, HA_ALTER_INPLACE_INSTANT, HA_ALTER_INPLACE_NOT_SUPPORTED, HA_ALTER_INPLACE_EXCLUSIVE_LOCK, HA_ALTER_INPLACE_SHARED_LOCK, HA_ALTER_INPLACE_NO_LOCK }; /* Flags for create_partitioning_metadata() */ enum chf_create_flags { CHF_CREATE_FLAG, CHF_DELETE_FLAG, CHF_RENAME_FLAG, CHF_INDEX_FLAG }; /* Bits in table_flags() to show what database can do */ #define HA_NO_TRANSACTIONS (1ULL << 0) /* Doesn't support transactions */ #define HA_PARTIAL_COLUMN_READ (1ULL << 1) /* read may not return all columns */ #define HA_TABLE_SCAN_ON_INDEX (1ULL << 2) /* No separate data/index file */ /* The following should be set if the following is not true when scanning a table with rnd_next() - We will see all rows (including deleted ones) - Row positions are 'table->s->db_record_offset' apart If this flag is not set, filesort will do a position() call for each matched row to be able to find the row later. */ #define HA_REC_NOT_IN_SEQ (1ULL << 3) #define HA_CAN_GEOMETRY (1ULL << 4) /* Reading keys in random order is as fast as reading keys in sort order (Used in records.cc to decide if we should use a record cache and by filesort to decide if we should sort key + data or key + pointer-to-row */ #define HA_FAST_KEY_READ (1ULL << 5) /* Set the following flag if we on delete should force all key to be read and on update read all keys that changes */ #define HA_REQUIRES_KEY_COLUMNS_FOR_DELETE (1ULL << 6) #define HA_NULL_IN_KEY (1ULL << 7) /* One can have keys with NULL */ #define HA_DUPLICATE_POS (1ULL << 8) /* ha_position() gives dup row */ #define HA_NO_BLOBS (1ULL << 9) /* Doesn't support blobs */ #define HA_CAN_INDEX_BLOBS (1ULL << 10) #define HA_AUTO_PART_KEY (1ULL << 11) /* auto-increment in multi-part key */ /* The engine requires every table to have a user-specified PRIMARY KEY. Do not set the flag if the engine can generate a hidden primary key internally. This flag is ignored if a SEQUENCE is created (which, in turn, needs HA_CAN_TABLES_WITHOUT_ROLLBACK flag) */ #define HA_REQUIRE_PRIMARY_KEY (1ULL << 12) #define HA_STATS_RECORDS_IS_EXACT (1ULL << 13) /* stats.records is exact */ /* INSERT_DELAYED only works with handlers that uses MySQL internal table level locks */ #define HA_CAN_INSERT_DELAYED (1ULL << 14) /* If we get the primary key columns for free when we do an index read (usually, it also implies that HA_PRIMARY_KEY_REQUIRED_FOR_POSITION flag is set). */ #define HA_PRIMARY_KEY_IN_READ_INDEX (1ULL << 15) /* If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, it means that to position() uses a primary key given by the record argument. Without primary key, we can't call position(). If not set, the position is returned as the current rows position regardless of what argument is given. */ #define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1ULL << 16) #define HA_CAN_RTREEKEYS (1ULL << 17) #define HA_NOT_DELETE_WITH_CACHE (1ULL << 18) /* unused */ /* The following is we need to a primary key to delete (and update) a row. If there is no primary key, all columns needs to be read on update and delete */ #define HA_PRIMARY_KEY_REQUIRED_FOR_DELETE (1ULL << 19) #define HA_NO_PREFIX_CHAR_KEYS (1ULL << 20) #define HA_CAN_FULLTEXT (1ULL << 21) #define HA_CAN_SQL_HANDLER (1ULL << 22) #define HA_NO_AUTO_INCREMENT (1ULL << 23) /* Has automatic checksums and uses the old checksum format */ #define HA_HAS_OLD_CHECKSUM (1ULL << 24) /* Table data are stored in separate files (for lower_case_table_names) */ #define HA_FILE_BASED (1ULL << 26) #define HA_CAN_BIT_FIELD (1ULL << 28) /* supports bit fields */ #define HA_NEED_READ_RANGE_BUFFER (1ULL << 29) /* for read_multi_range */ #define HA_ANY_INDEX_MAY_BE_UNIQUE (1ULL << 30) #define HA_NO_COPY_ON_ALTER (1ULL << 31) #define HA_HAS_RECORDS (1ULL << 32) /* records() gives exact count*/ /* Has it's own method of binlog logging */ #define HA_HAS_OWN_BINLOGGING (1ULL << 33) /* Engine is capable of row-format and statement-format logging, respectively */ #define HA_BINLOG_ROW_CAPABLE (1ULL << 34) #define HA_BINLOG_STMT_CAPABLE (1ULL << 35) /* When a multiple key conflict happens in a REPLACE command mysql expects the conflicts to be reported in the ascending order of key names. For e.g. CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT NULL, INDEX(c)); REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3); MySQL expects the conflict with 'a' to be reported before the conflict with 'b'. If the underlying storage engine does not report the conflicting keys in ascending order, it causes unexpected errors when the REPLACE command is executed. This flag helps the underlying SE to inform the server that the keys are not ordered. */ #define HA_DUPLICATE_KEY_NOT_IN_ORDER (1ULL << 36) /* Engine supports REPAIR TABLE. Used by CHECK TABLE FOR UPGRADE if an incompatible table is detected. If this flag is set, CHECK TABLE FOR UPGRADE will report ER_TABLE_NEEDS_UPGRADE, otherwise ER_TABLE_NEED_REBUILD. */ #define HA_CAN_REPAIR (1ULL << 37) /* Has automatic checksums and uses the new checksum format */ #define HA_HAS_NEW_CHECKSUM (1ULL << 38) #define HA_CAN_VIRTUAL_COLUMNS (1ULL << 39) #define HA_MRR_CANT_SORT (1ULL << 40) /* All of VARCHAR is stored, including bytes after real varchar data */ #define HA_RECORD_MUST_BE_CLEAN_ON_WRITE (1ULL << 41) /* This storage engine supports condition pushdown */ #define HA_CAN_TABLE_CONDITION_PUSHDOWN (1ULL << 42) /* old name for the same flag */ #define HA_MUST_USE_TABLE_CONDITION_PUSHDOWN HA_CAN_TABLE_CONDITION_PUSHDOWN /** The handler supports read before write removal optimization Read before write removal may be used for storage engines which support write without previous read of the row to be updated. Handler returning this flag must implement start_read_removal() and end_read_removal(). The handler may return "fake" rows constructed from the key of the row asked for. This is used to optimize UPDATE and DELETE by reducing the number of roundtrips between handler and storage engine. Example: UPDATE a=1 WHERE pk IN (<keys>) Sql_cmd_update::update_single_table() { if (<conditions for starting read removal>) start_read_removal() -> handler returns true if read removal supported for this table/query while(read_record("pk=<key>")) -> handler returns fake row with column "pk" set to <key> ha_update_row() -> handler sends write "a=1" for row with "pk=<key>" end_read_removal() -> handler returns the number of rows actually written } @note This optimization in combination with batching may be used to remove even more roundtrips. */ #define HA_READ_BEFORE_WRITE_REMOVAL (1ULL << 43) /* Engine supports extended fulltext API */ #define HA_CAN_FULLTEXT_EXT (1ULL << 44) /* Storage engine supports table export using the FLUSH TABLE <table_list> FOR EXPORT statement (meaning, after this statement one can copy table files out of the datadir and later "import" (somehow) in another MariaDB instance) */ #define HA_CAN_EXPORT (1ULL << 45) /* Storage engine does not require an exclusive metadata lock on the table during optimize. (TODO and repair?). It can allow other connections to open the table. (it does not necessarily mean that other connections can read or modify the table - this is defined by THR locks and the ::store_lock() method). */ #define HA_CONCURRENT_OPTIMIZE (1ULL << 46) /* If the storage engine support tables that will not roll back on commit In addition the table should not lock rows and support READ and WRITE UNCOMMITTED. This is useful for implementing things like SEQUENCE but can also in the future be useful to do logging that should never roll back. */ #define HA_CAN_TABLES_WITHOUT_ROLLBACK (1ULL << 47) /* Mainly for usage by SEQUENCE engine. Setting this flag means that the table will never roll back and that all operations for this table should stored in the non transactional log space that will always be written, even on rollback. */ #define HA_PERSISTENT_TABLE (1ULL << 48) /* If storage engine uses another engine as a base This flag is also needed if the table tries to open the .frm file as part of drop table. */ #define HA_REUSES_FILE_NAMES (1ULL << 49) /* Set of all binlog flags. Currently only contain the capabilities flags. */ #define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE) /* The following are used by Spider */ #define HA_CAN_FORCE_BULK_UPDATE (1ULL << 50) #define HA_CAN_FORCE_BULK_DELETE (1ULL << 51) #define HA_CAN_DIRECT_UPDATE_AND_DELETE (1ULL << 52) /* The following is for partition handler */ #define HA_CAN_MULTISTEP_MERGE (1LL << 53) /* calling cmp_ref() on the engine is expensive */ #define HA_SLOW_CMP_REF (1ULL << 54) #define HA_CMP_REF_IS_EXPENSIVE HA_SLOW_CMP_REF /** Some engines are unable to provide an efficient implementation for rnd_pos(). Server will try to avoid it, if possible TODO better to do it with cost estimates, not with an explicit flag */ #define HA_SLOW_RND_POS (1ULL << 55) /* Safe for online backup */ #define HA_CAN_ONLINE_BACKUPS (1ULL << 56) /* Support native hash index */ #define HA_CAN_HASH_KEYS (1ULL << 57) #define HA_CRASH_SAFE (1ULL << 58) /* There is no need to evict the table from the table definition cache having run ANALYZE TABLE on it */ #define HA_ONLINE_ANALYZE (1ULL << 59) /* Rowid's are not comparable. This is set if the rowid is unique to the current open handler, like it is with federated where the rowid is a pointer to a local result set buffer. The effect of having this set is that the optimizer will not consider the following optimizations for the table: ror scans, filtering or duplicate weedout */ #define HA_NON_COMPARABLE_ROWID (1ULL << 60) /* Implements SELECT ... FOR UPDATE SKIP LOCKED */ #define HA_CAN_SKIP_LOCKED (1ULL << 61) #define HA_CHECK_UNIQUE_AFTER_WRITE (1ULL << 62) /* This engine is not compatible with Online ALTER TABLE */ #define HA_NO_ONLINE_ALTER (1ULL << 63) #define HA_LAST_TABLE_FLAG HA_NO_ONLINE_ALTER /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ #define HA_READ_PREV 2 /* supports ::index_prev */ #define HA_READ_ORDER 4 /* index_next/prev follow sort order */ #define HA_READ_RANGE 8 /* can find all records in a range */ #define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */ #define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */ /* Index scan will not return records in rowid order. Not guaranteed to be set for unordered (e.g. HASH) indexes. */ #define HA_KEY_SCAN_NOT_ROR 128 #define HA_DO_INDEX_COND_PUSHDOWN 256 /* Supports Index Condition Pushdown */ /* Data is clustered on this key. This means that when you read the key you also get the row data without any additional disk reads. */ #define HA_CLUSTERED_INDEX 512 #define HA_DO_RANGE_FILTER_PUSHDOWN 1024 /* bits in alter_table_flags: */ /* These bits are set if different kinds of indexes can be created or dropped in-place without re-creating the table using a temporary table. NO_READ_WRITE indicates that the handler needs concurrent reads and writes of table data to be blocked. Partitioning needs both ADD and DROP to be supported by its underlying handlers, due to error handling, see bug#57778. */ #define HA_INPLACE_ADD_INDEX_NO_READ_WRITE (1UL << 0) #define HA_INPLACE_DROP_INDEX_NO_READ_WRITE (1UL << 1) #define HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE (1UL << 2) #define HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE (1UL << 3) #define HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE (1UL << 4) #define HA_INPLACE_DROP_PK_INDEX_NO_READ_WRITE (1UL << 5) /* These are set if different kinds of indexes can be created or dropped in-place while still allowing concurrent reads (but not writes) of table data. If a handler is capable of one or more of these, it should also set the corresponding *_NO_READ_WRITE bit(s). */ #define HA_INPLACE_ADD_INDEX_NO_WRITE (1UL << 6) #define HA_INPLACE_DROP_INDEX_NO_WRITE (1UL << 7) #define HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE (1UL << 8) #define HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE (1UL << 9) #define HA_INPLACE_ADD_PK_INDEX_NO_WRITE (1UL << 10) #define HA_INPLACE_DROP_PK_INDEX_NO_WRITE (1UL << 11) /* HA_PARTITION_FUNCTION_SUPPORTED indicates that the function is supported at all. HA_FAST_CHANGE_PARTITION means that optimised variants of the changes exists but they are not necessarily done online. HA_ONLINE_DOUBLE_WRITE means that the handler supports writing to both the new partition and to the old partitions when updating through the old partitioning schema while performing a change of the partitioning. This means that we can support updating of the table while performing the copy phase of the change. For no lock at all also a double write from new to old must exist and this is not required when this flag is set. This is actually removed even before it was introduced the first time. The new idea is that handlers will handle the lock level already in store_lock for ALTER TABLE partitions. HA_PARTITION_ONE_PHASE is a flag that can be set by handlers that take care of changing the partitions online and in one phase. Thus all phases needed to handle the change are implemented inside the storage engine. The storage engine must also support auto-discovery since the frm file is changed as part of the change and this change must be controlled by the storage engine. A typical engine to support this is NDB (through WL #2498). */ #define HA_PARTITION_FUNCTION_SUPPORTED (1UL << 12) #define HA_FAST_CHANGE_PARTITION (1UL << 13) #define HA_PARTITION_ONE_PHASE (1UL << 14) /* Note: the following includes binlog and closing 0. TODO remove the limit, use dynarrays */ #define MAX_HA 64 /* Use this instead of 0 as the initial value for the slot number of handlerton, so that we can distinguish uninitialized slot number from slot 0. */ #define HA_SLOT_UNDEF ((uint)-1) /* Parameters for open() (in register form->filestat) HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED */ #define HA_OPEN_KEYFILE 1U #define HA_READ_ONLY 16U /* File opened as readonly */ /* Try readonly if can't open with read and write */ #define HA_TRY_READ_ONLY 32U /* Some key definitions */ #define HA_KEY_NULL_LENGTH 1 #define HA_KEY_BLOB_LENGTH 2 /* Maximum length of any index lookup key, in bytes */ #define MAX_KEY_LENGTH (MAX_DATA_LENGTH_FOR_KEY \ +(MAX_REF_PARTS \ *(HA_KEY_NULL_LENGTH + HA_KEY_BLOB_LENGTH))) #define HA_LEX_CREATE_TMP_TABLE 1U #define HA_CREATE_TMP_ALTER 8U #define HA_LEX_CREATE_SEQUENCE 16U #define HA_VERSIONED_TABLE 32U #define HA_SKIP_KEY_SORT 64U /* A temporary table that can be used by different threads, eg. replication threads. This flag ensure that memory is not allocated with THREAD_SPECIFIC, as we do for other temporary tables. */ #define HA_LEX_CREATE_GLOBAL_TMP_TABLE 128U #define HA_MAX_REC_LENGTH 65535 /* Table caching type */ #define HA_CACHE_TBL_NONTRANSACT 0 #define HA_CACHE_TBL_NOCACHE 1U #define HA_CACHE_TBL_ASKTRANSACT 2U #define HA_CACHE_TBL_TRANSACT 4U /** Options for the START TRANSACTION statement. Note that READ ONLY and READ WRITE are logically mutually exclusive. This is enforced by the parser and depended upon by trans_begin(). We need two flags instead of one in order to differentiate between situation when no READ WRITE/ONLY clause were given and thus transaction is implicitly READ WRITE and the case when READ WRITE clause was used explicitly. */ // WITH CONSISTENT SNAPSHOT option static const uint MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT = 1; // READ ONLY option static const uint MYSQL_START_TRANS_OPT_READ_ONLY = 2; // READ WRITE option static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4; /* Flags for method is_fatal_error */ #define HA_CHECK_DUP_KEY 1U #define HA_CHECK_DUP_UNIQUE 2U #define HA_CHECK_FK_ERROR 4U #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE) #define HA_CHECK_ALL (~0U) /* Options for info_push() */ #define INFO_KIND_UPDATE_FIELDS 101 #define INFO_KIND_UPDATE_VALUES 102 #define INFO_KIND_FORCE_LIMIT_BEGIN 103 #define INFO_KIND_FORCE_LIMIT_END 104 enum legacy_db_type { /* note these numerical values are fixed and can *not* be changed */ DB_TYPE_UNKNOWN=0, DB_TYPE_HEAP=6, DB_TYPE_MYISAM=9, DB_TYPE_MRG_MYISAM=10, DB_TYPE_INNODB=12, DB_TYPE_EXAMPLE_DB=15, DB_TYPE_ARCHIVE_DB=16, DB_TYPE_CSV_DB=17, DB_TYPE_FEDERATED_DB=18, DB_TYPE_BLACKHOLE_DB=19, DB_TYPE_PARTITION_DB=20, DB_TYPE_BINLOG=21, DB_TYPE_ONLINE_ALTER=22, DB_TYPE_PBXT=23, DB_TYPE_PERFORMANCE_SCHEMA=28, DB_TYPE_S3=41, DB_TYPE_ARIA=42, DB_TYPE_TOKUDB=43, /* disabled in MariaDB Server 10.5, removed in 10.6 */ DB_TYPE_SEQUENCE=44, DB_TYPE_FIRST_DYNAMIC=45, DB_TYPE_DEFAULT=127 // Must be last }; /* Better name for DB_TYPE_UNKNOWN. Should be used for engines that do not have a hard-coded type value here. */ #define DB_TYPE_AUTOASSIGN DB_TYPE_UNKNOWN enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED, ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT, ROW_TYPE_PAGE }; /* not part of the enum, so that it shouldn't be in switch(row_type) */ #define ROW_TYPE_MAX ((uint)ROW_TYPE_PAGE + 1) /* Specifies data storage format for individual columns */ enum column_format_type { COLUMN_FORMAT_TYPE_DEFAULT= 0, /* Not specified (use engine default) */ COLUMN_FORMAT_TYPE_FIXED= 1, /* FIXED format */ COLUMN_FORMAT_TYPE_DYNAMIC= 2 /* DYNAMIC format */ }; enum enum_binlog_func { BFN_RESET_LOGS= 1, BFN_RESET_SLAVE= 2, BFN_BINLOG_WAIT= 3, BFN_BINLOG_END= 4, BFN_BINLOG_PURGE_FILE= 5 }; enum enum_binlog_command { LOGCOM_CREATE_TABLE, LOGCOM_ALTER_TABLE, LOGCOM_RENAME_TABLE, LOGCOM_DROP_TABLE, LOGCOM_CREATE_DB, LOGCOM_ALTER_DB, LOGCOM_DROP_DB }; /* struct to hold information about the table that should be created */ /* Bits in used_fields */ #define HA_CREATE_USED_AUTO (1UL << 0) #define HA_CREATE_USED_RAID (1UL << 1) //RAID is no longer available #define HA_CREATE_USED_UNION (1UL << 2) #define HA_CREATE_USED_INSERT_METHOD (1UL << 3) #define HA_CREATE_USED_MIN_ROWS (1UL << 4) #define HA_CREATE_USED_MAX_ROWS (1UL << 5) #define HA_CREATE_USED_AVG_ROW_LENGTH (1UL << 6) #define HA_CREATE_USED_PACK_KEYS (1UL << 7) #define HA_CREATE_USED_CHARSET (1UL << 8) #define HA_CREATE_USED_DEFAULT_CHARSET (1UL << 9) #define HA_CREATE_USED_DATADIR (1UL << 10) #define HA_CREATE_USED_INDEXDIR (1UL << 11) #define HA_CREATE_USED_ENGINE (1UL << 12) #define HA_CREATE_USED_CHECKSUM (1UL << 13) #define HA_CREATE_USED_DELAY_KEY_WRITE (1UL << 14) #define HA_CREATE_USED_ROW_FORMAT (1UL << 15) #define HA_CREATE_USED_COMMENT (1UL << 16) #define HA_CREATE_USED_PASSWORD (1UL << 17) #define HA_CREATE_USED_CONNECTION (1UL << 18) #define HA_CREATE_USED_KEY_BLOCK_SIZE (1UL << 19) /* The following two are used by Maria engine: */ #define HA_CREATE_USED_TRANSACTIONAL (1UL << 20) #define HA_CREATE_USED_PAGE_CHECKSUM (1UL << 21) /** This is set whenever STATS_PERSISTENT=0|1|default has been specified in CREATE/ALTER TABLE. See also HA_OPTION_STATS_PERSISTENT in include/my_base.h. It is possible to distinguish whether STATS_PERSISTENT=default has been specified or no STATS_PERSISTENT= is given at all. */ #define HA_CREATE_USED_STATS_PERSISTENT (1UL << 22) /** This is set whenever STATS_AUTO_RECALC=0|1|default has been specified in CREATE/ALTER TABLE. See enum_stats_auto_recalc. It is possible to distinguish whether STATS_AUTO_RECALC=default has been specified or no STATS_AUTO_RECALC= is given at all. */ #define HA_CREATE_USED_STATS_AUTO_RECALC (1UL << 23) /** This is set whenever STATS_SAMPLE_PAGES=N|default has been specified in CREATE/ALTER TABLE. It is possible to distinguish whether STATS_SAMPLE_PAGES=default has been specified or no STATS_SAMPLE_PAGES= is given at all. */ #define HA_CREATE_USED_STATS_SAMPLE_PAGES (1UL << 24) /* Create a sequence */ #define HA_CREATE_USED_SEQUENCE (1UL << 25) /* Tell binlog_show_create_table to print all engine options */ #define HA_CREATE_PRINT_ALL_OPTIONS (1UL << 26) typedef ulonglong alter_table_operations; class Event_log; class Cache_flip_event_log; class binlog_cache_data; class online_alter_cache_data; typedef bool Log_func(THD*, TABLE*, Event_log *, binlog_cache_data *, bool, ulong, const uchar*, const uchar*); /* These flags are set by the parser and describes the type of operation(s) specified by the ALTER TABLE statement. */ // Set by parser for ADD [COLUMN] #define ALTER_PARSER_ADD_COLUMN (1ULL << 0) // Set by parser for DROP [COLUMN] #define ALTER_PARSER_DROP_COLUMN (1ULL << 1) // Set for CHANGE [COLUMN] | MODIFY [CHANGE] & mysql_recreate_table #define ALTER_CHANGE_COLUMN (1ULL << 2) // Set for ADD INDEX | ADD KEY | ADD PRIMARY KEY | ADD UNIQUE KEY | // ADD UNIQUE INDEX | ALTER ADD [COLUMN] #define ALTER_ADD_INDEX (1ULL << 3) // Set for DROP PRIMARY KEY | DROP FOREIGN KEY | DROP KEY | DROP INDEX #define ALTER_DROP_INDEX (1ULL << 4) // Set for RENAME [TO] #define ALTER_RENAME (1ULL << 5) // Set for ORDER BY #define ALTER_ORDER (1ULL << 6) // Set for table_options, like table comment #define ALTER_OPTIONS (1ULL << 7) // Set for ALTER [COLUMN] ... SET DEFAULT ... | DROP DEFAULT #define ALTER_CHANGE_COLUMN_DEFAULT (1ULL << 8) // Set for DISABLE KEYS | ENABLE KEYS #define ALTER_KEYS_ONOFF (1ULL << 9) // Set for FORCE, ENGINE(same engine), by mysql_recreate_table() #define ALTER_RECREATE (1ULL << 10) // Set for CONVERT TO #define ALTER_CONVERT_TO (1ULL << 11) // Set for DROP ... ADD some_index #define ALTER_RENAME_INDEX (1ULL << 12) // Set for ADD FOREIGN KEY #define ALTER_ADD_FOREIGN_KEY (1ULL << 21) // Set for DROP FOREIGN KEY #define ALTER_DROP_FOREIGN_KEY (1ULL << 22) #define ALTER_CHANGE_INDEX_COMMENT (1ULL << 23) // Set for ADD [COLUMN] FIRST | AFTER #define ALTER_COLUMN_ORDER (1ULL << 25) #define ALTER_ADD_CHECK_CONSTRAINT (1ULL << 27) #define ALTER_DROP_CHECK_CONSTRAINT (1ULL << 28) #define ALTER_RENAME_COLUMN (1ULL << 29) #define ALTER_COLUMN_UNVERSIONED (1ULL << 30) #define ALTER_ADD_SYSTEM_VERSIONING (1ULL << 31) #define ALTER_DROP_SYSTEM_VERSIONING (1ULL << 32) #define ALTER_ADD_PERIOD (1ULL << 33) #define ALTER_DROP_PERIOD (1ULL << 34) /* Following defines are used by ALTER_INPLACE_TABLE They do describe in more detail the type operation(s) to be executed by the storage engine. For example, which type of type of index to be added/dropped. These are set by fill_alter_inplace_info(). */ #define ALTER_RECREATE_TABLE ALTER_RECREATE #define ALTER_CHANGE_CREATE_OPTION ALTER_OPTIONS #define ALTER_ADD_COLUMN (ALTER_ADD_VIRTUAL_COLUMN | \ ALTER_ADD_STORED_BASE_COLUMN | \ ALTER_ADD_STORED_GENERATED_COLUMN) #define ALTER_DROP_COLUMN (ALTER_DROP_VIRTUAL_COLUMN | \ ALTER_DROP_STORED_COLUMN) #define ALTER_COLUMN_DEFAULT ALTER_CHANGE_COLUMN_DEFAULT // Add non-unique, non-primary index #define ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX (1ULL << 35) // Drop non-unique, non-primary index #define ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX (1ULL << 36) // Add unique, non-primary index #define ALTER_ADD_UNIQUE_INDEX (1ULL << 37) // Drop unique, non-primary index #define ALTER_DROP_UNIQUE_INDEX (1ULL << 38) // Add primary index #define ALTER_ADD_PK_INDEX (1ULL << 39) // Drop primary index #define ALTER_DROP_PK_INDEX (1ULL << 40) // Virtual generated column #define ALTER_ADD_VIRTUAL_COLUMN (1ULL << 41) // Stored base (non-generated) column #define ALTER_ADD_STORED_BASE_COLUMN (1ULL << 42) // Stored generated column #define ALTER_ADD_STORED_GENERATED_COLUMN (1ULL << 43) // Drop column #define ALTER_DROP_VIRTUAL_COLUMN (1ULL << 44) #define ALTER_DROP_STORED_COLUMN (1ULL << 45) // Rename column (verified; ALTER_RENAME_COLUMN may use original name) #define ALTER_COLUMN_NAME (1ULL << 46) // Change column datatype #define ALTER_VIRTUAL_COLUMN_TYPE (1ULL << 47) #define ALTER_STORED_COLUMN_TYPE (1ULL << 48) // Engine can handle type change by itself in ALGORITHM=INPLACE #define ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE (1ULL << 49) // Reorder column #define ALTER_STORED_COLUMN_ORDER (1ULL << 50) // Reorder column #define ALTER_VIRTUAL_COLUMN_ORDER (1ULL << 51) // Change column from NOT NULL to NULL #define ALTER_COLUMN_NULLABLE (1ULL << 52) // Change column from NULL to NOT NULL #define ALTER_COLUMN_NOT_NULLABLE (1ULL << 53) // Change column generation expression #define ALTER_VIRTUAL_GCOL_EXPR (1ULL << 54) #define ALTER_STORED_GCOL_EXPR (1ULL << 55) // column's engine options changed, something in field->option_struct #define ALTER_COLUMN_OPTION (1ULL << 56) // MySQL alias for the same thing: #define ALTER_COLUMN_STORAGE_TYPE ALTER_COLUMN_OPTION // Change the column format of column #define ALTER_COLUMN_COLUMN_FORMAT (1ULL << 57) /** Changes in generated columns that affect storage, for example, when a vcol type or expression changes and this vcol is indexed or used in a partitioning expression */ #define ALTER_COLUMN_VCOL (1ULL << 58) /** ALTER TABLE for a partitioned table. The engine needs to commit online alter of all partitions atomically (using group_commit_ctx) */ #define ALTER_PARTITIONED (1ULL << 59) /** Change in index length such that it doesn't require index rebuild. */ #define ALTER_COLUMN_INDEX_LENGTH (1ULL << 60) /** Indicate that index order might have been changed. Disables inplace algorithm by default (not for InnoDB). */ #define ALTER_INDEX_ORDER (1ULL << 61) /** Means that the ignorability of an index is changed. */ #define ALTER_INDEX_IGNORABILITY (1ULL << 62) /* Flags set in partition_flags when altering partitions */ // Set for ADD PARTITION #define ALTER_PARTITION_ADD (1ULL << 1) // Set for DROP PARTITION #define ALTER_PARTITION_DROP (1ULL << 2) // Set for COALESCE PARTITION #define ALTER_PARTITION_COALESCE (1ULL << 3) // Set for REORGANIZE PARTITION ... INTO #define ALTER_PARTITION_REORGANIZE (1ULL << 4) // Set for partition_options #define ALTER_PARTITION_INFO (1ULL << 5) // Set for LOAD INDEX INTO CACHE ... PARTITION // Set for CACHE INDEX ... PARTITION #define ALTER_PARTITION_ADMIN (1ULL << 6) // Set for REBUILD PARTITION #define ALTER_PARTITION_REBUILD (1ULL << 7) // Set for partitioning operations specifying ALL keyword #define ALTER_PARTITION_ALL (1ULL << 8) // Set for REMOVE PARTITIONING #define ALTER_PARTITION_REMOVE (1ULL << 9) // Set for EXCHANGE PARITION #define ALTER_PARTITION_EXCHANGE (1ULL << 10) // Set by Sql_cmd_alter_table_truncate_partition::execute() #define ALTER_PARTITION_TRUNCATE (1ULL << 11) // Set for REORGANIZE PARTITION #define ALTER_PARTITION_TABLE_REORG (1ULL << 12) #define ALTER_PARTITION_CONVERT_IN (1ULL << 13) #define ALTER_PARTITION_CONVERT_OUT (1ULL << 14) // Set for vers_add_auto_hist_parts() operation #define ALTER_PARTITION_AUTO_HIST (1ULL << 15) /* This is master database for most of system tables. However there can be other databases which can hold system tables. Respective storage engines define their own system database names. */ extern const char *mysqld_system_database; /* Structure to hold list of system_database.system_table. This is used at both mysqld and storage engine layer. */ struct st_system_tablename { const char *db; const char *tablename; }; typedef ulonglong my_xid; // this line is the same as in log_event.h #define MYSQL_XID_PREFIX "MySQLXid" #define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8 #define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id)) #define MYSQL_XID_GTRID_LEN (MYSQL_XID_OFFSET+sizeof(my_xid)) #define XIDDATASIZE MYSQL_XIDDATASIZE #define MAXGTRIDSIZE 64 #define MAXBQUALSIZE 64 #define COMPATIBLE_DATA_YES 0 #define COMPATIBLE_DATA_NO 1 /** struct xid_t is binary compatible with the XID structure as in the X/Open CAE Specification, Distributed Transaction Processing: The XA Specification, X/Open Company Ltd., 1991. http://www.opengroup.org/bookstore/catalog/c193.htm @see MYSQL_XID in mysql/plugin.h */ struct xid_t { long formatID; long gtrid_length; long bqual_length; char data[XIDDATASIZE]; // not \0-terminated ! xid_t() = default; /* Remove gcc warning */ bool eq(struct xid_t *xid) const { return !xid->is_null() && eq(xid->gtrid_length, xid->bqual_length, xid->data); } bool eq(long g, long b, const char *d) const { return !is_null() && g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); } void set(struct xid_t *xid) { memcpy(this, xid, xid->length()); } void set(long f, const char *g, long gl, const char *b, long bl) { formatID= f; if ((gtrid_length= gl)) memcpy(data, g, gl); if ((bqual_length= bl)) memcpy(data+gl, b, bl); } // Populate server_id if it's specified, otherwise use the current server_id void set(ulonglong xid, decltype(::server_id) trx_server_id= server_id) { my_xid tmp; formatID= 1; set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX); memcpy(data+MYSQL_XID_PREFIX_LEN, &trx_server_id, sizeof(trx_server_id)); tmp= xid; memcpy(data+MYSQL_XID_OFFSET, &tmp, sizeof(tmp)); gtrid_length=MYSQL_XID_GTRID_LEN; } void set(long g, long b, const char *d) { formatID= 1; gtrid_length= g; bqual_length= b; memcpy(data, d, g+b); } bool is_null() const { return formatID == -1; } void null() { formatID= -1; } my_xid quick_get_my_xid() { my_xid tmp; memcpy(&tmp, data+MYSQL_XID_OFFSET, sizeof(tmp)); return tmp; } my_xid get_my_xid() { return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 && !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ? quick_get_my_xid() : 0; } decltype(::server_id) get_trx_server_id() { decltype(::server_id) trx_server_id; memcpy(&trx_server_id, data+MYSQL_XID_PREFIX_LEN, sizeof(trx_server_id)); return trx_server_id; } uint length() { return static_cast<uint>(sizeof(formatID)) + key_length(); } uchar *key() const { return (uchar *)>rid_length; } uint key_length() const { return static_cast<uint>(sizeof(gtrid_length)+sizeof(bqual_length)+ gtrid_length+bqual_length); } }; typedef struct xid_t XID; struct Online_alter_cache_list; struct XA_data: XID { Online_alter_cache_list *online_alter_cache= NULL; XA_data &operator=(const XID &x) { XID::operator=(x); return *this; } }; /* Enumerates a sequence in the order of their creation that is in the top-down order of the index file. Ranges from zero through MAX_binlog_id. Not confuse the value with the binlog file numerical suffix, neither with the binlog file line in the binlog index file. */ typedef uint Binlog_file_id; const Binlog_file_id MAX_binlog_id= UINT_MAX; const my_off_t MAX_off_t = (~(my_off_t) 0); /* Compound binlog-id and byte offset of transaction's first event in a sequence (e.g the recovery sequence) of binlog files. Binlog_offset(0,0) is the minimum value to mean the first byte of the first binlog file. */ typedef std::pair<Binlog_file_id, my_off_t> Binlog_offset; /* binlog-based recovery transaction descriptor */ struct xid_recovery_member { my_xid xid; uint in_engine_prepare; // number of engines that have xid prepared bool decided_to_commit; /* Semisync recovery binlog offset. It's initialized with the maximum unreachable offset. The max value will remain for any transaction not found in binlog to yield its rollback decision as it's guaranteed to be within a truncated tail part of the binlog. */ Binlog_offset binlog_coord; XID *full_xid; // needed by wsrep or past it recovery decltype(::server_id) server_id; // server id of orginal server xid_recovery_member(my_xid xid_arg, uint prepare_arg, bool decided_arg, XID *full_xid_arg, decltype(::server_id) server_id_arg) : xid(xid_arg), in_engine_prepare(prepare_arg), decided_to_commit(decided_arg), binlog_coord(Binlog_offset(MAX_binlog_id, MAX_off_t)), full_xid(full_xid_arg), server_id(server_id_arg) {}; }; /* for recover() handlerton call */ #define MIN_XID_LIST_SIZE 128 #define MAX_XID_LIST_SIZE (1024*128) /* Statistics about batch operations like bulk_insert */ struct ha_copy_info { ha_rows records; /* Used to check if rest of variables can be used */ ha_rows touched; ha_rows copied; ha_rows deleted; ha_rows updated; }; /* The handler for a table type. Will be included in the TABLE structure */ struct TABLE; /* Make sure that the order of schema_tables and enum_schema_tables are the same. */ enum enum_schema_tables { SCH_ALL_PLUGINS, SCH_APPLICABLE_ROLES, SCH_CHARSETS, SCH_CHECK_CONSTRAINTS, SCH_COLLATIONS, SCH_COLLATION_CHARACTER_SET_APPLICABILITY, SCH_COLUMNS, SCH_COLUMN_PRIVILEGES, SCH_ENABLED_ROLES, SCH_ENGINES, SCH_EVENTS, SCH_EXPLAIN_TABULAR, SCH_EXPLAIN_JSON, SCH_ANALYZE_TABULAR, SCH_ANALYZE_JSON, SCH_FILES, SCH_GLOBAL_STATUS, SCH_GLOBAL_VARIABLES, SCH_KEYWORDS, SCH_KEY_CACHES, SCH_KEY_COLUMN_USAGE, SCH_KEY_PERIOD_USAGE, SCH_OPEN_TABLES, SCH_OPTIMIZER_COSTS, SCH_OPT_TRACE, SCH_PARAMETERS, SCH_PERIODS, SCH_PARTITIONS, SCH_PLUGINS, SCH_PROCESSLIST, SCH_PROFILES, SCH_REFERENTIAL_CONSTRAINTS, SCH_PROCEDURES, SCH_SCHEMATA, SCH_SCHEMA_PRIVILEGES, SCH_SESSION_STATUS, SCH_SESSION_VARIABLES, SCH_STATISTICS, SCH_SQL_FUNCTIONS, SCH_SYSTEM_VARIABLES, SCH_TABLES, SCH_TABLESPACES, SCH_TABLE_CONSTRAINTS, SCH_TABLE_NAMES, SCH_TABLE_PRIVILEGES, SCH_TRIGGERS, SCH_USER_PRIVILEGES, SCH_VIEWS, SCH_N_SERVER_TABLES, /* How many SCHEMA tables in the server. */ SCH_PLUGIN_TABLE /* Schema table defined in plugin. */ }; struct TABLE_SHARE; struct HA_CREATE_INFO; struct st_foreign_key_info; typedef struct st_foreign_key_info FOREIGN_KEY_INFO; typedef bool (stat_print_fn)(THD *thd, const char *type, size_t type_len, const char *file, size_t file_len, const char *status, size_t status_len); enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; extern MYSQL_PLUGIN_IMPORT st_plugin_int *hton2plugin[MAX_HA]; struct handlerton; #define view_pseudo_hton ((handlerton *)1) /* Definitions for engine-specific table/field/index options in the CREATE TABLE. Options are declared with HA_*OPTION_* macros (HA_TOPTION_NUMBER, HA_FOPTION_ENUM, HA_IOPTION_STRING, etc). Every macros takes the option name, and the name of the underlying field of the appropriate C structure. The "appropriate C structure" is ha_table_option_struct for table level options, ha_field_option_struct for field level options, ha_index_option_struct for key level options. The engine either defines a structure of this name, or uses #define's to map these "appropriate" names to the actual structure type name. ULL options use a ulonglong as the backing store. HA_*OPTION_NUMBER() takes the option name, the structure field name, the default value for the option, min, max, and blk_siz values. STRING options use a char* as a backing store. HA_*OPTION_STRING takes the option name and the structure field name. The default value will be 0. ENUM options use a uint as a backing store (not enum!!!). HA_*OPTION_ENUM takes the option name, the structure field name, the default value for the option as a number, and a string with the permitted values for this enum - one string with comma separated values, for example: "gzip,bzip2,lzma" BOOL options use a bool as a backing store. HA_*OPTION_BOOL takes the option name, the structure field name, and the default value for the option. From the SQL, BOOL options accept YES/NO, ON/OFF, and 1/0. The name of the option is limited to 255 bytes, the value (for string options) - to the 32767 bytes. See ha_example.cc for an example. */ struct ha_table_option_struct; struct ha_field_option_struct; struct ha_index_option_struct; enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */ HA_OPTION_TYPE_STRING, /* char * */ HA_OPTION_TYPE_ENUM, /* uint */ HA_OPTION_TYPE_BOOL, /* bool */ HA_OPTION_TYPE_SYSVAR};/* type of the sysval */ #define HA_xOPTION_NUMBER(name, struc, field, def, min, max, blk_siz) \ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \ offsetof(struc, field), def, min, max, blk_siz, 0, 0 } #define HA_xOPTION_STRING(name, struc, field) \ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \ offsetof(struc, field), 0, 0, 0, 0, 0, 0} #define HA_xOPTION_ENUM(name, struc, field, values, def) \ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \ offsetof(struc, field), def, 0, \ sizeof(values)-1, 0, values, 0 } #define HA_xOPTION_BOOL(name, struc, field, def) \ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \ offsetof(struc, field), def, 0, 1, 0, 0, 0 } #define HA_xOPTION_SYSVAR(name, struc, field, sysvar) \ { HA_OPTION_TYPE_SYSVAR, name, sizeof(name)-1, \ offsetof(struc, field), 0, 0, 0, 0, 0, MYSQL_SYSVAR(sysvar) } #define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0, 0 } #define HA_TOPTION_NUMBER(name, field, def, min, max, blk_siz) \ HA_xOPTION_NUMBER(name, ha_table_option_struct, field, def, min, max, blk_siz) #define HA_TOPTION_STRING(name, field) \ HA_xOPTION_STRING(name, ha_table_option_struct, field) #define HA_TOPTION_ENUM(name, field, values, def) \ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def) #define HA_TOPTION_BOOL(name, field, def) \ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def) #define HA_TOPTION_SYSVAR(name, field, sysvar) \ HA_xOPTION_SYSVAR(name, ha_table_option_struct, field, sysvar) #define HA_TOPTION_END HA_xOPTION_END #define HA_FOPTION_NUMBER(name, field, def, min, max, blk_siz) \ HA_xOPTION_NUMBER(name, ha_field_option_struct, field, def, min, max, blk_siz) #define HA_FOPTION_STRING(name, field) \ HA_xOPTION_STRING(name, ha_field_option_struct, field) #define HA_FOPTION_ENUM(name, field, values, def) \ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def) #define HA_FOPTION_BOOL(name, field, def) \ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def) #define HA_FOPTION_SYSVAR(name, field, sysvar) \ HA_xOPTION_SYSVAR(name, ha_field_option_struct, field, sysvar) #define HA_FOPTION_END HA_xOPTION_END #define HA_IOPTION_NUMBER(name, field, def, min, max, blk_siz) \ HA_xOPTION_NUMBER(name, ha_index_option_struct, field, def, min, max, blk_siz) #define HA_IOPTION_STRING(name, field) \ HA_xOPTION_STRING(name, ha_index_option_struct, field) #define HA_IOPTION_ENUM(name, field, values, def) \ HA_xOPTION_ENUM(name, ha_index_option_struct, field, values, def) #define HA_IOPTION_BOOL(name, field, def) \ HA_xOPTION_BOOL(name, ha_index_option_struct, field, def) #define HA_IOPTION_SYSVAR(name, field, sysvar) \ HA_xOPTION_SYSVAR(name, ha_index_option_struct, field, sysvar) #define HA_IOPTION_END HA_xOPTION_END typedef struct st_ha_create_table_option { enum ha_option_type type; const char *name; size_t name_length; ptrdiff_t offset; ulonglong def_value; ulonglong min_value, max_value, block_size; const char *values; struct st_mysql_sys_var *var; } ha_create_table_option; class handler; class group_by_handler; class derived_handler; class select_handler; struct Query; typedef class st_select_lex SELECT_LEX; typedef class st_select_lex_unit SELECT_LEX_UNIT; typedef struct st_order ORDER; /* handlerton is a singleton structure - one instance per storage engine - to provide access to storage engine functionality that works on the "global" level (unlike handler class that works on a per-table basis) usually handlerton instance is defined statically in ha_xxx.cc as static handlerton { ... } xxx_hton; savepoint_*, prepare, recover, and *_by_xid pointers can be 0. */ struct handlerton { /* Historical number used for frm file to determine the correct storage engine. This is going away and new engines will just use "name" for this. */ enum legacy_db_type db_type; /* each storage engine has it's own memory area (actually a pointer) in the thd, for storing per-connection information. It is accessed as thd->ha_data[xxx_hton.slot] slot number is initialized by MySQL after xxx_init() is called. */ uint slot; /* to store per-savepoint data storage engine is provided with an area of a requested size (0 is ok here). savepoint_offset must be initialized statically to the size of the needed memory to store per-savepoint information. After xxx_init it is changed to be an offset to savepoint storage area and need not be used by storage engine. see binlog_hton and binlog_savepoint_set/rollback for an example. */ uint savepoint_offset; /* handlerton methods: close_connection is only called if thd->ha_data[xxx_hton.slot] is non-zero, so even if you don't need this storage area - set it to something, so that MySQL would know this storage engine was accessed in this connection */ int (*close_connection)(handlerton *hton, THD *thd); /* Tell handler that query has been killed. */ void (*kill_query)(handlerton *hton, THD *thd, enum thd_kill_levels level); /* sv points to an uninitialized storage area of requested size (see savepoint_offset description) */ int (*savepoint_set)(handlerton *hton, THD *thd, void *sv); /* sv points to a storage area, that was earlier passed to the savepoint_set call */ int (*savepoint_rollback)(handlerton *hton, THD *thd, void *sv); /** Check if storage engine allows to release metadata locks which were acquired after the savepoint if rollback to savepoint is done. @return true - If it is safe to release MDL locks. false - If it is not. */ bool (*savepoint_rollback_can_release_mdl)(handlerton *hton, THD *thd); int (*savepoint_release)(handlerton *hton, THD *thd, void *sv); /* 'all' is true if it's a real commit, that makes persistent changes 'all' is false if it's not in fact a commit but an end of the statement that is part of the transaction. NOTE 'all' is also false in auto-commit mode where 'end of statement' and 'real commit' mean the same event. */ int (*commit)(handlerton *hton, THD *thd, bool all); /* The commit_ordered() method is called prior to the commit() method, after the transaction manager has decided to commit (not rollback) the transaction. Unlike commit(), commit_ordered() is called only when the full transaction is committed, not for each commit of statement transaction in a multi-statement transaction. Not that like prepare(), commit_ordered() is only called when 2-phase commit takes place. Ie. when no binary log and only a single engine participates in a transaction, one commit() is called, no commit_ordered(). So engines must be prepared for this. The calls to commit_ordered() in multiple parallel transactions is guaranteed to happen in the same order in every participating handler. This can be used to ensure the same commit order among multiple handlers (eg. in table handler and binlog). So if transaction T1 calls into commit_ordered() of handler A before T2, then T1 will also call commit_ordered() of handler B before T2. Engines that implement this method should during this call make the transaction visible to other transactions, thereby making the order of transaction commits be defined by the order of commit_ordered() calls. The intention is that commit_ordered() should do the minimal amount of work that needs to happen in consistent commit order among handlers. To preserve ordering, calls need to be serialised on a global mutex, so doing any time-consuming or blocking operations in commit_ordered() will limit scalability. Handlers can rely on commit_ordered() calls to be serialised (no two calls can run in parallel, so no extra locking on the handler part is required to ensure this). Note that commit_ordered() can be called from a different thread than the one handling the transaction! So it can not do anything that depends on thread local storage, in particular it can not call my_error() and friends (instead it can store the error code and delay the call of my_error() to the commit() method). Similarly, since commit_ordered() returns void, any return error code must be saved and returned from the commit() method instead. The commit_ordered method is optional, and can be left unset if not needed in a particular handler (then there will be no ordering guarantees wrt. other engines and binary log). */ void (*commit_ordered)(handlerton *hton, THD *thd, bool all); int (*rollback)(handlerton *hton, THD *thd, bool all); int (*prepare)(handlerton *hton, THD *thd, bool all); /* The prepare_ordered method is optional. If set, it will be called after successful prepare() in all handlers participating in 2-phase commit. Like commit_ordered(), it is called only when the full transaction is committed, not for each commit of statement transaction. The calls to prepare_ordered() among multiple parallel transactions are ordered consistently with calls to commit_ordered(). This means that calls to prepare_ordered() effectively define the commit order, and that each handler will see the same sequence of transactions calling into prepare_ordered() and commit_ordered(). Thus, prepare_ordered() can be used to define commit order for handlers that need to do this in the prepare step (like binlog). It can also be used to release transaction's locks early in an order consistent with the order transactions will be eventually committed. Like commit_ordered(), prepare_ordered() calls are serialised to maintain ordering, so the intention is that they should execute fast, with only the minimal amount of work needed to define commit order. Handlers can rely on this serialisation, and do not need to do any extra locking to avoid two prepare_ordered() calls running in parallel. Like commit_ordered(), prepare_ordered() is not guaranteed to be called in the context of the thread handling the rest of the transaction. So it cannot invoke code that relies on thread local storage, in particular it cannot call my_error(). prepare_ordered() cannot cause a rollback by returning an error, all possible errors must be handled in prepare() (the prepare_ordered() method returns void). In case of some fatal error, a record of the error must be made internally by the engine and returned from commit() later. Note that for user-level XA SQL commands, no consistent ordering among prepare_ordered() and commit_ordered() is guaranteed (as that would require blocking all other commits for an indefinite time). When 2-phase commit is not used (eg. only one engine (and no binlog) in transaction), neither prepare() nor prepare_ordered() is called. */ void (*prepare_ordered)(handlerton *hton, THD *thd, bool all); int (*recover)(handlerton *hton, XID *xid_list, uint len); int (*commit_by_xid)(handlerton *hton, XID *xid); int (*rollback_by_xid)(handlerton *hton, XID *xid); /* The commit_checkpoint_request() handlerton method is used to checkpoint the XA recovery process for storage engines that support two-phase commit. The method is optional - an engine that does not implemented is expected to work the traditional way, where every commit() durably flushes the transaction to disk in the engine before completion, so XA recovery will no longer be needed for that transaction. An engine that does implement commit_checkpoint_request() is also expected to implement commit_ordered(), so that ordering of commits is consistent between 2pc participants. Such engine is no longer required to durably flush to disk transactions in commit(), provided that the transaction has been successfully prepare()d and commit_ordered(); thus potentionally saving one fsync() call. (Engine must still durably flush to disk in commit() when no prepare()/commit_ordered() steps took place, at least if durable commits are wanted; this happens eg. if binlog is disabled). The TC will periodically (eg. once per binlog rotation) call commit_checkpoint_request(). When this happens, the engine must arrange for all transaction that have completed commit_ordered() to be durably flushed to disk (this does not include transactions that might be in the middle of executing commit_ordered()). When such flush has completed, the engine must call commit_checkpoint_notify_ha(), passing back the opaque "cookie". The flush and call of commit_checkpoint_notify_ha() need not happen immediately - it can be scheduled and performed asynchronously (ie. as part of next prepare(), or sync every second, or whatever), but should not be postponed indefinitely. It is however also permissible to do it immediately, before returning from commit_checkpoint_request(). When commit_checkpoint_notify_ha() is called, the TC will know that the transactions are durably committed, and thus no longer require XA recovery. It uses that to reduce the work needed for any subsequent XA recovery process. */ void (*commit_checkpoint_request)(void *cookie); /* "Disable or enable checkpointing internal to the storage engine. This is used for FLUSH TABLES WITH READ LOCK AND DISABLE CHECKPOINT to ensure that the engine will never start any recovery from a time between FLUSH TABLES ... ; UNLOCK TABLES. While checkpointing is disabled, the engine should pause any background write activity (such as tablespace checkpointing) that require consistency between different files (such as transaction log and tablespace files) for crash recovery to succeed. The idea is to use this to make safe multi-volume LVM snapshot backups. */ int (*checkpoint_state)(handlerton *hton, bool disabled); void *(*create_cursor_read_view)(handlerton *hton, THD *thd); void (*set_cursor_read_view)(handlerton *hton, THD *thd, void *read_view); void (*close_cursor_read_view)(handlerton *hton, THD *thd, void *read_view); handler *(*create)(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); void (*drop_database)(handlerton *hton, char* path); /* return 0 if dropped successfully, -1 if nothing was done by design (as in e.g. blackhole) an error code (e.g. HA_ERR_NO_SUCH_TABLE) otherwise */ int (*drop_table)(handlerton *hton, const char* path); int (*panic)(handlerton *hton, enum ha_panic_function flag); int (*start_consistent_snapshot)(handlerton *hton, THD *thd); bool (*flush_logs)(handlerton *hton); bool (*show_status)(handlerton *hton, THD *thd, stat_print_fn *print, enum ha_stat_type stat); uint (*partition_flags)(); alter_table_operations (*alter_table_flags)(alter_table_operations flags); int (*fill_is_table)(handlerton *hton, THD *thd, TABLE_LIST *tables, class Item *cond, enum enum_schema_tables); uint32 flags; /* global handler flags */ /* Those handlerton functions below are properly initialized at handler init. */ int (*binlog_func)(handlerton *hton, THD *thd, enum_binlog_func fn, void *arg); void (*binlog_log_query)(handlerton *hton, THD *thd, enum_binlog_command binlog_command, const char *query, uint query_length, const char *db, const char *table_name); void (*abort_transaction)(handlerton *hton, THD *bf_thd, THD *victim_thd, my_bool signal) __attribute__((nonnull)); int (*set_checkpoint)(handlerton *hton, const XID *xid); int (*get_checkpoint)(handlerton *hton, XID* xid); /** Check if the version of the table matches the version in the .frm file. This is mainly used to verify in recovery to check if an inplace ALTER TABLE succeded. Storage engines that does not support inplace alter table does not have to implement this function. @param hton handlerton @param path Path for table @param version The unique id that is stored in the .frm file for CREATE and updated for each ALTER TABLE (but not for simple renames). This is the ID used for the final table. @param create_id The value returned from handler->table_version() for the original table (before ALTER TABLE). @retval 0 If id matches or table is newer than create_id (depending on what version check the engine supports. This means that The (inplace) alter table did succeed. @retval # > 0 Alter table did not succeed. Related to handler::discover_check_version(). */ int (*check_version)(handlerton *hton, const char *path, const LEX_CUSTRING *version, ulonglong create_id); /* Called for all storage handlers after ddl recovery is done */ int (*signal_ddl_recovery_done)(handlerton *hton); /* Called at startup to update default engine costs */ void (*update_optimizer_costs)(OPTIMIZER_COSTS *costs); void *optimizer_costs; /* Costs are stored here */ /* Optional clauses in the CREATE/ALTER TABLE */ ha_create_table_option *table_options; // table level options ha_create_table_option *field_options; // these are specified per field ha_create_table_option *index_options; // these are specified per index /** The list of extensions of files created for a single table in the database directory (datadir/db_name/). Used by open_table_error(), by the default rename_table and delete_table handler methods, and by the default discovery implementation. For engines that have more than one file name extensions (separate metadata, index, and/or data files), the order of elements is relevant. First element of engine file name extensions array should be metadata file extention. This is implied by the open_table_error() and the default discovery implementation. Second element - data file extension. This is implied assumed by REPAIR TABLE ... USE_FRM implementation. */ const char **tablefile_extensions; // by default - empty list /********************************************************************** Functions to intercept queries **********************************************************************/ /* Create and return a group_by_handler, if the storage engine can execute the summary / group by query. If the storage engine can't do that, return NULL. The server guaranteeds that all tables in the list belong to this storage engine. */ group_by_handler *(*create_group_by)(THD *thd, Query *query); /* Create and return a derived_handler if the storage engine can execute the derived table 'derived', otherwise return NULL. In a general case 'derived' may contain tables not from the engine. If the engine cannot handle or does not want to handle such pushed derived the function create_group_by has to return NULL. */ derived_handler *(*create_derived)(THD *thd, TABLE_LIST *derived); /* Create and return a select_handler for a single SELECT. If the storage engine cannot execute the select statement, return NULL */ select_handler *(*create_select) (THD *thd, SELECT_LEX *select_lex, SELECT_LEX_UNIT *select_lex_unit); /* Create and return a select_handler for a unit (i.e. multiple SELECTs combined with UNION/EXCEPT/INTERSECT). If the storage engine cannot execute the statement, return NULL */ select_handler *(*create_unit)(THD *thd, SELECT_LEX_UNIT *select_unit); /********************************************************************* Table discovery API. It allows the server to "discover" tables that exist in the storage engine, without user issuing an explicit CREATE TABLE statement. **********************************************************************/ /* This method is required for any engine that supports automatic table discovery, there is no default implementation. Given a TABLE_SHARE discover_table() fills it in with a correct table structure using one of the TABLE_SHARE::init_from_* methods. Returns HA_ERR_NO_SUCH_TABLE if the table did not exist in the engine, zero if the table was discovered successfully, or any other HA_ERR_* error code as appropriate if the table existed, but the discovery failed. */ int (*discover_table)(handlerton *hton, THD* thd, TABLE_SHARE *share); /* The discover_table_names method tells the server about all tables in the specified database that the engine knows about. Tables (or file names of tables) are added to the provided discovered_list collector object using add_table() or add_file() methods. */ class discovered_list { public: virtual bool add_table(const char *tname, size_t tlen) = 0; virtual bool add_file(const char *fname) = 0; protected: virtual ~discovered_list() = default; }; /* By default (if not implemented by the engine, but the discover_table() is implemented) it will perform a file-based discovery: - if tablefile_extensions[0] is not null, this will discovers all tables with the tablefile_extensions[0] extension. Returns 0 on success and 1 on error. */ int (*discover_table_names)(handlerton *hton, const LEX_CSTRING *db, MY_DIR *dir, discovered_list *result); /* This is a method that allows to server to check if a table exists without an overhead of the complete discovery. By default (if not implemented by the engine, but the discovery_table() is implemented) it will try to perform a file-based discovery: - if tablefile_extensions[0] is not null this will look for a file name with the tablefile_extensions[0] extension. - if tablefile_extensions[0] is null, this will resort to discover_table(). Note that resorting to discover_table() is slow and the engine should probably implement its own discover_table_existence() method, if its tablefile_extensions[0] is null. Returns 1 if the table exists and 0 if it does not. */ int (*discover_table_existence)(handlerton *hton, const char *db, const char *table_name); /* This is the assisted table discovery method. Unlike the fully automatic discovery as above, here a user is expected to issue an explicit CREATE TABLE with the appropriate table attributes to "assist" the discovery of a table. But this "discovering" CREATE TABLE statement will not specify the table structure - the engine discovers it using this method. For example, FederatedX uses it in CREATE TABLE t1 ENGINE=FEDERATED CONNECTION="mysql://foo/bar/t1"; Given a TABLE_SHARE discover_table_structure() fills it in with a correct table structure using one of the TABLE_SHARE::init_from_* methods. Assisted discovery works independently from the automatic discover. An engine is allowed to support only assisted discovery and not support automatic one. Or vice versa. */ int (*discover_table_structure)(handlerton *hton, THD* thd, TABLE_SHARE *share, HA_CREATE_INFO *info); /* Notify the storage engine that the definition of the table (and the .frm file) has changed. Returns 0 if ok. */ int (*notify_tabledef_changed)(handlerton *hton, LEX_CSTRING *db, LEX_CSTRING *table_name, LEX_CUSTRING *frm, LEX_CUSTRING *org_tabledef_version, handler *file); /* System Versioning */ /** Determine if system-versioned data was modified by the transaction. @param[in,out] thd current session @param[out] trx_id transaction start ID @return transaction commit ID @retval 0 if no system-versioned data was affected by the transaction */ ulonglong (*prepare_commit_versioned)(THD *thd, ulonglong *trx_id); /** Disable or enable the internal writes of a storage engine */ void (*disable_internal_writes)(bool disable); /* backup */ void (*prepare_for_backup)(void); void (*end_backup)(void); /* Server shutdown early notification.*/ void (*pre_shutdown)(void); /* Inform handler that partitioning engine has changed the .frm and the .par files */ int (*create_partitioning_metadata)(const char *path, const char *old_path, chf_create_flags action_flag); }; extern const char *hton_no_exts[]; static inline LEX_CSTRING *hton_name(const handlerton *hton) { return &(hton2plugin[hton->slot]->name); } static inline handlerton *plugin_hton(plugin_ref plugin) { return plugin_data(plugin, handlerton *); } static inline sys_var *find_hton_sysvar(handlerton *hton, st_mysql_sys_var *var) { return find_plugin_sysvar(hton2plugin[hton->slot], var); } handlerton *ha_default_handlerton(THD *thd); handlerton *ha_default_tmp_handlerton(THD *thd); /* Possible flags of a handlerton (there can be 32 of them) */ #define HTON_NO_FLAGS 0 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0) #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter #define HTON_CAN_RECREATE (1 << 2) //Delete all is used for truncate #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists #define HTON_NOT_USER_SELECTABLE (1 << 5) #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported #define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables #define HTON_NO_PARTITION (1 << 8) //Not partition of these tables /* This flag should be set when deciding that the engine does not allow row based binary logging (RBL) optimizations. Currently, setting this flag, means that table's read/write_set will be left untouched when logging changes to tables in this engine. In practice this means that the server will not mess around with table->write_set and/or table->read_set when using RBL and deciding whether to log full or minimal rows. It's valuable for instance for virtual tables, eg: Performance Schema which have no meaning for replication. */ #define HTON_NO_BINLOG_ROW_OPT (1 << 9) #define HTON_SUPPORTS_EXTENDED_KEYS (1 <<10) //supports extended keys #define HTON_NATIVE_SYS_VERSIONING (1 << 11) //Engine supports System Versioning // MySQL compatibility. Unused. #define HTON_SUPPORTS_FOREIGN_KEYS (1 << 0) //Foreign key constraint supported. #define HTON_CAN_MERGE (1 <<11) //Merge type table // Engine needs to access the main connect string in partitions #define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 <<12) /* can be replicated by wsrep replication provider plugin */ #define HTON_WSREP_REPLICATION (1 << 13) /* Set this on the *slave* that's connected to a shared with a master storage. The slave will ignore any CREATE TABLE, DROP or updates for this engine. */ #define HTON_IGNORE_UPDATES (1 << 14) /* Set this on the *master* that's connected to a shared with a slave storage. The table may not exists on the slave. The effects of having this flag are: - ALTER TABLE that changes engine from this table to another engine will be replicated as CREATE + INSERT - CREATE ... LIKE shared_table will be replicated as a full CREATE TABLE - ALTER TABLE for this engine will have "IF EXISTS" added. - RENAME TABLE for this engine will have "IF EXISTS" added. - DROP TABLE for this engine will have "IF EXISTS" added. */ #define HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE (1 << 15) /* True if handler cannot rollback transactions. If not true, the transaction will be put in the transactional binlog cache. For some engines, like Aria, the rollback can happen in case of crash, but not trough a handler rollback call. */ #define HTON_NO_ROLLBACK (1 << 16) /* This storage engine can support both transactional and non transactional tables */ #define HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL (1 << 17) /* Table requires and close and reopen after truncate If the handler has HTON_CAN_RECREATE, this flag is not used */ #define HTON_REQUIRES_CLOSE_AFTER_TRUNCATE (1 << 18) /* Truncate requires that all other handlers are closed */ #define HTON_TRUNCATE_REQUIRES_EXCLUSIVE_USE (1 << 19) /* Used by mysql_inplace_alter_table() to decide if we should call hton->notify_tabledef_changed() before commit (MyRocks) or after (InnoDB). */ #define HTON_REQUIRES_NOTIFY_TABLEDEF_CHANGED_AFTER_COMMIT (1 << 20) class Ha_trx_info; struct THD_TRANS { /* true is not all entries in the ht[] support 2pc */ bool no_2pc; /* storage engines that registered in this transaction */ Ha_trx_info *ha_list; /* The purpose of this flag is to keep track of non-transactional tables that were modified in scope of: - transaction, when the variable is a member of THD::transaction.all - top-level statement or sub-statement, when the variable is a member of THD::transaction.stmt This member has the following life cycle: * stmt.modified_non_trans_table is used to keep track of modified non-transactional tables of top-level statements. At the end of the previous statement and at the beginning of the session, it is reset to FALSE. If such functions as mysql_insert(), Sql_cmd_update::update_single_table, Sql_cmd_delete::delete_single_table modify a non-transactional table, they set this flag to TRUE. At the end of the statement, the value of stmt.modified_non_trans_table is merged with all.modified_non_trans_table and gets reset. * all.modified_non_trans_table is reset at the end of transaction * Since we do not have a dedicated context for execution of a sub-statement, to keep track of non-transactional changes in a sub-statement, we re-use stmt.modified_non_trans_table. At entrance into a sub-statement, a copy of the value of stmt.modified_non_trans_table (containing the changes of the outer statement) is saved on stack. Then stmt.modified_non_trans_table is reset to FALSE and the substatement is executed. Then the new value is merged with the saved value. */ bool modified_non_trans_table; void reset() { no_2pc= FALSE; modified_non_trans_table= FALSE; m_unsafe_rollback_flags= 0; } bool is_empty() const { return ha_list == NULL; } THD_TRANS() = default; /* Remove gcc warning */ unsigned int m_unsafe_rollback_flags; /* Define the type of statements which cannot be rolled back safely. Each type occupies one bit in m_unsafe_rollback_flags. MODIFIED_NON_TRANS_TABLE is limited to mark only the temporary non-transactional table *when* it's cached along with the transactional events; the regular table is covered by the "namesake" bool var. */ enum unsafe_statement_types { MODIFIED_NON_TRANS_TABLE= 1, CREATED_TEMP_TABLE= 2, DROPPED_TEMP_TABLE= 4, DID_WAIT= 8, DID_DDL= 0x10, EXECUTED_TABLE_ADMIN_CMD= 0x20 }; void mark_modified_non_trans_temp_table() { m_unsafe_rollback_flags|= MODIFIED_NON_TRANS_TABLE; } bool has_modified_non_trans_temp_table() const { return (m_unsafe_rollback_flags & MODIFIED_NON_TRANS_TABLE) != 0; } void mark_executed_table_admin_cmd() { DBUG_PRINT("debug", ("mark_executed_table_admin_cmd")); m_unsafe_rollback_flags|= EXECUTED_TABLE_ADMIN_CMD; } bool trans_executed_admin_cmd() { return (m_unsafe_rollback_flags & EXECUTED_TABLE_ADMIN_CMD) != 0; } void mark_created_temp_table() { DBUG_PRINT("debug", ("mark_created_temp_table")); m_unsafe_rollback_flags|= CREATED_TEMP_TABLE; } void mark_dropped_temp_table() { DBUG_PRINT("debug", ("mark_dropped_temp_table")); m_unsafe_rollback_flags|= DROPPED_TEMP_TABLE; } bool has_created_dropped_temp_table() const { return (m_unsafe_rollback_flags & (CREATED_TEMP_TABLE|DROPPED_TEMP_TABLE)) != 0; } void mark_trans_did_wait() { m_unsafe_rollback_flags|= DID_WAIT; } bool trans_did_wait() const { return (m_unsafe_rollback_flags & DID_WAIT) != 0; } bool is_trx_read_write() const; void mark_trans_did_ddl() { m_unsafe_rollback_flags|= DID_DDL; } bool trans_did_ddl() const { return (m_unsafe_rollback_flags & DID_DDL) != 0; } }; /** Either statement transaction or normal transaction - related thread-specific storage engine data. If a storage engine participates in a statement/transaction, an instance of this class is present in thd->transaction.{stmt|all}.ha_list. The addition to {stmt|all}.ha_list is made by trans_register_ha(). When it's time to commit or rollback, each element of ha_list is used to access storage engine's prepare()/commit()/rollback() methods, and also to evaluate if a full two phase commit is necessary. @sa General description of transaction handling in handler.cc. */ class Ha_trx_info { public: /** Register this storage engine in the given transaction context. */ void register_ha(THD_TRANS *trans, handlerton *ht_arg) { DBUG_ASSERT(m_flags == 0); DBUG_ASSERT(m_ht == NULL); DBUG_ASSERT(m_next == NULL); m_ht= ht_arg; m_flags= (int) TRX_READ_ONLY; /* Assume read-only at start. */ m_next= trans->ha_list; trans->ha_list= this; } /** Clear, prepare for reuse. */ void reset() { m_next= NULL; m_ht= NULL; m_flags= 0; } Ha_trx_info() { reset(); } void set_trx_read_write() { DBUG_ASSERT(is_started()); m_flags|= (int) TRX_READ_WRITE; } bool is_trx_read_write() const { DBUG_ASSERT(is_started()); return m_flags & (int) TRX_READ_WRITE; } void set_trx_no_rollback() { DBUG_ASSERT(is_started()); m_flags|= (int) TRX_NO_ROLLBACK; } bool is_trx_no_rollback() const { DBUG_ASSERT(is_started()); return m_flags & (int) TRX_NO_ROLLBACK; } bool is_started() const { return m_ht != NULL; } /** Mark this transaction read-write if the argument is read-write. */ void coalesce_trx_with(const Ha_trx_info *stmt_trx) { /* Must be called only after the transaction has been started. Can be called many times, e.g. when we have many read-write statements in a transaction. */ DBUG_ASSERT(is_started()); if (stmt_trx->is_trx_read_write()) set_trx_read_write(); } Ha_trx_info *next() const { DBUG_ASSERT(is_started()); return m_next; } handlerton *ht() const { DBUG_ASSERT(is_started()); return m_ht; } private: enum { TRX_READ_ONLY= 0, TRX_READ_WRITE= 1, TRX_NO_ROLLBACK= 2 }; /** Auxiliary, used for ha_list management */ Ha_trx_info *m_next; /** Although a given Ha_trx_info instance is currently always used for the same storage engine, 'ht' is not-NULL only when the corresponding storage is a part of a transaction. */ handlerton *m_ht; /** Transaction flags related to this engine. Not-null only if this instance is a part of transaction. May assume a combination of enum values above. */ uchar m_flags; }; inline bool THD_TRANS::is_trx_read_write() const { Ha_trx_info *ha_info; for (ha_info= ha_list; ha_info; ha_info= ha_info->next()) if (ha_info->is_trx_read_write()) return TRUE; return FALSE; } enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED, ISO_REPEATABLE_READ, ISO_SERIALIZABLE}; typedef struct { ulonglong data_file_length; ulonglong max_data_file_length; ulonglong index_file_length; ulonglong max_index_file_length; ulonglong delete_length; ha_rows records; ulong mean_rec_length; time_t create_time; time_t check_time; time_t update_time; ulonglong check_sum; bool check_sum_null; } PARTITION_STATS; #define UNDEF_NODEGROUP 65535 class Item; struct st_table_log_memory_entry; class partition_info; struct st_partition_iter; enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES, HA_CHOICE_MAX }; enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0, HA_STATS_AUTO_RECALC_ON, HA_STATS_AUTO_RECALC_OFF }; /** A helper struct for schema DDL statements: CREATE SCHEMA [IF NOT EXISTS] name [ schema_specification... ] ALTER SCHEMA name [ schema_specification... ] It stores the "schema_specification" part of the CREATE/ALTER statements and is passed to mysql_create_db() and mysql_alter_db(). Currently consists of the schema default character set, collation and schema_comment. */ struct Schema_specification_st { CHARSET_INFO *default_table_charset; LEX_CSTRING *schema_comment; void init() { bzero(this, sizeof(*this)); } }; class Create_field; struct Table_period_info: Sql_alloc { Table_period_info() : create_if_not_exists(false), constr(NULL), unique_keys(0) {} Table_period_info(const char *name_arg, size_t size) : name(name_arg, size), create_if_not_exists(false), constr(NULL), unique_keys(0){} Lex_ident name; struct start_end_t { start_end_t() = default; start_end_t(const LEX_CSTRING& _start, const LEX_CSTRING& _end) : start(_start), end(_end) {} Lex_ident start; Lex_ident end; }; start_end_t period; bool create_if_not_exists; Virtual_column_info *constr; uint unique_keys; bool is_set() const { DBUG_ASSERT(bool(period.start) == bool(period.end)); return period.start; } void set_period(const Lex_ident& start, const Lex_ident& end) { period.start= start; period.end= end; } bool check_field(const Create_field* f, const Lex_ident& f_name) const; }; struct Vers_parse_info: public Table_period_info { Vers_parse_info() : Table_period_info(STRING_WITH_LEN("SYSTEM_TIME")), versioned_fields(false), unversioned_fields(false), can_native(-1) {} Table_period_info::start_end_t as_row; friend struct Table_scope_and_contents_source_st; void set_start(const LEX_CSTRING field_name) { as_row.start= field_name; period.start= field_name; } void set_end(const LEX_CSTRING field_name) { as_row.end= field_name; period.end= field_name; } protected: bool is_start(const Create_field &f) const; bool is_end(const Create_field &f) const; bool fix_implicit(THD *thd, Alter_info *alter_info); operator bool() const { return as_row.start || as_row.end || period.start || period.end; } bool need_check(const Alter_info *alter_info) const; bool check_conditions(const Lex_table_name &table_name, const Lex_table_name &db) const; bool create_sys_field(THD *thd, const char *field_name, Alter_info *alter_info, int flags); public: static const Lex_ident default_start; static const Lex_ident default_end; bool fix_alter_info(THD *thd, Alter_info *alter_info, HA_CREATE_INFO *create_info, TABLE *table); bool fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_info, TABLE_LIST &src_table, TABLE_LIST &table); bool check_sys_fields(const Lex_table_name &table_name, const Lex_table_name &db, Alter_info *alter_info) const; /** At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'. Useful for error handling. */ bool versioned_fields : 1; bool unversioned_fields : 1; int can_native; }; /** A helper struct for table DDL statements, e.g.: CREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name table_contents_source; Represents a combinations of: 1. The scope, i.e. TEMPORARY or not TEMPORARY 2. The "table_contents_source" part of the table DDL statements, which can be initialized from either of these: - table_element_list ... // Explicit definition (column and key list) - LIKE another_table_name ... // Copy structure from another table - [AS] SELECT ... // Copy structure from a subquery */ struct Table_scope_and_contents_source_pod_st // For trivial members { CHARSET_INFO *alter_table_convert_to_charset; LEX_CUSTRING tabledef_version; LEX_CUSTRING org_tabledef_version; /* version of dropped table */ LEX_CSTRING connect_string; LEX_CSTRING comment; LEX_CSTRING alias; LEX_CSTRING org_storage_engine_name, new_storage_engine_name; const char *password, *tablespace; const char *data_file_name, *index_file_name; ulonglong max_rows,min_rows; ulonglong auto_increment_value; ulong table_options; ///< HA_OPTION_ values ulong avg_row_length; ulong used_fields; ulong key_block_size; ulong expression_length; ulong field_check_constraints; /* number of pages to sample during stats estimation, if used, otherwise 0. */ uint stats_sample_pages; uint null_bits; /* NULL bits at start of record */ uint options; /* OR of HA_CREATE_ options */ uint merge_insert_method; uint extra_size; /* length of extra data segment */ handlerton *db_type; /** Row type of the table definition. Defaults to ROW_TYPE_DEFAULT for all non-ALTER statements. For ALTER TABLE defaults to ROW_TYPE_NOT_USED (means "keep the current"). Can be changed either explicitly by the parser. If nothing specified inherits the value of the original table (if present). */ enum row_type row_type; enum ha_choice transactional; enum ha_storage_media storage_media; ///< DEFAULT, DISK or MEMORY enum ha_choice page_checksum; ///< If we have page_checksums engine_option_value *option_list; ///< list of table create options enum_stats_auto_recalc stats_auto_recalc; bool varchar; ///< 1 if table has a VARCHAR bool sequence; // If SEQUENCE=1 was used List<Virtual_column_info> *check_constraint_list; /* the following three are only for ALTER TABLE, check_if_incompatible_data() */ ha_table_option_struct *option_struct; ///< structure with parsed table options ha_field_option_struct **fields_option_struct; ///< array of field option structures ha_index_option_struct **indexes_option_struct; ///< array of index option structures /* The following is used to remember the old state for CREATE OR REPLACE */ TABLE *table; TABLE_LIST *pos_in_locked_tables; TABLE_LIST *merge_list; MDL_ticket *mdl_ticket; bool table_was_deleted; sequence_definition *seq_create_info; void init() { bzero(this, sizeof(*this)); } bool tmp_table() const { return options & HA_LEX_CREATE_TMP_TABLE; } void use_default_db_type(THD *thd) { db_type= tmp_table() ? ha_default_tmp_handlerton(thd) : ha_default_handlerton(thd); } bool versioned() const { return options & HA_VERSIONED_TABLE; } }; struct Table_scope_and_contents_source_st: public Table_scope_and_contents_source_pod_st { Vers_parse_info vers_info; Table_period_info period_info; void init() { Table_scope_and_contents_source_pod_st::init(); vers_info= {}; period_info= {}; } bool fix_create_fields(THD *thd, Alter_info *alter_info, const TABLE_LIST &create_table); bool fix_period_fields(THD *thd, Alter_info *alter_info); bool check_fields(THD *thd, Alter_info *alter_info, const Lex_table_name &table_name, const Lex_table_name &db, int select_count= 0); bool check_period_fields(THD *thd, Alter_info *alter_info); void vers_check_native(); bool vers_fix_system_fields(THD *thd, Alter_info *alter_info, const TABLE_LIST &create_table); bool vers_check_system_fields(THD *thd, Alter_info *alter_info, const Lex_table_name &table_name, const Lex_table_name &db, int select_count= 0); }; /** This struct is passed to handler table routines, e.g. ha_create(). It does not include the "OR REPLACE" and "IF NOT EXISTS" parts, as these parts are handled on the SQL level and are not needed on the handler level. */ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st, public Schema_specification_st { /* TODO: remove after MDEV-20865 */ Alter_info *alter_info; void init() { Table_scope_and_contents_source_st::init(); Schema_specification_st::init(); alter_info= NULL; } ulong table_options_with_row_type() { if (row_type == ROW_TYPE_DYNAMIC || row_type == ROW_TYPE_PAGE) return table_options | HA_OPTION_PACK_RECORD; else return table_options; } bool resolve_to_charset_collation_context(THD *thd, const Lex_table_charset_collation_attrs_st &default_cscl, const Lex_table_charset_collation_attrs_st &convert_cscl, const Charset_collation_context &ctx); bool check_if_valid_log_table(); }; /** This struct is passed to mysql_create_table() and similar creation functions, as well as to show_create_table(). */ struct Table_specification_st: public HA_CREATE_INFO, public DDL_options_st { Lex_table_charset_collation_attrs_st default_charset_collation; Lex_table_charset_collation_attrs_st convert_charset_collation; // Deep initialization void init() { HA_CREATE_INFO::init(); DDL_options_st::init(); default_charset_collation.init(); convert_charset_collation.init(); } void init(DDL_options_st::Options options_arg) { HA_CREATE_INFO::init(); DDL_options_st::init(options_arg); default_charset_collation.init(); convert_charset_collation.init(); } /* Quick initialization, for parser. Most of the HA_CREATE_INFO is left uninitialized. It gets fully initialized in sql_yacc.yy, only when the parser scans a related keyword (e.g. CREATE, ALTER). */ void lex_start() { HA_CREATE_INFO::options= 0; DDL_options_st::init(); default_charset_collation.init(); convert_charset_collation.init(); } bool add_table_option_convert_charset(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs) { // cs can be NULL, e.g.: ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT; used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET); return cs ? convert_charset_collation.merge_exact_charset(used, map, Lex_exact_charset(cs)) : convert_charset_collation.merge_charset_default(); } bool add_table_option_convert_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl) { used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET); return convert_charset_collation.merge_collation(used, map, cl); } bool add_table_option_default_charset(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs) { // cs can be NULL, e.g.: CREATE TABLE t1 (..) CHARACTER SET DEFAULT; used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; return cs ? default_charset_collation.merge_exact_charset(used, map, Lex_exact_charset(cs)) : default_charset_collation.merge_charset_default(); } bool add_table_option_default_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl) { used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; return default_charset_collation.merge_collation(used, map, cl); } bool resolve_to_charset_collation_context(THD *thd, const Charset_collation_context &ctx) { return HA_CREATE_INFO:: resolve_to_charset_collation_context(thd, default_charset_collation, convert_charset_collation, ctx); } }; /** Structure describing changes to an index to be caused by ALTER TABLE. */ struct KEY_PAIR { /** Pointer to KEY object describing old version of index in TABLE::key_info array for TABLE instance representing old version of table. */ KEY *old_key; /** Pointer to KEY object describing new version of index in Alter_inplace_info::key_info_buffer array. */ KEY *new_key; }; /** In-place alter handler context. This is a superclass intended to be subclassed by individual handlers in order to store handler unique context between in-place alter API calls. The handler is responsible for creating the object. This can be done as early as during check_if_supported_inplace_alter(). The SQL layer is responsible for destroying the object. The class extends Sql_alloc so the memory will be mem root allocated. @see Alter_inplace_info */ class inplace_alter_handler_ctx : public Sql_alloc { public: inplace_alter_handler_ctx() = default; virtual ~inplace_alter_handler_ctx() = default; virtual void set_shared_data(const inplace_alter_handler_ctx& ctx) {} }; /** Class describing changes to be done by ALTER TABLE. Instance of this class is passed to storage engine in order to determine if this ALTER TABLE can be done using in-place algorithm. It is also used for executing the ALTER TABLE using in-place algorithm. */ class Alter_inplace_info { public: /** Create options (like MAX_ROWS) for the new version of table. @note The referenced instance of HA_CREATE_INFO object was already used to create new .FRM file for table being altered. So it has been processed by mysql_prepare_create_table() already. For example, this means that it has HA_OPTION_PACK_RECORD flag in HA_CREATE_INFO::table_options member correctly set. */ HA_CREATE_INFO *create_info; /** Alter options, fields and keys for the new version of table. @note The referenced instance of Alter_info object was already used to create new .FRM file for table being altered. So it has been processed by mysql_prepare_create_table() already. In particular, this means that in Create_field objects for fields which were present in some form in the old version of table, Create_field::field member points to corresponding Field instance for old version of table. */ Alter_info *alter_info; /** Array of KEYs for new version of table - including KEYs to be added. @note Currently this array is produced as result of mysql_prepare_create_table() call. This means that it follows different convention for KEY_PART_INFO::fieldnr values than objects in TABLE::key_info array. @todo This is mainly due to the fact that we need to keep compatibility with removed handler::add_index() call. We plan to switch to TABLE::key_info numbering later. KEYs are sorted - see sort_keys(). */ KEY *key_info_buffer; /** Size of key_info_buffer array. */ uint key_count; /** Size of index_drop_buffer array. */ uint index_drop_count= 0; /** Array of pointers to KEYs to be dropped belonging to the TABLE instance for the old version of the table. */ KEY **index_drop_buffer= nullptr; /** Size of index_add_buffer array. */ uint index_add_count= 0; /** Array of indexes into key_info_buffer for KEYs to be added, sorted in increasing order. */ uint *index_add_buffer= nullptr; KEY_PAIR *index_altered_ignorability_buffer= nullptr; /** Size of index_altered_ignorability_buffer array. */ uint index_altered_ignorability_count= 0; /** Old and new index names. Used for index rename. */ struct Rename_key_pair { Rename_key_pair(const KEY *old_key, const KEY *new_key) : old_key(old_key), new_key(new_key) { } const KEY *old_key; const KEY *new_key; }; /** Vector of key pairs from DROP/ADD index which can be renamed. */ typedef Mem_root_array<Rename_key_pair, true> Rename_keys_vector; /** A list of indexes which should be renamed. Index definitions stays the same. */ Rename_keys_vector rename_keys; /** Context information to allow handlers to keep context between in-place alter API calls. @see inplace_alter_handler_ctx for information about object lifecycle. */ inplace_alter_handler_ctx *handler_ctx= nullptr; /** If the table uses several handlers, like ha_partition uses one handler per partition, this contains a Null terminated array of ctx pointers that should all be committed together. Or NULL if only handler_ctx should be committed. Set to NULL if the low level handler::commit_inplace_alter_table uses it, to signal to the main handler that everything was committed as atomically. @see inplace_alter_handler_ctx for information about object lifecycle. */ inplace_alter_handler_ctx **group_commit_ctx= nullptr; /** Flags describing in detail which operations the storage engine is to execute. Flags are defined in sql_alter.h */ alter_table_operations handler_flags= 0; /* Alter operations involving parititons are strored here */ ulong partition_flags; /** Partition_info taking into account the partition changes to be performed. Contains all partitions which are present in the old version of the table with partitions to be dropped or changed marked as such + all partitions to be added in the new version of table marked as such. */ partition_info * const modified_part_info; /** true for ALTER IGNORE TABLE ... */ const bool ignore; /** true for online operation (LOCK=NONE) */ bool online= false; /** When ha_commit_inplace_alter_table() is called the engine can set this to a function to be called after the ddl log is committed. */ typedef void (inplace_alter_table_commit_callback)(void *); inplace_alter_table_commit_callback *inplace_alter_table_committed= nullptr; /* This will be used as the argument to the above function when called */ void *inplace_alter_table_committed_argument= nullptr; /** which ALGORITHM and LOCK are supported by the storage engine */ enum_alter_inplace_result inplace_supported; /** Can be set by handler to describe why a given operation cannot be done in-place (HA_ALTER_INPLACE_NOT_SUPPORTED) or why it cannot be done online (HA_ALTER_INPLACE_NO_LOCK or HA_ALTER_INPLACE_COPY_NO_LOCK) If set, it will be used with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON if results from handler::check_if_supported_inplace_alter() doesn't match requirements set by user. If not set, the more generic ER_ALTER_OPERATION_NOT_SUPPORTED will be used. Please set to a properly localized string, for example using my_get_err_msg(), so that the error message as a whole is localized. */ const char *unsupported_reason= nullptr; /** true when InnoDB should abort the alter when table is not empty */ const bool error_if_not_empty; /** True when DDL should avoid downgrading the MDL */ bool mdl_exclusive_after_prepare= false; Alter_inplace_info(HA_CREATE_INFO *create_info_arg, Alter_info *alter_info_arg, KEY *key_info_arg, uint key_count_arg, partition_info *modified_part_info_arg, bool ignore_arg, bool error_non_empty); ~Alter_inplace_info() { delete handler_ctx; } /** Used after check_if_supported_inplace_alter() to report error if the result does not match the LOCK/ALGORITHM requirements set by the user. @param not_supported Part of statement that was not supported. @param try_instead Suggestion as to what the user should replace not_supported with. */ void report_unsupported_error(const char *not_supported, const char *try_instead) const; void add_altered_index_ignorability(KEY *old_key, KEY *new_key) { KEY_PAIR *key_pair= index_altered_ignorability_buffer + index_altered_ignorability_count++; key_pair->old_key= old_key; key_pair->new_key= new_key; DBUG_PRINT("info", ("index had ignorability altered: %i to %i", old_key->is_ignored, new_key->is_ignored)); } }; typedef struct st_key_create_information { enum ha_key_alg algorithm; ulong block_size; uint flags; /* HA_USE.. flags */ LEX_CSTRING parser_name; LEX_CSTRING comment; bool is_ignored; } KEY_CREATE_INFO; typedef struct st_savepoint SAVEPOINT; extern ulong savepoint_alloc_size; extern KEY_CREATE_INFO default_key_create_info; /* Forward declaration for condition pushdown to storage engine */ typedef class Item COND; typedef struct st_ha_check_opt { st_ha_check_opt() = default; /* Remove gcc warning */ uint flags; /* isam layer flags (e.g. for myisamchk) */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ uint handler_flags; /* Reserved for handler usage */ time_t start_time; /* When check/repair starts */ KEY_CACHE *key_cache; /* new key cache when changing key cache */ void init(); } HA_CHECK_OPT; /******************************************************************************** * MRR ********************************************************************************/ typedef void *range_seq_t; typedef struct st_range_seq_if { /* Get key information SYNOPSIS get_key_info() init_params The seq_init_param parameter length OUT length of the keys in this range sequence map OUT key_part_map of the keys in this range sequence DESCRIPTION This function is set only when using HA_MRR_FIXED_KEY mode. In that mode, all ranges are single-point equality ranges that use the same set of key parts. This function allows the MRR implementation to get the length of a key, and which keyparts it uses. */ void (*get_key_info)(void *init_params, uint *length, key_part_map *map); /* Initialize the traversal of range sequence SYNOPSIS init() init_params The seq_init_param parameter n_ranges The number of ranges obtained flags A combination of HA_MRR_SINGLE_POINT, HA_MRR_FIXED_KEY RETURN An opaque value to be used as RANGE_SEQ_IF::next() parameter */ range_seq_t (*init)(void *init_params, uint n_ranges, uint flags); /* Get the next range in the range sequence SYNOPSIS next() seq The value returned by RANGE_SEQ_IF::init() range OUT Information about the next range RETURN FALSE - Ok, the range structure filled with info about the next range TRUE - No more ranges */ bool (*next) (range_seq_t seq, KEY_MULTI_RANGE *range); /* Check whether range_info orders to skip the next record SYNOPSIS skip_record() seq The value returned by RANGE_SEQ_IF::init() range_info Information about the next range (Ignored if MRR_NO_ASSOCIATION is set) rowid Rowid of the record to be checked (ignored if set to 0) RETURN 1 - Record with this range_info and/or this rowid shall be filtered out from the stream of records returned by multi_range_read_next() 0 - The record shall be left in the stream */ bool (*skip_record) (range_seq_t seq, range_id_t range_info, uchar *rowid); /* Check if the record combination matches the index condition SYNOPSIS skip_index_tuple() seq The value returned by RANGE_SEQ_IF::init() range_info Information about the next range RETURN 0 - The record combination satisfies the index condition 1 - Otherwise */ bool (*skip_index_tuple) (range_seq_t seq, range_id_t range_info); } RANGE_SEQ_IF; typedef bool (*SKIP_INDEX_TUPLE_FUNC) (range_seq_t seq, range_id_t range_info); #define MARIADB_NEW_COST_MODEL 1 /* Separated costs for IO and CPU */ struct IO_AND_CPU_COST { double io; double cpu; void add(IO_AND_CPU_COST cost) { io+= cost.io; cpu+= cost.cpu; } }; /* Cost for reading a row through an index */ struct ALL_READ_COST { IO_AND_CPU_COST index_cost, row_cost; longlong max_index_blocks, max_row_blocks; /* index_only_read = index_cost + copy_cost */ double copy_cost; void reset() { row_cost= {0,0}; index_cost= {0,0}; max_index_blocks= max_row_blocks= 0; copy_cost= 0.0; } }; class Cost_estimate { public: double avg_io_cost; /* cost of an average I/O oper. to fetch records */ double cpu_cost; /* Cpu cost unrelated to engine costs */ double comp_cost; /* Cost of comparing found rows with WHERE clause */ double copy_cost; /* Copying the data to 'record' */ double limit_cost; /* Total cost when restricting rows with limit */ double setup_cost; /* MULTI_RANGE_READ_SETUP_COST or similar */ IO_AND_CPU_COST index_cost; IO_AND_CPU_COST row_cost; Cost_estimate() { reset(); } /* Total cost for the range Note that find_cost() + compare_cost() + data_copy_cost() == total_cost() */ double total_cost() const { return ((index_cost.io + row_cost.io) * avg_io_cost+ index_cost.cpu + row_cost.cpu + copy_cost + comp_cost + cpu_cost + setup_cost); } /* Cost for just fetching and copying a row (no compare costs) */ double fetch_cost() const { return ((index_cost.io + row_cost.io) * avg_io_cost+ index_cost.cpu + row_cost.cpu + copy_cost); } /* Cost of copying the row or key to 'record' */ inline double data_copy_cost() const { return copy_cost; } /* Multiply costs to simulate a scan where we read We assume that io blocks will be cached and we only allocate memory once. There should also be no import_cost that needs to be done multiple times */ void multiply(uint n) { index_cost.io*= n; index_cost.cpu*= n; row_cost.io*= n; row_cost.cpu*= n; copy_cost*= n; comp_cost*= n; cpu_cost*= n; } void add(Cost_estimate *cost) { avg_io_cost= cost->avg_io_cost; index_cost.io+= cost->index_cost.io; index_cost.cpu+= cost->index_cost.cpu; row_cost.io+= cost->row_cost.io; row_cost.cpu+= cost->row_cost.cpu; copy_cost+= cost->copy_cost; comp_cost+= cost->comp_cost; cpu_cost+= cost->cpu_cost; setup_cost+= cost->setup_cost; } inline void reset() { avg_io_cost= 0; comp_cost= cpu_cost= 0.0; copy_cost= limit_cost= 0.0; setup_cost= 0.0; index_cost= {0,0}; row_cost= {0,0}; } inline void reset(handler *file); /* To be used when we go from old single value-based cost calculations to the new Cost_estimate-based. */ void convert_from_cost(double cost) { reset(); cpu_cost= cost; } }; /* Indicates that all scanned ranges will be singlepoint (aka equality) ranges. The ranges may not use the full key but all of them will use the same number of key parts. */ #define HA_MRR_SINGLE_POINT 1U #define HA_MRR_FIXED_KEY 2U /* Indicates that RANGE_SEQ_IF::next(&range) doesn't need to fill in the 'range' parameter. */ #define HA_MRR_NO_ASSOCIATION 4U /* The MRR user will provide ranges in key order, and MRR implementation must return rows in key order. */ #define HA_MRR_SORTED 8U /* MRR implementation doesn't have to retrieve full records */ #define HA_MRR_INDEX_ONLY 16U /* The passed memory buffer is of maximum possible size, the caller can't assume larger buffer. */ #define HA_MRR_LIMITS 32U /* Flag set <=> default MRR implementation is used (The choice is made by **_info[_const]() function which may set this flag. SQL layer remembers the flag value and then passes it to multi_read_range_init(). */ #define HA_MRR_USE_DEFAULT_IMPL 64U /* Used only as parameter to multi_range_read_info(): Flag set <=> the caller guarantees that the bounds of the scanned ranges will not have NULL values. */ #define HA_MRR_NO_NULL_ENDPOINTS 128U /* The MRR user has materialized range keys somewhere in the user's buffer. This can be used for optimization of the procedure that sorts these keys since in this case key values don't have to be copied into the MRR buffer. In other words, it is guaranteed that after RANGE_SEQ_IF::next() call the pointer in range->start_key.key will point to a key value that will remain there until the end of the MRR scan. */ #define HA_MRR_MATERIALIZED_KEYS 256U /* The following bits are reserved for use by MRR implementation. The intended use scenario: * sql layer calls handler->multi_range_read_info[_const]() - MRR implementation figures out what kind of scan it will perform, saves the result in *mrr_mode parameter. * sql layer remembers what was returned in *mrr_mode * the optimizer picks the query plan (which may or may not include the MRR scan that was estimated by the multi_range_read_info[_const] call) * if the query is an EXPLAIN statement, sql layer will call handler->multi_range_read_explain_info(mrr_mode) to get a text description of the picked MRR scan; the description will be a part of EXPLAIN output. */ #define HA_MRR_IMPLEMENTATION_FLAG1 512U #define HA_MRR_IMPLEMENTATION_FLAG2 1024U #define HA_MRR_IMPLEMENTATION_FLAG3 2048U #define HA_MRR_IMPLEMENTATION_FLAG4 4096U #define HA_MRR_IMPLEMENTATION_FLAG5 8192U #define HA_MRR_IMPLEMENTATION_FLAG6 16384U #define HA_MRR_IMPLEMENTATION_FLAGS \ (512U | 1024U | 2048U | 4096U | 8192U | 16384U) /* This is a buffer area that the handler can use to store rows. 'end_of_used_area' should be kept updated after calls to read-functions so that other parts of the code can use the remaining area (until next read calls is issued). */ typedef struct st_handler_buffer { /* const? */uchar *buffer; /* Buffer one can start using */ /* const? */uchar *buffer_end; /* End of buffer */ uchar *end_of_used_area; /* End of area that was used by handler */ } HANDLER_BUFFER; typedef struct system_status_var SSV; class ha_statistics { public: ulonglong data_file_length; /* Length off data file */ ulonglong max_data_file_length; /* Length off data file */ ulonglong index_file_length; ulonglong max_index_file_length; ulonglong delete_length; /* Free bytes */ ulonglong auto_increment_value; /* The number of records in the table. 0 - means the table has exactly 0 rows other - if (table_flags() & HA_STATS_RECORDS_IS_EXACT) the value is the exact number of records in the table else it is an estimate */ ha_rows records; ha_rows deleted; /* Deleted records */ ulong mean_rec_length; /* physical reclength */ time_t create_time; /* When table was created */ time_t check_time; time_t update_time; uint block_size; /* index block size */ ha_checksum checksum; bool checksum_null; /* number of buffer bytes that native mrr implementation needs, */ uint mrr_length_per_rec; ha_statistics(): data_file_length(0), max_data_file_length(0), index_file_length(0), max_index_file_length(0), delete_length(0), auto_increment_value(0), records(0), deleted(0), mean_rec_length(0), create_time(0), check_time(0), update_time(0), block_size(8192), checksum(0), checksum_null(FALSE), mrr_length_per_rec(0) {} }; extern "C" check_result_t handler_index_cond_check(void* h_arg); extern "C" check_result_t handler_rowid_filter_check(void* h_arg); extern "C" int handler_rowid_filter_is_active(void* h_arg); uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map); /* bitmap with first N+1 bits set (keypart_map for a key prefix of [0..N] keyparts) */ inline key_part_map make_keypart_map(uint N) { return ((key_part_map)2 << (N)) - 1; } /* bitmap with first N bits set (keypart_map for a key prefix of [0..N-1] keyparts) */ inline key_part_map make_prev_keypart_map(uint N) { return ((key_part_map)1 << (N)) - 1; } /** Base class to be used by handlers different shares */ class Handler_share { public: Handler_share() = default; virtual ~Handler_share() = default; }; enum class Compare_keys : uint32_t { Equal= 0, EqualButKeyPartLength, EqualButComment, NotEqual }; /* This class stores a table file name in the format: homedir/db/table where db and table use tablename_to_filename() compatible encoding. */ class Table_path_buffer: public CharBuffer<FN_REFLEN> { public: Table_path_buffer() { } /** Make a lower-cased path for a table. @homedir - home directory, get copied to the buffer as is (without lower-casing) @db_and_table - the database and the table name part in the format "/db/table", can be in arbitrary letter case. It gets converted to lower case during copying to the buffer. The "db" and "table" parts can be prefixed with '#myql50#'. Makes the path in the format "homedir/db/table". */ Table_path_buffer & set_casedn(const Lex_cstring &homedir, CHARSET_INFO *db_and_table_charset, const Lex_cstring &db_and_table) { DBUG_ASSERT(homedir.length + db_and_table.length <= max_data_size()); copy_bin(homedir); append_casedn(db_and_table_charset, db_and_table); return *this; } }; /** The handler class is the interface for dynamically loadable storage engines. Do not add ifdefs and take care when adding or changing virtual functions to avoid vtable confusion Functions in this class accept and return table columns data. Two data representation formats are used: 1. TableRecordFormat - Used to pass [partial] table records to/from storage engine 2. KeyTupleFormat - used to pass index search tuples (aka "keys") to storage engine. See opt_range.cc for description of this format. TableRecordFormat ================= [Warning: this description is work in progress and may be incomplete] The table record is stored in a fixed-size buffer: record: null_bytes, column1_data, column2_data, ... The offsets of the parts of the buffer are also fixed: every column has an offset to its column{i}_data, and if it is nullable it also has its own bit in null_bytes. The record buffer only includes data about columns that are marked in the relevant column set (table->read_set and/or table->write_set, depending on the situation). <not-sure>It could be that it is required that null bits of non-present columns are set to 1</not-sure> VARIOUS EXCEPTIONS AND SPECIAL CASES If the table has no nullable columns, then null_bytes is still present, its length is one byte <not-sure> which must be set to 0xFF at all times. </not-sure> If the table has columns of type BIT, then certain bits from those columns may be stored in null_bytes as well. Grep around for Field_bit for details. For blob columns (see Field_blob), the record buffer stores length of the data, following by memory pointer to the blob data. The pointer is owned by the storage engine and is valid until the next operation. If a blob column has NULL value, then its length and blob data pointer must be set to 0. */ class handler :public Sql_alloc { public: typedef ulonglong Table_flags; protected: TABLE_SHARE *table_share; /* The table definition */ TABLE *table; /* The current open table */ Table_flags cached_table_flags; /* Set on init() and open() */ ha_rows estimation_rows_to_insert; /* Statistics for the query. Updated if handler_stats.active is set */ ha_handler_stats active_handler_stats; void set_handler_stats(); public: handlerton *ht; /* storage engine of this handler */ OPTIMIZER_COSTS *costs; /* Points to table->share->costs */ uchar *ref; /* Pointer to current row */ uchar *dup_ref; /* Pointer to duplicate row */ uchar *lookup_buffer; handler *lookup_handler; /* General statistics for the table like number of row, file sizes etc */ ha_statistics stats; /* Collect query stats here if pointer is != NULL. This is a pointer because if we do a clone of the handler, we want to use the original handler for collecting statistics. */ ha_handler_stats *handler_stats; /** MultiRangeRead-related members: */ range_seq_t mrr_iter; /* Iterator to traverse the range sequence */ RANGE_SEQ_IF mrr_funcs; /* Range sequence traversal functions */ HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */ uint ranges_in_seq; /* Total number of ranges in the traversed sequence */ /** Current range (the one we're now returning rows from) */ KEY_MULTI_RANGE mrr_cur_range; /** The following are for read_range() */ key_range save_end_range, *end_range; KEY_PART_INFO *range_key_part; int key_compare_result_on_equal; /* TRUE <=> source MRR ranges and the output are ordered */ bool mrr_is_output_sorted; /** TRUE <=> we're currently traversing a range in mrr_cur_range. */ bool mrr_have_range; bool eq_range; bool internal_tmp_table; /* If internal tmp table */ bool implicit_emptied; /* Can be !=0 only if HEAP */ bool mark_trx_read_write_done; /* mark_trx_read_write was called */ bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */ bool check_table_binlog_row_based_result; /* cached check_table_binlog... */ /* TRUE <=> the engine guarantees that returned records are within the range being scanned. */ bool in_range_check_pushed_down; uint lookup_errkey; uint errkey; /* Last dup key */ uint key_used_on_scan; uint active_index, keyread; /** Length of ref (1-8 or the clustered key length) */ uint ref_length; FT_INFO *ft_handler; enum init_stat { NONE=0, INDEX, RND }; init_stat inited, pre_inited; const COND *pushed_cond; /** next_insert_id is the next value which should be inserted into the auto_increment column: in a inserting-multi-row statement (like INSERT SELECT), for the first row where the autoinc value is not specified by the statement, get_auto_increment() called and asked to generate a value, next_insert_id is set to the next value, then for all other rows next_insert_id is used (and increased each time) without calling get_auto_increment(). */ ulonglong next_insert_id; /** insert id for the current row (*autogenerated*; if not autogenerated, it's 0). At first successful insertion, this variable is stored into THD::first_successful_insert_id_in_cur_stmt. */ ulonglong insert_id_for_cur_row; /** Interval returned by get_auto_increment() and being consumed by the inserter. */ /* Statistics variables */ ulonglong rows_read; ulonglong rows_tmp_read; ulonglong rows_changed; /* One bigger than needed to avoid to test if key == MAX_KEY */ ulonglong index_rows_read[MAX_KEY+1]; ha_copy_info copy_info; private: /* ANALYZE time tracker, if present */ Exec_time_tracker *tracker; public: void set_time_tracker(Exec_time_tracker *tracker_arg) { tracker=tracker_arg;} Exec_time_tracker *get_time_tracker() { return tracker; } Item *pushed_idx_cond; uint pushed_idx_cond_keyno; /* The index which the above condition is for */ /* Rowid filter pushed into the engine */ Rowid_filter *pushed_rowid_filter; /* true when the pushed rowid filter has been already filled */ bool rowid_filter_is_active; /* Used for disabling/enabling pushed_rowid_filter */ Rowid_filter *save_pushed_rowid_filter; bool save_rowid_filter_is_active; Discrete_interval auto_inc_interval_for_cur_row; /** Number of reserved auto-increment intervals. Serves as a heuristic when we have no estimation of how many records the statement will insert: the more intervals we have reserved, the bigger the next one. Reset in handler::ha_release_auto_increment(). */ uint auto_inc_intervals_count; /** Instrumented table associated with this handler. This member should be set to NULL when no instrumentation is in place, so that linking an instrumented/non instrumented server/plugin works. For example: - the server is compiled with the instrumentation. The server expects either NULL or valid pointers in m_psi. - an engine plugin is compiled without instrumentation. The plugin can not leave this pointer uninitialized, or can not leave a trash value on purpose in this pointer, as this would crash the server. */ PSI_table *m_psi; private: /** Internal state of the batch instrumentation. */ enum batch_mode_t { /** Batch mode not used. */ PSI_BATCH_MODE_NONE, /** Batch mode used, before first table io. */ PSI_BATCH_MODE_STARTING, /** Batch mode used, after first table io. */ PSI_BATCH_MODE_STARTED }; /** Batch mode state. @sa start_psi_batch_mode. @sa end_psi_batch_mode. */ batch_mode_t m_psi_batch_mode; /** The number of rows in the batch. @sa start_psi_batch_mode. @sa end_psi_batch_mode. */ ulonglong m_psi_numrows; /** The current event in a batch. @sa start_psi_batch_mode. @sa end_psi_batch_mode. */ PSI_table_locker *m_psi_locker; /** Storage for the event in a batch. @sa start_psi_batch_mode. @sa end_psi_batch_mode. */ PSI_table_locker_state m_psi_locker_state; public: virtual void unbind_psi(); virtual void rebind_psi(); /* Return error if definition doesn't match for already opened table */ virtual int discover_check_version() { return 0; } /** Put the handler in 'batch' mode when collecting table io instrumented events. When operating in batch mode: - a single start event is generated in the performance schema. - all table io performed between @c start_psi_batch_mode and @c end_psi_batch_mode is not instrumented: the number of rows affected is counted instead in @c m_psi_numrows. - a single end event is generated in the performance schema when the batch mode ends with @c end_psi_batch_mode. */ void start_psi_batch_mode(); /** End a batch started with @c start_psi_batch_mode. */ void end_psi_batch_mode(); /* If we have row logging enabled for this table */ bool row_logging, row_logging_init; /* If the row logging should be done in transaction cache */ bool row_logging_has_trans; private: /** The lock type set by when calling::ha_external_lock(). This is propagated down to the storage engine. The reason for also storing it here, is that when doing MRR we need to create/clone a second handler object. This cloned handler object needs to know about the lock_type used. */ int m_lock_type; /** Pointer where to store/retrieve the Handler_share pointer. For non partitioned handlers this is &TABLE_SHARE::ha_share. */ Handler_share **ha_share; public: double optimizer_where_cost; // Copy of THD->...optimzer_where_cost double optimizer_scan_setup_cost; // Copy of THD->...optimzer_scan_... handler(handlerton *ht_arg, TABLE_SHARE *share_arg) :table_share(share_arg), table(0), estimation_rows_to_insert(0), ht(ht_arg), costs(0), ref(0), lookup_buffer(NULL), lookup_handler(this), handler_stats(NULL), end_range(NULL), implicit_emptied(0), mark_trx_read_write_done(0), check_table_binlog_row_based_done(0), check_table_binlog_row_based_result(0), in_range_check_pushed_down(FALSE), lookup_errkey(-1), errkey(-1), key_used_on_scan(MAX_KEY), active_index(MAX_KEY), keyread(MAX_KEY), ref_length(sizeof(my_off_t)), ft_handler(0), inited(NONE), pre_inited(NONE), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0), tracker(NULL), pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY), pushed_rowid_filter(NULL), rowid_filter_is_active(0), save_pushed_rowid_filter(NULL), save_rowid_filter_is_active(false), auto_inc_intervals_count(0), m_psi(NULL), m_psi_batch_mode(PSI_BATCH_MODE_NONE), m_psi_numrows(0), m_psi_locker(NULL), row_logging(0), row_logging_init(0), m_lock_type(F_UNLCK), ha_share(NULL), optimizer_where_cost(0), optimizer_scan_setup_cost(0) { DBUG_PRINT("info", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", F_UNLCK, F_RDLCK, F_WRLCK)); reset_statistics(); /* The following variables should be updated in set_optimizer_costs() which is to be run as part of setting up the table for the query */ MEM_UNDEFINED(&optimizer_where_cost, sizeof(optimizer_where_cost)); MEM_UNDEFINED(&optimizer_scan_setup_cost, sizeof(optimizer_scan_setup_cost)); } virtual ~handler(void) { DBUG_ASSERT(m_lock_type == F_UNLCK); DBUG_ASSERT(inited == NONE); } /* To check if table has been properely opened */ bool is_open() { return ref != 0; } virtual handler *clone(const char *name, MEM_ROOT *mem_root); /** This is called after create to allow us to set up cached variables */ void init() { cached_table_flags= table_flags(); } /* ha_ methods: public wrappers for private virtual API */ int ha_open(TABLE *table, const char *name, int mode, uint test_if_locked, MEM_ROOT *mem_root= 0, List<String> *partitions_to_open=NULL); int ha_index_init(uint idx, bool sorted); int ha_index_end() { DBUG_ENTER("ha_index_end"); DBUG_ASSERT(inited==INDEX); inited= NONE; active_index= MAX_KEY; end_range= NULL; DBUG_RETURN(index_end()); } /* This is called after index_init() if we need to do a index scan */ virtual int prepare_index_scan() { return 0; } virtual int prepare_index_key_scan_map(const uchar * key, key_part_map keypart_map) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); return prepare_index_key_scan(key, key_len); } virtual int prepare_index_key_scan( const uchar * key, uint key_len ) { return 0; } virtual int prepare_range_scan(const key_range *start_key, const key_range *end_key) { return 0; } int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result)) { DBUG_EXECUTE_IF("ha_rnd_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); int result; DBUG_ENTER("ha_rnd_init"); DBUG_ASSERT(inited==NONE || (inited==RND && scan)); inited= (result= rnd_init(scan)) ? NONE: RND; end_range= NULL; DBUG_RETURN(result); } int ha_rnd_end() { DBUG_ENTER("ha_rnd_end"); DBUG_ASSERT(inited==RND); inited=NONE; end_range= NULL; DBUG_RETURN(rnd_end()); } int ha_rnd_init_with_error(bool scan) __attribute__ ((warn_unused_result)); int ha_reset(); /* this is necessary in many places, e.g. in HANDLER command */ int ha_index_or_rnd_end() { return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0; } /** The cached_table_flags is set at ha_open and ha_external_lock */ Table_flags ha_table_flags() const { DBUG_ASSERT((cached_table_flags >> 1) < HA_LAST_TABLE_FLAG); return cached_table_flags; } /** These functions represent the public interface to *users* of the handler class, hence they are *not* virtual. For the inheritance interface, see the (private) functions write_row(), update_row(), and delete_row() below. */ int ha_external_lock(THD *thd, int lock_type); int ha_external_unlock(THD *thd) { return ha_external_lock(thd, F_UNLCK); } int ha_write_row(const uchar * buf); int ha_update_row(const uchar * old_data, const uchar * new_data); int ha_delete_row(const uchar * buf); void ha_release_auto_increment(); inline bool keyread_enabled() { return keyread < MAX_KEY; } inline int ha_start_keyread(uint idx) { DBUG_ASSERT(!keyread_enabled()); keyread= idx; return extra_opt(HA_EXTRA_KEYREAD, idx); } inline int ha_end_keyread() { if (!keyread_enabled()) /* Enably lazy usage */ return 0; keyread= MAX_KEY; return extra(HA_EXTRA_NO_KEYREAD); } /* End any active keyread. Return state so that we can restore things at end. */ int ha_end_active_keyread() { int org_keyread; if (!keyread_enabled()) return MAX_KEY; org_keyread= keyread; ha_end_keyread(); return org_keyread; } /* Restore state to before ha_end_active_keyread */ void ha_restart_keyread(int org_keyread) { DBUG_ASSERT(!keyread_enabled()); if (org_keyread != MAX_KEY) ha_start_keyread(org_keyread); } protected: bool is_root_handler() const; public: int check_collation_compatibility(); int check_long_hash_compatibility() const; int ha_check_for_upgrade(HA_CHECK_OPT *check_opt); /** to be actually called to get 'check()' functionality*/ int ha_check(THD *thd, HA_CHECK_OPT *check_opt); int ha_repair(THD* thd, HA_CHECK_OPT* check_opt); void ha_start_bulk_insert(ha_rows rows, uint flags= 0) { DBUG_ENTER("handler::ha_start_bulk_insert"); estimation_rows_to_insert= rows; bzero(©_info,sizeof(copy_info)); start_bulk_insert(rows, flags); DBUG_VOID_RETURN; } int ha_end_bulk_insert(); int ha_bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found); int ha_delete_all_rows(); int ha_truncate(); int ha_reset_auto_increment(ulonglong value); int ha_optimize(THD* thd, HA_CHECK_OPT* check_opt); int ha_analyze(THD* thd, HA_CHECK_OPT* check_opt); bool ha_check_and_repair(THD *thd); int ha_disable_indexes(key_map map, bool persist); int ha_enable_indexes(key_map map, bool persist); int ha_discard_or_import_tablespace(my_bool discard); int ha_rename_table(const char *from, const char *to); int ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info); int ha_create_partitioning_metadata(const char *name, const char *old_name, chf_create_flags action_flag, bool ignore_delete_error= false); int ha_change_partitions(HA_CREATE_INFO *create_info, const char *path, ulonglong * const copied, ulonglong * const deleted, const uchar *pack_frm_data, size_t pack_frm_len); int ha_drop_partitions(const char *path); int ha_rename_partitions(const char *path); void adjust_next_insert_id_after_explicit_value(ulonglong nr); int update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); /** Retrieves the names of the table and the key for which there was a duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY. If any of the table or key name is not available this method will return false and will not change any of child_table_name or child_key_name. @param child_table_name[out] Table name @param child_table_name_len[in] Table name buffer size @param child_key_name[out] Key name @param child_key_name_len[in] Key name buffer size @retval true table and key names were available and were written into the corresponding out parameters. @retval false table and key names were not available, the out parameters were not touched. */ virtual bool get_foreign_dup_key(char *child_table_name, uint child_table_name_len, char *child_key_name, uint child_key_name_len) { DBUG_ASSERT(false); return(false); } void reset_statistics() { rows_read= rows_changed= rows_tmp_read= 0; bzero(index_rows_read, sizeof(index_rows_read)); bzero(©_info, sizeof(copy_info)); } virtual void reset_copy_info() {} void ha_reset_copy_info() { bzero(©_info, sizeof(copy_info)); reset_copy_info(); } virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share); inline double io_cost(IO_AND_CPU_COST cost) { return cost.io * DISK_READ_COST * DISK_READ_RATIO; } inline double cost(IO_AND_CPU_COST cost) { return io_cost(cost) + cost.cpu; } /* Calculate cost with capping io_blocks to the given maximum. This is done here instead of earlier to allow filtering to work with the original' io_block counts. */ inline double cost(ALL_READ_COST *cost) { double blocks= (MY_MIN(cost->index_cost.io,(double) cost->max_index_blocks) + MY_MIN(cost->row_cost.io, (double) cost->max_row_blocks)); return ((cost->index_cost.cpu + cost->row_cost.cpu + cost->copy_cost) + blocks * DISK_READ_COST * DISK_READ_RATIO); } /* Same as above but without capping. This is only used for comparing cost with s->quick_read time, which does not do any capping. */ inline double cost_no_capping(ALL_READ_COST *cost) { double blocks= (cost->index_cost.io + cost->row_cost.io); return ((cost->index_cost.cpu + cost->row_cost.cpu + cost->copy_cost) + blocks * DISK_READ_COST * DISK_READ_RATIO); } /* Calculate cost when we are going to excute the given read method multiple times */ inline double cost_for_reading_multiple_times(double multiple, ALL_READ_COST *cost) { double blocks= (MY_MIN(cost->index_cost.io * multiple, (double) cost->max_index_blocks) + MY_MIN(cost->row_cost.io * multiple, (double) cost->max_row_blocks)); return ((cost->index_cost.cpu + cost->row_cost.cpu + cost->copy_cost) * multiple + blocks * DISK_READ_COST * DISK_READ_RATIO); } virtual ulonglong row_blocks() { return (stats.data_file_length + IO_SIZE-1) / IO_SIZE; } virtual ulonglong index_blocks(uint index, uint ranges, ha_rows rows); inline ulonglong index_blocks(uint index) { return index_blocks(index, 1, stats.records); } /* Time for a full table data scan. To be overrided by engines, should not be used by the sql level. */ protected: virtual IO_AND_CPU_COST scan_time() { IO_AND_CPU_COST cost; ulonglong length= stats.data_file_length; cost.io= (double) (length / IO_SIZE); cost.cpu= (!stats.block_size ? 0.0 : (double) ((length + stats.block_size-1)/stats.block_size) * INDEX_BLOCK_COPY_COST); return cost; } public: /* Time for a full table scan @param records Number of records from the engine or records from status tables stored by ANALYZE TABLE. The TABLE_SCAN_SETUP_COST is there to prefer range scans to full table scans. This is mainly to make the test suite happy as many tests has very few rows. In real life tables has more than a few rows and the extra cost has no practical effect. */ inline IO_AND_CPU_COST ha_scan_time(ha_rows rows) { IO_AND_CPU_COST cost= scan_time(); cost.cpu+= (TABLE_SCAN_SETUP_COST + (double) rows * (ROW_NEXT_FIND_COST + ROW_COPY_COST)); return cost; } /* Time for a full table scan, fetching the rows from the table and comparing the row with the where clause */ inline IO_AND_CPU_COST ha_scan_and_compare_time(ha_rows rows) { IO_AND_CPU_COST cost= ha_scan_time(rows); cost.cpu+= (double) rows * WHERE_COST; return cost; } /* Update table->share optimizer costs for this particular table. Called once when table is opened the first time. */ virtual void update_optimizer_costs(OPTIMIZER_COSTS *costs) {} /* Set handler optimizer cost variables. Called for each table used by the statment This is virtual mainly for the partition engine. */ virtual void set_optimizer_costs(THD *thd); protected: /* Cost of reading 'rows' number of rows with a rowid */ virtual IO_AND_CPU_COST rnd_pos_time(ha_rows rows) { double r= rows2double(rows); return { r * ((stats.block_size + IO_SIZE -1 )/IO_SIZE), // Blocks read r * INDEX_BLOCK_COPY_COST // Copy block from cache }; } public: /* Time for doing and internal rnd_pos() inside the engine. For some engine, this is more efficient than the SQL layer calling rnd_pos() as there is no overhead in converting/checking the rnd_pos_value. This is used when calculating the cost of fetching a key+row in one go (like when scanning an index and fetching the row). */ inline IO_AND_CPU_COST ha_rnd_pos_time(ha_rows rows) { IO_AND_CPU_COST cost= rnd_pos_time(rows); set_if_smaller(cost.io, (double) row_blocks()); cost.cpu+= rows2double(rows) * (ROW_LOOKUP_COST + ROW_COPY_COST); return cost; } /* This cost if when we are calling rnd_pos() explict in the call For the moment this function is identical to ha_rnd_pos time, but that may change in the future after we do more cost checks for more engines. */ inline IO_AND_CPU_COST ha_rnd_pos_call_time(ha_rows rows) { IO_AND_CPU_COST cost= rnd_pos_time(rows); set_if_smaller(cost.io, (double) row_blocks()); cost.cpu+= rows2double(rows) * (ROW_LOOKUP_COST + ROW_COPY_COST); return cost; } inline IO_AND_CPU_COST ha_rnd_pos_call_and_compare_time(ha_rows rows) { IO_AND_CPU_COST cost; cost= ha_rnd_pos_call_time(rows); cost.cpu+= rows2double(rows) * WHERE_COST; return cost; } /** Calculate cost of 'index_only' scan for given index, a number of ranges and number of records. @param index Index to read @param rows #of records to read @param blocks Number of IO blocks that needs to be accessed. 0 if not known (in which case it's calculated) */ protected: virtual IO_AND_CPU_COST keyread_time(uint index, ulong ranges, ha_rows rows, ulonglong blocks); public: /* Calculate cost of 'keyread' scan for given index and number of records including fetching the key to the 'record' buffer. */ IO_AND_CPU_COST ha_keyread_time(uint index, ulong ranges, ha_rows rows, ulonglong blocks); /* Same as above, but take into account copying the key the the SQL layer */ inline IO_AND_CPU_COST ha_keyread_and_copy_time(uint index, ulong ranges, ha_rows rows, ulonglong blocks) { IO_AND_CPU_COST cost= ha_keyread_time(index, ranges, rows, blocks); cost.cpu+= (double) rows * KEY_COPY_COST; return cost; } inline IO_AND_CPU_COST ha_keyread_and_compare_time(uint index, ulong ranges, ha_rows rows, ulonglong blocks) { IO_AND_CPU_COST cost= ha_keyread_time(index, ranges, rows, blocks); cost.cpu+= (double) rows * (KEY_COPY_COST + WHERE_COST); return cost; } IO_AND_CPU_COST ha_keyread_clustered_time(uint index, ulong ranges, ha_rows rows, ulonglong blocks); /* Time for a full table index scan (without copy or compare cost). To be overrided by engines, sql level should use ha_key_scan_time(). Note that IO_AND_CPU_COST does not include avg_io_cost() ! */ protected: virtual IO_AND_CPU_COST key_scan_time(uint index, ha_rows rows) { return keyread_time(index, 1, MY_MAX(rows, 1), 0); } public: /* Cost of doing a full index scan */ inline IO_AND_CPU_COST ha_key_scan_time(uint index, ha_rows rows) { IO_AND_CPU_COST cost= key_scan_time(index, rows); cost.cpu+= (INDEX_SCAN_SETUP_COST + KEY_LOOKUP_COST + (double) rows * (KEY_NEXT_FIND_COST + KEY_COPY_COST)); return cost; } /* Cost of doing a full index scan with record copy and compare @param rows Rows from stat tables */ inline IO_AND_CPU_COST ha_key_scan_and_compare_time(uint index, ha_rows rows) { IO_AND_CPU_COST cost= ha_key_scan_time(index, rows); cost.cpu+= (double) rows * WHERE_COST; return cost; } virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; } /* True if changes to the table is persistent (if there are no rollback) This is used to decide: - If the table is stored in the transaction or non transactional binary log - How things are tracked in trx and in add_changed_table(). - If we can combine several statements under one commit in the binary log. */ bool has_transactions() const { return ((ha_table_flags() & (HA_NO_TRANSACTIONS | HA_PERSISTENT_TABLE)) == 0); } /* True if table has both transactions and rollback. This is used to decide if we should write the changes to the binary log. If this is true, we don't have to write failed statements to the log as they can be rolled back. */ bool has_transactions_and_rollback() const { return has_transactions() && has_rollback(); } /* True if the underlaying table support transactions and rollback */ bool has_transaction_manager() const { return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0 && has_rollback()); } /* True if the underlaying table support TRANSACTIONAL table option */ bool has_transactional_option() const { extern handlerton *maria_hton; return partition_ht() == maria_hton || has_transaction_manager(); } /* True if table has rollback. Used to check if an update on the table can be killed fast. */ bool has_rollback() const { return ((ht->flags & HTON_NO_ROLLBACK) == 0); } /** This method is used to analyse the error to see whether the error is ignorable or not, certain handlers can have more error that are ignorable than others. E.g. the partition handler can get inserts into a range where there is no partition and this is an ignorable error. HA_ERR_FOUND_DUP_UNIQUE is a special case in MyISAM that means the same thing as HA_ERR_FOUND_DUP_KEY but can in some cases lead to a slightly different error message. */ virtual bool is_fatal_error(int error, uint flags) { if (!error || ((flags & HA_CHECK_DUP_KEY) && (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)) || error == HA_ERR_AUTOINC_ERANGE || ((flags & HA_CHECK_FK_ERROR) && (error == HA_ERR_ROW_IS_REFERENCED || error == HA_ERR_NO_REFERENCED_ROW))) return FALSE; return TRUE; } /** Number of rows in table. It will only be called if (table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0 */ virtual int pre_records() { return 0; } virtual ha_rows records() { return stats.records; } /** Return upper bound of current number of records in the table (max. of how many records one will retrieve when doing a full table scan) If upper bound is not known, HA_POS_ERROR should be returned as a max possible upper bound. */ virtual ha_rows estimate_rows_upper_bound() { return stats.records+EXTRA_RECORDS; } /** Get the row type from the storage engine. If this method returns ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used. */ virtual enum row_type get_row_type() const { return ROW_TYPE_NOT_USED; } virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";} /** Signal that the table->read_set and table->write_set table maps changed The handler is allowed to set additional bits in the above map in this call. Normally the handler should ignore all calls until we have done a ha_rnd_init() or ha_index_init(), write_row(), update_row or delete_row() as there may be several calls to this routine. */ virtual void column_bitmaps_signal(); /* We have to check for inited as some engines, like innodb, sets active_index during table scan. */ uint get_index(void) const { return inited == INDEX ? active_index : MAX_KEY; } int ha_close(void); /** @retval 0 Bulk update used by handler @retval 1 Bulk update not used, normal operation used */ virtual bool start_bulk_update() { return 1; } /** @retval 0 Bulk delete used by handler @retval 1 Bulk delete not used, normal operation used */ virtual bool start_bulk_delete() { return 1; } /** After this call all outstanding updates must be performed. The number of duplicate key errors are reported in the duplicate key parameter. It is allowed to continue to the batched update after this call, the handler has to wait until end_bulk_update with changing state. @param dup_key_found Number of duplicate keys found @retval 0 Success @retval >0 Error code */ virtual int exec_bulk_update(ha_rows *dup_key_found) { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } /** Perform any needed clean-up, no outstanding updates are there at the moment. */ virtual int end_bulk_update() { return 0; } /** Execute all outstanding deletes and close down the bulk delete. @retval 0 Success @retval >0 Error code */ virtual int end_bulk_delete() { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } virtual int pre_index_read_map(const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag, bool use_parallel) { return 0; } virtual int pre_index_first(bool use_parallel) { return 0; } virtual int pre_index_last(bool use_parallel) { return 0; } virtual int pre_index_read_last_map(const uchar *key, key_part_map keypart_map, bool use_parallel) { return 0; } /* virtual int pre_read_multi_range_first(KEY_MULTI_RANGE **found_range_p, KEY_MULTI_RANGE *ranges, uint range_count, bool sorted, HANDLER_BUFFER *buffer, bool use_parallel); */ virtual int pre_multi_range_read_next(bool use_parallel) { return 0; } virtual int pre_read_range_first(const key_range *start_key, const key_range *end_key, bool eq_range, bool sorted, bool use_parallel) { return 0; } virtual int pre_ft_read(bool use_parallel) { return 0; } virtual int pre_rnd_next(bool use_parallel) { return 0; } int ha_pre_rnd_init(bool scan) { int result; DBUG_ENTER("ha_pre_rnd_init"); DBUG_ASSERT(pre_inited==NONE || (pre_inited==RND && scan)); pre_inited= (result= pre_rnd_init(scan)) ? NONE: RND; DBUG_RETURN(result); } int ha_pre_rnd_end() { DBUG_ENTER("ha_pre_rnd_end"); DBUG_ASSERT(pre_inited==RND); pre_inited=NONE; DBUG_RETURN(pre_rnd_end()); } virtual int pre_rnd_init(bool scan) { return 0; } virtual int pre_rnd_end() { return 0; } virtual int pre_index_init(uint idx, bool sorted) { return 0; } virtual int pre_index_end() { return 0; } int ha_pre_index_init(uint idx, bool sorted) { int result; DBUG_ENTER("ha_pre_index_init"); DBUG_ASSERT(pre_inited==NONE); if (!(result= pre_index_init(idx, sorted))) pre_inited=INDEX; DBUG_RETURN(result); } int ha_pre_index_end() { DBUG_ENTER("ha_pre_index_end"); DBUG_ASSERT(pre_inited==INDEX); pre_inited=NONE; DBUG_RETURN(pre_index_end()); } int ha_pre_index_or_rnd_end() { return (pre_inited == INDEX ? ha_pre_index_end() : pre_inited == RND ? ha_pre_rnd_end() : 0 ); } virtual bool vers_can_native(THD *thd) { return ht->flags & HTON_NATIVE_SYS_VERSIONING; } /** @brief Positions an index cursor to the index specified in the handle. Fetches the row if available. If the key value is null, begin at the first key of the index. */ protected: virtual int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); return index_read(buf, key, key_len, find_flag); } /** @brief Positions an index cursor to the index specified in the handle. Fetches the row if available. If the key value is null, begin at the first key of the index. */ virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); virtual int index_next(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_prev(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_first(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); /** @brief The following functions works like index_read, but it find the last row with the current key value or prefix. @returns @see index_read_map(). */ virtual int index_read_last_map(uchar * buf, const uchar * key, key_part_map keypart_map) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); return index_read_last(buf, key, key_len); } virtual int close(void)=0; inline void update_rows_read() { if (likely(!internal_tmp_table)) rows_read++; else rows_tmp_read++; } inline void update_index_statistics() { index_rows_read[active_index]++; update_rows_read(); } public: int ha_index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); int ha_index_next(uchar * buf); int ha_index_prev(uchar * buf); int ha_index_first(uchar * buf); int ha_index_last(uchar * buf); int ha_index_next_same(uchar *buf, const uchar *key, uint keylen); /* TODO: should we make for those functions non-virtual ha_func_name wrappers, too? */ virtual ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, void *seq_init_param, uint n_ranges, uint *bufsz, uint *mrr_mode, ha_rows limit, Cost_estimate *cost); virtual ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys, uint key_parts, uint *bufsz, uint *mrr_mode, Cost_estimate *cost); virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, uint n_ranges, uint mrr_mode, HANDLER_BUFFER *buf); virtual int multi_range_read_next(range_id_t *range_info); private: inline void calculate_costs(Cost_estimate *cost, uint keyno, uint ranges, uint multi_row_ranges, uint flags, ha_rows total_rows, ulonglong io_blocks, ulonglong unassigned_single_point_ranges); public: /* Return string representation of the MRR plan. This is intended to be used for EXPLAIN, via the following scenario: 1. SQL layer calls handler->multi_range_read_info(). 1.1. Storage engine figures out whether it will use some non-default MRR strategy, sets appropritate bits in *mrr_mode, and returns control to SQL layer 2. SQL layer remembers the returned mrr_mode 3. SQL layer compares various options and choses the final query plan. As a part of that, it makes a choice of whether to use the MRR strategy picked in 1.1 4. EXPLAIN code converts the query plan to its text representation. If MRR strategy is part of the plan, it calls multi_range_read_explain_info(mrr_mode) to get a text representation of the picked MRR strategy. @param mrr_mode Mode which was returned by multi_range_read_info[_const] @param str INOUT string to be printed for EXPLAIN @param str_end End of the string buffer. The function is free to put the string into [str..str_end] memory range. */ virtual int multi_range_read_explain_info(uint mrr_mode, char *str, size_t size) { return 0; } virtual int read_range_first(const key_range *start_key, const key_range *end_key, bool eq_range, bool sorted); virtual int read_range_next(); void set_end_range(const key_range *end_key); int compare_key(key_range *range); int compare_key2(key_range *range) const; virtual int ft_init() { return HA_ERR_WRONG_COMMAND; } virtual int pre_ft_init() { return HA_ERR_WRONG_COMMAND; } virtual void ft_end() {} virtual int pre_ft_end() { return 0; } virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } public: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; /** This function only works for handlers having HA_PRIMARY_KEY_REQUIRED_FOR_POSITION set. It will return the row with the PK given in the record argument. */ virtual int rnd_pos_by_record(uchar *record) { int error; DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION); error = ha_rnd_init(false); if (error != 0) return error; position(record); error = ha_rnd_pos(record, ref); ha_rnd_end(); return error; } virtual int read_first_row(uchar *buf, uint primary_key); public: /* Same as above, but with statistics */ inline int ha_ft_read(uchar *buf); inline void ha_ft_end() { ft_end(); ft_handler=NULL; } int ha_rnd_next(uchar *buf); int ha_rnd_pos(uchar *buf, uchar *pos); inline int ha_rnd_pos_by_record(uchar *buf); inline int ha_read_first_row(uchar *buf, uint primary_key); /** The following 2 function is only needed for tables that may be internal temporary tables during joins. */ virtual int remember_rnd_pos() { return HA_ERR_WRONG_COMMAND; } virtual int restart_rnd_next(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual ha_rows records_in_range(uint inx, const key_range *min_key, const key_range *max_key, page_range *res) { return (ha_rows) 10; } /* If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, then it sets ref (reference to the row, aka position, with the primary key given in the record). Otherwise it set ref to the current row. */ virtual void position(const uchar *record)=0; virtual int info(uint)=0; // see my_base.h for full description virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id); virtual void set_partitions_to_open(List<String> *partition_names) {} virtual bool check_if_updates_are_ignored(const char *op) const; virtual int change_partitions_to_open(List<String> *partition_names) { return 0; } virtual int extra(enum ha_extra_function operation) { return 0; } virtual int extra_opt(enum ha_extra_function operation, ulong arg) { return extra(operation); } /* Table version id for the table. This should change for each sucessfull ALTER TABLE. This is used by the handlerton->check_version() to ask the engine if the table definition has been updated. Storage engines that does not support inplace alter table does not have to support this call. */ virtual ulonglong table_version() const { return 0; } /** In an UPDATE or DELETE, if the row under the cursor was locked by another transaction, and the engine used an optimistic read of the last committed row value under the cursor, then the engine returns 1 from this function. MySQL must NOT try to update this optimistic value. If the optimistic value does not match the WHERE condition, MySQL can decide to skip over this row. Currently only works for InnoDB. This can be used to avoid unnecessary lock waits. If this method returns nonzero, it will also signal the storage engine that the next read will be a locking re-read of the row. */ bool ha_was_semi_consistent_read(); virtual bool was_semi_consistent_read() { return 0; } /** Tell the engine whether it should avoid unnecessary lock waits. If yes, in an UPDATE or DELETE, if the row under the cursor was locked by another transaction, the engine may try an optimistic read of the last committed row value under the cursor. */ virtual void try_semi_consistent_read(bool) {} virtual void unlock_row() {} virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;} virtual bool need_info_for_auto_inc() { return 0; } virtual bool can_use_for_auto_inc_init() { return 1; } virtual void get_auto_increment(ulonglong offset, ulonglong increment, ulonglong nb_desired_values, ulonglong *first_value, ulonglong *nb_reserved_values); void set_next_insert_id(ulonglong id) { DBUG_PRINT("info",("auto_increment: next value %lu", (ulong)id)); next_insert_id= id; } virtual void restore_auto_increment(ulonglong prev_insert_id) { /* Insertion of a row failed, re-use the lastly generated auto_increment id, for the next row. This is achieved by resetting next_insert_id to what it was before the failed insertion (that old value is provided by the caller). If that value was 0, it was the first row of the INSERT; then if insert_id_for_cur_row contains 0 it means no id was generated for this first row, so no id was generated since the INSERT started, so we should set next_insert_id to 0; if insert_id_for_cur_row is not 0, it is the generated id of the first and failed row, so we use it. */ next_insert_id= (prev_insert_id > 0) ? prev_insert_id : insert_id_for_cur_row; } virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } /* end of the list of admin commands */ virtual int indexes_are_disabled(void) {return 0;} virtual void append_create_info(String *packet) {} /** If index == MAX_KEY then a check for table is made and if index < MAX_KEY then a check is made if the table has foreign keys and if a foreign key uses this index (and thus the index cannot be dropped). @param index Index to check if foreign key uses it @retval TRUE Foreign key defined on table or index @retval FALSE No foreign key defined */ virtual bool is_fk_defined_on_table_or_index(uint index) { return FALSE; } virtual char* get_foreign_key_create_info() { return(NULL);} /* gets foreign key create string from InnoDB */ /** Used in ALTER TABLE to check if changing storage engine is allowed. @note Called without holding thr_lock.c lock. @retval true Changing storage engine is allowed. @retval false Changing storage engine not allowed. */ virtual bool can_switch_engines() { return true; } virtual int can_continue_handler_scan() { return 0; } /** Get the list of foreign keys in this table. @remark Returns the set of foreign keys where this table is the dependent or child table. @param thd The thread handle. @param f_key_list[out] The list of foreign keys. @return The handler error code or zero for success. */ virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) { return 0; } /** Get the list of foreign keys referencing this table. @remark Returns the set of foreign keys where this table is the referenced or parent table. @param thd The thread handle. @param f_key_list[out] The list of foreign keys. @return The handler error code or zero for success. */ virtual int get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) { return 0; } virtual bool referenced_by_foreign_key() const noexcept { return false;} virtual void init_table_handle_for_HANDLER() { return; } /* prepare InnoDB for HANDLER */ virtual void free_foreign_key_create_info(char* str) {} /** The following can be called without an open handler */ virtual const char *table_type() const { return hton_name(ht)->str; } /* The following is same as table_table(), except for partition engine */ virtual const char *real_table_type() const { return hton_name(ht)->str; } const char **bas_ext() const { return ht->tablefile_extensions; } virtual int get_default_no_partitions(HA_CREATE_INFO *create_info) { return 1;} virtual void set_auto_partitions(partition_info *part_info) { return; } virtual bool get_no_parts(const char *name, uint *no_parts) { *no_parts= 0; return 0; } virtual void set_part_info(partition_info *part_info) {return;} virtual void return_record_by_parent() { return; } /* Information about index. Both index and part starts from 0 */ virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0; uint max_record_length() const { return MY_MIN(HA_MAX_REC_LENGTH, max_supported_record_length()); } uint max_keys() const { return MY_MIN(MAX_KEY, max_supported_keys()); } uint max_key_parts() const { return MY_MIN(MAX_REF_PARTS, max_supported_key_parts()); } uint max_key_length() const { return MY_MIN(MAX_DATA_LENGTH_FOR_KEY, max_supported_key_length()); } uint max_key_part_length() const { return MY_MIN(MAX_DATA_LENGTH_FOR_KEY, max_supported_key_part_length()); } virtual uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; } virtual uint max_supported_keys() const { return 0; } virtual uint max_supported_key_parts() const { return MAX_REF_PARTS; } virtual uint max_supported_key_length() const { return MAX_DATA_LENGTH_FOR_KEY; } virtual uint max_supported_key_part_length() const { return 255; } virtual uint min_record_length(uint options) const { return 1; } virtual int pre_calculate_checksum() { return 0; } virtual int calculate_checksum(); virtual bool is_crashed() const { return 0; } virtual bool auto_repair(int error) const { return 0; } void update_global_table_stats(); void update_global_index_stats(); /** @note lock_count() can return > 1 if the table is MERGE or partitioned. */ virtual uint lock_count(void) const { return 1; } /** Get the lock(s) for the table and perform conversion of locks if needed. Is not invoked for non-transactional temporary tables. @note store_lock() can return more than one lock if the table is MERGE or partitioned. @note that one can NOT rely on table->in_use in store_lock(). It may refer to a different thread if called from mysql_lock_abort_for_thread(). @note If the table is MERGE, store_lock() can return less locks than lock_count() claimed. This can happen when the MERGE children are not attached when this is called from another thread. */ virtual THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type)=0; /** Type of table for caching query */ virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; } /** @brief Register a named table with a call back function to the query cache. @param thd The thread handle @param table_key A pointer to the table name in the table cache @param key_length The length of the table name @param[out] engine_callback The pointer to the storage engine call back function @param[out] engine_data Storage engine specific data which could be anything This method offers the storage engine, the possibility to store a reference to a table name which is going to be used with query cache. The method is called each time a statement is written to the cache and can be used to verify if a specific statement is cacheable. It also offers the possibility to register a generic (but static) call back function which is called each time a statement is matched against the query cache. @note If engine_data supplied with this function is different from engine_data supplied with the callback function, and the callback returns FALSE, a table invalidation on the current table will occur. @return Upon success the engine_callback will point to the storage engine call back function, if any, and engine_data will point to any storage engine data used in the specific implementation. @retval TRUE Success @retval FALSE The specified table or current statement should not be cached */ virtual my_bool register_query_cache_table(THD *thd, const char *table_key, uint key_length, qc_engine_callback *callback, ulonglong *engine_data) { *callback= 0; return TRUE; } /* Count tables invisible from all tables list on which current one built (like myisammrg and partitioned tables) tables_type mask for the tables should be added herdde returns number of such tables */ virtual uint count_query_cache_dependant_tables(uint8 *tables_type __attribute__((unused))) { return 0; } /* register tables invisible from all tables list on which current one built (like myisammrg and partitioned tables). @note they should be counted by method above cache Query cache pointer block Query cache block to write the table n Number of the table @retval FALSE - OK @retval TRUE - Error */ virtual my_bool register_query_cache_dependant_tables(THD *thd __attribute__((unused)), Query_cache *cache __attribute__((unused)), Query_cache_block_table **block __attribute__((unused)), uint *n __attribute__((unused))) { return FALSE; } /* Check if the key is a clustering key - Data is stored together with the primary key (no secondary lookup needed to find the row data). The optimizer uses this to find out the cost of fetching data. Note that in many cases a clustered key is also a reference key. This means that: - The key is part of each secondary key and is used to find the row data in the primary index when reading trough secondary indexes. - When doing a HA_KEYREAD_ONLY we get also all the primary key parts into the row. This is critical property used by index_merge. All the above is usually true for engines that store the row data in the primary key index (e.g. in a b-tree), and use the key key value as a position(). InnoDB is an example of such an engine. For a clustered (primary) key, the following should also hold: index_flags() should contain HA_CLUSTERED_INDEX index_flags() should not contain HA_KEYREAD_ONLY or HA_DO_RANGE_FILTER_PUSHDOWN table_flags() should contain HA_TABLE_SCAN_ON_INDEX For a reference key the following should also hold: table_flags() should contain HA_PRIMARY_KEY_IS_READ_INDEX. @retval TRUE yes @retval FALSE No. */ /* The following code is for primary keys */ inline bool pk_is_clustering_key(uint index) const; /* Same as before but for other keys, in which case we can skip the check */ inline bool is_clustering_key(uint index) const; virtual int cmp_ref(const uchar *ref1, const uchar *ref2) { return memcmp(ref1, ref2, ref_length); } /* Condition pushdown to storage engines */ /** Push condition down to the table handler. @param cond Condition to be pushed. The condition tree must not be modified by the by the caller. @return The 'remainder' condition that caller must use to filter out records. NULL means the handler will not return rows that do not match the passed condition. @note The pushed conditions form a stack (from which one can remove the last pushed condition using cond_pop). The table handler filters out rows using (pushed_cond1 AND pushed_cond2 AND ... AND pushed_condN) or less restrictive condition, depending on handler's capabilities. handler->ha_reset() call empties the condition stack. Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the condition stack. */ virtual const COND *cond_push(const COND *cond) { return cond; }; /** Pop the top condition from the condition stack of the handler instance. Pops the top if condition stack, if stack is not empty. */ virtual void cond_pop() { return; }; /** Push metadata for the current operation down to the table handler. */ virtual int info_push(uint info_type, void *info) { return 0; }; /** Push down an index condition to the handler. The server will use this method to push down a condition it wants the handler to evaluate when retrieving records using a specified index. The pushed index condition will only refer to fields from this handler that is contained in the index (but it may also refer to fields in other handlers). Before the handler evaluates the condition it must read the content of the index entry into the record buffer. The handler is free to decide if and how much of the condition it will take responsibility for evaluating. Based on this evaluation it should return the part of the condition it will not evaluate. If it decides to evaluate the entire condition it should return NULL. If it decides not to evaluate any part of the condition it should return a pointer to the same condition as given as argument. @param keyno the index number to evaluate the condition on @param idx_cond the condition to be evaluated by the handler @return The part of the pushed condition that the handler decides not to evaluate */ virtual Item *idx_cond_push(uint keyno, Item* idx_cond) { return idx_cond; } /** Reset information about pushed index conditions */ virtual void cancel_pushed_idx_cond() { pushed_idx_cond= NULL; pushed_idx_cond_keyno= MAX_KEY; in_range_check_pushed_down= false; } virtual void cancel_pushed_rowid_filter() { pushed_rowid_filter= NULL; if (rowid_filter_is_active) { rowid_filter_is_active= false; rowid_filter_changed(); } } virtual void disable_pushed_rowid_filter() { DBUG_ASSERT(pushed_rowid_filter != NULL && save_pushed_rowid_filter == NULL); save_pushed_rowid_filter= pushed_rowid_filter; save_rowid_filter_is_active= rowid_filter_is_active; pushed_rowid_filter= NULL; if (rowid_filter_is_active) { rowid_filter_is_active= false; rowid_filter_changed(); } } virtual void enable_pushed_rowid_filter() { DBUG_ASSERT(save_pushed_rowid_filter != NULL && pushed_rowid_filter == NULL); pushed_rowid_filter= save_pushed_rowid_filter; save_pushed_rowid_filter= NULL; if (save_rowid_filter_is_active) { rowid_filter_is_active= true; rowid_filter_changed(); } } virtual bool rowid_filter_push(Rowid_filter *rowid_filter) { return true; } /* Signal that rowid filter may have been enabled / disabled */ virtual void rowid_filter_changed() {} /* Needed for partition / spider */ virtual TABLE_LIST *get_next_global_for_child() { return NULL; } /** Part of old, deprecated in-place ALTER API. */ virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) { return COMPATIBLE_DATA_NO; } /* On-line/in-place ALTER TABLE interface. */ /* Here is an outline of on-line/in-place ALTER TABLE execution through this interface. Phase 1 : Initialization ======================== During this phase we determine which algorithm should be used for execution of ALTER TABLE and what level concurrency it will require. *) This phase starts by opening the table and preparing description of the new version of the table. *) Then we check if it is impossible even in theory to carry out this ALTER TABLE using the in-place algorithm. For example, because we need to change storage engine or the user has explicitly requested usage of the "copy" algorithm. *) If in-place ALTER TABLE is theoretically possible, we continue by compiling differences between old and new versions of the table in the form of HA_ALTER_FLAGS bitmap. We also build a few auxiliary structures describing requested changes and store all these data in the Alter_inplace_info object. *) Then the handler::check_if_supported_inplace_alter() method is called in order to find if the storage engine can carry out changes requested by this ALTER TABLE using the in-place algorithm. To determine this, the engine can rely on data in HA_ALTER_FLAGS/Alter_inplace_info passed to it as well as on its own checks. If the in-place algorithm can be used for this ALTER TABLE, the level of required concurrency for its execution is also returned. If any errors occur during the handler call, ALTER TABLE is aborted and no further handler functions are called. *) Locking requirements of the in-place algorithm are compared to any concurrency requirements specified by user. If there is a conflict between them, we either switch to the copy algorithm or emit an error. Phase 2 : Execution =================== In this phase the operations are executed. *) As the first step, we acquire a lock corresponding to the concurrency level which was returned by handler::check_if_supported_inplace_alter() and requested by the user. This lock is held for most of the duration of in-place ALTER (if HA_ALTER_INPLACE_COPY_LOCK or HA_ALTER_INPLACE_COPY_NO_LOCK were returned we acquire an exclusive lock for duration of the next step only). *) After that we call handler::ha_prepare_inplace_alter_table() to give the storage engine a chance to update its internal structures with a higher lock level than the one that will be used for the main step of algorithm. After that we downgrade the lock if it is necessary. *) After that, the main step of this phase and algorithm is executed. We call the handler::ha_inplace_alter_table() method, which carries out the changes requested by ALTER TABLE but does not makes them visible to other connections yet. *) We ensure that no other connection uses the table by upgrading our lock on it to exclusive. *) a) If the previous step succeeds, handler::ha_commit_inplace_alter_table() is called to allow the storage engine to do any final updates to its structures, to make all earlier changes durable and visible to other connections. b) If we have failed to upgrade lock or any errors have occurred during the handler functions calls (including commit), we call handler::ha_commit_inplace_alter_table() to rollback all changes which were done during previous steps. Phase 3 : Final =============== In this phase we: *) Update SQL-layer data-dictionary by installing .FRM file for the new version of the table. *) Inform the storage engine about this change by calling the hton::notify_table_changed() *) Destroy the Alter_inplace_info and handler_ctx objects. */ /** Check if a storage engine supports a particular alter table in-place @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data used during in-place alter. @retval HA_ALTER_ERROR Unexpected error. @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy. @retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock. @retval HA_ALTER_INPLACE_COPY_LOCK Supported, but requires SNW lock during main phase. Prepare phase requires X lock. @retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock. @retval HA_ALTER_INPLACE_COPY_NO_LOCK Supported, concurrent reads/writes allowed. However, prepare phase requires X lock. @retval HA_ALTER_INPLACE_NO_LOCK Supported, concurrent reads/writes allowed. @note The default implementation uses the old in-place ALTER API to determine if the storage engine supports in-place ALTER or not. @note Called without holding thr_lock.c lock. */ virtual enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info); /** Public functions wrapping the actual handler call. @see prepare_inplace_alter_table() */ bool ha_prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info); /** Public function wrapping the actual handler call. @see inplace_alter_table() */ bool ha_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { return inplace_alter_table(altered_table, ha_alter_info); } /** Public function wrapping the actual handler call. Allows us to enforce asserts regardless of handler implementation. @see commit_inplace_alter_table() */ bool ha_commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit); protected: /** Allows the storage engine to update internal structures with concurrent writes blocked. If check_if_supported_inplace_alter() returns HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_COPY_LOCK, this function is called with exclusive lock otherwise the same level of locking as for inplace_alter_table() will be used. @note Storage engines are responsible for reporting any errors by calling my_error()/print_error() @note If this function reports error, commit_inplace_alter_table() will be called with commit= false. @note For partitioning, failing to prepare one partition, means that commit_inplace_alter_table() will be called to roll back changes for all partitions. This means that commit_inplace_alter_table() might be called without prepare_inplace_alter_table() having been called first for a given partition. @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data used during in-place alter. @retval true Error @retval false Success */ virtual bool prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { return false; } /** Alter the table structure in-place with operations specified using HA_ALTER_FLAGS and Alter_inplace_info. The level of concurrency allowed during this operation depends on the return value from check_if_supported_inplace_alter(). @note Storage engines are responsible for reporting any errors by calling my_error()/print_error() @note If this function reports error, commit_inplace_alter_table() will be called with commit= false. @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data used during in-place alter. @retval true Error @retval false Success */ virtual bool inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { return false; } /** Commit or rollback the changes made during prepare_inplace_alter_table() and inplace_alter_table() inside the storage engine. Note that in case of rollback the allowed level of concurrency during this operation will be the same as for inplace_alter_table() and thus might be higher than during prepare_inplace_alter_table(). (For example, concurrent writes were blocked during prepare, but might not be during rollback). @note Storage engines are responsible for reporting any errors by calling my_error()/print_error() @note If this function with commit= true reports error, it will be called again with commit= false. @note In case of partitioning, this function might be called for rollback without prepare_inplace_alter_table() having been called first. Also partitioned tables sets ha_alter_info->group_commit_ctx to a NULL terminated array of the partitions handlers and if all of them are committed as one, then group_commit_ctx should be set to NULL to indicate to the partitioning handler that all partitions handlers are committed. @see prepare_inplace_alter_table(). @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data used during in-place alter. @param commit True => Commit, False => Rollback. @retval true Error @retval false Success */ virtual bool commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit) { /* Nothing to commit/rollback, mark all handlers committed! */ ha_alter_info->group_commit_ctx= NULL; return false; } public: /* End of On-line/in-place ALTER TABLE interface. */ /** use_hidden_primary_key() is called in case of an update/delete when (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined but we don't have a primary key */ virtual void use_hidden_primary_key(); virtual alter_table_operations alter_table_flags(alter_table_operations flags) { if (ht->alter_table_flags) return ht->alter_table_flags(flags); return 0; } virtual LEX_CSTRING *engine_name(); TABLE* get_table() { return table; } TABLE_SHARE* get_table_share() { return table_share; } protected: /* Service methods for use by storage engines. */ THD *ha_thd(void) const; /** Acquire the instrumented table information from a table share. @return an instrumented table share, or NULL. */ PSI_table_share *ha_table_share_psi() const; /** Default rename_table() and delete_table() rename/delete files with a given name and extensions from bas_ext(). These methods can be overridden, but their default implementation provide useful functionality. */ virtual int rename_table(const char *from, const char *to); public: /** Delete a table in the engine. Called for base as well as temporary tables. */ virtual int delete_table(const char *name); bool check_table_binlog_row_based(); bool prepare_for_row_logging(); int prepare_for_insert(bool do_create); int binlog_log_row(const uchar *before_record, const uchar *after_record, Log_func *log_func); inline void clear_cached_table_binlog_row_based_flag() { check_table_binlog_row_based_done= 0; } virtual void handler_stats_updated() {} inline void ha_handler_stats_reset() { handler_stats= &active_handler_stats; active_handler_stats.reset(); active_handler_stats.active= 1; handler_stats_updated(); } inline void ha_handler_stats_disable() { if (handler_stats) { handler_stats= 0; active_handler_stats.active= 0; handler_stats_updated(); } } private: /* Cache result to avoid extra calls */ inline void mark_trx_read_write() { if (unlikely(!mark_trx_read_write_done)) { mark_trx_read_write_done= 1; mark_trx_read_write_internal(); } } bool check_old_types() const; void mark_trx_read_write_internal(); bool check_table_binlog_row_based_internal(); int create_lookup_handler(); void alloc_lookup_buffer(); int check_duplicate_long_entry_key(const uchar *new_rec, uint key_no); /** PRIMARY KEY/UNIQUE WITHOUT OVERLAPS check */ int ha_check_overlaps(const uchar *old_data, const uchar* new_data); int ha_check_long_uniques(const uchar *old_rec, const uchar *new_rec); int ha_check_inserver_constraints(const uchar *old_data, const uchar* new_data); protected: /* These are intended to be used only by handler::ha_xxxx() functions However, engines that implement read_range_XXX() (like MariaRocks) or embed other engines (like ha_partition) may need to call these also */ /* Increment statistics. As a side effect increase accessed_rows_and_keys and checks if lex->limit_rows_examined_cnt is reached */ inline void increment_statistics(ulong SSV::*offset) const; /* Same as increment_statistics but doesn't increase accessed_rows_and_keys */ inline void fast_increment_statistics(ulong SSV::*offset) const; inline void decrement_statistics(ulong SSV::*offset) const; private: /* Low-level primitives for storage engines. These should be overridden by the storage engine class. To call these methods, use the corresponding 'ha_*' method above. */ virtual int open(const char *name, int mode, uint test_if_locked)=0; /* Note: ha_index_read_idx_map() may bypass index_init() */ virtual int index_init(uint idx, bool sorted) { return 0; } virtual int index_end() { return 0; } /** rnd_init() can be called two times without rnd_end() in between (it only makes sense if scan=1). then the second call should prepare for the new table scan (e.g if rnd_init allocates the cursor, second call should position it to the start of the table, no need to deallocate and allocate it again */ virtual int rnd_init(bool scan)= 0; virtual int rnd_end() { return 0; } virtual int write_row(const uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } /** Update a single row. Note: If HA_ERR_FOUND_DUPP_KEY is returned, the handler must read all columns of the row so MySQL can create an error message. If the columns required for the error message are not read, the error message will contain garbage. */ virtual int update_row(const uchar *old_data __attribute__((unused)), const uchar *new_data __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } /* Optimized function for updating the first row. Only used by sequence tables */ virtual int update_first_row(const uchar *new_data); virtual int delete_row(const uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } /* Perform initialization for a direct update request */ public: int ha_direct_update_rows(ha_rows *update_rows, ha_rows *found_rows); virtual int direct_update_rows_init(List<Item> *update_fields) { return HA_ERR_WRONG_COMMAND; } private: virtual int pre_direct_update_rows_init(List<Item> *update_fields) { return HA_ERR_WRONG_COMMAND; } virtual int direct_update_rows(ha_rows *update_rows __attribute__((unused)), ha_rows *found_rows __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } virtual int pre_direct_update_rows() { return HA_ERR_WRONG_COMMAND; } /* Perform initialization for a direct delete request */ public: int ha_direct_delete_rows(ha_rows *delete_rows); virtual int direct_delete_rows_init() { return HA_ERR_WRONG_COMMAND; } private: virtual int pre_direct_delete_rows_init() { return HA_ERR_WRONG_COMMAND; } virtual int direct_delete_rows(ha_rows *delete_rows __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } virtual int pre_direct_delete_rows() { return HA_ERR_WRONG_COMMAND; } /** Reset state of file to after 'open'. This function is called after every statement for all tables used by that statement. */ virtual int reset() { return 0; } virtual Table_flags table_flags(void) const= 0; /** Is not invoked for non-transactional temporary tables. Tells the storage engine that we intend to read or write data from the table. This call is prefixed with a call to handler::store_lock() and is invoked only for those handler instances that stored the lock. Calls to rnd_init/index_init are prefixed with this call. When table IO is complete, we call external_lock(F_UNLCK). A storage engine writer should expect that each call to ::external_lock(F_[RD|WR]LOCK is followed by a call to ::external_lock(F_UNLCK). If it is not, it is a bug in MySQL. The name and signature originate from the first implementation in MyISAM, which would call fcntl to set/clear an advisory lock on the data file in this method. @param lock_type F_RDLCK, F_WRLCK, F_UNLCK @return non-0 in case of failure, 0 in case of success. When lock_type is F_UNLCK, the return value is ignored. */ virtual int external_lock(THD *thd __attribute__((unused)), int lock_type __attribute__((unused))) { return 0; } virtual void release_auto_increment() { return; }; /** admin commands - called from mysql_admin_table */ virtual int check_for_upgrade(HA_CHECK_OPT *check_opt) { return 0; } virtual int check(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } /** In this method check_opt can be modified to specify CHECK option to use to call check() upon the table. */ virtual int repair(THD* thd, HA_CHECK_OPT* check_opt) { DBUG_ASSERT(!(ha_table_flags() & HA_CAN_REPAIR)); return HA_ADMIN_NOT_IMPLEMENTED; } protected: virtual void start_bulk_insert(ha_rows rows, uint flags) {} virtual int end_bulk_insert() { return 0; } virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) { my_errno= HA_ERR_WRONG_COMMAND; return HA_ERR_WRONG_COMMAND; } friend class ha_partition; friend class ha_sequence; public: /** This method is similar to update_row, however the handler doesn't need to execute the updates at this point in time. The handler can be certain that another call to bulk_update_row will occur OR a call to exec_bulk_update before the set of updates in this query is concluded. @param old_data Old record @param new_data New record @param dup_key_found Number of duplicate keys found @retval 0 Bulk delete used by handler @retval 1 Bulk delete not used, normal operation used */ virtual int bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found) { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } /** This is called to delete all rows in a table If the handler don't support this, then this function will return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one by one. */ virtual int delete_all_rows() { return (my_errno=HA_ERR_WRONG_COMMAND); } /** Quickly remove all rows from a table. @remark This method is responsible for implementing MySQL's TRUNCATE TABLE statement, which is a DDL operation. As such, a engine can bypass certain integrity checks and in some cases avoid fine-grained locking (e.g. row locks) which would normally be required for a DELETE statement. @remark Typically, truncate is not used if it can result in integrity violation. For example, truncate is not used when a foreign key references the table, but it might be used if foreign key checks are disabled. @remark Engine is responsible for resetting the auto-increment counter. @remark The table is locked in exclusive mode. */ virtual int truncate() { int error= delete_all_rows(); return error ? error : reset_auto_increment(0); } /** Reset the auto-increment counter to the given value, i.e. the next row inserted will get the given value. */ virtual int reset_auto_increment(ulonglong value) { return 0; } virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } virtual bool check_and_repair(THD *thd) { return TRUE; } virtual int disable_indexes(key_map map, bool persist) { return HA_ERR_WRONG_COMMAND; } virtual int enable_indexes(key_map map, bool persist) { return HA_ERR_WRONG_COMMAND; } virtual int discard_or_import_tablespace(my_bool discard) { return (my_errno=HA_ERR_WRONG_COMMAND); } virtual void drop_table(const char *name); virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0; virtual int create_partitioning_metadata(const char *name, const char *old_name, chf_create_flags action_flag, bool ignore_delete_error) { return FALSE; } virtual int change_partitions(HA_CREATE_INFO *create_info, const char *path, ulonglong * const copied, ulonglong * const deleted, const uchar *pack_frm_data, size_t pack_frm_len) { return HA_ERR_WRONG_COMMAND; } /* @return true if it's necessary to switch current statement log format from STATEMENT to ROW if binary log format is MIXED and autoincrement values are changed in the statement */ virtual bool autoinc_lock_mode_stmt_unsafe() const { return false; } virtual int drop_partitions(const char *path) { return HA_ERR_WRONG_COMMAND; } virtual int rename_partitions(const char *path) { return HA_ERR_WRONG_COMMAND; } virtual bool set_ha_share_ref(Handler_share **arg_ha_share) { DBUG_ASSERT(!ha_share); DBUG_ASSERT(arg_ha_share); if (ha_share || !arg_ha_share) return true; ha_share= arg_ha_share; return false; } inline void set_table(TABLE* table_arg); int get_lock_type() const { return m_lock_type; } public: /* XXX to be removed, see ha_partition::partition_ht() */ virtual handlerton *partition_ht() const { return ht; } virtual bool partition_engine() { return 0;} /* Used with 'wrapper' engines, like SEQUENCE, to access to the underlaying engine used for storage. */ virtual handlerton *storage_ht() const { return ht; } inline int ha_write_tmp_row(uchar *buf); inline int ha_delete_tmp_row(uchar *buf); inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data); virtual void set_lock_type(enum thr_lock_type lock); friend check_result_t handler_index_cond_check(void* h_arg); friend check_result_t handler_rowid_filter_check(void *h_arg); /** Find unique record by index or unique constrain @param record record to find (also will be fillded with actual record fields) @param unique_ref index or unique constraiun number (depends on what used in the engine @retval -1 Error @retval 1 Not found @retval 0 Found */ virtual int find_unique_row(uchar *record, uint unique_ref) { return -1; /*unsupported */} bool native_versioned() const { DBUG_ASSERT(ht); return partition_ht()->flags & HTON_NATIVE_SYS_VERSIONING; } virtual void update_partition(uint part_id) {} /** Some engines can perform column type conversion with ALGORITHM=INPLACE. These functions check for such possibility. Implementation could be based on Field_xxx::is_equal() */ virtual bool can_convert_nocopy(const Field &, const Column_definition &) const { return false; } /* If the table is using sql level unique constraints on some column */ inline bool has_long_unique(); /* Used for ALTER TABLE. Some engines can handle some differences in indexes by themself. */ virtual Compare_keys compare_key_parts(const Field &old_field, const Column_definition &new_field, const KEY_PART_INFO &old_part, const KEY_PART_INFO &new_part) const; /* If lower_case_table_names == 2 (case-preserving but case-insensitive file system) and the storage is not HA_FILE_BASED, we need to provide a lowercase file name for the engine. */ inline bool needs_lower_case_filenames() const { return (lower_case_table_names == 2 && !(ha_table_flags() & HA_FILE_BASED)); } Lex_cstring get_canonical_filename(const Lex_cstring &path, Table_path_buffer *tmp_path) const; bool is_canonical_filename(const LEX_CSTRING &path) const { Table_path_buffer cpath; return !strcmp(path.str, get_canonical_filename(path, &cpath).str); } bool log_not_redoable_operation(const char *operation); protected: Handler_share *get_ha_share_ptr(); void set_ha_share_ptr(Handler_share *arg_ha_share); void lock_shared_ha_data(); void unlock_shared_ha_data(); /* Mroonga needs to call some xxx_time() directly for it's internal handler methods */ friend class ha_mroonga; }; #include "multi_range_read.h" #include "group_by_handler.h" bool key_uses_partial_cols(TABLE_SHARE *table, uint keyno); /* Some extern variables used with handlers */ extern const LEX_CSTRING ha_row_type[]; extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[]; extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[]; extern TYPELIB tx_isolation_typelib; extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; /* lookups */ plugin_ref ha_resolve_by_name(THD *thd, const LEX_CSTRING *name, bool tmp_table); plugin_ref ha_lock_engine(THD *thd, const handlerton *hton); handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type); handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, handlerton *db_type); handlerton *ha_checktype(THD *thd, handlerton *hton, bool no_substitute); static inline handlerton *ha_checktype(THD *thd, enum legacy_db_type type, bool no_substitute = 0) { return ha_checktype(thd, ha_resolve_by_legacy_type(thd, type), no_substitute); } static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type) { return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type; } static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type) { return (db_type == NULL ? "UNKNOWN" : db_type == view_pseudo_hton ? "VIEW" : hton_name(db_type)->str); } static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag) { return db_type && (db_type->flags & flag); } static inline bool ha_storage_engine_is_enabled(const handlerton *db_type) { return db_type && db_type->create; } /* basic stuff */ int ha_init_errors(void); int ha_init(void); int ha_end(void); int ha_initialize_handlerton(void *plugin); int ha_finalize_handlerton(void *plugin); TYPELIB *ha_known_exts(void); int ha_panic(enum ha_panic_function flag); void ha_close_connection(THD* thd); void ha_kill_query(THD* thd, enum thd_kill_levels level); void ha_signal_ddl_recovery_done(); bool ha_flush_logs(); void ha_drop_database(const char* path); void ha_checkpoint_state(bool disable); void ha_commit_checkpoint_request(void *cookie, void (*pre_hook)(void *)); int ha_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, LEX_CUSTRING *frm, bool skip_frm_file); int ha_delete_table(THD *thd, handlerton *db_type, const char *path, const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); int ha_delete_table_force(THD *thd, const char *path, const LEX_CSTRING *db, const LEX_CSTRING *alias); void ha_prepare_for_backup(); void ha_end_backup(); void ha_pre_shutdown(); void ha_disable_internal_writes(bool disable); /* statistics and info */ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat); /* discovery */ #ifdef MYSQL_SERVER class Discovered_table_list: public handlerton::discovered_list { THD *thd; const char *wild, *wend; bool with_temps; // whether to include temp tables in the result public: Dynamic_array<LEX_CSTRING*> *tables; Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg, const LEX_CSTRING *wild_arg); Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg) : thd(thd_arg), wild(NULL), with_temps(true), tables(tables_arg) {} ~Discovered_table_list() = default; bool add_table(const char *tname, size_t tlen) override; bool add_file(const char *fname) override; void sort(); void remove_duplicates(); // assumes that the list is sorted #ifndef DBUG_OFF /* Used to find unstable mtr tests querying INFORMATION_SCHEMA.TABLES without ORDER BY. */ void sort_desc(); #endif /* DBUG_OFF */ }; int ha_discover_table(THD *thd, TABLE_SHARE *share); int ha_discover_table_names(THD *thd, const LEX_CSTRING *db, MY_DIR *dirp, Discovered_table_list *result, bool reusable); bool ha_table_exists(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, LEX_CUSTRING *table_version= 0, LEX_CSTRING *partition_engine_name= 0, handlerton **hton= 0, bool *is_sequence= 0); bool ha_check_if_updates_are_ignored(THD *thd, handlerton *hton, const char *op); #endif /* MYSQL_SERVER */ /* key cache */ extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache, void *); int ha_resize_key_cache(KEY_CACHE *key_cache); int ha_change_key_cache_param(KEY_CACHE *key_cache); int ha_repartition_key_cache(KEY_CACHE *key_cache); int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); /* transactions: interface to handlerton functions */ int ha_start_consistent_snapshot(THD *thd); int ha_commit_or_rollback_by_xid(XID *xid, bool commit); int ha_commit_one_phase(THD *thd, bool all); int ha_commit_trans(THD *thd, bool all); int ha_rollback_trans(THD *thd, bool all); int ha_prepare(THD *thd); int ha_recover(HASH *commit_list, MEM_ROOT *mem_root= NULL); uint ha_recover_complete(HASH *commit_list, Binlog_offset *coord= NULL); /* transactions: these functions never call handlerton functions directly */ int ha_enable_transaction(THD *thd, bool on); /* savepoints */ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv); bool ha_rollback_to_savepoint_can_release_mdl(THD *thd); int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); #ifdef WITH_WSREP int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); #endif /* these are called by storage engines */ void trans_register_ha(THD *thd, bool all, handlerton *ht, ulonglong trxid); /* Storage engine has to assume the transaction will end up with 2pc if - there is more than one 2pc-capable storage engine available - in the current transaction 2pc was not disabled yet */ #define trans_need_2pc(thd, all) ((total_ha_2pc > 1) && \ !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc)) void commit_checkpoint_notify_ha(void *cookie); inline const LEX_CSTRING *table_case_name(HA_CREATE_INFO *info, const LEX_CSTRING *name) { return ((lower_case_table_names == 2 && info->alias.str) ? &info->alias : name); } /** @def MYSQL_TABLE_IO_WAIT Instrumentation helper for table io_waits. Note that this helper is intended to be used from within the handler class only, as it uses members from @c handler Performance schema events are instrumented as follows: - in non batch mode, one event is generated per call - in batch mode, the number of rows affected is saved in @c m_psi_numrows, so that @c end_psi_batch_mode() generates a single event for the batch. @param OP the table operation to be performed @param INDEX the table index used if any, or MAX_KEY. @param PAYLOAD instrumented code to execute @sa handler::end_psi_batch_mode. */ #ifdef HAVE_PSI_TABLE_INTERFACE #define MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD) \ { \ if (m_psi != NULL) \ { \ switch (m_psi_batch_mode) \ { \ case PSI_BATCH_MODE_NONE: \ { \ PSI_table_locker *sub_locker= NULL; \ PSI_table_locker_state reentrant_safe_state; \ sub_locker= PSI_TABLE_CALL(start_table_io_wait) \ (& reentrant_safe_state, m_psi, OP, INDEX, \ __FILE__, __LINE__); \ PAYLOAD \ if (sub_locker != NULL) \ PSI_TABLE_CALL(end_table_io_wait) \ (sub_locker, 1); \ break; \ } \ case PSI_BATCH_MODE_STARTING: \ { \ m_psi_locker= PSI_TABLE_CALL(start_table_io_wait) \ (& m_psi_locker_state, m_psi, OP, INDEX, \ __FILE__, __LINE__); \ PAYLOAD \ if (!RESULT) \ m_psi_numrows++; \ m_psi_batch_mode= PSI_BATCH_MODE_STARTED; \ break; \ } \ case PSI_BATCH_MODE_STARTED: \ default: \ { \ DBUG_ASSERT(m_psi_batch_mode \ == PSI_BATCH_MODE_STARTED); \ PAYLOAD \ if (!RESULT) \ m_psi_numrows++; \ break; \ } \ } \ } \ else \ { \ PAYLOAD \ } \ } #else #define MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD) \ PAYLOAD #endif #define TABLE_IO_WAIT(TRACKER, OP, INDEX, RESULT, PAYLOAD) \ { \ Exec_time_tracker *this_tracker; \ if (unlikely((this_tracker= tracker))) \ tracker->start_tracking(table->in_use); \ \ MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD); \ \ if (unlikely(this_tracker)) \ tracker->stop_tracking(table->in_use); \ } void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag); void print_keydup_error(TABLE *table, KEY *key, myf errflag); int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table); uint ha_count_rw_all(THD *thd, Ha_trx_info **ptr_ha_info); bool non_existing_table_error(int error); uint ha_count_rw_2pc(THD *thd, bool all); uint ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list, bool all, bool *no_rollback); inline void Cost_estimate::reset(handler *file) { reset(); avg_io_cost= file->DISK_READ_COST * file->DISK_READ_RATIO; } int get_select_field_pos(Alter_info *alter_info, int select_field_count, bool versioned); #ifndef DBUG_OFF String dbug_format_row(TABLE *table, const uchar *rec, bool print_names= true); #endif /* DBUG_OFF */ #endif /* HANDLER_INCLUDED */ mysqld_suffix.h 0000644 00000002261 15156036140 0007614 0 ustar 00 #ifndef MYSQLD_SUFFIX_INCLUDED #define MYSQLD_SUFFIX_INCLUDED /* Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file Set MYSQL_SERVER_SUFFIX_STR. The following code is quite ugly as there is no portable way to easily set a string to the value of a macro */ #ifdef MYSQL_SERVER_SUFFIX #define MYSQL_SERVER_SUFFIX_STR STRINGIFY_ARG(MYSQL_SERVER_SUFFIX) #else #define MYSQL_SERVER_SUFFIX_STR MYSQL_SERVER_SUFFIX_DEF #endif #endif /* MYSQLD_SUFFIX_INCLUDED */ item_jsonfunc.h 0000644 00000070275 15156036140 0007574 0 ustar 00 #ifndef ITEM_JSONFUNC_INCLUDED #define ITEM_JSONFUNC_INCLUDED /* Copyright (c) 2016, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file defines all JSON functions */ #include <json_lib.h> #include "item_cmpfunc.h" // Item_bool_func #include "item_strfunc.h" // Item_str_func #include "item_sum.h" #include "sql_type_json.h" #include "json_schema.h" class json_path_with_flags { public: json_path_t p; bool constant; bool parsed; json_path_step_t *cur_step; void set_constant_flag(bool s_constant) { constant= s_constant; parsed= FALSE; } }; void report_path_error_ex(const char *ps, json_path_t *p, const char *fname, int n_param, Sql_condition::enum_warning_level lv); void report_json_error_ex(const char *js, json_engine_t *je, const char *fname, int n_param, Sql_condition::enum_warning_level lv); class Json_engine_scan: public json_engine_t { public: Json_engine_scan(CHARSET_INFO *i_cs, const uchar *str, const uchar *end) { json_scan_start(this, i_cs, str, end); } Json_engine_scan(const String &str) :Json_engine_scan(str.charset(), (const uchar *) str.ptr(), (const uchar *) str.end()) { } bool check_and_get_value_scalar(String *res, int *error); bool check_and_get_value_complex(String *res, int *error, json_value_types cur_value_type= JSON_VALUE_UNINITIALIZED); }; class Json_path_extractor: public json_path_with_flags { protected: String tmp_js, tmp_path; virtual ~Json_path_extractor() { } virtual bool check_and_get_value(Json_engine_scan *je, String *to, int *error)=0; bool extract(String *to, Item *js, Item *jp, CHARSET_INFO *cs); }; class Item_func_json_valid: public Item_bool_func { protected: String tmp_value; public: Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {} bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_valid") }; return name; } bool fix_length_and_dec(THD *thd) override { if (Item_bool_func::fix_length_and_dec(thd)) return TRUE; set_maybe_null(); return FALSE; } bool set_format_by_check_constraint(Send_field_extended_metadata *to) const override { static const Lex_cstring fmt(STRING_WITH_LEN("json")); return to->set_format_name(fmt); } enum Functype functype() const override { return JSON_VALID_FUNC; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_valid>(thd, this); } }; class Item_func_json_equals: public Item_bool_func { public: Item_func_json_equals(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_equals") }; return name; } bool fix_length_and_dec(THD *thd) override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_equals>(thd, this); } bool val_bool() override; }; class Item_func_json_exists: public Item_bool_func { protected: json_path_with_flags path; String tmp_js, tmp_path; public: Item_func_json_exists(THD *thd, Item *js, Item *i_path): Item_bool_func(thd, js, i_path) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_exists") }; return name; } bool fix_length_and_dec(THD *thd) override; bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_exists>(thd, this); } }; class Item_json_func: public Item_str_func { public: Item_json_func(THD *thd) :Item_str_func(thd) { } Item_json_func(THD *thd, Item *a) :Item_str_func(thd, a) { } Item_json_func(THD *thd, Item *a, Item *b) :Item_str_func(thd, a, b) { } Item_json_func(THD *thd, List<Item> &list) :Item_str_func(thd, list) { } const Type_handler *type_handler() const override { return Type_handler_json_common::json_type_handler(max_length); } }; class Item_func_json_value: public Item_str_func, public Json_path_extractor { public: Item_func_json_value(THD *thd, Item *js, Item *i_path): Item_str_func(thd, js, i_path) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_value") }; return name; } bool fix_length_and_dec(THD *thd) override ; String *val_str(String *to) override { null_value= Json_path_extractor::extract(to, args[0], args[1], collation.collation); return null_value ? NULL : to; } bool check_and_get_value(Json_engine_scan *je, String *res, int *error) override { return je->check_and_get_value_scalar(res, error); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_value>(thd, this); } }; class Item_func_json_query: public Item_json_func, public Json_path_extractor { public: Item_func_json_query(THD *thd, Item *js, Item *i_path): Item_json_func(thd, js, i_path) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_query") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *to) override { null_value= Json_path_extractor::extract(to, args[0], args[1], collation.collation); return null_value ? NULL : to; } bool check_and_get_value(Json_engine_scan *je, String *res, int *error) override { return je->check_and_get_value_complex(res, error, JSON_VALUE_UNINITIALIZED); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_query>(thd, this); } }; class Item_func_json_quote: public Item_str_func { protected: String tmp_s; public: Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_quote") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_quote>(thd, this); } }; class Item_func_json_unquote: public Item_str_func { protected: String tmp_s; String *read_json(json_engine_t *je); public: Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_unquote") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_unquote>(thd, this); } }; class Item_json_str_multipath: public Item_json_func { protected: json_path_with_flags *paths; String *tmp_paths; private: /** Number of paths returned by calling virtual method get_n_paths() and remembered inside fix_fields(). It is used by the virtual destructor ~Item_json_str_multipath() to iterate along allocated memory chunks stored in the array tmp_paths and free every of them. The virtual method get_n_paths() can't be used for this goal from within virtual destructor. We could get rid of the virtual method get_n_paths() and store the number of paths directly in the constructor of classes derived from the class Item_json_str_multipath but presence of the method get_n_paths() allows to check invariant that the number of arguments not changed between sequential runs of the same prepared statement that seems to be useful. */ uint n_paths; public: Item_json_str_multipath(THD *thd, List<Item> &list): Item_json_func(thd, list), paths(NULL), tmp_paths(0), n_paths(0) {} virtual ~Item_json_str_multipath(); bool fix_fields(THD *thd, Item **ref) override; virtual uint get_n_paths() const = 0; }; class Item_func_json_extract: public Item_json_str_multipath { protected: String tmp_js; public: String *read_json(String *str, json_value_types *type, char **out_val, int *value_len); Item_func_json_extract(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_extract") }; return name; } enum Functype functype() const override { return JSON_EXTRACT_FUNC; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; longlong val_int() override; double val_real() override; my_decimal *val_decimal(my_decimal *) override; uint get_n_paths() const override { return arg_count - 1; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_extract>(thd, this); } }; class Item_func_json_contains: public Item_bool_func { protected: String tmp_js; json_path_with_flags path; String tmp_path; bool a2_constant, a2_parsed; String tmp_val, *val; public: Item_func_json_contains(THD *thd, List<Item> &list): Item_bool_func(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_contains") }; return name; } bool fix_length_and_dec(THD *thd) override; bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_contains>(thd, this); } }; class Item_func_json_contains_path: public Item_bool_func { protected: String tmp_js; json_path_with_flags *paths; String *tmp_paths; bool mode_one; bool ooa_constant, ooa_parsed; bool *p_found; public: Item_func_json_contains_path(THD *thd, List<Item> &list): Item_bool_func(thd, list), tmp_paths(0) {} virtual ~Item_func_json_contains_path(); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_contains_path") }; return name; } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_contains_path>(thd, this); } }; class Item_func_json_array: public Item_json_func { protected: String tmp_val; ulong result_limit; public: Item_func_json_array(THD *thd): Item_json_func(thd) {} Item_func_json_array(THD *thd, List<Item> &list): Item_json_func(thd, list) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_array") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_array>(thd, this); } }; class Item_func_json_array_append: public Item_json_str_multipath { protected: String tmp_js; String tmp_val; public: Item_func_json_array_append(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; uint get_n_paths() const override { return arg_count/2; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_array_append") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_array_append>(thd, this); } }; class Item_func_json_array_insert: public Item_func_json_array_append { public: Item_func_json_array_insert(THD *thd, List<Item> &list): Item_func_json_array_append(thd, list) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_array_insert") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_array_insert>(thd, this); } }; class Item_func_json_object: public Item_func_json_array { public: Item_func_json_object(THD *thd): Item_func_json_array(thd) {} Item_func_json_object(THD *thd, List<Item> &list): Item_func_json_array(thd, list) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_object") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_object>(thd, this); } }; class Item_func_json_merge: public Item_func_json_array { protected: String tmp_js1, tmp_js2; public: Item_func_json_merge(THD *thd, List<Item> &list): Item_func_json_array(thd, list) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_merge_preserve") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_merge>(thd, this); } }; class Item_func_json_merge_patch: public Item_func_json_merge { public: Item_func_json_merge_patch(THD *thd, List<Item> &list): Item_func_json_merge(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_merge_patch") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_merge_patch>(thd, this); } }; class Item_func_json_normalize: public Item_json_func { public: Item_func_json_normalize(THD *thd, Item *a): Item_json_func(thd, a) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_normalize") }; return name; } bool fix_length_and_dec(THD *thd) override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_normalize>(thd, this); } }; class Item_func_json_object_to_array: public Item_json_func { protected: String tmp; public: Item_func_json_object_to_array(THD *thd, Item *a): Item_json_func(thd, a) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_object_to_array") }; return name; } bool fix_length_and_dec(THD *thd) override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_object_to_array>(thd, this); } }; class Item_func_json_length: public Item_long_func { bool check_arguments() const override { const LEX_CSTRING name= func_name_cstring(); if (arg_count == 0 || arg_count > 2) { my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); return true; } return args[0]->check_type_can_return_text(name) || (arg_count > 1 && args[1]->check_type_general_purpose_string(name)); } protected: json_path_with_flags path; String tmp_js; String tmp_path; public: Item_func_json_length(THD *thd, List<Item> &list): Item_long_func(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_length") }; return name; } bool fix_length_and_dec(THD *thd) override; longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_length>(thd, this); } }; class Item_func_json_depth: public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_text(func_name_cstring()); } protected: String tmp_js; public: Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_depth") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; return FALSE; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_depth>(thd, this); } }; class Item_func_json_type: public Item_str_func { protected: String tmp_js; public: Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_type") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_type>(thd, this); } }; class Item_func_json_insert: public Item_json_str_multipath { protected: String tmp_js; String tmp_val; bool mode_insert, mode_replace; public: Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list): Item_json_str_multipath(thd, list), mode_insert(i_mode), mode_replace(r_mode) {} bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; uint get_n_paths() const override { return arg_count/2; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING json_set= {STRING_WITH_LEN("json_set") }; static LEX_CSTRING json_insert= {STRING_WITH_LEN("json_insert") }; static LEX_CSTRING json_replace= {STRING_WITH_LEN("json_replace") }; return (mode_insert ? (mode_replace ? json_set : json_insert) : json_replace); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_insert>(thd, this); } }; class Item_func_json_remove: public Item_json_str_multipath { protected: String tmp_js; public: Item_func_json_remove(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; uint get_n_paths() const override { return arg_count - 1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_remove") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_remove>(thd, this); } }; class Item_func_json_keys: public Item_str_func { protected: json_path_with_flags path; String tmp_js, tmp_path; public: Item_func_json_keys(THD *thd, List<Item> &list): Item_str_func(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_keys") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_keys>(thd, this); } }; class Item_func_json_search: public Item_json_str_multipath { protected: String tmp_js, tmp_path, esc_value; bool mode_one; bool ooa_constant, ooa_parsed; int escape; int n_path_found; json_path_t sav_path; int compare_json_value_wild(json_engine_t *je, const String *cmp_str); public: Item_func_json_search(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_search") }; return name; } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; uint get_n_paths() const override { return arg_count > 4 ? arg_count - 4 : 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_search>(thd, this); } }; class Item_func_json_format: public Item_json_func { public: enum formats { NONE, COMPACT, LOOSE, DETAILED }; protected: formats fmt; String tmp_js; public: Item_func_json_format(THD *thd, Item *js, formats format): Item_json_func(thd, js), fmt(format) {} Item_func_json_format(THD *thd, List<Item> &list): Item_json_func(thd, list), fmt(DETAILED) {} LEX_CSTRING func_name_cstring() const override; bool fix_length_and_dec(THD *thd) override; String *val_str(String *str) override; String *val_json(String *str) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_format>(thd, this); } }; class Item_func_json_arrayagg : public Item_func_group_concat { protected: /* Overrides Item_func_group_concat::skip_nulls() NULL-s should be added to the result as JSON null value. */ bool skip_nulls() const override { return false; } String *get_str_from_item(Item *i, String *tmp) override; String *get_str_from_field(Item *i, Field *f, String *tmp, const uchar *key, size_t offset) override; void cut_max_length(String *result, uint old_length, uint max_length) const override; public: String m_tmp_json; /* Used in get_str_from_*.. */ Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List<Item> *is_select, const SQL_I_List<ORDER> &is_order, String *is_separator, bool limit_clause, Item *row_limit, Item *offset_limit): Item_func_group_concat(thd, context_arg, is_distinct, is_select, is_order, is_separator, limit_clause, row_limit, offset_limit) { } Item_func_json_arrayagg(THD *thd, Item_func_json_arrayagg *item) : Item_func_group_concat(thd, item) {} const Type_handler *type_handler() const override { return Type_handler_json_common::json_type_handler_sum(this); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_arrayagg(") }; return name; } bool fix_fields(THD *thd, Item **ref) override; enum Sumfunctype sum_func() const override { return JSON_ARRAYAGG_FUNC; } String* val_str(String *str) override; Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_arrayagg>(thd, this); } }; class Item_func_json_objectagg : public Item_sum { String result; public: Item_func_json_objectagg(THD *thd, Item *key, Item *value) : Item_sum(thd, key, value) { quick_group= FALSE; result.append('{'); } Item_func_json_objectagg(THD *thd, Item_func_json_objectagg *item); void cleanup() override; enum Sumfunctype sum_func () const override { return JSON_OBJECTAGG_FUNC;} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_objectagg") }; return name; } const Type_handler *type_handler() const override { return Type_handler_json_common::json_type_handler_sum(this); } void clear() override; bool add() override; void reset_field() override { DBUG_ASSERT(0); } // not used void update_field() override { DBUG_ASSERT(0); } // not used bool fix_fields(THD *,Item **) override; double val_real() override { return 0.0; } longlong val_int() override { return 0; } my_decimal *val_decimal(my_decimal *decimal_value) override { my_decimal_set_zero(decimal_value); return decimal_value; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_string(thd, ltime, fuzzydate); } String* val_str(String* str) override; Item *copy_or_same(THD* thd) override; void no_rows_in_result() override {} protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_objectagg>(thd, this); } }; extern bool is_json_type(const Item *item); class Item_func_json_overlaps: public Item_bool_func { String tmp_js; bool a2_constant, a2_parsed; String tmp_val, *val; public: Item_func_json_overlaps(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_overlaps") }; return name; } bool fix_length_and_dec(THD *thd) override; bool val_bool() override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_overlaps>(thd, this); } }; class Item_func_json_schema_valid: public Item_bool_func { String tmp_js; bool schema_parsed; String tmp_val, *val; List<Json_schema_keyword> keyword_list; List<Json_schema_keyword> all_keywords; public: Item_func_json_schema_valid(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b) { val= NULL; schema_parsed= false; set_maybe_null(); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_schema_valid") }; return name; } bool fix_length_and_dec(THD *thd) override; bool val_bool() override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_schema_valid>(thd, this); } void cleanup() override; }; class Item_func_json_key_value: public Item_json_func, public Json_path_extractor { String tmp_str; public: Item_func_json_key_value(THD *thd, Item *js, Item *i_path): Item_json_func(thd, js, i_path) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_key_value") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str(String *to) override; bool check_and_get_value(Json_engine_scan *je, String *res, int *error) override { return je->check_and_get_value_complex(res, error, JSON_VALUE_OBJECT); } bool get_key_value(json_engine_t *je, String *str); Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_key_value>(thd, this); } }; class Item_func_json_array_intersect: public Item_str_func { protected: String tmp_js1, tmp_js2, temp_str; bool item_hash_inited, seen_hash_inited, root_inited; HASH items, seen; MEM_ROOT hash_root; bool parse_for_each_row; public: Item_func_json_array_intersect(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) { item_hash_inited= seen_hash_inited= root_inited= parse_for_each_row= false; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_array_intersect") }; return name; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_array_intersect>(thd, this); } void cleanup() override { Item_str_func::cleanup(); if (item_hash_inited) my_hash_free(&items); if (seen_hash_inited) my_hash_free(&seen); if (root_inited) free_root(&hash_root, MYF(0)); } bool prepare_json_and_create_hash(json_engine_t *je1, String *js); bool get_intersect_between_arrays(String *str, json_engine_t *value, HASH *items, HASH *seen); }; class Item_func_json_object_filter_keys: public Item_str_func { protected: String tmp_js1, tmp_js2; bool hash_inited, root_inited; HASH items; MEM_ROOT hash_root; public: Item_func_json_object_filter_keys(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) { hash_inited= root_inited= false; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_object_filter_keys") }; return name; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_json_object_filter_keys>(thd, this); } void cleanup() override { Item_str_func::cleanup(); if (hash_inited) my_hash_free(&items); if (root_inited) free_root(&hash_root, MYF(0)); } }; #endif /* ITEM_JSONFUNC_INCLUDED */ sql_type_json.h 0000644 00000014013 15156036140 0007606 0 ustar 00 #ifndef SQL_TYPE_JSON_INCLUDED #define SQL_TYPE_JSON_INCLUDED /* Copyright (c) 2019, 2021 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mariadb.h" #include "sql_type.h" class Type_handler_json_common { public: static Virtual_column_info *make_json_valid_expr(THD *thd, const LEX_CSTRING *field_name); static bool make_json_valid_expr_if_needed(THD *thd, Column_definition *c); static bool set_format_name(Send_field_extended_metadata *to) { static const Lex_cstring fmt(STRING_WITH_LEN("json")); return to->set_format_name(fmt); } static const Type_handler *json_type_handler(uint max_octet_length); static const Type_handler *json_blob_type_handler_by_length_bytes(uint len); static const Type_handler *json_type_handler_sum(const Item_sum *sum); static const Type_handler *json_type_handler_from_generic(const Type_handler *th); static bool has_json_valid_constraint(const Field *field); static const Type_collection *type_collection(); static bool is_json_type_handler(const Type_handler *handler) { return handler->type_collection() == type_collection(); } }; template <class BASE, const Named_type_handler<BASE> &thbase> class Type_handler_general_purpose_string_to_json: public BASE, public Type_handler_json_common { public: const Type_handler *type_handler_base() const override { return &thbase; } const Type_collection *type_collection() const override { return Type_handler_json_common::type_collection(); } bool Column_definition_validate_check_constraint(THD *thd, Column_definition *c) const override { return make_json_valid_expr_if_needed(thd, c) || BASE::Column_definition_validate_check_constraint(thd, c); } bool Column_definition_data_type_info_image(Binary_string *to, const Column_definition &def) const override { /* Override the inherited method to avoid JSON type handlers writing any extended metadata to FRM. JSON type handlers are currently detected only by CHECK(JSON_VALID()) constraint. This may change in the future to do write extended metadata to FRM, for more reliable detection. */ return false; } bool Item_append_extended_type_info(Send_field_extended_metadata *to, const Item *item) const override { return set_format_name(to); // Send "format=json" in the protocol } bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *hybrid, Type_all_attributes *attr, Item **items, uint nitems) const override { if (BASE::Item_hybrid_func_fix_attributes(thd, name, hybrid, attr, items, nitems)) return true; /* The above call can change the type handler on "hybrid", e.g. choose a proper BLOB type handler according to the calculated max_length. Convert general purpose string type handler to its JSON counterpart. This makes hybrid functions preserve JSON data types, e.g.: COALESCE(json_expr1, json_expr2) -> JSON */ hybrid->set_handler(json_type_handler_from_generic(hybrid->type_handler())); return false; } }; class Type_handler_string_json: public Type_handler_general_purpose_string_to_json<Type_handler_string, type_handler_string> { }; class Type_handler_varchar_json: public Type_handler_general_purpose_string_to_json<Type_handler_varchar, type_handler_varchar> { }; class Type_handler_tiny_blob_json: public Type_handler_general_purpose_string_to_json<Type_handler_tiny_blob, type_handler_tiny_blob> { }; class Type_handler_blob_json: public Type_handler_general_purpose_string_to_json<Type_handler_blob, type_handler_blob> { }; class Type_handler_medium_blob_json: public Type_handler_general_purpose_string_to_json<Type_handler_medium_blob, type_handler_medium_blob> { }; class Type_handler_long_blob_json: public Type_handler_general_purpose_string_to_json<Type_handler_long_blob, type_handler_long_blob> { }; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_string_json> type_handler_string_json; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_varchar_json> type_handler_varchar_json; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_tiny_blob_json> type_handler_tiny_blob_json; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_blob_json> type_handler_blob_json; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_medium_blob_json> type_handler_medium_blob_json; extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_long_blob_json> type_handler_long_blob_json; #endif // SQL_TYPE_JSON_INCLUDED gstream.h 0000644 00000004605 15156036140 0006365 0 ustar 00 #ifndef GSTREAM_INCLUDED #define GSTREAM_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <my_sys.h> /* MY_ALLOW_ZERO_PTR */ #include "m_ctype.h" /* my_charset_latin1, my_charset_bin */ class Gis_read_stream { public: enum enum_tok_types { unknown, eostream, word, numeric, l_bra, r_bra, comma }; Gis_read_stream(CHARSET_INFO *charset, const char *buffer, int size) :m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL), m_charset(charset) {} Gis_read_stream(): m_cur(NullS), m_limit(NullS), m_err_msg(NullS) {} ~Gis_read_stream() { my_free(m_err_msg); } enum enum_tok_types get_next_toc_type(); bool lookup_next_word(LEX_STRING *res); bool get_next_word(LEX_STRING *); bool get_next_number(double *); bool check_next_symbol(char); inline void skip_space() { while ((m_cur < m_limit) && my_isspace(&my_charset_latin1, *m_cur)) m_cur++; } /* Skip next character, if match. Return 1 if no match */ inline bool skip_char(char skip) { skip_space(); if ((m_cur >= m_limit) || *m_cur != skip) return 1; /* Didn't find char */ m_cur++; return 0; } /* Returns the next notempty character. */ char next_symbol() { skip_space(); if (m_cur >= m_limit) return 0; /* EOL meet. */ return *m_cur; } void set_error_msg(const char *msg); // caller should free this pointer char *get_error_msg() { char *err_msg = m_err_msg; m_err_msg= NullS; return err_msg; } protected: const char *m_cur; const char *m_limit; char *m_err_msg; CHARSET_INFO *m_charset; }; #endif /* GSTREAM_INCLUDED */ scope.h 0000644 00000010451 15156036140 0006030 0 ustar 00 /* Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #include <type_traits> #include <utility> namespace detail { template <typename Callable> class scope_exit { public: template <typename F> explicit scope_exit(F &&f) : function_(std::forward<F>(f)) { } template <typename F> scope_exit(F &&f, bool engaged) : function_(std::forward<F>(f)), engaged_(engaged) { } scope_exit(scope_exit &&rhs) : function_(std::move(rhs.function_)), engaged_(rhs.engaged_) { rhs.release(); } scope_exit(const scope_exit &)= delete; scope_exit &operator=(scope_exit &&)= delete; scope_exit &operator=(const scope_exit &)= delete; void release() { engaged_= false; } void engage() { DBUG_ASSERT(!engaged_); engaged_= true; } ~scope_exit() { if (engaged_) function_(); } private: Callable function_; bool engaged_= true; }; } // end namespace detail template <typename Callable> inline ::detail::scope_exit<typename std::decay<Callable>::type> make_scope_exit(Callable &&f, bool engaged= true) { return ::detail::scope_exit<typename std::decay<Callable>::type>( std::forward<Callable>(f), engaged); } #define CONCAT_IMPL(x, y) x##y #define CONCAT(x, y) CONCAT_IMPL(x, y) #define ANONYMOUS_VARIABLE CONCAT(_anonymous_variable, __LINE__) #define SCOPE_EXIT auto ANONYMOUS_VARIABLE= make_scope_exit #define IF_CLASS(C) typename std::enable_if<std::is_class<C>::value>::type #define IF_NOT_CLASS(C) typename std::enable_if<!std::is_class<C>::value>::type namespace detail { template <typename T> class Scope_value { public: // Use SFINAE for passing structs by reference and plain types by value. // This ctor is defined only if T is a class or struct: template <typename U = T, typename = IF_CLASS(U)> Scope_value(T &variable, const T &scope_value) : variable_(&variable), saved_value_(variable) { variable= scope_value; } // This ctor is defined only if T is NOT a class or struct: template <typename U = T, typename = IF_NOT_CLASS(U)> Scope_value(T &variable, const T scope_value) : variable_(&variable), saved_value_(variable) { variable= scope_value; } Scope_value(Scope_value &&rhs) : variable_(rhs.variable_), saved_value_(rhs.saved_value_) { rhs.variable_= NULL; } Scope_value(const Scope_value &)= delete; Scope_value &operator=(const Scope_value &)= delete; Scope_value &operator=(Scope_value &&)= delete; ~Scope_value() { if (variable_) *variable_= saved_value_; } private: T *variable_; T saved_value_; }; } // namespace detail // Use like this: // auto _= make_scope_value(var, tmp_value); template <typename T, typename = IF_CLASS(T)> inline ::detail::Scope_value<T> make_scope_value(T &variable, const T &scope_value) { return ::detail::Scope_value<T>(variable, scope_value); } template <typename T, typename = IF_NOT_CLASS(T)> inline ::detail::Scope_value<T> make_scope_value(T &variable, T scope_value) { return ::detail::Scope_value<T>(variable, scope_value); } /* Note: perfect forwarding version can not pass const: template <typename T, typename U> inline detail::Scope_value<T> make_scope_value(T &variable, U &&scope_value) { return detail::Scope_value<T>(variable, std::forward<U>(scope_value)); } as `const U &&` fails with error `expects an rvalue for 2nd argument`. That happens because const U && is treated as rvalue only (this is the exact syntax for declaring rvalues). */ #define SCOPE_VALUE auto ANONYMOUS_VARIABLE= make_scope_value #define SCOPE_SET(VAR, MASK) auto ANONYMOUS_VARIABLE= make_scope_value(VAR, VAR | MASK) #define SCOPE_CLEAR(VAR, MASK) auto ANONYMOUS_VARIABLE= make_scope_value(VAR, VAR & ~MASK) sql_tvc.h 0000644 00000004562 15156036140 0006400 0 ustar 00 /* Copyright (c) 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_TVC_INCLUDED #define SQL_TVC_INCLUDED #include "sql_type.h" typedef List<Item> List_item; typedef bool (Item::*Item_processor) (void *arg); class select_result; class Explain_select; class Explain_query; class Item_func_in; class st_select_lex_unit; typedef class st_select_lex SELECT_LEX; class Type_holder; /** @class table_value_constr @brief Definition of a Table Value Construction(TVC) It contains a list of lists of values which this TVC is defined by and reference on SELECT where this TVC is defined. */ class table_value_constr : public Sql_alloc { public: List<List_item> lists_of_values; select_result *result; SELECT_LEX *select_lex; Type_holder *type_holders; enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE} have_query_plan; Explain_select *explain; ulonglong select_options; table_value_constr(List<List_item> tvc_values, SELECT_LEX *sl, ulonglong select_options_arg) : lists_of_values(tvc_values), result(0), select_lex(sl), type_holders(0), have_query_plan(QEP_NOT_PRESENT_YET), explain(0), select_options(select_options_arg) { }; ha_rows get_records() { return lists_of_values.elements; } bool prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tmp_result, st_select_lex_unit *unit_arg); bool to_be_wrapped_as_with_tail(); int save_explain_data_intern(THD *thd_arg, Explain_query *output); bool optimize(THD *thd_arg); bool exec(SELECT_LEX *sl); void print(THD *thd_arg, String *str, enum_query_type query_type); bool walk_values(Item_processor processor, bool walk_subquery, void *arg); }; st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl); #endif /* SQL_TVC_INCLUDED */ sql_string.h 0000644 00000113653 15156036140 0007114 0 ustar 00 #ifndef SQL_STRING_INCLUDED #define SQL_STRING_INCLUDED /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2008, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file is originally from the mysql distribution. Coded by monty */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "m_ctype.h" /* my_charset_bin */ #include <my_sys.h> /* alloc_root, my_free, my_realloc */ #include "m_string.h" /* TRASH */ #include "sql_list.h" class String; #ifdef MYSQL_SERVER extern PSI_memory_key key_memory_String_value; #define STRING_PSI_MEMORY_KEY key_memory_String_value #else #define STRING_PSI_MEMORY_KEY PSI_NOT_INSTRUMENTED #endif typedef struct st_io_cache IO_CACHE; typedef struct st_mem_root MEM_ROOT; #define ASSERT_LENGTH(A) DBUG_ASSERT(str_length + (uint32) (A) <= Alloced_length) #include "pack.h" class Binary_string; int sortcmp(const Binary_string *s, const Binary_string *t, CHARSET_INFO *cs); int stringcmp(const Binary_string *s, const Binary_string *t); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); inline uint32 copy_and_convert(char *to, size_t to_length, CHARSET_INFO *to_cs, const char *from, size_t from_length, CHARSET_INFO *from_cs, uint *errors) { return my_convert(to, (uint)to_length, to_cs, from, (uint)from_length, from_cs, errors); } class String_copy_status: protected MY_STRCOPY_STATUS { public: const char *source_end_pos() const { return m_source_end_pos; } const char *well_formed_error_pos() const { return m_well_formed_error_pos; } }; class Well_formed_prefix_status: public String_copy_status { public: Well_formed_prefix_status(CHARSET_INFO *cs, const char *str, const char *end, size_t nchars) { cs->well_formed_char_length(str, end, nchars, this); } }; class Well_formed_prefix: public Well_formed_prefix_status { const char *m_str; // The beginning of the string public: Well_formed_prefix(CHARSET_INFO *cs, const char *str, const char *end, size_t nchars) :Well_formed_prefix_status(cs, str, end, nchars), m_str(str) { } Well_formed_prefix(CHARSET_INFO *cs, const char *str, size_t length, size_t nchars) :Well_formed_prefix_status(cs, str, str + length, nchars), m_str(str) { } Well_formed_prefix(CHARSET_INFO *cs, const char *str, size_t length) :Well_formed_prefix_status(cs, str, str + length, length), m_str(str) { } Well_formed_prefix(CHARSET_INFO *cs, LEX_CSTRING str, size_t nchars) :Well_formed_prefix_status(cs, str.str, str.str + str.length, nchars), m_str(str.str) { } size_t length() const { return m_source_end_pos - m_str; } }; class String_copier: public String_copy_status, protected MY_STRCONV_STATUS { public: const char *cannot_convert_error_pos() const { return m_cannot_convert_error_pos; } const char *most_important_error_pos() const { return well_formed_error_pos() ? well_formed_error_pos() : cannot_convert_error_pos(); } /* Convert a string between character sets. "dstcs" and "srccs" cannot be &my_charset_bin. */ size_t convert_fix(CHARSET_INFO *dstcs, char *dst, size_t dst_length, CHARSET_INFO *srccs, const char *src, size_t src_length, size_t nchars) { return my_convert_fix(dstcs, dst, dst_length, srccs, src, src_length, nchars, this, this); } /* Copy a string. Fix bad bytes/characters to '?'. */ uint well_formed_copy(CHARSET_INFO *to_cs, char *to, size_t to_length, CHARSET_INFO *from_cs, const char *from, size_t from_length, size_t nchars); // Same as above, but without the "nchars" limit. uint well_formed_copy(CHARSET_INFO *to_cs, char *to, size_t to_length, CHARSET_INFO *from_cs, const char *from, size_t from_length) { return well_formed_copy(to_cs, to, to_length, from_cs, from, from_length, from_length /* No limit on "nchars"*/); } }; size_t my_copy_with_hex_escaping(CHARSET_INFO *cs, char *dst, size_t dstlen, const char *src, size_t srclen); uint convert_to_printable(char *to, size_t to_len, const char *from, size_t from_len, CHARSET_INFO *from_cs, size_t nbytes= 0); size_t convert_to_printable_required_length(uint len); class Charset { CHARSET_INFO *m_charset; public: Charset() :m_charset(&my_charset_bin) { } Charset(CHARSET_INFO *cs) :m_charset(cs) { } CHARSET_INFO *charset() const { return m_charset; } bool use_mb() const { return m_charset->use_mb(); } uint mbminlen() const { return m_charset->mbminlen; } uint mbmaxlen() const { return m_charset->mbmaxlen; } bool is_good_for_ft() const { // Binary and UCS2/UTF16/UTF32 are not supported return m_charset != &my_charset_bin && m_charset->mbminlen == 1; } size_t numchars(const char *str, const char *end) const { return m_charset->numchars(str, end); } size_t lengthsp(const char *str, size_t length) const { return m_charset->lengthsp(str, length); } size_t charpos(const char *str, const char *end, size_t pos) const { return m_charset->charpos(str, end, pos); } void set_charset(CHARSET_INFO *charset_arg) { m_charset= charset_arg; } void set_charset(const Charset &other) { m_charset= other.m_charset; } void swap(Charset &other) { swap_variables(CHARSET_INFO*, m_charset, other.m_charset); } bool same_encoding(const Charset &other) const { return my_charset_same(m_charset, other.m_charset); } /* Collation name without the character set name. For example, in case of "latin1_swedish_ci", this method returns "_swedish_ci". */ LEX_CSTRING collation_specific_name() const; bool encoding_allows_reinterpret_as(CHARSET_INFO *cs) const; bool eq_collation_specific_names(CHARSET_INFO *cs) const; bool can_have_collate_clause() const { return m_charset != &my_charset_bin; } /* The MariaDB version when the last collation change happened, e.g. due to a bug fix. See functions below. */ static ulong latest_mariadb_version_with_collation_change() { return 110002; } /* Check if the collation with the given ID changed its order since the given MariaDB version. */ static bool collation_changed_order(ulong mysql_version, uint cs_number) { if ((mysql_version < 50048 && (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */ cs_number == 41 || /* latin7_general_ci - bug #29461 */ cs_number == 42 || /* latin7_general_cs - bug #29461 */ cs_number == 20 || /* latin7_estonian_cs - bug #29461 */ cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */ cs_number == 22 || /* koi8u_general_ci - bug #29461 */ cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */ cs_number == 26)) || /* cp1250_general_ci - bug #29461 */ (mysql_version < 50124 && (cs_number == 33 || /* utf8mb3_general_ci - bug #27877 */ cs_number == 35))) /* ucs2_general_ci - bug #27877 */ return true; if (cs_number == 159 && /* ucs2_general_mysql500_ci - MDEV-30746 */ ((mysql_version >= 100400 && mysql_version < 100429) || (mysql_version >= 100500 && mysql_version < 100520) || (mysql_version >= 100600 && mysql_version < 100613) || (mysql_version >= 100700 && mysql_version < 100708) || (mysql_version >= 100800 && mysql_version < 100808) || (mysql_version >= 100900 && mysql_version < 100906) || (mysql_version >= 101000 && mysql_version < 101004) || (mysql_version >= 101100 && mysql_version < 101103) || (mysql_version >= 110000 && mysql_version < 110002))) return true; return false; } /** Check if a collation has changed ID since the given version. Return the new ID. @param mysql_version @param cs_number - collation ID @retval the new collation ID (or cs_number, if no change) */ static uint upgrade_collation_id(ulong mysql_version, uint cs_number) { if (mysql_version >= 50300 && mysql_version <= 50399) { switch (cs_number) { case 149: return MY_PAGE2_COLLATION_ID_UCS2; // ucs2_crotian_ci case 213: return MY_PAGE2_COLLATION_ID_UTF8; // utf8_crotian_ci } } if ((mysql_version >= 50500 && mysql_version <= 50599) || (mysql_version >= 100000 && mysql_version <= 100005)) { switch (cs_number) { case 149: return MY_PAGE2_COLLATION_ID_UCS2; // ucs2_crotian_ci case 213: return MY_PAGE2_COLLATION_ID_UTF8; // utf8_crotian_ci case 214: return MY_PAGE2_COLLATION_ID_UTF32; // utf32_croatian_ci case 215: return MY_PAGE2_COLLATION_ID_UTF16; // utf16_croatian_ci case 245: return MY_PAGE2_COLLATION_ID_UTF8MB4;// utf8mb4_croatian_ci } } return cs_number; } }; /** Storage for strings with both length and allocated length. Automatically grows on demand. */ class Binary_string: public Sql_alloc { protected: char *Ptr; uint32 str_length, Alloced_length, extra_alloc; bool alloced, thread_specific; void init_private_data() { Ptr= 0; Alloced_length= extra_alloc= str_length= 0; alloced= thread_specific= false; } inline void free_buffer() { if (alloced) { alloced=0; my_free(Ptr); } } public: Binary_string() { init_private_data(); } explicit Binary_string(size_t length_arg) { init_private_data(); (void) real_alloc(length_arg); } /* NOTE: If one intend to use the c_ptr() method, the following two contructors need the size of memory for STR to be at least LEN+1 (to make room for zero termination). */ Binary_string(const char *str, size_t len) { Ptr= (char*) str; str_length= (uint32) len; Alloced_length= 0; /* Memory cannot be written to */ extra_alloc= 0; alloced= thread_specific= 0; } Binary_string(char *str, size_t len) { Ptr= str; str_length= Alloced_length= (uint32) len; extra_alloc= 0; alloced= thread_specific= 0; } explicit Binary_string(const Binary_string &str) { Ptr= str.Ptr; str_length= str.str_length; Alloced_length= str.Alloced_length; extra_alloc= 0; alloced= thread_specific= 0; } ~Binary_string() { free(); } inline uint32 length() const { return str_length;} inline char& operator [] (size_t i) const { return Ptr[i]; } inline void length(size_t len) { str_length=(uint32)len ; } inline bool is_empty() const { return (str_length == 0); } inline const char *ptr() const { return Ptr; } inline const char *end() const { return Ptr + str_length; } bool has_8bit_bytes() const { for (const char *c= ptr(), *c_end= end(); c < c_end; c++) { if (!my_isascii(*c)) return true; } return false; } bool bin_eq(const Binary_string *other) const { return length() == other->length() && !memcmp(ptr(), other->ptr(), length()); } // Returns offset to substring or -1 int strstr(const Binary_string &search, uint32 offset=0) const; int strstr(const char *search, uint32 search_length, uint32 offset=0) const; // Returns offset to substring or -1 int strrstr(const Binary_string &search, uint32 offset=0) const; /* The following append operations do not extend the strings and in production mode do NOT check that alloced memory! q_*** methods writes values of parameters itself qs_*** methods writes string representation of value */ void q_append(const char c) { ASSERT_LENGTH(1); Ptr[str_length++] = c; } void q_append2b(const uint32 n) { ASSERT_LENGTH(2); int2store(Ptr + str_length, n); str_length += 2; } void q_append(const uint32 n) { ASSERT_LENGTH(4); int4store(Ptr + str_length, n); str_length += 4; } void q_append(double d) { ASSERT_LENGTH(8); float8store(Ptr + str_length, d); str_length += 8; } void q_append(double *d) { ASSERT_LENGTH(8); float8store(Ptr + str_length, *d); str_length += 8; } /* Append a wide character. The caller must have allocated at least cs->mbmaxlen bytes. */ int q_append_wc(my_wc_t wc, CHARSET_INFO *cs) { int mblen; if ((mblen= cs->cset->wc_mb(cs, wc, (uchar *) end(), (uchar *) end() + cs->mbmaxlen)) > 0) str_length+= (uint32) mblen; return mblen; } void q_append(const char *data, size_t data_len) { ASSERT_LENGTH(data_len); if (data_len) memcpy(Ptr + str_length, data, data_len); DBUG_ASSERT(str_length <= UINT_MAX32 - data_len); str_length += (uint)data_len; } void q_append(const LEX_CSTRING *ls) { DBUG_ASSERT(ls->length < UINT_MAX32 && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))); q_append(ls->str, (uint32) ls->length); } void write_at_position(uint32 position, uint32 value) { DBUG_ASSERT(str_length >= position + 4); int4store(Ptr + position,value); } void qs_append(const LEX_CSTRING *ls) { DBUG_ASSERT(ls->length < UINT_MAX32 && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))); qs_append(ls->str, (uint32)ls->length); } void qs_append(const char *str, size_t len); void qs_append_hex(const char *str, uint32 len); void qs_append_hex_uint32(uint32 num); void qs_append(double d); void qs_append(const double *d); inline void qs_append(const char c) { ASSERT_LENGTH(1); Ptr[str_length]= c; str_length++; } void qs_append(int i); void qs_append(uint i) { qs_append((ulonglong)i); } void qs_append(ulong i) { qs_append((ulonglong)i); } void qs_append(ulonglong i); void qs_append(longlong i, int radix) { ASSERT_LENGTH(22); char *buff= Ptr + str_length; char *end= ll2str(i, buff, radix, 0); str_length+= (uint32) (end-buff); } /* Mark variable thread specific it it's not allocated already */ inline void set_thread_specific() { if (!alloced) thread_specific= 1; } bool is_alloced() const { return alloced; } inline uint32 alloced_length() const { return Alloced_length;} inline uint32 extra_allocation() const { return extra_alloc;} inline void extra_allocation(size_t len) { extra_alloc= (uint32)len; } inline void mark_as_const() { Alloced_length= 0;} inline bool uses_buffer_owned_by(const Binary_string *s) const { return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->Alloced_length); } /* Swap two string objects. Efficient way to exchange data without memcpy. */ void swap(Binary_string &s) { swap_variables(char *, Ptr, s.Ptr); swap_variables(uint32, str_length, s.str_length); swap_variables(uint32, Alloced_length, s.Alloced_length); swap_variables(bool, alloced, s.alloced); } /** Points the internal buffer to the supplied one. The old buffer is freed. @param str Pointer to the new buffer. @param arg_length Length of the new buffer in characters, excluding any null character. @note The new buffer will not be null terminated. */ void set_alloced(char *str, size_t length, size_t alloced_length) { free_buffer(); Ptr= str; str_length= (uint32) length; DBUG_ASSERT(alloced_length < UINT_MAX32); Alloced_length= (uint32) alloced_length; } inline void set(char *str, size_t arg_length) { set_alloced(str, arg_length, arg_length); } inline void set(const char *str, size_t length) { free_buffer(); Ptr= (char*) str; str_length= (uint32) length; Alloced_length= 0; } void set(Binary_string &str, size_t offset, size_t length) { DBUG_ASSERT(&str != this); free_buffer(); Ptr= str.Ptr + offset; str_length= (uint32) length; Alloced_length= 0; if (str.Alloced_length) Alloced_length= (uint32) (str.Alloced_length - offset); } LEX_CSTRING to_lex_cstring() const { LEX_CSTRING tmp= {Ptr, str_length}; return tmp; } inline LEX_CSTRING *get_value(LEX_CSTRING *res) const { res->str= Ptr; res->length= str_length; return res; } /* Take over handling of buffer from some other object */ void reset(char *ptr_arg, size_t length_arg, size_t alloced_length_arg) { set_alloced(ptr_arg, length_arg, alloced_length_arg); alloced= ptr_arg != 0; } /* Forget about the buffer, let some other object handle it */ char *release() { char *old= Ptr; init_private_data(); return old; } /* This is used to set a new buffer for String. However if the String already has an allocated buffer, it will keep that one. It's not to be used to set the value or length of the string. */ inline void set_buffer_if_not_allocated(char *str, size_t arg_length) { if (!alloced) { /* Following should really set str_length= 0, but some code may depend on that the String length is same as buffer length. */ Ptr= str; str_length= Alloced_length= (uint32) arg_length; } /* One should set str_length before using it */ MEM_UNDEFINED(&str_length, sizeof(str_length)); } inline Binary_string& operator=(const Binary_string &s) { if (&s != this) { /* It is forbidden to do assignments like some_string = substring_of_that_string */ DBUG_ASSERT(!s.uses_buffer_owned_by(this)); set_alloced((char *) s.Ptr, s.str_length, s.Alloced_length); } return *this; } bool set_hex(ulonglong num); bool set_hex(const char *str, uint32 len); bool set_fcvt(double num, uint decimals); bool copy(); // Alloc string if not alloced bool copy(const Binary_string &s); // Allocate new string bool copy(const char *s, size_t arg_length); // Allocate new string bool copy_or_move(const char *s,size_t arg_length); /** Convert a string to a printable format. All non-convertable and control characters are replaced to 5-character sequences '\hhhh'. */ bool copy_printable_hhhh(CHARSET_INFO *to_cs, CHARSET_INFO *from_cs, const char *from, size_t from_length); bool append_ulonglong(ulonglong val); bool append_longlong(longlong val); bool append(const char *s, size_t size) { if (!size) return false; if (realloc_with_extra_if_needed(str_length + size)) return true; q_append(s, size); return false; } bool append(const LEX_CSTRING &s) { return append(s.str, s.length); } bool append(const Binary_string &s) { return append(s.ptr(), s.length()); } bool append(IO_CACHE* file, uint32 arg_length); inline bool append_char(char chr) { if (str_length < Alloced_length) { Ptr[str_length++]= chr; } else { if (unlikely(realloc_with_extra(str_length + 1))) return true; Ptr[str_length++]= chr; } return false; } bool append_hex(const char *src, uint32 srclen) { for (const char *src_end= src + srclen ; src != src_end ; src++) { if (unlikely(append_char(_dig_vec_lower[((uchar) *src) >> 4])) || unlikely(append_char(_dig_vec_lower[((uchar) *src) & 0x0F]))) return true; } return false; } bool append_hex_uint32(uint32 num) { if (reserve(8)) return true; qs_append_hex_uint32(num); return false; } bool append_with_step(const char *s, uint32 arg_length, uint32 step_alloc) { uint32 new_length= arg_length + str_length; if (new_length > Alloced_length && unlikely(realloc(new_length + step_alloc))) return true; q_append(s, arg_length); return false; } inline char *c_ptr() { if (unlikely(!Ptr)) return (char*) ""; /* Here we assume that any buffer used to initalize String has an end \0 or have at least an accessable character at end. This is to handle the case of String("Hello",5) and String("hello",5) efficiently. We have two options here. To test for !Alloced_length or !alloced. Using "Alloced_length" is slightly safer so that we do not read from potentially unintialized memory (normally not dangerous but may give warnings in valgrind), but "alloced" is safer as there are less change to get memory loss from code that is using String((char*), length) or String.set((char*), length) and does not free things properly (and there is several places in the code where this happens and it is hard to find out if any of these will call c_ptr(). */ if (unlikely(!alloced && !Ptr[str_length])) return Ptr; if (str_length < Alloced_length) { Ptr[str_length]=0; return Ptr; } (void) realloc(str_length); /* This will add end \0 */ return Ptr; } /* One should use c_ptr() instead for most cases. This will be deleted soon, kept for compatiblity. */ inline char *c_ptr_quick() { return c_ptr_safe(); } /* This is to be used only in the case when one cannot use c_ptr(). The cases are: - When one initializes String with an external buffer and length and buffer[length] could be uninitalized when c_ptr() is called. - When valgrind gives warnings about uninitialized memory with c_ptr(). */ inline char *c_ptr_safe() { if (Ptr && str_length < Alloced_length) Ptr[str_length]=0; else (void) realloc(str_length); return Ptr; } inline void free() { free_buffer(); /* We have to clear the values as some Strings, like in Field, are reused after free(). Because of this we cannot use MEM_UNDEFINED() here. */ Ptr= 0; str_length= 0; Alloced_length= extra_alloc= 0; } inline bool alloc(size_t arg_length) { /* Allocate if we need more space or if we don't have done any allocation yet (we don't want to have Ptr to be NULL for empty strings). Note that if arg_length == Alloced_length then we don't allocate. This ensures we don't do any extra allocations in protocol and String:int, but the string will not be automatically null terminated if c_ptr() is not called. */ if (arg_length <= Alloced_length && Alloced_length) return 0; return real_alloc(arg_length); } bool real_alloc(size_t arg_length); // Empties old string bool realloc_raw(size_t arg_length); bool realloc(size_t arg_length) { if (realloc_raw(arg_length+1)) return TRUE; Ptr[arg_length]= 0; // This make other funcs shorter return FALSE; } bool realloc_with_extra(size_t arg_length) { if (extra_alloc < 4096) extra_alloc= extra_alloc*2+128; if (realloc_raw(arg_length + extra_alloc)) return TRUE; Ptr[arg_length]=0; // This make other funcs shorter return FALSE; } bool realloc_with_extra_if_needed(size_t arg_length) { if (arg_length < Alloced_length) { Ptr[arg_length]=0; // behave as if realloc was called. return 0; } return realloc_with_extra(arg_length); } // Shrink the buffer, but only if it is allocated on the heap. void shrink(size_t arg_length); void move(Binary_string &s) { set_alloced(s.Ptr, s.str_length, s.Alloced_length); extra_alloc= s.extra_alloc; alloced= s.alloced; thread_specific= s.thread_specific; s.alloced= 0; } bool fill(size_t max_length,char fill); /* Replace substring with string If wrong parameter or not enough memory, do nothing */ bool replace(uint32 offset,uint32 arg_length, const char *to, uint32 length); bool replace(uint32 offset,uint32 arg_length, const Binary_string &to) { return replace(offset,arg_length,to.ptr(),to.length()); } int reserve(size_t space_needed) { DBUG_ASSERT((ulonglong) str_length + space_needed < UINT_MAX32); return realloc(str_length + space_needed); } int reserve(size_t space_needed, size_t grow_by); inline char *prep_append(uint32 arg_length, uint32 step_alloc) { uint32 new_length= arg_length + str_length; if (new_length > Alloced_length) { if (unlikely(realloc(new_length + step_alloc))) return 0; } uint32 old_length= str_length; str_length+= arg_length; return Ptr + old_length; // Area to use } void q_net_store_length(ulonglong length) { DBUG_ASSERT(Alloced_length >= (str_length + net_length_size(length))); char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length); str_length= uint32(pos - Ptr); } void q_net_store_data(const uchar *from, size_t length) { DBUG_ASSERT(length < UINT_MAX32); DBUG_ASSERT(Alloced_length >= (str_length + length + net_length_size(length))); q_net_store_length(length); q_append((const char *)from, (uint32) length); } }; class String: public Charset, public Binary_string { public: String() = default; String(size_t length_arg) :Binary_string(length_arg) { } /* NOTE: If one intend to use the c_ptr() method, the following two contructors need the size of memory for STR to be at least LEN+1 (to make room for zero termination). */ String(const char *str, size_t len, CHARSET_INFO *cs) :Charset(cs), Binary_string(str, len) { } String(char *str, size_t len, CHARSET_INFO *cs) :Charset(cs), Binary_string(str, len) { } String(const String &str) = default; String(String &&str) noexcept :Charset(std::move(str)), Binary_string(std::move(str)){} void set(String &str,size_t offset,size_t arg_length) { Binary_string::set(str, offset, arg_length); set_charset(str); } inline void set(char *str,size_t arg_length, CHARSET_INFO *cs) { Binary_string::set(str, arg_length); set_charset(cs); } inline void set(const char *str,size_t arg_length, CHARSET_INFO *cs) { Binary_string::set(str, arg_length); set_charset(cs); } bool set_ascii(const char *str, size_t arg_length); inline void set_buffer_if_not_allocated(char *str,size_t arg_length, CHARSET_INFO *cs) { Binary_string::set_buffer_if_not_allocated(str, arg_length); set_charset(cs); } bool set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs); bool set(int num, CHARSET_INFO *cs) { return set_int(num, false, cs); } bool set(uint num, CHARSET_INFO *cs) { return set_int(num, true, cs); } bool set(long num, CHARSET_INFO *cs) { return set_int(num, false, cs); } bool set(ulong num, CHARSET_INFO *cs) { return set_int(num, true, cs); } bool set(longlong num, CHARSET_INFO *cs) { return set_int(num, false, cs); } bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); } bool set_real(double num,uint decimals, CHARSET_INFO *cs); bool set_fcvt(double num, uint decimals) { set_charset(&my_charset_latin1); return Binary_string::set_fcvt(num, decimals); } bool set_hex(ulonglong num) { set_charset(&my_charset_latin1); return Binary_string::set_hex(num); } bool set_hex(const char *str, uint32 len) { set_charset(&my_charset_latin1); return Binary_string::set_hex(str, len); } /* Take over handling of buffer from some other object */ void reset(char *ptr_arg, size_t length_arg, size_t alloced_length_arg, CHARSET_INFO *cs) { Binary_string::reset(ptr_arg, length_arg, alloced_length_arg); set_charset(cs); } inline String& operator = (const String &s) { if (&s != this) { set_charset(s); Binary_string::operator=(s); } return *this; } bool copy() { return Binary_string::copy(); } bool copy(const String &s) { set_charset(s); return Binary_string::copy(s); } bool copy(const char *s, size_t arg_length, CHARSET_INFO *cs) { set_charset(cs); return Binary_string::copy(s, arg_length); } bool copy_or_move(const char *s, size_t arg_length, CHARSET_INFO *cs) { set_charset(cs); return Binary_string::copy_or_move(s, arg_length); } static bool needs_conversion(size_t arg_length, CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, uint32 *offset); static bool needs_conversion_on_storage(size_t arg_length, CHARSET_INFO *cs_from, CHARSET_INFO *cs_to); bool copy_aligned(const char *s, size_t arg_length, size_t offset, CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, size_t arg_length, CHARSET_INFO *cs); bool can_be_safely_converted_to(CHARSET_INFO *tocs) const { if (charset() == &my_charset_bin) return Well_formed_prefix(tocs, ptr(), length()).length() == length(); String try_val; uint try_conv_error= 0; try_val.copy(ptr(), length(), charset(), tocs, &try_conv_error); return try_conv_error == 0; } bool copy(const char*s, size_t arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto, uint *errors); bool copy(const String *str, CHARSET_INFO *tocs, uint *errors) { return copy(str->ptr(), str->length(), str->charset(), tocs, errors); } bool copy(CHARSET_INFO *tocs, CHARSET_INFO *fromcs, const char *src, size_t src_length, size_t nchars, String_copier *copier) { if (unlikely(alloc(tocs->mbmaxlen * src_length))) return true; str_length= copier->well_formed_copy(tocs, Ptr, alloced_length(), fromcs, src, (uint) src_length, (uint) nchars); set_charset(tocs); return false; } // Append without character set conversion bool append(const String &s) { return Binary_string::append(s); } inline bool append(char chr) { return append(&chr, 1); } bool append_hex(const char *src, uint32 srclen) { return Binary_string::append_hex(src, srclen); } bool append_hex(const uchar *src, uint32 srclen) { return Binary_string::append_hex((const char*)src, srclen); } bool append_introducer_and_hex(const String *str) { return append('_') || append(str->charset()->cs_name) || append(STRING_WITH_LEN(" 0x")) || append_hex(str->ptr(), (uint32) str->length()); } bool append(IO_CACHE* file, uint32 arg_length) { return Binary_string::append(file, arg_length); } inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) { return append_with_step(s, arg_length, step_alloc); } // Append with optional character set conversion from ASCII (e.g. to UCS2) bool append(const LEX_CSTRING *ls) { DBUG_ASSERT(ls->length < UINT_MAX32 && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))); return append(ls->str, (uint32) ls->length); } bool append(const LEX_CSTRING &ls) { return append(&ls); } bool append_name_value(const LEX_CSTRING &name, const LEX_CSTRING &value, uchar quot= '\0') { return append(name) || append('=') || (quot && append(quot)) || append(value) || (quot && append(quot)); } bool append(const char *s, size_t size); bool append_parenthesized(long nr, int radix= 10); // Append with optional character set conversion from cs to charset() bool append(const char *s, size_t arg_length, CHARSET_INFO *cs); bool append(const LEX_CSTRING &s, CHARSET_INFO *cs) { return append(s.str, s.length, cs); } // Append a wide character bool append_wc(my_wc_t wc) { if (reserve(mbmaxlen())) return true; int mblen= q_append_wc(wc, charset()); if (mblen > 0) return false; else if (mblen == MY_CS_ILUNI && wc != '?') return q_append_wc('?', charset()) <= 0; return true; } // Append a number with zero prefilling bool append_zerofill(uint num, uint width) { static const char zeros[15]= "00000000000000"; char intbuff[15]; uint length= (uint) (int10_to_str(num, intbuff, 10) - intbuff); if (length < width && append(zeros, width - length, &my_charset_latin1)) return true; return append(intbuff, length, &my_charset_latin1); } /* Append a bitmask in an uint32 with a translation into a C-style human readable representation, e.g.: 0x05 -> "(flag04|flag01)" @param flags - the flags to translate @param names - an array of flag names @param count - the number of available elements in "names" */ bool append_flag32_names(uint32 flags, LEX_CSTRING names[], size_t count) { bool added= false; if (flags && append('(')) return true; for (ulong i= 0; i <= 31; i++) { ulong bit= 31 - i; if (flags & (1 << bit)) { if (added && append('|')) return true; if (bit < count ? append(names[bit]) : append('?')) return true; added= true; } } if (flags && append(')')) return true; return false; } inline void chop() { if (str_length) { str_length--; str_length= well_formed_length(); } } void strip_sp(); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); friend class Field; uint32 numchars() const { return (uint32) Charset::numchars(ptr(), end()); } int charpos(longlong i, uint32 offset=0) { if (i <= 0) return (int) i; return (int) Charset::charpos(ptr() + offset, end(), (size_t) i); } size_t lengthsp() const { return Charset::lengthsp(Ptr, str_length); } void print(String *to) const; void print_with_conversion(String *to, CHARSET_INFO *cs) const; void print(String *to, CHARSET_INFO *cs) const { if (my_charset_same(charset(), cs)) print(to); else print_with_conversion(to, cs); } static my_wc_t escaped_wc_for_single_quote(my_wc_t ch) { switch (ch) { case '\\': return '\\'; case '\0': return '0'; case '\'': return '\''; case '\b': return 'b'; case '\t': return 't'; case '\n': return 'n'; case '\r': return 'r'; case '\032': return 'Z'; } return 0; } // Append for single quote using mb_wc/wc_mb Unicode conversion bool append_for_single_quote_using_mb_wc(const char *str, size_t length, CHARSET_INFO *cs); // Append for single quote with optional mb_wc/wc_mb conversion bool append_for_single_quote_opt_convert(const char *str, size_t length, CHARSET_INFO *cs) { return charset() == &my_charset_bin || cs == &my_charset_bin || my_charset_same(charset(), cs) ? append_for_single_quote(str, length) : append_for_single_quote_using_mb_wc(str, length, cs); } bool append_for_single_quote_opt_convert(const String &str) { return append_for_single_quote_opt_convert(str.ptr(), str.length(), str.charset()); } bool append_for_single_quote(const char *st, size_t len); bool append_for_single_quote(const String *s) { return append_for_single_quote(s->ptr(), s->length()); } void swap(String &s) { Charset::swap(s); Binary_string::swap(s); } uint well_formed_length() const { return (uint) Well_formed_prefix(charset(), ptr(), length()).length(); } bool is_ascii() const { if (length() == 0) return TRUE; if (charset()->mbminlen > 1) return FALSE; return !has_8bit_bytes(); } bool eq(const String *other, CHARSET_INFO *cs) const { return !sortcmp(this, other, cs); } private: bool append_semi_hex(const char *s, uint len, CHARSET_INFO *cs); }; // The following class is a backport from MySQL 5.6: /** String class wrapper with a preallocated buffer of size buff_sz This class allows to replace sequences of: char buff[12345]; String str(buff, sizeof(buff)); str.length(0); with a simple equivalent declaration: StringBuffer<12345> str; */ template<size_t buff_sz> class StringBuffer : public String { char buff[buff_sz]; public: StringBuffer() : String(buff, buff_sz, &my_charset_bin) { length(0); } explicit StringBuffer(CHARSET_INFO *cs) : String(buff, buff_sz, cs) { length(0); } void set_buffer_if_not_allocated(CHARSET_INFO *cs) { if (!is_alloced()) { Ptr= buff; Alloced_length= (uint32) buff_sz; } str_length= 0; /* Safety, not required */ /* One should set str_length before using it */ MEM_UNDEFINED(&str_length, sizeof(str_length)); set_charset(cs); } }; template<size_t buff_sz> class BinaryStringBuffer : public Binary_string { char buff[buff_sz]; public: BinaryStringBuffer() : Binary_string(buff, buff_sz) { length(0); } }; static inline bool check_if_only_end_space(CHARSET_INFO *cs, const char *str, const char *end) { return str + cs->scan(str, end, MY_SEQ_SPACES) == end; } int append_query_string(CHARSET_INFO *csinfo, String *to, const char *str, size_t len, bool no_backslash); #endif /* SQL_STRING_INCLUDED */ ddl_log.h 0000644 00000031007 15156036140 0006323 0 ustar 00 /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. Copyright (c) 2010, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* External interfaces to ddl log functions */ #ifndef DDL_LOG_INCLUDED #define DDL_LOG_INCLUDED enum ddl_log_entry_code { /* DDL_LOG_UNKOWN Here mainly to detect blocks that are all zero DDL_LOG_EXECUTE_CODE: This is a code that indicates that this is a log entry to be executed, from this entry a linked list of log entries can be found and executed. DDL_LOG_ENTRY_CODE: An entry to be executed in a linked list from an execute log entry. DDL_LOG_IGNORE_ENTRY_CODE: An entry that is to be ignored */ DDL_LOG_UNKNOWN= 0, DDL_LOG_EXECUTE_CODE= 1, DDL_LOG_ENTRY_CODE= 2, DDL_LOG_IGNORE_ENTRY_CODE= 3, DDL_LOG_ENTRY_CODE_LAST= 4 }; /* When adding things below, also add an entry to ddl_log_action_names and ddl_log_entry_phases in ddl_log.cc */ enum ddl_log_action_code { /* The type of action that a DDL_LOG_ENTRY_CODE entry is to perform. */ DDL_LOG_UNKNOWN_ACTION= 0, /* Delete a .frm file or a table in the partition engine */ DDL_LOG_DELETE_ACTION= 1, /* Rename a .frm fire a table in the partition engine */ DDL_LOG_RENAME_ACTION= 2, /* Rename an entity after removing the previous entry with the new name, that is replace this entry. */ DDL_LOG_REPLACE_ACTION= 3, /* Exchange two entities by renaming them a -> tmp, b -> a, tmp -> b */ DDL_LOG_EXCHANGE_ACTION= 4, /* log do_rename(): Rename of .frm file, table, stat_tables and triggers */ DDL_LOG_RENAME_TABLE_ACTION= 5, DDL_LOG_RENAME_VIEW_ACTION= 6, DDL_LOG_DROP_INIT_ACTION= 7, DDL_LOG_DROP_TABLE_ACTION= 8, DDL_LOG_DROP_VIEW_ACTION= 9, DDL_LOG_DROP_TRIGGER_ACTION= 10, DDL_LOG_DROP_DB_ACTION=11, DDL_LOG_CREATE_TABLE_ACTION=12, DDL_LOG_CREATE_VIEW_ACTION=13, DDL_LOG_DELETE_TMP_FILE_ACTION=14, DDL_LOG_CREATE_TRIGGER_ACTION=15, DDL_LOG_ALTER_TABLE_ACTION=16, DDL_LOG_STORE_QUERY_ACTION=17, DDL_LOG_LAST_ACTION /* End marker */ }; /* Number of phases for each ddl_log_action_code */ extern const uchar ddl_log_entry_phases[DDL_LOG_LAST_ACTION]; enum enum_ddl_log_exchange_phase { EXCH_PHASE_NAME_TO_TEMP= 0, EXCH_PHASE_FROM_TO_NAME= 1, EXCH_PHASE_TEMP_TO_FROM= 2, EXCH_PHASE_END }; enum enum_ddl_log_rename_table_phase { DDL_RENAME_PHASE_TRIGGER= 0, DDL_RENAME_PHASE_STAT, DDL_RENAME_PHASE_TABLE, DDL_RENAME_PHASE_END }; enum enum_ddl_log_drop_table_phase { DDL_DROP_PHASE_TABLE=0, DDL_DROP_PHASE_TRIGGER, DDL_DROP_PHASE_BINLOG, DDL_DROP_PHASE_RESET, /* Reset found list of dropped tables */ DDL_DROP_PHASE_END }; enum enum_ddl_log_drop_db_phase { DDL_DROP_DB_PHASE_INIT=0, DDL_DROP_DB_PHASE_LOG, DDL_DROP_DB_PHASE_END }; enum enum_ddl_log_create_table_phase { DDL_CREATE_TABLE_PHASE_INIT=0, DDL_CREATE_TABLE_PHASE_LOG, DDL_CREATE_TABLE_PHASE_END }; enum enum_ddl_log_create_view_phase { DDL_CREATE_VIEW_PHASE_NO_OLD_VIEW, DDL_CREATE_VIEW_PHASE_DELETE_VIEW_COPY, DDL_CREATE_VIEW_PHASE_OLD_VIEW_COPIED, DDL_CREATE_VIEW_PHASE_END }; enum enum_ddl_log_create_trigger_phase { DDL_CREATE_TRIGGER_PHASE_NO_OLD_TRIGGER, DDL_CREATE_TRIGGER_PHASE_DELETE_COPY, DDL_CREATE_TRIGGER_PHASE_OLD_COPIED, DDL_CREATE_TRIGGER_PHASE_END }; enum enum_ddl_log_alter_table_phase { DDL_ALTER_TABLE_PHASE_INIT, DDL_ALTER_TABLE_PHASE_RENAME_FAILED, DDL_ALTER_TABLE_PHASE_INPLACE_COPIED, DDL_ALTER_TABLE_PHASE_INPLACE, DDL_ALTER_TABLE_PHASE_PREPARE_INPLACE, DDL_ALTER_TABLE_PHASE_CREATED, DDL_ALTER_TABLE_PHASE_COPIED, DDL_ALTER_TABLE_PHASE_OLD_RENAMED, DDL_ALTER_TABLE_PHASE_UPDATE_TRIGGERS, DDL_ALTER_TABLE_PHASE_UPDATE_STATS, DDL_ALTER_TABLE_PHASE_UPDATE_BINARY_LOG, DDL_ALTER_TABLE_PHASE_END }; /* Flags stored in DDL_LOG_ENTRY.flags The flag values can be reused for different commands */ #define DDL_LOG_FLAG_ALTER_RENAME (1 << 0) #define DDL_LOG_FLAG_ALTER_ENGINE_CHANGED (1 << 1) #define DDL_LOG_FLAG_ONLY_FRM (1 << 2) #define DDL_LOG_FLAG_UPDATE_STAT (1 << 3) /* Set when using ALTER TABLE on a partitioned table and the table engine is not changed */ #define DDL_LOG_FLAG_ALTER_PARTITION (1 << 4) /* Setting ddl_log_entry.phase to this has the same effect as setting the phase to the maximum phase (..PHASE_END) for an entry. */ #define DDL_LOG_FINAL_PHASE ((uchar) 0xff) typedef struct st_ddl_log_entry { LEX_CSTRING name; LEX_CSTRING from_name; LEX_CSTRING handler_name; LEX_CSTRING db; LEX_CSTRING from_db; LEX_CSTRING from_handler_name; LEX_CSTRING tmp_name; /* frm file or temporary file name */ LEX_CSTRING extra_name; /* Backup table name */ uchar uuid[MY_UUID_SIZE]; // UUID for new frm file ulonglong xid; // Xid stored in the binary log /* unique_id can be used to store a unique number to check current state. Currently it is used to store new size of frm file, link to another ddl log entry or store an a uniq version for a storage engine in alter table. For execute entries this is reused as an execute counter to ensure we don't repeat an entry too many times if executing the entry fails. */ ulonglong unique_id; uint next_entry; uint entry_pos; // Set by write_dll_log_entry() uint16 flags; // Flags unique for each command enum ddl_log_entry_code entry_type; // Set automatically enum ddl_log_action_code action_type; /* Most actions have only one phase. REPLACE does however have two phases. The first phase removes the file with the new name if there was one there before and the second phase renames the old name to the new name. */ uchar phase; // set automatically } DDL_LOG_ENTRY; typedef struct st_ddl_log_memory_entry { uint entry_pos; struct st_ddl_log_memory_entry *next_log_entry; struct st_ddl_log_memory_entry *prev_log_entry; struct st_ddl_log_memory_entry *next_active_log_entry; } DDL_LOG_MEMORY_ENTRY; /* State of the ddl log during execution of a DDL. A ddl log state has one execute entry (main entry pointing to the first action entry) and many 'action entries' linked in a list in the order they should be executed. One recovery the log is parsed and all execute entries will be executed. All entries are stored as separate blocks in the ddl recovery file. */ typedef struct st_ddl_log_state { /* List of ddl log entries */ DDL_LOG_MEMORY_ENTRY *list; /* One execute entry per list */ DDL_LOG_MEMORY_ENTRY *execute_entry; /* Entry used for PHASE updates. Normally same as first in 'list', but in case of a query log event, this points to the main event. */ DDL_LOG_MEMORY_ENTRY *main_entry; uint16 flags; /* Cache for flags */ bool is_active() { return list != 0; } } DDL_LOG_STATE; /* These functions are for recovery */ bool ddl_log_initialize(); void ddl_log_release(); bool ddl_log_close_binlogged_events(HASH *xids); int ddl_log_execute_recovery(); /* functions for updating the ddl log */ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry, DDL_LOG_MEMORY_ENTRY **active_entry); bool ddl_log_write_execute_entry(uint first_entry, uint cond_entry, DDL_LOG_MEMORY_ENTRY** active_entry); inline bool ddl_log_write_execute_entry(uint first_entry, DDL_LOG_MEMORY_ENTRY **active_entry) { return ddl_log_write_execute_entry(first_entry, 0, active_entry); } bool ddl_log_disable_execute_entry(DDL_LOG_MEMORY_ENTRY **active_entry); void ddl_log_complete(DDL_LOG_STATE *ddl_log_state); bool ddl_log_revert(THD *thd, DDL_LOG_STATE *ddl_log_state); bool ddl_log_update_phase(DDL_LOG_STATE *entry, uchar phase); bool ddl_log_add_flag(DDL_LOG_STATE *entry, uint16 flag); bool ddl_log_update_unique_id(DDL_LOG_STATE *state, ulonglong id); bool ddl_log_update_xid(DDL_LOG_STATE *state, ulonglong xid); bool ddl_log_disable_entry(DDL_LOG_STATE *state); bool ddl_log_increment_phase(uint entry_pos); void ddl_log_release_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry); bool ddl_log_sync(); bool ddl_log_execute_entry(THD *thd, uint first_entry); void ddl_log_add_entry(DDL_LOG_STATE *state, DDL_LOG_MEMORY_ENTRY *log_entry); void ddl_log_release_entries(DDL_LOG_STATE *ddl_log_state); bool ddl_log_rename_table(DDL_LOG_STATE *ddl_state, handlerton *hton, const LEX_CSTRING *org_db, const LEX_CSTRING *org_alias, const LEX_CSTRING *new_db, const LEX_CSTRING *new_alias); bool ddl_log_rename_view(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *org_db, const LEX_CSTRING *org_alias, const LEX_CSTRING *new_db, const LEX_CSTRING *new_alias); bool ddl_log_drop_table_init(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *db, const LEX_CSTRING *comment); bool ddl_log_drop_view_init(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *db); bool ddl_log_drop_table(DDL_LOG_STATE *ddl_state, handlerton *hton, const LEX_CSTRING *path, const LEX_CSTRING *db, const LEX_CSTRING *table); bool ddl_log_drop_view(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *path, const LEX_CSTRING *db, const LEX_CSTRING *table); bool ddl_log_drop_trigger(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *db, const LEX_CSTRING *table, const LEX_CSTRING *trigger_name, const LEX_CSTRING *query); bool ddl_log_drop_view(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *path, const LEX_CSTRING *db, const LEX_CSTRING *table); bool ddl_log_drop_db(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *db, const LEX_CSTRING *path); bool ddl_log_create_table(DDL_LOG_STATE *ddl_state, handlerton *hton, const LEX_CSTRING *path, const LEX_CSTRING *db, const LEX_CSTRING *table, bool only_frm); bool ddl_log_create_view(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *path, enum_ddl_log_create_view_phase phase); bool ddl_log_delete_tmp_file(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *path, DDL_LOG_STATE *depending_state); bool ddl_log_create_trigger(DDL_LOG_STATE *ddl_state, const LEX_CSTRING *db, const LEX_CSTRING *table, const LEX_CSTRING *trigger_name, enum_ddl_log_create_trigger_phase phase); bool ddl_log_alter_table(DDL_LOG_STATE *ddl_state, handlerton *org_hton, const LEX_CSTRING *db, const LEX_CSTRING *table, handlerton *new_hton, handlerton *partition_underlying_hton, const LEX_CSTRING *new_db, const LEX_CSTRING *new_table, const LEX_CSTRING *frm_path, const LEX_CSTRING *backup_table_name, const LEX_CUSTRING *version, ulonglong table_version, bool is_renamed); bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_log_state, const char *query, size_t length); bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path); extern mysql_mutex_t LOCK_gdl; #endif /* DDL_LOG_INCLUDED */ grant.h 0000644 00000005306 15156036140 0006035 0 ustar 00 /* Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_GRANT_INCLUDED #define SQL_GRANT_INCLUDED #include "lex_string.h" #include "privilege.h" class LEX_COLUMN; class Lex_ident_sys; class Table_ident; /* Represents the object name in this standard SQL grammar: GRANT <object privileges> ON <object name> */ class Grant_object_name { public: enum Type { STAR, // ON * IDENT_STAR, // ON db.* STAR_STAR, // ON *.* TABLE_IDENT // ON db.name }; Lex_cstring m_db; Table_ident *m_table_ident; Type m_type; public: Grant_object_name(Table_ident *table_ident) :m_table_ident(table_ident), m_type(TABLE_IDENT) { } Grant_object_name(const LEX_CSTRING &db, Type type) :m_db(db), m_table_ident(NULL), m_type(type) { } privilege_t all_privileges_by_type() const; }; /* Represents standard SQL statements described by: - <grant privilege statement> - <revoke privilege statement> */ class Grant_privilege { protected: List<LEX_COLUMN> m_columns; Lex_cstring m_db; privilege_t m_object_privilege; privilege_t m_column_privilege_total; bool m_all_privileges; public: Grant_privilege() :m_object_privilege(NO_ACL), m_column_privilege_total(NO_ACL), m_all_privileges(false) { } Grant_privilege(privilege_t privilege, bool all_privileges) :m_object_privilege(privilege), m_column_privilege_total(NO_ACL), m_all_privileges(all_privileges) { } void add_object_privilege(privilege_t privilege) { m_object_privilege|= privilege; } bool add_column_privilege(THD *thd, const Lex_ident_sys &col, privilege_t privilege); bool add_column_list_privilege(THD *thd, List<Lex_ident_sys> &list, privilege_t privilege); bool set_object_name(THD *thd, const Grant_object_name &ident, SELECT_LEX *sel, privilege_t with_grant_option); const List<LEX_COLUMN> & columns() const { return m_columns; } }; #endif // SQL_GRANT_INCLUDED unireg.h 0000644 00000017411 15156036140 0006213 0 ustar 00 #ifndef UNIREG_INCLUDED #define UNIREG_INCLUDED /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include <mysql_version.h> /* FRM_VER */ /* Extra functions used by unireg library */ #ifndef NO_ALARM_LOOP #define NO_ALARM_LOOP /* lib5 and popen can't use alarm */ #endif /* These paths are converted to other systems (WIN95) before use */ #define LANGUAGE "english/" #define ERRMSG_FILE "errmsg.sys" #define TEMP_PREFIX "MY" #define LOG_PREFIX "ML" #define PROGDIR "bin/" #ifndef MYSQL_DATADIR #define MYSQL_DATADIR "data/" #endif #ifndef SHAREDIR #define SHAREDIR "share/" #endif #ifndef PLUGINDIR #define PLUGINDIR "lib/plugin" #endif #define MAX_ERROR_RANGES 4 /* 1000-2000, 2000-3000, 3000-4000, 4000-5000 */ #define ERRORS_PER_RANGE 1000 #define DEFAULT_ERRMSGS my_default_lc_messages->errmsgs->errmsgs #define CURRENT_THD_ERRMSGS (current_thd)->variables.errmsgs #ifndef mysqld_error_find_printf_error_used #define ER_DEFAULT(X) DEFAULT_ERRMSGS[((X)-ER_ERROR_FIRST) / ERRORS_PER_RANGE][(X)% ERRORS_PER_RANGE] #define ER_THD(thd,X) ((thd)->variables.errmsgs[((X)-ER_ERROR_FIRST) / ERRORS_PER_RANGE][(X) % ERRORS_PER_RANGE]) #define ER(X) ER_THD(current_thd, (X)) #endif #define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, (X)) : ER_DEFAULT(X)) #define SPECIAL_USE_LOCKS 1 /* Lock used databases */ #define SPECIAL_NO_NEW_FUNC 2 /* Skip new functions */ #define SPECIAL_SKIP_SHOW_DB 4 /* Don't allow 'show db' */ #define SPECIAL_WAIT_IF_LOCKED 8 /* Wait if locked database */ #define SPECIAL_SAME_DB_NAME 16 /* form name = file name */ #define SPECIAL_ENGLISH 32 /* English error messages */ #define SPECIAL_NO_RESOLVE 64 /* Obsolete */ #define SPECIAL_NO_PRIOR 128 /* Obsolete */ #define SPECIAL_BIG_SELECTS 256 /* Don't use heap tables */ #define SPECIAL_NO_HOST_CACHE 512 /* Don't cache hosts */ #define SPECIAL_SHORT_LOG_FORMAT 1024 #define SPECIAL_SAFE_MODE 2048 #define SPECIAL_LOG_QUERIES_NOT_USING_INDEXES 4096 /* Obsolete */ /* Extern defines */ #define store_record(A,B) memcpy((A)->B,(A)->record[0],(size_t) (A)->s->reclength) #define restore_record(A,B) memcpy((A)->record[0],(A)->B,(size_t) (A)->s->reclength) #define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->s->reclength) #define empty_record(A) { \ restore_record((A),s->default_values); \ if ((A)->s->null_bytes) \ bfill((A)->null_flags,(A)->s->null_bytes,255); \ } /* Defines for use with openfrm, openprt and openfrd */ #define READ_ALL (1 << 0) /* openfrm: Read all parameters */ #define EXTRA_RECORD (1 << 3) /* Reserve space for an extra record */ #define DELAYED_OPEN (1 << 12) /* Open table later */ #define OPEN_VIEW_NO_PARSE (1 << 14) /* Open frm only if it's a view, but do not parse view itself */ /** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to open FRM file only to get necessary data. */ #define OPEN_FRM_FILE_ONLY (1 << 15) /** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to process tables only to get necessary data. Views are not processed. */ #define OPEN_TABLE_ONLY (1 << 16) /** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to process views only to get necessary data. Tables are not processed. */ #define OPEN_VIEW_ONLY (1 << 17) /** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine. The flag means that we need to open a view using open_normal_and_derived_tables() function. */ #define OPEN_VIEW_FULL (1 << 18) /** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine. The flag means that I_S table uses optimization algorithm. */ #define OPTIMIZE_I_S_TABLE (1 << 19) /** This flag is used to instruct tdc_open_view() to check metadata version. */ #define CHECK_METADATA_VERSION (1 << 20) /* The flag means that we need to process trigger files only. */ #define OPEN_TRIGGER_ONLY (1 << 21) /** This flag is used in information schema to determine if handling funciton can treat open result extensively and provide some user output even if table open fails. */ #define I_S_EXTENDED_ERROR_HANDLING (1 << 22) /* Minimum length pattern before Turbo Boyer-Moore is used for SELECT "text" LIKE "%pattern%", excluding the two wildcards in class Item_func_like. */ #define MIN_TURBOBM_PATTERN_LEN 3 /* Defines for binary logging. Do not decrease the value of BIN_LOG_HEADER_SIZE. Do not even increase it before checking code. */ #define BIN_LOG_HEADER_SIZE 4 #define DEFAULT_KEY_CACHE_NAME "default" /* Include prototypes for unireg */ #include "mysqld_error.h" #include "structs.h" /* All structs we need */ #include "sql_list.h" /* List<> */ #include "field.h" /* Create_field */ /* Types of values in the MariaDB extra2 frm segment. Each value is written as type: 1 byte length: 1 byte (1..255) or \0 and 2 bytes. binary value of the 'length' bytes. Older MariaDB servers can ignore values of unknown types if the type code is less than 128 (EXTRA2_ENGINE_IMPORTANT). Otherwise older (but newer than 10.0.1) servers are required to report an error. */ enum extra2_frm_value_type { EXTRA2_TABLEDEF_VERSION=0, EXTRA2_DEFAULT_PART_ENGINE=1, EXTRA2_GIS=2, EXTRA2_APPLICATION_TIME_PERIOD=3, EXTRA2_PERIOD_FOR_SYSTEM_TIME=4, EXTRA2_INDEX_FLAGS=5, #define EXTRA2_ENGINE_IMPORTANT 128 EXTRA2_ENGINE_TABLEOPTS=128, EXTRA2_FIELD_FLAGS=129, EXTRA2_FIELD_DATA_TYPE_INFO=130, EXTRA2_PERIOD_WITHOUT_OVERLAPS=131, }; enum extra2_field_flags { VERS_OPTIMIZED_UPDATE= 1 << INVISIBLE_MAX_BITS, }; enum extra2_index_flags { EXTRA2_DEFAULT_INDEX_FLAGS, EXTRA2_IGNORED_KEY }; static inline size_t extra2_read_len(const uchar **extra2, const uchar *end) { size_t length= *(*extra2)++; if (length) return length; if ((*extra2) + 2 >= end) return 0; length= uint2korr(*extra2); (*extra2)+= 2; if (length < 256 || *extra2 + length > end) return 0; return length; } LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, HA_CREATE_INFO *create_info, List<Create_field> &create_fields, uint keys, KEY *key_info, handler *db_file); #define FRM_HEADER_SIZE 64 #define FRM_FORMINFO_SIZE 288 #define FRM_MAX_SIZE (1024*1024) static inline bool is_binary_frm_header(const uchar *head) { return head[0] == 254 && head[1] == 1 && head[2] >= FRM_VER && head[2] <= FRM_VER_CURRENT; } #endif lex_string.h 0000644 00000011421 15156036140 0007073 0 ustar 00 /* Copyright (c) 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LEX_STRING_INCLUDED #define LEX_STRING_INCLUDED typedef struct st_mysql_const_lex_string LEX_CSTRING; class Lex_cstring : public LEX_CSTRING { public: Lex_cstring() { str= NULL; length= 0; } Lex_cstring(const LEX_CSTRING &str) { LEX_CSTRING::operator=(str); } Lex_cstring(const char *_str, size_t _len) { str= _str; length= _len; } Lex_cstring(const char *start, const char *end) { DBUG_ASSERT(start <= end); str= start; length= end - start; } void set(const char *_str, size_t _len) { str= _str; length= _len; } /* Trim left white spaces. Assumes that there are no multi-bytes characters that can be considered white-space. */ Lex_cstring ltrim_whitespace(CHARSET_INFO *cs) const { DBUG_ASSERT(cs->mbminlen == 1); Lex_cstring str= *this; while (str.length > 0 && my_isspace(cs, str.str[0])) { str.length--; str.str++; } return str; } /* Trim right white spaces. Assumes that there are no multi-bytes characters that can be considered white-space. Also, assumes that the character set supports backward space parsing. */ Lex_cstring rtrim_whitespace(CHARSET_INFO *cs) const { DBUG_ASSERT(cs->mbminlen == 1); Lex_cstring str= *this; while (str.length > 0 && my_isspace(cs, str.str[str.length - 1])) { str.length --; } return str; } /* Trim all spaces. */ Lex_cstring trim_whitespace(CHARSET_INFO *cs) const { return ltrim_whitespace(cs).rtrim_whitespace(cs); } /* Trim all spaces and return the length of the leading space sequence. */ Lex_cstring trim_whitespace(CHARSET_INFO *cs, size_t *prefix_length) const { Lex_cstring tmp= Lex_cstring(*this).ltrim_whitespace(cs); if (prefix_length) *prefix_length= tmp.str - str; return tmp.rtrim_whitespace(cs); } /* Return the "n" leftmost bytes if this[0] is longer than "n" bytes, or return this[0] itself otherwise. */ Lex_cstring left(size_t n) const { return Lex_cstring(str, MY_MIN(length, n)); } /* If this[0] is shorter than "pos" bytes, then return an empty string. Otherwise, return a substring of this[0] starting from the byte position "pos" until the end. */ Lex_cstring substr(size_t pos) const { return length <= pos ? Lex_cstring(str + length, (size_t) 0) : Lex_cstring(str + pos, length - pos); } // Check if a prefix of this[0] is equal to "rhs". bool starts_with(const LEX_CSTRING &rhs) const { DBUG_ASSERT(str); DBUG_ASSERT(rhs.str); return length >= rhs.length && !memcmp(str, rhs.str, rhs.length); } }; class Lex_cstring_strlen: public Lex_cstring { public: explicit Lex_cstring_strlen(const char *from) :Lex_cstring(from, from ? strlen(from) : 0) { } }; /* Functions to compare if two lex strings are equal */ static inline bool lex_string_cmp(CHARSET_INFO *charset, const LEX_CSTRING *a, const LEX_CSTRING *b) { return my_strcasecmp(charset, a->str, b->str); } /* Compare to LEX_CSTRING's and return 0 if equal */ static inline bool cmp(const LEX_CSTRING *a, const LEX_CSTRING *b) { return a->length != b->length || (a->length && memcmp(a->str, b->str, a->length)); } static inline bool cmp(const LEX_CSTRING a, const LEX_CSTRING b) { return a.length != b.length || (a.length && memcmp(a.str, b.str, a.length)); } /* Compare if two LEX_CSTRING are equal. Assumption is that character set is ASCII (like for plugin names) */ static inline bool lex_string_eq(const LEX_CSTRING *a, const LEX_CSTRING *b) { if (a->length != b->length) return 0; /* Different */ return strcasecmp(a->str, b->str) == 0; } /* To be used when calling lex_string_eq with STRING_WITH_LEN() as second argument */ static inline bool lex_string_eq(const LEX_CSTRING *a, const char *b, size_t b_length) { if (a->length != b_length) return 0; /* Different */ return strcasecmp(a->str, b) == 0; } #endif /* LEX_STRING_INCLUDED */ log_event.h 0000644 00000531101 15156036141 0006702 0 ustar 00 /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @addtogroup Replication @{ @file @brief Binary log event definitions. This includes generic code common to all types of log events, as well as specific code for each type of log event. */ #ifndef _log_event_h #define _log_event_h #if defined(USE_PRAGMA_INTERFACE) && defined(MYSQL_SERVER) #pragma interface /* gcc class implementation */ #endif #include <my_bitmap.h> #include "rpl_constants.h" #include <vector> #include <string> #include <functional> #include <memory> #include <map> #include <lex_charset.h> #ifdef MYSQL_CLIENT #include "sql_const.h" #include "rpl_utility.h" #include "hash.h" #include "rpl_tblmap.h" #include "sql_string.h" #endif #ifdef MYSQL_SERVER #include "rpl_record.h" #include "rpl_reporting.h" #include "sql_class.h" /* THD */ #include "sql_insert.h" #else typedef ulong enum_slave_exec_mode; #endif #include "rpl_gtid.h" #include "log_event_data_type.h" /* Forward declarations */ #ifndef MYSQL_CLIENT class String; #endif #define PREFIX_SQL_LOAD "SQL_LOAD-" #define LONG_FIND_ROW_THRESHOLD 60 /* seconds */ /** Either assert or return an error. In debug build, the condition will be checked, but in non-debug builds, the error code given will be returned instead. @param COND Condition to check @param ERRNO Error number to return in non-debug builds */ #ifdef DBUG_OFF #define ASSERT_OR_RETURN_ERROR(COND, ERRNO) \ do { if (!(COND)) return ERRNO; } while (0) #else #define ASSERT_OR_RETURN_ERROR(COND, ERRNO) \ DBUG_ASSERT(COND) #endif #define LOG_READ_EOF -1 #define LOG_READ_BOGUS -2 #define LOG_READ_IO -3 #define LOG_READ_MEM -5 #define LOG_READ_TRUNC -6 #define LOG_READ_TOO_LARGE -7 #define LOG_READ_CHECKSUM_FAILURE -8 #define LOG_READ_DECRYPT -9 #define LOG_EVENT_OFFSET 4 /* 3 is MySQL 4.x; 4 is MySQL 5.0.0. Compared to version 3, version 4 has: - a different Start_log_event, which includes info about the binary log (sizes of headers); this info is included for better compatibility if the master's MySQL version is different from the slave's. - all events have a unique ID (the triplet (server_id, timestamp at server start, other) to be sure an event is not executed more than once in a multimaster setup, example: M1 / \ v v M2 M3 \ / v v S if a query is run on M1, it will arrive twice on S, so we need that S remembers the last unique ID it has processed, to compare and know if the event should be skipped or not. Example of ID: we already have the server id (4 bytes), plus: timestamp_when_the_master_started (4 bytes), a counter (a sequence number which increments every time we write an event to the binlog) (3 bytes). Q: how do we handle when the counter is overflowed and restarts from 0 ? - Query and Load (Create or Execute) events may have a more precise timestamp (with microseconds), number of matched/affected/warnings rows and fields of session variables: SQL_MODE, FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, SQL_AUTO_IS_NULL, the collations and charsets, the PASSWORD() version (old/new/...). */ #define BINLOG_VERSION 4 /* We could have used SERVER_VERSION_LENGTH, but this introduces an obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH this would break the replication protocol */ #define ST_SERVER_VER_LEN 50 /* These are flags and structs to handle all the LOAD DATA INFILE options (LINES TERMINATED etc). */ /* These are flags and structs to handle all the LOAD DATA INFILE options (LINES TERMINATED etc). DUMPFILE_FLAG is probably useless (DUMPFILE is a clause of SELECT, not of LOAD DATA). */ #define DUMPFILE_FLAG 0x1 #define OPT_ENCLOSED_FLAG 0x2 #define REPLACE_FLAG 0x4 #define IGNORE_FLAG 0x8 #define FIELD_TERM_EMPTY 0x1 #define ENCLOSED_EMPTY 0x2 #define LINE_TERM_EMPTY 0x4 #define LINE_START_EMPTY 0x8 #define ESCAPED_EMPTY 0x10 #define NUM_LOAD_DELIM_STRS 5 /* The following is the max table_map_id. This is limited by that we are using 6 bytes for it in replication */ #define MAX_TABLE_MAP_ID ((1ULL << (6*8)) -1) /***************************************************************************** MySQL Binary Log This log consists of events. Each event has a fixed-length header, possibly followed by a variable length data body. The data body consists of an optional fixed length segment (post-header) and an optional variable length segment. See the #defines below for the format specifics. The events which really update data are Query_log_event, Execute_load_query_log_event and Execute_load_log_event events (Execute_load_query is used together with Begin_load_query and Append_block events to replicate LOAD DATA INFILE. ****************************************************************************/ #define LOG_EVENT_HEADER_LEN 19 /* the fixed header length */ /* Fixed header length. That is, some future version may have a longer header, but at least the first 19 bytes will be the same. So LOG_EVENT_HEADER_LEN will be something like 26, but LOG_EVENT_MINIMAL_HEADER_LEN will remain 19. */ #define LOG_EVENT_MINIMAL_HEADER_LEN 19 /* event-specific post-header sizes */ // where 3.23, 4.x and 5.0 agree #define QUERY_HEADER_MINIMAL_LEN (4 + 4 + 1 + 2) // where 5.0 differs: 2 for len of N-bytes vars. #define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 2) #define STOP_HEADER_LEN 0 #define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4) #define SLAVE_HEADER_LEN 0 #define START_V3_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4) #define ROTATE_HEADER_LEN 8 // this is FROZEN (the Rotate post-header is frozen) #define INTVAR_HEADER_LEN 0 #define CREATE_FILE_HEADER_LEN 4 #define APPEND_BLOCK_HEADER_LEN 4 #define EXEC_LOAD_HEADER_LEN 4 #define DELETE_FILE_HEADER_LEN 4 #define NEW_LOAD_HEADER_LEN LOAD_HEADER_LEN #define RAND_HEADER_LEN 0 #define USER_VAR_HEADER_LEN 0 #define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES) #define XID_HEADER_LEN 0 #define BEGIN_LOAD_QUERY_HEADER_LEN APPEND_BLOCK_HEADER_LEN #define ROWS_HEADER_LEN_V1 8 #define TABLE_MAP_HEADER_LEN 8 #define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1) #define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN) #define INCIDENT_HEADER_LEN 2 #define HEARTBEAT_HEADER_LEN 0 #define IGNORABLE_HEADER_LEN 0 #define ROWS_HEADER_LEN_V2 10 #define ANNOTATE_ROWS_HEADER_LEN 0 #define BINLOG_CHECKPOINT_HEADER_LEN 4 #define GTID_HEADER_LEN 19 #define GTID_LIST_HEADER_LEN 4 #define START_ENCRYPTION_HEADER_LEN 0 #define XA_PREPARE_HEADER_LEN 0 /* Max number of possible extra bytes in a replication event compared to a packet (i.e. a query) sent from client to master; First, an auxiliary log_event status vars estimation: */ #define MAX_SIZE_LOG_EVENT_STATUS (uint) \ (1 + 4 /* type, flags2 */ + \ 1 + 8 /* type, sql_mode */ + \ 1 + 1 + 255 /* type, length, catalog */ + \ 1 + 4 /* type, auto_increment */ + \ 1 + 6 /* type, charset */ + \ 1 + 1 + 255 /* type, length, time_zone */ + \ 1 + 2 /* type, lc_time_names_number */ + \ 1 + 2 /* type, charset_database_number */ + \ 1 + 8 /* type, table_map_for_update */ + \ 1 + 4 /* type, master_data_written */ + \ 1 + 3 /* type, sec_part of NOW() */ + \ 1 + 16 + 1 + 60/* type, user_len, user, host_len, host */ + \ 1 + 2 + 8 /* type, flags3, seq_no */ + \ 1 + Charset_collation_map_st::binary_size_max() \ /* type, map */ \ ) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \ MAX_SIZE_LOG_EVENT_STATUS + /* status */ \ NAME_LEN + 1) /* The new option is added to handle large packets that are sent from the master to the slave. It is used to increase the thd(max_allowed) for both the DUMP thread on the master and the SQL/IO thread on the slave. */ #define MAX_MAX_ALLOWED_PACKET (1024*1024*1024) /* Event header offsets; these point to places inside the fixed header. */ #define EVENT_TYPE_OFFSET 4 #define SERVER_ID_OFFSET 5 #define EVENT_LEN_OFFSET 9 #define LOG_POS_OFFSET 13 #define FLAGS_OFFSET 17 /* start event post-header (for v3 and v4) */ #define ST_BINLOG_VER_OFFSET 0 #define ST_SERVER_VER_OFFSET 2 #define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN) #define ST_COMMON_HEADER_LEN_OFFSET (ST_CREATED_OFFSET + 4) /* slave event post-header (this event is never written) */ #define SL_MASTER_PORT_OFFSET 8 #define SL_MASTER_POS_OFFSET 0 #define SL_MASTER_HOST_OFFSET 10 /* query event post-header */ #define Q_THREAD_ID_OFFSET 0 #define Q_EXEC_TIME_OFFSET 4 #define Q_DB_LEN_OFFSET 8 #define Q_ERR_CODE_OFFSET 9 #define Q_STATUS_VARS_LEN_OFFSET 11 #define Q_DATA_OFFSET QUERY_HEADER_LEN /* these are codes, not offsets; not more than 256 values (1 byte). */ #define Q_FLAGS2_CODE 0 #define Q_SQL_MODE_CODE 1 /* Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL 5.0.x where 0<=x<=3. We have to keep it to be able to replicate these old masters. */ #define Q_CATALOG_CODE 2 #define Q_AUTO_INCREMENT 3 #define Q_CHARSET_CODE 4 #define Q_TIME_ZONE_CODE 5 /* Q_CATALOG_NZ_CODE is catalog withOUT end zero stored; it is used by MySQL 5.0.x where x>=4. Saves one byte in every Query_log_event in binlog, compared to Q_CATALOG_CODE. The reason we didn't simply re-use Q_CATALOG_CODE is that then a 5.0.3 slave of this 5.0.x (x>=4) master would crash (segfault etc) because it would expect a 0 when there is none. */ #define Q_CATALOG_NZ_CODE 6 #define Q_LC_TIME_NAMES_CODE 7 #define Q_CHARSET_DATABASE_CODE 8 #define Q_TABLE_MAP_FOR_UPDATE_CODE 9 #define Q_MASTER_DATA_WRITTEN_CODE 10 #define Q_INVOKER 11 #define Q_HRNOW 128 #define Q_XID 129 #define Q_GTID_FLAGS3 130 #define Q_CHARACTER_SET_COLLATIONS 131 /* Intvar event post-header */ /* Intvar event data */ #define I_TYPE_OFFSET 0 #define I_VAL_OFFSET 1 /* Rand event data */ #define RAND_SEED1_OFFSET 0 #define RAND_SEED2_OFFSET 8 /* User_var event data */ #define UV_VAL_LEN_SIZE 4 #define UV_VAL_IS_NULL 1 #define UV_VAL_TYPE_SIZE 1 #define UV_NAME_LEN_SIZE 4 #define UV_CHARSET_NUMBER_SIZE 4 /* Load event post-header */ #define L_THREAD_ID_OFFSET 0 #define L_EXEC_TIME_OFFSET 4 #define L_SKIP_LINES_OFFSET 8 #define L_TBL_LEN_OFFSET 12 #define L_DB_LEN_OFFSET 13 #define L_NUM_FIELDS_OFFSET 14 #define L_SQL_EX_OFFSET 18 #define L_DATA_OFFSET LOAD_HEADER_LEN /* Rotate event post-header */ #define R_POS_OFFSET 0 #define R_IDENT_OFFSET 8 /* CF to DF handle LOAD DATA INFILE */ /* CF = "Create File" */ #define CF_FILE_ID_OFFSET 0 #define CF_DATA_OFFSET CREATE_FILE_HEADER_LEN /* AB = "Append Block" */ #define AB_FILE_ID_OFFSET 0 #define AB_DATA_OFFSET APPEND_BLOCK_HEADER_LEN /* EL = "Execute Load" */ #define EL_FILE_ID_OFFSET 0 /* DF = "Delete File" */ #define DF_FILE_ID_OFFSET 0 /* TM = "Table Map" */ #define TM_MAPID_OFFSET 0 #define TM_FLAGS_OFFSET 6 /* RW = "RoWs" */ #define RW_MAPID_OFFSET 0 #define RW_FLAGS_OFFSET 6 #define RW_VHLEN_OFFSET 8 #define RW_V_TAG_LEN 1 #define RW_V_EXTRAINFO_TAG 0 /* ELQ = "Execute Load Query" */ #define ELQ_FILE_ID_OFFSET QUERY_HEADER_LEN #define ELQ_FN_POS_START_OFFSET ELQ_FILE_ID_OFFSET + 4 #define ELQ_FN_POS_END_OFFSET ELQ_FILE_ID_OFFSET + 8 #define ELQ_DUP_HANDLING_OFFSET ELQ_FILE_ID_OFFSET + 12 /* 4 bytes which all binlogs should begin with */ #define BINLOG_MAGIC (const uchar*) "\xfe\x62\x69\x6e" /* The 2 flags below were useless : - the first one was never set - the second one was set in all Rotate events on the master, but not used for anything useful. So they are now removed and their place may later be reused for other flags. Then one must remember that Rotate events in 4.x have LOG_EVENT_FORCED_ROTATE_F set, so one should not rely on the value of the replacing flag when reading a Rotate event. I keep the defines here just to remember what they were. */ #ifdef TO_BE_REMOVED #define LOG_EVENT_TIME_F 0x1 #define LOG_EVENT_FORCED_ROTATE_F 0x2 #endif /* This flag only makes sense for Format_description_log_event. It is set when the event is written, and *reset* when a binlog file is closed (yes, it's the only case when MySQL modifies already written part of binlog). Thus it is a reliable indicator that binlog was closed correctly. (Stop_log_event is not enough, there's always a small chance that mysqld crashes in the middle of insert and end of the binlog would look like a Stop_log_event). This flag is used to detect a restart after a crash, and to provide "unbreakable" binlog. The problem is that on a crash storage engines rollback automatically, while binlog does not. To solve this we use this flag and automatically append ROLLBACK to every non-closed binlog (append virtually, on reading, file itself is not changed). If this flag is found, mysqlbinlog simply prints "ROLLBACK" Replication master does not abort on binlog corruption, but takes it as EOF, and replication slave forces a rollback in this case. Note, that old binlogs does not have this flag set, so we get a a backward-compatible behaviour. */ #define LOG_EVENT_BINLOG_IN_USE_F 0x1 /** @def LOG_EVENT_THREAD_SPECIFIC_F If the query depends on the thread (for example: TEMPORARY TABLE). Currently this is used by mysqlbinlog to know it must print SET @@PSEUDO_THREAD_ID=xx; before the query (it would not hurt to print it for every query but this would be slow). */ #define LOG_EVENT_THREAD_SPECIFIC_F 0x4 /** @def LOG_EVENT_SUPPRESS_USE_F Suppress the generation of 'USE' statements before the actual statement. This flag should be set for any events that does not need the current database set to function correctly. Most notable cases are 'CREATE DATABASE' and 'DROP DATABASE'. This flags should only be used in exceptional circumstances, since it introduce a significant change in behaviour regarding the replication logic together with the flags --binlog-do-db and --replicated-do-db. */ #define LOG_EVENT_SUPPRESS_USE_F 0x8 /* Note: this is a place holder for the flag LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F (0x10), which is not used any more, please do not reused this value for other flags. */ /** @def LOG_EVENT_ARTIFICIAL_F Artificial events are created arbitrarily and not written to binary log These events should not update the master log position when slave SQL thread executes them. */ #define LOG_EVENT_ARTIFICIAL_F 0x20 /** @def LOG_EVENT_RELAY_LOG_F Events with this flag set are created by slave IO thread and written to relay log */ #define LOG_EVENT_RELAY_LOG_F 0x40 /** @def LOG_EVENT_IGNORABLE_F For an event, 'e', carrying a type code, that a slave, 's', does not recognize, 's' will check 'e' for LOG_EVENT_IGNORABLE_F, and if the flag is set, then 'e' is ignored. Otherwise, 's' acknowledges that it has found an unknown event in the relay log. */ #define LOG_EVENT_IGNORABLE_F 0x80 /** @def LOG_EVENT_ACCEPT_OWN_F Flag sets by the semisync slave for accepting the same server_id ("own") events which the slave must not have in its state. Typically such events were never committed by their originator (this server) and discared at its semisync-slave recovery. */ #define LOG_EVENT_ACCEPT_OWN_F 0x4000 /** @def LOG_EVENT_SKIP_REPLICATION_F Flag set by application creating the event (with @@skip_replication); the slave will skip replication of such events if --replicate-events-marked-for-skip is not set to REPLICATE. This is a MariaDB flag; we allocate it from the end of the available values to reduce risk of conflict with new MySQL flags. */ #define LOG_EVENT_SKIP_REPLICATION_F 0x8000 /** @def OPTIONS_WRITTEN_TO_BIN_LOG OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must be written to the binlog. OPTIONS_WRITTEN_TO_BIN_LOG could be written into the Format_description_log_event, so that if later we don't want to replicate a variable we did replicate, or the contrary, it's doable. But it should not be too hard to deduct the value of OPTIONS_WRITTEN_TO_BIN_LOG from the master's version. This is done in deduct_options_written_to_bin_log(). You *must* update it, when changing the definition below. */ #define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_EXPLICIT_DEF_TIMESTAMP |\ OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \ OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT | OPTION_IF_EXISTS |\ OPTION_INSERT_HISTORY) #define CHECKSUM_CRC32_SIGNATURE_LEN 4 /** defined statically while there is just one alg implemented */ #define BINLOG_CHECKSUM_LEN CHECKSUM_CRC32_SIGNATURE_LEN #define BINLOG_CHECKSUM_ALG_DESC_LEN 1 /* 1 byte checksum alg descriptor */ /* These are capability numbers for MariaDB slave servers. Newer MariaDB slaves set this to inform the master about their capabilities. This allows the master to decide which events it can send to the slave without breaking replication on old slaves that maybe do not understand all events from newer masters. As new releases are backwards compatible, a given capability implies also all capabilities with smaller number. Older MariaDB slaves and other MySQL slave servers do not set this, so they are recorded with capability 0. */ /* MySQL or old MariaDB slave with no announced capability. */ #define MARIA_SLAVE_CAPABILITY_UNKNOWN 0 /* MariaDB >= 5.3, which understands ANNOTATE_ROWS_EVENT. */ #define MARIA_SLAVE_CAPABILITY_ANNOTATE 1 /* MariaDB >= 5.5. This version has the capability to tolerate events omitted from the binlog stream without breaking replication (MySQL slaves fail because they mis-compute the offsets into the master's binlog). */ #define MARIA_SLAVE_CAPABILITY_TOLERATE_HOLES 2 /* MariaDB >= 10.0, which knows about binlog_checkpoint_log_event. */ #define MARIA_SLAVE_CAPABILITY_BINLOG_CHECKPOINT 3 /* MariaDB >= 10.0.1, which knows about global transaction id events. */ #define MARIA_SLAVE_CAPABILITY_GTID 4 /* Our capability. */ #define MARIA_SLAVE_CAPABILITY_MINE MARIA_SLAVE_CAPABILITY_GTID /* When the size of 'log_pos' within Heartbeat_log_event exceeds UINT32_MAX it cannot be accommodated in common_header, as 'log_pos' is of 4 bytes size. In such cases, sub_header, of size 8 bytes will hold larger 'log_pos' value. */ #define HB_SUB_HEADER_LEN 8 /** @enum Log_event_type Enumeration type for the different types of log events. */ enum Log_event_type { /* Every time you update this enum (when you add a type), you have to fix Format_description_log_event::Format_description_log_event(). */ UNKNOWN_EVENT= 0, START_EVENT_V3= 1, QUERY_EVENT= 2, STOP_EVENT= 3, ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT= 6, SLAVE_EVENT= 7, CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10, DELETE_FILE_EVENT= 11, NEW_LOAD_EVENT= 12, RAND_EVENT= 13, USER_VAR_EVENT= 14, FORMAT_DESCRIPTION_EVENT= 15, XID_EVENT= 16, BEGIN_LOAD_QUERY_EVENT= 17, EXECUTE_LOAD_QUERY_EVENT= 18, TABLE_MAP_EVENT = 19, /* These event numbers were used for 5.1.0 to 5.1.15 and are therefore obsolete. */ PRE_GA_WRITE_ROWS_EVENT = 20, PRE_GA_UPDATE_ROWS_EVENT = 21, PRE_GA_DELETE_ROWS_EVENT = 22, /* These event numbers are used from 5.1.16 until mysql-5.6.6, and in MariaDB */ WRITE_ROWS_EVENT_V1 = 23, UPDATE_ROWS_EVENT_V1 = 24, DELETE_ROWS_EVENT_V1 = 25, /* Something out of the ordinary happened on the master */ INCIDENT_EVENT= 26, /* Heartbeat event to be send by master at its idle time to ensure master's online status to slave */ HEARTBEAT_LOG_EVENT= 27, /* In some situations, it is necessary to send over ignorable data to the slave: data that a slave can handle in case there is code for handling it, but which can be ignored if it is not recognized. These mysql-5.6 events are not recognized (and ignored) by MariaDB */ IGNORABLE_LOG_EVENT= 28, ROWS_QUERY_LOG_EVENT= 29, /* Version 2 of the Row events, generated only by mysql-5.6.6+ */ WRITE_ROWS_EVENT = 30, UPDATE_ROWS_EVENT = 31, DELETE_ROWS_EVENT = 32, /* MySQL 5.6 GTID events, ignored by MariaDB */ GTID_LOG_EVENT= 33, ANONYMOUS_GTID_LOG_EVENT= 34, PREVIOUS_GTIDS_LOG_EVENT= 35, /* MySQL 5.7 events, ignored by MariaDB */ TRANSACTION_CONTEXT_EVENT= 36, VIEW_CHANGE_EVENT= 37, /* not ignored */ XA_PREPARE_LOG_EVENT= 38, /** Extension of UPDATE_ROWS_EVENT, allowing partial values according to binlog_row_value_options. */ PARTIAL_UPDATE_ROWS_EVENT = 39, TRANSACTION_PAYLOAD_EVENT = 40, HEARTBEAT_LOG_EVENT_V2 = 41, /* Add new events here - right above this comment! Existing events (except ENUM_END_EVENT) should never change their numbers */ /* New MySQL/Sun events are to be added right above this comment */ MYSQL_EVENTS_END, MARIA_EVENTS_BEGIN= 160, /* New Maria event numbers start from here */ ANNOTATE_ROWS_EVENT= 160, /* Binlog checkpoint event. Used for XA crash recovery on the master, not used in replication. A binlog checkpoint event specifies a binlog file such that XA crash recovery can start from that file - and it is guaranteed to find all XIDs that are prepared in storage engines but not yet committed. */ BINLOG_CHECKPOINT_EVENT= 161, /* Gtid event. For global transaction ID, used to start a new event group, instead of the old BEGIN query event, and also to mark stand-alone events. */ GTID_EVENT= 162, /* Gtid list event. Logged at the start of every binlog, to record the current replication state. This consists of the last GTID seen for each replication domain. */ GTID_LIST_EVENT= 163, START_ENCRYPTION_EVENT= 164, /* Compressed binlog event. Note that the order between WRITE/UPDATE/DELETE events is significant; this is so that we can convert from the compressed to the uncompressed event type with (type-WRITE_ROWS_COMPRESSED_EVENT + WRITE_ROWS_EVENT) and similar for _V1. */ QUERY_COMPRESSED_EVENT = 165, WRITE_ROWS_COMPRESSED_EVENT_V1 = 166, UPDATE_ROWS_COMPRESSED_EVENT_V1 = 167, DELETE_ROWS_COMPRESSED_EVENT_V1 = 168, WRITE_ROWS_COMPRESSED_EVENT = 169, UPDATE_ROWS_COMPRESSED_EVENT = 170, DELETE_ROWS_COMPRESSED_EVENT = 171, /* Add new MariaDB events here - right above this comment! */ ENUM_END_EVENT /* end marker */ }; /* Bit flags for what has been writing to cache. Used to discard logs with table map events but not row events and nothing else important. This is stored by cache. */ enum enum_logged_status { LOGGED_TABLE_MAP= 1, LOGGED_ROW_EVENT= 2, LOGGED_NO_DATA= 4, LOGGED_CRITICAL= 8 }; static inline bool LOG_EVENT_IS_QUERY(enum Log_event_type type) { return type == QUERY_EVENT || type == QUERY_COMPRESSED_EVENT; } static inline bool LOG_EVENT_IS_WRITE_ROW(enum Log_event_type type) { return type == WRITE_ROWS_EVENT || type == WRITE_ROWS_EVENT_V1 || type == WRITE_ROWS_COMPRESSED_EVENT || type == WRITE_ROWS_COMPRESSED_EVENT_V1; } static inline bool LOG_EVENT_IS_UPDATE_ROW(enum Log_event_type type) { return type == UPDATE_ROWS_EVENT || type == UPDATE_ROWS_EVENT_V1 || type == UPDATE_ROWS_COMPRESSED_EVENT || type == UPDATE_ROWS_COMPRESSED_EVENT_V1; } static inline bool LOG_EVENT_IS_DELETE_ROW(enum Log_event_type type) { return type == DELETE_ROWS_EVENT || type == DELETE_ROWS_EVENT_V1 || type == DELETE_ROWS_COMPRESSED_EVENT || type == DELETE_ROWS_COMPRESSED_EVENT_V1; } static inline bool LOG_EVENT_IS_ROW_COMPRESSED(enum Log_event_type type) { return type == WRITE_ROWS_COMPRESSED_EVENT || type == WRITE_ROWS_COMPRESSED_EVENT_V1 || type == UPDATE_ROWS_COMPRESSED_EVENT || type == UPDATE_ROWS_COMPRESSED_EVENT_V1 || type == DELETE_ROWS_COMPRESSED_EVENT || type == DELETE_ROWS_COMPRESSED_EVENT_V1; } static inline bool LOG_EVENT_IS_ROW_V2(enum Log_event_type type) { return (type >= WRITE_ROWS_EVENT && type <= DELETE_ROWS_EVENT) || (type >= WRITE_ROWS_COMPRESSED_EVENT && type <= DELETE_ROWS_COMPRESSED_EVENT); } /* The number of types we handle in Format_description_log_event (UNKNOWN_EVENT is not to be handled, it does not exist in binlogs, it does not have a format). */ #define LOG_EVENT_TYPES (ENUM_END_EVENT-1) enum Int_event_type { INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2 }; #ifdef MYSQL_SERVER class String; class MYSQL_BIN_LOG; class THD; #endif class Format_description_log_event; class Relay_log_info; class binlog_cache_data; bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file); #ifdef MYSQL_CLIENT enum enum_base64_output_mode { BASE64_OUTPUT_NEVER= 0, BASE64_OUTPUT_AUTO= 1, BASE64_OUTPUT_UNSPEC= 2, BASE64_OUTPUT_DECODE_ROWS= 3, /* insert new output modes here */ BASE64_OUTPUT_MODE_COUNT }; bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to); /* A structure for mysqlbinlog to know how to print events This structure is passed to the event's print() methods, There are two types of settings stored here: 1. Last db, flags2, sql_mode etc comes from the last printed event. They are stored so that only the necessary USE and SET commands are printed. 2. Other information on how to print the events, e.g. short_form, hexdump_from. These are not dependent on the last event. */ typedef struct st_print_event_info { /* Settings for database, sql_mode etc that comes from the last event that was printed. We cache these so that we don't have to print them if they are unchanged. */ char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is char charset[6]; // 3 variables, each of them storable in 2 bytes char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; char delimiter[16]; sql_mode_t sql_mode; /* must be same as THD.variables.sql_mode */ my_thread_id thread_id; ulonglong row_events; ulong auto_increment_increment, auto_increment_offset; uint lc_time_names_number; uint charset_database_number; uint verbose; uchar gtid_ev_flags2; uint32 flags2; uint32 server_id; uint32 domain_id; uint8 common_header_len; enum_base64_output_mode base64_output_mode; my_off_t hexdump_from; table_mapping m_table_map; table_mapping m_table_map_ignored; bool flags2_inited; bool sql_mode_inited; bool charset_inited; bool thread_id_printed; bool server_id_printed; bool domain_id_printed; bool allow_parallel; bool allow_parallel_printed; bool found_row_event; bool print_row_count; static const uint max_delimiter_size= 16; /* Settings on how to print the events */ bool short_form; /* This is set whenever a Format_description_event is printed. Later, when an event is printed in base64, this flag is tested: if no Format_description_event has been seen, it is unsafe to print the base64 event, so an error message is generated. */ bool printed_fd_event; /* Track when @@skip_replication changes so we need to output a SET statement for it. */ bool skip_replication; bool print_table_metadata; /* These two caches are used by the row-based replication events to collect the header information and the main body of the events making up a statement. */ IO_CACHE head_cache; IO_CACHE body_cache; IO_CACHE tail_cache; #ifdef WHEN_FLASHBACK_REVIEW_READY /* Storing the SQL for reviewing */ IO_CACHE review_sql_cache; #endif FILE *file; /* Used to include the events within a GTID start/stop boundary */ my_bool m_is_event_group_active; /* Tracks whether or not output events must be explicitly activated in order to be printed */ my_bool m_is_event_group_filtering_enabled; st_print_event_info(); ~st_print_event_info() { close_cached_file(&head_cache); close_cached_file(&body_cache); close_cached_file(&tail_cache); #ifdef WHEN_FLASHBACK_REVIEW_READY close_cached_file(&review_sql_cache); #endif } bool init_ok() /* tells if construction was successful */ { return my_b_inited(&head_cache) && my_b_inited(&body_cache) #ifdef WHEN_FLASHBACK_REVIEW_READY && my_b_inited(&review_sql_cache) #endif ; } void flush_for_error() { if (!copy_event_cache_to_file_and_reinit(&head_cache, file)) copy_event_cache_to_file_and_reinit(&body_cache, file); fflush(file); } /* Notify that all events part of the current group should be printed */ void activate_current_event_group() { m_is_event_group_active= TRUE; } void deactivate_current_event_group() { m_is_event_group_active= FALSE; } /* Used for displaying events part of an event group. Returns TRUE when both event group filtering is enabled and the current event group should be displayed, OR if event group filtering is disabled. More specifically, if filtering is disabled, all events should be shown. Returns FALSE when event group filtering is enabled and the current event group is filtered out. */ my_bool is_event_group_active() { return m_is_event_group_filtering_enabled ? m_is_event_group_active : TRUE; } /* Notify that events must be explicitly activated in order to be printed */ void enable_event_group_filtering() { m_is_event_group_filtering_enabled= TRUE; } my_bool is_xa_trans(); } PRINT_EVENT_INFO; #endif // MYSQL_CLIENT /** This class encapsulates writing of Log_event objects to IO_CACHE. Automatically calculates the checksum and encrypts the data, if necessary. */ class Log_event_writer { /* Log_event_writer is updated when ctx is set */ int (Log_event_writer::*encrypt_or_write)(const uchar *pos, size_t len); public: ulonglong bytes_written; void *ctx; ///< Encryption context or 0 if no encryption is needed /* The length of a checksum written at the end of the event, if any. Currently this is always either 0, when checksums are disabled, or BINLOG_CHECKSUM_LEN when using BINLOG_CHECKSUM_ALG_CRC32. (If we ever add another checksum algorithm, we will need to instead store here the algorithm to use instead of just the length). */ uint checksum_len; int write(Log_event *ev); int write_header(uchar *pos, size_t len); int write_data(const uchar *pos, size_t len); int write_footer(); my_off_t pos() { return my_b_safe_tell(file); } void add_status(enum_logged_status status); void set_incident(); void set_encrypted_writer() { encrypt_or_write= &Log_event_writer::encrypt_and_write; } Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg, enum_binlog_checksum_alg checksum_alg, Binlog_crypt_data *cr) :encrypt_or_write(&Log_event_writer::write_internal), bytes_written(0), ctx(0), checksum_len(( checksum_alg != BINLOG_CHECKSUM_ALG_OFF && checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ? BINLOG_CHECKSUM_LEN : 0), file(file_arg), cache_data(cache_data_arg), crypto(cr) { } private: IO_CACHE *file; binlog_cache_data *cache_data; /** Placeholder for event checksum while writing to binlog. */ ha_checksum crc; /** Encryption data (key, nonce). Only used if ctx != 0. */ Binlog_crypt_data *crypto; /** Event length to be written into the next encrypted block */ uint event_len; int write_internal(const uchar *pos, size_t len); int encrypt_and_write(const uchar *pos, size_t len); int maybe_write_event_len(uchar *pos, size_t len); }; /** the struct aggregates two parameters that identify an event uniquely in scope of communication of a particular master and slave couple. I.e there can not be 2 events from the same staying connected master which have the same coordinates. @note Such identifier is not yet unique generally as the event originating master is resettable. Also the crashed master can be replaced with some other. */ typedef struct event_coordinates { char * file_name; // binlog file name (directories stripped) my_off_t pos; // event's position in the binlog file } LOG_POS_COORD; /** @class Log_event This is the abstract base class for binary log events. @section Log_event_binary_format Binary Format Any @c Log_event saved on disk consists of the following three components. - Common-Header - Post-Header - Body The Common-Header, documented in the table @ref Table_common_header "below", always has the same form and length within one version of MySQL. Each event type specifies a format and length of the Post-Header. The length of the Common-Header is the same for all events of the same type. The Body may be of different format and length even for different events of the same type. The binary formats of Post-Header and Body are documented separately in each subclass. The binary format of Common-Header is as follows. <table> <caption>Common-Header</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>timestamp</td> <td>4 byte unsigned integer</td> <td>The time when the query started, in seconds since 1970. </td> </tr> <tr> <td>type</td> <td>1 byte enumeration</td> <td>See enum #Log_event_type.</td> </tr> <tr> <td>server_id</td> <td>4 byte unsigned integer</td> <td>Server ID of the server that created the event.</td> </tr> <tr> <td>total_size</td> <td>4 byte unsigned integer</td> <td>The total size of this event, in bytes. In other words, this is the sum of the sizes of Common-Header, Post-Header, and Body. </td> </tr> <tr> <td>master_position</td> <td>4 byte unsigned integer</td> <td>The position of the next event in the master binary log, in bytes from the beginning of the file. In a binlog that is not a relay log, this is just the position of the next event, in bytes from the beginning of the file. In a relay log, this is the position of the next event in the master's binlog. </td> </tr> <tr> <td>flags</td> <td>2 byte bitfield</td> <td>See Log_event::flags.</td> </tr> </table> Summing up the numbers above, we see that the total size of the common header is 19 bytes. @subsection Log_event_format_of_atomic_primitives Format of Atomic Primitives - All numbers, whether they are 16-, 24-, 32-, or 64-bit numbers, are stored in little endian, i.e., the least significant byte first, unless otherwise specified. @anchor packed_integer - Some events use a special format for efficient representation of unsigned integers, called Packed Integer. A Packed Integer has the capacity of storing up to 8-byte integers, while small integers still can use 1, 3, or 4 bytes. The value of the first byte determines how to read the number, according to the following table: <table> <caption>Format of Packed Integer</caption> <tr> <th>First byte</th> <th>Format</th> </tr> <tr> <td>0-250</td> <td>The first byte is the number (in the range 0-250), and no more bytes are used.</td> </tr> <tr> <td>252</td> <td>Two more bytes are used. The number is in the range 251-0xffff.</td> </tr> <tr> <td>253</td> <td>Three more bytes are used. The number is in the range 0xffff-0xffffff.</td> </tr> <tr> <td>254</td> <td>Eight more bytes are used. The number is in the range 0xffffff-0xffffffffffffffff.</td> </tr> </table> - Strings are stored in various formats. The format of each string is documented separately. */ class Log_event { public: /** Enumeration of what kinds of skipping (and non-skipping) that can occur when the slave executes an event. @see shall_skip @see do_shall_skip */ enum enum_skip_reason { /** Don't skip event. */ EVENT_SKIP_NOT, /** Skip event by ignoring it. This means that the slave skip counter will not be changed. */ EVENT_SKIP_IGNORE, /** Skip event and decrease skip counter. */ EVENT_SKIP_COUNT }; enum enum_event_cache_type { EVENT_INVALID_CACHE, /* If possible the event should use a non-transactional cache before being flushed to the binary log. This means that it must be flushed right after its correspondent statement is completed. */ EVENT_STMT_CACHE, /* The event should use a transactional cache before being flushed to the binary log. This means that it must be flushed upon commit or rollback. */ EVENT_TRANSACTIONAL_CACHE, /* The event must be written directly to the binary log without going through a cache. */ EVENT_NO_CACHE, /** If there is a need for different types, introduce them before this. */ EVENT_CACHE_COUNT }; /* The following type definition is to be used whenever data is placed and manipulated in a common buffer. Use this typedef for buffers that contain data containing binary and character data. */ typedef unsigned char Byte; /* The offset in the log where this event originally appeared (it is preserved in relay logs, making SHOW SLAVE STATUS able to print coordinates of the event in the master's binlog). Note: when a transaction is written by the master to its binlog (wrapped in BEGIN/COMMIT) the log_pos of all the queries it contains is the one of the BEGIN (this way, when one does SHOW SLAVE STATUS it sees the offset of the BEGIN, which is logical as rollback may occur), except the COMMIT query which has its real offset. */ my_off_t log_pos; /* A temp buffer for read_log_event; it is later analysed according to the event's type, and its content is distributed in the event-specific fields. */ uchar *temp_buf; /* Timestamp on the master(for debugging and replication of NOW()/TIMESTAMP). It is important for queries and LOAD DATA INFILE. This is set at the event's creation time, except for Query and Load (et al.) events where this is set at the query's execution time, which guarantees good replication (otherwise, we could have a query and its event with different timestamps). */ my_time_t when; ulong when_sec_part; /* The number of seconds the query took to run on the master. */ ulong exec_time; /* Number of bytes written by write() function */ size_t data_written; /* The master's server id (is preserved in the relay log; used to prevent from infinite loops in circular replication). */ uint32 server_id; /** Some 16 flags. See the definitions above for LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F, LOG_EVENT_SUPPRESS_USE_F, and LOG_EVENT_SKIP_REPLICATION_F for notes. */ uint16 flags; /** true <=> this event 'owns' temp_buf and should call my_free() when done with it */ bool event_owns_temp_buf; enum_event_cache_type cache_type; /** A storage to cache the global system variable's value. Handling of a separate event will be governed its member. */ enum_slave_exec_mode slave_exec_mode; #ifdef MYSQL_SERVER THD* thd; Log_event(); Log_event(THD* thd_arg, uint16 flags_arg, bool is_transactional); /* init_show_field_list() prepares the column names and types for the output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG EVENTS. */ static void init_show_field_list(THD *thd, List<Item>* field_list); #ifdef HAVE_REPLICATION int net_send(Protocol *protocol, const char* log_name, my_off_t pos); /* pack_info() is used by SHOW BINLOG EVENTS; as print() it prepares and sends a string to display to the user, so it resembles print(). */ virtual void pack_info(Protocol *protocol); #endif /* HAVE_REPLICATION */ virtual const char* get_db() { return thd ? thd->db.str : 0; } #else Log_event() : temp_buf(0), when(0), flags(0) {} /* The checksum algorithm used (if any) when the event was read. */ enum_binlog_checksum_alg read_checksum_alg; ha_checksum read_checksum_value; /* print*() functions are used by mysqlbinlog */ virtual bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0; bool print_timestamp(IO_CACHE* file, time_t *ts = 0); bool print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more); bool print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool do_print_encoded); #endif /* MYSQL_SERVER */ /* The following code used for Flashback */ #ifdef MYSQL_CLIENT my_bool is_flashback; my_bool need_flashback_review; String output_buf; // Storing the event output #ifdef WHEN_FLASHBACK_REVIEW_READY String m_review_dbname; String m_review_tablename; void set_review_dbname(const char *name) { if (name) { m_review_dbname.free(); m_review_dbname.append(name); } } void set_review_tablename(const char *name) { if (name) { m_review_tablename.free(); m_review_tablename.append(name); } } const char *get_review_dbname() const { return m_review_dbname.ptr(); } const char *get_review_tablename() const { return m_review_tablename.ptr(); } #endif #endif private: static size_t get_max_packet() { size_t max_packet= ~0UL; #if !defined(MYSQL_CLIENT) THD *thd=current_thd; if (thd) max_packet= thd->slave_thread ? slave_max_allowed_packet : thd->variables.max_allowed_packet; #endif return max_packet; } public: /* read_log_event() functions read an event from a binlog or relay log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the master (reads master's binlog), the slave IO thread (reads the event sent by binlog_dump), the slave SQL thread (reads the event from the relay log). If mutex is 0, the read will proceed without mutex. We need the description_event to be able to parse the event (to know the post-header's size); in fact in read_log_event we detect the event's type, then call the specific event's constructor and pass description_event as an argument. */ static Log_event* read_log_event(IO_CACHE* file, int *out_error, const Format_description_log_event *description_event, my_bool crc_check, my_bool print_errors, size_t max_allowed_packet); static Log_event* read_log_event(IO_CACHE* file, int *out_error, const Format_description_log_event *description_event, my_bool crc_check, my_bool print_errors= 1) { return read_log_event(file, out_error, description_event, crc_check, print_errors, get_max_packet()); } /** Reads an event from a binlog or relay log. Used by the dump thread this method reads the event into a raw buffer without parsing it. @Note If mutex is 0, the read will proceed without mutex. @Note If a log name is given than the method will check if the given binlog is still active. @param[in] file log file to be read @param[out] packet packet to hold the event @param[in] checksum_alg_arg verify the event checksum using this algorithm (or don't if it's use BINLOG_CHECKSUM_ALG_OFF) @retval 0 success @retval LOG_READ_EOF end of file, nothing was read @retval LOG_READ_BOGUS malformed event @retval LOG_READ_IO io error while reading @retval LOG_READ_MEM packet memory allocation failed @retval LOG_READ_TRUNC only a partial event could be read @retval LOG_READ_TOO_LARGE event too large */ static int read_log_event(IO_CACHE* file, String* packet, const Format_description_log_event *fdle, enum enum_binlog_checksum_alg checksum_alg_arg, size_t max_allowed_packet); static int read_log_event(IO_CACHE* file, String* packet, const Format_description_log_event *fdle, enum enum_binlog_checksum_alg checksum_alg) { return read_log_event(file, packet, fdle, checksum_alg, get_max_packet()); } static void *operator new(size_t size) { extern PSI_memory_key key_memory_log_event; return my_malloc(key_memory_log_event, size, MYF(MY_WME|MY_FAE)); } static void operator delete(void *ptr, size_t) { my_free(ptr); } /* Placement version of the above operators */ static void *operator new(size_t, void* ptr) { return ptr; } static void operator delete(void*, void*) { } #ifdef MYSQL_SERVER bool write_header(Log_event_writer *writer, size_t event_data_length); bool write_data(Log_event_writer *writer, const uchar *buf, size_t data_length) { return writer->write_data(buf, data_length); } bool write_data(Log_event_writer *writer, const char *buf, size_t data_length) { return write_data(writer, (uchar*)buf, data_length); } bool write_footer(Log_event_writer *writer) { return writer->write_footer(); } enum_binlog_checksum_alg select_checksum_alg(const binlog_cache_data *data); virtual bool write(Log_event_writer *writer) { return write_header(writer, get_data_size()) || write_data_header(writer) || write_data_body(writer) || write_footer(writer); } virtual bool write_data_header(Log_event_writer *writer) { return 0; } virtual bool write_data_body(Log_event_writer *writer) { return 0; } /* Return start of query time or current time */ inline my_time_t get_time() { THD *tmp_thd; if (when) return when; if (thd) { when= thd->start_time; when_sec_part= thd->start_time_sec_part; return when; } /* thd will only be 0 here at time of log creation */ if ((tmp_thd= current_thd)) { when= tmp_thd->start_time; when_sec_part= tmp_thd->start_time_sec_part; return when; } my_hrtime_t hrtime= my_hrtime(); when= hrtime_to_my_time(hrtime); when_sec_part= hrtime_sec_part(hrtime); return when; } #endif virtual Log_event_type get_type_code() = 0; virtual enum_logged_status logged_status() { return LOGGED_CRITICAL; } virtual bool is_valid() const = 0; virtual my_off_t get_header_len(my_off_t len) { return len; } void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; } void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; } bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; } bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; } inline bool use_trans_cache() const { return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE); } inline void set_direct_logging() { cache_type = Log_event::EVENT_NO_CACHE; } inline bool use_direct_logging() { return (cache_type == Log_event::EVENT_NO_CACHE); } Log_event(const uchar *buf, const Format_description_log_event *description_event); virtual ~Log_event() { free_temp_buf();} void register_temp_buf(uchar* buf, bool must_free) { temp_buf= buf; event_owns_temp_buf= must_free; } void free_temp_buf() { if (temp_buf) { if (event_owns_temp_buf) my_free(temp_buf); temp_buf = 0; } } /* Get event length for simple events. For complicated events the length is calculated during write() */ virtual int get_data_size() { return 0;} static Log_event* read_log_event(const uchar *buf, uint event_len, const char **error, const Format_description_log_event *description_event, my_bool crc_check, my_bool print_errors= 1); /** Returns the human readable name of the given event type. */ static const char* get_type_str(Log_event_type type); /** Returns the human readable name of this event's type. */ const char* get_type_str(); #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) /** Increase or decrease the rows inserted during ALTER TABLE based on the event type. */ virtual void online_alter_update_row_count(ha_rows *) const {} /** Apply the event to the database. This function represents the public interface for applying an event. @see do_apply_event */ int apply_event(rpl_group_info *rgi); /** Update the relay log position. This function represents the public interface for "stepping over" the event and will update the relay log information. @see do_update_pos */ int update_pos(rpl_group_info *rgi) { return do_update_pos(rgi); } /** Decide if the event shall be skipped, and the reason for skipping it. @see do_shall_skip */ enum_skip_reason shall_skip(rpl_group_info *rgi) { return do_shall_skip(rgi); } /* Check if an event is non-final part of a stand-alone event group, such as Intvar_log_event (such events should be processed as part of the following event group, not individually). See also is_part_of_group() */ static bool is_part_of_group(enum Log_event_type ev_type) { switch (ev_type) { case GTID_EVENT: case INTVAR_EVENT: case RAND_EVENT: case USER_VAR_EVENT: case TABLE_MAP_EVENT: case ANNOTATE_ROWS_EVENT: return true; case DELETE_ROWS_EVENT: case UPDATE_ROWS_EVENT: case WRITE_ROWS_EVENT: /* ToDo: also check for non-final Rows_log_event (though such events are usually in a BEGIN-COMMIT group). */ default: return false; } } /* Same as above, but works on the object. In addition this is true for all rows event except the last one. */ virtual bool is_part_of_group() { return 0; } static bool is_group_event(enum Log_event_type ev_type) { switch (ev_type) { case START_EVENT_V3: case STOP_EVENT: case ROTATE_EVENT: case SLAVE_EVENT: case FORMAT_DESCRIPTION_EVENT: case INCIDENT_EVENT: case HEARTBEAT_LOG_EVENT: case BINLOG_CHECKPOINT_EVENT: case GTID_LIST_EVENT: case START_ENCRYPTION_EVENT: return false; default: return true; } } protected: /** Helper function to ignore an event w.r.t. the slave skip counter. This function can be used inside do_shall_skip() for functions that cannot end a group. If the slave skip counter is 1 when seeing such an event, the event shall be ignored, the counter left intact, and processing continue with the next event. A typical usage is: @code enum_skip_reason do_shall_skip(rpl_group_info *rgi) { return continue_group(rgi); } @endcode @return Skip reason */ enum_skip_reason continue_group(rpl_group_info *rgi); /** Primitive to apply an event to the database. This is where the change to the database is made. @note The primitive is protected instead of private, since there is a hierarchy of actions to be performed in some cases. @see Format_description_log_event::do_apply_event() @param rli Pointer to relay log info structure @retval 0 Event applied successfully @retval errno Error code if event application failed */ virtual int do_apply_event(rpl_group_info *rgi) { return 0; /* Default implementation does nothing */ } /** Advance relay log coordinates. This function is called to advance the relay log coordinates to just after the event. It is essential that both the relay log coordinate and the group log position is updated correctly, since this function is used also for skipping events. Normally, each implementation of do_update_pos() shall: - Update the event position to refer to the position just after the event. - Update the group log position to refer to the position just after the event <em>if the event is last in a group</em> @param rli Pointer to relay log info structure @retval 0 Coordinates changed successfully @retval errno Error code if advancing failed (usually just 1). Observe that handler errors are returned by the do_apply_event() function, and not by this one. */ virtual int do_update_pos(rpl_group_info *rgi); /** Decide if this event shall be skipped or not and the reason for skipping it. The default implementation decide that the event shall be skipped if either: - the server id of the event is the same as the server id of the server and <code>rli->replicate_same_server_id</code> is true, or - if <code>rli->slave_skip_counter</code> is greater than zero. @see do_apply_event @see do_update_pos @retval Log_event::EVENT_SKIP_NOT The event shall not be skipped and should be applied. @retval Log_event::EVENT_SKIP_IGNORE The event shall be skipped by just ignoring it, i.e., the slave skip counter shall not be changed. This happends if, for example, the originating server id of the event is the same as the server id of the slave. @retval Log_event::EVENT_SKIP_COUNT The event shall be skipped because the slave skip counter was non-zero. The caller shall decrease the counter by one. */ virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; /* One class for each type of event. Two constructors for each class: - one to create the event for logging (when the server acts as a master), called after an update to the database is done, which accepts parameters like the query, the database, the options for LOAD DATA INFILE... - one to create the event from a packet (when the server acts as a slave), called before reproducing the update, which accepts parameters (like a buffer). Used to read from the master, from the relay log, and in mysqlbinlog. This constructor must be format-tolerant. */ /** @class Query_log_event A @c Query_log_event is created for each query that modifies the database, unless the query is logged row-based. @section Query_log_event_binary_format Binary format See @ref Log_event_binary_format "Binary format for log events" for a general discussion and introduction to the binary format of binlog events. The Post-Header has five components: <table> <caption>Post-Header for Query_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>slave_proxy_id</td> <td>4 byte unsigned integer</td> <td>An integer identifying the client thread that issued the query. The id is unique per server. (Note, however, that two threads on different servers may have the same slave_proxy_id.) This is used when a client thread creates a temporary table local to the client. The slave_proxy_id is used to distinguish temporary tables that belong to different clients. </td> </tr> <tr> <td>exec_time</td> <td>4 byte unsigned integer</td> <td>The time from when the query started to when it was logged in the binlog, in seconds.</td> </tr> <tr> <td>db_len</td> <td>1 byte integer</td> <td>The length of the name of the currently selected database.</td> </tr> <tr> <td>error_code</td> <td>2 byte unsigned integer</td> <td>Error code generated by the master. If the master fails, the slave will fail with the same error code, except for the error codes ER_DB_CREATE_EXISTS == 1007 and ER_DB_DROP_EXISTS == 1008. </td> </tr> <tr> <td>status_vars_len</td> <td>2 byte unsigned integer</td> <td>The length of the status_vars block of the Body, in bytes. See @ref query_log_event_status_vars "below". </td> </tr> </table> The Body has the following components: <table> <caption>Body for Query_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>@anchor query_log_event_status_vars status_vars</td> <td>status_vars_len bytes</td> <td>Zero or more status variables. Each status variable consists of one byte identifying the variable stored, followed by the value of the variable. The possible variables are listed separately in the table @ref Table_query_log_event_status_vars "below". MySQL always writes events in the order defined below; however, it is capable of reading them in any order. </td> </tr> <tr> <td>db</td> <td>db_len+1</td> <td>The currently selected database, as a null-terminated string. (The trailing zero is redundant since the length is already known; it is db_len from Post-Header.) </td> </tr> <tr> <td>query</td> <td>variable length string without trailing zero, extending to the end of the event (determined by the length field of the Common-Header) </td> <td>The SQL query.</td> </tr> </table> The following table lists the status variables that may appear in the status_vars field. @anchor Table_query_log_event_status_vars <table> <caption>Status variables for Query_log_event</caption> <tr> <th>Status variable</th> <th>1 byte identifier</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>flags2</td> <td>Q_FLAGS2_CODE == 0</td> <td>4 byte bitfield</td> <td>The flags in @c thd->options, binary AND-ed with @c OPTIONS_WRITTEN_TO_BIN_LOG. The @c thd->options bitfield contains options for "SELECT". @c OPTIONS_WRITTEN identifies those options that need to be written to the binlog (not all do). These flags correspond to the SQL variables SQL_AUTO_IS_NULL, FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, and AUTOCOMMIT, documented in the "SET Syntax" section of the MySQL Manual. This field is always written to the binlog in version >= 5.0, and never written in version < 5.0. </td> </tr> <tr> <td>sql_mode</td> <td>Q_SQL_MODE_CODE == 1</td> <td>8 byte bitfield</td> <td>The @c sql_mode variable. See the section "SQL Modes" in the MySQL manual, and see sql_priv.h for a list of the possible flags. Currently (2007-10-04), the following flags are available: <pre> MODE_REAL_AS_FLOAT==0x1 MODE_PIPES_AS_CONCAT==0x2 MODE_ANSI_QUOTES==0x4 MODE_IGNORE_SPACE==0x8 MODE_IGNORE_BAD_TABLE_OPTIONS==0x10 MODE_ONLY_FULL_GROUP_BY==0x20 MODE_NO_UNSIGNED_SUBTRACTION==0x40 MODE_NO_DIR_IN_CREATE==0x80 MODE_POSTGRESQL==0x100 MODE_ORACLE==0x200 MODE_MSSQL==0x400 MODE_DB2==0x800 MODE_MAXDB==0x1000 MODE_NO_KEY_OPTIONS==0x2000 MODE_NO_TABLE_OPTIONS==0x4000 MODE_NO_FIELD_OPTIONS==0x8000 MODE_MYSQL323==0x10000 MODE_MYSQL323==0x20000 MODE_MYSQL40==0x40000 MODE_ANSI==0x80000 MODE_NO_AUTO_VALUE_ON_ZERO==0x100000 MODE_NO_BACKSLASH_ESCAPES==0x200000 MODE_STRICT_TRANS_TABLES==0x400000 MODE_STRICT_ALL_TABLES==0x800000 MODE_NO_ZERO_IN_DATE==0x1000000 MODE_NO_ZERO_DATE==0x2000000 MODE_INVALID_DATES==0x4000000 MODE_ERROR_FOR_DIVISION_BY_ZERO==0x8000000 MODE_TRADITIONAL==0x10000000 MODE_NO_AUTO_CREATE_USER==0x20000000 MODE_HIGH_NOT_PRECEDENCE==0x40000000 MODE_PAD_CHAR_TO_FULL_LENGTH==0x80000000 </pre> All these flags are replicated from the server. However, all flags except @c MODE_NO_DIR_IN_CREATE are honored by the slave; the slave always preserves its old value of @c MODE_NO_DIR_IN_CREATE. For a rationale, see comment in @c Query_log_event::do_apply_event in @c log_event.cc. This field is always written to the binlog. </td> </tr> <tr> <td>catalog</td> <td>Q_CATALOG_NZ_CODE == 6</td> <td>Variable-length string: the length in bytes (1 byte) followed by the characters (at most 255 bytes) </td> <td>Stores the client's current catalog. Every database belongs to a catalog, the same way that every table belongs to a database. Currently, there is only one catalog, "std". This field is written if the length of the catalog is > 0; otherwise it is not written. </td> </tr> <tr> <td>auto_increment</td> <td>Q_AUTO_INCREMENT == 3</td> <td>two 2 byte unsigned integers, totally 2+2=4 bytes</td> <td>The two variables auto_increment_increment and auto_increment_offset, in that order. For more information, see "System variables" in the MySQL manual. This field is written if auto_increment > 1. Otherwise, it is not written. </td> </tr> <tr> <td>charset</td> <td>Q_CHARSET_CODE == 4</td> <td>three 2 byte unsigned integers, totally 2+2+2=6 bytes</td> <td>The three variables character_set_client, collation_connection, and collation_server, in that order. character_set_client is a code identifying the character set and collation used by the client to encode the query. collation_connection identifies the character set and collation that the master converts the query to when it receives it; this is useful when comparing literal strings. collation_server is the default character set and collation used when a new database is created. See also "Connection Character Sets and Collations" in the MySQL 5.1 manual. All three variables are codes identifying a (character set, collation) pair. To see which codes map to which pairs, run the query "SELECT id, character_set_name, collation_name FROM COLLATIONS". Cf. Q_CHARSET_DATABASE_CODE below. This field is always written. </td> </tr> <tr> <td>time_zone</td> <td>Q_TIME_ZONE_CODE == 5</td> <td>Variable-length string: the length in bytes (1 byte) followed by the characters (at most 255 bytes). <td>The time_zone of the master. See also "System Variables" and "MySQL Server Time Zone Support" in the MySQL manual. This field is written if the length of the time zone string is > 0; otherwise, it is not written. </td> </tr> <tr> <td>lc_time_names_number</td> <td>Q_LC_TIME_NAMES_CODE == 7</td> <td>2 byte integer</td> <td>A code identifying a table of month and day names. The mapping from codes to languages is defined in @c sql_locale.cc. This field is written if it is not 0, i.e., if the locale is not en_US. </td> </tr> <tr> <td>charset_database_number</td> <td>Q_CHARSET_DATABASE_CODE == 8</td> <td>2 byte integer</td> <td>The value of the collation_database system variable (in the source code stored in @c thd->variables.collation_database), which holds the code for a (character set, collation) pair as described above (see Q_CHARSET_CODE). collation_database was used in old versions (???WHEN). Its value was loaded when issuing a "use db" query and could be changed by issuing a "SET collation_database=xxx" query. It used to affect the "LOAD DATA INFILE" and "CREATE TABLE" commands. In newer versions, "CREATE TABLE" has been changed to take the character set from the database of the created table, rather than the character set of the current database. This makes a difference when creating a table in another database than the current one. "LOAD DATA INFILE" has not yet changed to do this, but there are plans to eventually do it, and to make collation_database read-only. This field is written if it is not 0. </td> </tr> <tr> <td>table_map_for_update</td> <td>Q_TABLE_MAP_FOR_UPDATE_CODE == 9</td> <td>8 byte integer</td> <td>The value of the table map that is to be updated by the multi-table update query statement. Every bit of this variable represents a table, and is set to 1 if the corresponding table is to be updated by this statement. The value of this variable is set when executing a multi-table update statement and used by slave to apply filter rules without opening all the tables on slave. This is required because some tables may not exist on slave because of the filter rules. </td> </tr> </table> @subsection Query_log_event_notes_on_previous_versions Notes on Previous Versions * Status vars were introduced in version 5.0. To read earlier versions correctly, check the length of the Post-Header. * The status variable Q_CATALOG_CODE == 2 existed in MySQL 5.0.x, where 0<=x<=3. It was identical to Q_CATALOG_CODE, except that the string had a trailing '\0'. The '\0' was removed in 5.0.4 since it was redundant (the string length is stored before the string). The Q_CATALOG_CODE will never be written by a new master, but can still be understood by a new slave. * See Q_CHARSET_DATABASE_CODE in the table above. * When adding new status vars, please don't forget to update the MAX_SIZE_LOG_EVENT_STATUS, and update function code_name */ class Query_log_event: public Log_event { LEX_CSTRING user; LEX_CSTRING host; protected: Log_event::Byte* data_buf; public: const char* query; const char* catalog; const char* db; /* If we already know the length of the query string we pass it with q_len, so we would not have to call strlen() otherwise, set it to 0, in which case, we compute it with strlen() */ uint32 q_len; uint32 db_len; uint16 error_code; my_thread_id thread_id; /* For events created by Query_log_event::do_apply_event we need the *original* thread id, to be able to log the event with the original (=master's) thread id (fix for BUG#1686). */ ulong slave_proxy_id; /* Binlog format 3 and 4 start to differ (as far as class members are concerned) from here. */ uint catalog_len; // <= 255 char; 0 means uninited /* We want to be able to store a variable number of N-bit status vars: (generally N=32; but N=64 for SQL_MODE) a user may want to log the number of affected rows (for debugging) while another does not want to lose 4 bytes in this. The storage on disk is the following: status_vars_len is part of the post-header, status_vars are in the variable-length part, after the post-header, before the db & query. status_vars on disk is a sequence of pairs (code, value) where 'code' means 'sql_mode', 'affected' etc. Sometimes 'value' must be a short string, so its first byte is its length. For now the order of status vars is: flags2 - sql_mode - catalog - autoinc - charset */ uint16 status_vars_len; /* 'flags2' is a second set of flags (on top of those in Log_event), for session variables. These are thd->options which is & against a mask (OPTIONS_WRITTEN_TO_BIN_LOG). flags2_inited helps make a difference between flags2==0 (3.23 or 4.x master, we don't know flags2, so use the slave server's global options) and flags2==0 (5.0 master, we know this has a meaning of flags all down which must influence the query). */ uint32 flags2_inited; bool sql_mode_inited; bool charset_inited; LEX_CSTRING character_set_collations; uint32 flags2; sql_mode_t sql_mode; ulong auto_increment_increment, auto_increment_offset; char charset[6]; uint time_zone_len; /* 0 means uninited */ const char *time_zone_str; uint lc_time_names_number; /* 0 means en_US */ uint charset_database_number; /* map for tables that will be updated for a multi-table update query statement, for other query statements, this will be zero. */ ulonglong table_map_for_update; /* Xid for the event, if such exists */ ulonglong xid; /* A copy of Gtid event's extra flags that is relevant for two-phase logged ALTER. */ uchar gtid_flags_extra; decltype(rpl_gtid::seq_no) sa_seq_no; /* data part for CA/RA flags */ #ifdef MYSQL_SERVER Query_log_event(THD* thd_arg, const char* query_arg, size_t query_length, bool using_trans, bool direct, bool suppress_use, int error); const char* get_db() override { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info); bool print_verbose(IO_CACHE* cache, PRINT_EVENT_INFO* print_event_info); bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Query_log_event(); Query_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event, Log_event_type event_type); ~Query_log_event() { if (data_buf) my_free(data_buf); } Log_event_type get_type_code() override { return QUERY_EVENT; } static int dummy_event(String *packet, ulong ev_offset, enum_binlog_checksum_alg checksum_alg); static int begin_event(String *packet, ulong ev_offset, enum_binlog_checksum_alg checksum_alg); #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; virtual bool write_post_header_for_derived(Log_event_writer *writer) { return FALSE; } #endif bool is_valid() const override { return query != 0; } /* Returns number of bytes additionally written to post header by derived events (so far it is only Execute_load_query event). */ virtual ulong get_post_header_size_for_derived() { return 0; } /* Writes derived event-specific part of post header. */ public: /* !!! Public in this patch to allow old usage */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; int do_apply_event(rpl_group_info *rgi) override; int do_apply_event(rpl_group_info *rgi, const char *query_arg, uint32 q_len_arg); static bool peek_is_commit_rollback(const uchar *event_start, size_t event_len, enum_binlog_checksum_alg checksum_alg); int handle_split_alter_query_log_event(rpl_group_info *rgi, bool &skip_error_check); #endif /* HAVE_REPLICATION */ /* If true, the event always be applied by slave SQL thread or be printed by mysqlbinlog */ bool is_trans_keyword(bool is_xa) { /* Before the patch for bug#50407, The 'SAVEPOINT and ROLLBACK TO' queries input by user was written into log events directly. So the keywords can be written in both upper case and lower case together, strncasecmp is used to check both cases. they also could be binlogged with comments in the front of these keywords. for examples: / * bla bla * / SAVEPOINT a; / * bla bla * / ROLLBACK TO a; but we don't handle these cases and after the patch, both quiries are binlogged in upper case with no comments. */ return is_xa ? !strncasecmp(query, C_STRING_WITH_LEN("XA ")) : (!strncmp(query, "BEGIN", q_len) || !strncmp(query, "COMMIT", q_len) || !strncasecmp(query, "SAVEPOINT", 9) || !strncasecmp(query, "ROLLBACK", 8)); } virtual bool is_begin() { return !strcmp(query, "BEGIN"); } virtual bool is_commit() { return !strcmp(query, "COMMIT"); } virtual bool is_rollback() { return !strcmp(query, "ROLLBACK"); } }; class Query_compressed_log_event:public Query_log_event{ protected: Log_event::Byte* query_buf; // point to the uncompressed query public: Query_compressed_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event, Log_event_type event_type); ~Query_compressed_log_event() { if (query_buf) my_free(query_buf); } Log_event_type get_type_code() override { return QUERY_COMPRESSED_EVENT; } /* the min length of log_bin_compress_min_len is 10, means that Begin/Commit/Rollback would never be compressed! */ bool is_begin() override { return false; } bool is_commit() override { return false; } bool is_rollback() override { return false; } #ifdef MYSQL_SERVER Query_compressed_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool direct, bool suppress_use, int error); bool write(Log_event_writer *writer) override; #endif }; /***************************************************************************** sql_ex_info struct ****************************************************************************/ struct sql_ex_info { const char* field_term; const char* enclosed; const char* line_term; const char* line_start; const char* escaped; int cached_new_format= -1; uint8 field_term_len= 0, enclosed_len= 0, line_term_len= 0, line_start_len= 0, escaped_len= 0; char opt_flags; char empty_flags= 0; // store in new format even if old is possible void force_new_format() { cached_new_format = 1;} int data_size() { return (new_format() ? field_term_len + enclosed_len + line_term_len + line_start_len + escaped_len + 6 : 7); } bool write_data(Log_event_writer *writer); const uchar *init(const uchar *buf, const uchar* buf_end, bool use_new_format); bool new_format() { return ((cached_new_format != -1) ? cached_new_format : (cached_new_format=(field_term_len > 1 || enclosed_len > 1 || line_term_len > 1 || line_start_len > 1 || escaped_len > 1))); } }; /** @class Start_encryption_log_event Start_encryption_log_event marks the beginning of encrypted data (all events after this event are encrypted). It contains the cryptographic scheme used for the encryption as well as any data required to decrypt (except the actual key). For binlog cryptoscheme 1: key version, and nonce for iv generation. */ class Start_encryption_log_event : public Log_event { public: #ifdef MYSQL_SERVER Start_encryption_log_event(uint crypto_scheme_arg, uint key_version_arg, const uchar* nonce_arg) : crypto_scheme(crypto_scheme_arg), key_version(key_version_arg) { cache_type = EVENT_NO_CACHE; DBUG_ASSERT(crypto_scheme == 1); memcpy(nonce, nonce_arg, BINLOG_NONCE_LENGTH); } bool write_data_body(Log_event_writer *writer) override { uchar scheme_buf= crypto_scheme; uchar key_version_buf[BINLOG_KEY_VERSION_LENGTH]; int4store(key_version_buf, key_version); return write_data(writer, &scheme_buf, sizeof(scheme_buf)) || write_data(writer, key_version_buf, sizeof(key_version_buf)) || write_data(writer, nonce, BINLOG_NONCE_LENGTH); } #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Start_encryption_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); bool is_valid() const override { return crypto_scheme == 1; } Log_event_type get_type_code() override { return START_ENCRYPTION_EVENT; } int get_data_size() override { return BINLOG_CRYPTO_SCHEME_LENGTH + BINLOG_KEY_VERSION_LENGTH + BINLOG_NONCE_LENGTH; } uint crypto_scheme; uint key_version; uchar nonce[BINLOG_NONCE_LENGTH]; protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info* rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info* rgi) override { return Log_event::EVENT_SKIP_NOT; } #endif }; class Version { protected: uchar m_ver[3]; int cmp(const Version &other) const { return memcmp(m_ver, other.m_ver, 3); } public: Version() { m_ver[0]= m_ver[1]= m_ver[2]= '\0'; } Version(uchar v0, uchar v1, uchar v2) { m_ver[0]= v0; m_ver[1]= v1; m_ver[2]= v2; } Version(const char *version, const char **endptr); const uchar& operator [] (size_t i) const { DBUG_ASSERT(i < 3); return m_ver[i]; } bool operator<(const Version &other) const { return cmp(other) < 0; } bool operator>(const Version &other) const { return cmp(other) > 0; } bool operator<=(const Version &other) const { return cmp(other) <= 0; } bool operator>=(const Version &other) const { return cmp(other) >= 0; } }; /** @class Format_description_log_event For binlog version 4. This event is saved by threads which read it, as they need it for future use (to decode the ordinary events). @section Format_description_log_event_binary_format Binary Format */ class Format_description_log_event: public Log_event { public: /* If this event is at the start of the first binary log since server startup 'created' should be the timestamp when the event (and the binary log) was created. In the other case (i.e. this event is at the start of a binary log created by FLUSH LOGS or automatic rotation), 'created' should be 0. This "trick" is used by MySQL >=4.0.14 slaves to know whether they must drop stale temporary tables and whether they should abort unfinished transaction. Note that when 'created'!=0, it is always equal to the event's timestamp; indeed Start_log_event is written only in log.cc where the first constructor below is called, in which 'created' is set to 'when'. So in fact 'created' is a useless variable. When it is 0 we can read the actual value from timestamp ('when') and when it is non-zero we can read the same value from timestamp ('when'). Conclusion: - we use timestamp to print when the binlog was created. - we use 'created' only to know if this is a first binlog or not. In 3.23.57 we did not pay attention to this identity, so mysqlbinlog in 3.23.57 does not print 'created the_date' if created was zero. This is now fixed. */ time_t created; uint16 binlog_version; char server_version[ST_SERVER_VER_LEN]; /* We set this to 1 if we don't want to have the created time in the log, which is the case when we rollover to a new log. */ bool dont_set_created; /* The size of the fixed header which _all_ events have (for binlogs written by this version, this is equal to LOG_EVENT_HEADER_LEN), except FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT (those have a header of size LOG_EVENT_MINIMAL_HEADER_LEN). */ uint8 common_header_len; uint8 number_of_event_types; /* The list of post-headers' lengths followed by the checksum alg description byte */ uint8 *post_header_len; class master_version_split: public Version { public: enum {KIND_MYSQL, KIND_MARIADB}; int kind; master_version_split() :kind(KIND_MARIADB) { } master_version_split(const char *version); bool version_is_valid() const { /* It is invalid only when all version numbers are 0 */ return !(m_ver[0] == 0 && m_ver[1] == 0 && m_ver[2] == 0); } }; master_version_split server_version_split; const uint8 *event_type_permutation; uint32 options_written_to_bin_log; /* The checksum algorithm used in the binlog or relaylog following this Format_description_event. Or BINLOG_CHECKSUM_ALG_UNDEF for a Format_description_event which is not part of a binlog or relaylog file. */ enum_binlog_checksum_alg used_checksum_alg; Format_description_log_event(uint8 binlog_ver, const char* server_ver= 0, enum_binlog_checksum_alg checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF); Format_description_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Format_description_log_event() { my_free(post_header_len); } Log_event_type get_type_code() override { return FORMAT_DESCRIPTION_EVENT;} my_off_t get_header_len(my_off_t) override { return LOG_EVENT_MINIMAL_HEADER_LEN; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif bool header_is_valid() const { return common_header_len >= LOG_EVENT_MINIMAL_HEADER_LEN && post_header_len; } bool is_valid() const override { return header_is_valid() && server_version_split.version_is_valid(); } int get_data_size() override { /* The vector of post-header lengths is considered as part of the post-header, because in a given version it never changes (contrary to the query in a Query_log_event). */ return FORMAT_DESCRIPTION_HEADER_LEN; } Binlog_crypt_data crypto_data; bool start_decryption(Start_encryption_log_event* sele); void copy_crypto_data(const Format_description_log_event* o) { crypto_data= o->crypto_data; } void reset_crypto() { crypto_data.scheme= 0; } void calc_server_version_split(); void deduct_options_written_to_bin_log(); static bool is_version_before_checksum(const master_version_split *version_split); protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; /** @class Intvar_log_event An Intvar_log_event will be created just before a Query_log_event, if the query uses one of the variables LAST_INSERT_ID or INSERT_ID. Each Intvar_log_event holds the value of one of these variables. @section Intvar_log_event_binary_format Binary Format The Post-Header for this event type is empty. The Body has two components: <table> <caption>Body for Intvar_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>type</td> <td>1 byte enumeration</td> <td>One byte identifying the type of variable stored. Currently, two identifiers are supported: LAST_INSERT_ID_EVENT==1 and INSERT_ID_EVENT==2. </td> </tr> <tr> <td>value</td> <td>8 byte unsigned integer</td> <td>The value of the variable.</td> </tr> </table> */ class Intvar_log_event: public Log_event { public: ulonglong val; uchar type; #ifdef MYSQL_SERVER Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg, bool using_trans, bool direct) :Log_event(thd_arg,0,using_trans),val(val_arg),type(type_arg) { if (direct) cache_type= Log_event::EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Intvar_log_event(const uchar *buf, const Format_description_log_event *description_event); ~Intvar_log_event() = default; Log_event_type get_type_code() override { return INTVAR_EVENT;} const char* get_var_type_name(); int get_data_size() override { return 9; /* sizeof(type) + sizeof(val) */;} #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #ifdef HAVE_REPLICATION bool is_part_of_group() override { return 1; } #endif #endif bool is_valid() const override { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; /** @class Rand_log_event Logs random seed used by the next RAND(), and by PASSWORD() in 4.1.0. 4.1.1 does not need it (it's repeatable again) so this event needn't be written in 4.1.1 for PASSWORD() (but the fact that it is written is just a waste, it does not cause bugs). The state of the random number generation consists of 128 bits, which are stored internally as two 64-bit numbers. @section Rand_log_event_binary_format Binary Format The Post-Header for this event type is empty. The Body has two components: <table> <caption>Body for Rand_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>seed1</td> <td>8 byte unsigned integer</td> <td>64 bit random seed1.</td> </tr> <tr> <td>seed2</td> <td>8 byte unsigned integer</td> <td>64 bit random seed2.</td> </tr> </table> */ class Rand_log_event: public Log_event { public: ulonglong seed1; ulonglong seed2; #ifdef MYSQL_SERVER Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg, bool using_trans, bool direct) :Log_event(thd_arg,0,using_trans),seed1(seed1_arg),seed2(seed2_arg) { if (direct) cache_type= Log_event::EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Rand_log_event(const uchar *buf, const Format_description_log_event *description_event); ~Rand_log_event() = default; Log_event_type get_type_code() override { return RAND_EVENT;} int get_data_size() override { return 16; /* sizeof(ulonglong) * 2*/ } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #ifdef HAVE_REPLICATION bool is_part_of_group() override { return 1; } #endif #endif bool is_valid() const override { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; class Xid_apply_log_event: public Log_event { public: #ifdef MYSQL_SERVER Xid_apply_log_event(THD* thd_arg): Log_event(thd_arg, 0, TRUE) {} #endif Xid_apply_log_event(const uchar *buf, const Format_description_log_event *description_event): Log_event(buf, description_event) {} ~Xid_apply_log_event() = default; bool is_valid() const override { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual int do_commit()= 0; int do_apply_event(rpl_group_info *rgi) override; int do_record_gtid(THD *thd, rpl_group_info *rgi, bool in_trans, void **out_hton, bool force_err= false); enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; virtual const char* get_query()= 0; #endif }; /** @class Xid_log_event Logs xid of the transaction-to-be-committed in the 2pc protocol. Has no meaning in replication, slaves ignore it. @section Xid_log_event_binary_format Binary Format */ #ifdef MYSQL_CLIENT typedef ulonglong my_xid; // this line is the same as in handler.h #endif class Xid_log_event: public Xid_apply_log_event { public: my_xid xid; #ifdef MYSQL_SERVER Xid_log_event(THD* thd_arg, my_xid x, bool direct): Xid_apply_log_event(thd_arg), xid(x) { if (direct) cache_type= Log_event::EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION const char* get_query() override { return "COMMIT /* implicit, from Xid_log_event */"; } void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Xid_log_event(const uchar *buf, const Format_description_log_event *description_event); ~Xid_log_event() = default; Log_event_type get_type_code() override { return XID_EVENT;} int get_data_size() override { return sizeof(xid); } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_commit() override; #endif }; /** @class XA_prepare_log_event Similar to Xid_log_event except that - it is specific to XA transaction - it carries out the prepare logics rather than the final committing when @c one_phase member is off. The latter option is only for compatibility with the upstream. From the groupping perspective the event finalizes the current "prepare" group that is started with Gtid_log_event similarly to the regular replicated transaction. */ /** Function serializes XID which is characterized by by four last arguments of the function. Serialized XID is presented in valid hex format and is returned to the caller in a buffer pointed by the first argument. The buffer size provived by the caller must be not less than 8 + 2 * XIDDATASIZE + 4 * sizeof(XID::formatID) + 1, see {MYSQL_,}XID definitions. @param buf pointer to a buffer allocated for storing serialized data @param fmt formatID value @param gln gtrid_length value @param bln bqual_length value @param dat data value @return the value of the buffer pointer */ inline char *serialize_xid(char *buf, long fmt, long gln, long bln, const char *dat) { int i; char *c= buf; /* Build a string consisting of the hex format representation of XID as passed through fmt,gln,bln,dat argument: X'hex11hex12...hex1m',X'hex21hex22...hex2n',11 and store it into buf. */ c[0]= 'X'; c[1]= '\''; c+= 2; for (i= 0; i < gln; i++) { c[0]=_dig_vec_lower[((uchar*) dat)[i] >> 4]; c[1]=_dig_vec_lower[((uchar*) dat)[i] & 0x0f]; c+= 2; } c[0]= '\''; c[1]= ','; c[2]= 'X'; c[3]= '\''; c+= 4; for (; i < gln + bln; i++) { c[0]=_dig_vec_lower[((uchar*) dat)[i] >> 4]; c[1]=_dig_vec_lower[((uchar*) dat)[i] & 0x0f]; c+= 2; } c[0]= '\''; sprintf(c+1, ",%lu", fmt); return buf; } /* The size of the string containing serialized Xid representation is computed as a sum of eight as the number of formatting symbols (X'',X'',) plus 2 x XIDDATASIZE (2 due to hex format), plus space for decimal digits of XID::formatID, plus one for 0x0. */ static const uint ser_buf_size= 8 + 2 * MYSQL_XIDDATASIZE + 4 * sizeof(long) + 1; struct event_mysql_xid_t : MYSQL_XID { char buf[ser_buf_size]; char *serialize() { return serialize_xid(buf, formatID, gtrid_length, bqual_length, data); } }; #ifndef MYSQL_CLIENT struct event_xid_t : XID { char buf[ser_buf_size]; char *serialize(char *buf_arg) { return serialize_xid(buf_arg, formatID, gtrid_length, bqual_length, data); } char *serialize() { return serialize(buf); } }; #endif class XA_prepare_log_event: public Xid_apply_log_event { protected: /* Constant contributor to subheader in write() by members of XID struct. */ static const int xid_subheader_no_data= 12; event_mysql_xid_t m_xid; void *xid; bool one_phase; public: #ifdef MYSQL_SERVER XA_prepare_log_event(THD* thd_arg, XID *xid_arg, bool one_phase_arg): Xid_apply_log_event(thd_arg), xid(xid_arg), one_phase(one_phase_arg) { cache_type= Log_event::EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif XA_prepare_log_event(const uchar *buf, const Format_description_log_event *description_event); ~XA_prepare_log_event() = default; Log_event_type get_type_code() override { return XA_PREPARE_LOG_EVENT; } bool is_valid() const override { return m_xid.formatID != -1; } int get_data_size() override { return xid_subheader_no_data + m_xid.gtrid_length + m_xid.bqual_length; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) char query[sizeof("XA COMMIT ONE PHASE") + 1 + ser_buf_size]; int do_commit() override; const char* get_query() override { sprintf(query, (one_phase ? "XA COMMIT %s ONE PHASE" : "XA PREPARE %s"), m_xid.serialize()); return query; } #endif }; /** @class User_var_log_event Every time a query uses the value of a user variable, a User_var_log_event is written before the Query_log_event, to set the user variable. @section User_var_log_event_binary_format Binary Format */ class User_var_log_event: public Log_event, public Log_event_data_type { public: const char *name; size_t name_len; const char *val; size_t val_len; bool is_null; #ifdef MYSQL_SERVER bool deferred; query_id_t query_id; User_var_log_event(THD* thd_arg, const char *name_arg, size_t name_len_arg, const char *val_arg, size_t val_len_arg, const Log_event_data_type &data_type, bool using_trans, bool direct) :Log_event(thd_arg, 0, using_trans), Log_event_data_type(data_type), name(name_arg), name_len(name_len_arg), val(val_arg), val_len(val_len_arg), deferred(false) { is_null= !val; if (direct) cache_type= Log_event::EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif User_var_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~User_var_log_event() = default; Log_event_type get_type_code() override { return USER_VAR_EVENT;} #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; /* Getter and setter for deferred User-event. Returns true if the event is not applied directly and which case the applier adjusts execution path. */ bool is_deferred() { return deferred; } /* In case of the deferred applying the variable instance is flagged and the parsing time query id is stored to be used at applying time. */ void set_deferred(query_id_t qid) { deferred= true; query_id= qid; } #ifdef HAVE_REPLICATION bool is_part_of_group() override { return 1; } #endif #endif bool is_valid() const override { return name != 0; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; /** @class Stop_log_event @section Stop_log_event_binary_format Binary Format The Post-Header and Body for this event type are empty; it only has the Common-Header. */ class Stop_log_event: public Log_event { public: #ifdef MYSQL_SERVER Stop_log_event() :Log_event() {} #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Stop_log_event(const uchar *buf, const Format_description_log_event *description_event): Log_event(buf, description_event) {} ~Stop_log_event() = default; Log_event_type get_type_code() override { return STOP_EVENT;} bool is_valid() const override { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override { /* Events from ourself should be skipped, but they should not decrease the slave skip counter. */ if (this->server_id == global_system_variables.server_id) return Log_event::EVENT_SKIP_IGNORE; else return Log_event::EVENT_SKIP_NOT; } #endif }; /** @class Rotate_log_event This will be deprecated when we move to using sequence ids. @section Rotate_log_event_binary_format Binary Format The Post-Header has one component: <table> <caption>Post-Header for Rotate_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>position</td> <td>8 byte integer</td> <td>The position within the binlog to rotate to.</td> </tr> </table> The Body has one component: <table> <caption>Body for Rotate_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>new_log</td> <td>variable length string without trailing zero, extending to the end of the event (determined by the length field of the Common-Header) </td> <td>Name of the binlog to rotate to.</td> </tr> </table> */ class Rotate_log_event: public Log_event { public: enum { DUP_NAME= 2, // if constructor should dup the string argument RELAY_LOG=4 // rotate event for relay log }; const char *new_log_ident; ulonglong pos; uint ident_len; uint flags; #ifdef MYSQL_SERVER Rotate_log_event(const char* new_log_ident_arg, uint ident_len_arg, ulonglong pos_arg, uint flags); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Rotate_log_event(const uchar *buf, uint event_len, const Format_description_log_event* description_event); ~Rotate_log_event() { if (flags & DUP_NAME) my_free((void*) new_log_ident); } Log_event_type get_type_code() override { return ROTATE_EVENT;} my_off_t get_header_len(my_off_t l __attribute__((unused))) override { return LOG_EVENT_MINIMAL_HEADER_LEN; } int get_data_size() override { return ident_len + ROTATE_HEADER_LEN;} bool is_valid() const override { return new_log_ident != 0; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; class Binlog_checkpoint_log_event: public Log_event { public: char *binlog_file_name; uint binlog_file_len; #ifdef MYSQL_SERVER Binlog_checkpoint_log_event(const char *binlog_file_name_arg, uint binlog_file_len_arg); #ifdef HAVE_REPLICATION void pack_info(Protocol *protocol) override; #endif #else bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif Binlog_checkpoint_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Binlog_checkpoint_log_event() { my_free(binlog_file_name); } Log_event_type get_type_code() override { return BINLOG_CHECKPOINT_EVENT;} int get_data_size() override { return binlog_file_len + BINLOG_CHECKPOINT_HEADER_LEN;} bool is_valid() const override { return binlog_file_name != 0; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; #ifdef HAVE_REPLICATION enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif #endif }; /** @class Gtid_log_event This event is logged as part of every event group to give the global transaction id (GTID) of that group. It replaces the BEGIN query event used in earlier versions to begin most event groups, but is also used for events that used to be stand-alone. @section Gtid_log_event_binary_format Binary Format The binary format for Gtid_log_event has 6 extra reserved bytes to make the length a total of 19 byte (+ 19 bytes of header in common with all events). This is just the minimal size for a BEGIN query event, which makes it easy to replace this event with such BEGIN event to remain compatible with old slave servers. <table> <caption>Post-Header</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>seq_no</td> <td>8 byte unsigned integer</td> <td>increasing id within one server_id. Starts at 1, holes in the sequence may occur</td> </tr> <tr> <td>domain_id</td> <td>4 byte unsigned integer</td> <td>Replication domain id, identifying independent replication streams></td> </tr> <tr> <td>flags</td> <td>1 byte bitfield</td> <td>Bit 0 set indicates stand-alone event (no terminating COMMIT)</td> <td>Bit 1 set indicates group commit, and that commit id exists</td> <td>Bit 2 set indicates a transactional event group (can be safely rolled back).</td> <td>Bit 3 set indicates that user allowed optimistic parallel apply (the @@SESSION.replicate_allow_parallel value was true at commit).</td> <td>Bit 4 set indicates that this transaction encountered a row (or other) lock wait during execution.</td> </tr> <tr> <td>Reserved (no group commit) / commit id (group commit) (see flags bit 1)</td> <td>6 bytes / 8 bytes</td> <td>Reserved bytes, set to 0. Maybe be used for future expansion (no group commit). OR commit id, same for all GTIDs in the same group commit (see flags bit 1).</td> </tr> </table> The Body of Gtid_log_event is empty. The total event size is 19 bytes + the normal 19 bytes common-header. */ class Gtid_log_event: public Log_event { public: uint64 seq_no; uint64 commit_id; uint32 domain_id; uint64 sa_seq_no; // start alter identifier for CA/RA #ifdef MYSQL_SERVER event_xid_t xid; #else event_mysql_xid_t xid; #endif uchar flags2; /* More flags area placed after the regular flags2's area. The type is declared to be in agreement with Query_log_event's member that may copy the flags_extra value. */ decltype(Query_log_event::gtid_flags_extra) flags_extra; /* Number of engine participants in transaction minus 1. When zero the event does not contain that information. */ uint8 extra_engines; /* Flags2. */ /* FL_STANDALONE is set when there is no terminating COMMIT event. */ static const uchar FL_STANDALONE= 1; /* FL_GROUP_COMMIT_ID is set when event group is part of a group commit on the master. Groups with same commit_id are part of the same group commit. */ static const uchar FL_GROUP_COMMIT_ID= 2; /* FL_TRANSACTIONAL is set for an event group that can be safely rolled back (no MyISAM, eg.). */ static const uchar FL_TRANSACTIONAL= 4; /* FL_ALLOW_PARALLEL reflects the (negation of the) value of @@SESSION.skip_parallel_replication at the time of commit. */ static const uchar FL_ALLOW_PARALLEL= 8; /* FL_WAITED is set if a row lock wait (or other wait) is detected during the execution of the transaction. */ static const uchar FL_WAITED= 16; /* FL_DDL is set for event group containing DDL. */ static const uchar FL_DDL= 32; /* FL_PREPARED_XA is set for XA transaction. */ static const uchar FL_PREPARED_XA= 64; /* FL_"COMMITTED or ROLLED-BACK"_XA is set for XA transaction. */ static const uchar FL_COMPLETED_XA= 128; /* flags_extra 's bit values. _E1 suffix below stands for Extra to infer the extra flags, their "1st" generation (more *generations* can come when necessary). FL_EXTRA_MULTI_ENGINE_E1 is set for event group comprising a transaction involving multiple storage engines. No flag and extra data are added to the event when the transaction involves only one engine. */ static const uchar FL_EXTRA_MULTI_ENGINE_E1= 1; static const uchar FL_START_ALTER_E1= 2; static const uchar FL_COMMIT_ALTER_E1= 4; static const uchar FL_ROLLBACK_ALTER_E1= 8; #ifdef MYSQL_SERVER Gtid_log_event(THD *thd_arg, uint64 seq_no, uint32 domain_id, bool standalone, uint16 flags, bool is_transactional, uint64 commit_id, bool has_xid= false, bool is_ro_1pc= false); #ifdef HAVE_REPLICATION void pack_info(Protocol *protocol) override; int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif #else bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif Gtid_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Gtid_log_event() = default; Log_event_type get_type_code() override { return GTID_EVENT; } enum_logged_status logged_status() override { return LOGGED_NO_DATA; } int get_data_size() override { return GTID_HEADER_LEN + ((flags2 & FL_GROUP_COMMIT_ID) ? 2 : 0); } bool is_valid() const override { /* seq_no is set to 0 if the structure of a serialized GTID event does not align with that as indicated by flags and extra_flags. */ return seq_no != 0; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; static int make_compatible_event(String *packet, bool *need_dummy_event, ulong ev_offset, enum_binlog_checksum_alg checksum_alg); static bool peek(const uchar *event_start, size_t event_len, enum_binlog_checksum_alg checksum_alg, uint32 *domain_id, uint32 *server_id, uint64 *seq_no, uchar *flags2, const Format_description_log_event *fdev); #endif }; /** @class Gtid_list_log_event This event is logged at the start of every binlog file to record the current replication state: the last global transaction id (GTID) applied on the server within each replication domain. It consists of a list of GTIDs, one for each replication domain ever seen on the server. @section Gtid_list_log_event_binary_format Binary Format <table> <caption>Post-Header</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>count</td> <td>4 byte unsigned integer</td> <td>The lower 28 bits are the number of GTIDs. The upper 4 bits are flags bits.</td> </tr> </table> <table> <caption>Body</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>domain_id</td> <td>4 byte unsigned integer</td> <td>Replication domain id of one GTID</td> </tr> <tr> <td>server_id</td> <td>4 byte unsigned integer</td> <td>Server id of one GTID</td> </tr> <tr> <td>seq_no</td> <td>8 byte unsigned integer</td> <td>sequence number of one GTID</td> </tr> </table> The three elements in the body repeat COUNT times to form the GTID list. At the time of writing, only two flag bit are in use. Bit 28 of `count' is used for flag FLAG_UNTIL_REACHED, which is sent in a Gtid_list event from the master to the slave to indicate that the START SLAVE UNTIL master_gtid_pos=xxx condition has been reached. (This flag is only sent in "fake" events generated on the fly, it is not written into the binlog). */ class Gtid_list_log_event: public Log_event { public: uint32 count; uint32 gl_flags; struct rpl_gtid *list; uint64 *sub_id_list; static const uint element_size= 4+4+8; /* Upper bits stored in 'count'. See comment above */ enum gtid_flags { FLAG_UNTIL_REACHED= (1<<28), FLAG_IGN_GTIDS= (1<<29), }; #ifdef MYSQL_SERVER Gtid_list_log_event(rpl_binlog_state *gtid_set, uint32 gl_flags); Gtid_list_log_event(slave_connection_state *gtid_set, uint32 gl_flags); #ifdef HAVE_REPLICATION void pack_info(Protocol *protocol) override; #endif #else bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif Gtid_list_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Gtid_list_log_event() { my_free(list); my_free(sub_id_list); } Log_event_type get_type_code() override { return GTID_LIST_EVENT; } int get_data_size() override { /* Replacing with dummy event, needed for older slaves, requires a minimum of 6 bytes in the body. */ return (count==0 ? GTID_LIST_HEADER_LEN+2 : GTID_LIST_HEADER_LEN+count*element_size); } bool is_valid() const override { return list != NULL; } #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) bool to_packet(String *packet); bool write(Log_event_writer *writer) override; int do_apply_event(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif static bool peek(const char *event_start, size_t event_len, enum_binlog_checksum_alg checksum_alg, rpl_gtid **out_gtid_list, uint32 *out_list_len, const Format_description_log_event *fdev); }; /** @class Append_block_log_event @section Append_block_log_event_binary_format Binary Format */ class Append_block_log_event: public Log_event { public: uchar* block; uint block_len; uint file_id; /* 'db' is filled when the event is created in mysql_load() (the event needs to have a 'db' member to be well filtered by binlog-*-db rules). 'db' is not written to the binlog (it's not used by Append_block_log_event::write()), so it can't be read in the Append_block_log_event(const uchar *buf, int event_len) constructor. In other words, 'db' is used only for filtering by binlog-*-db rules. */ const char* db; #ifdef MYSQL_SERVER Append_block_log_event(THD* thd, const char* db_arg, uchar* block_arg, uint block_len_arg, bool using_trans); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif Append_block_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Append_block_log_event() = default; Log_event_type get_type_code() override { return APPEND_BLOCK_EVENT;} int get_data_size() override { return block_len + APPEND_BLOCK_HEADER_LEN ;} bool is_valid() const override { return block != 0; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; const char* get_db() override { return db; } #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; #endif }; /** @class Delete_file_log_event @section Delete_file_log_event_binary_format Binary Format */ class Delete_file_log_event: public Log_event { public: uint file_id; const char* db; /* see comment in Append_block_log_event */ #ifdef MYSQL_SERVER Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local); #endif Delete_file_log_event(const uchar *buf, uint event_len, const Format_description_log_event* description_event); ~Delete_file_log_event() = default; Log_event_type get_type_code() override { return DELETE_FILE_EVENT;} int get_data_size() override { return DELETE_FILE_HEADER_LEN ;} bool is_valid() const override { return file_id != 0; } #ifdef MYSQL_SERVER bool write(Log_event_writer *writer) override; const char* get_db() override { return db; } #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; #endif }; /** @class Begin_load_query_log_event Event for the first block of file to be loaded, its only difference from Append_block event is that this event creates or truncates existing file before writing data. @section Begin_load_query_log_event_binary_format Binary Format */ class Begin_load_query_log_event: public Append_block_log_event { public: #ifdef MYSQL_SERVER Begin_load_query_log_event(THD* thd_arg, const char *db_arg, uchar* block_arg, uint block_len_arg, bool using_trans); #ifdef HAVE_REPLICATION Begin_load_query_log_event(THD* thd); int get_create_or_append() const override; #endif /* HAVE_REPLICATION */ #endif Begin_load_query_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Begin_load_query_log_event() = default; Log_event_type get_type_code() override { return BEGIN_LOAD_QUERY_EVENT; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif }; /* Elements of this enum describe how LOAD DATA handles duplicates. */ enum enum_load_dup_handling { LOAD_DUP_ERROR= 0, LOAD_DUP_IGNORE, LOAD_DUP_REPLACE }; /** @class Execute_load_query_log_event Event responsible for LOAD DATA execution, it similar to Query_log_event but before executing the query it substitutes original filename in LOAD DATA query with name of temporary file. @section Execute_load_query_log_event_binary_format Binary Format */ class Execute_load_query_log_event: public Query_log_event { public: uint file_id; // file_id of temporary file uint fn_pos_start; // pointer to the part of the query that should // be substituted uint fn_pos_end; // pointer to the end of this part of query /* We have to store type of duplicate handling explicitly, because for LOAD DATA it also depends on LOCAL option. And this part of query will be rewritten during replication so this information may be lost... */ enum_load_dup_handling dup_handling; #ifdef MYSQL_SERVER Execute_load_query_log_event(THD* thd, const char* query_arg, ulong query_length, uint fn_pos_start_arg, uint fn_pos_end_arg, enum_load_dup_handling dup_handling_arg, bool using_trans, bool direct, bool suppress_use, int errcode); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, const char *local_fname); #endif Execute_load_query_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); ~Execute_load_query_log_event() = default; Log_event_type get_type_code() override { return EXECUTE_LOAD_QUERY_EVENT; } bool is_valid() const override { return Query_log_event::is_valid() && file_id != 0; } ulong get_post_header_size_for_derived() override; #ifdef MYSQL_SERVER bool write_post_header_for_derived(Log_event_writer *writer) override; #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; #endif }; #ifdef MYSQL_CLIENT /** @class Unknown_log_event @section Unknown_log_event_binary_format Binary Format */ class Unknown_log_event: public Log_event { public: enum { UNKNOWN, ENCRYPTED } what; /* Even if this is an unknown event, we still pass description_event to Log_event's ctor, this way we can extract maximum information from the event's header (the unique ID for example). */ Unknown_log_event(const uchar *buf, const Format_description_log_event *description_event): Log_event(buf, description_event), what(UNKNOWN) {} /* constructor for hopelessly corrupted events */ Unknown_log_event(): Log_event(), what(ENCRYPTED) {} ~Unknown_log_event() = default; bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; Log_event_type get_type_code() override { return UNKNOWN_EVENT;} bool is_valid() const override { return 1; } }; #endif char *str_to_hex(char *to, const uchar *from, size_t len); /** @class Annotate_rows_log_event In row-based mode, if binlog_annotate_row_events = ON, each group of Table_map_log_events is preceded by an Annotate_rows_log_event which contains the query which caused the subsequent rows operations. The Annotate_rows_log_event has no post-header and its body contains the corresponding query (without trailing zero). Note. The query length is to be calculated as a difference between the whole event length and the common header length. */ class Annotate_rows_log_event: public Log_event { public: #ifndef MYSQL_CLIENT Annotate_rows_log_event(THD*, bool using_trans, bool direct); #endif Annotate_rows_log_event(const uchar *buf, uint event_len, const Format_description_log_event*); ~Annotate_rows_log_event(); int get_data_size() override; Log_event_type get_type_code() override; enum_logged_status logged_status() override { return LOGGED_NO_DATA; } bool is_valid() const override; #ifndef MYSQL_CLIENT bool write_data_header(Log_event_writer *writer) override; bool write_data_body(Log_event_writer *writer) override; #ifdef HAVE_REPLICATION bool is_part_of_group() override { return 1; } #endif #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) void pack_info(Protocol*) override; #endif #ifdef MYSQL_CLIENT bool print(FILE*, PRINT_EVENT_INFO*) override; #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) private: int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info*) override; #endif private: char *m_query_txt; uint m_query_len; char *m_save_thd_query_txt; uint m_save_thd_query_len; bool m_saved_thd_query; bool m_used_query_txt; }; class table_def; /** @class Table_map_log_event In row-based mode, every row operation event is preceded by a Table_map_log_event which maps a table definition to a number. The table definition consists of database name, table name, and column definitions. @section Table_map_log_event_binary_format Binary Format The Post-Header has the following components: <table> <caption>Post-Header for Table_map_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>table_id</td> <td>6 bytes unsigned integer</td> <td>The number that identifies the table.</td> </tr> <tr> <td>flags</td> <td>2 byte bitfield</td> <td>Reserved for future use; currently always 0.</td> </tr> </table> The Body has the following components: <table> <caption>Body for Table_map_log_event</caption> <tr> <th>Name</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>database_name</td> <td>one byte string length, followed by null-terminated string</td> <td>The name of the database in which the table resides. The name is represented as a one byte unsigned integer representing the number of bytes in the name, followed by length bytes containing the database name, followed by a terminating 0 byte. (Note the redundancy in the representation of the length.) </td> </tr> <tr> <td>table_name</td> <td>one byte string length, followed by null-terminated string</td> <td>The name of the table, encoded the same way as the database name above.</td> </tr> <tr> <td>column_count</td> <td>@ref packed_integer "Packed Integer"</td> <td>The number of columns in the table, represented as a packed variable-length integer.</td> </tr> <tr> <td>column_type</td> <td>List of column_count 1 byte enumeration values</td> <td>The type of each column in the table, listed from left to right. Each byte is mapped to a column type according to the enumeration type enum_field_types defined in mysql_com.h. The mapping of types to numbers is listed in the table @ref Table_table_map_log_event_column_types "below" (along with description of the associated metadata field). </td> </tr> <tr> <td>metadata_length</td> <td>@ref packed_integer "Packed Integer"</td> <td>The length of the following metadata block</td> </tr> <tr> <td>metadata</td> <td>list of metadata for each column</td> <td>For each column from left to right, a chunk of data who's length and semantics depends on the type of the column. The length and semantics for the metadata for each column are listed in the table @ref Table_table_map_log_event_column_types "below".</td> </tr> <tr> <td>null_bits</td> <td>column_count bits, rounded up to nearest byte</td> <td>For each column, a bit indicating whether data in the column can be NULL or not. The number of bytes needed for this is int((column_count+7)/8). The flag for the first column from the left is in the least-significant bit of the first byte, the second is in the second least significant bit of the first byte, the ninth is in the least significant bit of the second byte, and so on. </td> </tr> <tr> <td>optional metadata fields</td> <td>optional metadata fields are stored in Type, Length, Value(TLV) format. Type takes 1 byte. Length is a packed integer value. Values takes Length bytes. </td> <td>There are some optional metadata defined. They are listed in the table @ref Table_table_map_event_optional_metadata. Optional metadata fields follow null_bits. Whether binlogging an optional metadata is decided by the server. The order is not defined, so they can be binlogged in any order. </td> </tr> </table> The table below lists all column types, along with the numerical identifier for it and the size and interpretation of meta-data used to describe the type. @anchor Table_table_map_log_event_column_types <table> <caption>Table_map_log_event column types: numerical identifier and metadata</caption> <tr> <th>Name</th> <th>Identifier</th> <th>Size of metadata in bytes</th> <th>Description of metadata</th> </tr> <tr> <td>MYSQL_TYPE_DECIMAL</td><td>0</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_TINY</td><td>1</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_SHORT</td><td>2</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_LONG</td><td>3</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_FLOAT</td><td>4</td> <td>1 byte</td> <td>1 byte unsigned integer, representing the "pack_length", which is equal to sizeof(float) on the server from which the event originates.</td> </tr> <tr> <td>MYSQL_TYPE_DOUBLE</td><td>5</td> <td>1 byte</td> <td>1 byte unsigned integer, representing the "pack_length", which is equal to sizeof(double) on the server from which the event originates.</td> </tr> <tr> <td>MYSQL_TYPE_NULL</td><td>6</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_TIMESTAMP</td><td>7</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_LONGLONG</td><td>8</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_INT24</td><td>9</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_DATE</td><td>10</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_TIME</td><td>11</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_DATETIME</td><td>12</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td>MYSQL_TYPE_YEAR</td><td>13</td> <td>0</td> <td>No column metadata.</td> </tr> <tr> <td><i>MYSQL_TYPE_NEWDATE</i></td><td><i>14</i></td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td>MYSQL_TYPE_VARCHAR</td><td>15</td> <td>2 bytes</td> <td>2 byte unsigned integer representing the maximum length of the string.</td> </tr> <tr> <td>MYSQL_TYPE_BIT</td><td>16</td> <td>2 bytes</td> <td>A 1 byte unsigned int representing the length in bits of the bitfield (0 to 64), followed by a 1 byte unsigned int representing the number of bytes occupied by the bitfield. The number of bytes is either int((length+7)/8) or int(length/8).</td> </tr> <tr> <td>MYSQL_TYPE_NEWDECIMAL</td><td>246</td> <td>2 bytes</td> <td>A 1 byte unsigned int representing the precision, followed by a 1 byte unsigned int representing the number of decimals.</td> </tr> <tr> <td><i>MYSQL_TYPE_ENUM</i></td><td><i>247</i></td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td><i>MYSQL_TYPE_SET</i></td><td><i>248</i></td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td>MYSQL_TYPE_TINY_BLOB</td><td>249</td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td><i>MYSQL_TYPE_MEDIUM_BLOB</i></td><td><i>250</i></td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td><i>MYSQL_TYPE_LONG_BLOB</i></td><td><i>251</i></td> <td>–</td> <td><i>This enumeration value is only used internally and cannot exist in a binlog.</i></td> </tr> <tr> <td>MYSQL_TYPE_BLOB</td><td>252</td> <td>1 byte</td> <td>The pack length, i.e., the number of bytes needed to represent the length of the blob: 1, 2, 3, or 4.</td> </tr> <tr> <td>MYSQL_TYPE_VAR_STRING</td><td>253</td> <td>2 bytes</td> <td>This is used to store both strings and enumeration values. The first byte is a enumeration value storing the <i>real type</i>, which may be either MYSQL_TYPE_VAR_STRING or MYSQL_TYPE_ENUM. The second byte is a 1 byte unsigned integer representing the field size, i.e., the number of bytes needed to store the length of the string.</td> </tr> <tr> <td>MYSQL_TYPE_STRING</td><td>254</td> <td>2 bytes</td> <td>The first byte is always MYSQL_TYPE_VAR_STRING (i.e., 253). The second byte is the field size, i.e., the number of bytes in the representation of size of the string: 3 or 4.</td> </tr> <tr> <td>MYSQL_TYPE_GEOMETRY</td><td>255</td> <td>1 byte</td> <td>The pack length, i.e., the number of bytes needed to represent the length of the geometry: 1, 2, 3, or 4.</td> </tr> </table> The table below lists all optional metadata types, along with the numerical identifier for it and the size and interpretation of meta-data used to describe the type. @anchor Table_table_map_event_optional_metadata <table> <caption>Table_map_event optional metadata types: numerical identifier and metadata. Optional metadata fields are stored in TLV fields. Format of values are described in this table. </caption> <tr> <th>Type</th> <th>Description</th> <th>Format</th> </tr> <tr> <td>SIGNEDNESS</td> <td>signedness of numeric colums. This is included for all values of binlog_row_metadata.</td> <td>For each numeric column, a bit indicates whether the numeric colunm has unsigned flag. 1 means it is unsigned. The number of bytes needed for this is int((column_count + 7) / 8). The order is the same as the order of column_type field.</td> </tr> <tr> <td>DEFAULT_CHARSET</td> <td>Charsets of character columns. It has a default charset for the case that most of character columns have same charset and the most used charset is binlogged as default charset.Collation numbers are binlogged for identifying charsets. They are stored in packed length format. Either DEFAULT_CHARSET or COLUMN_CHARSET is included for all values of binlog_row_metadata.</td> <td>Default charset's collation is logged first. The charsets which are not same to default charset are logged following default charset. They are logged as column index and charset collation number pair sequence. The column index is counted only in all character columns. The order is same to the order of column_type field. </td> </tr> <tr> <td>COLUMN_CHARSET</td> <td>Charsets of character columns. For the case that most of columns have different charsets, this field is logged. It is never logged with DEFAULT_CHARSET together. Either DEFAULT_CHARSET or COLUMN_CHARSET is included for all values of binlog_row_metadata.</td> <td>It is a collation number sequence for all character columns.</td> </tr> <tr> <td>COLUMN_NAME</td> <td>Names of columns. This is only included if binlog_row_metadata=FULL.</td> <td>A sequence of column names. For each column name, 1 byte for the string length in bytes is followed by a string without null terminator.</td> </tr> <tr> <td>SET_STR_VALUE</td> <td>The string values of SET columns. This is only included if binlog_row_metadata=FULL.</td> <td>For each SET column, a pack_length representing the value count is followed by a sequence of length and string pairs. length is the byte count in pack_length format. The string has no null terminator.</td> </tr> <tr> <td>ENUM_STR_VALUE</td> <td>The string values is ENUM columns. This is only included if binlog_row_metadata=FULL.</td> <td>The format is the same as SET_STR_VALUE.</td> </tr> <tr> <td>GEOMETRY_TYPE</td> <td>The real type of geometry columns. This is only included if binlog_row_metadata=FULL.</td> <td>A sequence of real type of geometry columns are stored in pack_length format. </td> </tr> <tr> <td>SIMPLE_PRIMARY_KEY</td> <td>The primary key without any prefix. This is only included if binlog_row_metadata=FULL and there is a primary key where every key part covers an entire column.</td> <td>A sequence of column indexes. The indexes are stored in pack_length format.</td> </tr> <tr> <td>PRIMARY_KEY_WITH_PREFIX</td> <td>The primary key with some prefix. It doesn't appear together with SIMPLE_PRIMARY_KEY. This is only included if binlog_row_metadata=FULL and there is a primary key where some key part covers a prefix of the column.</td> <td>A sequence of column index and prefix length pairs. Both column index and prefix length are in pack_length format. Prefix length 0 means that the whole column value is used.</td> </tr> <tr> <td>ENUM_AND_SET_DEFAULT_CHARSET</td> <td>Charsets of ENUM and SET columns. It has the same layout as DEFAULT_CHARSET. If there are SET or ENUM columns and binlog_row_metadata=FULL, exactly one of ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET appears (the encoder chooses the representation that uses the least amount of space). Otherwise, none of them appears.</td> <td>The same format as for DEFAULT_CHARSET, except it counts ENUM and SET columns rather than character columns.</td> </tr> <tr> <td>ENUM_AND_SET_COLUMN_CHARSET</td> <td>Charsets of ENUM and SET columns. It has the same layout as COLUMN_CHARSET. If there are SET or ENUM columns and binlog_row_metadata=FULL, exactly one of ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET appears (the encoder chooses the representation that uses the least amount of space). Otherwise, none of them appears.</td> <td>The same format as for COLUMN_CHARSET, except it counts ENUM and SET columns rather than character columns.</td> </tr> </table> */ class Table_map_log_event : public Log_event { public: /* Constants */ enum { TYPE_CODE = TABLE_MAP_EVENT }; /** Enumeration of the errors that can be returned. */ enum enum_error { ERR_OPEN_FAILURE = -1, /**< Failure to open table */ ERR_OK = 0, /**< No error */ ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */ ERR_OUT_OF_MEM = 2, /**< Out of memory */ ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */ ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */ }; enum enum_flag { /* Nothing here right now, but the flags support is there in preparation for changes that are coming. Need to add a constant to make it compile under HP-UX: aCC does not like empty enumerations. */ ENUM_FLAG_COUNT }; typedef uint16 flag_set; /** DEFAULT_CHARSET and COLUMN_CHARSET don't appear together, and ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET don't appear together. They are just alternative ways to pack character set information. When binlogging, it logs character sets in the way that occupies least storage. SIMPLE_PRIMARY_KEY and PRIMARY_KEY_WITH_PREFIX don't appear together. SIMPLE_PRIMARY_KEY is for the primary keys which only use whole values of pk columns. PRIMARY_KEY_WITH_PREFIX is for the primary keys which just use part value of pk columns. */ enum Optional_metadata_field_type { SIGNEDNESS = 1, // UNSIGNED flag of numeric columns DEFAULT_CHARSET, /* Character set of string columns, optimized to minimize space when many columns have the same charset. */ COLUMN_CHARSET, /* Character set of string columns, optimized to minimize space when columns have many different charsets. */ COLUMN_NAME, SET_STR_VALUE, // String value of SET columns ENUM_STR_VALUE, // String value of ENUM columns GEOMETRY_TYPE, // Real type of geometry columns SIMPLE_PRIMARY_KEY, // Primary key without prefix PRIMARY_KEY_WITH_PREFIX, // Primary key with prefix ENUM_AND_SET_DEFAULT_CHARSET, /* Character set of enum and set columns, optimized to minimize space when many columns have the same charset. */ ENUM_AND_SET_COLUMN_CHARSET, /* Character set of enum and set columns, optimized to minimize space when many columns have the same charset. */ }; /** Metadata_fields organizes m_optional_metadata into a structured format which is easy to access. */ // Values for binlog_row_metadata sysvar enum enum_binlog_row_metadata { BINLOG_ROW_METADATA_NO_LOG= 0, BINLOG_ROW_METADATA_MINIMAL= 1, BINLOG_ROW_METADATA_FULL= 2 }; struct Optional_metadata_fields { typedef std::pair<unsigned int, unsigned int> uint_pair; typedef std::vector<std::string> str_vector; struct Default_charset { Default_charset() : default_charset(0) {} bool empty() const { return default_charset == 0; } // Default charset for the columns which are not in charset_pairs. unsigned int default_charset; /* The uint_pair means <column index, column charset number>. */ std::vector<uint_pair> charset_pairs; }; // Contents of DEFAULT_CHARSET field is converted into Default_charset. Default_charset m_default_charset; // Contents of ENUM_AND_SET_DEFAULT_CHARSET are converted into // Default_charset. Default_charset m_enum_and_set_default_charset; std::vector<bool> m_signedness; // Character set number of every string column std::vector<unsigned int> m_column_charset; // Character set number of every ENUM or SET column. std::vector<unsigned int> m_enum_and_set_column_charset; std::vector<std::string> m_column_name; // each str_vector stores values of one enum/set column std::vector<str_vector> m_enum_str_value; std::vector<str_vector> m_set_str_value; std::vector<unsigned int> m_geometry_type; /* The uint_pair means <column index, prefix length>. Prefix length is 0 if whole column value is used. */ std::vector<uint_pair> m_primary_key; /* It parses m_optional_metadata and populates into above variables. @param[in] optional_metadata points to the begin of optional metadata fields in table_map_event. @param[in] optional_metadata_len length of optional_metadata field. */ Optional_metadata_fields(unsigned char* optional_metadata, unsigned int optional_metadata_len); }; /** Print column metadata. Its format looks like: # Columns(colume_name type, colume_name type, ...) if colume_name field is not logged into table_map_log_event, then only type is printed. @@param[out] file the place where colume metadata is printed @@param[in] The metadata extracted from optional metadata fields */ void print_columns(IO_CACHE *file, const Optional_metadata_fields &fields); /** Print primary information. Its format looks like: # Primary Key(colume_name, column_name(prifix), ...) if colume_name field is not logged into table_map_log_event, then colume index is printed. @@param[out] file the place where primary key is printed @@param[in] The metadata extracted from optional metadata fields */ void print_primary_key(IO_CACHE *file, const Optional_metadata_fields &fields); /* Special constants representing sets of flags */ enum { TM_NO_FLAGS = 0U, TM_BIT_LEN_EXACT_F = (1U << 0), // MariaDB flags (we starts from the other end) TM_BIT_HAS_TRIGGERS_F= (1U << 14) }; flag_set get_flags(flag_set flag) const { return m_flags & flag; } #ifdef MYSQL_SERVER Table_map_log_event(THD *thd, TABLE *tbl, ulonglong tid, bool is_transactional); #endif #ifdef HAVE_REPLICATION Table_map_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif ~Table_map_log_event(); #ifdef MYSQL_CLIENT table_def *create_table_def() { return new table_def(m_coltype, m_colcnt, m_field_metadata, m_field_metadata_size, m_null_bits, m_flags); } int rewrite_db(const char* new_name, size_t new_name_len, const Format_description_log_event*); #endif ulonglong get_table_id() const { return m_table_id; } const char *get_table_name() const { return m_tblnam; } const char *get_db_name() const { return m_dbnam; } Log_event_type get_type_code() override { return TABLE_MAP_EVENT; } enum_logged_status logged_status() override { return LOGGED_TABLE_MAP; } bool is_valid() const override { return m_memory != NULL; /* we check malloc */ } int get_data_size() override { return (uint) m_data_size; } #ifdef MYSQL_SERVER #ifdef HAVE_REPLICATION bool is_part_of_group() override { return 1; } #endif virtual int save_field_metadata(); bool write_data_header(Log_event_writer *writer) override; bool write_data_body(Log_event_writer *writer) override; const char *get_db() override { return m_dbnam; } #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) void pack_info(Protocol *protocol) override; #endif #ifdef MYSQL_CLIENT bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif table_def get_table_def(); private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; #endif #ifdef MYSQL_SERVER TABLE *m_table; Binlog_type_info *binlog_type_info_array; // Metadata fields buffer StringBuffer<1024> m_metadata_buf; /** Capture the optional metadata fields which should be logged into table_map_log_event and serialize them into m_metadata_buf. */ void init_metadata_fields(); bool init_signedness_field(); /** Capture and serialize character sets. Character sets for character columns (TEXT etc) and character sets for ENUM and SET columns are stored in different metadata fields. The reason is that TEXT character sets are included even when binlog_row_metadata=MINIMAL, whereas ENUM and SET character sets are included only when binlog_row_metadata=FULL. @param include_type Predicate to determine if a given Field object is to be included in the metadata field. @param default_charset_type Type code when storing in "default charset" format. (See comment above Table_maps_log_event in libbinlogevents/include/rows_event.h) @param column_charset_type Type code when storing in "column charset" format. (See comment above Table_maps_log_event in libbinlogevents/include/rows_event.h) */ bool init_charset_field(bool(* include_type)(Binlog_type_info *, Field *), Optional_metadata_field_type default_charset_type, Optional_metadata_field_type column_charset_type); bool init_column_name_field(); bool init_set_str_value_field(); bool init_enum_str_value_field(); bool init_geometry_type_field(); bool init_primary_key_field(); #endif #ifdef MYSQL_CLIENT class Charset_iterator; class Default_charset_iterator; class Column_charset_iterator; #endif char const *m_dbnam; size_t m_dblen; char const *m_tblnam; size_t m_tbllen; ulong m_colcnt; uchar *m_coltype; uchar *m_memory; ulonglong m_table_id; flag_set m_flags; size_t m_data_size; uchar *m_field_metadata; // buffer for field metadata /* The size of field metadata buffer set by calling save_field_metadata() */ ulong m_field_metadata_size; uchar *m_null_bits; uchar *m_meta_memory; unsigned int m_optional_metadata_len; unsigned char *m_optional_metadata; }; /** @class Rows_log_event Common base class for all row-containing log events. RESPONSIBILITIES Encode the common parts of all events containing rows, which are: - Write data header and data body to an IO_CACHE. - Provide an interface for adding an individual row to the event. @section Rows_log_event_binary_format Binary Format */ class Rows_log_event : public Log_event { public: /** Enumeration of the errors that can be returned. */ enum enum_error { ERR_OPEN_FAILURE = -1, /**< Failure to open table */ ERR_OK = 0, /**< No error */ ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */ ERR_OUT_OF_MEM = 2, /**< Out of memory */ ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */ ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */ }; /* These definitions allow you to combine the flags into an appropriate flag set using the normal bitwise operators. The implicit conversion from an enum-constant to an integer is accepted by the compiler, which is then used to set the real set of flags. */ enum enum_flag { /* Last event of a statement */ STMT_END_F = (1U << 0), /* Value of the OPTION_NO_FOREIGN_KEY_CHECKS flag in thd->options */ NO_FOREIGN_KEY_CHECKS_F = (1U << 1), /* Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */ RELAXED_UNIQUE_CHECKS_F = (1U << 2), /** Indicates that rows in this event are complete, that is contain values for all columns of the table. */ COMPLETE_ROWS_F = (1U << 3), /* Value of the OPTION_NO_CHECK_CONSTRAINT_CHECKS flag in thd->options */ NO_CHECK_CONSTRAINT_CHECKS_F = (1U << 7) }; typedef uint16 flag_set; /* Special constants representing sets of flags */ enum { RLE_NO_FLAGS = 0U }; virtual ~Rows_log_event(); void set_flags(flag_set flags_arg) { m_flags |= flags_arg; } void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; } flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; } void update_flags() { int2store(temp_buf + m_flags_pos, m_flags); } Log_event_type get_type_code() override { return m_type; } /* Specific type (_V1 etc) */ enum_logged_status logged_status() override { return LOGGED_ROW_EVENT; } virtual Log_event_type get_general_type_code() const = 0; /* General rows op type, no version */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) void pack_info(Protocol *protocol) override; #endif #ifdef MYSQL_CLIENT struct Field_info { const uchar *pos; // Point to a field in before or after image size_t length; // Length of the field. }; /* not for direct call, each derived has its own ::print() */ bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override= 0; void change_to_flashback_event(PRINT_EVENT_INFO *print_event_info, uchar *rows_buff, Log_event_type ev_type); bool print_verbose(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info); size_t print_verbose_one_row(IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info, MY_BITMAP *cols_bitmap, const uchar *ptr, const uchar *prefix); size_t calc_row_event_length(table_def *td, MY_BITMAP *cols_bitmap, const uchar *value, Field_info *fields); void count_row_events(PRINT_EVENT_INFO *print_event_info); #endif #ifdef MYSQL_SERVER int add_row_data(uchar *data, size_t length) { return do_add_row_data(data,length); } #endif /* Member functions to implement superclass interface */ int get_data_size() override; MY_BITMAP const *get_cols() const { return &m_cols; } MY_BITMAP const *get_cols_ai() const { return &m_cols_ai; } size_t get_width() const { return m_width; } ulonglong get_table_id() const { return m_table_id; } #if defined(MYSQL_SERVER) /* This member function compares the table's read/write_set with this event's m_cols and m_cols_ai. Comparison takes into account what type of rows event is this: Delete, Write or Update, therefore it uses the correct m_cols[_ai] according to the event type code. Note that this member function should only be called for the following events: - Delete_rows_log_event - Write_rows_log_event - Update_rows_log_event @param[IN] table The table to compare this events bitmaps against. @return TRUE if sets match, FALSE otherwise. (following bitmap_cmp return logic). */ bool read_write_bitmaps_cmp(TABLE *table) { bool res= FALSE; switch (get_general_type_code()) { case DELETE_ROWS_EVENT: res= bitmap_cmp(get_cols(), table->read_set); break; case UPDATE_ROWS_EVENT: res= (bitmap_cmp(get_cols(), table->read_set) && bitmap_cmp(get_cols_ai(), table->rpl_write_set)); break; case WRITE_ROWS_EVENT: res= bitmap_cmp(get_cols(), table->rpl_write_set); break; default: /* We should just compare bitmaps for Delete, Write or Update rows events. */ DBUG_ASSERT(0); } return res; } #endif #ifdef MYSQL_SERVER bool write_data_header(Log_event_writer *writer) override; bool write_data_body(Log_event_writer *writer) override; virtual bool write_compressed(Log_event_writer *writer); const char *get_db() override { return m_table->s->db.str; } #ifdef HAVE_REPLICATION bool is_part_of_group() override { return get_flags(STMT_END_F) != 0; } #endif #endif /* Check that malloc() succeeded in allocating memory for the rows buffer and the COLS vector. Checking that an Update_rows_log_event is valid is done in the Update_rows_log_event::is_valid() function. */ bool is_valid() const override { return m_cols.bitmap; } uint m_row_count; /* The number of rows added to the event */ const uchar* get_extra_row_data() const { return m_extra_row_data; } #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual uint8 get_trg_event_map() const = 0; inline bool do_invoke_trigger() { return (slave_run_triggers_for_rbr && !master_had_triggers) || slave_run_triggers_for_rbr == SLAVE_RUN_TRIGGERS_FOR_RBR_ENFORCE; } #endif protected: /* The constructors are protected since you're supposed to inherit this class, not create instances of this class. */ #ifdef MYSQL_SERVER Rows_log_event(THD*, TABLE*, ulonglong table_id, MY_BITMAP const *cols, bool is_transactional, Log_event_type event_type); #endif Rows_log_event(const uchar *row_data, uint event_len, const Format_description_log_event *description_event); void uncompress_buf(); #ifdef MYSQL_CLIENT bool print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); #endif #ifdef MYSQL_SERVER virtual int do_add_row_data(uchar *data, size_t length); #endif #ifdef MYSQL_SERVER TABLE *m_table; /* The table the rows belong to */ #endif ulonglong m_table_id; /* Table ID */ MY_BITMAP m_cols; /* Bitmap denoting columns available */ uint m_width; /* The width of the columns bitmap */ /* Bitmap for columns available in the after image, if present. These fields are only available for Update_rows events. Observe that the width of both the before image COLS vector and the after image COLS vector is the same: the number of columns of the table on the master. */ MY_BITMAP m_cols_ai; ulong m_master_reclength; /* Length of record on master side */ /* Bit buffers in the same memory as the class */ my_bitmap_map m_bitbuf[128/(sizeof(my_bitmap_map)*8)]; my_bitmap_map m_bitbuf_ai[128/(sizeof(my_bitmap_map)*8)]; uchar *m_rows_buf; /* The rows in packed format */ uchar *m_rows_cur; /* One-after the end of the data */ uchar *m_rows_end; /* One-after the end of the allocated space */ size_t m_rows_before_size; /* The length before m_rows_buf */ size_t m_flags_pos; /* The position of the m_flags */ flag_set m_flags; /* Flags for row-level events */ Log_event_type m_type; /* Actual event type */ uchar *m_extra_row_data; /* Pointer to extra row data if any */ /* If non null, first byte is length */ bool m_vers_from_plain; /* helper functions */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) const uchar *m_curr_row; /* Start of the row being processed */ const uchar *m_curr_row_end; /* One-after the end of the current row */ uchar *m_key; /* Buffer to keep key value during searches */ KEY *m_key_info; /* Pointer to KEY info for m_key_nr */ uint m_key_nr; /* Key number */ uint m_usable_key_parts; /* A number of key_parts suited to lookup */ bool master_had_triggers; /* set after tables opening */ /* RAII helper class to automatically handle the override/restore of thd->db when applying row events, so it will be visible in SHOW PROCESSLIST. If triggers will be invoked, their logic frees the current thread's db, so we use set_db() to use a copy of the table share's database. If not using triggers, the db is never freed, and we can reference the same memory owned by the table share. */ class Db_restore_ctx { private: THD *thd; LEX_CSTRING restore_db; bool db_copied; Db_restore_ctx(Rows_log_event *rev) : thd(rev->thd), restore_db(rev->thd->db) { TABLE *table= rev->m_table; if (table->triggers && rev->do_invoke_trigger()) { thd->reset_db(&null_clex_str); thd->set_db(&table->s->db); db_copied= true; } else { thd->reset_db(&table->s->db); db_copied= false; } } ~Db_restore_ctx() { if (db_copied) thd->set_db(&null_clex_str); thd->reset_db(&restore_db); } friend class Rows_log_event; }; int find_key(const rpl_group_info *); // Find a best key to use in find_row() uint find_key_parts(const KEY *key) const; bool use_pk_position() const; int find_row(rpl_group_info *); int update_sequence(); // Unpack the current row into m_table->record[0], but with // a different columns bitmap. int unpack_current_row(rpl_group_info *rgi, MY_BITMAP const *cols) { DBUG_ASSERT(m_table); ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT); return ::unpack_row(rgi, m_table, m_width, m_curr_row, cols, &m_curr_row_end, &m_master_reclength, m_rows_end); } // Unpack the current row into m_table->record[0] int unpack_current_row(rpl_group_info *rgi) { DBUG_ASSERT(m_table); ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT); return ::unpack_row(rgi, m_table, m_width, m_curr_row, &m_cols, &m_curr_row_end, &m_master_reclength, m_rows_end); } bool process_triggers(trg_event_type event, trg_action_time_type time_type, bool old_row_is_record1); /** Helper function to check whether there is an auto increment column on the table where the event is to be applied. @return true if there is an autoincrement field on the extra columns, false otherwise. */ inline bool is_auto_inc_in_extra_columns() { DBUG_ASSERT(m_table); return (m_table->next_number_field && m_table->next_number_field->field_index >= m_width); } #endif private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; int do_update_pos(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; /** @brief Primitive to prepare for a sequence of row executions. DESCRIPTION Before doing a sequence of do_prepare_row() and do_exec_row() calls, this member function should be called to prepare for the entire sequence. Typically, this member function will allocate space for any buffers that are needed for the two member functions mentioned above. @return The member function will return 0 if all went OK, or a non-zero error code otherwise. */ virtual int do_before_row_operations(rpl_group_info *log, COPY_INFO *, Write_record *) = 0; /** @brief Primitive to clean up after a sequence of row executions. DESCRIPTION After doing a sequence of do_prepare_row() and do_exec_row(), this member function should be called to clean up and release any allocated buffers. The error argument, if non-zero, indicates an error which happened during row processing before this function was called. In this case, even if function is successful, it should return the error code given in the argument. */ virtual int do_after_row_operations(int error) = 0; /** @brief Primitive to do the actual execution necessary for a row. DESCRIPTION The member function will do the actual execution needed to handle a row. The row is located at m_curr_row. When the function returns, m_curr_row_end should point at the next row (one byte after the end of the current row). @return 0 if execution succeeded, 1 if execution failed. */ virtual int do_exec_row(rpl_group_info *rli) = 0; #endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */ }; /** @class Write_rows_log_event Log row insertions and updates. The event contain several insert/update rows for a table. Note that each event contains only rows for one table. @section Write_rows_log_event_binary_format Binary Format */ class Write_rows_log_event : public Rows_log_event { public: /* Support interface to THD::binlog_prepare_pending_rows_event */ static constexpr Log_event_type TYPE_CODE = WRITE_ROWS_EVENT; #if defined(MYSQL_SERVER) Write_rows_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); #endif #ifdef HAVE_REPLICATION Write_rows_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif #if defined(MYSQL_SERVER) static bool binlog_row_logging_function(THD *thd, TABLE *table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, ulong, const uchar *before_record __attribute__((unused)), const uchar *after_record) { DBUG_ASSERT(!table->versioned(VERS_TRX_ID)); return thd->binlog_write_row(table, bin_log, cache_data, is_transactional, after_record); } #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) uint8 get_trg_event_map() const override; void online_alter_update_row_count(ha_rows *rows) const override { *rows += m_row_count; } int incomplete_record_callback(rpl_group_info *rgi); #endif private: Log_event_type get_general_type_code() const override { return TYPE_CODE; } #ifdef MYSQL_CLIENT bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) Write_record *m_write_record; int write_row(rpl_group_info *, bool); int do_before_row_operations(rpl_group_info *, COPY_INFO *, Write_record *) override; int do_after_row_operations(int) override; int do_exec_row(rpl_group_info *) override; #endif }; class Write_rows_compressed_log_event : public Write_rows_log_event { public: #if defined(MYSQL_SERVER) Write_rows_compressed_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); bool write(Log_event_writer *writer) override; #endif #ifdef HAVE_REPLICATION Write_rows_compressed_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif private: #if defined(MYSQL_CLIENT) bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif }; /** @class Update_rows_log_event Log row updates with a before image. The event contain several update rows for a table. Note that each event contains only rows for one table. Also note that the row data consists of pairs of row data: one row for the old data and one row for the new data. @section Update_rows_log_event_binary_format Binary Format */ class Update_rows_log_event : public Rows_log_event { public: /* Support interface to THD::binlog_prepare_pending_rows_event */ static constexpr Log_event_type TYPE_CODE = UPDATE_ROWS_EVENT; #ifdef MYSQL_SERVER Update_rows_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); void init(MY_BITMAP const *cols); #endif ~Update_rows_log_event() override; #ifdef HAVE_REPLICATION Update_rows_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif #ifdef MYSQL_SERVER static bool binlog_row_logging_function(THD *thd, TABLE *table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, ulong row_image, const uchar *before_record, const uchar *after_record) { DBUG_ASSERT(!table->versioned(VERS_TRX_ID)); return thd->binlog_update_row(table, bin_log, cache_data, is_transactional, (enum_binlog_row_image)row_image, before_record, after_record); } #endif bool is_valid() const override { return Rows_log_event::is_valid() && m_cols_ai.bitmap; } #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) uint8 get_trg_event_map() const override; #endif protected: Log_event_type get_general_type_code() const override { return TYPE_CODE; } #ifdef MYSQL_CLIENT bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_before_row_operations(rpl_group_info *rgi, COPY_INFO *, Write_record *) override; int do_after_row_operations(int) override; int do_exec_row(rpl_group_info *) override; #endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */ }; class Update_rows_compressed_log_event : public Update_rows_log_event { public: #if defined(MYSQL_SERVER) Update_rows_compressed_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); bool write(Log_event_writer *writer) override; #endif #ifdef HAVE_REPLICATION Update_rows_compressed_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif private: #if defined(MYSQL_CLIENT) bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif }; /** @class Delete_rows_log_event Log row deletions. The event contain several delete rows for a table. Note that each event contains only rows for one table. RESPONSIBILITIES - Act as a container for rows that has been deleted on the master and should be deleted on the slave. COLLABORATION Row_writer Create the event and add rows to the event. Row_reader Extract the rows from the event. @section Delete_rows_log_event_binary_format Binary Format */ class Delete_rows_log_event : public Rows_log_event { public: /* Support interface to THD::binlog_prepare_pending_rows_event */ static constexpr Log_event_type TYPE_CODE = DELETE_ROWS_EVENT; #ifdef MYSQL_SERVER Delete_rows_log_event(THD*, TABLE*, ulonglong, bool is_transactional); #endif #ifdef HAVE_REPLICATION Delete_rows_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif #ifdef MYSQL_SERVER static bool binlog_row_logging_function(THD *thd, TABLE *table, Event_log *bin_log, binlog_cache_data *cache_data, bool is_transactional, ulong row_image, const uchar *before_record, const uchar *after_record __attribute__((unused))) { DBUG_ASSERT(!table->versioned(VERS_TRX_ID)); return thd->binlog_delete_row(table, bin_log, cache_data, is_transactional, (enum_binlog_row_image)row_image, before_record); } #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) uint8 get_trg_event_map() const override; void online_alter_update_row_count(ha_rows *rows) const override { *rows -= m_row_count; } #endif protected: Log_event_type get_general_type_code() const override { return TYPE_CODE; } #ifdef MYSQL_CLIENT bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_before_row_operations(rpl_group_info *rgi, COPY_INFO *, Write_record *) override; int do_after_row_operations(int) override; int do_exec_row(rpl_group_info *) override; #endif }; class Delete_rows_compressed_log_event : public Delete_rows_log_event { public: #if defined(MYSQL_SERVER) Delete_rows_compressed_log_event(THD*, TABLE*, ulonglong, bool is_transactional); bool write(Log_event_writer *writer) override; #endif #ifdef HAVE_REPLICATION Delete_rows_compressed_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); #endif private: #if defined(MYSQL_CLIENT) bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif }; /** @class Incident_log_event Class representing an incident, an occurence out of the ordinary, that happened on the master. The event is used to inform the slave that something out of the ordinary happened on the master that might cause the database to be in an inconsistent state. <table id="IncidentFormat"> <caption>Incident event format</caption> <tr> <th>Symbol</th> <th>Format</th> <th>Description</th> </tr> <tr> <td>INCIDENT</td> <td align="right">2</td> <td>Incident number as an unsigned integer</td> </tr> <tr> <td>MSGLEN</td> <td align="right">1</td> <td>Message length as an unsigned integer</td> </tr> <tr> <td>MESSAGE</td> <td align="right">MSGLEN</td> <td>The message, if present. Not null terminated.</td> </tr> </table> @section Delete_rows_log_event_binary_format Binary Format */ class Incident_log_event : public Log_event { public: #ifdef MYSQL_SERVER Incident_log_event(THD *thd_arg, Incident incident) : Log_event(thd_arg, 0, FALSE), m_incident(incident) { DBUG_ENTER("Incident_log_event::Incident_log_event"); DBUG_PRINT("enter", ("m_incident: %d", m_incident)); m_message.str= NULL; /* Just as a precaution */ m_message.length= 0; set_direct_logging(); /* Replicate the incident regardless of @@skip_replication. */ flags&= ~LOG_EVENT_SKIP_REPLICATION_F; DBUG_VOID_RETURN; } Incident_log_event(THD *thd_arg, Incident incident, const LEX_CSTRING *msg) : Log_event(thd_arg, 0, FALSE), m_incident(incident) { extern PSI_memory_key key_memory_Incident_log_event_message; DBUG_ENTER("Incident_log_event::Incident_log_event"); DBUG_PRINT("enter", ("m_incident: %d", m_incident)); m_message.length= 0; if (!(m_message.str= (char*) my_malloc(key_memory_Incident_log_event_message, msg->length + 1, MYF(MY_WME)))) { /* Mark this event invalid */ m_incident= INCIDENT_NONE; DBUG_VOID_RETURN; } strmake(m_message.str, msg->str, msg->length); m_message.length= msg->length; set_direct_logging(); /* Replicate the incident regardless of @@skip_replication. */ flags&= ~LOG_EVENT_SKIP_REPLICATION_F; DBUG_VOID_RETURN; } #endif #ifdef MYSQL_SERVER #ifdef HAVE_REPLICATION void pack_info(Protocol*) override; #endif bool write_data_header(Log_event_writer *writer) override; bool write_data_body(Log_event_writer *writer) override; #endif Incident_log_event(const uchar *buf, uint event_len, const Format_description_log_event *descr_event); virtual ~Incident_log_event(); #ifdef MYSQL_CLIENT bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) int do_apply_event(rpl_group_info *rgi) override; #endif Log_event_type get_type_code() override { return INCIDENT_EVENT; } bool is_valid() const override { return m_incident > INCIDENT_NONE && m_incident < INCIDENT_COUNT; } int get_data_size() override { return INCIDENT_HEADER_LEN + 1 + (uint) m_message.length; } private: const char *description() const; Incident m_incident; LEX_STRING m_message; }; /** @class Ignorable_log_event Base class for ignorable log events. Events deriving from this class can be safely ignored by slaves that cannot recognize them. Newer slaves, will be able to read and handle them. This has been designed to be an open-ended architecture, so adding new derived events shall not harm the old slaves that support ignorable log event mechanism (they will just ignore unrecognized ignorable events). @note The only thing that makes an event ignorable is that it has the LOG_EVENT_IGNORABLE_F flag set. It is not strictly necessary that ignorable event types derive from Ignorable_log_event; they may just as well derive from Log_event and pass LOG_EVENT_IGNORABLE_F as argument to the Log_event constructor. **/ class Ignorable_log_event : public Log_event { public: int number; const char *description; #ifndef MYSQL_CLIENT Ignorable_log_event(THD *thd_arg) :Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, FALSE), number(0), description("internal") { DBUG_ENTER("Ignorable_log_event::Ignorable_log_event"); DBUG_VOID_RETURN; } #endif Ignorable_log_event(const uchar *buf, const Format_description_log_event *descr_event, const char *event_name); virtual ~Ignorable_log_event(); #ifndef MYSQL_CLIENT #ifdef HAVE_REPLICATION void pack_info(Protocol*) override; #endif #else bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif Log_event_type get_type_code() override { return IGNORABLE_LOG_EVENT; } bool is_valid() const override { return 1; } int get_data_size() override { return IGNORABLE_HEADER_LEN; } }; #ifdef MYSQL_CLIENT bool copy_cache_to_string_wrapped(IO_CACHE *body, LEX_STRING *to, bool do_wrap, const char *delimiter, bool is_verbose); bool copy_cache_to_file_wrapped(IO_CACHE *body, FILE *file, bool do_wrap, const char *delimiter, bool is_verbose); #endif #ifdef MYSQL_SERVER /***************************************************************************** Heartbeat Log Event class Replication event to ensure to slave that master is alive. The event is originated by master's dump thread and sent straight to slave without being logged. Slave itself does not store it in relay log but rather uses a data for immediate checks and throws away the event. Two members of the class log_ident and Log_event::log_pos comprise @see the event_coordinates instance. The coordinates that a heartbeat instance carries correspond to the last event master has sent from its binlog. ****************************************************************************/ class Heartbeat_log_event: public Log_event { public: uint8 hb_flags; Heartbeat_log_event(const uchar *buf, uint event_len, const Format_description_log_event* description_event); Log_event_type get_type_code() override { return HEARTBEAT_LOG_EVENT; } bool is_valid() const override { return (log_ident != NULL && ident_len <= FN_REFLEN-1 && log_pos >= BIN_LOG_HEADER_SIZE); } const uchar * get_log_ident() { return log_ident; } uint get_ident_len() { return ident_len; } private: uint ident_len; const uchar *log_ident; }; inline int Log_event_writer::write(Log_event *ev) { int res= ev->write(this); add_status(ev->logged_status()); return res; } /** The function is called by slave applier in case there are active table filtering rules to force gathering events associated with Query-log-event into an array to execute them once the fate of the Query is determined for execution. */ bool slave_execute_deferred_events(THD *thd); #endif bool event_that_should_be_ignored(const uchar *buf); bool event_checksum_test(uchar *buf, ulong event_len, enum_binlog_checksum_alg alg); enum_binlog_checksum_alg get_checksum_alg(const uchar *buf, ulong len); extern TYPELIB binlog_checksum_typelib; #ifdef WITH_WSREP enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size); #endif /* WITH_WSREP */ /** @} (end of group Replication) */ int binlog_buf_compress(const uchar *src, uchar *dst, uint32 len, uint32 *comlen); int binlog_buf_uncompress(const uchar *src, uchar *dst, uint32 len, uint32 *newlen); uint32 binlog_get_compress_len(uint32 len); uint32 binlog_get_uncompress_len(const uchar *buf); int query_event_uncompress(const Format_description_log_event *description_event, bool contain_checksum, const uchar *src, ulong src_len, uchar *buf, ulong buf_size, bool* is_malloc, uchar **dst, ulong *newlen); int row_log_event_uncompress(const Format_description_log_event *description_event, bool contain_checksum, const uchar *src, ulong src_len, uchar* buf, ulong buf_size, bool *is_malloc, uchar **dst, ulong *newlen); bool is_parallel_retry_error(rpl_group_info *rgi, int err); /* Compares two GTIDs to facilitate sorting a GTID list log event by domain id (ascending) and sequence number (ascending) */ int compare_glle_gtids(const void * _gtid1, const void *_gtid2); #endif /* _log_event_h */ ssl_compat.h 0000644 00000006464 15156036141 0007075 0 ustar 00 /* Copyright (c) 2016, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <openssl/opensslv.h> /* OpenSSL version specific definitions */ #if defined(OPENSSL_VERSION_NUMBER) #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000L) #define HAVE_OPENSSL11 1 #define SSL_LIBRARY OpenSSL_version(OPENSSL_VERSION) #define ERR_remove_state(X) ERR_clear_error() #define EVP_CIPHER_CTX_SIZE 200 #define EVP_MD_CTX_SIZE 80 #undef EVP_MD_CTX_init #define EVP_MD_CTX_init(X) do { memset((X), 0, EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0) #undef EVP_CIPHER_CTX_init #define EVP_CIPHER_CTX_init(X) do { memset((X), 0, EVP_CIPHER_CTX_SIZE); EVP_CIPHER_CTX_reset(X); } while(0) /* Macros below are deprecated. OpenSSL 1.1 may define them or not, depending on how it was built. */ #undef ERR_free_strings #define ERR_free_strings() #undef EVP_cleanup #define EVP_cleanup() #undef CRYPTO_cleanup_all_ex_data #define CRYPTO_cleanup_all_ex_data() #undef SSL_load_error_strings #define SSL_load_error_strings() #else #define HAVE_OPENSSL10 1 #ifdef HAVE_WOLFSSL #define SSL_LIBRARY "WolfSSL " WOLFSSL_VERSION #else #define SSL_LIBRARY SSLeay_version(SSLEAY_VERSION) #endif #ifdef HAVE_WOLFSSL #undef ERR_remove_state #define ERR_remove_state(x) do {} while(0) #undef SSL_get_cipher #define SSL_get_cipher(ssl) (SSL_version(ssl) == TLS1_3_VERSION ? wolfSSL_get_cipher(ssl) : wolfSSL_get_cipher_name(ssl)) #undef SSL_get_cipher_list #define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list(i) #elif defined (HAVE_ERR_remove_thread_state) #define ERR_remove_state(X) ERR_remove_thread_state(NULL) #endif /* HAVE_ERR_remove_thread_state */ #endif /* HAVE_OPENSSL11 */ #endif #ifdef HAVE_WOLFSSL #define EVP_MD_CTX_SIZE sizeof(wc_Md5) #endif #ifndef HAVE_OPENSSL11 #ifndef ASN1_STRING_get0_data #define ASN1_STRING_get0_data(X) ASN1_STRING_data(X) #endif #ifndef EVP_MD_CTX_SIZE #define EVP_MD_CTX_SIZE sizeof(EVP_MD_CTX) #endif #ifndef DH_set0_pqg #define DH_set0_pqg(D,P,Q,G) ((D)->p= (P), (D)->g= (G)) #endif #define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt) #define EVP_CIPHER_CTX_SIZE sizeof(EVP_CIPHER_CTX) #ifndef HAVE_WOLFSSL #define OPENSSL_init_ssl(X,Y) SSL_library_init() #define EVP_MD_CTX_reset(X) EVP_MD_CTX_cleanup(X) #define EVP_CIPHER_CTX_reset(X) EVP_CIPHER_CTX_cleanup(X) #define X509_get0_notBefore(X) X509_get_notBefore(X) #define X509_get0_notAfter(X) X509_get_notAfter(X) #endif #endif #ifndef TLS1_3_VERSION #define SSL_CTX_set_ciphersuites(X,Y) 0 #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ int check_openssl_compatibility(); #ifdef __cplusplus } #endif pfs_table_provider.h 0000644 00000005101 15156036141 0010565 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_TABLE_PROVIDER_H #define PFS_TABLE_PROVIDER_H /** @file include/pfs_table_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_TABLE_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_TABLE_CALL(M) pfs_ ## M ## _v1 C_MODE_START PSI_table_share* pfs_get_table_share_v1(my_bool temporary, struct TABLE_SHARE *share); void pfs_release_table_share_v1(PSI_table_share* share); void pfs_drop_table_share_v1(my_bool temporary, const char *schema_name, int schema_name_length, const char *table_name, int table_name_length); PSI_table* pfs_open_table_v1(PSI_table_share *share, const void *identity); void pfs_unbind_table_v1(PSI_table *table); PSI_table * pfs_rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table); void pfs_close_table_v1(struct TABLE_SHARE *server_share, PSI_table *table); PSI_table_locker* pfs_start_table_io_wait_v1(PSI_table_locker_state *state, PSI_table *table, PSI_table_io_operation op, uint index, const char *src_file, uint src_line); PSI_table_locker* pfs_start_table_lock_wait_v1(PSI_table_locker_state *state, PSI_table *table, PSI_table_lock_operation op, ulong op_flags, const char *src_file, uint src_line); void pfs_end_table_io_wait_v1(PSI_table_locker* locker, ulonglong numrows); void pfs_end_table_lock_wait_v1(PSI_table_locker* locker); void pfs_unlock_table_v1(PSI_table *table); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_TABLE_INTERFACE */ #endif sql_alter.h 0000644 00000036125 15156036141 0006714 0 ustar 00 /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. Copyright (c) 2013, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_ALTER_TABLE_H #define SQL_ALTER_TABLE_H class Alter_drop; class Alter_column; class Alter_rename_key; class Alter_index_ignorability; class Key; /** Data describing the table being created by CREATE TABLE or altered by ALTER TABLE. */ class Alter_info { public: enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; bool vers_prohibited(THD *thd) const; /** The different values of the ALGORITHM clause. Describes which algorithm to use when altering the table. */ enum enum_alter_table_algorithm { /* Use thd->variables.alter_algorithm for alter method. If this is also default then use the fastest possible ALTER TABLE method (INSTANT, NOCOPY, INPLACE, COPY) */ ALTER_TABLE_ALGORITHM_DEFAULT, // Copy if supported, error otherwise. ALTER_TABLE_ALGORITHM_COPY, // In-place if supported, error otherwise. ALTER_TABLE_ALGORITHM_INPLACE, // No Copy will refuse any operation which does rebuild. ALTER_TABLE_ALGORITHM_NOCOPY, // Instant should allow any operation that changes metadata only. ALTER_TABLE_ALGORITHM_INSTANT, // When there is no specification of algorithm during alter table. ALTER_TABLE_ALGORITHM_NONE }; /** The different values of the LOCK clause. Describes the level of concurrency during ALTER TABLE. */ enum enum_alter_table_lock { // Maximum supported level of concurency for the given operation. ALTER_TABLE_LOCK_DEFAULT, // Allow concurrent reads & writes. If not supported, give error. ALTER_TABLE_LOCK_NONE, // Allow concurrent reads only. If not supported, give error. ALTER_TABLE_LOCK_SHARED, // Block reads and writes. ALTER_TABLE_LOCK_EXCLUSIVE }; Lex_table_name db, table_name; // Columns and keys to be dropped. List<Alter_drop> drop_list; // Columns for ALTER_CHANGE_COLUMN_DEFAULT. List<Alter_column> alter_list; // List of keys, used by both CREATE and ALTER TABLE. List<Key> key_list; // List of keys to be renamed. List<Alter_rename_key> alter_rename_key_list; // List of columns, used by both CREATE and ALTER TABLE. List<Create_field> create_list; // Indexes whose ignorability needs to be changed. List<Alter_index_ignorability> alter_index_ignorability_list; List<Virtual_column_info> check_constraint_list; // Type of ALTER TABLE operation. alter_table_operations flags; ulong partition_flags; // Enable or disable keys. enum_enable_or_disable keys_onoff; // Used only in add_stat_drop_index() TABLE *original_table; // List of partitions. List<const char> partition_names; // Number of partitions. uint num_parts; /* List of fields that we should delete statistics from */ List<Field> drop_stat_fields; struct DROP_INDEX_STAT_PARAMS { KEY *key; bool ext_prefixes_only; }; struct RENAME_COLUMN_STAT_PARAMS { Field *field; LEX_CSTRING *name; uint duplicate_counter; // For temporary names }; struct RENAME_INDEX_STAT_PARAMS { const KEY *key; const LEX_CSTRING *name; uint duplicate_counter; // For temporary names uint usage_count; // How many rename entries }; /* List of index that we should delete statistics from */ List<DROP_INDEX_STAT_PARAMS> drop_stat_indexes; List<RENAME_COLUMN_STAT_PARAMS> rename_stat_fields; List<RENAME_INDEX_STAT_PARAMS> rename_stat_indexes; bool add_stat_drop_index(KEY *key, bool ext_prefixes_only, MEM_ROOT *mem_root) { DROP_INDEX_STAT_PARAMS *param; if (!(param= (DROP_INDEX_STAT_PARAMS*) alloc_root(mem_root, sizeof(*param)))) return true; param->key= key; param->ext_prefixes_only= ext_prefixes_only; return drop_stat_indexes.push_back(param, mem_root); } bool add_stat_drop_index(THD *thd, const LEX_CSTRING *key_name); bool add_stat_rename_index(const KEY *key, const LEX_CSTRING *name, MEM_ROOT *mem_root) { RENAME_INDEX_STAT_PARAMS *param; if (!(param= (RENAME_INDEX_STAT_PARAMS*) alloc_root(mem_root, sizeof(*param)))) return true; param->key= key; param->name= name; param->usage_count= 0; return rename_stat_indexes.push_back(param, mem_root); } bool add_stat_rename_field(Field *field, LEX_CSTRING *name, MEM_ROOT *mem_root) { RENAME_COLUMN_STAT_PARAMS *param; if (!(param= (RENAME_COLUMN_STAT_PARAMS*) alloc_root(mem_root, sizeof(*param)))) return true; param->field= field; param->name= name; param->duplicate_counter= 0; return rename_stat_fields.push_back(param, mem_root); } bool collect_renamed_fields(THD *thd); /* Delete/update statistics in EITS tables */ void apply_statistics_deletes_renames(THD *thd, TABLE *table); private: // Type of ALTER TABLE algorithm. enum_alter_table_algorithm requested_algorithm; public: // Type of ALTER TABLE lock. enum_alter_table_lock requested_lock; Alter_info() : flags(0), partition_flags(0), keys_onoff(LEAVE_AS_IS), original_table(0), num_parts(0), requested_algorithm(ALTER_TABLE_ALGORITHM_NONE), requested_lock(ALTER_TABLE_LOCK_DEFAULT) {} void reset() { drop_list.empty(); alter_list.empty(); key_list.empty(); alter_rename_key_list.empty(); create_list.empty(); alter_index_ignorability_list.empty(); check_constraint_list.empty(); drop_stat_fields.empty(); drop_stat_indexes.empty(); rename_stat_fields.empty(); rename_stat_indexes.empty(); flags= 0; partition_flags= 0; keys_onoff= LEAVE_AS_IS; num_parts= 0; partition_names.empty(); requested_algorithm= ALTER_TABLE_ALGORITHM_NONE; requested_lock= ALTER_TABLE_LOCK_DEFAULT; } /** Construct a copy of this object to be used for mysql_alter_table and mysql_create_table. Historically, these two functions modify their Alter_info arguments. This behaviour breaks re-execution of prepared statements and stored procedures and is compensated by always supplying a copy of Alter_info to these functions. @param rhs Alter_info to make copy of @param mem_root Mem_root for new Alter_info @note You need to use check the error in THD for out of memory condition after calling this function. */ Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root); /** Parses the given string and sets requested_algorithm if the string value matches a supported value. Supported values: INPLACE, COPY, DEFAULT @param str String containing the supplied value @retval false Supported value found, state updated @retval true Not supported value, no changes made */ bool set_requested_algorithm(const LEX_CSTRING *str); /** Parses the given string and sets requested_lock if the string value matches a supported value. Supported values: NONE, SHARED, EXCLUSIVE, DEFAULT @param str String containing the supplied value @retval false Supported value found, state updated @retval true Not supported value, no changes made */ bool set_requested_lock(const LEX_CSTRING *str); /** Set the requested algorithm to the given algorithm value @param algo_value algorithm to be set */ void set_requested_algorithm(enum_alter_table_algorithm algo_value); /** Returns the algorithm value in the format "algorithm=value" */ const char* algorithm_clause(THD *thd) const; /** Returns the lock value in the format "lock=value" */ const char* lock() const; /** Check whether the given result can be supported with the specified user alter algorithm. @param thd Thread handle @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data during in-place alter @retval false Supported operation @retval true Not supported value */ bool supports_algorithm(THD *thd, const Alter_inplace_info *ha_alter_info); /** Check whether the given result can be supported with the specified user lock type. @param ha_alter_info Structure describing changes to be done by ALTER TABLE and holding data during in-place alter @retval false Supported lock type @retval true Not supported value */ bool supports_lock(THD *thd, bool, Alter_inplace_info *ha_alter_info); /** Return user requested algorithm. If user does not specify algorithm then return alter_algorithm variable value. */ enum_alter_table_algorithm algorithm(const THD *thd) const; bool algorithm_is_nocopy(const THD *thd) const; uint check_vcol_field(Item_field *f) const; private: Alter_info &operator=(const Alter_info &rhs); // not implemented Alter_info(const Alter_info &rhs); // not implemented }; /** Runtime context for ALTER TABLE. */ class Alter_table_ctx { public: Alter_table_ctx(); Alter_table_ctx(THD *thd, TABLE_LIST *table_list, uint tables_opened_arg, const LEX_CSTRING *new_db_arg, const LEX_CSTRING *new_name_arg); /** @return true if the table is moved to another database or a new table created by ALTER_PARTITION_CONVERT_OUT, false otherwise. */ bool is_database_changed() const { return (new_db.str != db.str); }; /** @return true if the table is renamed or a new table created by ALTER_PARTITION_CONVERT_OUT, false otherwise. */ bool is_table_renamed() const { return (is_database_changed() || new_name.str != table_name.str); }; /** @return filename (including .frm) for the new table. */ const char *get_new_filename() const { DBUG_ASSERT(!tmp_table); return new_filename; } /** @return path to the original table. */ const char *get_path() const { DBUG_ASSERT(!tmp_table); return path; } /** @return path to the new table. */ const char *get_new_path() const { DBUG_ASSERT(!tmp_table); return new_path; } /** @return path to the temporary table created during ALTER TABLE. */ const char *get_tmp_path() const { return tmp_path; } const LEX_CSTRING get_tmp_cstring_path() const { LEX_CSTRING tmp= { tmp_path, strlen(tmp_path) }; return tmp; }; /** Mark ALTER TABLE as needing to produce foreign key error if it deletes a row from the table being changed. */ void set_fk_error_if_delete_row(FOREIGN_KEY_INFO *fk) { fk_error_if_delete_row= true; fk_error_id= fk->foreign_id->str; fk_error_table= fk->foreign_table->str; } void report_implicit_default_value_error(THD *thd, const TABLE_SHARE *) const; public: Create_field *implicit_default_value_error_field= nullptr; bool error_if_not_empty= false; uint tables_opened= 0; LEX_CSTRING db; LEX_CSTRING table_name; LEX_CSTRING storage_engine_name; LEX_CSTRING alias; LEX_CSTRING new_db; LEX_CSTRING new_name; LEX_CSTRING new_alias; LEX_CSTRING tmp_name; LEX_CSTRING tmp_storage_engine_name; LEX_CUSTRING tmp_id, id; char tmp_buff[80]; uchar id_buff[MY_UUID_SIZE]; char storage_engine_buff[NAME_LEN], tmp_storage_engine_buff[NAME_LEN]; bool storage_engine_partitioned; bool tmp_storage_engine_name_partitioned; /** Indicates that if a row is deleted during copying of data from old version of table to the new version ER_FK_CANNOT_DELETE_PARENT error should be emitted. */ bool fk_error_if_delete_row= false; /** Name of foreign key for the above error. */ const char *fk_error_id= nullptr; /** Name of table for the above error. */ const char *fk_error_table= nullptr; bool modified_primary_key= false; bool fast_alter_partition= false; /** Indicates that we are altering temporary table */ bool tmp_table= false; private: char new_filename[FN_REFLEN + 1]; char new_alias_buff[NAME_LEN + 1]; char tmp_name_buff[NAME_LEN + 1]; char path[FN_REFLEN + 1]; char new_path[FN_REFLEN + 1]; char tmp_path[FN_REFLEN + 1]; Alter_table_ctx &operator=(const Alter_table_ctx &rhs); // not implemented Alter_table_ctx(const Alter_table_ctx &rhs); // not implemented }; /** Sql_cmd_common_alter_table represents the common properties of the ALTER TABLE statements. @todo move Alter_info and other ALTER generic structures from Lex here. */ class Sql_cmd_common_alter_table : public Sql_cmd { protected: /** Constructor. */ Sql_cmd_common_alter_table() = default; virtual ~Sql_cmd_common_alter_table() = default; enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; /** Sql_cmd_alter_table represents the generic ALTER TABLE statement. @todo move Alter_info and other ALTER specific structures from Lex here. */ class Sql_cmd_alter_table : public Sql_cmd_common_alter_table, public Storage_engine_name { public: /** Constructor, used to represent a ALTER TABLE statement. */ Sql_cmd_alter_table() = default; ~Sql_cmd_alter_table() = default; Storage_engine_name *option_storage_engine_name() override { return this; } bool execute(THD *thd) override; }; /** Sql_cmd_alter_sequence represents the ALTER SEQUENCE statement. */ class Sql_cmd_alter_sequence : public Sql_cmd, public DDL_options { public: /** Constructor, used to represent a ALTER TABLE statement. */ Sql_cmd_alter_sequence(const DDL_options &options) :DDL_options(options) {} ~Sql_cmd_alter_sequence() = default; enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_SEQUENCE; } bool execute(THD *thd) override; }; /** Sql_cmd_alter_table_tablespace represents ALTER TABLE IMPORT/DISCARD TABLESPACE statements. */ class Sql_cmd_discard_import_tablespace : public Sql_cmd_common_alter_table { public: enum enum_tablespace_op_type { DISCARD_TABLESPACE, IMPORT_TABLESPACE }; Sql_cmd_discard_import_tablespace(enum_tablespace_op_type tablespace_op_arg) : m_tablespace_op(tablespace_op_arg) {} bool execute(THD *thd) override; private: const enum_tablespace_op_type m_tablespace_op; }; #endif lex_charset.h 0000644 00000063654 15156036141 0007236 0 ustar 00 /* Copyright (c) 2021, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef LEX_CHARSET_INCLUDED #define LEX_CHARSET_INCLUDED #include "charset_collations.h" /* An extention for Charset_loader_mysys, with server error and warning support. */ class Charset_loader_server: public Charset_loader_mysys { public: using Charset_loader_mysys::Charset_loader_mysys; void raise_unknown_collation_error(const char *name) const; void raise_not_applicable_error(const char *cs, const char *cl) const; /* Find an exact collation by name. Raise an error on a faulure. @param cs - the character set @param collation_name - the collation name, e.g. "utf8_bin" @param my_flags - my flags, e.g. MYF(WME) @returns - a NULL pointer in case of failure, or a CHARSET_INFO pointer on success. */ CHARSET_INFO * get_exact_collation_or_error(const char *name, myf my_flags= MYF(0)) { CHARSET_INFO *ci= get_exact_collation(name, my_flags); if (!ci) raise_unknown_collation_error(name); return ci; } /* Find an exact collation by a character set and a contextually typed collation name. Raise an error on in case of a faulure. @param cs - the character set @param context_cl_name - the context name, e.g. "uca1400_cs_ci" @param my_flags - my flags, e.g. MYF(WME) @returns - a NULL pointer in case of failure, or a CHARSET_INFO pointer on success. */ CHARSET_INFO * get_exact_collation_by_context_name_or_error(CHARSET_INFO *cs, const char *name, myf my_flags= MYF(0)) { CHARSET_INFO *ci= get_exact_collation_by_context_name(cs, name, my_flags); if (!ci) raise_not_applicable_error(cs->cs_name.str, name); return ci; } /* Find an abstract context collation by name. Raise an error on a faulure. The returned pointer needs to be resolved to a character set name. It should not be passed directly to the character set routines. @param cs - the character set @param context_cl_name - the context name, e.g. "uca1400_cs_ci" @param my_flags - my flags, e.g. MYF(WME) @returns - a NULL pointer in case of failure, or a CHARSET_INFO pointer on success. */ CHARSET_INFO * get_context_collation_or_error(const char *collation_name, myf my_flags= MYF(0)) { CHARSET_INFO *ci= get_context_collation(collation_name, my_flags); if (!ci) raise_unknown_collation_error(collation_name); return ci; } /* Find an exact binary collation in the given character set. Raise an error on a faulure. @param cs - the character set @param my_flags - my flags, e.g. MYF(WME) @returns - a NULL pointer in case of failure, or a CHARSET_INFO pointer on success. */ CHARSET_INFO * get_bin_collation_or_error(CHARSET_INFO *cs, myf my_flags= MYF(0)) { const char *cs_name= cs->cs_name.str; if (!(cs= get_bin_collation(cs, my_flags))) { char tmp[65]; strxnmov(tmp, sizeof(tmp)-1, cs_name, "_bin", NULL); raise_unknown_collation_error(tmp); } return cs; } /* Find an exact default collation in the given character set. This routine does not fail. Any character set must have a default collation. @param cs - the character set @param my_flags - my flags, e.g. MYF(WME) @returns - a CHARSET_INFO pointer */ CHARSET_INFO *get_default_collation(CHARSET_INFO *cs, myf my_flags= MYF(0)) { return Charset_loader_mysys::get_default_collation(cs, my_flags); } }; ///////////////////////////////////////////////////////////////////// /* An exact character set, e.g: CHARACTER SET latin1 */ class Lex_exact_charset { CHARSET_INFO *m_ci; public: explicit Lex_exact_charset(CHARSET_INFO *ci) :m_ci(ci) { DBUG_ASSERT(m_ci); DBUG_ASSERT(m_ci->state & MY_CS_PRIMARY); } CHARSET_INFO *charset_info() const { return m_ci; } bool raise_if_not_equal(const Lex_exact_charset &rhs) const; bool raise_if_not_applicable(const class Lex_exact_collation &cl) const; }; /* An optional contextually typed character set: [ CHARACTER SET DEFAULT ] */ class Lex_opt_context_charset_st { /* Currently we support only DEFAULT as a possible value. So "bool" is enough. */ bool m_had_charset_default; public: void init() { m_had_charset_default= false; } void merge_charset_default() { /* Ok to specify CHARACTER SET DEFAULT multiple times. No error raised here. */ m_had_charset_default= true; } bool is_empty() const { return !m_had_charset_default; } bool is_contextually_typed_charset_default() const { return m_had_charset_default; } }; /* A contextually typed collation, e.g.: COLLATE DEFAULT CHAR(10) BINARY */ class Lex_context_collation { CHARSET_INFO *m_ci; public: explicit Lex_context_collation(CHARSET_INFO *ci) :m_ci(ci) { DBUG_ASSERT(ci); } CHARSET_INFO *charset_info() const { return m_ci; } bool is_contextually_typed_collate_default() const { return m_ci == &my_collation_contextually_typed_default; } bool is_contextually_typed_binary_style() const { return m_ci == &my_collation_contextually_typed_binary; } bool raise_if_not_equal(const Lex_context_collation &cl) const; /* Skip the character set prefix, return the suffix. utf8mb4_uca1400_as_ci -> uca1400_as_ci */ LEX_CSTRING collation_name_context_suffix() const { return m_ci->get_collation_name(MY_COLLATION_NAME_MODE_CONTEXT); } LEX_CSTRING collation_name_for_show() const; }; /* An exact collation, e.g. COLLATE latin1_swedish_ci */ class Lex_exact_collation { CHARSET_INFO *m_ci; public: explicit Lex_exact_collation(CHARSET_INFO *ci) :m_ci(ci) { DBUG_ASSERT(ci); } CHARSET_INFO *charset_info() const { return m_ci; } // EXACT + EXACT bool raise_if_not_equal(const Lex_exact_collation &cl) const; // EXACT + CONTEXT // CONTEXT + EXACT bool raise_if_conflicts_with_context_collation(const Lex_context_collation &, bool reverse_order) const; }; /* Parse time COLLATE clause: COLLATE colation_name The collation can be either exact or contextual: COLLATE latin1_bin COLLATE DEFAULT */ class Lex_extended_collation_st { public: enum Type { TYPE_EXACT, TYPE_CONTEXTUALLY_TYPED }; protected: CHARSET_INFO *m_ci; Type m_type; public: void init(CHARSET_INFO *ci, Type type) { m_ci= ci; m_type= type; } CHARSET_INFO *charset_info() const { return m_ci; } Type type() const { return m_type; } LEX_CSTRING collation_name_for_show() const { switch (m_type) { case TYPE_CONTEXTUALLY_TYPED: return Lex_context_collation(m_ci).collation_name_for_show(); case TYPE_EXACT: return m_ci->coll_name; } DBUG_ASSERT(0); return m_ci->coll_name; } static Lex_extended_collation_st collate_default() { Lex_extended_collation_st res; res.set_collate_default(); return res; } void set_collate_default() { m_ci= &my_collation_contextually_typed_default; m_type= TYPE_CONTEXTUALLY_TYPED; } bool set_by_name(const char *name, myf my_flags); // e.g. MY_UTF8_IS_UTF8MB3 bool raise_if_conflicts_with_context_collation(const Lex_context_collation &) const; bool merge_exact_charset(Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset &rhs); bool merge_exact_collation(const Lex_exact_collation &rhs); bool merge(const Lex_extended_collation_st &rhs); }; class Lex_extended_collation: public Lex_extended_collation_st { public: Lex_extended_collation(CHARSET_INFO *ci, Type type) { init(ci, type); } Lex_extended_collation(const Lex_exact_collation &rhs) { init(rhs.charset_info(), TYPE_EXACT); } Lex_extended_collation(const Lex_context_collation &rhs) { init(rhs.charset_info(), TYPE_CONTEXTUALLY_TYPED); } }; /* CHARACTER SET cs_exact [COLLATE cl_exact_or_context] */ class Lex_exact_charset_opt_extended_collate { CHARSET_INFO *m_ci; bool m_with_collate; public: Lex_exact_charset_opt_extended_collate(CHARSET_INFO *ci, bool with_collate) :m_ci(ci), m_with_collate(with_collate) { DBUG_ASSERT(m_ci); DBUG_ASSERT((m_ci->state & MY_CS_PRIMARY) || m_with_collate); } Lex_exact_charset_opt_extended_collate(const Lex_exact_charset &cs) :m_ci(cs.charset_info()), m_with_collate(false) { DBUG_ASSERT(m_ci); DBUG_ASSERT(m_ci->state & MY_CS_PRIMARY); } Lex_exact_charset_opt_extended_collate(const Lex_exact_collation &cl) :m_ci(cl.charset_info()), m_with_collate(true) { DBUG_ASSERT(m_ci); } bool with_collate() const { return m_with_collate; } CHARSET_INFO *find_bin_collation() const; CHARSET_INFO *find_compiled_default_collation() const; CHARSET_INFO *find_mapped_default_collation( Sql_used *used, const Charset_collation_map_st &map) const; bool raise_if_charsets_differ(const Lex_exact_charset &cs) const; bool raise_if_not_applicable(const Lex_exact_collation &cl) const; /* Add another COLLATE clause (exact or context). So the full syntax looks like: CHARACTER SET cs [COLLATE cl] ... COLLATE cl2 */ bool merge_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl) { switch (cl.type()) { case Lex_extended_collation_st::TYPE_EXACT: return merge_exact_collation(Lex_exact_collation(cl.charset_info())); case Lex_extended_collation_st::TYPE_CONTEXTUALLY_TYPED: return merge_context_collation(used, map, Lex_context_collation(cl.charset_info())); } DBUG_ASSERT(0); return false; } bool merge_collation_override(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl) { switch (cl.type()) { case Lex_extended_collation_st::TYPE_EXACT: return merge_exact_collation_override( Lex_exact_collation(cl.charset_info())); case Lex_extended_collation_st::TYPE_CONTEXTUALLY_TYPED: return merge_context_collation_override( used, map, Lex_context_collation(cl.charset_info())); } DBUG_ASSERT(0); return false; } /* Add a context collation: CHARACTER SET cs [COLLATE cl] ... COLLATE DEFAULT */ bool merge_context_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_context_collation &cl); bool merge_context_collation_override(Sql_used *used, const Charset_collation_map_st &map, const Lex_context_collation &cl); /* Add an exact collation: CHARACTER SET cs [COLLATE cl] ... COLLATE latin1_bin */ bool merge_exact_collation(const Lex_exact_collation &cl); bool merge_exact_collation_override(const Lex_exact_collation &cl); Lex_exact_collation collation() const { return Lex_exact_collation(m_ci); } Lex_exact_charset charset() const { if ((m_ci->state & MY_CS_PRIMARY)) return Lex_exact_charset(m_ci); return Lex_exact_charset(find_compiled_default_collation()); } }; /* Parse time character set and collation for: [CHARACTER SET cs_exact] [COLLATE cl_exact_or_context] Can be: 1. Empty (not specified on the column level): CREATE TABLE t1 (a CHAR(10)) CHARACTER SET latin2; -- (1a) CREATE TABLE t1 (a CHAR(10)); -- (1b) 2. Precisely typed: CREATE TABLE t1 (a CHAR(10) COLLATE latin1_bin); -- (2a) CREATE TABLE t1 ( a CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin); -- (2b) 3. Contextually typed: CREATE TABLE t2 (a CHAR(10) BINARY) CHARACTER SET latin2; -- (3a) CREATE TABLE t2 (a CHAR(10) BINARY); -- (3b) CREATE TABLE t2 (a CHAR(10) COLLATE DEFAULT) CHARACER SET latin2 COLLATE latin2_bin; -- (3c) In case of an empty or a contextually typed collation, it is a subject to later resolution, when the context character set becomes known in the end of the CREATE statement: - either after the explicit table level CHARACTER SET, like in (1a,3a,3c) - or by the inhereted database level CHARACTER SET, like in (1b,3b) Resolution happens in Type_handler::Column_definition_prepare_stage1(). */ struct Lex_exact_charset_extended_collation_attrs_st { public: enum Type { TYPE_EMPTY= 0, TYPE_CHARACTER_SET= 1, TYPE_COLLATE_EXACT= 2, TYPE_CHARACTER_SET_COLLATE_EXACT= 3, TYPE_COLLATE_CONTEXTUALLY_TYPED= 4 }; // Number of bits required to store enum Type values #define LEX_CHARSET_COLLATION_TYPE_BITS 3 #define LEX_CHARSET_COLLATION_TYPE_MASK ((1<<LEX_CHARSET_COLLATION_TYPE_BITS)-1) static_assert(LEX_CHARSET_COLLATION_TYPE_MASK >= TYPE_COLLATE_CONTEXTUALLY_TYPED, "Lex_exact_charset_extended_collation_attrs_st::Type bits"); protected: CHARSET_INFO *m_ci; Type m_type; protected: static Type type_from_lex_collation_type(Lex_extended_collation_st::Type type) { switch (type) { case Lex_extended_collation_st::TYPE_EXACT: return TYPE_COLLATE_EXACT; case Lex_extended_collation_st::TYPE_CONTEXTUALLY_TYPED: return TYPE_COLLATE_CONTEXTUALLY_TYPED; } DBUG_ASSERT(0); return TYPE_COLLATE_EXACT; } public: void init() { m_ci= NULL; m_type= TYPE_EMPTY; } void init(CHARSET_INFO *cs, Type type) { DBUG_ASSERT(cs || type == TYPE_EMPTY); m_ci= cs; m_type= type; } void init(const Lex_exact_charset &cs) { m_ci= cs.charset_info(); m_type= TYPE_CHARACTER_SET; } void init(const Lex_exact_collation &cs) { m_ci= cs.charset_info(); m_type= TYPE_COLLATE_EXACT; } void init(const Lex_exact_charset_opt_extended_collate &cscl) { if (cscl.with_collate()) init(cscl.collation().charset_info(), TYPE_CHARACTER_SET_COLLATE_EXACT); else init(cscl.charset()); } bool is_empty() const { return m_type == TYPE_EMPTY; } void set_charset(const Lex_exact_charset &cs) { m_ci= cs.charset_info(); m_type= TYPE_CHARACTER_SET; } bool set_charset_collate_default(Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset &cs) { CHARSET_INFO *ci; if (!(ci= Lex_exact_charset_opt_extended_collate(cs). find_mapped_default_collation(used, map))) return true; m_ci= ci; m_type= TYPE_CHARACTER_SET_COLLATE_EXACT; return false; } bool set_charset_collate_binary(const Lex_exact_charset &cs) { CHARSET_INFO *ci; if (!(ci= Lex_exact_charset_opt_extended_collate(cs).find_bin_collation())) return true; m_ci= ci; m_type= TYPE_CHARACTER_SET_COLLATE_EXACT; return false; } void set_collate_default() { m_ci= &my_collation_contextually_typed_default; m_type= TYPE_COLLATE_CONTEXTUALLY_TYPED; } void set_contextually_typed_binary_style() { m_ci= &my_collation_contextually_typed_binary; m_type= TYPE_COLLATE_CONTEXTUALLY_TYPED; } bool is_contextually_typed_collate_default() const { return Lex_context_collation(m_ci).is_contextually_typed_collate_default(); } CHARSET_INFO *charset_info() const { return m_ci; } CHARSET_INFO *charset_info(Sql_used *used, const Charset_collation_map_st &map) const { switch (m_type) { case TYPE_CHARACTER_SET: return map.get_collation_for_charset(used, m_ci); case TYPE_EMPTY: case TYPE_CHARACTER_SET_COLLATE_EXACT: case TYPE_COLLATE_CONTEXTUALLY_TYPED: case TYPE_COLLATE_EXACT: break; } return m_ci; } Type type() const { return m_type; } bool is_contextually_typed_collation() const { return m_type == TYPE_COLLATE_CONTEXTUALLY_TYPED; } CHARSET_INFO *resolved_to_character_set(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs) const; /* Merge the column CHARACTER SET clause to: - an exact collation name - a contextually typed collation "this" corresponds to `CHARACTER SET xxx [BINARY]` "cl" corresponds to the COLLATE clause */ bool merge_column_charset_clause_and_collate_clause( Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset_extended_collation_attrs_st &cl) { switch (cl.type()) { case TYPE_EMPTY: return false; case TYPE_COLLATE_EXACT: return merge_exact_collation(Lex_exact_collation(cl.m_ci)); case TYPE_COLLATE_CONTEXTUALLY_TYPED: return merge_context_collation(used, map, Lex_context_collation(cl.m_ci)); case TYPE_CHARACTER_SET: case TYPE_CHARACTER_SET_COLLATE_EXACT: break; } DBUG_ASSERT(0); return false; } /* This method is used in the "attribute_list" rule to merge two independent COLLATE clauses (not belonging to a CHARACTER SET clause). "BINARY" and "COLLATE DEFAULT" are not possible in an independent COLLATE clause in a column attribute. */ bool merge_column_collate_clause_and_collate_clause( Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset_extended_collation_attrs_st &cl) { DBUG_ASSERT(m_type != TYPE_CHARACTER_SET); switch (cl.type()) { case TYPE_EMPTY: return false; case TYPE_COLLATE_EXACT: return merge_exact_collation(Lex_exact_collation(cl.m_ci)); case TYPE_COLLATE_CONTEXTUALLY_TYPED: return merge_context_collation(used, map, Lex_context_collation(cl.m_ci)); case TYPE_CHARACTER_SET: case TYPE_CHARACTER_SET_COLLATE_EXACT: break; } DBUG_ASSERT(0); return false; } bool merge_exact_charset(Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset &cs); bool merge_exact_collation(const Lex_exact_collation &cl); bool merge_context_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_context_collation &cl); bool merge_collation(Sql_used *used, const Charset_collation_map_st &map, const Lex_extended_collation_st &cl); }; class Charset_collation_context { /* Although the goal of m_charset_default is to store the meaning of CHARACTER SET DEFAULT, it does not necessarily point to a default collation of CHARACTER SET DEFAULT. It can point to its any arbitrary collation. For performance purposes we don't need to find the default collation at the instantiation time of "this", because: - m_charset_default may not be even needed during the resolution - when it's needed, in many cases it's passed to my_charset_same(), which does not need the default collation again. Note, m_charset_default and m_collate_default are not necessarily equal. - The default value for CHARACTER SET is taken from the upper level: CREATE DATABASE db1 CHARACTER SET DEFAULT; <-- @@character_set_server ALTER DATABASE db1 CHARACTER SET DEFAULT; <-- @@character_set_server - The default value for COLLATE is taken from the upper level for CREATE: CREATE DATABASE db1 COLLATE DEFAULT; <-- @@collation_server CREATE TABLE db1.t1 COLLATE DEFAULT; <-- character set of "db1" - The default value for COLLATE is taken from the same level for ALTER: ALTER DATABASE db1 COLLATE DEFAULT; <-- the default collation of the current db1 character set ALTER TABLE db1.t1 COLLATE DEFAULT; <-- the default collation of the current db1.t1 character set */ // comes from the upper level Lex_exact_charset_opt_extended_collate m_charset_default; // comes from the upper or the current level Lex_exact_collation m_collate_default; public: Charset_collation_context(CHARSET_INFO *charset_default, CHARSET_INFO *collate_default) :m_charset_default(charset_default, !(charset_default->state & MY_CS_PRIMARY)), m_collate_default(collate_default) { } const Lex_exact_charset_opt_extended_collate charset_default() const { return m_charset_default; } const Lex_exact_collation collate_default() const { return m_collate_default; } }; /* A universal container. It can store at the same time: - CHARACTER SET DEFAULT - CHARACTER SET cs_exact - COLLATE {cl_exact|cl_context} All three parts can co-exist. All three parts are optional. Parts can come in any arbitrary order, e.g: CHARACTER SET DEFAULT [CHARACTER SET latin1] COLLATE latin1_bin CHARACTER SET latin1 CHARACTER SET DEFAULT COLLATE latin1_bin COLLATE latin1_bin [CHARACTER SET latin1] CHARACTER SET DEFAULT COLLATE latin1_bin CHARACTER SET DEFAULT [CHARACTER SET latin1] */ class Lex_extended_charset_extended_collation_attrs_st: public Lex_opt_context_charset_st, public Lex_exact_charset_extended_collation_attrs_st { enum charset_type_t { CHARSET_TYPE_EMPTY, CHARSET_TYPE_CONTEXT, CHARSET_TYPE_EXACT }; /* Which part came first: - CHARACTER SET DEFAULT or - CHARACTER SET cs_exact e.g. to produce error messages preserving the user typed order of CHARACTER SET clauses in case of conflicts. */ charset_type_t m_charset_order; public: void init() { Lex_opt_context_charset_st::init(); Lex_exact_charset_extended_collation_attrs_st::init(); m_charset_order= CHARSET_TYPE_EMPTY; } void init(const Lex_exact_charset_opt_extended_collate &c) { Lex_opt_context_charset_st::init(); Lex_exact_charset_extended_collation_attrs_st::init(c); m_charset_order= CHARSET_TYPE_EXACT; } bool is_empty() const { return Lex_opt_context_charset_st::is_empty() && Lex_exact_charset_extended_collation_attrs_st::is_empty(); } bool raise_if_charset_conflicts_with_default( const Lex_exact_charset_opt_extended_collate &def) const; CHARSET_INFO *resolved_to_context(Sql_used *used, const Charset_collation_map_st &map, const Charset_collation_context &ctx) const; bool merge_charset_default(); bool merge_exact_charset(Sql_used *used, const Charset_collation_map_st &map, const Lex_exact_charset &cs); }; class Lex_exact_charset_extended_collation_attrs: public Lex_exact_charset_extended_collation_attrs_st { public: Lex_exact_charset_extended_collation_attrs() { init(); } Lex_exact_charset_extended_collation_attrs(CHARSET_INFO *collation, Type type) { init(collation, type); } explicit Lex_exact_charset_extended_collation_attrs(const Lex_exact_charset &cs) { init(cs.charset_info(), TYPE_CHARACTER_SET); } explicit Lex_exact_charset_extended_collation_attrs(const Lex_exact_collation &cl) { init(cl.charset_info(), TYPE_COLLATE_EXACT); } explicit Lex_exact_charset_extended_collation_attrs(const Lex_context_collation &cl) { init(cl.charset_info(), TYPE_COLLATE_CONTEXTUALLY_TYPED); } explicit Lex_exact_charset_extended_collation_attrs( const Lex_exact_charset_opt_extended_collate &cscl) { init(cscl); } explicit Lex_exact_charset_extended_collation_attrs(const Lex_extended_collation_st &cl) { init(cl.charset_info(), type_from_lex_collation_type(cl.type())); } static Lex_exact_charset_extended_collation_attrs national(bool bin_mod) { return bin_mod ? Lex_exact_charset_extended_collation_attrs(&my_charset_utf8mb3_bin, TYPE_COLLATE_EXACT) : Lex_exact_charset_extended_collation_attrs(&my_charset_utf8mb3_general_ci, TYPE_CHARACTER_SET); } }; class Lex_extended_charset_extended_collation_attrs: public Lex_extended_charset_extended_collation_attrs_st { public: Lex_extended_charset_extended_collation_attrs() { init(); } explicit Lex_extended_charset_extended_collation_attrs( const Lex_exact_charset_opt_extended_collate &c) { init(c); } }; using Lex_column_charset_collation_attrs_st = Lex_exact_charset_extended_collation_attrs_st; using Lex_column_charset_collation_attrs = Lex_exact_charset_extended_collation_attrs; using Lex_table_charset_collation_attrs_st = Lex_extended_charset_extended_collation_attrs_st; using Lex_table_charset_collation_attrs = Lex_extended_charset_extended_collation_attrs; #endif // LEX_CHARSET_INCLUDED strfunc.h 0000644 00000004343 15156036141 0006407 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef STRFUNC_INCLUDED #define STRFUNC_INCLUDED typedef struct st_typelib TYPELIB; ulonglong find_set(const TYPELIB *lib, const char *x, size_t length, CHARSET_INFO *cs, char **err_pos, uint *err_len, bool *set_warning); ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, ulonglong cur_set, ulonglong default_set, const char *str, uint length, CHARSET_INFO *cs, char **err_pos, uint *err_len, bool *set_warning); uint find_type(const TYPELIB *lib, const char *find, size_t length, bool part_match); uint find_type2(const TYPELIB *lib, const char *find, size_t length, CHARSET_INFO *cs); void unhex_type2(TYPELIB *lib); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); int find_string_in_array(LEX_CSTRING * const haystack, LEX_CSTRING * const needle, CHARSET_INFO * const cs); const char *flagset_to_string(THD *thd, LEX_CSTRING *result, ulonglong set, const char *lib[]); const char *set_to_string(THD *thd, LEX_CSTRING *result, ulonglong set, const char *lib[]); /* These functions were protected by INNODB_COMPATIBILITY_HOOKS */ uint strconvert(CHARSET_INFO *from_cs, const char *from, size_t from_length, CHARSET_INFO *to_cs, char *to, size_t to_length, uint *errors); #endif /* STRFUNC_INCLUDED */ lex.h 0000644 00000073050 15156036141 0005514 0 ustar 00 #ifndef LEX_INCLUDED #define LEX_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. Copyright (c) 2009, 2015, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file includes all reserved words and functions */ #include "lex_symbol.h" SYM_GROUP sym_group_common= {"", ""}; SYM_GROUP sym_group_geom= {"Spatial extensions", "HAVE_SPATIAL"}; SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; /* We don't want to include sql_yacc.h into gen_lex_hash */ #ifdef NO_YACC_SYMBOLS #define SYM_OR_NULL(A) 0 #else #define SYM_OR_NULL(A) A #endif #define SYM(A) SYM_OR_NULL(A),0,&sym_group_common /* Symbols are broken into separated arrays to allow field names with same name as functions. These are kept sorted for human lookup (the symbols are hashed). NOTE! The symbol tables should be the same regardless of what features are compiled into the server. Don't add ifdef'ed symbols to the lists NOTE!! If you add or delete symbols from this file, you must also update results for the perfschema.start_server_low_digest_sql_length test! */ SYMBOL symbols[] = { { "&&", SYM(AND_AND_SYM)}, { "<=", SYM(LE)}, { "<>", SYM(NE)}, { "!=", SYM(NE)}, { ">=", SYM(GE)}, { "<<", SYM(SHIFT_LEFT)}, { ">>", SYM(SHIFT_RIGHT)}, { "<=>", SYM(EQUAL_SYM)}, { "ACCESSIBLE", SYM(ACCESSIBLE_SYM)}, { "ACCOUNT", SYM(ACCOUNT_SYM)}, { "ACTION", SYM(ACTION)}, { "ADD", SYM(ADD)}, { "ADMIN", SYM(ADMIN_SYM)}, { "AFTER", SYM(AFTER_SYM)}, { "AGAINST", SYM(AGAINST)}, { "AGGREGATE", SYM(AGGREGATE_SYM)}, { "ALL", SYM(ALL)}, { "ALGORITHM", SYM(ALGORITHM_SYM)}, { "ALTER", SYM(ALTER)}, { "ALWAYS", SYM(ALWAYS_SYM)}, { "ANALYZE", SYM(ANALYZE_SYM)}, { "AND", SYM(AND_SYM)}, { "ANY", SYM(ANY_SYM)}, { "AS", SYM(AS)}, { "ASC", SYM(ASC)}, { "ASCII", SYM(ASCII_SYM)}, { "ASENSITIVE", SYM(ASENSITIVE_SYM)}, { "AT", SYM(AT_SYM)}, { "ATOMIC", SYM(ATOMIC_SYM)}, { "AUTHORS", SYM(AUTHORS_SYM)}, { "AUTO", SYM(AUTO_SYM)}, { "AUTO_INCREMENT", SYM(AUTO_INC)}, { "AUTOEXTEND_SIZE", SYM(AUTOEXTEND_SIZE_SYM)}, { "AVG", SYM(AVG_SYM)}, { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, { "BACKUP", SYM(BACKUP_SYM)}, { "BEFORE", SYM(BEFORE_SYM)}, { "BEGIN", SYM(BEGIN_MARIADB_SYM)}, { "BETWEEN", SYM(BETWEEN_SYM)}, { "BIGINT", SYM(BIGINT)}, { "BINARY", SYM(BINARY)}, { "BINLOG", SYM(BINLOG_SYM)}, { "BIT", SYM(BIT_SYM)}, { "BLOB", SYM(BLOB_MARIADB_SYM)}, { "BLOCK", SYM(BLOCK_SYM)}, { "BODY", SYM(BODY_MARIADB_SYM)}, { "BOOL", SYM(BOOL_SYM)}, { "BOOLEAN", SYM(BOOLEAN_SYM)}, { "BOTH", SYM(BOTH)}, { "BTREE", SYM(BTREE_SYM)}, { "BY", SYM(BY)}, { "BYTE", SYM(BYTE_SYM)}, { "CACHE", SYM(CACHE_SYM)}, { "CALL", SYM(CALL_SYM)}, { "CASCADE", SYM(CASCADE)}, { "CASCADED", SYM(CASCADED)}, { "CASE", SYM(CASE_SYM)}, { "CATALOG_NAME", SYM(CATALOG_NAME_SYM)}, { "CHAIN", SYM(CHAIN_SYM)}, { "CHANGE", SYM(CHANGE)}, { "CHANGED", SYM(CHANGED)}, { "CHANNEL", SYM(CHANNEL_SYM)}, { "CHAR", SYM(CHAR_SYM)}, { "CHARACTER", SYM(CHAR_SYM)}, { "CHARSET", SYM(CHARSET)}, { "CHECK", SYM(CHECK_SYM)}, { "CHECKPOINT", SYM(CHECKPOINT_SYM)}, { "CHECKSUM", SYM(CHECKSUM_SYM)}, { "CIPHER", SYM(CIPHER_SYM)}, { "CLASS_ORIGIN", SYM(CLASS_ORIGIN_SYM)}, { "CLIENT", SYM(CLIENT_SYM)}, { "CLOB", SYM(CLOB_MARIADB_SYM)}, { "CLOSE", SYM(CLOSE_SYM)}, { "COALESCE", SYM(COALESCE)}, { "CODE", SYM(CODE_SYM)}, { "COLLATE", SYM(COLLATE_SYM)}, { "COLLATION", SYM(COLLATION_SYM)}, { "COLUMN", SYM(COLUMN_SYM)}, { "COLUMN_NAME", SYM(COLUMN_NAME_SYM)}, { "COLUMNS", SYM(COLUMNS)}, { "COLUMN_ADD", SYM(COLUMN_ADD_SYM)}, { "COLUMN_CHECK", SYM(COLUMN_CHECK_SYM)}, { "COLUMN_CREATE", SYM(COLUMN_CREATE_SYM)}, { "COLUMN_DELETE", SYM(COLUMN_DELETE_SYM)}, { "COLUMN_GET", SYM(COLUMN_GET_SYM)}, { "COMMENT", SYM(COMMENT_SYM)}, { "COMMIT", SYM(COMMIT_SYM)}, { "COMMITTED", SYM(COMMITTED_SYM)}, { "COMPACT", SYM(COMPACT_SYM)}, { "COMPLETION", SYM(COMPLETION_SYM)}, { "COMPRESSED", SYM(COMPRESSED_SYM)}, { "CONCURRENT", SYM(CONCURRENT)}, { "CONDITION", SYM(CONDITION_SYM)}, { "CONNECTION", SYM(CONNECTION_SYM)}, { "CONSISTENT", SYM(CONSISTENT_SYM)}, { "CONSTRAINT", SYM(CONSTRAINT)}, { "CONSTRAINT_CATALOG", SYM(CONSTRAINT_CATALOG_SYM)}, { "CONSTRAINT_NAME", SYM(CONSTRAINT_NAME_SYM)}, { "CONSTRAINT_SCHEMA", SYM(CONSTRAINT_SCHEMA_SYM)}, { "CONTAINS", SYM(CONTAINS_SYM)}, { "CONTEXT", SYM(CONTEXT_SYM)}, { "CONTINUE", SYM(CONTINUE_MARIADB_SYM)}, { "CONTRIBUTORS", SYM(CONTRIBUTORS_SYM)}, { "CONVERT", SYM(CONVERT_SYM)}, { "CPU", SYM(CPU_SYM)}, { "CREATE", SYM(CREATE)}, { "CROSS", SYM(CROSS)}, { "CUBE", SYM(CUBE_SYM)}, { "CURRENT", SYM(CURRENT_SYM)}, { "CURRENT_DATE", SYM(CURDATE)}, { "CURRENT_POS", SYM(CURRENT_POS_SYM)}, { "CURRENT_ROLE", SYM(CURRENT_ROLE)}, { "CURRENT_TIME", SYM(CURTIME)}, { "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, { "CURRENT_USER", SYM(CURRENT_USER)}, { "CURSOR", SYM(CURSOR_SYM)}, { "CURSOR_NAME", SYM(CURSOR_NAME_SYM)}, { "CYCLE", SYM(CYCLE_SYM)}, { "DATA", SYM(DATA_SYM)}, { "DATABASE", SYM(DATABASE)}, { "DATABASES", SYM(DATABASES)}, { "DATAFILE", SYM(DATAFILE_SYM)}, { "DATE", SYM(DATE_SYM)}, { "DATETIME", SYM(DATETIME)}, { "DAY", SYM(DAY_SYM)}, { "DAY_HOUR", SYM(DAY_HOUR_SYM)}, { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM)}, { "DAY_MINUTE", SYM(DAY_MINUTE_SYM)}, { "DAY_SECOND", SYM(DAY_SECOND_SYM)}, { "DEALLOCATE", SYM(DEALLOCATE_SYM)}, { "DEC", SYM(DECIMAL_SYM)}, { "DECIMAL", SYM(DECIMAL_SYM)}, { "DECLARE", SYM(DECLARE_MARIADB_SYM)}, { "DEFAULT", SYM(DEFAULT)}, { "DEFINER", SYM(DEFINER_SYM)}, { "DELAYED", SYM(DELAYED_SYM)}, { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)}, { "DELETE", SYM(DELETE_SYM)}, { "DELETE_DOMAIN_ID", SYM(DELETE_DOMAIN_ID_SYM)}, { "DESC", SYM(DESC)}, { "DESCRIBE", SYM(DESCRIBE)}, { "DES_KEY_FILE", SYM(DES_KEY_FILE)}, { "DETERMINISTIC", SYM(DETERMINISTIC_SYM)}, { "DIAGNOSTICS", SYM(DIAGNOSTICS_SYM)}, { "DIRECTORY", SYM(DIRECTORY_SYM)}, { "DISABLE", SYM(DISABLE_SYM)}, { "DISCARD", SYM(DISCARD)}, { "DISK", SYM(DISK_SYM)}, { "DISTINCT", SYM(DISTINCT)}, { "DISTINCTROW", SYM(DISTINCT)}, /* Access likes this */ { "DIV", SYM(DIV_SYM)}, { "DO", SYM(DO_SYM)}, { "DOUBLE", SYM(DOUBLE_SYM)}, { "DO_DOMAIN_IDS", SYM(DO_DOMAIN_IDS_SYM)}, { "DROP", SYM(DROP)}, { "DUAL", SYM(DUAL_SYM)}, { "DUMPFILE", SYM(DUMPFILE)}, { "DUPLICATE", SYM(DUPLICATE_SYM)}, { "DYNAMIC", SYM(DYNAMIC_SYM)}, { "EACH", SYM(EACH_SYM)}, { "ELSE", SYM(ELSE)}, { "ELSEIF", SYM(ELSEIF_MARIADB_SYM)}, { "ELSIF", SYM(ELSIF_MARIADB_SYM)}, { "EMPTY", SYM(EMPTY_SYM)}, { "ENABLE", SYM(ENABLE_SYM)}, { "ENABLE_GOVERNOR", SYM(ENABLE_GOVERNOR_SYM)}, { "ENABLE_GOVERNOR_RECON", SYM(ENABLE_GOVERNOR_RECONN_SYM)}, { "ENABLE_GOVERNOR_LVE", SYM(ENABLE_GOVERNOR_LVE_SYM)}, { "ENABLE_GOVERNOR_RECON_LVE", SYM(ENABLE_GOVERNOR_RECONN_LVE_SYM)}, { "ENCLOSED", SYM(ENCLOSED)}, { "END", SYM(END)}, { "ENDS", SYM(ENDS_SYM)}, { "ENGINE", SYM(ENGINE_SYM)}, { "ENGINES", SYM(ENGINES_SYM)}, { "ENUM", SYM(ENUM)}, { "ERROR", SYM(ERROR_SYM)}, { "ERRORS", SYM(ERRORS)}, { "ESCAPE", SYM(ESCAPE_SYM)}, { "ESCAPED", SYM(ESCAPED)}, { "EVENT", SYM(EVENT_SYM)}, { "EVENTS", SYM(EVENTS_SYM)}, { "EVERY", SYM(EVERY_SYM)}, { "EXAMINED", SYM(EXAMINED_SYM)}, { "EXCEPT", SYM(EXCEPT_SYM)}, { "EXCHANGE", SYM(EXCHANGE_SYM)}, { "EXCLUDE", SYM(EXCLUDE_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)}, { "EXCEPTION", SYM(EXCEPTION_MARIADB_SYM)}, { "EXISTS", SYM(EXISTS)}, { "EXIT", SYM(EXIT_MARIADB_SYM)}, { "EXPANSION", SYM(EXPANSION_SYM)}, { "EXPIRE", SYM(EXPIRE_SYM)}, { "EXPORT", SYM(EXPORT_SYM)}, { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, { "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, { "FAULTS", SYM(FAULTS_SYM)}, { "FEDERATED", SYM(FEDERATED_SYM)}, { "FETCH", SYM(FETCH_SYM)}, { "FIELDS", SYM(COLUMNS)}, { "FILE", SYM(FILE_SYM)}, { "FIRST", SYM(FIRST_SYM)}, { "FIXED", SYM(FIXED_SYM)}, { "FLOAT", SYM(FLOAT_SYM)}, { "FLOAT4", SYM(FLOAT_SYM)}, { "FLOAT8", SYM(DOUBLE_SYM)}, { "FLUSH", SYM(FLUSH_SYM)}, { "FOLLOWING", SYM(FOLLOWING_SYM)}, { "FOLLOWS", SYM(FOLLOWS_SYM)}, { "FOR", SYM(FOR_SYM)}, { "FORCE", SYM(FORCE_SYM)}, { "FOREIGN", SYM(FOREIGN)}, { "FORMAT", SYM(FORMAT_SYM)}, { "FOUND", SYM(FOUND_SYM)}, { "FROM", SYM(FROM)}, { "FULL", SYM(FULL)}, { "FULLTEXT", SYM(FULLTEXT_SYM)}, { "FUNCTION", SYM(FUNCTION_SYM)}, { "GENERAL", SYM(GENERAL)}, { "GENERATED", SYM(GENERATED_SYM)}, { "GET_FORMAT", SYM(GET_FORMAT)}, { "GET", SYM(GET_SYM)}, { "GLOBAL", SYM(GLOBAL_SYM)}, { "GOTO", SYM(GOTO_MARIADB_SYM)}, { "GRANT", SYM(GRANT)}, { "GRANTS", SYM(GRANTS)}, { "GROUP", SYM(GROUP_SYM)}, { "HANDLER", SYM(HANDLER_SYM)}, { "HARD", SYM(HARD_SYM)}, { "HASH", SYM(HASH_SYM)}, { "HAVING", SYM(HAVING)}, { "HELP", SYM(HELP_SYM)}, { "HIGH_PRIORITY", SYM(HIGH_PRIORITY)}, { "HISTORY", SYM(HISTORY_SYM)}, { "HOST", SYM(HOST_SYM)}, { "HOSTS", SYM(HOSTS_SYM)}, { "HOUR", SYM(HOUR_SYM)}, { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM)}, { "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM)}, { "HOUR_SECOND", SYM(HOUR_SECOND_SYM)}, { "ID", SYM(ID_SYM)}, { "IDENTIFIED", SYM(IDENTIFIED_SYM)}, { "IF", SYM(IF_SYM)}, { "IGNORE", SYM(IGNORE_SYM)}, { "IGNORED", SYM(IGNORED_SYM)}, { "IGNORE_DOMAIN_IDS", SYM(IGNORE_DOMAIN_IDS_SYM)}, { "IGNORE_SERVER_IDS", SYM(IGNORE_SERVER_IDS_SYM)}, { "IMMEDIATE", SYM(IMMEDIATE_SYM)}, { "IMPORT", SYM(IMPORT)}, { "INTERSECT", SYM(INTERSECT_SYM)}, { "IN", SYM(IN_SYM)}, { "INCREMENT", SYM(INCREMENT_SYM)}, { "INDEX", SYM(INDEX_SYM)}, { "INDEXES", SYM(INDEXES)}, { "INFILE", SYM(INFILE)}, { "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)}, { "INNER", SYM(INNER_SYM)}, { "INOUT", SYM(INOUT_SYM)}, { "INSENSITIVE", SYM(INSENSITIVE_SYM)}, { "INSERT", SYM(INSERT)}, { "INSERT_METHOD", SYM(INSERT_METHOD)}, { "INSTALL", SYM(INSTALL_SYM)}, { "INT", SYM(INT_SYM)}, { "INT1", SYM(TINYINT)}, { "INT2", SYM(SMALLINT)}, { "INT3", SYM(MEDIUMINT)}, { "INT4", SYM(INT_SYM)}, { "INT8", SYM(BIGINT)}, { "INTEGER", SYM(INT_SYM)}, { "INTERVAL", SYM(INTERVAL_SYM)}, { "INVISIBLE", SYM(INVISIBLE_SYM)}, { "INTO", SYM(INTO)}, { "IO", SYM(IO_SYM)}, { "IO_THREAD", SYM(RELAY_THREAD)}, { "IPC", SYM(IPC_SYM)}, { "IS", SYM(IS)}, { "ISOLATION", SYM(ISOLATION)}, { "ISOPEN", SYM(ISOPEN_SYM)}, { "ISSUER", SYM(ISSUER_SYM)}, { "ITERATE", SYM(ITERATE_SYM)}, { "INVOKER", SYM(INVOKER_SYM)}, { "JOIN", SYM(JOIN_SYM)}, { "JSON", SYM(JSON_SYM)}, { "JSON_TABLE", SYM(JSON_TABLE_SYM)}, { "KEY", SYM(KEY_SYM)}, { "KEYS", SYM(KEYS)}, { "KEY_BLOCK_SIZE", SYM(KEY_BLOCK_SIZE)}, { "KILL", SYM(KILL_SYM)}, { "LANGUAGE", SYM(LANGUAGE_SYM)}, { "LAST", SYM(LAST_SYM)}, { "LAST_VALUE", SYM(LAST_VALUE)}, { "LASTVAL", SYM(LASTVAL_SYM)}, { "LEADING", SYM(LEADING)}, { "LEAVE", SYM(LEAVE_SYM)}, { "LEAVES", SYM(LEAVES)}, { "LEFT", SYM(LEFT)}, { "LESS", SYM(LESS_SYM)}, { "LEVEL", SYM(LEVEL_SYM)}, { "LIKE", SYM(LIKE)}, { "LIMIT", SYM(LIMIT)}, { "LINEAR", SYM(LINEAR_SYM)}, { "LINES", SYM(LINES)}, { "LIST", SYM(LIST_SYM)}, { "LOAD", SYM(LOAD)}, { "LOCAL", SYM(LOCAL_SYM)}, { "LOCALTIME", SYM(NOW_SYM)}, { "LOCALTIMESTAMP", SYM(NOW_SYM)}, { "LOCK", SYM(LOCK_SYM)}, { "LOCKED", SYM(LOCKED_SYM)}, { "LOCKS", SYM(LOCKS_SYM)}, { "LOGFILE", SYM(LOGFILE_SYM)}, { "LOGS", SYM(LOGS_SYM)}, { "LONG", SYM(LONG_SYM)}, { "LONGBLOB", SYM(LONGBLOB)}, { "LONGTEXT", SYM(LONGTEXT)}, { "LOOP", SYM(LOOP_SYM)}, { "LOW_PRIORITY", SYM(LOW_PRIORITY)}, { "MASTER", SYM(MASTER_SYM)}, { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)}, { "MASTER_DELAY", SYM(MASTER_DELAY_SYM)}, { "MASTER_GTID_POS", SYM(MASTER_GTID_POS_SYM)}, { "MASTER_HOST", SYM(MASTER_HOST_SYM)}, { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)}, { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM)}, { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM)}, { "MASTER_PORT", SYM(MASTER_PORT_SYM)}, { "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM)}, { "MASTER_SSL", SYM(MASTER_SSL_SYM)}, { "MASTER_SSL_CA", SYM(MASTER_SSL_CA_SYM)}, { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM)}, { "MASTER_SSL_CERT", SYM(MASTER_SSL_CERT_SYM)}, { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM)}, { "MASTER_SSL_CRL", SYM(MASTER_SSL_CRL_SYM)}, { "MASTER_SSL_CRLPATH",SYM(MASTER_SSL_CRLPATH_SYM)}, { "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM)}, { "MASTER_SSL_VERIFY_SERVER_CERT", SYM(MASTER_SSL_VERIFY_SERVER_CERT_SYM)}, { "MASTER_USER", SYM(MASTER_USER_SYM)}, { "MASTER_USE_GTID", SYM(MASTER_USE_GTID_SYM)}, { "MASTER_DEMOTE_TO_REPLICA", SYM(MASTER_DEMOTE_TO_SLAVE_SYM)}, { "MASTER_DEMOTE_TO_SLAVE", SYM(MASTER_DEMOTE_TO_SLAVE_SYM)}, { "MASTER_HEARTBEAT_PERIOD", SYM(MASTER_HEARTBEAT_PERIOD_SYM)}, { "MATCH", SYM(MATCH)}, { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)}, { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)}, { "MAX_ROWS", SYM(MAX_ROWS)}, { "MAX_SIZE", SYM(MAX_SIZE_SYM)}, { "MAX_STATEMENT_TIME", SYM(MAX_STATEMENT_TIME_SYM)}, { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)}, { "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)}, { "MAXVALUE", SYM(MAXVALUE_SYM)}, { "MEDIUM", SYM(MEDIUM_SYM)}, { "MEDIUMBLOB", SYM(MEDIUMBLOB)}, { "MEDIUMINT", SYM(MEDIUMINT)}, { "MEDIUMTEXT", SYM(MEDIUMTEXT)}, { "MEMORY", SYM(MEMORY_SYM)}, { "MERGE", SYM(MERGE_SYM)}, { "MESSAGE_TEXT", SYM(MESSAGE_TEXT_SYM)}, { "MICROSECOND", SYM(MICROSECOND_SYM)}, { "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */ { "MIGRATE", SYM(MIGRATE_SYM)}, { "MINUS", SYM(MINUS_ORACLE_SYM)}, { "MINUTE", SYM(MINUTE_SYM)}, { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM)}, { "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM)}, { "MINVALUE", SYM(MINVALUE_SYM)}, { "MIN_ROWS", SYM(MIN_ROWS)}, { "MOD", SYM(MOD_SYM)}, { "MODE", SYM(MODE_SYM)}, { "MODIFIES", SYM(MODIFIES_SYM)}, { "MODIFY", SYM(MODIFY_SYM)}, { "MONITOR", SYM(MONITOR_SYM)}, { "MONTH", SYM(MONTH_SYM)}, { "MUTEX", SYM(MUTEX_SYM)}, { "MYSQL", SYM(MYSQL_SYM)}, { "MYSQL_ERRNO", SYM(MYSQL_ERRNO_SYM)}, { "NAME", SYM(NAME_SYM)}, { "NAMES", SYM(NAMES_SYM)}, { "NATIONAL", SYM(NATIONAL_SYM)}, { "NATURAL", SYM(NATURAL)}, { "NCHAR", SYM(NCHAR_SYM)}, { "NESTED", SYM(NESTED_SYM)}, { "NEVER", SYM(NEVER_SYM)}, { "NEXT", SYM(NEXT_SYM)}, { "NEXTVAL", SYM(NEXTVAL_SYM)}, { "NO", SYM(NO_SYM)}, { "NOMAXVALUE", SYM(NOMAXVALUE_SYM)}, { "NOMINVALUE", SYM(NOMINVALUE_SYM)}, { "NOCACHE", SYM(NOCACHE_SYM)}, { "NOCYCLE", SYM(NOCYCLE_SYM)}, { "NO_WAIT", SYM(NO_WAIT_SYM)}, { "NOWAIT", SYM(NOWAIT_SYM)}, { "NODEGROUP", SYM(NODEGROUP_SYM)}, { "NONE", SYM(NONE_SYM)}, { "NOT", SYM(NOT_SYM)}, { "NOTFOUND", SYM(NOTFOUND_SYM)}, { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, { "NULL", SYM(NULL_SYM)}, { "NUMBER", SYM(NUMBER_MARIADB_SYM)}, { "NUMERIC", SYM(NUMERIC_SYM)}, { "NVARCHAR", SYM(NVARCHAR_SYM)}, { "OF", SYM(OF_SYM)}, { "OFFSET", SYM(OFFSET_SYM)}, { "OLD_PASSWORD", SYM(OLD_PASSWORD_SYM)}, { "ON", SYM(ON)}, { "ONE", SYM(ONE_SYM)}, { "ONLINE", SYM(ONLINE_SYM)}, { "ONLY", SYM(ONLY_SYM)}, { "OPEN", SYM(OPEN_SYM)}, { "OPTIMIZE", SYM(OPTIMIZE)}, { "OPTIONS", SYM(OPTIONS_SYM)}, { "OPTION", SYM(OPTION)}, { "OPTIONALLY", SYM(OPTIONALLY)}, { "OR", SYM(OR_SYM)}, { "ORDER", SYM(ORDER_SYM)}, { "ORDINALITY", SYM(ORDINALITY_SYM)}, { "OTHERS", SYM(OTHERS_MARIADB_SYM)}, { "OUT", SYM(OUT_SYM)}, { "OUTER", SYM(OUTER)}, { "OUTFILE", SYM(OUTFILE)}, { "OVER", SYM(OVER_SYM)}, { "OVERLAPS", SYM(OVERLAPS_SYM)}, { "OWNER", SYM(OWNER_SYM)}, { "PACKAGE", SYM(PACKAGE_MARIADB_SYM)}, { "PACK_KEYS", SYM(PACK_KEYS_SYM)}, { "PAGE", SYM(PAGE_SYM)}, { "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)}, { "PARSER", SYM(PARSER_SYM)}, { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)}, { "PATH", SYM(PATH_SYM)}, { "PERIOD", SYM(PERIOD_SYM)}, { "PARTIAL", SYM(PARTIAL)}, { "PARTITION", SYM(PARTITION_SYM)}, { "PARTITIONING", SYM(PARTITIONING_SYM)}, { "PARTITIONS", SYM(PARTITIONS_SYM)}, { "PASSWORD", SYM(PASSWORD_SYM)}, { "PERSISTENT", SYM(PERSISTENT_SYM)}, { "PHASE", SYM(PHASE_SYM)}, { "PLUGIN", SYM(PLUGIN_SYM)}, { "PLUGINS", SYM(PLUGINS_SYM)}, { "PORT", SYM(PORT_SYM)}, { "PORTION", SYM(PORTION_SYM)}, { "PRECEDES", SYM(PRECEDES_SYM)}, { "PRECEDING", SYM(PRECEDING_SYM)}, { "PRECISION", SYM(PRECISION)}, { "PREPARE", SYM(PREPARE_SYM)}, { "PRESERVE", SYM(PRESERVE_SYM)}, { "PREV", SYM(PREV_SYM)}, { "PREVIOUS", SYM(PREVIOUS_SYM)}, { "PRIMARY", SYM(PRIMARY_SYM)}, { "PRIVILEGES", SYM(PRIVILEGES)}, { "PROCEDURE", SYM(PROCEDURE_SYM)}, { "PROCESS" , SYM(PROCESS)}, { "PROCESSLIST", SYM(PROCESSLIST_SYM)}, { "PROFILE", SYM(PROFILE_SYM)}, { "PROFILES", SYM(PROFILES_SYM)}, { "PROXY", SYM(PROXY_SYM)}, { "PURGE", SYM(PURGE)}, { "QUARTER", SYM(QUARTER_SYM)}, { "QUERY", SYM(QUERY_SYM)}, { "QUICK", SYM(QUICK)}, { "RAISE", SYM(RAISE_MARIADB_SYM)}, { "RANGE", SYM(RANGE_SYM)}, { "RAW", SYM(RAW_MARIADB_SYM)}, { "READ", SYM(READ_SYM)}, { "READ_ONLY", SYM(READ_ONLY_SYM)}, { "READ_WRITE", SYM(READ_WRITE_SYM)}, { "READS", SYM(READS_SYM)}, { "REAL", SYM(REAL)}, { "REBUILD", SYM(REBUILD_SYM)}, { "RECOVER", SYM(RECOVER_SYM)}, { "RECURSIVE", SYM(RECURSIVE_SYM)}, { "REDO_BUFFER_SIZE", SYM(REDO_BUFFER_SIZE_SYM)}, { "REDOFILE", SYM(REDOFILE_SYM)}, { "REDUNDANT", SYM(REDUNDANT_SYM)}, { "REFERENCES", SYM(REFERENCES)}, { "REGEXP", SYM(REGEXP)}, { "RELAY", SYM(RELAY)}, { "RELAYLOG", SYM(RELAYLOG_SYM)}, { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)}, { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)}, { "RELAY_THREAD", SYM(RELAY_THREAD)}, { "RELEASE", SYM(RELEASE_SYM)}, { "RELOAD", SYM(RELOAD)}, { "REMOVE", SYM(REMOVE_SYM)}, { "RENAME", SYM(RENAME)}, { "REORGANIZE", SYM(REORGANIZE_SYM)}, { "REPAIR", SYM(REPAIR)}, { "REPEATABLE", SYM(REPEATABLE_SYM)}, { "REPLACE", SYM(REPLACE)}, { "REPLAY", SYM(REPLAY_SYM)}, { "REPLICA", SYM(SLAVE)}, { "REPLICAS", SYM(SLAVES)}, { "REPLICA_POS", SYM(SLAVE_POS_SYM)}, { "REPLICATION", SYM(REPLICATION)}, { "REPEAT", SYM(REPEAT_SYM)}, { "REQUIRE", SYM(REQUIRE_SYM)}, { "RESET", SYM(RESET_SYM)}, { "RESIGNAL", SYM(RESIGNAL_SYM)}, { "RESTART", SYM(RESTART_SYM)}, { "RESTORE", SYM(RESTORE_SYM)}, { "RESTRICT", SYM(RESTRICT)}, { "RESUME", SYM(RESUME_SYM)}, { "RETURNED_SQLSTATE",SYM(RETURNED_SQLSTATE_SYM)}, { "RETURN", SYM(RETURN_MARIADB_SYM)}, { "RETURNING", SYM(RETURNING_SYM)}, { "RETURNS", SYM(RETURNS_SYM)}, { "REUSE", SYM(REUSE_SYM)}, { "REVERSE", SYM(REVERSE_SYM)}, { "REVOKE", SYM(REVOKE)}, { "RIGHT", SYM(RIGHT)}, { "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */ { "ROLE", SYM(ROLE_SYM)}, { "ROLLBACK", SYM(ROLLBACK_SYM)}, { "ROLLUP", SYM(ROLLUP_SYM)}, { "ROUTINE", SYM(ROUTINE_SYM)}, { "ROW", SYM(ROW_SYM)}, { "ROWCOUNT", SYM(ROWCOUNT_SYM)}, /* Oracle-N */ { "ROWNUM", SYM(ROWNUM_SYM)}, /* Oracle-R */ { "ROWS", SYM(ROWS_SYM)}, { "ROWTYPE", SYM(ROWTYPE_MARIADB_SYM)}, { "ROW_COUNT", SYM(ROW_COUNT_SYM)}, { "ROW_FORMAT", SYM(ROW_FORMAT_SYM)}, /** sql_function and condition_property_name for GET DIAGNOSTICS */ { "ROW_NUMBER", SYM(ROW_NUMBER_SYM)}, { "RTREE", SYM(RTREE_SYM)}, { "SAVEPOINT", SYM(SAVEPOINT_SYM)}, { "SCHEDULE", SYM(SCHEDULE_SYM)}, { "SCHEMA", SYM(DATABASE)}, { "SCHEMA_NAME", SYM(SCHEMA_NAME_SYM)}, { "SCHEMAS", SYM(DATABASES)}, { "SECOND", SYM(SECOND_SYM)}, { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)}, { "SECURITY", SYM(SECURITY_SYM)}, { "SELECT", SYM(SELECT_SYM)}, { "SENSITIVE", SYM(SENSITIVE_SYM)}, { "SEPARATOR", SYM(SEPARATOR_SYM)}, { "SEQUENCE", SYM(SEQUENCE_SYM)}, { "SERIAL", SYM(SERIAL_SYM)}, { "SERIALIZABLE", SYM(SERIALIZABLE_SYM)}, { "SESSION", SYM(SESSION_SYM)}, { "SERVER", SYM(SERVER_SYM)}, { "SET", SYM(SET)}, { "SETVAL", SYM(SETVAL_SYM)}, { "SHARE", SYM(SHARE_SYM)}, { "SHOW", SYM(SHOW)}, { "SHUTDOWN", SYM(SHUTDOWN)}, { "SIGNAL", SYM(SIGNAL_SYM)}, { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SKIP", SYM(SKIP_SYM)}, { "SLAVE", SYM(SLAVE)}, { "SLAVES", SYM(SLAVES)}, { "SLAVE_POS", SYM(SLAVE_POS_SYM)}, { "SLOW", SYM(SLOW)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, { "SOCKET", SYM(SOCKET_SYM)}, { "SOFT", SYM(SOFT_SYM)}, { "SOME", SYM(ANY_SYM)}, { "SONAME", SYM(SONAME_SYM)}, { "SOUNDS", SYM(SOUNDS_SYM)}, { "SOURCE", SYM(SOURCE_SYM)}, { "STAGE", SYM(STAGE_SYM)}, { "STORED", SYM(STORED_SYM)}, { "SPATIAL", SYM(SPATIAL_SYM)}, { "SPECIFIC", SYM(SPECIFIC_SYM)}, { "REF_SYSTEM_ID", SYM(REF_SYSTEM_ID_SYM)}, { "SQL", SYM(SQL_SYM)}, { "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM)}, { "SQLSTATE", SYM(SQLSTATE_SYM)}, { "SQLWARNING", SYM(SQLWARNING_SYM)}, { "SQL_AFTER_GTIDS", SYM(SQL_AFTER_GTIDS_SYM)}, { "SQL_BEFORE_GTIDS", SYM(SQL_BEFORE_GTIDS_SYM)}, { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)}, { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)}, { "SQL_CACHE", SYM(SQL_CACHE_SYM)}, { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS)}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)}, { "SQL_THREAD", SYM(SQL_THREAD)}, { "SQL_TSI_SECOND", SYM(SECOND_SYM)}, { "SQL_TSI_MINUTE", SYM(MINUTE_SYM)}, { "SQL_TSI_HOUR", SYM(HOUR_SYM)}, { "SQL_TSI_DAY", SYM(DAY_SYM)}, { "SQL_TSI_WEEK", SYM(WEEK_SYM)}, { "SQL_TSI_MONTH", SYM(MONTH_SYM)}, { "SQL_TSI_QUARTER", SYM(QUARTER_SYM)}, { "SQL_TSI_YEAR", SYM(YEAR_SYM)}, { "SSL", SYM(SSL_SYM)}, { "START", SYM(START_SYM)}, { "STARTING", SYM(STARTING)}, { "STARTS", SYM(STARTS_SYM)}, { "STATEMENT", SYM(STATEMENT_SYM)}, { "STATS_AUTO_RECALC",SYM(STATS_AUTO_RECALC_SYM)}, { "STATS_PERSISTENT", SYM(STATS_PERSISTENT_SYM)}, { "STATS_SAMPLE_PAGES",SYM(STATS_SAMPLE_PAGES_SYM)}, { "STATUS", SYM(STATUS_SYM)}, { "STOP", SYM(STOP_SYM)}, { "STORAGE", SYM(STORAGE_SYM)}, { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN)}, { "STRING", SYM(STRING_SYM)}, { "SUBCLASS_ORIGIN", SYM(SUBCLASS_ORIGIN_SYM)}, { "SUBJECT", SYM(SUBJECT_SYM)}, { "SUBPARTITION", SYM(SUBPARTITION_SYM)}, { "SUBPARTITIONS", SYM(SUBPARTITIONS_SYM)}, { "SUPER", SYM(SUPER_SYM)}, { "SUSPEND", SYM(SUSPEND_SYM)}, { "SWAPS", SYM(SWAPS_SYM)}, { "SWITCHES", SYM(SWITCHES_SYM)}, { "SYSDATE", SYM(SYSDATE)}, { "SYSTEM", SYM(SYSTEM)}, { "SYSTEM_TIME", SYM(SYSTEM_TIME_SYM)}, { "TABLE", SYM(TABLE_SYM)}, { "TABLE_NAME", SYM(TABLE_NAME_SYM)}, { "TABLES", SYM(TABLES)}, { "TABLESPACE", SYM(TABLESPACE)}, { "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)}, { "TEMPORARY", SYM(TEMPORARY)}, { "TEMPTABLE", SYM(TEMPTABLE_SYM)}, { "TERMINATED", SYM(TERMINATED)}, { "TEXT", SYM(TEXT_SYM)}, { "THAN", SYM(THAN_SYM)}, { "THEN", SYM(THEN_SYM)}, { "TIES", SYM(TIES_SYM)}, { "TIME", SYM(TIME_SYM)}, { "TIMESTAMP", SYM(TIMESTAMP)}, { "TIMESTAMPADD", SYM(TIMESTAMP_ADD)}, { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF)}, { "TINYBLOB", SYM(TINYBLOB)}, { "TINYINT", SYM(TINYINT)}, { "TINYTEXT", SYM(TINYTEXT)}, { "TO", SYM(TO_SYM)}, { "TRAILING", SYM(TRAILING)}, { "TRANSACTION", SYM(TRANSACTION_SYM)}, { "TRANSACTIONAL", SYM(TRANSACTIONAL_SYM)}, { "THREADS", SYM(THREADS_SYM)}, { "TRIGGER", SYM(TRIGGER_SYM)}, { "TRIGGERS", SYM(TRIGGERS_SYM)}, { "TRUE", SYM(TRUE_SYM)}, { "TRUNCATE", SYM(TRUNCATE_SYM)}, { "TYPE", SYM(TYPE_SYM)}, { "UNBOUNDED", SYM(UNBOUNDED_SYM)}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, { "UNDEFINED", SYM(UNDEFINED_SYM)}, { "UNDO_BUFFER_SIZE", SYM(UNDO_BUFFER_SIZE_SYM)}, { "UNDOFILE", SYM(UNDOFILE_SYM)}, { "UNDO", SYM(UNDO_SYM)}, { "UNICODE", SYM(UNICODE_SYM)}, { "UNION", SYM(UNION_SYM)}, { "UNIQUE", SYM(UNIQUE_SYM)}, { "UNKNOWN", SYM(UNKNOWN_SYM)}, { "UNLOCK", SYM(UNLOCK_SYM)}, { "UNINSTALL", SYM(UNINSTALL_SYM)}, { "UNSIGNED", SYM(UNSIGNED)}, { "UNTIL", SYM(UNTIL_SYM)}, { "UPDATE", SYM(UPDATE_SYM)}, { "UPGRADE", SYM(UPGRADE_SYM)}, { "USAGE", SYM(USAGE)}, { "USE", SYM(USE_SYM)}, { "USER", SYM(USER_SYM)}, { "USER_RESOURCES", SYM(RESOURCES)}, { "USE_FRM", SYM(USE_FRM)}, { "USING", SYM(USING)}, { "UTC_DATE", SYM(UTC_DATE_SYM)}, { "UTC_TIME", SYM(UTC_TIME_SYM)}, { "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM)}, { "VALIDATION", SYM(VALIDATION_SYM)}, { "VALUE", SYM(VALUE_SYM)}, { "VALUES", SYM(VALUES)}, { "VARBINARY", SYM(VARBINARY)}, { "VARCHAR", SYM(VARCHAR)}, { "VARCHARACTER", SYM(VARCHAR)}, { "VARCHAR2", SYM(VARCHAR2_MARIADB_SYM)}, { "VARIABLES", SYM(VARIABLES)}, { "VARYING", SYM(VARYING)}, { "VIA", SYM(VIA_SYM)}, { "VIEW", SYM(VIEW_SYM)}, { "VIRTUAL", SYM(VIRTUAL_SYM)}, { "VISIBLE", SYM(VISIBLE_SYM)}, { "VERSIONING", SYM(VERSIONING_SYM)}, { "WAIT", SYM(WAIT_SYM)}, { "WARNINGS", SYM(WARNINGS)}, { "WEEK", SYM(WEEK_SYM)}, { "WEIGHT_STRING", SYM(WEIGHT_STRING_SYM)}, { "WHEN", SYM(WHEN_SYM)}, { "WHERE", SYM(WHERE)}, { "WHILE", SYM(WHILE_SYM)}, { "WINDOW", SYM(WINDOW_SYM)}, { "WITH", SYM(WITH)}, { "WITHIN", SYM(WITHIN)}, { "WITHOUT", SYM(WITHOUT)}, { "WORK", SYM(WORK_SYM)}, { "WRAPPER", SYM(WRAPPER_SYM)}, { "WRITE", SYM(WRITE_SYM)}, { "X509", SYM(X509_SYM)}, { "XOR", SYM(XOR)}, { "XA", SYM(XA_SYM)}, { "XML", SYM(XML_SYM)}, /* LOAD XML Arnold/Erik */ { "YEAR", SYM(YEAR_SYM)}, { "YEAR_MONTH", SYM(YEAR_MONTH_SYM)}, { "ZEROFILL", SYM(ZEROFILL)}, { "||", SYM(OR2_SYM)} }; SYMBOL sql_functions[] = { { "ADDDATE", SYM(ADDDATE_SYM)}, { "BIT_AND", SYM(BIT_AND)}, { "BIT_OR", SYM(BIT_OR)}, { "BIT_XOR", SYM(BIT_XOR)}, { "CAST", SYM(CAST_SYM)}, { "COUNT", SYM(COUNT_SYM)}, { "CUME_DIST", SYM(CUME_DIST_SYM)}, { "CURDATE", SYM(CURDATE)}, { "CURTIME", SYM(CURTIME)}, { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, { "DENSE_RANK", SYM(DENSE_RANK_SYM)}, { "EXTRACT", SYM(EXTRACT_SYM)}, { "FIRST_VALUE", SYM(FIRST_VALUE_SYM)}, { "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)}, { "JSON_ARRAYAGG", SYM(JSON_ARRAYAGG_SYM)}, { "JSON_OBJECTAGG", SYM(JSON_OBJECTAGG_SYM)}, { "LAG", SYM(LAG_SYM)}, { "LEAD", SYM(LEAD_SYM)}, { "MAX", SYM(MAX_SYM)}, { "MEDIAN", SYM(MEDIAN_SYM)}, { "MID", SYM(SUBSTRING)}, /* unireg function */ { "MIN", SYM(MIN_SYM)}, { "NOW", SYM(NOW_SYM)}, { "NTH_VALUE", SYM(NTH_VALUE_SYM)}, { "NTILE", SYM(NTILE_SYM)}, { "POSITION", SYM(POSITION_SYM)}, { "PERCENT_RANK", SYM(PERCENT_RANK_SYM)}, { "PERCENTILE_CONT", SYM(PERCENTILE_CONT_SYM)}, { "PERCENTILE_DISC", SYM(PERCENTILE_DISC_SYM)}, { "RANK", SYM(RANK_SYM)}, { "SESSION_USER", SYM(USER_SYM)}, { "STD", SYM(STD_SYM)}, { "STDDEV", SYM(STD_SYM)}, { "STDDEV_POP", SYM(STD_SYM)}, { "STDDEV_SAMP", SYM(STDDEV_SAMP_SYM)}, { "SUBDATE", SYM(SUBDATE_SYM)}, { "SUBSTR", SYM(SUBSTRING)}, { "SUBSTRING", SYM(SUBSTRING)}, { "SUM", SYM(SUM_SYM)}, { "SYSTEM_USER", SYM(USER_SYM)}, { "TRIM", SYM(TRIM)}, { "TRIM_ORACLE", SYM(TRIM_ORACLE)}, { "VARIANCE", SYM(VARIANCE_SYM)}, { "VAR_POP", SYM(VARIANCE_SYM)}, { "VAR_SAMP", SYM(VAR_SAMP_SYM)}, }; size_t symbols_length= sizeof(symbols) / sizeof(SYMBOL); size_t sql_functions_length= sizeof(sql_functions) / sizeof(SYMBOL); #endif /* LEX_INCLUDED */ sql_type_geom.h 0000644 00000045137 15156036141 0007600 0 ustar 00 #ifndef SQL_TYPE_GEOM_H_INCLUDED #define SQL_TYPE_GEOM_H_INCLUDED /* Copyright (c) 2015 MariaDB Foundation Copyright (c) 2019, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation #endif #include "mariadb.h" #include "sql_type.h" #ifdef HAVE_SPATIAL class Type_handler_geometry: public Type_handler_string_result { public: enum geometry_types { GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3, GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6, GEOM_GEOMETRYCOLLECTION = 7 }; static bool check_type_geom_or_binary(const LEX_CSTRING &opname, const Item *item); static bool check_types_geom_or_binary(const LEX_CSTRING &opname, Item * const *args, uint start, uint end); static const Type_handler_geometry *type_handler_geom_by_type(uint type); LEX_CSTRING extended_metadata_data_type_name() const; public: virtual ~Type_handler_geometry() {} enum_field_types field_type() const override { return MYSQL_TYPE_GEOMETRY; } bool Item_append_extended_type_info(Send_field_extended_metadata *to, const Item *item) const override { LEX_CSTRING tmp= extended_metadata_data_type_name(); return tmp.length ? to->set_data_type_name(tmp) : false; } bool is_param_long_data_type() const override { return true; } uint32 max_display_length_for_field(const Conv_source &src) const override; uint32 calc_pack_length(uint32 length) const override; const Type_collection *type_collection() const override; const Type_handler *type_handler_for_comparison() const override; virtual geometry_types geometry_type() const { return GEOM_GEOMETRY; } virtual Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; const Type_handler *type_handler_frm_unpack(const uchar *buffer) const override; bool is_binary_compatible_geom_super_type_for(const Type_handler_geometry *th) const { return geometry_type() == GEOM_GEOMETRY || geometry_type() == th->geometry_type(); } bool type_can_have_key_part() const override { return true; } bool subquery_type_allows_materialization(const Item *, const Item *, bool) const override { return false; // Materialization does not work with GEOMETRY columns } void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const override; Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; Log_event_data_type user_var_log_event_data_type(uint charset_nr) const override { return Log_event_data_type(name().lex_cstring(), result_type(), charset_nr, false/*unsigned*/); } uint Column_definition_gis_options_image(uchar *buff, const Column_definition &def) const override; bool Column_definition_data_type_info_image(Binary_string *to, const Column_definition &def) const override { return false; } void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; bool Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *c, const Field *field) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, column_definition_type_t type, const Column_derived_attributes *derived_attr) const override; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const override; bool Key_part_spec_init_primary(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_unique(Key_part_spec *part, const Column_definition &def, const handler *file, bool *has_key_needed) const override; bool Key_part_spec_init_multiple(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_foreign(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_spatial(Key_part_spec *part, const Column_definition &def) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *share) const override; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override; bool can_return_int() const override { return false; } bool can_return_decimal() const override { return false; } bool can_return_real() const override { return false; } bool can_return_text() const override { return false; } bool can_return_date() const override { return false; } bool can_return_time() const override { return false; } bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *h, Type_all_attributes *attr, Item **items, uint nitems) const override; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const override; bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const override; bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const override; bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const override; bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const override; bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const override; bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const override; bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const override; }; class Type_handler_point: public Type_handler_geometry { // Binary length of a POINT value: 4 byte SRID + 21 byte WKB POINT static uint octet_length() { return 25; } public: geometry_types geometry_type() const override { return GEOM_POINT; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; bool Key_part_spec_init_primary(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_unique(Key_part_spec *part, const Column_definition &def, const handler *file, bool *has_key_needed) const override; bool Key_part_spec_init_multiple(Key_part_spec *part, const Column_definition &def, const handler *file) const override; bool Key_part_spec_init_foreign(Key_part_spec *part, const Column_definition &def, const handler *file) const override; }; class Type_handler_linestring: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_LINESTRING; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; class Type_handler_polygon: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_POLYGON; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; class Type_handler_multipoint: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_MULTIPOINT; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; class Type_handler_multilinestring: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_MULTILINESTRING; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; class Type_handler_multipolygon: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_MULTIPOLYGON; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; class Type_handler_geometrycollection: public Type_handler_geometry { public: geometry_types geometry_type() const override { return GEOM_GEOMETRYCOLLECTION; } Item *make_constructor_item(THD *thd, List<Item> *args) const override; }; extern Named_type_handler<Type_handler_geometry> type_handler_geometry; extern Named_type_handler<Type_handler_point> type_handler_point; extern Named_type_handler<Type_handler_linestring> type_handler_linestring; extern Named_type_handler<Type_handler_polygon> type_handler_polygon; extern Named_type_handler<Type_handler_multipoint> type_handler_multipoint; extern Named_type_handler<Type_handler_multilinestring> type_handler_multilinestring; extern Named_type_handler<Type_handler_multipolygon> type_handler_multipolygon; extern Named_type_handler<Type_handler_geometrycollection> type_handler_geometrycollection; class Type_collection_geometry: public Type_collection { const Type_handler *aggregate_common(const Type_handler *a, const Type_handler *b) const { if (a == b) return a; if (dynamic_cast<const Type_handler_geometry*>(a) && dynamic_cast<const Type_handler_geometry*>(b)) return &type_handler_geometry; return NULL; } const Type_handler *aggregate_if_null(const Type_handler *a, const Type_handler *b) const { return a == &type_handler_null ? b : b == &type_handler_null ? a : NULL; } const Type_handler *aggregate_if_long_blob(const Type_handler *a, const Type_handler *b) const { return a == &type_handler_long_blob ? &type_handler_long_blob : b == &type_handler_long_blob ? &type_handler_long_blob : NULL; } const Type_handler *aggregate_if_string(const Type_handler *a, const Type_handler *b) const; #ifndef DBUG_OFF bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const; #endif public: bool init(Type_handler_data *data) override; const Type_handler *aggregate_for_result(const Type_handler *a, const Type_handler *b) const override; const Type_handler *aggregate_for_comparison(const Type_handler *a, const Type_handler *b) const override; const Type_handler *aggregate_for_min_max(const Type_handler *a, const Type_handler *b) const override; const Type_handler *aggregate_for_num_op(const Type_handler *a, const Type_handler *b) const override { return NULL; } }; extern Type_collection_geometry type_collection_geometry; const Type_handler * Type_collection_geometry_handler_by_name(const LEX_CSTRING &name); #include "field.h" class Field_geom :public Field_blob { const Type_handler_geometry *m_type_handler; public: uint srid; uint precision; enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1}; enum storage_type storage; Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, const Type_handler_geometry *gth, uint field_srid) :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, blob_pack_length, &my_charset_bin), m_type_handler(gth) { srid= field_srid; } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override; enum ha_base_keytype key_type() const override { return HA_KEYTYPE_VARBINARY2; } const Type_handler *type_handler() const override { return m_type_handler; } const Type_handler_geometry *type_handler_geom() const { return m_type_handler; } void set_type_handler(const Type_handler_geometry *th) { m_type_handler= th; } enum_field_types type() const override { return MYSQL_TYPE_GEOMETRY; } enum_field_types real_type() const override { return MYSQL_TYPE_GEOMETRY; } Information_schema_character_attributes information_schema_character_attributes() const override { return Information_schema_character_attributes(); } void make_send_field(Send_field *to) override { Field_longstr::make_send_field(to); LEX_CSTRING tmp= m_type_handler->extended_metadata_data_type_name(); if (tmp.length) to->set_data_type_name(tmp); } Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const override; void sql_type(String &str) const override; Copy_func *get_copy_func(const Field *from) const override { const Type_handler_geometry *fth= dynamic_cast<const Type_handler_geometry*>(from->type_handler()); if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth)) return get_identical_copy_func(); return do_conv_blob; } bool memcpy_field_possible(const Field *from) const override { const Type_handler_geometry *fth= dynamic_cast<const Type_handler_geometry*>(from->type_handler()); return fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth) && !table->copy_blobs; } bool is_equal(const Column_definition &new_field) const override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; uint size_of() const override{ return sizeof(*this); } /** Key length is provided only to support hash joins. (compared byte for byte) Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2. The comparison is not very relevant, as identical geometry might be represented differently, but we need to support it either way. */ uint32 key_length() const override{ return packlength; } uint get_key_image(uchar *buff,uint length, const uchar *ptr_arg, imagetype type_arg) const override; /** Non-nullable GEOMETRY types cannot have defaults, but the underlying blob must still be reset. */ int reset(void) override{ return Field_blob::reset() || !maybe_null(); } bool load_data_set_null(THD *thd) override; bool load_data_set_no_data(THD *thd, bool fixed_format) override; uint get_srid() const { return srid; } void print_key_value(String *out, uint32 length) override { out->append(STRING_WITH_LEN("unprintable_geometry_value")); } Binlog_type_info binlog_type_info() const override; }; #endif // HAVE_SPATIAL #endif // SQL_TYPE_GEOM_H_INCLUDED my_virtual_mem.h 0000644 00000002147 15156036141 0007754 0 ustar 00 /* Copyright (c) 2025, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once /* Functionality for handling virtual memory (reserve, commit, decommit, release) */ #include <stddef.h> /*size_t*/ #ifdef __cplusplus extern "C" { #endif # ifdef _WIN32 char *my_virtual_mem_reserve(size_t *size); # endif char *my_virtual_mem_commit(char *ptr, size_t size); void my_virtual_mem_decommit(char *ptr, size_t size); void my_virtual_mem_release(char *ptr, size_t size); #ifdef __cplusplus } #endif mysys_err.h 0000644 00000005761 15156036141 0006764 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _mysys_err_h #define _mysys_err_h #ifdef __cplusplus extern "C" { #endif #define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */ #define EE(X) (globerrs[(X) - EE_ERROR_FIRST]) extern const char *globerrs[]; /* my_error_messages is here */ /* Error message numbers in global map */ /* Do not add error numbers before EE_ERROR_FIRST. If necessary to add lower numbers, change EE_ERROR_FIRST accordingly. We start with error 1 to not confuse peoples with 'error 0' */ #define EE_ERROR_FIRST 1 /*Copy first error nr.*/ #define EE_CANTCREATEFILE 1 #define EE_READ 2 #define EE_WRITE 3 #define EE_BADCLOSE 4 #define EE_OUTOFMEMORY 5 #define EE_DELETE 6 #define EE_LINK 7 #define EE_EOFERR 9 #define EE_CANTLOCK 10 #define EE_CANTUNLOCK 11 #define EE_DIR 12 #define EE_STAT 13 #define EE_CANT_CHSIZE 14 #define EE_CANT_OPEN_STREAM 15 #define EE_GETWD 16 #define EE_SETWD 17 #define EE_LINK_WARNING 18 #define EE_OPEN_WARNING 19 #define EE_DISK_FULL 20 #define EE_CANT_MKDIR 21 #define EE_UNKNOWN_CHARSET 22 #define EE_OUT_OF_FILERESOURCES 23 #define EE_CANT_READLINK 24 #define EE_CANT_SYMLINK 25 #define EE_REALPATH 26 #define EE_SYNC 27 #define EE_UNKNOWN_COLLATION 28 #define EE_FILENOTFOUND 29 #define EE_FILE_NOT_CLOSED 30 #define EE_CHANGE_OWNERSHIP 31 #define EE_CHANGE_PERMISSIONS 32 #define EE_CANT_SEEK 33 #define EE_CANT_CHMOD 34 #define EE_CANT_COPY_OWNERSHIP 35 #define EE_BADMEMORYRELEASE 36 #define EE_PERM_LOCK_MEMORY 37 #define EE_MEMCNTL 38 #define EE_DUPLICATE_CHARSET 39 #define EE_NAME_DEPRECATED 40 #define EE_ERROR_LAST 40 /* Copy last error nr */ /* Add error numbers before EE_ERROR_LAST and change it accordingly. */ /* exit codes for all MySQL programs */ #define EXIT_UNSPECIFIED_ERROR 1 #define EXIT_UNKNOWN_OPTION 2 #define EXIT_AMBIGUOUS_OPTION 3 #define EXIT_NO_ARGUMENT_ALLOWED 4 #define EXIT_ARGUMENT_REQUIRED 5 #define EXIT_VAR_PREFIX_NOT_UNIQUE 6 #define EXIT_UNKNOWN_VARIABLE 7 #define EXIT_OUT_OF_MEMORY 8 #define EXIT_UNKNOWN_SUFFIX 9 #define EXIT_NO_PTR_TO_VARIABLE 10 #define EXIT_CANNOT_CONNECT_TO_SERVICE 11 #define EXIT_OPTION_DISABLED 12 #define EXIT_ARGUMENT_INVALID 13 #ifdef __cplusplus } #endif #endif queues.h 0000644 00000006625 15156036142 0006240 0 ustar 00 /* Copyright (C) 2010 Monty Program Ab All Rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Code for general handling of priority Queues. Implementation of queues from "Algorithms in C" by Robert Sedgewick. */ #ifndef _queues_h #define _queues_h #include <my_cmp.h> #ifdef __cplusplus extern "C" { #endif typedef struct st_queue { uchar **root; void *first_cmp_arg; uint elements; uint max_elements; uint offset_to_key; /* compare is done on element+offset */ uint offset_to_queue_pos; /* If we want to store position in element */ uint auto_extent; int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ qsort_cmp2 compare; } QUEUE; #define queue_first_element(queue) 1 #define queue_last_element(queue) (queue)->elements #define queue_empty(queue) ((queue)->elements == 0) #define queue_top(queue) ((queue)->root[1]) #define queue_element(queue,index) ((queue)->root[index]) #define queue_end(queue) ((queue)->root[(queue)->elements]) #define queue_replace_top(queue) _downheap(queue, 1) #define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg #define queue_set_max_at_top(queue, set_arg) \ (queue)->max_at_top= set_arg ? -1 : 1 #define queue_remove_top(queue_arg) queue_remove((queue_arg), queue_first_element(queue_arg)) int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, my_bool max_at_top, qsort_cmp2 compare, void *first_cmp_arg, uint offset_to_queue_pos, uint auto_extent); int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, my_bool max_at_top, qsort_cmp2 compare, void *first_cmp_arg, uint offset_to_queue_pos, uint auto_extent); int resize_queue(QUEUE *queue, uint max_elements); void delete_queue(QUEUE *queue); void queue_insert(QUEUE *queue, uchar *element); int queue_insert_safe(QUEUE *queue, uchar *element); uchar *queue_remove(QUEUE *queue,uint idx); void queue_replace(QUEUE *queue,uint idx); #define queue_remove_all(queue) { (queue)->elements= 0; } #define queue_is_full(queue) (queue->elements == queue->max_elements) void _downheap(QUEUE *queue, uint idx); void queue_fix(QUEUE *queue); #define is_queue_inited(queue) ((queue)->root != 0) #ifdef __cplusplus } #endif #endif tztime.h 0000644 00000007226 15156036142 0006243 0 ustar 00 #ifndef TZTIME_INCLUDED #define TZTIME_INCLUDED /* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class interface */ #endif #include "my_time.h" /* my_time_t */ #include "mysql_time.h" /* MYSQL_TIME */ #include "sql_list.h" /* Sql_alloc */ #include "sql_string.h" /* String */ class THD; #if !defined(TESTTIME) && !defined(TZINFO2SQL) class THD; /** This class represents abstract time zone and provides basic interface for MYSQL_TIME <-> my_time_t conversion. Actual time zones which are specified by DB, or via offset or use system functions are its descendants. */ class Time_zone: public Sql_alloc { public: Time_zone() = default; /* Remove gcc warning */ /** Converts local time in broken down MYSQL_TIME representation to my_time_t (UTC seconds since Epoch) represenation. Returns 0 in case of error. May set error_code to ER_WARN_DATA_OUT_OF_RANGE or ER_WARN_INVALID_TIMESTAMP, see TIME_to_timestamp()) */ virtual my_time_t TIME_to_gmt_sec(const MYSQL_TIME *t, uint *error_code) const = 0; /** Converts time in my_time_t representation to local time in broken down MYSQL_TIME representation. */ virtual void gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const = 0; /** Because of constness of String returned by get_name() time zone name have to be already zeroended to be able to use String::ptr() instead of c_ptr(). */ virtual const String * get_name() const = 0; virtual void get_timezone_information(struct my_tz* curr_tz, const MYSQL_TIME *local_TIME) const = 0; /** We need this only for surpressing warnings, objects of this type are allocated on MEM_ROOT and should not require destruction. */ virtual ~Time_zone() = default; /** Check if the time zone does not have any anomalies around "sec", such as: - DST changes (spring forward, fall back) - leap seconds (the 60-th second) */ bool is_monotone_continuous_around(my_time_t sec) const; protected: static inline void adjust_leap_second(MYSQL_TIME *t); }; extern Time_zone * my_tz_UTC; extern MYSQL_PLUGIN_IMPORT Time_zone * my_tz_SYSTEM; extern Time_zone * my_tz_OFFSET0; extern Time_zone * my_tz_find(THD *thd, const String *name); extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap); extern void my_tz_free(); extern my_time_t sec_since_epoch_TIME(MYSQL_TIME *t); /** Number of elements in table list produced by my_tz_get_table_list() (this table list contains tables which are needed for dynamical loading of time zone descriptions). Actually it is imlementation detail that should not be used anywhere outside of tztime.h and tztime.cc. */ static const int MY_TZ_TABLES_COUNT= 4; #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ #endif /* TZTIME_INCLUDED */ sql_type_timeofday.h 0000644 00000004407 15156036142 0010626 0 ustar 00 /* Copyright (c) 2024, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TYPE_TIMEOFDAY_INCLUDED #define SQL_TYPE_TIMEOFDAY_INCLUDED #include "my_time.h" // TIME_MAX_MINUTE /* This class stores a time of the day with fractional precision up to 6 digits. */ class TimeOfDay6 { uint m_hour; // 0..23 uint m_minute; // 0..59 uint m_second; // 0..59 uint m_usecond; // 0..999999 bool is_valid_time_of_day6() const { return m_hour <= 23 && m_minute <= TIME_MAX_MINUTE && m_second <= TIME_MAX_SECOND && m_usecond <= TIME_MAX_SECOND_PART; } public: TimeOfDay6() :m_hour(0), m_minute(0), m_second(0), m_usecond(0) { } // This constructor assumes the caller passes valid 'hh:mm:ss.ff' values TimeOfDay6(uint hour, uint minute, uint second, uint usecond) :m_hour(hour), m_minute(minute), m_second(second), m_usecond(usecond) { DBUG_ASSERT(is_valid_time_of_day6()); } uint hour() const { return m_hour; } uint minute() const { return m_minute; } uint second() const { return m_second; } uint usecond() const { return m_usecond; } /* Return the last time of the day for the given precision, e.g.: - '23:59:59.000000' for decimals==0 - '23:59:59.999000' for decimals==3 - '23:59:59.999999' for decimals==6 */ static TimeOfDay6 end_of_day(decimal_digits_t decimals) { long rem= my_time_fraction_remainder(TIME_MAX_SECOND_PART, decimals); DBUG_ASSERT(rem >= 0 && rem <= TIME_MAX_SECOND_PART); return TimeOfDay6(23, TIME_MAX_MINUTE, TIME_MAX_SECOND, (uint) (TIME_MAX_SECOND_PART - (uint) rem)); } }; #endif // SQL_TYPE_TIMEOFDAY_INCLUDED sp_rcontext.h 0000644 00000034127 15156036142 0007277 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_RCONTEXT_H_ #define _SP_RCONTEXT_H_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_class.h" // select_result_interceptor #include "sp_pcontext.h" // sp_condition_value /////////////////////////////////////////////////////////////////////////// // sp_rcontext declaration. /////////////////////////////////////////////////////////////////////////// class sp_cursor; class sp_lex_keeper; class sp_instr_cpush; class sp_instr_hpush_jump; class Query_arena; class sp_head; class Item_cache; class Virtual_tmp_table; /* This class is a runtime context of a Stored Routine. It is used in an execution and is intended to contain all dynamic objects (i.e. objects, which can be changed during execution), such as: - stored routine variables; - cursors; - handlers; Runtime context is used with sp_head class. sp_head class is intended to contain all static things, related to the stored routines (code, for example). sp_head instance creates runtime context for the execution of a stored routine. There is a parsing context (an instance of sp_pcontext class), which is used on parsing stage. However, now it contains some necessary for an execution things, such as definition of used stored routine variables. That's why runtime context needs a reference to the parsing context. */ class sp_rcontext : public Sql_alloc { public: /// Construct and properly initialize a new sp_rcontext instance. The static /// create-function is needed because we need a way to return an error from /// the constructor. /// /// @param thd Thread handle. /// @param root_parsing_ctx Top-level parsing context for this stored program. /// @param return_value_fld Field object to store the return value /// (for stored functions only). /// /// @return valid sp_rcontext object or NULL in case of OOM-error. static sp_rcontext *create(THD *thd, sp_head *owner, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, Row_definition_list &defs); ~sp_rcontext(); private: sp_rcontext(sp_head *owner, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, bool in_sub_stmt); // Prevent use of copying constructor and operator. sp_rcontext(const sp_rcontext &); void operator=(sp_rcontext &); public: /// This class stores basic information about SQL-condition, such as: /// - SQL error code; /// - error level; /// - SQLSTATE; /// - text message. /// /// It's used to organize runtime SQL-handler call stack. /// /// Standard Sql_condition class can not be used, because we don't always have /// an Sql_condition object for an SQL-condition in Diagnostics_area. /// /// Eventually, this class should be moved to sql_error.h, and be a part of /// standard SQL-condition processing (Diagnostics_area should contain an /// object for active SQL-condition, not just information stored in DA's /// fields). class Sql_condition_info : public Sql_alloc, public Sql_condition_identity { public: /// Text message. char *message; /** Row number where the condition has happened */ ulong m_row_number; /// The constructor. /// /// @param _sql_condition The SQL condition. /// @param arena Query arena for SP Sql_condition_info(const Sql_condition *_sql_condition, Query_arena *arena) :Sql_condition_identity(*_sql_condition) { message= strdup_root(arena->mem_root, _sql_condition->get_message_text()); m_row_number= _sql_condition->m_row_number; } }; private: /// This class represents a call frame of SQL-handler (one invocation of a /// handler). Basically, it's needed to store continue instruction pointer for /// CONTINUE SQL-handlers. class Handler_call_frame : public Sql_alloc { public: /// SQL-condition, triggered handler activation. const Sql_condition_info *sql_condition; /// Continue-instruction-pointer for CONTINUE-handlers. /// The attribute contains 0 for EXIT-handlers. uint continue_ip; /// The constructor. /// /// @param _sql_condition SQL-condition, triggered handler activation. /// @param _continue_ip Continue instruction pointer. Handler_call_frame(const Sql_condition_info *_sql_condition, uint _continue_ip) :sql_condition(_sql_condition), continue_ip(_continue_ip) { } }; public: /// Arena used to (re) allocate items on. E.g. reallocate INOUT/OUT /// SP-variables when they don't fit into prealloced items. This is common /// situation with String items. It is used mainly in sp_eval_func_item(). Query_arena *callers_arena; /// Flag to end an open result set before start executing an SQL-handler /// (if one is found). Otherwise the client will hang due to a violation /// of the client/server protocol. bool end_partial_result_set; bool pause_state; bool quit_func; uint instr_ptr; /// The stored program for which this runtime context is created. Used for /// checking if correct runtime context is used for variable handling, /// and to access the package run-time context. /// Also used by slow log. sp_head *m_sp; ///////////////////////////////////////////////////////////////////////// // SP-variables. ///////////////////////////////////////////////////////////////////////// uint argument_count() const { return m_root_parsing_ctx->context_var_count(); } int set_variable(THD *thd, uint var_idx, Item **value); int set_variable_row_field(THD *thd, uint var_idx, uint field_idx, Item **value); int set_variable_row_field_by_name(THD *thd, uint var_idx, const LEX_CSTRING &field_name, Item **value); int set_variable_row(THD *thd, uint var_idx, List<Item> &items); int set_parameter(THD *thd, uint var_idx, Item **value) { DBUG_ASSERT(var_idx < argument_count()); return set_variable(thd, var_idx, value); } Item_field *get_variable(uint var_idx) const { return m_var_items[var_idx]; } Item **get_variable_addr(uint var_idx) const { return ((Item **) m_var_items.array()) + var_idx; } Item_field *get_parameter(uint var_idx) const { DBUG_ASSERT(var_idx < argument_count()); return get_variable(var_idx); } bool find_row_field_by_name_or_error(uint *field_idx, uint var_idx, const LEX_CSTRING &field_name); bool set_return_value(THD *thd, Item **return_value_item); bool is_return_value_set() const { return m_return_value_set; } ///////////////////////////////////////////////////////////////////////// // SQL-handlers. ///////////////////////////////////////////////////////////////////////// /// Push an sp_instr_hpush_jump instance to the handler call stack. /// /// @param entry The condition handler entry /// /// @return error flag. /// @retval false on success. /// @retval true on error. bool push_handler(sp_instr_hpush_jump *entry); /// Pop and delete given number of instances from the handler /// call stack. /// /// @param count Number of handler entries to pop & delete. void pop_handlers(size_t count); const Sql_condition_info *raised_condition() const { return m_handler_call_stack.elements() ? (*m_handler_call_stack.back())->sql_condition : NULL; } /// Handle current SQL condition (if any). /// /// This is the public-interface function to handle SQL conditions in /// stored routines. /// /// @param thd Thread handle. /// @param ip[out] Instruction pointer to the first handler /// instruction. /// @param cur_spi Current SP instruction. /// /// @retval true if an SQL-handler has been activated. That means, all of /// the following conditions are satisfied: /// - the SP-instruction raised SQL-condition(s), /// - and there is an SQL-handler to process at least one of those /// SQL-conditions, /// - and that SQL-handler has been activated. /// Note, that the return value has nothing to do with "error flag" /// semantics. /// /// @retval false otherwise. bool handle_sql_condition(THD *thd, uint *ip, const sp_instr *cur_spi); /// Remove latest call frame from the handler call stack. /// /// @param da Diagnostics area containing handled conditions. /// /// @return continue instruction pointer of the removed handler. uint exit_handler(Diagnostics_area *da); ///////////////////////////////////////////////////////////////////////// // Cursors. ///////////////////////////////////////////////////////////////////////// /// Push a cursor to the cursor stack. /// /// @param cursor The cursor /// void push_cursor(sp_cursor *cur); void pop_cursor(THD *thd); /// Pop and delete given number of sp_cursor instance from the cursor stack. /// /// @param count Number of cursors to pop & delete. void pop_cursors(THD *thd, size_t count); void pop_all_cursors(THD *thd) { pop_cursors(thd, m_ccount); } sp_cursor *get_cursor(uint i) const { return m_cstack[i]; } ///////////////////////////////////////////////////////////////////////// // CASE expressions. ///////////////////////////////////////////////////////////////////////// /// Set CASE expression to the specified value. /// /// @param thd Thread handler. /// @param case_expr_id The CASE expression identifier. /// @param case_expr_item The CASE expression value /// /// @return error flag. /// @retval false on success. /// @retval true on error. /// /// @note The idea is to reuse Item_cache for the expression of the one /// CASE statement. This optimization takes place when there is CASE /// statement inside of a loop. So, in other words, we will use the same /// object on each iteration instead of creating a new one for each /// iteration. /// /// TODO /// Hypothetically, a type of CASE expression can be different for each /// iteration. For instance, this can happen if the expression contains /// a session variable (something like @@VAR) and its type is changed /// from one iteration to another. /// /// In order to cope with this problem, we check type each time, when we /// use already created object. If the type does not match, we re-create /// Item. This also can (should?) be optimized. bool set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr); Item *get_case_expr(int case_expr_id) const { return m_case_expr_holders[case_expr_id]; } Item ** get_case_expr_addr(int case_expr_id) const { return (Item**) m_case_expr_holders.array() + case_expr_id; } private: /// Internal function to allocate memory for arrays. /// /// @param thd Thread handle. /// /// @return error flag: false on success, true in case of failure. bool alloc_arrays(THD *thd); /// Create and initialize a table to store SP-variables. /// /// param thd Thread handle. /// /// @return error flag. /// @retval false on success. /// @retval true on error. bool init_var_table(THD *thd, List<Spvar_definition> &defs); /// Create and initialize an Item-adapter (Item_field) for each SP-var field. /// /// param thd Thread handle. /// /// @return error flag. /// @retval false on success. /// @retval true on error. bool init_var_items(THD *thd, List<Spvar_definition> &defs); /// Create an instance of appropriate Item_cache class depending on the /// specified type in the callers arena. /// /// @note We should create cache items in the callers arena, as they are /// used between in several instructions. /// /// @param thd Thread handler. /// @param item Item to get the expression type. /// /// @return Pointer to valid object on success, or NULL in case of error. Item_cache *create_case_expr_holder(THD *thd, const Item *item) const; Virtual_tmp_table *virtual_tmp_table_for_row(uint idx); private: /// Top-level (root) parsing context for this runtime context. const sp_pcontext *m_root_parsing_ctx; /// Virtual table for storing SP-variables. Virtual_tmp_table *m_var_table; /// Collection of Item_field proxies, each of them points to the /// corresponding field in m_var_table. Bounds_checked_array<Item_field *> m_var_items; /// This is a pointer to a field, which should contain return value for /// stored functions (only). For stored procedures, this pointer is NULL. Field *m_return_value_fld; /// Indicates whether the return value (in m_return_value_fld) has been /// set during execution. bool m_return_value_set; /// Flag to tell if the runtime context is created for a sub-statement. bool m_in_sub_stmt; /// Stack of visible handlers. Dynamic_array<sp_instr_hpush_jump *> m_handlers; /// Stack of caught SQL conditions. Dynamic_array<Handler_call_frame *> m_handler_call_stack; /// Stack of cursors. Bounds_checked_array<sp_cursor *> m_cstack; /// Current number of cursors in m_cstack. uint m_ccount; /// Array of CASE expression holders. Bounds_checked_array<Item_cache *> m_case_expr_holders; }; // class sp_rcontext : public Sql_alloc #endif /* _SP_RCONTEXT_H_ */ wsrep.h 0000644 00000006354 15156036142 0006070 0 ustar 00 /* Copyright 2014 Codership Oy <http://www.codership.com> & SkySQL Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef WSREP_INCLUDED #define WSREP_INCLUDED #include <my_config.h> #include "log.h" #ifdef WITH_WSREP #define IF_WSREP(A,B) A #define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) extern ulong wsrep_debug; // wsrep_mysqld.cc extern void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...); #define WSREP_DEBUG(...) \ if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) #define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) #define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) #define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) #define WSREP_UNKNOWN(fmt, ...) WSREP_ERROR("UNKNOWN: " fmt, ##__VA_ARGS__) #define WSREP_LOG_CONFLICT_THD(thd, role) \ WSREP_INFO("%s: \n " \ " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ " SQL: %s", \ role, \ thd_get_thread_id(thd), \ wsrep_thd_client_mode_str(thd), \ wsrep_thd_client_state_str(thd), \ wsrep_thd_transaction_state_str(thd), \ wsrep_thd_trx_seqno(thd), \ wsrep_thd_query(thd) \ ); #define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ if (wsrep_debug || wsrep_log_conflicts) \ { \ WSREP_INFO("cluster conflict due to %s for threads:", \ (bf_abort) ? "high priority abort" : "certification failure" \ ); \ if (bf_thd) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ WSREP_INFO("context: %s:%d", __FILE__, __LINE__); \ } #else /* !WITH_WSREP */ /* These macros are needed to compile MariaDB without WSREP support * (e.g. embedded) */ #define IF_WSREP(A,B) B //#define DBUG_ASSERT_IF_WSREP(A) #define WSREP_DEBUG(...) //#define WSREP_INFO(...) //#define WSREP_WARN(...) #define WSREP_ERROR(...) #endif /* WITH_WSREP */ #endif /* WSREP_INCLUDED */ sql_sort.h 0000644 00000053733 15156036142 0006601 0 ustar 00 #ifndef SQL_SORT_INCLUDED #define SQL_SORT_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_base.h" /* ha_rows */ #include <my_cmp.h> #include "queues.h" #include "sql_string.h" #include "sql_class.h" class Field; struct TABLE; /* Defines used by filesort and uniques */ #define MERGEBUFF 7 #define MERGEBUFF2 15 /* The structure SORT_ADDON_FIELD describes a fixed layout for field values appended to sorted values in records to be sorted in the sort buffer. Only fixed layout is supported now. Null bit maps for the appended values is placed before the values themselves. Offsets are from the last sorted field, that is from the record referefence, which is still last component of sorted records. It is preserved for backward compatiblility. The structure is used tp store values of the additional fields in the sort buffer. It is used also when these values are read from a temporary file/buffer. As the reading procedures are beyond the scope of the 'filesort' code the values have to be retrieved via the callback function 'unpack_addon_fields'. */ typedef struct st_sort_addon_field { /* Sort addon packed field */ Field *field; /* Original field */ uint offset; /* Offset from the last sorted field */ uint null_offset; /* Offset to null bit from the last sorted field */ uint length; /* Length in the sort buffer */ uint8 null_bit; /* Null bit mask for the field */ } SORT_ADDON_FIELD; struct BUFFPEK_COMPARE_CONTEXT { qsort_cmp2 key_compare; void *key_compare_arg; }; /** Descriptor for a merge chunk to be sort-merged. A merge chunk is a sequence of pre-sorted records, written to a temporary file. A Merge_chunk instance describes where this chunk is stored in the file, and where it is located when it is in memory. It is a POD because - we read/write them from/to files. We have accessors (getters/setters) for all struct members. */ struct Merge_chunk { public: my_off_t file_position() const { return m_file_position; } void set_file_position(my_off_t val) { m_file_position= val; } void advance_file_position(my_off_t val) { m_file_position+= val; } uchar *buffer_start() { return m_buffer_start; } const uchar *buffer_end() const { return m_buffer_end; } void set_buffer(uchar *start, uchar *end) { m_buffer_start= start; m_buffer_end= end; } void set_buffer_start(uchar *start) { m_buffer_start= start; } void set_buffer_end(uchar *end) { DBUG_ASSERT(m_buffer_end == NULL || end <= m_buffer_end); m_buffer_end= end; } void init_current_key() { m_current_key= m_buffer_start; } uchar *current_key() { return m_current_key; } void advance_current_key(uint val) { m_current_key+= val; } void decrement_rowcount(ha_rows val) { m_rowcount-= val; } void set_rowcount(ha_rows val) { m_rowcount= val; } ha_rows rowcount() const { return m_rowcount; } ha_rows mem_count() const { return m_mem_count; } void set_mem_count(ha_rows val) { m_mem_count= val; } ha_rows decrement_mem_count() { return --m_mem_count; } ha_rows max_keys() const { return m_max_keys; } void set_max_keys(ha_rows val) { m_max_keys= val; } size_t buffer_size() const { return m_buffer_end - m_buffer_start; } /** Tries to merge *this with *mc, returns true if successful. The assumption is that *this is no longer in use, and the space it has been allocated can be handed over to a buffer which is adjacent to it. */ bool merge_freed_buff(Merge_chunk *mc) const { if (mc->m_buffer_end == m_buffer_start) { mc->m_buffer_end= m_buffer_end; mc->m_max_keys+= m_max_keys; return true; } else if (mc->m_buffer_start == m_buffer_end) { mc->m_buffer_start= m_buffer_start; mc->m_max_keys+= m_max_keys; return true; } return false; } /// The current key for this chunk uchar *m_current_key= nullptr; /// Current position in the file to be sorted. my_off_t m_file_position= 0; /// Start of main-memory buffer for this chunk. uchar *m_buffer_start= nullptr; /// End of main-memory buffer for this chunk. uchar *m_buffer_end= nullptr; /// Number of unread rows in this chunk. ha_rows m_rowcount= 0; /// Number of rows in the main-memory buffer. ha_rows m_mem_count= 0; /// If we have fixed-size rows: max number of rows in buffer. ha_rows m_max_keys= 0; }; typedef Bounds_checked_array<SORT_ADDON_FIELD> Addon_fields_array; typedef Bounds_checked_array<SORT_FIELD> Sort_keys_array; /** This class wraps information about usage of addon fields. An Addon_fields object is used both during packing of data in the filesort buffer, and later during unpacking in 'Filesort_info::unpack_addon_fields'. @see documentation for the Sort_addon_field struct. @see documentation for get_addon_fields() */ class Addon_fields { public: Addon_fields(Addon_fields_array arr) : m_field_descriptors(arr), m_addon_buf(), m_addon_buf_length(), m_using_packed_addons(false) { DBUG_ASSERT(!arr.is_null()); } SORT_ADDON_FIELD *begin() { return m_field_descriptors.begin(); } SORT_ADDON_FIELD *end() { return m_field_descriptors.end(); } /// rr_unpack_from_tempfile needs an extra buffer when unpacking. uchar *allocate_addon_buf(uint sz) { m_addon_buf= (uchar *)my_malloc(PSI_INSTRUMENT_ME, sz, MYF(MY_WME | MY_THREAD_SPECIFIC)); if (m_addon_buf) m_addon_buf_length= sz; return m_addon_buf; } void free_addon_buff() { my_free(m_addon_buf); m_addon_buf= NULL; m_addon_buf_length= 0; } uchar *get_addon_buf() { return m_addon_buf; } uint get_addon_buf_length() const { return m_addon_buf_length; } void set_using_packed_addons(bool val) { m_using_packed_addons= val; } bool using_packed_addons() const { return m_using_packed_addons; } static bool can_pack_addon_fields(uint record_length) { return (record_length <= (0xFFFF)); } /** @returns Total number of bytes used for packed addon fields. the size of the length field + size of null bits + sum of field sizes. */ static uint read_addon_length(uchar *p) { return size_of_length_field + uint2korr(p); } /** Stores the number of bytes used for packed addon fields. */ static void store_addon_length(uchar *p, uint sz) { // We actually store the length of everything *after* the length field. int2store(p, sz - size_of_length_field); } static const uint size_of_length_field= 2; private: Addon_fields_array m_field_descriptors; uchar *m_addon_buf; ///< Buffer for unpacking addon fields. uint m_addon_buf_length; ///< Length of the buffer. bool m_using_packed_addons; ///< Are we packing the addon fields? }; /** This class wraps information about usage of sort keys. A Sort_keys object is used both during packing of data in the filesort buffer, and later during unpacking in 'Filesort_info::unpack_addon_fields'. @see SORT_FIELD struct. */ class Sort_keys :public Sql_alloc, public Sort_keys_array { public: Sort_keys(SORT_FIELD* arr, size_t count): Sort_keys_array(arr, count), m_using_packed_sortkeys(false), size_of_packable_fields(0), sort_length_with_original_values(0), sort_length_with_memcmp_values(0), parameters_computed(false) { DBUG_ASSERT(!is_null()); } bool using_packed_sortkeys() const { return m_using_packed_sortkeys; } void set_using_packed_sortkeys(bool val) { m_using_packed_sortkeys= val; } void set_size_of_packable_fields(uint len) { size_of_packable_fields= len; } uint get_size_of_packable_fields() { return size_of_packable_fields; } void set_sort_length_with_original_values(uint len) { sort_length_with_original_values= len; } uint get_sort_length_with_original_values() { return sort_length_with_original_values; } void set_sort_length_with_memcmp_values(uint len) { sort_length_with_memcmp_values= len; } uint get_sort_length_with_memcmp_values() { return sort_length_with_memcmp_values; } static void store_sortkey_length(uchar *p, uint sz) { int4store(p, sz - size_of_length_field); } static uint read_sortkey_length(uchar *p) { return size_of_length_field + uint4korr(p); } void increment_size_of_packable_fields(uint len) { size_of_packable_fields+= len; } void increment_original_sort_length(uint len) { sort_length_with_original_values+= len; } bool is_parameters_computed() { return parameters_computed; } void set_parameters_computed(bool val) { parameters_computed= val; } static const uint size_of_length_field= 4; private: bool m_using_packed_sortkeys; // Are we packing sort keys uint size_of_packable_fields; // Total length bytes for packable columns /* The sort length for all the keyparts storing the original values */ uint sort_length_with_original_values; /* The sort length for all the keyparts storing the mem-comparable images */ uint sort_length_with_memcmp_values; /* TRUE parameters(like sort_length_* , size_of_packable_field) are computed FALSE otherwise. */ bool parameters_computed; }; /** PACKED SORT KEYS Description In this optimization where we would like the pack the values of the sort key inside the sort buffer for each record. Contents: 1. Background 1.1 Implementation details 2. Solution : Packed Sort Keys 2.1 Packed key format 2.2 Which format to use 3. Special cases 3.1 Handling very long strings 3.2 Handling for long binary strings 3.3 Handling very long strings with Packed sort keys 4. Sort key columns in addon_fields 1. Background Before this optimization of using packed sort keys, filesort() sorted the data using mem-comparable keys. That is, if we wanted to sort by ORDER BY col1, col2, ... colN then the filesort code would for each row generate one "Sort Key" and then sort the rows by their Sort Keys. The Sort Keys are mem-comparable (that is, are compared by memcmp()) and they are of FIXED SIZE. The sort key has the same length regardless of what value it represents. This causes INEFFICIENT MEMORY USAGE. 1.1 Implementation details make_sortkey() is the function that produces a sort key from a record. The function treats Field and Item objects differently. class Field has: a) void make_sort_key(uchar *buff, uint length); make_sort_key is a non-virtual function which handles encoding of SQL null values. b) virtual void sort_string(uchar *buff,uint length)=0; sort_string produces mem-comparable image of the field value for each datatype. For Items, Type_handler has a virtual function: virtual void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const= 0; which various datatypes overload. 2. SOLUTION: PACKED SORT KEYS Note that one can have mem-comparable keys are that are not fixed-size. MyRocks uses such encoding for example. However for this optimization it was decided to store the original (non-mem-comparable) values instead and use a datatype-aware key comparison function. 2.1 Packed key format The keys are stored in a new variable-size data format called "packed". The format is as follows: <sort_key_length><packed_value_1><packed_value2> ....... <packed_valueN> format for a n-part sort key <sort_key_length> is the length of the whole key. Each packed value is encoded as follows: <null_byte=0> // This is a an SQL NULL [<null_byte=1>] <packed_value> // this a non-NULL value null_byte is present if the field/item is NULLable. SQL NULL is encoded as just one NULL-indicator byte. The value itself is omitted. The format of the packed_value depends on the datatype. For "non-packable" datatypes it is just their mem-comparable form, as before. The "packable" datatypes are currently variable-length strings and the packed format for them is (for binary blobs, see a note below): <length> <string> 2.2 Which format to use The advantage of Packed Key Format is potential space savings for variable-length fields. The disadvantages are: a) It may actually take more space, because of sort_key_length and length fields. b) The comparison function is more expensive. Currently the logic is: use Packed Key Format if we would save 128 or more bytes when constructing a sort key from values that have empty string for each packable component. 3. SPECIAL CASES 3.1 HANDLING VERY LONG STRINGS the size of sort key part was limited by @@max_sort_length variable. It is defined as: The number of bytes to use when sorting data values. The server uses only the first max_sort_length bytes of each value and ignores the rest. 3.2 HANDLING VERY LONG BINARY STRINGS Long binary strings receive special treatment. A sort key for the long binary string is truncated at max_sort_length bytes like described above, but then a "suffix" is appended which contains the total length of the value before the truncation. 3.3 HANDLING VERY LONG STRINGS WITH PACKED SORT KEY Truncating multi-byte string at N bytes is not safe because one can cut in the middle of a character. One is tempted to solve this by discarding the partial character but that's also not a good idea as in some collations multiple characters may produce one weight (this is called "contraction"). This combination of circumstances: The string value is very long, so truncation is necessary The collation is "complex", so truncation is dangerous is deemed to be relatively rare so it was decided to just use the non-packed sort keys in this case. 4. SORT KEY COLUMNS IN ADDON FIELDS Currently, each sort key column is actually stored twice 1. as part of the sort key 2. in the addon_fields This made total sense when sort key stored the mem-comparable image (from which one cannot restore the original value in general case). But since we now store the original value, we could also remove it from the addon_fields and further save space. This is still a limitation and needs to be fixed later @see Sort_keys **/ /** The sort record format may use one of two formats for the non-sorted part of the record: 1. Use the rowid |<sort_key>| <rowid> | / / ref_length / 2. Use "addon fields" |<sort_key>|<null bits>|<field a><field b>...| / / addon_length / The packed format for "addon fields" |<sort_key>|<length>|<null bits>|<field a><field b>...| / / addon_length / <sort_key> The key may use one of the two formats: A. fixed-size mem-comparable form. The record is always sort_length bytes long. B. "PackedKeyFormat" - the records are variable-size. <key> Fields are fixed-size, specially encoded with Field::make_sort_key() so we can do byte-by-byte compare. <length> Contains the *actual* packed length (after packing) of everything after the sort keys. The size of the length field is 2 bytes, which should cover most use cases: addon data <= 65535 bytes. This is the same as max record size in MySQL. <null bits> One bit for each nullable field, indicating whether the field is null or not. May have size zero if no fields are nullable. <field xx> Are stored with field->pack(), and retrieved with field->unpack(). Addon fields within a record are stored consecutively, with no "holes" or padding. They will have zero size for NULL values. */ class Sort_param { public: // Length of sorted records. ALWAYS equal to sort_length + addon_length uint rec_length; /* Length of what we need to sort: Sorted columns + ref_length if not addon fields are used */ uint sort_length; /* Length of the reference to the row (rowid or primary key etc */ uint ref_length; // Length of record ref. /* Length of all addon fields. 0 if no addon fields */ uint addon_length; // Length of addon_fields /* The length of the 'result' we are going to return to the caller for each sort element. Also the length of data in final sorted file/buffer. */ uint res_length; uint max_keys_per_buffer; // Max keys / buffer. uint min_dupl_count; ha_rows limit_rows; // Select limit, or HA_POS_ERROR if unlimited. ha_rows examined_rows; // Number of examined rows. TABLE *sort_form; // For quicker make_sortkey. /** ORDER BY list with some precalculated info for filesort. Array is created and owned by a Filesort instance. */ Bounds_checked_array<SORT_FIELD> local_sortorder; Addon_fields *addon_fields; // Descriptors for companion fields. Sort_keys *sort_keys; ha_rows *accepted_rows; /* For ROWNUM */ bool using_pq; bool set_all_read_bits; uchar *unique_buff; bool not_killable; String tmp_buffer; // The fields below are used only by Unique class. qsort_cmp2 compare; BUFFPEK_COMPARE_CONTEXT cmp_context; Sort_param() { memset(reinterpret_cast<void*>(this), 0, sizeof(*this)); tmp_buffer.set_thread_specific(); /* Fix memset() clearing the charset. TODO: The constructor should be eventually rewritten not to use memset(). */ tmp_buffer.set_charset(&my_charset_bin); } void init_for_filesort(TABLE *table, Filesort *filesort, uint sortlen, ha_rows limit_rows_arg); void setup_lengths_and_limit(TABLE *table, uint sortlen, uint addon_length, ha_rows limit_rows_arg); void (*unpack)(TABLE *); /// Enables the packing of addons if possible. void try_to_pack_addons(ulong max_length_for_sort_data); /// Are we packing the "addon fields"? bool using_packed_addons() const { DBUG_ASSERT(m_using_packed_addons == (addon_fields != NULL && addon_fields->using_packed_addons())); return m_using_packed_addons; } bool using_packed_sortkeys() const { DBUG_ASSERT(m_using_packed_sortkeys == (sort_keys != NULL && sort_keys->using_packed_sortkeys())); return m_using_packed_sortkeys; } /// Are we using "addon fields"? bool using_addon_fields() const { return addon_fields != NULL; } uint32 get_result_length(uchar *plen) { if (!m_using_packed_addons) return res_length; return Addon_fields::read_addon_length(plen); } uint32 get_addon_length(uchar *plen) { if (using_packed_addons()) return Addon_fields::read_addon_length(plen); else return addon_length; } uint32 get_sort_length(uchar *plen) { if (using_packed_sortkeys()) return Sort_keys::read_sortkey_length(plen) + /* when addon fields are not present, then the sort_length also includes the res_length. For packed keys here we add the res_length */ (using_addon_fields() ? 0: res_length); else return sort_length; } uint get_record_length(uchar *plen) { if (m_packed_format) { uint sort_len= get_sort_length(plen); return sort_len + get_addon_length(plen + sort_len); } else return rec_length; } /** Getter for record length and result length. @param record_start Pointer to record. @param [out] recl Store record length here. @param [out] resl Store result length here. */ void get_rec_and_res_len(uchar *record_start, uint *recl, uint *resl) { if (m_packed_format) { uint sort_len= get_sort_length(record_start); uint addon_len= get_addon_length(record_start + sort_len); *recl= sort_len + addon_len; *resl= using_addon_fields() ? addon_len : res_length; } else { *recl= rec_length; *resl= res_length; } } void try_to_pack_sortkeys(); qsort_cmp2 get_compare_function() const { return using_packed_sortkeys() ? get_packed_keys_compare_ptr() : get_ptr_compare(sort_length); } void* get_compare_argument(size_t *sort_len) const { return using_packed_sortkeys() ? (void*) this : (void*) sort_len; } bool is_packed_format() const { return m_packed_format; } private: uint m_packable_length; bool m_using_packed_addons; ///< caches the value of using_packed_addons() /* caches the value of using_packed_sortkeys() */ bool m_using_packed_sortkeys; bool m_packed_format; }; typedef Bounds_checked_array<uchar> Sort_buffer; int merge_many_buff(Sort_param *param, Sort_buffer sort_buffer, Merge_chunk *buffpek, uint *maxbuffer, IO_CACHE *t_file); ulong read_to_buffer(IO_CACHE *fromfile, Merge_chunk *buffpek, Sort_param *param, bool packing_format); bool merge_buffers(Sort_param *param,IO_CACHE *from_file, IO_CACHE *to_file, Sort_buffer sort_buffer, Merge_chunk *lastbuff, Merge_chunk *Fb, Merge_chunk *Tb, int flag); int merge_index(Sort_param *param, Sort_buffer sort_buffer, Merge_chunk *buffpek, uint maxbuffer, IO_CACHE *tempfile, IO_CACHE *outfile); void reuse_freed_buff(QUEUE *queue, Merge_chunk *reuse, uint key_length); #endif /* SQL_SORT_INCLUDED */ derror.h 0000644 00000001724 15156036142 0006221 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef DERROR_INCLUDED #define DERROR_INCLUDED bool init_errmessage(void); void free_error_messages(); bool read_texts(const char *file_name, const char *language, const char ****data); #endif /* DERROR_INCLUDED */ log_cache.h 0000644 00000017114 15156036142 0006630 0 ustar 00 /* Copyright (c) 2023, MariaDB plc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "log_event.h" static constexpr my_off_t MY_OFF_T_UNDEF= ~0ULL; /** Truncate cache log files bigger than this */ static constexpr my_off_t CACHE_FILE_TRUNC_SIZE = 65536; class binlog_cache_data { public: binlog_cache_data(bool precompute_checksums): before_stmt_pos(MY_OFF_T_UNDEF), m_pending(0), status(0), incident(FALSE), precompute_checksums(precompute_checksums), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0), ptr_binlog_cache_disk_use(0) { /* Read the current checksum setting. We will use this setting to decide whether to pre-compute checksums in the cache. Then when writing the cache to the actual binlog, another check will be made and checksums recomputed in the unlikely case that the setting changed meanwhile. */ checksum_opt= !precompute_checksums ? BINLOG_CHECKSUM_ALG_OFF : (enum_binlog_checksum_alg)binlog_checksum_options; } ~binlog_cache_data() { DBUG_ASSERT(empty()); close_cached_file(&cache_log); } /* Return 1 if there is no relevant entries in the cache This is: - Cache is empty - There are row or critical (DDL?) events in the cache The status test is needed to avoid writing entries with only a table map entry, which would crash in do_apply_event() on the slave as it assumes that there is always a row entry after a table map. */ bool empty() const { return (pending() == NULL && (my_b_write_tell(&cache_log) == 0 || ((status & (LOGGED_ROW_EVENT | LOGGED_CRITICAL)) == 0))); } Rows_log_event *pending() const { return m_pending; } void set_pending(Rows_log_event *const pending_arg) { m_pending= pending_arg; } void set_incident(void) { incident= TRUE; } void clear_incident(void) { incident= FALSE; } bool has_incident(void) const { return(incident); } void reset() { bool cache_was_empty= empty(); bool truncate_file= (cache_log.file != -1 && my_b_write_tell(&cache_log) > CACHE_FILE_TRUNC_SIZE); truncate(0,1); // Forget what's in cache checksum_opt= !precompute_checksums ? BINLOG_CHECKSUM_ALG_OFF : (enum_binlog_checksum_alg)binlog_checksum_options; if (!cache_was_empty) compute_statistics(); if (truncate_file) my_chsize(cache_log.file, 0, 0, MYF(MY_WME)); status= 0; incident= FALSE; before_stmt_pos= MY_OFF_T_UNDEF; DBUG_ASSERT(empty()); } my_off_t get_byte_position() const { return my_b_tell(&cache_log); } my_off_t get_prev_position() const { return(before_stmt_pos); } void set_prev_position(my_off_t pos) { before_stmt_pos= pos; } void restore_prev_position() { truncate(before_stmt_pos); } void restore_savepoint(my_off_t pos) { truncate(pos); if (pos < before_stmt_pos) before_stmt_pos= MY_OFF_T_UNDEF; } void set_binlog_cache_info(my_off_t param_max_binlog_cache_size, ulong *param_ptr_binlog_cache_use, ulong *param_ptr_binlog_cache_disk_use) { /* The assertions guarantee that the set_binlog_cache_info is called just once and information passed as parameters are never zero. This is done while calling the constructor binlog_cache_mngr. We cannot set information in the constructor binlog_cache_data because the space for binlog_cache_mngr is allocated through a placement new. In the future, we can refactor this and change it to avoid the set_binlog_info. */ DBUG_ASSERT(saved_max_binlog_cache_size == 0); DBUG_ASSERT(param_max_binlog_cache_size != 0); DBUG_ASSERT(ptr_binlog_cache_use == 0); DBUG_ASSERT(param_ptr_binlog_cache_use != 0); DBUG_ASSERT(ptr_binlog_cache_disk_use == 0); DBUG_ASSERT(param_ptr_binlog_cache_disk_use != 0); saved_max_binlog_cache_size= param_max_binlog_cache_size; ptr_binlog_cache_use= param_ptr_binlog_cache_use; ptr_binlog_cache_disk_use= param_ptr_binlog_cache_disk_use; cache_log.end_of_file= saved_max_binlog_cache_size; } void add_status(enum_logged_status status_arg) { status|= status_arg; } /* Cache to store data before copying it to the binary log. */ IO_CACHE cache_log; protected: /* Binlog position before the start of the current statement. */ my_off_t before_stmt_pos; private: /* Pending binrows event. This event is the event where the rows are currently written. */ Rows_log_event *m_pending; /* Bit flags for what has been writing to cache. Used to discard logs without any data changes. see enum_logged_status; */ uint32 status; public: /* The algorithm (if any) used to pre-compute checksums in the cache. Initialized from binlog_checksum_options when the cache is reset. */ enum_binlog_checksum_alg checksum_opt; private: /* This indicates that some events did not get into the cache and most likely it is corrupted. */ bool incident; /* Whether the caller requested precomputing checksums. */ bool precompute_checksums; /** This function computes binlog cache and disk usage. */ void compute_statistics() { statistic_increment(*ptr_binlog_cache_use, &LOCK_status); if (cache_log.disk_writes != 0) { #ifdef REAL_STATISTICS statistic_add(*ptr_binlog_cache_disk_use, cache_log.disk_writes, &LOCK_status); #else statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status); #endif cache_log.disk_writes= 0; } } /* Stores the values of maximum size of the cache allowed when this cache is configured. This corresponds to either . max_binlog_cache_size or max_binlog_stmt_cache_size. */ my_off_t saved_max_binlog_cache_size; /* Stores a pointer to the status variable that keeps track of the in-memory cache usage. This corresponds to either . binlog_cache_use or binlog_stmt_cache_use. */ ulong *ptr_binlog_cache_use; /* Stores a pointer to the status variable that keeps track of the disk cache usage. This corresponds to either . binlog_cache_disk_use or binlog_stmt_cache_disk_use. */ ulong *ptr_binlog_cache_disk_use; /* It truncates the cache to a certain position. This includes deleting the pending event. */ void truncate(my_off_t pos, bool reset_cache=0) { DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); cache_log.error=0; if (pending()) { delete pending(); set_pending(0); } my_bool res __attribute__((unused))= reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache); DBUG_ASSERT(res == 0); cache_log.end_of_file= saved_max_binlog_cache_size; } binlog_cache_data& operator=(const binlog_cache_data& info); binlog_cache_data(const binlog_cache_data& info); }; sql_binlog.h 0000644 00000001577 15156036142 0007063 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_BINLOG_INCLUDED #define SQL_BINLOG_INCLUDED class THD; void mysql_client_binlog_statement(THD *thd); #endif /* SQL_BINLOG_INCLUDED */ rpl_constants.h 0000644 00000006435 15156036142 0007621 0 ustar 00 /* Copyright (c) 2007 MySQL AB, 2008 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_CONSTANTS_H #define RPL_CONSTANTS_H #include <my_sys.h> #include <my_crypt.h> /** Enumeration of the incidents that can occur for the server. */ enum Incident { /** No incident */ INCIDENT_NONE = 0, /** There are possibly lost events in the replication stream */ INCIDENT_LOST_EVENTS = 1, /** Shall be last event of the enumeration */ INCIDENT_COUNT }; /** Enumeration of the reserved formats of Binlog extra row information */ enum ExtraRowInfoFormat { /** Reserved formats 0 -> 63 inclusive */ ERIF_LASTRESERVED = 63, /** Available / uncontrolled formats 64 -> 254 inclusive */ ERIF_OPEN1 = 64, ERIF_OPEN2 = 65, ERIF_LASTOPEN = 254, /** Multi-payload format 255 Length is total length, payload is sequence of sub-payloads with their own headers containing length + format. */ ERIF_MULTI = 255 }; /* 1 byte length, 1 byte format Length is total length in bytes, including 2 byte header Length values 0 and 1 are currently invalid and reserved. */ #define EXTRA_ROW_INFO_LEN_OFFSET 0 #define EXTRA_ROW_INFO_FORMAT_OFFSET 1 #define EXTRA_ROW_INFO_HDR_BYTES 2 #define EXTRA_ROW_INFO_MAX_PAYLOAD (255 - EXTRA_ROW_INFO_HDR_BYTES) enum enum_binlog_checksum_alg { BINLOG_CHECKSUM_ALG_OFF= 0, // Events are without checksum though its generator // is checksum-capable New Master (NM). BINLOG_CHECKSUM_ALG_CRC32= 1, // CRC32 of zlib algorithm. BINLOG_CHECKSUM_ALG_ENUM_END, // the cut line: valid alg range is [1, 0x7f]. BINLOG_CHECKSUM_ALG_UNDEF= 255 // special value to tag undetermined yet checksum // or events from checksum-unaware servers }; #define BINLOG_CRYPTO_SCHEME_LENGTH 1 #define BINLOG_KEY_VERSION_LENGTH 4 #define BINLOG_IV_LENGTH MY_AES_BLOCK_SIZE #define BINLOG_IV_OFFS_LENGTH 4 #define BINLOG_NONCE_LENGTH (BINLOG_IV_LENGTH - BINLOG_IV_OFFS_LENGTH) struct Binlog_crypt_data { uint scheme; uint key_version, key_length, ctx_size; uchar key[MY_AES_MAX_KEY_LENGTH]; uchar nonce[BINLOG_NONCE_LENGTH]; int init(uint sch, uint kv) { scheme= sch; ctx_size= encryption_ctx_size(ENCRYPTION_KEY_SYSTEM_DATA, kv); key_version= kv; key_length= sizeof(key); return encryption_key_get(ENCRYPTION_KEY_SYSTEM_DATA, kv, key, &key_length); } void set_iv(uchar* iv, uint32 offs) const { memcpy(iv, nonce, BINLOG_NONCE_LENGTH); int4store(iv + BINLOG_NONCE_LENGTH, offs); } }; #endif /* RPL_CONSTANTS_H */ sql_alloc.h 0000644 00000003304 15156036142 0006671 0 ustar 00 #ifndef SQL_ALLOC_INCLUDED #define SQL_ALLOC_INCLUDED /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <my_sys.h> /* alloc_root, MEM_ROOT, TRASH */ /* MariaDB standard class memory allocator */ class Sql_alloc { public: static void *operator new(size_t size) throw () { return thd_alloc(_current_thd(), size); } static void *operator new[](size_t size) throw () { return thd_alloc(_current_thd(), size); } static void *operator new[](size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw() { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *, MEM_ROOT *){} static void operator delete[](void *, MEM_ROOT *) { /* never called */ } static void operator delete[](void *ptr, size_t size) { TRASH_FREE(ptr, size); } }; #endif /* SQL_ALLOC_INCLUDED */ event_queue.h 0000644 00000006556 15156036143 0007262 0 ustar 00 #ifndef _EVENT_QUEUE_H_ #define _EVENT_QUEUE_H_ /* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @addtogroup Event_Scheduler @{ @file event_queue.h Queue of events awaiting execution. */ #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_LOCK_event_queue; extern PSI_cond_key key_COND_queue_state; #endif /* HAVE_PSI_INTERFACE */ #include "queues.h" // QUEUE #include "sql_string.h" /* LEX_CSTRING */ #include "my_time.h" /* my_time_t, interval_type */ class Event_basic; class Event_queue_element; class Event_queue_element_for_exec; class THD; /** Queue of active events awaiting execution. */ class Event_queue { public: Event_queue(); ~Event_queue(); bool init_queue(THD *thd); /* Methods for queue management follow */ bool create_event(THD *thd, Event_queue_element *new_element, bool *created); void update_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name, Event_queue_element *new_element); void drop_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name); void drop_schema_events(THD *thd, const LEX_CSTRING *schema); void recalculate_activation_times(THD *thd); bool get_top_for_execution_if_time(THD *thd, Event_queue_element_for_exec **event_name); void dump_internal_status(); private: void empty_queue(); void deinit_queue(); /* helper functions for working with mutexes & conditionals */ void lock_data(const char *func, uint line); void unlock_data(const char *func, uint line); void cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, const char *src_func, const char *src_file, uint src_line); void find_n_remove_event(const LEX_CSTRING *db, const LEX_CSTRING *name); void drop_matching_events(THD *thd, const LEX_CSTRING *pattern, bool (*)(const LEX_CSTRING*, Event_basic *)); void dbug_dump_queue(my_time_t now); /* LOCK_event_queue is the mutex which protects the access to the queue. */ mysql_mutex_t LOCK_event_queue; mysql_cond_t COND_queue_state; /* The sorted queue with the Event_queue_element objects */ QUEUE queue; my_time_t next_activation_at; uint mutex_last_locked_at_line; uint mutex_last_unlocked_at_line; uint mutex_last_attempted_lock_at_line; const char* mutex_last_locked_in_func; const char* mutex_last_unlocked_in_func; const char* mutex_last_attempted_lock_in_func; bool mutex_queue_data_locked; bool mutex_queue_data_attempting_lock; bool waiting_on_cond; }; /** @} (End of group Event_Scheduler) */ #endif /* _EVENT_QUEUE_H_ */ sql_rename.h 0000644 00000001726 15156036143 0007055 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_RENAME_INCLUDED #define SQL_RENAME_INCLUDED class THD; struct TABLE_LIST; bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent, bool if_exists); #endif /* SQL_RENAME_INCLUDED */ my_bit.h 0000644 00000014064 15156036143 0006211 0 ustar 00 /* Copyright (c) 2007, 2011, Oracle and/or its affiliates. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MY_BIT_INCLUDED #define MY_BIT_INCLUDED /* Some useful bit functions */ C_MODE_START extern const uchar _my_bits_reverse_table[256]; /* my_bit_log2_xxx() In the given value, find the highest bit set, which is the smallest X that satisfies the condition: (2^X >= value). Can be used as a reverse operation for (1<<X), to find X. Examples: - returns 0 for (1<<0) - returns 1 for (1<<1) - returns 2 for (1<<2) - returns 2 for 3, which has (1<<2) as the highest bit set. Note, the behaviour of log2(0) is not defined. Let's return 0 for the input 0, for the code simplicity. See the 000x branch. It covers both (1<<0) and 0. */ static inline CONSTEXPR uint my_bit_log2_hex_digit(uint8 value) { return value & 0x0C ? /*1100*/ (value & 0x08 ? /*1000*/ 3 : /*0100*/ 2) : /*0010*/ (value & 0x02 ? /*0010*/ 1 : /*000x*/ 0); } static inline CONSTEXPR uint my_bit_log2_uint8(uint8 value) { return value & 0xF0 ? my_bit_log2_hex_digit((uint8) (value >> 4)) + 4: my_bit_log2_hex_digit(value); } static inline CONSTEXPR uint my_bit_log2_uint16(uint16 value) { return value & 0xFF00 ? my_bit_log2_uint8((uint8) (value >> 8)) + 8 : my_bit_log2_uint8((uint8) value); } static inline CONSTEXPR uint my_bit_log2_uint32(uint32 value) { return value & 0xFFFF0000UL ? my_bit_log2_uint16((uint16) (value >> 16)) + 16 : my_bit_log2_uint16((uint16) value); } static inline CONSTEXPR uint my_bit_log2_uint64(ulonglong value) { return value & 0xFFFFFFFF00000000ULL ? my_bit_log2_uint32((uint32) (value >> 32)) + 32 : my_bit_log2_uint32((uint32) value); } static inline CONSTEXPR uint my_bit_log2_size_t(size_t value) { #ifdef __cplusplus static_assert(sizeof(size_t) <= sizeof(ulonglong), "size_t <= ulonglong is an assumption that needs to be fixed " "for this architecture. Please create an issue on " "https://jira.mariadb.org"); #endif return my_bit_log2_uint64((ulonglong) value); } /* Count bits in 32bit integer Algorithm by Sean Anderson, according to: http://graphics.stanford.edu/~seander/bithacks.html under "Counting bits set, in parallel" (Original code public domain). */ static inline uint my_count_bits_uint32(uint32 v) { v = v - ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; } static inline uint my_count_bits(ulonglong x) { return my_count_bits_uint32((uint32)x) + my_count_bits_uint32((uint32)(x >> 32)); } /* Next highest power of two SYNOPSIS my_round_up_to_next_power() v Value to check RETURN Next or equal power of 2 Note: 0 will return 0 NOTES Algorithm by Sean Anderson, according to: http://graphics.stanford.edu/~seander/bithacks.html (Original code public domain) Comments shows how this works with 01100000000000000000000000001011 */ static inline uint32 my_round_up_to_next_power(uint32 v) { v--; /* 01100000000000000000000000001010 */ v|= v >> 1; /* 01110000000000000000000000001111 */ v|= v >> 2; /* 01111100000000000000000000001111 */ v|= v >> 4; /* 01111111110000000000000000001111 */ v|= v >> 8; /* 01111111111111111100000000001111 */ v|= v >> 16; /* 01111111111111111111111111111111 */ return v+1; /* 10000000000000000000000000000000 */ } static inline uint32 my_clear_highest_bit(uint32 v) { uint32 w=v >> 1; w|= w >> 1; w|= w >> 2; w|= w >> 4; w|= w >> 8; w|= w >> 16; return v & w; } static inline uint32 my_reverse_bits(uint32 key) { return ((uint32)_my_bits_reverse_table[ key & 255] << 24) | ((uint32)_my_bits_reverse_table[(key>> 8) & 255] << 16) | ((uint32)_my_bits_reverse_table[(key>>16) & 255] << 8) | (uint32)_my_bits_reverse_table[(key>>24) ]; } /* a number with the n lowest bits set an overflow-safe version of (1 << n) - 1 */ static inline uint64 my_set_bits(int n) { return (((1ULL << (n - 1)) - 1) << 1) | 1; } /* Create a mask of the significant bits for the last byte (1,3,7,..255) */ static inline uchar last_byte_mask(uint bits) { /* Get the number of used bits-1 (0..7) in the last byte */ unsigned int const used = (bits - 1U) & 7U; /* Return bitmask for the significant bits */ return (uchar) ((2U << used) - 1); } static inline uint my_bits_in_bytes(uint n) { return ((n + 7) / 8); } #ifdef _MSC_VER #include <intrin.h> #endif /* Find the position of the first(least significant) bit set in the argument. Returns 64 if the argument was 0. */ static inline uint my_find_first_bit(ulonglong n) { if(!n) return 64; #if defined(__GNUC__) return __builtin_ctzll(n); #elif defined(_MSC_VER) #if defined(_M_IX86) unsigned long bit; if( _BitScanForward(&bit, (uint)n)) return bit; _BitScanForward(&bit, (uint)(n>>32)); return bit + 32; #else unsigned long bit; _BitScanForward64(&bit, n); return bit; #endif #else /* Generic case */ uint shift= 0; static const uchar last_bit[16] = { 32, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; uint bit; while ((bit = last_bit[(n >> shift) & 0xF]) == 32) shift+= 4; return shift+bit; #endif } C_MODE_END #endif /* MY_BIT_INCLUDED */ my_crypt.h 0000644 00000001610 15156036143 0006565 0 ustar 00 /* Copyright (c) 2014 Google Inc. Copyright (c) 2014, 2015 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MY_CRYPT_INCLUDED #define MY_CRYPT_INCLUDED #include <my_config.h> /* HAVE_EncryptAes128{Ctr,Gcm} */ #include <mysql/service_my_crypt.h> #endif /* MY_CRYPT_INCLUDED */ pfs_file_provider.h 0000644 00000006121 15156036143 0010422 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_FILE_PROVIDER_H #define PFS_FILE_PROVIDER_H /** @file include/pfs_file_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_FILE_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_FILE_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_file_v1(const char *category, PSI_file_info_v1 *info, int count); void pfs_create_file_v1(PSI_file_key key, const char *name, File file); PSI_file_locker* pfs_get_thread_file_name_locker_v1(PSI_file_locker_state *state, PSI_file_key key, PSI_file_operation op, const char *name, const void *identity); PSI_file_locker* pfs_get_thread_file_stream_locker_v1(PSI_file_locker_state *state, PSI_file *file, PSI_file_operation op); PSI_file_locker* pfs_get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, File file, PSI_file_operation op); void pfs_start_file_open_wait_v1(PSI_file_locker *locker, const char *src_file, uint src_line); PSI_file* pfs_end_file_open_wait_v1(PSI_file_locker *locker, void *result); void pfs_end_file_open_wait_and_bind_to_descriptor_v1 (PSI_file_locker *locker, File file); void pfs_end_temp_file_open_wait_and_bind_to_descriptor_v1 (PSI_file_locker *locker, File file, const char *filename); void pfs_start_file_wait_v1(PSI_file_locker *locker, size_t count, const char *src_file, uint src_line); void pfs_end_file_wait_v1(PSI_file_locker *locker, size_t byte_count); void pfs_start_file_close_wait_v1(PSI_file_locker *locker, const char *src_file, uint src_line); void pfs_end_file_close_wait_v1(PSI_file_locker *locker, int rc); void pfs_end_file_rename_wait_v1(PSI_file_locker *locker, const char *old_name, const char *new_name, int rc); C_MODE_END #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_FILE_INTERFACE */ #endif wsrep_client_state.h 0000644 00000003036 15156036143 0010621 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_CLIENT_STATE_H #define WSREP_CLIENT_STATE_H /* wsrep-lib */ #include "wsrep/client_state.hpp" #include "my_global.h" class THD; class Wsrep_client_state : public wsrep::client_state { public: Wsrep_client_state(THD* thd, wsrep::mutex& mutex, wsrep::condition_variable& cond, wsrep::server_state& server_state, wsrep::client_service& client_service, const wsrep::client_id& id) : wsrep::client_state(mutex, cond, server_state, client_service, id, wsrep::client_state::m_local) , m_thd(thd) { } THD* thd() { return m_thd; } private: THD* m_thd; }; #endif /* WSREP_CLIENT_STATE_H */ structs.h 0000644 00000075327 15156036143 0006446 0 ustar 00 #ifndef STRUCTS_INCLUDED #define STRUCTS_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* The old structures from unireg */ #include "sql_plugin.h" /* plugin_ref */ #include "sql_const.h" /* MAX_REFLENGTH */ #include "my_time.h" /* enum_mysql_timestamp_type */ #include "thr_lock.h" /* thr_lock_type */ #include "my_base.h" /* ha_rows, ha_key_alg */ #include <mysql_com.h> /* USERNAME_LENGTH */ #include "sql_bitmap.h" #include "lex_charset.h" struct TABLE; class Type_handler; class Field; class Index_statistics; struct Lex_ident_cli_st; class THD; /* Array index type for table.field[] */ typedef uint16 field_index_t; typedef struct st_date_time_format { uchar positions[8]; char time_separator; /* Separator between hour and minute */ uint flag; /* For future */ LEX_CSTRING format; } DATE_TIME_FORMAT; typedef struct st_keyfile_info { /* used with ha_info() */ uchar ref[MAX_REFLENGTH]; /* Pointer to current row */ uchar dupp_ref[MAX_REFLENGTH]; /* Pointer to dupp row */ uint ref_length; /* Length of ref (1-8) */ uint block_size; /* index block size */ File filenr; /* (uniq) filenr for table */ ha_rows records; /* Records i datafilen */ ha_rows deleted; /* Deleted records */ ulonglong data_file_length; /* Length off data file */ ulonglong max_data_file_length; /* Length off data file */ ulonglong index_file_length; ulonglong max_index_file_length; ulonglong delete_length; /* Free bytes */ ulonglong auto_increment_value; int errkey,sortkey; /* Last errorkey and sorted by */ time_t create_time; /* When table was created */ time_t check_time; time_t update_time; ulong mean_rec_length; /* physical reclength */ } KEYFILE_INFO; typedef struct st_key_part_info { /* Info about a key part */ Field *field; /* the Field object for the indexed prefix of the original table Field. NOT necessarily the original Field */ uint offset; /* Offset in record (from 0) */ uint null_offset; /* Offset to null_bit in record */ /* Length of key part in bytes, excluding NULL flag and length bytes */ uint length; /* Number of bytes required to store the keypart value. This may be different from the "length" field as it also counts - possible NULL-flag byte (see HA_KEY_NULL_LENGTH) - possible HA_KEY_BLOB_LENGTH bytes needed to store actual value length. */ uint store_length; uint16 key_type; field_index_t fieldnr; /* Fieldnr begins counting from 1 */ uint16 key_part_flag; /* 0 or HA_REVERSE_SORT */ uint8 type; uint8 null_bit; /* Position to null_bit */ } KEY_PART_INFO ; class engine_option_value; struct ha_index_option_struct; typedef struct st_key { ulong flags; /* dupp key and pack flags */ ulong ext_key_flags; /* Flags for extended key */ ulong index_flags; /* Copy of handler->index_flags(index_number, 0, 1) */ uint key_length; /* total length of user defined key parts */ uint user_defined_key_parts; /* How many key_parts */ uint usable_key_parts; /* Should normally be = user_defined_key_parts */ uint ext_key_parts; /* Number of key parts in extended key */ uint block_size; /* The flag is on if statistical data for the index prefixes has to be taken from the system statistical tables. */ bool is_statistics_from_stat_tables; bool without_overlaps; bool is_ignored; // TRUE if index needs to be ignored /* Parts of primary key that are in the extension of this index. Example: if this structure describes idx1, which is defined as INDEX idx1 (pk2, col2) and pk is defined as: PRIMARY KEY (pk1, pk2) then pk1 is in the extension idx1, ext_key_part_map.is_set(0) == true pk2 is explicitly present in idx1, it is not in the extension, so ext_key_part_map.is_set(1) == false */ key_part_map ext_key_part_map; /* Bitmap of indexes having common parts with this index (only key parts from key definitions are taken into account) */ key_map overlapped; /* Set of keys constraint correlated with this key */ key_map constraint_correlated; LEX_CSTRING name; enum ha_key_alg algorithm; /* Note that parser is used when the table is opened for use, and parser_name is used when the table is being created. */ union { plugin_ref parser; /* Fulltext [pre]parser */ LEX_CSTRING *parser_name; /* Fulltext [pre]parser name */ }; KEY_PART_INFO *key_part; /* Unique name for cache; db + \0 + table_name + \0 + key_name + \0 */ uchar *cache_name; /* Array of AVG(#records with the same field value) for 1st ... Nth key part. 0 means 'not known'. For temporary heap tables this member is NULL. */ ulong *rec_per_key; /* Average space index tuple takes on disk, according to the engine's statistics. 0 if statistics is not available. */ size_t stat_storage_length; /* This structure is used for statistical data on the index that has been read from the statistical table index_stat */ Index_statistics *read_stats; /* This structure is used for statistical data on the index that is collected by the function collect_statistics_for_table */ Index_statistics *collected_stats; TABLE *table; LEX_CSTRING comment; /** reference to the list of options or NULL */ engine_option_value *option_list; ha_index_option_struct *option_struct; /* structure with parsed options */ /* Bitmap of key parts where all values are NULL (nulls_ratio == 1.0). Bit N set means key part N has all NULLs in the corresponding column. Used for NULL-aware cardinality estimation. It is computed based on EITS data, otherwise it is 0. */ key_part_map all_nulls_key_parts; double actual_rec_per_key(uint last_key_part_in_prefix) const; double rec_per_key_null_aware(uint last_key_part_in_prefix, key_part_map notnull_part) const; } KEY; struct st_join_table; typedef struct st_reginfo { /* Extra info about reg */ struct st_join_table *join_tab; /* Used by SELECT() */ enum thr_lock_type lock_type; /* How database is used */ bool skip_locked; bool not_exists_optimize; /* TRUE <=> range optimizer found that there is no rows satisfying table conditions. */ bool impossible_range; } REGINFO; /* Originally MySQL used MYSQL_TIME structure inside server only, but since 4.1 it's exported to user in the new client API. Define aliases for new names to keep existing code simple. */ typedef enum enum_mysql_timestamp_type timestamp_type; typedef struct { ulong year,month,day,hour; ulonglong minute,second,second_part; bool neg; } INTERVAL; typedef struct st_known_date_time_format { const char *format_name; const char *date_format; const char *datetime_format; const char *time_format; } KNOWN_DATE_TIME_FORMAT; extern const char *show_comp_option_name[]; typedef int *(*update_var)(THD *, struct st_mysql_show_var *); struct USER_AUTH : public Sql_alloc { LEX_CSTRING plugin, auth_str, pwtext; USER_AUTH *next; USER_AUTH() : next(NULL) { plugin.str= auth_str.str= ""; pwtext.str= NULL; plugin.length= auth_str.length= pwtext.length= 0; } }; struct AUTHID { LEX_CSTRING user, host; void init() { memset(this, 0, sizeof(*this)); } void copy(MEM_ROOT *root, const LEX_CSTRING *usr, const LEX_CSTRING *host); bool is_role() const { return user.str[0] && (!host.str || !host.str[0]); } void set_lex_string(LEX_CSTRING *l, char *buf) { if (is_role()) *l= user; else { l->str= buf; l->length= strxmov(buf, user.str, "@", host.str, NullS) - buf; } } void parse(const char *str, size_t length); bool read_from_mysql_proc_row(THD *thd, TABLE *table); }; struct LEX_USER: public AUTHID { USER_AUTH *auth; bool has_auth() { return auth && (auth->plugin.length || auth->auth_str.length || auth->pwtext.length); } }; /* This structure specifies the maximum amount of resources which can be consumed by each account. Zero value of a member means there is no limit. */ typedef struct user_resources { /* Maximum number of queries/statements per hour. */ uint questions; /* Maximum number of updating statements per hour (which statements are updating is defined by sql_command_flags array). */ uint updates; /* Maximum number of connections established per hour. */ uint conn_per_hour; /* Maximum number of concurrent connections. If -1 then no new connections allowed */ int user_conn; /* Max query timeout */ double max_statement_time; /* Values of this enum and specified_limits member are used by the parser to store which user limits were specified in GRANT statement. */ enum {QUERIES_PER_HOUR= 1, UPDATES_PER_HOUR= 2, CONNECTIONS_PER_HOUR= 4, USER_CONNECTIONS= 8, MAX_STATEMENT_TIME= 16}; uint specified_limits; } USER_RESOURCES; /* This structure is used for counting resources consumed and for checking them against specified user limits. */ typedef struct user_conn { /* Pointer to user+host key (pair separated by '\0') defining the entity for which resources are counted (By default it is user account thus priv_user/priv_host pair is used. If --old-style-user-limits option is enabled, resources are counted for each user+host separately). */ char *user; /* Pointer to host part of the key. */ char *host; /** The moment of time when per hour counters were reset last time (i.e. start of "hour" for conn_per_hour, updates, questions counters). */ ulonglong reset_utime; /* Total length of the key. */ uint len; /* Current amount of concurrent connections for this account. */ int connections; /* Current number of connections per hour, number of updating statements per hour and total number of statements per hour for this account. */ uint conn_per_hour, updates, questions; /* Maximum amount of resources which account is allowed to consume. */ USER_RESOURCES user_resources; } USER_CONN; typedef struct st_user_stats { char user[MY_MAX(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1]; // Account name the user is mapped to when this is a user from mapped_user. // Otherwise, the same value as user. char priv_user[MY_MAX(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1]; uint user_name_length; uint total_connections; uint total_ssl_connections; uint concurrent_connections; time_t connected_time; // in seconds ha_rows rows_read, rows_sent; ha_rows rows_updated, rows_deleted, rows_inserted; ulonglong bytes_received; ulonglong bytes_sent; ulonglong binlog_bytes_written; ulonglong select_commands, update_commands, other_commands; ulonglong commit_trans, rollback_trans; ulonglong denied_connections, lost_connections, max_statement_time_exceeded; ulonglong access_denied_errors; ulonglong empty_queries; double busy_time; // in seconds double cpu_time; // in seconds } USER_STATS; typedef struct st_table_stats { char table[NAME_LEN * 2 + 2]; // [db] + '\0' + [table] + '\0' size_t table_name_length; ulonglong rows_read, rows_changed; ulonglong rows_changed_x_indexes; /* Stores enum db_type, but forward declarations cannot be done */ int engine_type; } TABLE_STATS; typedef struct st_index_stats { // [db] + '\0' + [table] + '\0' + [index] + '\0' char index[NAME_LEN * 3 + 3]; size_t index_name_length; /* Length of 'index' */ ulonglong rows_read; } INDEX_STATS; /* Bits in form->update */ #define REG_MAKE_DUPP 1U /* Make a copy of record when read */ #define REG_NEW_RECORD 2U /* Write a new record if not found */ #define REG_UPDATE 4U /* Uppdate record */ #define REG_DELETE 8U /* Delete found record */ #define REG_PROG 16U /* User is updating database */ #define REG_CLEAR_AFTER_WRITE 32U #define REG_MAY_BE_UPDATED 64U #define REG_AUTO_UPDATE 64U /* Used in D-forms for scroll-tables */ #define REG_OVERWRITE 128U #define REG_SKIP_DUP 256U /* Bits in form->status */ #define STATUS_NO_RECORD (1U+2U) /* Record isn't usable */ #define STATUS_GARBAGE 1U #define STATUS_NOT_FOUND 2U /* No record in database when needed */ #define STATUS_NO_PARENT 4U /* Parent record wasn't found */ #define STATUS_NOT_READ 8U /* Record isn't read */ #define STATUS_UPDATED 16U /* Record is updated by formula */ #define STATUS_NULL_ROW 32U /* table->null_row is set */ #define STATUS_DELETED 64U /* Such interval is "discrete": it is the set of { auto_inc_interval_min + k * increment, 0 <= k <= (auto_inc_interval_values-1) } Where "increment" is maintained separately by the user of this class (and is currently only thd->variables.auto_increment_increment). It mustn't derive from Sql_alloc, because SET INSERT_ID needs to allocate memory which must stay allocated for use by the next statement. */ class Discrete_interval { private: ulonglong interval_min; ulonglong interval_values; ulonglong interval_max; // excluded bound. Redundant. public: Discrete_interval *next; // used when linked into Discrete_intervals_list void replace(ulonglong start, ulonglong val, ulonglong incr) { interval_min= start; interval_values= val; interval_max= (val == ULONGLONG_MAX) ? val : start + val * incr; } Discrete_interval(ulonglong start, ulonglong val, ulonglong incr) : next(NULL) { replace(start, val, incr); }; Discrete_interval() : next(NULL) { replace(0, 0, 0); }; ulonglong minimum() const { return interval_min; }; ulonglong values() const { return interval_values; }; ulonglong maximum() const { return interval_max; }; /* If appending [3,5] to [1,2], we merge both in [1,5] (they should have the same increment for that, user of the class has to ensure that). That is just a space optimization. Returns 0 if merge succeeded. */ bool merge_if_contiguous(ulonglong start, ulonglong val, ulonglong incr) { if (interval_max == start) { if (val == ULONGLONG_MAX) { interval_values= interval_max= val; } else { interval_values+= val; interval_max= start + val * incr; } return 0; } return 1; }; }; /* List of Discrete_interval objects */ class Discrete_intervals_list { private: Discrete_interval *head; Discrete_interval *tail; /* When many intervals are provided at the beginning of the execution of a statement (in a replication slave or SET INSERT_ID), "current" points to the interval being consumed by the thread now (so "current" goes from "head" to "tail" then to NULL). */ Discrete_interval *current; uint elements; // number of elements void set_members(Discrete_interval *h, Discrete_interval *t, Discrete_interval *c, uint el) { head= h; tail= t; current= c; elements= el; } void operator=(Discrete_intervals_list &); /* prevent use of these */ Discrete_intervals_list(const Discrete_intervals_list &); public: Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {}; void empty_no_free() { set_members(NULL, NULL, NULL, 0); } void empty() { for (Discrete_interval *i= head; i;) { Discrete_interval *next= i->next; delete i; i= next; } empty_no_free(); } void copy_shallow(const Discrete_intervals_list * dli) { head= dli->get_head(); tail= dli->get_tail(); current= dli->get_current(); elements= dli->nb_elements(); } void swap (Discrete_intervals_list * dli) { Discrete_interval *h, *t, *c; uint el; h= dli->get_head(); t= dli->get_tail(); c= dli->get_current(); el= dli->nb_elements(); dli->copy_shallow(this); set_members(h, t, c, el); } const Discrete_interval* get_next() { Discrete_interval *tmp= current; if (current != NULL) current= current->next; return tmp; } ~Discrete_intervals_list() { empty(); }; bool append(ulonglong start, ulonglong val, ulonglong incr); bool append(Discrete_interval *interval); ulonglong minimum() const { return (head ? head->minimum() : 0); }; ulonglong maximum() const { return (head ? tail->maximum() : 0); }; uint nb_elements() const { return elements; } Discrete_interval* get_head() const { return head; }; Discrete_interval* get_tail() const { return tail; }; Discrete_interval* get_current() const { return current; }; }; /* DDL options: - CREATE IF NOT EXISTS - DROP IF EXISTS - CREATE LIKE - REPLACE */ struct DDL_options_st { public: enum Options { OPT_NONE= 0, OPT_IF_NOT_EXISTS= 2, // CREATE TABLE IF NOT EXISTS OPT_LIKE= 4, // CREATE TABLE LIKE OPT_OR_REPLACE= 16, // CREATE OR REPLACE TABLE OPT_OR_REPLACE_SLAVE_GENERATED= 32,// REPLACE was added on slave, it was // not in the original query on master. OPT_IF_EXISTS= 64, OPT_CREATE_SELECT= 128, // CREATE ... SELECT OPT_IMPORT_TABLESPACE= 256 // ALTER ... IMPORT TABLESPACE }; private: Options m_options; public: Options create_like_options() const { return (DDL_options_st::Options) (((uint) m_options) & (OPT_IF_NOT_EXISTS | OPT_OR_REPLACE)); } void init() { m_options= OPT_NONE; } void init(Options options) { m_options= options; } void set(Options other) { m_options= other; } void set(const DDL_options_st other) { m_options= other.m_options; } bool if_not_exists() const { return m_options & OPT_IF_NOT_EXISTS; } bool or_replace() const { return m_options & OPT_OR_REPLACE; } bool or_replace_slave_generated() const { return m_options & OPT_OR_REPLACE_SLAVE_GENERATED; } bool like() const { return m_options & OPT_LIKE; } bool if_exists() const { return m_options & OPT_IF_EXISTS; } bool is_create_select() const { return m_options & OPT_CREATE_SELECT; } bool import_tablespace() const { return m_options & OPT_IMPORT_TABLESPACE; } void add(const DDL_options_st::Options other) { m_options= (Options) ((uint) m_options | (uint) other); } void add(const DDL_options_st &other) { add(other.m_options); } DDL_options_st operator|(const DDL_options_st &other) { add(other.m_options); return *this; } DDL_options_st operator|=(DDL_options_st::Options other) { add(other); return *this; } }; class DDL_options: public DDL_options_st { public: DDL_options() { init(); } DDL_options(Options options) { init(options); } DDL_options(const DDL_options_st &options) { DDL_options_st::operator=(options); } }; struct Lex_length_and_dec_st { protected: uint32 m_length; uint8 m_dec; uint8 m_collation_type:LEX_CHARSET_COLLATION_TYPE_BITS; bool m_has_explicit_length:1; bool m_has_explicit_dec:1; bool m_length_overflowed:1; bool m_dec_overflowed:1; static_assert(LEX_CHARSET_COLLATION_TYPE_BITS <= 8, "Lex_length_and_dec_st::m_collation_type bits check"); public: void reset() { m_length= 0; m_dec= 0; m_collation_type= 0; m_has_explicit_length= false; m_has_explicit_dec= false; m_length_overflowed= false; m_dec_overflowed= false; } void set_length_only(uint32 length) { m_length= length; m_dec= 0; m_collation_type= 0; m_has_explicit_length= true; m_has_explicit_dec= false; m_length_overflowed= false; m_dec_overflowed= false; } void set_dec_only(uint8 dec) { m_length= 0; m_dec= dec; m_collation_type= 0; m_has_explicit_length= false; m_has_explicit_dec= true; m_length_overflowed= false; m_dec_overflowed= false; } void set_length_and_dec(uint32 length, uint8 dec) { m_length= length; m_dec= dec; m_collation_type= 0; m_has_explicit_length= true; m_has_explicit_dec= true; m_length_overflowed= false; m_dec_overflowed= false; } void set(const char *length, const char *dec); uint32 length() const { return m_length; } uint8 dec() const { return m_dec; } bool has_explicit_length() const { return m_has_explicit_length; } bool has_explicit_dec() const { return m_has_explicit_dec; } bool length_overflowed() const { return m_length_overflowed; } bool dec_overflowed() const { return m_dec_overflowed; } }; struct Lex_field_type_st: public Lex_length_and_dec_st { private: const Type_handler *m_handler; CHARSET_INFO *m_ci; public: void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec, CHARSET_INFO *cs= NULL) { m_handler= handler; m_ci= cs; Lex_length_and_dec_st::operator=(length_and_dec); } void set(const Type_handler *handler, const Lex_length_and_dec_st &length_and_dec, const Lex_column_charset_collation_attrs_st &coll) { m_handler= handler; m_ci= coll.charset_info(); Lex_length_and_dec_st::operator=(length_and_dec); // Using bit-and to avoid the warning: // conversion from ‘uint8’ to ‘unsigned char:3’ may change value m_collation_type= ((uint8) coll.type()) & LEX_CHARSET_COLLATION_TYPE_MASK; } void set(const Type_handler *handler, const Lex_column_charset_collation_attrs_st &coll) { m_handler= handler; m_ci= coll.charset_info(); Lex_length_and_dec_st::reset(); // Using bit-and to avoid the warning: // conversion from ‘uint8’ to ‘unsigned char:3’ may change value m_collation_type= ((uint8) coll.type()) & LEX_CHARSET_COLLATION_TYPE_MASK; } void set(const Type_handler *handler, CHARSET_INFO *cs= NULL) { m_handler= handler; m_ci= cs; Lex_length_and_dec_st::reset(); } void set_handler_length_flags(const Type_handler *handler, const Lex_length_and_dec_st &length, uint32 flags); void set_handler_length(const Type_handler *handler, uint32 length) { m_handler= handler; m_ci= NULL; Lex_length_and_dec_st::set_length_only(length); } void set_handler(const Type_handler *handler) { m_handler= handler; } const Type_handler *type_handler() const { return m_handler; } CHARSET_INFO *charset_collation() const { return m_ci; } Lex_column_charset_collation_attrs charset_collation_attrs() const { return Lex_column_charset_collation_attrs(m_ci, (Lex_column_charset_collation_attrs_st::Type) m_collation_type); } }; struct Lex_dyncol_type_st: public Lex_length_and_dec_st { private: int m_type; // enum_dynamic_column_type is not visible here, so use int CHARSET_INFO *m_ci; public: void set(int type, Lex_length_and_dec_st length_and_dec, CHARSET_INFO *cs= NULL) { m_type= type; m_ci= cs; Lex_length_and_dec_st::operator=(length_and_dec); } void set(int type) { m_type= type; m_ci= NULL; Lex_length_and_dec_st::reset(); } void set(int type, CHARSET_INFO *cs) { m_type= type; m_ci= cs; Lex_length_and_dec_st::reset(); } bool set(int type, Sql_used *used, const Charset_collation_map_st &map, const Lex_column_charset_collation_attrs_st &collation, CHARSET_INFO *charset) { CHARSET_INFO *tmp= collation.resolved_to_character_set(used, map, charset); if (!tmp) return true; set(type, tmp); return false; } int dyncol_type() const { return m_type; } CHARSET_INFO *charset_collation() const { return m_ci; } }; struct Lex_spblock_handlers_st { public: int hndlrs; void init(int count) { hndlrs= count; } }; struct Lex_spblock_st: public Lex_spblock_handlers_st { public: int vars; int conds; int curs; void init() { vars= conds= hndlrs= curs= 0; } void init_using_vars(uint nvars) { vars= nvars; conds= hndlrs= curs= 0; } void join(const Lex_spblock_st &b1, const Lex_spblock_st &b2) { vars= b1.vars + b2.vars; conds= b1.conds + b2.conds; hndlrs= b1.hndlrs + b2.hndlrs; curs= b1.curs + b2.curs; } }; class Lex_spblock: public Lex_spblock_st { public: Lex_spblock() { init(); } Lex_spblock(const Lex_spblock_handlers_st &other) { vars= conds= curs= 0; hndlrs= other.hndlrs; } }; struct Lex_for_loop_bounds_st { public: class sp_assignment_lex *m_index; // The first iteration value (or cursor) class sp_assignment_lex *m_target_bound; // The last iteration value int8 m_direction; bool m_implicit_cursor; bool is_for_loop_cursor() const { return m_target_bound == NULL; } }; class Lex_for_loop_bounds_intrange: public Lex_for_loop_bounds_st { public: Lex_for_loop_bounds_intrange(int8 direction, class sp_assignment_lex *left_expr, class sp_assignment_lex *right_expr) { m_direction= direction; m_index= direction > 0 ? left_expr : right_expr; m_target_bound= direction > 0 ? right_expr : left_expr; m_implicit_cursor= false; } }; struct Lex_for_loop_st { public: class sp_variable *m_index; // The first iteration value (or cursor) class sp_variable *m_target_bound; // The last iteration value int m_cursor_offset; int8 m_direction; bool m_implicit_cursor; void init() { m_index= 0; m_target_bound= 0; m_cursor_offset= 0; m_direction= 0; m_implicit_cursor= false; } bool is_for_loop_cursor() const { return m_target_bound == NULL; } bool is_for_loop_explicit_cursor() const { return is_for_loop_cursor() && !m_implicit_cursor; } }; enum trim_spec { TRIM_LEADING, TRIM_TRAILING, TRIM_BOTH }; struct Lex_trim_st { Item *m_remove; Item *m_source; trim_spec m_spec; public: void set(trim_spec spec, Item *remove, Item *source) { m_spec= spec; m_remove= remove; m_source= source; } void set(trim_spec spec, Item *source) { set(spec, NULL, source); } Item *make_item_func_trim_std(THD *thd) const; Item *make_item_func_trim_oracle(THD *thd) const; }; class Lex_trim: public Lex_trim_st { public: Lex_trim(trim_spec spec, Item *source) { set(spec, source); } }; class Lex_substring_spec_st { public: Item *m_subject; Item *m_from; Item *m_for; static Lex_substring_spec_st init(Item *subject, Item *from, Item *xfor= NULL) { Lex_substring_spec_st res; res.m_subject= subject; res.m_from= from; res.m_for= xfor; return res; } }; class st_select_lex; class Lex_select_lock { public: struct { uint defined_lock:1; uint update_lock:1; uint defined_timeout:1; uint skip_locked:1; }; ulong timeout; void empty() { defined_lock= update_lock= defined_timeout= skip_locked= FALSE; timeout= 0; } void set_to(st_select_lex *sel); }; class Lex_select_limit { public: /* explicit LIMIT clause was used */ bool explicit_limit; bool with_ties; Item *select_limit, *offset_limit; void clear() { explicit_limit= FALSE; // No explicit limit given by user with_ties= FALSE; // No use of WITH TIES operator select_limit= NULL; // denotes the default limit = HA_POS_ERROR offset_limit= NULL; // denotes the default offset = 0 } }; struct st_order; class Load_data_param { protected: CHARSET_INFO *m_charset; // Character set of the file ulonglong m_fixed_length; // Sum of target field lengths for fixed format bool m_is_fixed_length; bool m_use_blobs; public: Load_data_param(CHARSET_INFO *cs, bool is_fixed_length): m_charset(cs), m_fixed_length(0), m_is_fixed_length(is_fixed_length), m_use_blobs(false) { } bool add_outvar_field(THD *thd, const Field *field); bool add_outvar_user_var(THD *thd); CHARSET_INFO *charset() const { return m_charset; } bool is_fixed_length() const { return m_is_fixed_length; } bool use_blobs() const { return m_use_blobs; } }; class Load_data_outvar { public: virtual ~Load_data_outvar() = default; virtual bool load_data_set_null(THD *thd, const Load_data_param *param)= 0; virtual bool load_data_set_value(THD *thd, const char *pos, uint length, const Load_data_param *param)= 0; virtual bool load_data_set_no_data(THD *thd, const Load_data_param *param)= 0; virtual void load_data_print_for_log_event(THD *thd, class String *to) const= 0; virtual bool load_data_add_outvar(THD *thd, Load_data_param *param) const= 0; virtual uint load_data_fixed_length() const= 0; }; class Timeval: public timeval { protected: Timeval() = default; public: Timeval(my_time_t sec, ulong usec) { tv_sec= sec; /* Since tv_usec is not always of type ulong, cast usec parameter explicitly to uint to avoid compiler warnings about losing integer precision. */ DBUG_ASSERT(usec < 1000000); tv_usec= (uint)usec; } explicit Timeval(const timeval &tv) :timeval(tv) { } }; /* A value that's either a Timeval or SQL NULL */ class Timeval_null: protected Timeval { bool m_is_null; public: Timeval_null() :Timeval(0, 0), m_is_null(true) { } Timeval_null(const my_time_t sec, ulong usec) :Timeval(sec, usec), m_is_null(false) { } const Timeval & to_timeval() const { DBUG_ASSERT(!m_is_null); return *this; } bool is_null() const { return m_is_null; } }; /* A run-time address of an SP variable. Consists of: - The rcontext type (LOCAL, PACKAGE BODY), controlled by m_rcontext_handler - The frame offset */ class sp_rcontext_addr { public: sp_rcontext_addr(const class Sp_rcontext_handler *h, uint offset) :m_rcontext_handler(h), m_offset(offset) { } const Sp_rcontext_handler *rcontext_handler() const { return m_rcontext_handler; } uint offset() const { return m_offset; } protected: const class Sp_rcontext_handler *m_rcontext_handler; uint m_offset; ///< Frame offset }; #endif /* STRUCTS_INCLUDED */ init.h 0000644 00000001524 15156036143 0005666 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef INIT_INCLUDED #define INIT_INCLUDED void unireg_init(ulong options); #endif /* INIT_INCLUDED */ sql_get_diagnostics.h 0000644 00000017313 15156036143 0010753 0 ustar 00 /* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_GET_DIAGNOSTICS_H #define SQL_GET_DIAGNOSTICS_H /** Diagnostics information forward reference. */ class Diagnostics_information; /** Sql_cmd_get_diagnostics represents a GET DIAGNOSTICS statement. The GET DIAGNOSTICS statement retrieves exception or completion condition information from a diagnostics area, usually pertaining to the last non-diagnostic SQL statement that was executed. */ class Sql_cmd_get_diagnostics : public Sql_cmd { public: /** Constructor, used to represent a GET DIAGNOSTICS statement. @param info Diagnostics information to be obtained. */ Sql_cmd_get_diagnostics(Diagnostics_information *info) : m_info(info) {} enum_sql_command sql_command_code() const override { return SQLCOM_GET_DIAGNOSTICS; } bool execute(THD *thd) override; private: /** The information to be obtained. */ Diagnostics_information *m_info; }; /** Represents the diagnostics information to be obtained. Diagnostic information is made available through statement information and condition information items. */ class Diagnostics_information : public Sql_alloc { public: /** Which diagnostics area to access. Only CURRENT is supported for now. */ enum Which_area { /** Access the first diagnostics area. */ CURRENT_AREA }; /** Set which diagnostics area to access. */ void set_which_da(Which_area area) { m_area= area; } /** Get which diagnostics area to access. */ Which_area get_which_da(void) const { return m_area; } /** Aggregate diagnostics information. @param thd The current thread. @param da The diagnostics area. @retval false on success. @retval true on error */ virtual bool aggregate(THD *thd, const Diagnostics_area *da) = 0; protected: /** Diagnostics_information objects are allocated in thd->mem_root. Do not rely on the destructor for any cleanup. */ virtual ~Diagnostics_information() { DBUG_ASSERT(false); } /** Evaluate a diagnostics information item in a specific context. @param thd The current thread. @param diag_item The diagnostics information item. @param ctx The context to evaluate the item. @retval false on success. @retval true on error. */ template <typename Diag_item, typename Context> bool evaluate(THD *thd, Diag_item *diag_item, Context ctx) { Item *value; /* Get this item's value. */ if (! (value= diag_item->get_value(thd, ctx))) return true; /* Set variable/parameter value. */ return diag_item->set_value(thd, &value); } private: /** Which diagnostics area to access. */ Which_area m_area; }; /** A diagnostics information item. Used to associate a specific diagnostics information item to a target variable. */ class Diagnostics_information_item : public Sql_alloc { public: /** Set a value for this item. @param thd The current thread. @param value The obtained value. @retval false on success. @retval true on error. */ bool set_value(THD *thd, Item **value); protected: /** Constructor, used to represent a diagnostics information item. @param target A target that gets the value of this item. */ Diagnostics_information_item(Item *target) : m_target(target) {} /** Diagnostics_information_item objects are allocated in thd->mem_root. Do not rely on the destructor for any cleanup. */ virtual ~Diagnostics_information_item() { DBUG_ASSERT(false); } private: /** The target variable that will receive the value of this item. */ Item *m_target; }; /** A statement information item. */ class Statement_information_item : public Diagnostics_information_item { public: /** The name of a statement information item. */ enum Name { NUMBER, ROW_COUNT }; /** Constructor, used to represent a statement information item. @param name The name of this item. @param target A target that gets the value of this item. */ Statement_information_item(Name name, Item *target) : Diagnostics_information_item(target), m_name(name) {} /** Obtain value of this statement information item. */ Item *get_value(THD *thd, const Diagnostics_area *da); private: /** The name of this statement information item. */ Name m_name; }; /** Statement information. @remark Provides information about the execution of a statement. */ class Statement_information : public Diagnostics_information { public: /** Constructor, used to represent the statement information of a GET DIAGNOSTICS statement. @param items List of requested statement information items. */ Statement_information(List<Statement_information_item> *items) : m_items(items) {} /** Obtain statement information in the context of a diagnostics area. */ bool aggregate(THD *thd, const Diagnostics_area *da) override; private: /* List of statement information items. */ List<Statement_information_item> *m_items; }; /** A condition information item. */ class Condition_information_item : public Diagnostics_information_item { public: /** The name of a condition information item. */ enum Name { CLASS_ORIGIN, SUBCLASS_ORIGIN, CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, COLUMN_NAME, CURSOR_NAME, MESSAGE_TEXT, MYSQL_ERRNO, RETURNED_SQLSTATE, ROW_NUMBER }; /** Constructor, used to represent a condition information item. @param name The name of this item. @param target A target that gets the value of this item. */ Condition_information_item(Name name, Item *target) : Diagnostics_information_item(target), m_name(name) {} /** Obtain value of this condition information item. */ Item *get_value(THD *thd, const Sql_condition *cond); private: /** The name of this condition information item. */ Name m_name; /** Create an string item to represent a condition item string. */ Item *make_utf8_string_item(THD *thd, const String *str); }; /** Condition information. @remark Provides information about conditions raised during the execution of a statement. */ class Condition_information : public Diagnostics_information { public: /** Constructor, used to represent the condition information of a GET DIAGNOSTICS statement. @param cond_number_expr Number that identifies the diagnostic condition. @param items List of requested condition information items. */ Condition_information(Item *cond_number_expr, List<Condition_information_item> *items) : m_cond_number_expr(cond_number_expr), m_items(items) {} /** Obtain condition information in the context of a diagnostics area. */ bool aggregate(THD *thd, const Diagnostics_area *da) override; private: /** Number that identifies the diagnostic condition for which information is to be obtained. */ Item *m_cond_number_expr; /** List of condition information items. */ List<Condition_information_item> *m_items; }; #endif sql_bitmap.h 0000644 00000017602 15156036143 0007062 0 ustar 00 /* Copyright (c) 2003, 2013, Oracle and/or its affiliates Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Implementation of a bitmap type. The idea with this is to be able to handle any constant number of bits but also be able to use 32 or 64 bits bitmaps very efficiently */ #ifndef SQL_BITMAP_INCLUDED #define SQL_BITMAP_INCLUDED #include <my_sys.h> #include <my_bitmap.h> #include <my_bit.h> /* An iterator to quickly walk over bits in ulonglong bitmap. */ class Table_map_iterator { ulonglong bmp; public: Table_map_iterator(ulonglong t): bmp(t){} uint next_bit() { if (!bmp) return BITMAP_END; uint bit= my_find_first_bit(bmp); bmp &= ~(1ULL << bit); return bit; } int operator++(int) { return next_bit(); } enum { BITMAP_END= 64 }; }; template <uint width> class Bitmap { /* Workaround GCC optimizer bug (generating SSE instuctions on unaligned data) */ #if defined (__GNUC__) && defined(__x86_64__) && (__GNUC__ < 6) && !defined(__clang__) #define NEED_GCC_NO_SSE_WORKAROUND #endif #ifdef NEED_GCC_NO_SSE_WORKAROUND #pragma GCC push_options #pragma GCC target ("no-sse") #endif private: static const int BITS_PER_ELEMENT= sizeof(ulonglong) * 8; static const int ARRAY_ELEMENTS= (width + BITS_PER_ELEMENT - 1) / BITS_PER_ELEMENT; static const ulonglong ALL_BITS_SET= ULLONG_MAX; ulonglong buffer[ARRAY_ELEMENTS]; uint bit_index(uint n) const { DBUG_ASSERT(n < width); return ARRAY_ELEMENTS == 1 ? 0 : n / BITS_PER_ELEMENT; } ulonglong bit_mask(uint n) const { DBUG_ASSERT(n < width); return ARRAY_ELEMENTS == 1 ? 1ULL << n : 1ULL << (n % BITS_PER_ELEMENT); } ulonglong last_element_mask(int n) const { DBUG_ASSERT(n % BITS_PER_ELEMENT != 0); return bit_mask(n) - 1; } public: /* The default constructor does nothing. The caller is supposed to either zero the memory or to call set_all()/clear_all()/set_prefix() to initialize bitmap. */ Bitmap() = default; explicit Bitmap(uint prefix) { set_prefix(prefix); } void init(uint prefix) { set_prefix(prefix); } uint length() const { return width; } void set_bit(uint n) { buffer[bit_index(n)] |= bit_mask(n); } void clear_bit(uint n) { buffer[bit_index(n)] &= ~bit_mask(n); } bool is_set(uint n) const { return buffer[bit_index(n)] & bit_mask(n); } void set_prefix(uint prefix_size) { set_if_smaller(prefix_size, width); size_t idx= prefix_size / BITS_PER_ELEMENT; for (size_t i= 0; i < idx; i++) buffer[i]= ALL_BITS_SET; if (prefix_size % BITS_PER_ELEMENT) buffer[idx++]= last_element_mask(prefix_size); for (size_t i= idx; i < ARRAY_ELEMENTS; i++) buffer[i]= 0; } bool is_prefix(uint prefix_size) const { DBUG_ASSERT(prefix_size <= width); size_t idx= prefix_size / BITS_PER_ELEMENT; for (size_t i= 0; i < idx; i++) if (buffer[i] != ALL_BITS_SET) return false; if (prefix_size % BITS_PER_ELEMENT) if (buffer[idx++] != last_element_mask(prefix_size)) return false; for (size_t i= idx; i < ARRAY_ELEMENTS; i++) if (buffer[i] != 0) return false; return true; } void set_all() { if (width % BITS_PER_ELEMENT) set_prefix(width); else if (ARRAY_ELEMENTS > 1) memset(buffer, 0xff, sizeof(buffer)); else buffer[0] = ALL_BITS_SET; } void clear_all() { if (ARRAY_ELEMENTS > 1) memset(buffer, 0, sizeof(buffer)); else buffer[0]= 0; } void intersect(const Bitmap& map2) { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) buffer[i] &= map2.buffer[i]; } private: /* Intersect with a bitmap represented as longlong. In addition, pad the rest of the bitmap with 0 or 1 bits depending on pad_with_ones parameter. */ void intersect_and_pad(ulonglong map2buff, bool pad_with_ones) { buffer[0] &= map2buff; for (size_t i= 1; i < ARRAY_ELEMENTS; i++) buffer[i]= pad_with_ones ? ALL_BITS_SET : 0; if (ARRAY_ELEMENTS > 1 && (width % BITS_PER_ELEMENT) && pad_with_ones) buffer[ARRAY_ELEMENTS - 1]= last_element_mask(width); } public: void intersect(ulonglong map2buff) { intersect_and_pad(map2buff, 0); } /* Use highest bit for all bits above first element. */ void intersect_extended(ulonglong map2buff) { intersect_and_pad(map2buff, (map2buff & (1ULL << 63))); } void subtract(const Bitmap& map2) { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) buffer[i] &= ~(map2.buffer[i]); } void merge(const Bitmap& map2) { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) buffer[i] |= map2.buffer[i]; } bool is_clear_all() const { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) if (buffer[i]) return false; return true; } bool is_subset(const Bitmap& map2) const { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) if (buffer[i] & ~(map2.buffer[i])) return false; return true; } bool is_overlapping(const Bitmap& map2) const { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) if (buffer[i] & map2.buffer[i]) return true; return false; } bool operator==(const Bitmap& map2) const { if (ARRAY_ELEMENTS > 1) return !memcmp(buffer,map2.buffer,sizeof(buffer)); return buffer[0] == map2.buffer[0]; } bool operator!=(const Bitmap& map2) const { return !(*this == map2); } /* Print hexadecimal representation of bitmap. Truncate trailing zeros. */ char *print(char *buf) const { size_t last; /*index of the last non-zero element, or 0. */ for (last= ARRAY_ELEMENTS - 1; last && !buffer[last]; last--){} const int HEX_DIGITS_PER_ELEMENT= BITS_PER_ELEMENT / 4; for (size_t i= 0; i < last; i++) { ulonglong num = buffer[i]; uint shift = BITS_PER_ELEMENT - 4; size_t pos= i * HEX_DIGITS_PER_ELEMENT; for (size_t j= 0; j < HEX_DIGITS_PER_ELEMENT; j++) { buf[pos + j]= _dig_vec_upper[(num >> shift) & 0xf]; shift += 4; } } longlong2str(buffer[last], buf, 16); return buf; } ulonglong to_ulonglong() const { return buffer[0]; } uint bits_set() const { uint res= 0; for (size_t i= 0; i < ARRAY_ELEMENTS; i++) if (buffer[i]) res+= my_count_bits(buffer[i]); return res; } uint find_first_bit() const { for (size_t i= 0; i < ARRAY_ELEMENTS; i++) if (buffer[i]) return (uint)i*BITS_PER_ELEMENT + my_find_first_bit(buffer[i]); return width; } class Iterator { const Bitmap& map; uint offset; Table_map_iterator tmi; public: Iterator(const Bitmap<width>& map2) : map(map2), offset(0), tmi(map2.buffer[0]) {} int operator++(int) { for (;;) { int nextbit= tmi++; if (nextbit != Table_map_iterator::BITMAP_END) return offset + nextbit; if (offset + BITS_PER_ELEMENT >= map.length()) return BITMAP_END; offset += BITS_PER_ELEMENT; tmi= Table_map_iterator(map.buffer[offset / BITS_PER_ELEMENT]); } } enum { BITMAP_END = width }; }; #ifdef NEED_GCC_NO_SSE_WORKAROUND #pragma GCC pop_options #undef NEED_GCC_NO_SSE_WORKAROUND #endif }; typedef Bitmap<MAX_INDEXES> key_map; /* Used for finding keys */ #endif /* SQL_BITMAP_INCLUDED */ mysqld_default_groups.h 0000644 00000000314 15156036143 0011333 0 ustar 00 const char *load_default_groups[]= { "mysqld", "server", MYSQL_BASE_VERSION, "mariadb", MARIADB_BASE_VERSION, "mariadbd", MARIADBD_BASE_VERSION, "client-server", #ifdef WITH_WSREP "galera", #endif 0, 0}; select_handler.h 0000644 00000006533 15156036144 0007705 0 ustar 00 /* Copyright (c) 2018, 2019 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SELECT_HANDLER_INCLUDED #define SELECT_HANDLER_INCLUDED #include "mariadb.h" #include "sql_priv.h" enum class select_pushdown_type { SINGLE_SELECT, PART_OF_UNIT, WHOLE_UNIT }; /** @class select_handler This interface class is to be used for execution of select queries by foreign engines */ class select_handler { public: // Constructor for a single SELECT_LEX (not a part of a unit) select_handler(THD *thd_arg, handlerton *ht_arg, SELECT_LEX *sel_lex); // Constructor for a unit (UNION/EXCEPT/INTERSECT) select_handler(THD *thd_arg, handlerton *ht_arg, SELECT_LEX_UNIT *sel_unit); /* Constructor for a SELECT_LEX which is a part of a unit (partial pushdown). Both SELECT_LEX and SELECT_LEX_UNIT are passed */ select_handler(THD *thd_arg, handlerton *ht_arg, SELECT_LEX *sel_lex, SELECT_LEX_UNIT *sel_unit); virtual ~select_handler(); int execute(); virtual bool prepare(); /* Select_handler processes these cases: - single SELECT - whole unit (multiple SELECTs combined with UNION/EXCEPT/INTERSECT) - single SELECT that is part of a unit (partial pushdown) In the case of single SELECT select_lex is initialized and lex_unit==NULL, in the case of whole UNIT select_lex == NULL and lex_unit is initialized, in the case of partial pushdown both select_lex and lex_unit are initialized */ SELECT_LEX *select_lex; // Single select/part of a unit to be executed SELECT_LEX_UNIT *lex_unit; // Unit to be executed /* Temporary table where all results should be stored in record[0] The table has a field for every item from the select_lex::item_list. The table is actually never filled. Only its record buffer is used. */ TABLE *table; protected: /* Functions to scan the select result set. All these returns 0 if ok, error code in case of error. */ /* Initialize the process of producing rows of result set */ virtual int init_scan() = 0; /* Put the next produced row of the result set in table->record[0] and return 0. Return HA_ERR_END_OF_FILE if there are no more rows, return other error number in case of fatal error. */ virtual int next_row() = 0; /* Finish scanning */ virtual int end_scan() = 0; /* Report errors */ virtual void print_error(int error, myf errflag); bool send_result_set_metadata(); bool send_data(); bool send_eof(); TABLE *create_tmp_table(THD *thd); select_pushdown_type get_pushdown_type(); THD *thd; handlerton *ht; select_result *result; // Object receiving the retrieved data List<Item> result_columns; bool is_analyze; }; #endif /* SELECT_HANDLER_INCLUDED */ sql_analyse.h 0000644 00000025565 15156036144 0007252 0 ustar 00 #ifndef SQL_ANALYSE_INCLUDED #define SQL_ANALYSE_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Analyse database */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "procedure.h" /* Procedure */ #define my_thd_charset default_charset_info #define DEC_IN_AVG 4 typedef struct st_number_info { // if zerofill is true, the number must be zerofill, or string bool negative, is_float, zerofill, maybe_zerofill; int8 integers; int8 decimals; double dval; ulonglong ullval; } NUM_INFO; typedef struct st_extreme_value_number_info { ulonglong ullval; longlong llval; double max_dval, min_dval; } EV_NUM_INFO; typedef struct st_tree_info { bool found; String *str; Item *item; } TREE_INFO; uint check_ulonglong(const char *str, uint length); bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num); bool test_if_number(NUM_INFO *info, const char *str, uint str_len); int compare_double(const double *s, const double *t); int compare_double2(void *, const void *s, const void *t); int compare_longlong(const longlong *s, const longlong *t); int compare_longlong2(void *, const void *s, const void *t); int compare_ulonglong(const ulonglong *s, const ulonglong *t); int compare_ulonglong2(void *, const void *s, const void *t); int compare_decimal2(void *len, const void *s, const void *t); Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result, List<Item> &field_list); int free_string(void* str, TREE_FREE, void*); class analyse; class field_info :public Sql_alloc { protected: ulong treemem, tree_elements, empty, nulls, min_length, max_length; uint room_in_tree; bool found; TREE tree; Item *item; analyse *pc; public: field_info(Item* a, analyse* b) : treemem(0), tree_elements(0), empty(0), nulls(0), min_length(0), max_length(0), room_in_tree(1), found(0),item(a), pc(b) {}; virtual ~field_info() { delete_tree(&tree, 0); } virtual void add() = 0; virtual void get_opt_type(String*, ha_rows) = 0; virtual String *get_min_arg(String *) = 0; virtual String *get_max_arg(String *) = 0; virtual String *avg(String*, ha_rows) = 0; virtual String *std(String*, ha_rows) = 0; virtual tree_walk_action collect_enum() = 0; virtual uint decimals() { return 0; } friend class analyse; }; int collect_string(void *element, element_count count, void *info); int sortcmp2(void *, const void *a, const void *b); class field_str :public field_info { String min_arg, max_arg; ulonglong sum; bool must_be_blob, was_zero_fill, was_maybe_zerofill, can_be_still_num; NUM_INFO num_info; EV_NUM_INFO ev_num_info; public: field_str(Item* a, analyse* b) :field_info(a,b), min_arg("",0,default_charset_info), max_arg("",0,default_charset_info), sum(0), must_be_blob(0), was_zero_fill(0), was_maybe_zerofill(0), can_be_still_num(1) { init_tree(&tree, 0, 0, sizeof(String), sortcmp2, free_string, NULL, MYF(MY_THREAD_SPECIFIC)); }; void add() override; void get_opt_type(String*, ha_rows) override; String *get_min_arg(String *not_used __attribute__((unused))) override { return &min_arg; } String *get_max_arg(String *not_used __attribute__((unused))) override { return &max_arg; } String *avg(String *s, ha_rows rows) override { if (!(rows - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)), DEC_IN_AVG,my_thd_charset); return s; } friend int collect_string(String *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() override { return collect_string; } String *std(String *s __attribute__((unused)), ha_rows rows __attribute__((unused))) override { return (String*) 0; } }; int collect_decimal(void *element, element_count count, void *info); class field_decimal :public field_info { my_decimal min_arg, max_arg; my_decimal sum[2], sum_sqr[2]; int cur_sum; int bin_size; public: field_decimal(Item* a, analyse* b) :field_info(a,b) { bin_size= my_decimal_get_binary_size(a->max_length, a->decimals); init_tree(&tree, 0, 0, bin_size, compare_decimal2, 0, (void *) &bin_size, MYF(MY_THREAD_SPECIFIC)); }; void add() override; void get_opt_type(String*, ha_rows) override; String *get_min_arg(String *) override; String *get_max_arg(String *) override; String *avg(String *s, ha_rows rows) override; friend int collect_decimal(uchar *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() override { return collect_decimal; } String *std(String *s, ha_rows rows) override; }; int collect_real(void *element, element_count count, void *info); class field_real: public field_info { double min_arg, max_arg; double sum, sum_sqr; uint max_notzero_dec_len; public: field_real(Item* a, analyse* b) :field_info(a,b), min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0) { init_tree(&tree, 0, 0, sizeof(double), compare_double2, NULL, NULL, MYF(MY_THREAD_SPECIFIC)); } void add() override; void get_opt_type(String*, ha_rows) override; String *get_min_arg(String *s) override { s->set_real(min_arg, item->decimals, my_thd_charset); return s; } String *get_max_arg(String *s) override { s->set_real(max_arg, item->decimals, my_thd_charset); return s; } String *avg(String *s, ha_rows rows) override { if (!(rows - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else s->set_real(((double)sum / (double) (rows - nulls)), item->decimals,my_thd_charset); return s; } String *std(String *s, ha_rows rows) override { double tmp = ulonglong2double(rows); if (!(tmp - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else { double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) / (tmp - nulls)); s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals,my_thd_charset); } return s; } uint decimals() override { return item->decimals; } friend int collect_real(double *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() override { return collect_real;} }; int collect_longlong(void *element, element_count count, void *info); class field_longlong: public field_info { longlong min_arg, max_arg; longlong sum, sum_sqr; public: field_longlong(Item* a, analyse* b) :field_info(a,b), min_arg(0), max_arg(0), sum(0), sum_sqr(0) { init_tree(&tree, 0, 0, sizeof(longlong), compare_longlong2, NULL, NULL, MYF(MY_THREAD_SPECIFIC)); } void add() override; void get_opt_type(String*, ha_rows) override; String *get_min_arg(String *s) override { s->set(min_arg,my_thd_charset); return s; } String *get_max_arg(String *s) override { s->set(max_arg,my_thd_charset); return s; } String *avg(String *s, ha_rows rows) override { if (!(rows - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else s->set_real(((double) sum / (double) (rows - nulls)), DEC_IN_AVG,my_thd_charset); return s; } String *std(String *s, ha_rows rows) override { double tmp = ulonglong2double(rows); if (!(tmp - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else { double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) / (tmp - nulls)); s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset); } return s; } friend int collect_longlong(longlong *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() override { return collect_longlong;} }; int collect_ulonglong(void *element, element_count count, void *info); class field_ulonglong: public field_info { ulonglong min_arg, max_arg; ulonglong sum, sum_sqr; public: field_ulonglong(Item* a, analyse * b) :field_info(a,b), min_arg(0), max_arg(0), sum(0),sum_sqr(0) { init_tree(&tree, 0, 0, sizeof(ulonglong), compare_ulonglong2, NULL, NULL, MYF(MY_THREAD_SPECIFIC)); } void add() override; void get_opt_type(String*, ha_rows) override; String *get_min_arg(String *s) override { s->set(min_arg,my_thd_charset); return s; } String *get_max_arg(String *s) override { s->set(max_arg,my_thd_charset); return s; } String *avg(String *s, ha_rows rows) override { if (!(rows - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)), DEC_IN_AVG,my_thd_charset); return s; } String *std(String *s, ha_rows rows) override { double tmp = ulonglong2double(rows); if (!(tmp - nulls)) s->set_real((double) 0.0, 1,my_thd_charset); else { double tmp2 = ((ulonglong2double(sum_sqr) - ulonglong2double(sum * sum) / (tmp - nulls)) / (tmp - nulls)); s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset); } return s; } friend int collect_ulonglong(ulonglong *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() override { return collect_ulonglong; } }; Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result, List<Item> &field_list); class analyse: public Procedure { protected: Item_proc *func_items[10]; List<Item> fields, result_fields; field_info **f_info, **f_end; ha_rows rows; uint output_str_length; public: uint max_tree_elements, max_treemem; analyse(select_result *res) :Procedure(res, PROC_NO_SORT), f_info(0), rows(0), output_str_length(0) {} ~analyse() { if (f_info) { for (field_info **f=f_info; f != f_end; f++) delete (*f); } } void add() override {} bool change_columns(THD *thd, List<Item> &fields) override; int send_row(List<Item> &field_list) override; void end_group(void) override {} int end_of_records(void) override; friend Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result, List<Item> &field_list); }; #endif /* SQL_ANALYSE_INCLUDED */ wsrep_sst.h 0000644 00000007557 15156036144 0006771 0 ustar 00 /* Copyright (C) 2013-2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_SST_H #define WSREP_SST_H #include <my_config.h> #include "wsrep/gtid.hpp" #include <my_global.h> #include <string> #define WSREP_SST_OPT_ROLE "--role" #define WSREP_SST_OPT_ADDR "--address" #define WSREP_SST_OPT_AUTH "--auth" #define WSREP_SST_OPT_DATA "--datadir" #define WSREP_SST_OPT_CONF "--defaults-file" #define WSREP_SST_OPT_CONF_SUFFIX "--defaults-group-suffix" #define WSREP_SST_OPT_CONF_EXTRA "--defaults-extra-file" #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" #define WSREP_SST_OPT_BINLOG_INDEX "--binlog-index" #define WSREP_SST_OPT_PROGRESS "--progress" #define WSREP_SST_OPT_MYSQLD "--mysqld-args" // mysqldump-specific options #define WSREP_SST_OPT_USER "--user" #define WSREP_SST_OPT_PSWD "--password" #define WSREP_SST_OPT_HOST "--host" #define WSREP_SST_OPT_PORT "--port" #define WSREP_SST_OPT_LPORT "--local-port" // donor-specific #define WSREP_SST_OPT_SOCKET "--socket" #define WSREP_SST_OPT_GTID "--gtid" #define WSREP_SST_OPT_BYPASS "--bypass" #define WSREP_SST_OPT_GTID_DOMAIN_ID "--gtid-domain-id" #define WSREP_SST_MYSQLDUMP "mysqldump" #define WSREP_SST_RSYNC "rsync" #define WSREP_SST_SKIP "skip" #define WSREP_SST_MARIABACKUP "mariabackup" #define WSREP_SST_XTRABACKUP "xtrabackup" #define WSREP_SST_XTRABACKUPV2 "xtrabackupv2" #define WSREP_SST_DEFAULT WSREP_SST_RSYNC #define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_SST_AUTH_MASK "********" /* system variables */ extern const char* wsrep_sst_method; extern const char* wsrep_sst_receive_address; extern const char* wsrep_sst_donor; extern const char* wsrep_sst_auth; extern my_bool wsrep_sst_donor_rejects_queries; /*! Synchronizes applier thread start with init thread */ extern void wsrep_sst_grab(); /*! Init thread waits for SST completion */ extern bool wsrep_sst_wait(); /*! Signals wsrep that initialization is complete, writesets can be applied */ extern bool wsrep_sst_continue(); extern void wsrep_sst_auth_init(); extern void wsrep_sst_auth_free(); extern void wsrep_SE_init_grab(); /*! grab init critical section */ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ /** Return a string containing the state transfer request string. Note that the string may contain a '\0' in the middle. */ std::string wsrep_sst_prepare(); /** Donate a SST. @param request SST request string received from the joiner. Note that the string may contain a '\0' in the middle. @param gtid Current position of the donor @param bypass If true, full SST is not needed. Joiner needs to be notified that it can continue starting from gtid. */ int wsrep_sst_donate(const std::string& request, const wsrep::gtid& gtid, bool bypass); #else #define wsrep_SE_initialized() do { } while(0) #define wsrep_SE_init_grab() do { } while(0) #define wsrep_SE_init_done() do { } while(0) #define wsrep_sst_continue() (0) #endif /* WSREP_SST_H */ rowid_filter.h 0000644 00000040026 15156036144 0007415 0 ustar 00 /* Copyright (c) 2018, 2019 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ROWID_FILTER_INCLUDED #define ROWID_FILTER_INCLUDED #include "mariadb.h" #include "sql_array.h" /* What rowid / primary filters are -------------------------------- Consider a join query Q of the form SELECT * FROM T1, ... , Tk WHERE P. For any of the table reference Ti(Q) from the from clause of Q different rowid / primary key filters (pk-filters for short) can be built. A pk-filter F built for Ti(Q) is a set of rowids / primary keys of Ti F= {pk1,...,pkN} such that for any row r=r1||...||rk from the result set of Q ri's rowid / primary key pk(ri) is contained in F. When pk-filters are useful -------------------------- If building a pk-filter F for Ti(Q )is not too costly and its cardinality #F is much less than the cardinality of T - #T then using the pk-filter when executing Q might be quite beneficial. Let r be a random row from Ti. Let s(F) be the probability that pk(r) belongs to F. Let BC(F) be the cost of building F. Suppose that the optimizer has chosen for Q a plan with this join order T1 => ... Tk and that the table Ti is accessed by a ref access using index I. Let K = {k1,...,kM} be the set of all rowid/primary keys values used to access rows of Ti when looking for matches in this table.to join Ti by index I. Let's assume that two set sets K and F are uncorrelated. With this assumption if before accessing data from Ti by the rowid / primary key k we first check whether k is in F then we can expect saving on M*(1-s(S)) accesses of data rows from Ti. If we can guarantee that test whether k is in F is relatively cheap then we can gain a lot assuming that BC(F) is much less then the cost of fetching M*(1-s(S)) records from Ti and following evaluation of conditions pushed into Ti. Making pk-filter test cheap --------------------------- If the search structure to test whether an element is in F can be fully placed in RAM then this test is expected to be much cheaper than a random access of a record from Ti. We'll consider two search structures for pk-filters: ordered array and bloom filter. Ordered array is easy to implement, but it's space consuming. If a filter contains primary keys then at least space for each primary key from the filter must be allocated in the search structure. On a the opposite a bloom filter requires a fixed number of bits and this number does not depend on the cardinality of the pk-filter (10 bits per element will serve pk-filter of any size). */ /* How and when the optimizer builds and uses range rowid filters -------------------------------------------------------------- 1. In make_join_statistics() for each join table s after the call of get_quick_record_count() the TABLE::method init_cost_info_for_usable_range_rowid_filters() is called The method build an array of Range_rowid_filter_cost_info elements containing the cost info on possible range filters for s->table. The array is optimized for further usage. 2. For each partial join order when the optimizer considers joining table s to this partial join In the function best_access_path() a. When evaluating a ref access r by index idx to join s the optimizer estimates the effect of usage of each possible range filter f and chooses one with the best gain. The gain is taken into account when the cost of thr ref access r is calculated. If it turns out that this is the best ref access to join s then the info about the chosen filter together with the info on r is remembered in the corresponding element of the array of POSITION structures. [We evaluate every pair (ref access, range_filter) rather then every pair (best ref access, range filter) because if the index ref_idx used for ref access r correlates with the index rf_idx used by the filter f then the pair (r,f) is not evaluated at all as we don't know how to estimate the effect of correlation between ref_idx and rf_idx.] b. When evaluating the best range access to join table s the optimizer estimates the effect of usage of each possible range filter f and chooses one with the best gain. [Here we should have evaluated every pair (range access, range filter) as well, but it's not done yet.] 3. When the cheapest execution plan has been chosen and after the call of JOIN::get_best_combination() The method JOIN::make_range_rowid_filters() is called For each range rowid filter used in the chosen execution plan the method creates a quick select object to be able to perform index range scan to fill the filter at the execution stage. The method also creates Range_rowid_filter objects that are used at the execution stage. 4. Just before the execution stage The method JOIN::init_range_rowid_filters() is called. For each join table s that is to be accessed with usage of a range filter the method allocates containers for the range filter and it lets the engine know that the filter will be used when accessing s. 5. At the execution stage In the function sub_select() just before the first access of a join table s employing a range filter The method JOIN_TAB::build_range_rowid_filter() is called The method fills the filter using the quick select created by JOIN::make_range_rowid_filters(). 6. The accessed key tuples are checked against the filter within the engine using the info pushed into it. */ struct TABLE; class SQL_SELECT; class Rowid_filter_container; class Range_rowid_filter_cost_info; typedef enum { SORTED_ARRAY_CONTAINER, BLOOM_FILTER_CONTAINER // Not used yet } Rowid_filter_container_type; /** @class Rowid_filter_container The interface for different types of containers to store info on the set of rowids / primary keys that defines a pk-filter. There will be two implementations of this abstract class. - sorted array - bloom filter */ class Rowid_filter_container : public Sql_alloc { public: virtual Rowid_filter_container_type get_type() = 0; /* Allocate memory for the container */ virtual bool alloc() = 0; /* @brief Add info on a rowid / primary to the container @param ctxt The context info (opaque) @param elem The rowid / primary key to be added to the container @retval true if elem is successfully added */ virtual bool add(void *ctxt, char *elem) = 0; /* @brief Check whether a rowid / primary key is in container @param ctxt The context info (opaque) @param elem The rowid / primary key to be checked against the container @retval False if elem is definitely not in the container */ virtual bool check(void *ctxt, char *elem) = 0; /* True if the container does not contain any element */ bool is_empty() { return elements() == 0; } virtual uint elements() = 0; virtual void sort (int (*cmp) (void *ctxt, const void *el1, const void *el2), void *cmp_arg) = 0; virtual ~Rowid_filter_container() = default; }; /** @class Rowid_filter The interface for different types of pk-filters Currently we support only range pk filters. */ class Rowid_filter : public Sql_alloc { protected: /* The container to store info the set of elements in the filter */ Rowid_filter_container *container; Rowid_filter_tracker *tracker; public: enum build_return_code { SUCCESS, NON_FATAL_ERROR, FATAL_ERROR, }; Rowid_filter(Rowid_filter_container *container_arg) : container(container_arg) {} /* Build the filter : fill it with info on the set of elements placed there */ virtual build_return_code build() = 0; /* Check whether an element is in the filter. Returns false is the elements is definitely not in the filter. */ virtual bool check(char *elem) = 0; virtual ~Rowid_filter() = default; bool is_empty() { return container->is_empty(); } Rowid_filter_container *get_container() { return container; } void set_tracker(Rowid_filter_tracker *track_arg) { tracker= track_arg; } Rowid_filter_tracker *get_tracker() { return tracker; } }; /** @class Rowid_filter_container The implementation of the Rowid_interface used for pk-filters that are filled when performing range index scans. */ class Range_rowid_filter: public Rowid_filter { /* The table for which the rowid filter is built */ TABLE *table; /* The select to perform the range scan to fill the filter */ SQL_SELECT *select; /* The cost info on the filter (used for EXPLAIN/ANALYZE) */ Range_rowid_filter_cost_info *cost_info; public: Range_rowid_filter(TABLE *tab, Range_rowid_filter_cost_info *cost_arg, Rowid_filter_container *container_arg, SQL_SELECT *sel) : Rowid_filter(container_arg), table(tab), select(sel), cost_info(cost_arg) {} ~Range_rowid_filter(); build_return_code build() override; bool check(char *elem) override { if (container->is_empty()) return false; bool was_checked= container->check(table, elem); tracker->increment_checked_elements_count(was_checked); return was_checked; } SQL_SELECT *get_select() { return select; } }; /** @class Refpos_container_sorted_array The wrapper class over Dynamic_array<char> to facilitate operations over array of elements of the type char[N] where N is the same for all elements */ class Refpos_container_sorted_array : public Sql_alloc { /* Maximum number of elements in the array (Now is used only at the initialization of the dynamic array) */ uint max_elements; /* Number of bytes allocated for an element */ uint elem_size; /* The dynamic array over which the wrapper is built */ DYNAMIC_ARRAY array; DYNAMIC_ARRAY_APPEND append; public: Refpos_container_sorted_array(uint max_elems, uint elem_sz) :max_elements(max_elems), elem_size(elem_sz) { bzero(&array, sizeof(array)); } ~Refpos_container_sorted_array() { delete_dynamic(&array); } bool alloc() { /* This can never fail as things will be allocated on demand */ init_dynamic_array2(PSI_INSTRUMENT_MEM, &array, elem_size, 0, max_elements, 512, MYF(0)); init_append_dynamic(&append, &array); return 0; } bool add(const char *elem) { return append_dynamic(&append, elem); } inline uchar *get_pos(uint n) const { return dynamic_array_ptr(&array, n); } inline uint elements() const { return (uint) array.elements; } void sort(qsort_cmp2 cmp, void *cmp_arg) { my_qsort2(array.buffer, array.elements, elem_size, cmp, cmp_arg); } }; /** @class Rowid_filter_sorted_array The implementation of the Rowid_filter_container interface as a sorted array container of rowids / primary keys */ class Rowid_filter_sorted_array: public Rowid_filter_container { /* The dynamic array to store rowids / primary keys */ Refpos_container_sorted_array refpos_container; public: Rowid_filter_sorted_array(uint elems, uint elem_size) : refpos_container(elems, elem_size) {} Rowid_filter_container_type get_type() override { return SORTED_ARRAY_CONTAINER; } bool alloc() override { return refpos_container.alloc(); } bool add(void *ctxt, char *elem) override { return refpos_container.add(elem); } bool check(void *ctxt, char *elem) override; uint elements() override { return refpos_container.elements(); } void sort (int (*cmp) (void *ctxt, const void *el1, const void *el2), void *cmp_arg) override { return refpos_container.sort(cmp, cmp_arg); } }; /** @class Range_rowid_filter_cost_info An objects of this class is created for each potentially usable range filter. It contains the info that allows to figure out whether usage of the range filter promises some gain. */ class Range_rowid_filter_cost_info final: public Sql_alloc { /* The table for which the range filter is to be built (if needed) */ TABLE *table; /* Estimated number of elements in the filter */ ulonglong est_elements; /* The index whose range scan would be used to build the range filter */ uint key_no; double cost_of_building_range_filter; double where_cost, base_lookup_cost, rowid_compare_cost; /* (gain*row_combinations)-cost_of_building_range_filter yields the gain of the filter for 'row_combinations' key tuples of the index key_no calculated with avg_access_and_eval_gain_per_row(container_type); */ double gain; /* The value of row_combinations where the gain is 0 */ double cross_x; /* Used for pruning of the potential range filters */ key_map abs_independent; /* These two parameters are used to choose the best range filter in the function TABLE::best_range_rowid_filter_for_partial_join */ double gain_adj; double cross_x_adj; public: /* The selectivity of the range filter */ double selectivity; /* The type of the container of the range filter */ Rowid_filter_container_type container_type; Range_rowid_filter_cost_info() : table(0), key_no(0) {} void init(Rowid_filter_container_type cont_type, TABLE *tab, uint key_no); double build_cost(Rowid_filter_container_type container_type); double lookup_cost(Rowid_filter_container_type cont_type); inline double lookup_cost() { return lookup_cost(container_type); } inline double avg_access_and_eval_gain_per_row(Rowid_filter_container_type cont_type, double cost_of_row_fetch); inline double avg_adjusted_gain_per_row(double access_cost_factor); inline void set_adjusted_gain_param(double access_cost_factor); /* Get the gain that usage of filter promises for r key tuples */ inline double get_gain(double row_combinations) { return row_combinations * gain - cost_of_building_range_filter; } /* Get the adjusted gain that usage of filter promises for r key tuples */ inline double get_adjusted_gain(double row_combinations) { return row_combinations * gain_adj - cost_of_building_range_filter; } /* The gain promised by usage of the filter for r key tuples due to less condition evaluations */ inline double get_cmp_gain(double row_combinations) { return (row_combinations * (1 - selectivity) * where_cost); } Rowid_filter_container *create_container(); double get_setup_cost() const { return cost_of_building_range_filter; } double get_lookup_cost(); double get_gain() const { return gain; } uint get_key_no() const { return key_no; } void trace_info(THD *thd); friend void TABLE::prune_range_rowid_filters(); friend void TABLE::init_cost_info_for_usable_range_rowid_filters(THD *thd); /* Best range row id filter for parital join */ friend Range_rowid_filter_cost_info * TABLE::best_range_rowid_filter(uint access_key_no, double records, double fetch_cost, double index_only_cost, double prev_records, double *records_out); Range_rowid_filter_cost_info * apply_filter(THD *thd, TABLE *table, ALL_READ_COST *cost, double *records_arg, double *startup_cost, uint ranges, double record_count); }; #endif /* ROWID_FILTER_INCLUDED */ pfs_idle_provider.h 0000644 00000002551 15156036144 0010424 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_IDLE_PROVIDER_H #define PFS_IDLE_PROVIDER_H /** @file include/pfs_idle_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_IDLE_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_IDLE_CALL(M) pfs_ ## M ## _v1 C_MODE_START PSI_idle_locker* pfs_start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_line); void pfs_end_idle_wait_v1(PSI_idle_locker* locker); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_IDLE_INTERFACE */ #endif thr_lock.h 0000644 00000016074 15156036144 0006537 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* For use with thr_lock:s */ #ifndef _thr_lock_h #define _thr_lock_h #ifdef __cplusplus extern "C" { #endif #include <my_pthread.h> #include <my_list.h> struct st_thr_lock; extern ulong locks_immediate,locks_waited ; /* Important: if a new lock type is added, a matching lock description must be added to sql_test.cc's lock_descriptions array. */ enum thr_lock_type { TL_IGNORE=-1, TL_UNLOCK, /* UNLOCK ANY LOCK */ /* Parser only! At open_tables() becomes TL_READ or TL_READ_NO_INSERT depending on the binary log format (SBR/RBR) and on the table category (log table). Used for tables that are read by statements which modify tables. */ TL_READ_DEFAULT, TL_READ, /* Read lock */ TL_READ_WITH_SHARED_LOCKS, /* High prior. than TL_WRITE. Allow concurrent insert */ TL_READ_HIGH_PRIORITY, /* READ, Don't allow concurrent insert */ TL_READ_NO_INSERT, /* READ, but skip locks if found */ TL_READ_SKIP_LOCKED, /* Write lock, but allow other threads to read / write. Used by BDB tables in MySQL to mark that someone is reading/writing to the table. */ TL_WRITE_ALLOW_WRITE, /* WRITE lock used by concurrent insert. Will allow READ, if one could use concurrent insert on table. */ TL_WRITE_CONCURRENT_INSERT, /* Write used by INSERT DELAYED. Allows READ locks */ TL_WRITE_DELAYED, /* parser only! Late bound low_priority flag. At open_tables() becomes thd->update_lock_default. */ TL_WRITE_DEFAULT, /* WRITE lock that has lower priority than TL_READ */ TL_WRITE_LOW_PRIORITY, /* WRITE, but skip locks if found */ TL_WRITE_SKIP_LOCKED, /* Normal WRITE lock */ TL_WRITE, /* Abort new lock request with an error */ TL_WRITE_ONLY}; /* TL_FIRST_WRITE is here to impose some consistency in the sql layer on determining read/write transactions and to provide some API compatibility if additional transactions are added. Above or equal to TL_FIRST_WRITE is a write transaction while < TL_FIRST_WRITE is a read transaction. */ #define TL_FIRST_WRITE TL_WRITE_ALLOW_WRITE enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1, THR_LOCK_WAIT_TIMEOUT= 2, THR_LOCK_DEADLOCK= 3 }; /* Priority for locks */ #define THR_LOCK_LATE_PRIV 1U /* For locks to be merged with org lock */ #define THR_LOCK_MERGE_PRIV 2U /* For merge tables */ #define THR_UNLOCK_UPDATE_STATUS 1U extern ulong max_write_lock_count; extern my_bool thr_lock_inited; extern enum thr_lock_type thr_upgraded_concurrent_insert_lock; /* A description of the thread which owns the lock. The address of an instance of this structure is used to uniquely identify the thread. */ typedef struct st_thr_lock_info { pthread_t thread; my_thread_id thread_id; void *mysql_thd; // THD pointer } THR_LOCK_INFO; typedef struct st_thr_lock_data { THR_LOCK_INFO *owner; struct st_thr_lock_data *next,**prev; struct st_thr_lock *lock; mysql_cond_t *cond; void *status_param; /* Param to status functions */ void *debug_print_param; /* For error messages */ struct PSI_table *m_psi; enum thr_lock_type type; enum thr_lock_type org_type; /* Cache for MariaDB */ uint priority; } THR_LOCK_DATA; struct st_lock_list { THR_LOCK_DATA *data,**last; }; typedef struct st_thr_lock { LIST list; mysql_mutex_t mutex; struct st_lock_list read_wait; struct st_lock_list read; struct st_lock_list write_wait; struct st_lock_list write; /* write_lock_count is incremented for write locks and reset on read locks */ ulong write_lock_count; uint read_no_write_count; my_bool (*get_status)(void*, my_bool);/* Called when one gets a lock */ void (*copy_status)(void*,void*); void (*update_status)(void*); /* Before release of write */ void (*restore_status)(void*); /* Before release of read */ my_bool (*start_trans)(void*); /* When all locks are taken */ my_bool (*check_status)(void *); void (*fix_status)(void *, void *);/* For thr_merge_locks() */ const char *name; /* Used for error reporting */ my_bool allow_multiple_concurrent_insert; } THR_LOCK; extern LIST *thr_lock_thread_list; extern mysql_mutex_t THR_LOCK_lock; struct st_my_thread_var; my_bool init_thr_lock(void); /* Must be called once/thread */ void thr_lock_info_init(THR_LOCK_INFO *info, struct st_my_thread_var *tmp); void thr_lock_init(THR_LOCK *lock); void thr_lock_delete(THR_LOCK *lock); void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *status_param); void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags); enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, ulong lock_wait_timeout); void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags); void thr_merge_locks(THR_LOCK_DATA **data, uint org_count, uint new_count); void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock); my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread); void thr_print_locks(void); /* For debugging */ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, enum thr_lock_type new_lock_type, ulong lock_wait_timeout); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, ulong lock_wait_timeout); void thr_set_lock_wait_callback(void (*before_wait)(void), void (*after_wait)(void)); #ifdef WITH_WSREP typedef my_bool (* wsrep_thd_is_brute_force_fun)(const MYSQL_THD, my_bool); typedef my_bool(* wsrep_abort_thd_fun)(MYSQL_THD, MYSQL_THD, my_bool); typedef my_bool (* wsrep_on_fun)(const MYSQL_THD); void wsrep_thr_lock_init( wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun); #endif #ifdef __cplusplus } #endif #endif /* _thr_lock_h */ my_atomic_wrapper.h 0000644 00000005753 15156036144 0010455 0 ustar 00 /* Copyright (c) 2020, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #ifdef __cplusplus #include <atomic> /** A wrapper for std::atomic, defaulting to std::memory_order_relaxed. When it comes to atomic loads or stores at std::memory_order_relaxed on IA-32 or AMD64, this wrapper is only introducing some constraints to the C++ compiler, to prevent some optimizations of loads or stores. On POWER and ARM, atomic loads and stores involve different instructions from normal loads and stores and will thus incur some overhead. Because atomic read-modify-write operations will always incur overhead, we intentionally do not define operator++(), operator--(), operator+=(), operator-=(), or similar, to make the overhead stand out in the users of this code. */ template <typename Type> class Atomic_relaxed { std::atomic<Type> m; public: Atomic_relaxed(const Atomic_relaxed<Type> &rhs) { m.store(rhs, std::memory_order_relaxed); } Atomic_relaxed(Type val) : m(val) {} Atomic_relaxed() = default; Type load(std::memory_order o= std::memory_order_relaxed) const { return m.load(o); } void store(Type i, std::memory_order o= std::memory_order_relaxed) { m.store(i, o); } operator Type() const { return m.load(); } Type operator=(const Type i) { store(i); return i; } Type operator=(const Atomic_relaxed<Type> &rhs) { return *this= Type{rhs}; } Type operator+=(const Type i) { return fetch_add(i); } Type fetch_add(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_add(i, o); } Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_sub(i, o); } Type fetch_xor(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_xor(i, o); } Type fetch_and(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_and(i, o); } Type fetch_or(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_or(i, o); } bool compare_exchange_strong(Type& i1, const Type i2, std::memory_order o1= std::memory_order_relaxed, std::memory_order o2= std::memory_order_relaxed) { return m.compare_exchange_strong(i1, i2, o1, o2); } Type exchange(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.exchange(i, o); } }; #endif /* __cplusplus */ sql_lex.h 0000644 00000535131 15156036144 0006401 0 ustar 00 /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. Copyright (c) 2010, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @defgroup Semantic_Analysis Semantic Analysis */ #ifndef SQL_LEX_INCLUDED #define SQL_LEX_INCLUDED #include "violite.h" /* SSL_type */ #include "sql_trigger.h" #include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */ #include "mem_root_array.h" #include "grant.h" #include "sql_cmd.h" #include "sql_alter.h" // Alter_info #include "sql_window.h" #include "sql_trigger.h" #include "sp.h" // enum enum_sp_type #include "sql_tvc.h" #include "item.h" #include "sql_limit.h" // Select_limit_counters #include "json_table.h" // Json_table_column #include "sql_schema.h" #include "table.h" #include "sql_class.h" // enum enum_column_usage #include "select_handler.h" /* Used for flags of nesting constructs */ #define SELECT_NESTING_MAP_SIZE 64 typedef Bitmap<SELECT_NESTING_MAP_SIZE> nesting_map; /* YACC and LEX Definitions */ /** A string with metadata. Usually points to a string in the client character set, but unlike Lex_ident_cli_st (see below) it does not necessarily point to a query fragment. It can also point to memory of other kinds (e.g. an additional THD allocated memory buffer not overlapping with the current query text). We'll add more flags here eventually, to know if the string has, e.g.: - multi-byte characters - bad byte sequences - backslash escapes: 'a\nb' and reuse the original query fragments instead of making the string copy too early, in Lex_input_stream::get_text(). This will allow to avoid unnecessary copying, as well as create more optimal Item types in sql_yacc.yy */ struct Lex_string_with_metadata_st: public LEX_CSTRING { private: bool m_is_8bit; // True if the string has 8bit characters char m_quote; // Quote character, or 0 if not quoted public: void set_8bit(bool is_8bit) { m_is_8bit= is_8bit; } void set_metadata(bool is_8bit, char quote) { m_is_8bit= is_8bit; m_quote= quote; } void set(const char *s, size_t len, bool is_8bit, char quote) { str= s; length= len; set_metadata(is_8bit, quote); } void set(const LEX_CSTRING *s, bool is_8bit, char quote) { ((LEX_CSTRING &)*this)= *s; set_metadata(is_8bit, quote); } bool is_8bit() const { return m_is_8bit; } bool is_quoted() const { return m_quote != '\0'; } char quote() const { return m_quote; } // Get string repertoire by the 8-bit flag and the character set my_repertoire_t repertoire(CHARSET_INFO *cs) const { return !m_is_8bit && my_charset_is_ascii_based(cs) ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; } // Get string repertoire by the 8-bit flag, for ASCII-based character sets my_repertoire_t repertoire() const { return !m_is_8bit ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; } }; /* Used to store identifiers in the client character set. Points to a query fragment. */ struct Lex_ident_cli_st: public Lex_string_with_metadata_st { public: void set_keyword(const char *s, size_t len) { set(s, len, false, '\0'); } void set_ident(const char *s, size_t len, bool is_8bit) { set(s, len, is_8bit, '\0'); } void set_ident_quoted(const char *s, size_t len, bool is_8bit, char quote) { set(s, len, is_8bit, quote); } void set_unquoted(const LEX_CSTRING *s, bool is_8bit) { set(s, is_8bit, '\0'); } const char *pos() const { return str - is_quoted(); } const char *end() const { return str + length + is_quoted(); } }; class Lex_ident_cli: public Lex_ident_cli_st { public: Lex_ident_cli(const LEX_CSTRING *s, bool is_8bit) { set_unquoted(s, is_8bit); } Lex_ident_cli(const char *s, size_t len) { set_ident(s, len, false); } }; struct Lex_ident_sys_st: public LEX_CSTRING, Sql_alloc { public: bool copy_ident_cli(const THD *thd, const Lex_ident_cli_st *str); bool copy_keyword(const THD *thd, const Lex_ident_cli_st *str); bool copy_sys(const THD *thd, const LEX_CSTRING *str); bool convert(const THD *thd, const LEX_CSTRING *str, CHARSET_INFO *cs); bool copy_or_convert(const THD *thd, const Lex_ident_cli_st *str, CHARSET_INFO *cs); bool is_null() const { return str == NULL; } bool to_size_number(ulonglong *to) const; void set_valid_utf8(const LEX_CSTRING *name) { DBUG_ASSERT(Well_formed_prefix(system_charset_info, name->str, name->length).length() == name->length); str= name->str ; length= name->length; } }; class Lex_ident_sys: public Lex_ident_sys_st { public: Lex_ident_sys(const THD *thd, const Lex_ident_cli_st *str) { if (copy_ident_cli(thd, str)) ((LEX_CSTRING &) *this)= null_clex_str; } Lex_ident_sys() { ((LEX_CSTRING &) *this)= null_clex_str; } Lex_ident_sys(const char *name, size_t length) { LEX_CSTRING tmp= {name, length}; set_valid_utf8(&tmp); } Lex_ident_sys(const THD *thd, const LEX_CSTRING *str) { set_valid_utf8(str); } Lex_ident_sys & operator=(const Lex_ident_sys_st &name) { Lex_ident_sys_st::operator=(name); return *this; } }; struct Lex_column_list_privilege_st { List<Lex_ident_sys> *m_columns; privilege_t m_privilege; }; class Lex_column_list_privilege: public Lex_column_list_privilege_st { public: Lex_column_list_privilege(List<Lex_ident_sys> *columns, privilege_t privilege) { m_columns= columns; m_privilege= privilege; } }; /** ORDER BY ... LIMIT parameters; */ class Lex_order_limit_lock: public Sql_alloc { public: SQL_I_List<st_order> *order_list; /* ORDER clause */ Lex_select_lock lock; Lex_select_limit limit; Lex_order_limit_lock() :order_list(NULL) {} bool set_to(st_select_lex *sel); }; enum sub_select_type { UNSPECIFIED_TYPE, /* following 3 enums should be as they are*/ UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE }; enum set_op_type { UNSPECIFIED, UNION_DISTINCT, UNION_ALL, EXCEPT_DISTINCT, EXCEPT_ALL, INTERSECT_DISTINCT, INTERSECT_ALL }; inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2) { DBUG_ASSERT(op1 >= UNION_TYPE && op1 <= EXCEPT_TYPE); DBUG_ASSERT(op2 >= UNION_TYPE && op2 <= EXCEPT_TYPE); return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0); } enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT}; enum enum_view_suid { VIEW_SUID_INVOKER= 0, VIEW_SUID_DEFINER= 1, VIEW_SUID_DEFAULT= 2 }; enum plsql_cursor_attr_t { PLSQL_CURSOR_ATTR_ISOPEN, PLSQL_CURSOR_ATTR_FOUND, PLSQL_CURSOR_ATTR_NOTFOUND, PLSQL_CURSOR_ATTR_ROWCOUNT }; enum enum_sp_suid_behaviour { SP_IS_DEFAULT_SUID= 0, SP_IS_NOT_SUID, SP_IS_SUID }; enum enum_sp_aggregate_type { DEFAULT_AGGREGATE= 0, NOT_AGGREGATE, GROUP_AGGREGATE }; /* These may not be declared yet */ class Table_ident; class sql_exchange; class LEX_COLUMN; class sp_head; class sp_name; class sp_instr; class sp_instr_cfetch; class sp_pcontext; class sp_variable; class sp_fetch_target; class sp_expr_lex; class sp_assignment_lex; class partition_info; class Event_parse_data; class set_var_base; class sys_var; class Item_func_match; class File_parser; class Key_part_spec; class Item_window_func; struct sql_digest_state; class With_clause; class my_var; class select_handler; class Pushdown_select; #define ALLOC_ROOT_SET 1024 #ifdef MYSQL_SERVER /* There are 8 different type of table access so there is no more than combinations 2^8 = 256: . STMT_READS_TRANS_TABLE . STMT_READS_NON_TRANS_TABLE . STMT_READS_TEMP_TRANS_TABLE . STMT_READS_TEMP_NON_TRANS_TABLE . STMT_WRITES_TRANS_TABLE . STMT_WRITES_NON_TRANS_TABLE . STMT_WRITES_TEMP_TRANS_TABLE . STMT_WRITES_TEMP_NON_TRANS_TABLE The unsafe conditions for each combination is represented within a byte and stores the status of the option --binlog-direct-non-trans-updates, whether the trx-cache is empty or not, and whether the isolation level is lower than ISO_REPEATABLE_READ: . option (OFF/ON) . trx-cache (empty/not empty) . isolation (>= ISO_REPEATABLE_READ / < ISO_REPEATABLE_READ) bits 0 : . OFF, . empty, . >= ISO_REPEATABLE_READ bits 1 : . OFF, . empty, . < ISO_REPEATABLE_READ bits 2 : . OFF, . not empty, . >= ISO_REPEATABLE_READ bits 3 : . OFF, . not empty, . < ISO_REPEATABLE_READ bits 4 : . ON, . empty, . >= ISO_REPEATABLE_READ bits 5 : . ON, . empty, . < ISO_REPEATABLE_READ bits 6 : . ON, . not empty, . >= ISO_REPEATABLE_READ bits 7 : . ON, . not empty, . < ISO_REPEATABLE_READ */ extern uint binlog_unsafe_map[256]; /* Initializes the array with unsafe combinations and its respective conditions. */ void binlog_unsafe_map_init(); #endif #ifdef MYSQL_SERVER /* The following hack is needed because yy_*.cc do not define YYSTYPE before including this file */ #ifdef MYSQL_YACC #define LEX_YYSTYPE void * #else #include "lex_symbol.h" #ifdef MYSQL_LEX #include "item_func.h" /* Cast_target used in yy_mariadb.hh */ #include "sql_get_diagnostics.h" /* Types used in yy_mariadb.hh */ #include "sp_pcontext.h" #include "yy_mariadb.hh" #define LEX_YYSTYPE YYSTYPE * #else #define LEX_YYSTYPE void * #endif #endif #endif // describe/explain types #define DESCRIBE_NORMAL 1 #define DESCRIBE_EXTENDED 2 /* This is not within #ifdef because we want "EXPLAIN PARTITIONS ..." to produce additional "partitions" column even if partitioning is not compiled in. */ #define DESCRIBE_PARTITIONS 4 #define DESCRIBE_EXTENDED2 8 #ifdef MYSQL_SERVER extern const LEX_STRING empty_lex_str; extern const LEX_CSTRING empty_clex_str; extern const LEX_CSTRING star_clex_str; extern const LEX_CSTRING param_clex_str; enum enum_sp_data_access { SP_DEFAULT_ACCESS= 0, SP_CONTAINS_SQL, SP_NO_SQL, SP_READS_SQL_DATA, SP_MODIFIES_SQL_DATA }; #define DERIVED_SUBQUERY 1 #define DERIVED_VIEW 2 #define DERIVED_WITH 4 enum enum_view_create_mode { VIEW_CREATE_NEW, // check that there are not such VIEW/table VIEW_ALTER, // check that VIEW .frm with such name exists VIEW_CREATE_OR_REPLACE // check only that there are not such table }; class Create_view_info: public Sql_alloc { public: LEX_CSTRING select; // The SELECT statement of CREATE VIEW enum enum_view_create_mode mode; uint16 algorithm; uint8 check; enum enum_view_suid suid; Create_view_info(enum_view_create_mode mode_arg, uint16 algorithm_arg, enum_view_suid suid_arg) :select(null_clex_str), mode(mode_arg), algorithm(algorithm_arg), check(VIEW_CHECK_NONE), suid(suid_arg) { } }; enum enum_drop_mode { DROP_DEFAULT, // mode is not specified DROP_CASCADE, // CASCADE option DROP_RESTRICT // RESTRICT option }; /* Options to add_table_to_list() */ #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_IGNORE_LEAVES 4 #define TL_OPTION_ALIAS 8 #define TL_OPTION_SEQUENCE 16 #define TL_OPTION_TABLE_FUNCTION 32 typedef List<Item> List_item; typedef Mem_root_array<ORDER*, true> Group_list_ptrs; /* SERVERS CACHE CHANGES */ typedef struct st_lex_server_options { long port; LEX_CSTRING server_name, host, db, username, password, scheme, socket, owner; void reset(LEX_CSTRING name) { server_name= name; host= db= username= password= scheme= socket= owner= null_clex_str; port= -1; } } LEX_SERVER_OPTIONS; /** Structure to hold parameters for CHANGE MASTER, START SLAVE, and STOP SLAVE. Remark: this should not be confused with Master_info (and perhaps would better be renamed to st_lex_replication_info). Some fields, e.g., delay, are saved in Relay_log_info, not in Master_info. */ struct LEX_MASTER_INFO { DYNAMIC_ARRAY repl_ignore_server_ids; DYNAMIC_ARRAY repl_do_domain_ids; DYNAMIC_ARRAY repl_ignore_domain_ids; const char *host, *user, *password, *log_file_name; const char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher; const char *ssl_crl, *ssl_crlpath; const char *relay_log_name; LEX_CSTRING connection_name; /* Value in START SLAVE UNTIL master_gtid_pos=xxx */ LEX_CSTRING gtid_pos_str; ulonglong pos; ulong relay_log_pos; ulong server_id; uint port, connect_retry; float heartbeat_period; int sql_delay; bool is_demotion_opt; bool is_until_before_gtids; /* Enum is used for making it possible to detect if the user changed variable or if it should be left at old value */ enum {LEX_MI_UNCHANGED= 0, LEX_MI_DISABLE, LEX_MI_ENABLE} ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt, repl_do_domain_ids_opt, repl_ignore_domain_ids_opt; enum { LEX_GTID_UNCHANGED, LEX_GTID_NO, LEX_GTID_CURRENT_POS, LEX_GTID_SLAVE_POS } use_gtid_opt; void init() { bzero(this, sizeof(*this)); my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_ignore_server_ids, sizeof(::server_id), 0, 16, MYF(0)); my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_do_domain_ids, sizeof(ulong), 0, 16, MYF(0)); my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_ignore_domain_ids, sizeof(ulong), 0, 16, MYF(0)); sql_delay= -1; } void reset(bool is_change_master) { if (unlikely(is_change_master)) { delete_dynamic(&repl_ignore_server_ids); /* Free all the array elements. */ delete_dynamic(&repl_do_domain_ids); delete_dynamic(&repl_ignore_domain_ids); } host= user= password= log_file_name= ssl_key= ssl_cert= ssl_ca= ssl_capath= ssl_cipher= ssl_crl= ssl_crlpath= relay_log_name= NULL; pos= relay_log_pos= server_id= port= connect_retry= 0; heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= repl_ignore_server_ids_opt= repl_do_domain_ids_opt= repl_ignore_domain_ids_opt= LEX_MI_UNCHANGED; gtid_pos_str= null_clex_str; use_gtid_opt= LEX_GTID_UNCHANGED; sql_delay= -1; is_demotion_opt= 0; is_until_before_gtids= false; } }; typedef struct st_lex_reset_slave { bool all; } LEX_RESET_SLAVE; enum olap_type { UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE }; /* String names used to print a statement with index hints. Keep in sync with index_hint_type. */ extern const char * index_hint_type_name[]; typedef uchar index_clause_map; /* Bits in index_clause_map : one for each possible FOR clause in USE/FORCE/IGNORE INDEX index hint specification */ #define INDEX_HINT_MASK_JOIN (1) #define INDEX_HINT_MASK_GROUP (1 << 1) #define INDEX_HINT_MASK_ORDER (1 << 2) #define INDEX_HINT_MASK_ALL (INDEX_HINT_MASK_JOIN | INDEX_HINT_MASK_GROUP | \ INDEX_HINT_MASK_ORDER) class select_result_sink; /* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */ class Index_hint : public Sql_alloc { public: /* The type of the hint : USE/FORCE/IGNORE */ enum index_hint_type type; /* Where the hit applies to. A bitmask of INDEX_HINT_MASK_<place> values */ index_clause_map clause; /* The index name. Empty (str=NULL) name represents an empty list USE INDEX () clause */ LEX_CSTRING key_name; Index_hint (enum index_hint_type type_arg, index_clause_map clause_arg, const char *str, size_t length) : type(type_arg), clause(clause_arg) { key_name.str= str; key_name.length= length; } void print(THD *thd, String *str); }; /* The state of the lex parsing for selects master and slaves are pointers to select_lex. master is pointer to upper level node. slave is pointer to lower level node select_lex is a SELECT without union unit is container of either - One SELECT - UNION of selects select_lex and unit are both inherited form st_select_lex_node neighbors are two select_lex or units on the same level All select describing structures linked with following pointers: - list of neighbors (next/prev) (prev of first element point to slave pointer of upper structure) - For select this is a list of UNION's (or one element list) - For units this is a list of sub queries for the upper level select - pointer to master (master), which is If this is a unit - pointer to outer select_lex If this is a select_lex - pointer to outer unit structure for select - pointer to slave (slave), which is either: If this is a unit: - first SELECT that belong to this unit If this is a select_lex - first unit that belong to this SELECT (subquries or derived tables) - list of all select_lex (link_next/link_prev) This is to be used for things like derived tables creation, where we go through this list and create the derived tables. If unit contain several selects (UNION now, INTERSECT etc later) then it have special select_lex called fake_select_lex. It used for storing global parameters (like ORDER BY, LIMIT) and executing union. Subqueries used in global ORDER BY clause will be attached to this fake_select_lex, which will allow them correctly resolve fields of 'upper' UNION and outer selects. For example for following query: select * from table1 where table1.field IN (select * from table1_1_1 union select * from table1_1_2) union select * from table2 where table2.field=(select (select f1 from table2_1_1_1_1 where table2_1_1_1_1.f2=table2_1_1.f3) from table2_1_1 where table2_1_1.f1=table2.f2) union select * from table3; we will have following structure: select1: (select * from table1 ...) select2: (select * from table2 ...) select3: (select * from table3) select1.1.1: (select * from table1_1_1) ... main unit fake0 select1 select2 select3 |^^ |^ s||| ||master l||| |+---------------------------------+ a||| +---------------------------------+| v|||master slave || e||+-------------------------+ || V| neighbor | V| unit1.1<+==================>unit1.2 unit2.1 fake1.1 select1.1.1 select 1.1.2 select1.2.1 select2.1.1 |^ || V| unit2.1.1.1 select2.1.1.1.1 relation in main unit will be following: (bigger picture for: main unit fake0 select1 select2 select3 in the above picture) main unit |^^^^|fake_select_lex |||||+--------------------------------------------+ ||||+--------------------------------------------+| |||+------------------------------+ || ||+--------------+ | || slave||master | | || V| neighbor | neighbor | master|V select1<========>select2<========>select3 fake0 list of all select_lex will be following (as it will be constructed by parser): select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+ | +---------------------------------------------------------------------+ | +->select1.1.1->select1.1.2 */ /* Base class for st_select_lex (SELECT_LEX) & st_select_lex_unit (SELECT_LEX_UNIT) */ struct LEX; class st_select_lex; class st_select_lex_unit; class st_select_lex_node { protected: st_select_lex_node *next, **prev, /* neighbor list */ *master, *slave, /* vertical links */ *link_next, **link_prev; /* list of whole SELECT_LEX */ enum sub_select_type linkage; void init_query_common(); public: ulonglong options; uint8 uncacheable; bool distinct:1; bool no_table_names_allowed:1; /* used for global order by */ /* result of this query can't be cached, bit field, can be : UNCACHEABLE_DEPENDENT_GENERATED UNCACHEABLE_DEPENDENT_INJECTED UNCACHEABLE_RAND UNCACHEABLE_SIDEEFFECT UNCACHEABLE_EXPLAIN UNCACHEABLE_PREPARE */ bool is_linkage_set() const { return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE; } enum sub_select_type get_linkage() { return linkage; } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} // Ensures that at least all members used during cleanup() are initialized. st_select_lex_node() : next(NULL), prev(NULL), master(NULL), slave(NULL), link_next(NULL), link_prev(NULL), linkage(UNSPECIFIED_TYPE) { } inline st_select_lex_node* get_master() { return master; } void include_down(st_select_lex_node *upper); void attach_single(st_select_lex_node *slave_arg); void include_neighbour(st_select_lex_node *before); void link_chain_down(st_select_lex_node *first); void link_neighbour(st_select_lex_node *neighbour) { DBUG_ASSERT(next == NULL); DBUG_ASSERT(neighbour != NULL); next= neighbour; neighbour->prev= &next; } void cut_next() { next= NULL; } void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); void include_global(st_select_lex_node **plink); void exclude(); void exclude_from_tree(); void exclude_from_global() { if (!link_prev) return; if (((*link_prev)= link_next)) link_next->link_prev= link_prev; link_next= NULL; link_prev= NULL; } void substitute_in_tree(st_select_lex_node *subst); void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } void move_node(st_select_lex_node *where_to_move) { if (where_to_move == this) return; if (next) next->prev= prev; *prev= next; *where_to_move->prev= this; next= where_to_move; } st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, st_select_lex_node *end_chain_node); void move_as_slave(st_select_lex_node *new_master); void set_linkage(enum sub_select_type l) { DBUG_ENTER("st_select_lex_node::set_linkage"); DBUG_PRINT("info", ("node: %p linkage: %d->%d", this, linkage, l)); linkage= l; DBUG_VOID_RETURN; } /* This method created for reiniting LEX in mysql_admin_table() and can be used only if you are going remove all SELECT_LEX & units except belonger to LEX (LEX::unit & LEX::select, for other purposes there are SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree. It is also used in parsing to detach builtin select. */ void cut_subtree() { slave= 0; } friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, bool open_view_no_parse); friend class st_select_lex; private: void fast_exclude(); }; typedef class st_select_lex_node SELECT_LEX_NODE; /* SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group SELECT_LEXs */ class THD; class select_result; class JOIN; class select_unit; class Procedure; class Explain_query; void delete_explain_query(LEX *lex); void create_explain_query(LEX *lex, MEM_ROOT *mem_root); void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root); bool print_explain_for_slow_log(LEX *lex, THD *thd, String *str); class st_select_lex_unit: public st_select_lex_node { private: /* When a CTE is merged to the parent SELECT, its unit is excluded which separates it from the tree of units for this query. It needs to be cleaned up but not at the time it is excluded, since its queries are merged to the unit above it. Remember all such units via the stranded_clean_list and clean them at the end of the query. This list is maintained only at the root unit node of the query tree. */ st_select_lex_unit *stranded_clean_list{nullptr}; // Add myself to the stranded_clean_list. void remember_my_cleanup(); /* Walk the stranded_clean_list and cleanup units. This must only be called for the st_select_lex_unit type because it assumes that those are the only nodes in the stranded_clean_list. */ void cleanup_stranded_units(); protected: TABLE_LIST result_table_list; select_unit *union_result; ulonglong found_rows_for_union; bool prepare_join(THD *thd, SELECT_LEX *sl, select_result *result, ulonglong additional_options, bool is_union_select); bool join_union_type_handlers(THD *thd, class Type_holder *holders, uint count); bool join_union_type_attributes(THD *thd, class Type_holder *holders, uint count); public: bool join_union_item_types(THD *thd, List<Item> &types, uint count); // Ensures that at least all members used during cleanup() are initialized. st_select_lex_unit() : union_result(NULL), table(NULL), result(NULL), fake_select_lex(NULL), last_procedure(NULL),cleaned(false), bag_set_op_optimized(false), have_except_all_or_intersect_all(false), pushdown_unit(NULL) { } void set_query_result(select_result *res) { result= res; } TABLE *table; /* temporary table using for appending UNION results */ select_result *result; st_select_lex *pre_last_parse; /* Node on which we should return current_select pointer after parsing subquery */ st_select_lex *return_to; /* LIMIT clause runtime counters */ Select_limit_counters lim; /* not NULL if unit used in subselect, point to subselect item */ Item_subselect *item; /* TABLE_LIST representing this union in the embedding select. Used for derived tables/views handling. */ TABLE_LIST *derived; /* With clause attached to this unit (if any) */ With_clause *with_clause; /* With element where this unit is used as the specification (if any) */ With_element *with_element; /* The unit used as a CTE specification from which this unit is cloned */ st_select_lex_unit *cloned_from; /* thread handler */ THD *thd; /* SELECT_LEX for hidden SELECT in union which process global ORDER BY and LIMIT */ st_select_lex *fake_select_lex; /** SELECT_LEX that stores LIMIT and OFFSET for UNION ALL when noq fake_select_lex is used. */ st_select_lex *saved_fake_select_lex; /* pointer to the last node before last subsequence of UNION ALL */ st_select_lex *union_distinct; Procedure *last_procedure; /* Pointer to procedure, if such exists */ // list of fields which points to temporary table for union List<Item> item_list; /* list of types of items inside union (used for union & derived tables) Item_type_holders from which this list consist may have pointers to Field, pointers is valid only after preparing SELECTS of this unit and before any SELECT of this unit execution */ List<Item> types; bool prepared:1; // prepare phase already performed for UNION (unit) bool optimized:1; // optimize phase already performed for UNION (unit) bool optimized_2:1; bool executed:1; // already executed bool cleaned:1; bool bag_set_op_optimized:1; bool optimize_started:1; bool have_except_all_or_intersect_all:1; /* The object used to organize execution of the UNIT by a foreign engine */ select_handler *pushdown_unit; /** TRUE if the unit contained TVC at the top level that has been wrapped into SELECT: VALUES (v1) ... (vn) => SELECT * FROM (VALUES (v1) ... (vn)) as tvc */ bool with_wrapped_tvc:1; bool is_view:1; bool describe:1; /* union exec() called for EXPLAIN */ bool columns_are_renamed:1; protected: /* This is bool, not bit, as it's used and set in many places */ bool saved_error; public: /** Pointer to 'last' select, or pointer to select where we stored global parameters for union. If this is a union of multiple selects, the parser puts the global parameters in fake_select_lex. If the union doesn't use a temporary table, st_select_lex_unit::prepare() nulls out fake_select_lex, but saves a copy in saved_fake_select_lex in order to preserve the global parameters. If it is not a union, first_select() is the last select. @return select containing the global parameters */ inline st_select_lex *global_parameters() { if (fake_select_lex != NULL) return fake_select_lex; else if (saved_fake_select_lex != NULL) return saved_fake_select_lex; return first_select(); }; void init_query(); st_select_lex* outer_select() const; const st_select_lex* first_select() const { return reinterpret_cast<const st_select_lex*>(slave); } st_select_lex* first_select() { return reinterpret_cast<st_select_lex*>(slave); } void set_with_clause(With_clause *with_cl); st_select_lex_unit* next_unit() { return reinterpret_cast<st_select_lex_unit*>(next); } st_select_lex* return_after_parsing() { return return_to; } void exclude_level(); // void exclude_tree(); // it is not used for long time bool is_excluded() { return prev == NULL; } /* UNION methods */ bool prepare(TABLE_LIST *derived_arg, select_result *sel_result, ulonglong additional_options); bool optimize(); void optimize_bag_operation(bool is_outer_distinct); bool exec(); bool exec_recursive(); bool cleanup(); inline void unclean() { cleaned= 0; } void reinit_exec_mechanism(); void print(String *str, enum_query_type query_type); bool add_fake_select_lex(THD *thd); void init_prepare_fake_select_lex(THD *thd, bool first_execution); void set_prepared() { prepared = true; } inline bool is_prepared() { return prepared; } bool change_result(select_result_interceptor *result, select_result_interceptor *old_result); void set_limit(st_select_lex *values); void set_thd(THD *thd_arg) { thd= thd_arg; } inline bool is_unit_op (); bool union_needs_tmp_table(); void set_unique_exclude(); bool check_distinct_in_union(); friend struct LEX; friend int subselect_union_engine::exec(); List<Item> *get_column_types(bool for_cursor); select_unit *get_union_result() { return union_result; } int save_union_explain(Explain_query *output); int save_union_explain_part2(Explain_query *output); unit_common_op common_op(); bool explainable() const; void reset_distinct(); void fix_distinct(); void register_select_chain(SELECT_LEX *first_sel); bool set_nest_level(int new_nest_level); bool check_parameters(SELECT_LEX *main_select); bool set_lock_to_the_last_select(Lex_select_lock l); void print_lock_from_the_last_select(String *str); bool can_be_merged(); friend class st_select_lex; private: bool exec_inner(); bool is_derived_eliminated() const; bool set_direct_union_result(select_result *sel_result); bool prepare_pushdown(bool use_direct_union_result, select_result *sel_result); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; typedef Bounds_checked_array<Item*> Ref_ptr_array; /** Structure which consists of the field and the item that corresponds to this field. */ class Field_pair :public Sql_alloc { public: Field *field; Item *corresponding_item; Field_pair(Field *fld, Item *item) :field(fld), corresponding_item(item) {} }; Field_pair *get_corresponding_field_pair(Item *item, List<Field_pair> pair_list); Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list); #define TOUCHED_SEL_COND 1/* WHERE/HAVING/ON should be reinited before use */ #define TOUCHED_SEL_DERIVED (1<<1)/* derived should be reinited before use */ #define UNIT_NEST_FL 1 /* SELECT_LEX - store information of parsed SELECT statment */ class st_select_lex: public st_select_lex_node { public: Name_resolution_context context; LEX_CSTRING db; /* Point to the LEX in which it was created, used in view subquery detection. TODO: make also st_select_lex::parent_stmt_lex (see LEX::stmt_lex) and use st_select_lex::parent_lex & st_select_lex::parent_stmt_lex instead of global (from THD) references where it is possible. */ LEX *parent_lex; /* Currently the field first_nested is used only by parser. It contains either a reference to the first select of the nest of selects to which 'this' belongs to, or in the case of priority jump it contains a reference to the select to which the priority nest has to be attached to. If there is no priority jump then the first select of the nest contains the reference to itself in first_nested. Example: select1 union select2 intersect select Here we have a priority jump at select2. So select2->first_nested points to select1, while select3->first_nested points to select2 and select1->first_nested points to select1. */ st_select_lex *first_nested; Item *where, *having; /* WHERE & HAVING clauses */ Item *prep_where; /* saved WHERE clause for prepared statement processing */ Item *prep_having;/* saved HAVING clause for prepared statement processing */ Item *cond_pushed_into_where; /* condition pushed into WHERE */ Item *cond_pushed_into_having; /* condition pushed into HAVING */ Item *where_cond_after_prepare; /* nest_levels are local to the query or VIEW, and that view merge procedure does not re-calculate them. So we also have to remember unit against which we count levels. */ SELECT_LEX_UNIT *nest_level_base; Item_sum *inner_sum_func_list; /* list of sum func in nested selects */ /* This is a copy of the original JOIN USING list that comes from the parser. The parser : 1. Sets the natural_join of the second TABLE_LIST in the join and the st_select_lex::prev_join_using. 2. Makes a parent TABLE_LIST and sets its is_natural_join/ join_using_fields members. 3. Uses the wrapper TABLE_LIST as a table in the upper level. We cannot assign directly to join_using_fields in the parser because at stage (1.) the parent TABLE_LIST is not constructed yet and the assignment will override the JOIN USING fields of the lower level joins on the right. */ List<String> *prev_join_using; JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ TABLE_LIST *embedding; /* table embedding to the above list */ table_value_constr *tvc; /* The object used to organize execution of the query by a foreign engine */ select_handler *pushdown_select; List<TABLE_LIST> *join_list; /* list for the currently parsed join */ st_select_lex *merged_into; /* select which this select is merged into */ /* (not 0 only for views/derived tables) */ const char *type; /* type of select for EXPLAIN */ /* List of references to fields referenced from inner selects */ List<Item_outer_ref> inner_refs_list; List<Item> attach_to_conds; /* Saved values of the WHERE and HAVING clauses*/ Item::cond_result cond_value, having_value; /* Usually it is pointer to ftfunc_list_alloc, but in union used to create fake select_lex for calling mysql_select under results of union */ List<Item_func_match> *ftfunc_list; List<Item_func_match> ftfunc_list_alloc; /* The list of items to which MIN/MAX optimizations of opt_sum_query() have been applied. Used to rollback those optimizations if it's needed. */ List<Item_sum> min_max_opt_list; List<TABLE_LIST> top_join_list; /* join list of the top level */ List<TABLE_LIST> sj_nests; /* Semi-join nests within this join */ /* Beginning of the list of leaves in a FROM clause, where the leaves inlcude all base tables including view tables. The tables are connected by TABLE_LIST::next_leaf, so leaf_tables points to the left-most leaf. List of all base tables local to a subquery including all view tables. Unlike 'next_local', this in this list views are *not* leaves. Created in setup_tables() -> make_leaves_list(). */ /* Subqueries that will need to be converted to semi-join nests, including those converted to jtbm nests. The list is emptied when conversion is done. */ List<Item_in_subselect> sj_subselects; /* List of IN-predicates in this st_select_lex that can be transformed into IN-subselect defined with TVC. */ List<Item_func_in> in_funcs; List<TABLE_LIST> leaf_tables; List<TABLE_LIST> leaf_tables_exec; List<TABLE_LIST> leaf_tables_prep; /* current index hint kind. used in filling up index_hints */ enum index_hint_type current_index_hint_type; /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ SQL_I_List<TABLE_LIST> table_list; /* GROUP BY clause. This list may be mutated during optimization (by remove_const()), so for prepared statements, we keep a copy of the ORDER.next pointers in group_list_ptrs, and re-establish the original list before each execution. */ SQL_I_List<ORDER> group_list; SQL_I_List<ORDER> save_group_list; Group_list_ptrs *group_list_ptrs; List<Item> item_list; /* list of fields & expressions */ List<Item> pre_fix; /* above list before fix_fields */ List<Item> fix_after_optimize; SQL_I_List<ORDER> order_list; /* ORDER clause */ SQL_I_List<ORDER> save_order_list; SQL_I_List<ORDER> gorder_list; Lex_select_limit limit_params; /* LIMIT clause parameters */ /* Structure to store fields that are used in the GROUP BY of this select */ List<Field_pair> grouping_tmp_fields; List<udf_func> udf_list; /* udf function calls stack */ List<Index_hint> *index_hints; /* list of USE/FORCE/IGNORE INDEX */ /* This list is used to restore the names of items from item_list after each execution of the statement. */ List<Lex_ident_sys> *orig_names_of_item_list_elems; List<List_item> save_many_values; List<Item> *save_insert_list; enum_column_usage item_list_usage; bool is_item_list_lookup:1; /* Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column of EXPLAIN */ bool have_merged_subqueries:1; bool is_set_query_expr_tail:1; bool with_sum_func:1; /* sum function indicator */ bool with_rownum:1; /* rownum() function indicator */ bool braces:1; /* SELECT ... UNION (SELECT ... ) <- this braces */ bool automatic_brackets:1; /* dummy select for INTERSECT precedence */ /* TRUE when having fix field called in processing of this SELECT */ bool having_fix_field:1; /* TRUE when fix field is called for a new condition pushed into the HAVING clause of this SELECT */ bool having_fix_field_for_pushed_cond:1; /* there are subquery in HAVING clause => we can't close tables before query processing end even if we use temporary table */ bool subquery_in_having:1; /* TRUE <=> this SELECT is correlated w.r.t. some ancestor select */ bool with_all_modifier:1; /* used for selects in union */ bool is_correlated:1; bool first_natural_join_processing:1; bool first_cond_optimization:1; /** The purpose of this flag is to run initialization phase for rownum only once. This flag is set on at st_select_lex::init_query and reset to the value false after the method optimize_rownum() has been called from the method JOIN::optimize_inner. */ bool first_rownum_optimization:1; /** Flag to guard against double initialization of leaf tables list */ bool leaf_tables_saved:1; /* do not wrap view fields with Item_ref */ bool no_wrap_view_item:1; /* exclude this select from check of unique_table() */ bool exclude_from_table_unique_test:1; bool in_tvc:1; bool skip_locked:1; bool m_non_agg_field_used:1; bool m_agg_func_used:1; bool m_custom_agg_func_used:1; /* the select is "service-select" and can not have tables */ bool is_service_select:1; /// Array of pointers to top elements of all_fields list Ref_ptr_array ref_pointer_array; ulong table_join_options; /* number of items in select_list and HAVING clause used to get number bigger then can be number of entries that will be added to all item list during split_sum_func */ uint select_n_having_items; uint cond_count; /* number of sargable Items in where/having/on */ uint between_count; /* number of between predicates in where/having/on */ uint max_equal_elems; /* max number of elements in multiple equalities */ /* Number of fields used in select list or where clause of current select and all inner subselects. */ uint select_n_where_fields; /* Total number of elements in group by and order by lists */ uint order_group_num; /* reserved for exists 2 in */ uint select_n_reserved; /* it counts the number of bit fields in the SELECT list. These are used when DISTINCT is converted to a GROUP BY involving BIT fields. */ uint hidden_bit_fields; /* Number of fields used in the definition of all the windows functions. This includes: 1) Fields in the arguments 2) Fields in the PARTITION BY clause 3) Fields in the ORDER BY clause */ /* Number of current derived table made with TVC during the transformation of IN-predicate into IN-subquery for this st_select_lex. */ uint curr_tvc_name; /* true <=> select has been created a TVC wrapper */ bool is_tvc_wrapper; uint fields_in_window_functions; uint insert_tables; enum_parsing_place parsing_place; /* where we are parsing expression */ enum_parsing_place save_parsing_place; enum_parsing_place context_analysis_place; /* where we are in prepare */ enum leaf_list_state {UNINIT, READY, SAVED}; enum leaf_list_state prep_leaf_list_state; enum olap_type olap; /* SELECT [FOR UPDATE/LOCK IN SHARE MODE] [SKIP LOCKED] */ enum select_lock_type {NONE, IN_SHARE_MODE, FOR_UPDATE}; enum select_lock_type select_lock; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ uint with_wild; /* item list contain '*' ; Counter */ /* Number of Item_sum-derived objects in this SELECT */ uint n_sum_items; /* Number of Item_sum-derived objects in children and descendant SELECTs */ uint n_child_sum_items; uint versioned_tables; /* For versioning */ int nest_level; /* nesting level of select */ /* index in the select list of the expression currently being fixed */ int cur_pos_in_select_list; /* This array is used to note whether we have any candidates for expression caching in the corresponding clauses */ bool expr_cache_may_be_used[PARSING_PLACE_SIZE]; uint8 nest_flags; /* This variable is required to ensure proper work of subqueries and stored procedures. Generally, one should use the states of Query_arena to determine if it's a statement prepare or first execution of a stored procedure. However, in case when there was an error during the first execution of a stored procedure, the SP body is not expelled from the SP cache. Therefore, a deeply nested subquery might be left unoptimized. So we need this per-subquery variable to inidicate the optimization/execution state of every subquery. Prepared statements work OK in that regard, as in case of an error during prepare the PS is not created. */ uint8 changed_elements; // see TOUCHED_SEL_* /** The set of those tables whose fields are referenced in the select list of this select level. */ table_map select_list_tables; /* Set to 1 if any field in field list has ROWNUM() */ bool rownum_in_field_list; /* namp of nesting SELECT visibility (for aggregate functions check) */ nesting_map name_visibility_map; table_map with_dep; index_clause_map current_index_hint_clause; /* it is for correct printing SELECT options */ thr_lock_type lock_type; /** System Versioning */ int vers_setup_conds(THD *thd, TABLE_LIST *tables); /* push new Item_field into item_list */ bool vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING field_name); int period_setup_conds(THD *thd, TABLE_LIST *table); void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } inline void set_master_unit(st_select_lex_unit *master_unit) { master= (st_select_lex_node *)master_unit; } void set_master(st_select_lex *master_arg) { master= master_arg; } st_select_lex_unit* first_inner_unit() { return (st_select_lex_unit*) slave; } st_select_lex* outer_select(); bool is_query_topmost(THD *thd); st_select_lex* next_select() { return (st_select_lex*) next; } st_select_lex* next_select_in_list() { return (st_select_lex*) link_next; } st_select_lex_node** next_select_in_list_addr() { return &link_next; } st_select_lex* return_after_parsing() { return master_unit()->return_after_parsing(); } inline bool is_subquery_function() { return master_unit()->item != 0; } bool mark_as_dependent(THD *thd, st_select_lex *last, Item_ident *dependency); void set_braces(bool value) { braces= value; } bool inc_in_sum_expr(); uint get_in_sum_expr(); bool add_item_to_list(THD *thd, Item *item); bool add_group_to_list(THD *thd, Item *item, bool asc); bool add_ftfunc_to_list(THD *thd, Item_func_match *func); bool add_order_to_list(THD *thd, Item *item, bool asc); bool add_gorder_to_list(THD *thd, Item *item, bool asc); TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table, const LEX_CSTRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, enum_mdl_type mdl_type= MDL_SHARED_READ, List<Index_hint> *hints= 0, List<String> *partition_names= 0, LEX_STRING *option= 0); TABLE_LIST* get_table_list(); bool init_nested_join(THD *thd); TABLE_LIST *end_nested_join(THD *thd); TABLE_LIST *nest_last_join(THD *thd); void add_joined_table(TABLE_LIST *table); bool add_cross_joined_table(TABLE_LIST *left_op, TABLE_LIST *right_op, bool straight_fl); TABLE_LIST *convert_right_join(); List<Item>* get_item_list(); bool save_item_list_names(THD *thd); void restore_item_list_names(); ulong get_table_join_options(); void set_lock_for_tables(thr_lock_type lock_type, bool for_update, bool skip_locks); /* This method created for reiniting LEX in mysql_admin_table() and can be used only if you are going remove all SELECT_LEX & units except belonger to LEX (LEX::unit & LEX::select, for other purposes there are SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree */ void cut_subtree() { slave= 0; } bool test_limit(); /** Get offset for LIMIT. Evaluate offset item if necessary. @return Number of rows to skip. */ ha_rows get_offset(); /** Get limit. Evaluate limit item if necessary. @return Limit of rows in result. */ ha_rows get_limit(); friend struct LEX; st_select_lex() : group_list_ptrs(NULL), braces(0), automatic_brackets(0), n_sum_items(0), n_child_sum_items(0) {} void make_empty_select() { init_query(); init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg); void print(THD *thd, String *str, enum_query_type query_type); void print_lock_type(String *str); void print_item_list(THD *thd, String *str, enum_query_type query_type); void print_set_clause(THD *thd, String *str, enum_query_type query_type); void print_on_duplicate_key_clause(THD *thd, String *str, enum_query_type query_type); static void print_order(String *str, ORDER *order, enum_query_type query_type); void print_limit(THD *thd, String *str, enum_query_type query_type); void fix_prepare_information(THD *thd, Item **conds, Item **having_conds); /* Destroy the used execution plan (JOIN) of this subtree (this SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs). */ bool cleanup(); /* Recursively cleanup the join of this select lex and of all nested select lexes. */ void cleanup_all_joins(bool full); void set_index_hint_type(enum index_hint_type type, index_clause_map clause); /* Add a index hint to the tagged list of hints. The type and clause of the hint will be the current ones (set by set_index_hint()) */ bool add_index_hint (THD *thd, const char *str, size_t length); /* make a list to hold index hints */ void alloc_index_hints (THD *thd); /* read and clear the index hints */ List<Index_hint>* pop_index_hints(void) { List<Index_hint> *hints= index_hints; index_hints= NULL; return hints; } inline void clear_index_hints(void) { index_hints= NULL; } bool is_part_of_union() { return master_unit()->is_unit_op(); } bool is_top_level_node() { return (select_number == 1) && !is_part_of_union(); } bool optimize_unflattened_subqueries(bool const_only); /* Set the EXPLAIN type for this subquery. */ void set_explain_type(bool on_the_fly); bool handle_derived(LEX *lex, uint phases); void append_table_to_list(TABLE_LIST *TABLE_LIST::*link, TABLE_LIST *table); bool get_free_table_map(table_map *map, uint *tablenr); void replace_leaf_table(TABLE_LIST *table, List<TABLE_LIST> &tbl_list); void remap_tables(TABLE_LIST *derived, table_map map, uint tablenr, st_select_lex *parent_lex); bool merge_subquery(THD *thd, TABLE_LIST *derived, st_select_lex *subq_lex, uint tablenr, table_map map); inline bool is_mergeable() { return (next_select() == 0 && group_list.elements == 0 && having == 0 && with_sum_func == 0 && with_rownum == 0 && table_list.elements >= 1 && !(options & SELECT_DISTINCT) && limit_params.select_limit == 0); } void mark_as_belong_to_derived(TABLE_LIST *derived); void increase_derived_records(ha_rows records); void update_used_tables(); void update_correlated_cache(); void mark_const_derived(bool empty); bool save_leaf_tables(THD *thd); bool save_prep_leaf_tables(THD *thd); void set_unique_exclude(); bool is_merged_child_of(st_select_lex *ancestor); /* For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags: - Non-aggregated fields are used in this select. - Aggregate functions are used in this select. In MODE_ONLY_FULL_GROUP_BY only one of these may be true. */ bool non_agg_field_used() const { return m_non_agg_field_used; } bool agg_func_used() const { return m_agg_func_used; } bool custom_agg_func_used() const { return m_custom_agg_func_used; } void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; } void set_agg_func_used(bool val) { m_agg_func_used= val; } void set_custom_agg_func_used(bool val) { m_custom_agg_func_used= val; } inline void set_with_clause(With_clause *with_clause); With_clause *get_with_clause() { return master_unit()->with_clause; } With_element *get_with_element() { return master_unit()->cloned_from ? master_unit()->cloned_from->with_element : master_unit()->with_element; } With_element *find_table_def_in_with_clauses(TABLE_LIST *table, st_select_lex_unit * excl_spec); bool check_unrestricted_recursive(bool only_standard_compliant); bool check_subqueries_with_recursive_references(); void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list); bool collect_grouping_fields(THD *thd); bool collect_fields_equal_to_grouping(THD *thd); void check_cond_extraction_for_grouping_fields(THD *thd, Item *cond); Item *build_cond_for_grouping_fields(THD *thd, Item *cond, bool no_to_clones); List<Window_spec> window_specs; bool is_win_spec_list_built; void prepare_add_window_spec(THD *thd); bool add_window_def(THD *thd, LEX_CSTRING *win_name, LEX_CSTRING *win_ref, SQL_I_List<ORDER> win_partition_list, SQL_I_List<ORDER> win_order_list, Window_frame *win_frame); bool add_window_spec(THD *thd, LEX_CSTRING *win_ref, SQL_I_List<ORDER> win_partition_list, SQL_I_List<ORDER> win_order_list, Window_frame *win_frame); List<Item_window_func> window_funcs; bool add_window_func(Item_window_func *win_func); bool have_window_funcs() const { return (window_funcs.elements !=0); } ORDER *find_common_window_func_partition_fields(THD *thd); bool cond_pushdown_is_allowed() const { return !olap && !limit_params.explicit_limit && !tvc && !with_rownum; } bool build_pushable_cond_for_having_pushdown(THD *thd, Item *cond); void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond, Item **remaining_cond, Item_transformer transformer, uchar *arg); Item *pushdown_from_having_into_where(THD *thd, Item *having); bool is_set_op() { return linkage == UNION_TYPE || linkage == EXCEPT_TYPE || linkage == INTERSECT_TYPE; } inline void add_where_field(st_select_lex *sel) { DBUG_ASSERT(this != sel); select_n_where_fields+= sel->select_n_where_fields; } inline void set_linkage_and_distinct(enum sub_select_type l, bool d) { DBUG_ENTER("SELECT_LEX::set_linkage_and_distinct"); DBUG_PRINT("info", ("select: %p distinct %d", this, d)); set_linkage(l); DBUG_ASSERT(l == UNSPECIFIED_TYPE || l == UNION_TYPE || l == INTERSECT_TYPE || l == EXCEPT_TYPE); if (d && master_unit() && master_unit()->union_distinct != this) master_unit()->union_distinct= this; distinct= d; with_all_modifier= !distinct; DBUG_VOID_RETURN; } bool set_nest_level(int new_nest_level); bool check_parameters(SELECT_LEX *main_select); void mark_select() { DBUG_ENTER("st_select_lex::mark_select()"); DBUG_PRINT("info", ("Select #%d", select_number)); DBUG_VOID_RETURN; } void register_unit(SELECT_LEX_UNIT *unit, Name_resolution_context *outer_context); SELECT_LEX_UNIT *attach_selects_chain(SELECT_LEX *sel, Name_resolution_context *context); void add_statistics(SELECT_LEX_UNIT *unit); bool make_unique_derived_name(THD *thd, LEX_CSTRING *alias); void lex_start(LEX *plex); bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); } void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; } bool is_sj_conversion_prohibited(THD *thd); TABLE_LIST *find_table(THD *thd, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name); bool optimize_constant_subqueries(); }; typedef class st_select_lex SELECT_LEX; inline bool st_select_lex_unit::is_unit_op () { if (!first_select()->next_select()) { if (first_select()->tvc) return 1; else return 0; } enum sub_select_type linkage= first_select()->next_select()->linkage; return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE; } struct st_sp_chistics { LEX_CSTRING comment; enum enum_sp_suid_behaviour suid; bool detistic; enum enum_sp_data_access daccess; enum enum_sp_aggregate_type agg_type; void init() { bzero(this, sizeof(*this)); } void set(const st_sp_chistics &other) { *this= other; } bool read_from_mysql_proc_row(THD *thd, TABLE *table); }; class Sp_chistics: public st_sp_chistics { public: Sp_chistics() { init(); } }; struct st_trg_chistics: public st_trg_execution_order { enum trg_action_time_type action_time; enum trg_event_type event; const char *ordering_clause_begin; const char *ordering_clause_end; }; enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE, XA_SUSPEND, XA_FOR_MIGRATE}; class Sroutine_hash_entry; /* Class representing list of all tables used by statement and other information which is necessary for opening and locking its tables, like SQL command for this statement. Also contains information about stored functions used by statement since during its execution we may have to add all tables used by its stored functions/triggers to this list in order to pre-open and lock them. Also used by LEX::reset_n_backup/restore_backup_query_tables_list() methods to save and restore this information. */ class Query_tables_list { public: /** SQL command for this statement. Part of this class since the process of opening and locking tables for the statement needs this information to determine correct type of lock for some of the tables. */ enum_sql_command sql_command; /* Global list of all tables used by this statement */ TABLE_LIST *query_tables; /* Pointer to next_global member of last element in the previous list. */ TABLE_LIST **query_tables_last; /* If non-0 then indicates that query requires prelocking and points to next_global member of last own element in query table list (i.e. last table which was not added to it as part of preparation to prelocking). 0 - indicates that this query does not need prelocking. */ TABLE_LIST **query_tables_own_last; /* Set of stored routines called by statement. (Note that we use lazy-initialization for this hash). */ enum { START_SROUTINES_HASH_SIZE= 16 }; HASH sroutines; /* List linking elements of 'sroutines' set. Allows you to add new elements to this set as you iterate through the list of existing elements. 'sroutines_list_own_last' is pointer to ::next member of last element of this list which represents routine which is explicitly used by query. 'sroutines_list_own_elements' number of explicitly used routines. We use these two members for restoring of 'sroutines_list' to the state in which it was right after query parsing. */ SQL_I_List<Sroutine_hash_entry> sroutines_list; Sroutine_hash_entry **sroutines_list_own_last; uint sroutines_list_own_elements; /** Locking state of tables in this particular statement. If we under LOCK TABLES or in prelocked mode we consider tables for the statement to be "locked" if there was a call to lock_tables() (which called handler::start_stmt()) for tables of this statement and there was no matching close_thread_tables() call. As result this state may differ significantly from one represented by Open_tables_state::lock/locked_tables_mode more, which are always "on" under LOCK TABLES or in prelocked mode. */ enum enum_lock_tables_state { LTS_NOT_LOCKED = 0, LTS_LOCKED }; enum_lock_tables_state lock_tables_state; bool is_query_tables_locked() const { return (lock_tables_state == LTS_LOCKED); } /* These constructor and destructor serve for creation/destruction of Query_tables_list instances which are used as backup storage. */ Query_tables_list() : lock_tables_state(LTS_NOT_LOCKED) {} ~Query_tables_list() {} /* Initializes (or resets) Query_tables_list object for "real" use. */ void reset_query_tables_list(bool init); void destroy_query_tables_list(); void set_query_tables_list(Query_tables_list *state) { *this= *state; } /* Direct addition to the list of query tables. If you are using this function, you must ensure that the table object, in particular table->db member, is initialized. */ void add_to_query_tables(TABLE_LIST *table) { *(table->prev_global= query_tables_last)= table; query_tables_last= &table->next_global; } bool requires_prelocking() { return MY_TEST(query_tables_own_last); } void mark_as_requiring_prelocking(TABLE_LIST **tables_own_last) { query_tables_own_last= tables_own_last; } /* Return pointer to first not-own table in query-tables or 0 */ TABLE_LIST* first_not_own_table() { return ( query_tables_own_last ? *query_tables_own_last : 0); } void chop_off_not_own_tables() { if (query_tables_own_last) { *query_tables_own_last= 0; query_tables_last= query_tables_own_last; query_tables_own_last= 0; } } /** Return a pointer to the last element in query table list. */ TABLE_LIST *last_table() { /* Don't use offsetof() macro in order to avoid warnings. */ return query_tables ? (TABLE_LIST*) ((char*) query_tables_last - ((char*) &(query_tables->next_global) - (char*) query_tables)) : 0; } /** Enumeration listing of all types of unsafe statement. @note The order of elements of this enumeration type must correspond to the order of the elements of the @c explanations array defined in the body of @c THD::issue_unsafe_warnings. */ enum enum_binlog_stmt_unsafe { /** SELECT..LIMIT is unsafe because the set of rows returned cannot be predicted. */ BINLOG_STMT_UNSAFE_LIMIT= 0, /** INSERT DELAYED is unsafe because the time when rows are inserted cannot be predicted. */ BINLOG_STMT_UNSAFE_INSERT_DELAYED, /** Access to log tables is unsafe because slave and master probably log different things. */ BINLOG_STMT_UNSAFE_SYSTEM_TABLE, /** Inserting into an autoincrement column in a stored routine is unsafe. Even with just one autoincrement column, if the routine is invoked more than once slave is not guaranteed to execute the statement graph same way as the master. And since it's impossible to estimate how many times a routine can be invoked at the query pre-execution phase (see lock_tables), the statement is marked pessimistically unsafe. */ BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS, /** Using a UDF (user-defined function) is unsafe. */ BINLOG_STMT_UNSAFE_UDF, /** Using most system variables is unsafe, because slave may run with different options than master. */ BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE, /** Using some functions is unsafe (e.g., UUID). */ BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION, /** Mixing transactional and non-transactional statements are unsafe if non-transactional reads or writes are occur after transactional reads or writes inside a transaction. */ BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS, /** Mixing self-logging and non-self-logging engines in a statement is unsafe. */ BINLOG_STMT_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE, /** Statements that read from both transactional and non-transactional tables and write to any of them are unsafe. */ BINLOG_STMT_UNSAFE_MIXED_STATEMENT, /** INSERT...IGNORE SELECT is unsafe because which rows are ignored depends on the order that rows are retrieved by SELECT. This order cannot be predicted and may differ on master and the slave. */ BINLOG_STMT_UNSAFE_INSERT_IGNORE_SELECT, /** INSERT...SELECT...UPDATE is unsafe because which rows are updated depends on the order that rows are retrieved by SELECT. This order cannot be predicted and may differ on master and the slave. */ BINLOG_STMT_UNSAFE_INSERT_SELECT_UPDATE, /** Query that writes to a table with auto_inc column after selecting from other tables are unsafe as the order in which the rows are retrieved by select may differ on master and slave. */ BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT, /** INSERT...REPLACE SELECT is unsafe because which rows are replaced depends on the order that rows are retrieved by SELECT. This order cannot be predicted and may differ on master and the slave. */ BINLOG_STMT_UNSAFE_REPLACE_SELECT, /** CREATE TABLE... IGNORE... SELECT is unsafe because which rows are ignored depends on the order that rows are retrieved by SELECT. This order cannot be predicted and may differ on master and the slave. */ BINLOG_STMT_UNSAFE_CREATE_IGNORE_SELECT, /** CREATE TABLE...REPLACE... SELECT is unsafe because which rows are replaced depends on the order that rows are retrieved from SELECT. This order cannot be predicted and may differ on master and the slave */ BINLOG_STMT_UNSAFE_CREATE_REPLACE_SELECT, /** CREATE TABLE...SELECT on a table with auto-increment column is unsafe because which rows are replaced depends on the order that rows are retrieved from SELECT. This order cannot be predicted and may differ on master and the slave */ BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC, /** UPDATE...IGNORE is unsafe because which rows are ignored depends on the order that rows are updated. This order cannot be predicted and may differ on master and the slave. */ BINLOG_STMT_UNSAFE_UPDATE_IGNORE, /** INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEYS is unsafe. */ BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS, /** INSERT into auto-inc field which is not the first part of composed primary key. */ BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST, /** Autoincrement lock mode is incompatible with STATEMENT binlog format. */ BINLOG_STMT_UNSAFE_AUTOINC_LOCK_MODE, /** INSERT .. SELECT ... SKIP LOCKED is unlikely to have the same rows locked on the replica. primary key. */ BINLOG_STMT_UNSAFE_SKIP_LOCKED, /* The last element of this enumeration type. */ BINLOG_STMT_UNSAFE_COUNT }; /** This has all flags from 0 (inclusive) to BINLOG_STMT_FLAG_COUNT (exclusive) set. */ static const uint32 BINLOG_STMT_UNSAFE_ALL_FLAGS= ((1U << BINLOG_STMT_UNSAFE_COUNT) - 1); /** Maps elements of enum_binlog_stmt_unsafe to error codes. */ static const int binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT]; /** Determine if this statement is marked as unsafe. @retval 0 if the statement is not marked as unsafe. @retval nonzero if the statement is marked as unsafe. */ inline bool is_stmt_unsafe() const { return get_stmt_unsafe_flags() != 0; } inline bool is_stmt_unsafe(enum_binlog_stmt_unsafe unsafe) { return binlog_stmt_flags & (1 << unsafe); } /** Flag the current (top-level) statement as unsafe. The flag will be reset after the statement has finished. @param unsafe_type The type of unsafety: one of the @c BINLOG_STMT_FLAG_UNSAFE_* flags in @c enum_binlog_stmt_flag. */ inline void set_stmt_unsafe(enum_binlog_stmt_unsafe unsafe_type) { DBUG_ENTER("set_stmt_unsafe"); DBUG_ASSERT(unsafe_type >= 0 && unsafe_type < BINLOG_STMT_UNSAFE_COUNT); binlog_stmt_flags|= (1U << unsafe_type); DBUG_VOID_RETURN; } /** Set the bits of binlog_stmt_flags determining the type of unsafeness of the current statement. No existing bits will be cleared, but new bits may be set. @param flags A binary combination of zero or more bits, (1<<flag) where flag is a member of enum_binlog_stmt_unsafe. */ inline void set_stmt_unsafe_flags(uint32 flags) { DBUG_ENTER("set_stmt_unsafe_flags"); DBUG_ASSERT((flags & ~BINLOG_STMT_UNSAFE_ALL_FLAGS) == 0); binlog_stmt_flags|= flags; DBUG_VOID_RETURN; } /** Return a binary combination of all unsafe warnings for the statement. If the statement has been marked as unsafe by the 'flag' member of enum_binlog_stmt_unsafe, then the return value from this function has bit (1<<flag) set to 1. */ inline uint32 get_stmt_unsafe_flags() const { DBUG_ENTER("get_stmt_unsafe_flags"); DBUG_RETURN(binlog_stmt_flags & BINLOG_STMT_UNSAFE_ALL_FLAGS); } /** Mark the current statement as safe; i.e., clear all bits in binlog_stmt_flags that correspond to elements of enum_binlog_stmt_unsafe. */ inline void clear_stmt_unsafe() { DBUG_ENTER("clear_stmt_unsafe"); binlog_stmt_flags&= ~BINLOG_STMT_UNSAFE_ALL_FLAGS; DBUG_VOID_RETURN; } /** Determine if this statement is a row injection. @retval 0 if the statement is not a row injection @retval nonzero if the statement is a row injection */ inline bool is_stmt_row_injection() const { return binlog_stmt_flags & (1U << BINLOG_STMT_TYPE_ROW_INJECTION); } /** Flag the statement as a row injection. A row injection is either a BINLOG statement, or a row event in the relay log executed by the slave SQL thread. */ inline void set_stmt_row_injection() { DBUG_ENTER("set_stmt_row_injection"); binlog_stmt_flags|= (1U << BINLOG_STMT_TYPE_ROW_INJECTION); DBUG_VOID_RETURN; } enum enum_stmt_accessed_table { /* If a transactional table is about to be read. Note that a write implies a read. */ STMT_READS_TRANS_TABLE= 0, /* If a non-transactional table is about to be read. Note that a write implies a read. */ STMT_READS_NON_TRANS_TABLE, /* If a temporary transactional table is about to be read. Note that a write implies a read. */ STMT_READS_TEMP_TRANS_TABLE, /* If a temporary non-transactional table is about to be read. Note that a write implies a read. */ STMT_READS_TEMP_NON_TRANS_TABLE, /* If a transactional table is about to be updated. */ STMT_WRITES_TRANS_TABLE, /* If a non-transactional table is about to be updated. */ STMT_WRITES_NON_TRANS_TABLE, /* If a temporary transactional table is about to be updated. */ STMT_WRITES_TEMP_TRANS_TABLE, /* If a temporary non-transactional table is about to be updated. */ STMT_WRITES_TEMP_NON_TRANS_TABLE, /* The last element of the enumeration. Please, if necessary add anything before this. */ STMT_ACCESS_TABLE_COUNT }; #ifndef DBUG_OFF static inline const char *stmt_accessed_table_string(enum_stmt_accessed_table accessed_table) { switch (accessed_table) { case STMT_READS_TRANS_TABLE: return "STMT_READS_TRANS_TABLE"; break; case STMT_READS_NON_TRANS_TABLE: return "STMT_READS_NON_TRANS_TABLE"; break; case STMT_READS_TEMP_TRANS_TABLE: return "STMT_READS_TEMP_TRANS_TABLE"; break; case STMT_READS_TEMP_NON_TRANS_TABLE: return "STMT_READS_TEMP_NON_TRANS_TABLE"; break; case STMT_WRITES_TRANS_TABLE: return "STMT_WRITES_TRANS_TABLE"; break; case STMT_WRITES_NON_TRANS_TABLE: return "STMT_WRITES_NON_TRANS_TABLE"; break; case STMT_WRITES_TEMP_TRANS_TABLE: return "STMT_WRITES_TEMP_TRANS_TABLE"; break; case STMT_WRITES_TEMP_NON_TRANS_TABLE: return "STMT_WRITES_TEMP_NON_TRANS_TABLE"; break; case STMT_ACCESS_TABLE_COUNT: default: DBUG_ASSERT(0); break; } MY_ASSERT_UNREACHABLE(); return ""; } #endif /* DBUG */ #define BINLOG_DIRECT_ON 0xF0 /* unsafe when --binlog-direct-non-trans-updates is ON */ #define BINLOG_DIRECT_OFF 0xF /* unsafe when --binlog-direct-non-trans-updates is OFF */ #define TRX_CACHE_EMPTY 0x33 /* unsafe when trx-cache is empty */ #define TRX_CACHE_NOT_EMPTY 0xCC /* unsafe when trx-cache is not empty */ #define IL_LT_REPEATABLE 0xAA /* unsafe when < ISO_REPEATABLE_READ */ #define IL_GTE_REPEATABLE 0x55 /* unsafe when >= ISO_REPEATABLE_READ */ /** Sets the type of table that is about to be accessed while executing a statement. @param accessed_table Enumeration type that defines the type of table, e.g. temporary, transactional, non-transactional. */ inline void set_stmt_accessed_table(enum_stmt_accessed_table accessed_table) { DBUG_ENTER("LEX::set_stmt_accessed_table"); DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT); stmt_accessed_table_flag |= (1U << accessed_table); DBUG_VOID_RETURN; } /** Checks if a type of table is about to be accessed while executing a statement. @param accessed_table Enumeration type that defines the type of table, e.g. temporary, transactional, non-transactional. @return @retval TRUE if the type of the table is about to be accessed @retval FALSE otherwise */ inline bool stmt_accessed_table(enum_stmt_accessed_table accessed_table) { DBUG_ENTER("LEX::stmt_accessed_table"); DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT); DBUG_RETURN((stmt_accessed_table_flag & (1U << accessed_table)) != 0); } /** Checks either a trans/non trans temporary table is being accessed while executing a statement. @return @retval TRUE if a temporary table is being accessed @retval FALSE otherwise */ inline bool stmt_accessed_temp_table() { DBUG_ENTER("THD::stmt_accessed_temp_table"); DBUG_RETURN(stmt_accessed_non_trans_temp_table() || stmt_accessed_trans_temp_table()); } /** Checks if a temporary transactional table is being accessed while executing a statement. @return @retval TRUE if a temporary transactional table is being accessed @retval FALSE otherwise */ inline bool stmt_accessed_trans_temp_table() { DBUG_ENTER("THD::stmt_accessed_trans_temp_table"); DBUG_RETURN((stmt_accessed_table_flag & ((1U << STMT_READS_TEMP_TRANS_TABLE) | (1U << STMT_WRITES_TEMP_TRANS_TABLE))) != 0); } inline bool stmt_writes_to_non_temp_table() { DBUG_ENTER("THD::stmt_writes_to_non_temp_table"); DBUG_RETURN((stmt_accessed_table_flag & ((1U << STMT_WRITES_TRANS_TABLE) | (1U << STMT_WRITES_NON_TRANS_TABLE)))); } /** Checks if a temporary non-transactional table is about to be accessed while executing a statement. @return @retval TRUE if a temporary non-transactional table is about to be accessed @retval FALSE otherwise */ inline bool stmt_accessed_non_trans_temp_table() { DBUG_ENTER("THD::stmt_accessed_non_trans_temp_table"); DBUG_RETURN((stmt_accessed_table_flag & ((1U << STMT_READS_TEMP_NON_TRANS_TABLE) | (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0); } /* Checks if a mixed statement is unsafe. @param in_multi_stmt_transaction_mode defines if there is an on-going multi-transactional statement. @param binlog_direct defines if --binlog-direct-non-trans-updates is active. @param trx_cache_is_not_empty defines if the trx-cache is empty or not. @param trx_isolation defines the isolation level. @return @retval TRUE if the mixed statement is unsafe @retval FALSE otherwise */ inline bool is_mixed_stmt_unsafe(bool in_multi_stmt_transaction_mode, bool binlog_direct, bool trx_cache_is_not_empty, uint tx_isolation) { bool unsafe= FALSE; if (in_multi_stmt_transaction_mode) { uint condition= (binlog_direct ? BINLOG_DIRECT_ON : BINLOG_DIRECT_OFF) & (trx_cache_is_not_empty ? TRX_CACHE_NOT_EMPTY : TRX_CACHE_EMPTY) & (tx_isolation >= ISO_REPEATABLE_READ ? IL_GTE_REPEATABLE : IL_LT_REPEATABLE); unsafe= (binlog_unsafe_map[stmt_accessed_table_flag] & condition); #if !defined(DBUG_OFF) DBUG_PRINT("LEX::is_mixed_stmt_unsafe", ("RESULT %02X %02X %02X", condition, binlog_unsafe_map[stmt_accessed_table_flag], (binlog_unsafe_map[stmt_accessed_table_flag] & condition))); int type_in= 0; for (; type_in < STMT_ACCESS_TABLE_COUNT; type_in++) { if (stmt_accessed_table((enum_stmt_accessed_table) type_in)) DBUG_PRINT("LEX::is_mixed_stmt_unsafe", ("ACCESSED %s ", stmt_accessed_table_string((enum_stmt_accessed_table) type_in))); } #endif } if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) && stmt_accessed_table(STMT_READS_TRANS_TABLE) && tx_isolation < ISO_REPEATABLE_READ) unsafe= TRUE; else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) && stmt_accessed_table(STMT_READS_TRANS_TABLE) && tx_isolation < ISO_REPEATABLE_READ) unsafe= TRUE; return(unsafe); } /** true if the parsed tree contains references to stored procedures or functions, false otherwise */ bool uses_stored_routines() const { return sroutines_list.elements != 0; } void set_date_funcs_used_flag() { date_funcs_used_flag= true; } /* Returns TRUE if date functions such as YEAR(), MONTH() or DATE() are used in this LEX */ bool are_date_funcs_used() const { return date_funcs_used_flag; } private: /** Enumeration listing special types of statements. Currently, the only possible type is ROW_INJECTION. */ enum enum_binlog_stmt_type { /** The statement is a row injection (i.e., either a BINLOG statement or a row event executed by the slave SQL thread). */ BINLOG_STMT_TYPE_ROW_INJECTION = BINLOG_STMT_UNSAFE_COUNT, /** The last element of this enumeration type. */ BINLOG_STMT_TYPE_COUNT }; /** Bit field indicating the type of statement. There are two groups of bits: - The low BINLOG_STMT_UNSAFE_COUNT bits indicate the types of unsafeness that the current statement has. - The next BINLOG_STMT_TYPE_COUNT-BINLOG_STMT_TYPE_COUNT bits indicate if the statement is of some special type. This must be a member of LEX, not of THD: each stored procedure needs to remember its unsafeness state between calls and each stored procedure has its own LEX object (but no own THD object). */ uint32 binlog_stmt_flags; /** Bit field that determines the type of tables that are about to be be accessed while executing a statement. */ uint32 stmt_accessed_table_flag; /* Flag indicating that date functions such as YEAR(), MONTH() or DATE() are used in this LEX */ bool date_funcs_used_flag= false; }; /* st_parsing_options contains the flags for constructions that are allowed in the current statement. */ struct st_parsing_options { bool allows_variable; bool lookup_keywords_after_qualifier; st_parsing_options() { reset(); } void reset(); }; /** The state of the lexical parser, when parsing comments. */ enum enum_comment_state { /** Not parsing comments. */ NO_COMMENT, /** Parsing comments that need to be preserved. Typically, these are user comments '/' '*' ... '*' '/'. */ PRESERVE_COMMENT, /** Parsing comments that need to be discarded. Typically, these are special comments '/' '*' '!' ... '*' '/', or '/' '*' '!' 'M' 'M' 'm' 'm' 'm' ... '*' '/', where the comment markers should not be expanded. */ DISCARD_COMMENT }; /** @brief This class represents the character input stream consumed during lexical analysis. In addition to consuming the input stream, this class performs some comment pre processing, by filtering out out of bound special text from the query input stream. Two buffers, with pointers inside each buffers, are maintained in parallel. The 'raw' buffer is the original query text, which may contain out-of-bound comments. The 'cpp' (for comments pre processor) is the pre-processed buffer that contains only the query text that should be seen once out-of-bound data is removed. */ class Lex_input_stream { size_t unescape(CHARSET_INFO *cs, char *to, const char *str, const char *end, int sep); my_charset_conv_wc_mb get_escape_func(THD *thd, my_wc_t sep) const; public: Lex_input_stream() = default; ~Lex_input_stream() = default; /** Object initializer. Must be called before usage. @retval FALSE OK @retval TRUE Error */ bool init(THD *thd, char *buff, size_t length); void reset(char *buff, size_t length); /** The main method to scan the next token, with token contraction processing for LALR(2) resolution, e.g. translate "WITH" followed by "ROLLUP" to a single token WITH_ROLLUP_SYM. */ int lex_token(union YYSTYPE *yylval, THD *thd); void reduce_digest_token(uint token_left, uint token_right); private: enum Ident_mode { GENERAL_KEYWORD_OR_FUNC_LPAREN, QUALIFIED_SPECIAL_FUNC_LPAREN }; int scan_ident_common(THD *thd, Lex_ident_cli_st *str, Ident_mode mode); /** Set the echo mode. When echo is true, characters parsed from the raw input stream are preserved. When false, characters parsed are silently ignored. @param echo the echo mode. */ void set_echo(bool echo) { m_echo= echo; } void save_in_comment_state() { m_echo_saved= m_echo; in_comment_saved= in_comment; } void restore_in_comment_state() { m_echo= m_echo_saved; in_comment= in_comment_saved; } /** Skip binary from the input stream. @param n number of bytes to accept. */ void skip_binary(int n) { if (m_echo) { memcpy(m_cpp_ptr, m_ptr, n); m_cpp_ptr += n; } m_ptr += n; } /** Get a character, and advance in the stream. @return the next character to parse. */ unsigned char yyGet() { char c= *m_ptr++; if (m_echo) *m_cpp_ptr++ = c; return c; } /** Get the last character accepted. @return the last character accepted. */ unsigned char yyGetLast() const { return m_ptr[-1]; } /** Look at the next character to parse, but do not accept it. */ unsigned char yyPeek() const { return m_ptr[0]; } /** Look ahead at some character to parse. @param n offset of the character to look up */ unsigned char yyPeekn(int n) const { return m_ptr[n]; } /** Cancel the effect of the last yyGet() or yySkip(). Note that the echo mode should not change between calls to yyGet / yySkip and yyUnget. The caller is responsible for ensuring that. */ void yyUnget() { m_ptr--; if (m_echo) m_cpp_ptr--; } /** Accept a character, by advancing the input stream. */ void yySkip() { if (m_echo) *m_cpp_ptr++ = *m_ptr++; else m_ptr++; } /** Accept multiple characters at once. @param n the number of characters to accept. */ void yySkipn(int n) { if (m_echo) { memcpy(m_cpp_ptr, m_ptr, n); m_cpp_ptr += n; } m_ptr += n; } /** Puts a character back into the stream, canceling the effect of the last yyGet() or yySkip(). Note that the echo mode should not change between calls to unput, get, or skip from the stream. */ char *yyUnput(char ch) { *--m_ptr= ch; if (m_echo) m_cpp_ptr--; return m_ptr; } /** End of file indicator for the query text to parse. @param n number of characters expected @return true if there are less than n characters to parse */ bool eof(int n) const { return ((m_ptr + n) >= m_end_of_query); } /** Mark the stream position as the start of a new token. */ void start_token() { m_tok_start_prev= m_tok_start; m_tok_start= m_ptr; m_tok_end= m_ptr; m_cpp_tok_start_prev= m_cpp_tok_start; m_cpp_tok_start= m_cpp_ptr; m_cpp_tok_end= m_cpp_ptr; } /** Adjust the starting position of the current token. This is used to compensate for starting whitespace. */ void restart_token() { m_tok_start= m_ptr; m_cpp_tok_start= m_cpp_ptr; } /** Get the maximum length of the utf8-body buffer. The utf8 body can grow because of the character set conversion and escaping. */ size_t get_body_utf8_maximum_length(THD *thd) const; /** Get the length of the current token, in the raw buffer. */ uint yyLength() const { /* The assumption is that the lexical analyser is always 1 character ahead, which the -1 account for. */ DBUG_ASSERT(m_ptr > m_tok_start); return (uint) ((m_ptr - m_tok_start) - 1); } /** Test if a lookahead token was already scanned by lex_token(), for LALR(2) resolution. */ bool has_lookahead() const { return lookahead_token >= 0; } public: /** End of file indicator for the query text to parse. @return true if there are no more characters to parse */ bool eof() const { return (m_ptr >= m_end_of_query); } /** Get the raw query buffer. */ const char *get_buf() const { return m_buf; } /** Get the pre-processed query buffer. */ const char *get_cpp_buf() const { return m_cpp_buf; } /** Get the end of the raw query buffer. */ const char *get_end_of_query() const { return m_end_of_query; } /** Get the token start position, in the raw buffer. */ const char *get_tok_start() const { return has_lookahead() ? m_tok_start_prev : m_tok_start; } void set_cpp_tok_start(const char *pos) { m_cpp_tok_start= pos; } /** Get the token end position, in the raw buffer. */ const char *get_tok_end() const { return m_tok_end; } /** Get the current stream pointer, in the raw buffer. */ const char *get_ptr() const { return m_ptr; } /** Get the token start position, in the pre-processed buffer. */ const char *get_cpp_tok_start() const { return has_lookahead() ? m_cpp_tok_start_prev : m_cpp_tok_start; } /** Get the token end position, in the pre-processed buffer. */ const char *get_cpp_tok_end() const { return m_cpp_tok_end; } /** Get the token end position in the pre-processed buffer, with trailing spaces removed. */ const char *get_cpp_tok_end_rtrim() const { const char *p; for (p= m_cpp_tok_end; p > m_cpp_buf && my_isspace(system_charset_info, p[-1]); p--) { } return p; } /** Get the current stream pointer, in the pre-processed buffer. */ const char *get_cpp_ptr() const { return m_cpp_ptr; } /** Get the current stream pointer, in the pre-processed buffer, with traling spaces removed. */ const char *get_cpp_ptr_rtrim() const { const char *p; for (p= m_cpp_ptr; p > m_cpp_buf && my_isspace(system_charset_info, p[-1]); p--) { } return p; } /** Get the utf8-body string. */ LEX_CSTRING body_utf8() const { return LEX_CSTRING({m_body_utf8, (size_t) (m_body_utf8_ptr - m_body_utf8)}); } void body_utf8_start(THD *thd, const char *begin_ptr); void body_utf8_append(const char *ptr); void body_utf8_append(const char *ptr, const char *end_ptr); void body_utf8_append_ident(THD *thd, const Lex_string_with_metadata_st *txt, const char *end_ptr); void body_utf8_append_escape(THD *thd, const LEX_CSTRING *txt, CHARSET_INFO *txt_cs, const char *end_ptr, my_wc_t sep); private: /** LALR(2) resolution, look ahead token. Value of the next token to return, if any, or -1, if no token was parsed in advance. Note: 0 is a legal token, and represents YYEOF. */ int lookahead_token; /** LALR(2) resolution, value of the look ahead token.*/ LEX_YYSTYPE lookahead_yylval; bool get_text(Lex_string_with_metadata_st *to, uint sep, int pre_skip, int post_skip); void add_digest_token(uint token, LEX_YYSTYPE yylval); bool consume_comment(int remaining_recursions_permitted); int lex_one_token(union YYSTYPE *yylval, THD *thd); int find_keyword(Lex_ident_cli_st *str, uint len, bool function) const; int find_keyword_qualified_special_func(Lex_ident_cli_st *str, uint len) const; LEX_CSTRING get_token(uint skip, uint length); int scan_ident_start(THD *thd, Lex_ident_cli_st *str); int scan_ident_middle(THD *thd, Lex_ident_cli_st *str, CHARSET_INFO **cs, my_lex_states *); int scan_ident_delimited(THD *thd, Lex_ident_cli_st *str, uchar quote_char); bool get_7bit_or_8bit_ident(THD *thd, uchar *last_char); /** Current thread. */ THD *m_thd; /** Pointer to the current position in the raw input stream. */ char *m_ptr; /** Starting position of the last token parsed, in the raw buffer. */ const char *m_tok_start; /** Ending position of the previous token parsed, in the raw buffer. */ const char *m_tok_end; /** End of the query text in the input stream, in the raw buffer. */ const char *m_end_of_query; /** Starting position of the previous token parsed, in the raw buffer. */ const char *m_tok_start_prev; /** Begining of the query text in the input stream, in the raw buffer. */ const char *m_buf; /** Length of the raw buffer. */ size_t m_buf_length; /** Echo the parsed stream to the pre-processed buffer. */ bool m_echo:1; bool m_echo_saved:1; /** Pre-processed buffer. */ char *m_cpp_buf; /** Pointer to the current position in the pre-processed input stream. */ char *m_cpp_ptr; /** Starting position of the last token parsed, in the pre-processed buffer. */ const char *m_cpp_tok_start; /** Starting position of the previous token parsed, in the pre-procedded buffer. */ const char *m_cpp_tok_start_prev; /** Ending position of the previous token parsed, in the pre-processed buffer. */ const char *m_cpp_tok_end; /** UTF8-body buffer created during parsing. */ char *m_body_utf8; /** Pointer to the current position in the UTF8-body buffer. */ char *m_body_utf8_ptr; /** Position in the pre-processed buffer. The query from m_cpp_buf to m_cpp_utf_processed_ptr is converted to UTF8-body. */ const char *m_cpp_utf8_processed_ptr; public: /** Current state of the lexical analyser. */ enum my_lex_states next_state; /** Position of ';' in the stream, to delimit multiple queries. This delimiter is in the raw buffer. */ const char *found_semicolon; /** SQL_MODE = IGNORE_SPACE. */ bool ignore_space:1; /** TRUE if we're parsing a prepared statement: in this mode we should allow placeholders. */ bool stmt_prepare_mode:1; /** TRUE if we should allow multi-statements. */ bool multi_statements:1; /** Current line number. */ uint yylineno; /** Current statement digest instrumentation. */ sql_digest_state* m_digest; private: /** State of the lexical analyser for comments. */ enum_comment_state in_comment; enum_comment_state in_comment_saved; /** Starting position of the TEXT_STRING or IDENT in the pre-processed buffer. NOTE: this member must be used within MYSQLlex() function only. */ const char *m_cpp_text_start; /** Ending position of the TEXT_STRING or IDENT in the pre-processed buffer. NOTE: this member must be used within MYSQLlex() function only. */ const char *m_cpp_text_end; /** Character set specified by the character-set-introducer. NOTE: this member must be used within MYSQLlex() function only. */ CHARSET_INFO *m_underscore_cs; }; /** Abstract representation of a statement. This class is an interface between the parser and the runtime. The parser builds the appropriate sub classes of Sql_statement to represent a SQL statement in the parsed tree. The execute() method in the sub classes contain the runtime implementation. Note that this interface is used for SQL statement recently implemented, the code for older statements tend to load the LEX structure with more attributes instead. The recommended way to implement new statements is to sub-class Sql_statement, as this improves code modularity (see the 'big switch' in dispatch_command()), and decrease the total size of the LEX structure (therefore saving memory in stored programs). */ class Sql_statement : public Sql_alloc { public: /** Execute this SQL statement. @param thd the current thread. @return 0 on success. */ virtual bool execute(THD *thd) = 0; protected: /** Constructor. @param lex the LEX structure that represents parts of this statement. */ Sql_statement(LEX *lex) : m_lex(lex) {} /** Destructor. */ virtual ~Sql_statement() { /* Sql_statement objects are allocated in thd->mem_root. In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is simply destroyed instead. Do not rely on the destructor for any cleanup. */ DBUG_ASSERT(FALSE); } protected: /** The legacy LEX structure for this statement. The LEX structure contains the existing properties of the parsed tree. TODO: with time, attributes from LEX should move to sub classes of Sql_statement, so that the parser only builds Sql_statement objects with the minimum set of attributes, instead of a LEX structure that contains the collection of every possible attribute. */ LEX *m_lex; }; class Delete_plan; class SQL_SELECT; class Explain_query; class Explain_update; class Explain_delete; /* Query plan of a single-table UPDATE. (This is actually a plan for single-table DELETE also) */ class Update_plan { protected: bool impossible_where; bool no_partitions; public: /* Allocate things there */ MEM_ROOT *mem_root; TABLE *table; SQL_SELECT *select; uint index; ha_rows scanned_rows; /* Top-level select_lex. Most of its fields are not used, we need it only to get to the subqueries. */ SELECT_LEX *select_lex; key_map possible_keys; bool using_filesort; bool using_io_buffer; /* Set this plan to be a plan to do nothing because of impossible WHERE */ void set_impossible_where() { impossible_where= true; } void set_no_partitions() { no_partitions= true; } Explain_update* save_explain_update_data(THD *thd, MEM_ROOT *mem_root); protected: bool save_explain_data_intern(THD *thd, MEM_ROOT *mem_root, Explain_update *eu, bool is_analyze); public: virtual ~Update_plan() = default; Update_plan(MEM_ROOT *mem_root_arg) : impossible_where(false), no_partitions(false), mem_root(mem_root_arg), using_filesort(false), using_io_buffer(false) {} }; /* Query plan of a single-table DELETE */ class Delete_plan : public Update_plan { bool deleting_all_rows; public: /* Construction functions */ Delete_plan(MEM_ROOT *mem_root_arg) : Update_plan(mem_root_arg), deleting_all_rows(false) {} /* Set this query plan to be a plan to make a call to h->delete_all_rows() */ void set_delete_all_rows(ha_rows rows_arg) { deleting_all_rows= true; scanned_rows= rows_arg; } void cancel_delete_all_rows() { deleting_all_rows= false; } Explain_delete* save_explain_delete_data(THD *thd, MEM_ROOT *mem_root); }; enum account_lock_type { ACCOUNTLOCK_UNSPECIFIED= 0, ACCOUNTLOCK_LOCKED, ACCOUNTLOCK_UNLOCKED }; enum password_exp_type { PASSWORD_EXPIRE_UNSPECIFIED= 0, PASSWORD_EXPIRE_NOW, PASSWORD_EXPIRE_NEVER, PASSWORD_EXPIRE_DEFAULT, PASSWORD_EXPIRE_INTERVAL }; struct Account_options: public USER_RESOURCES { Account_options() = default; void reset() { bzero(this, sizeof(*this)); ssl_type= SSL_TYPE_NOT_SPECIFIED; } enum SSL_type ssl_type; // defined in violite.h LEX_CSTRING x509_subject, x509_issuer, ssl_cipher; account_lock_type account_locked; password_exp_type password_expire; longlong num_expiration_days; }; class Query_arena_memroot; /* The state of the lex parsing. This is saved in the THD struct */ class Lex_prepared_stmt { Lex_ident_sys m_name; // Statement name (in all queries) Item *m_code; // PREPARE or EXECUTE IMMEDIATE source expression List<Item> m_params; // List of parameters for EXECUTE [IMMEDIATE] public: Lex_prepared_stmt() :m_code(NULL) { } const Lex_ident_sys &name() const { return m_name; } uint param_count() const { return m_params.elements; } List<Item> ¶ms() { return m_params; } void set(const Lex_ident_sys_st &ident, Item *code, List<Item> *params) { DBUG_ASSERT(m_params.elements == 0); m_name= ident; m_code= code; if (params) m_params= *params; } bool params_fix_fields(THD *thd) { // Fix Items in the EXECUTE..USING list List_iterator_fast<Item> param_it(m_params); while (Item *param= param_it++) { if (param->fix_fields_if_needed_for_scalar(thd, 0)) return true; } return false; } bool get_dynamic_sql_string(THD *thd, LEX_CSTRING *dst, String *buffer); void lex_start() { m_params.empty(); } }; class Lex_grant_object_name: public Grant_object_name, public Sql_alloc { public: Lex_grant_object_name(Table_ident *table_ident) :Grant_object_name(table_ident) { } Lex_grant_object_name(const LEX_CSTRING &db, Type type) :Grant_object_name(db, type) { } }; class Lex_grant_privilege: public Grant_privilege, public Sql_alloc { public: Lex_grant_privilege() {} Lex_grant_privilege(privilege_t grant, bool all_privileges= false) :Grant_privilege(grant, all_privileges) { } }; class sp_lex_local; class sp_lex_cursor; struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ SELECT_LEX *first_select_lex() { return unit.first_select(); } const SELECT_LEX *first_select_lex() const { return unit.first_select(); } private: SELECT_LEX builtin_select; public: /* current SELECT_LEX in parsing */ SELECT_LEX *current_select; /* list of all SELECT_LEX */ SELECT_LEX *all_selects_list; /* current with clause in parsing if any, otherwise 0*/ With_clause *curr_with_clause; /* pointer to the first with clause in the current statement */ With_clause *with_clauses_list; /* (*with_clauses_list_last_next) contains a pointer to the last with clause in the current statement */ With_clause **with_clauses_list_last_next; /* When a copy of a with element is parsed this is set to the offset of the with element in the input string, otherwise it's set to 0 */ my_ptrdiff_t clone_spec_offset; Create_view_info *create_view; /* Query Plan Footprint of a currently running select */ Explain_query *explain; /* LEX which represents current statement (conventional, SP or PS) For example during view parsing THD::lex will point to the views LEX and lex::stmt_lex will point to LEX of the statement where the view will be included Currently it is used to have always correct select numbering inside statement (LEX::current_select_number) without storing and restoring a global counter which was THD::select_number. TODO: make some unified statement representation (now SP has different) to store such data like LEX::current_select_number. */ LEX *stmt_lex; LEX_CSTRING name; const char *help_arg; const char *backup_dir; /* For RESTORE/BACKUP */ const char* to_log; /* For PURGE MASTER LOGS TO */ String *wild; /* Wildcard in SHOW {something} LIKE 'wild'*/ sql_exchange *exchange; select_result *result; /** @c the two may also hold BINLOG arguments: either comment holds a base64-char string or both represent the BINLOG fragment user variables. */ LEX_CSTRING comment, ident; LEX_USER *grant_user; XID *xid; THD *thd; /* maintain a list of used plugins for this LEX */ DYNAMIC_ARRAY plugins; plugin_ref plugins_static_buffer[INITIAL_LEX_PLUGIN_LIST_SIZE]; /** SELECT of CREATE VIEW statement */ LEX_STRING create_view_select; /** Start of 'ON table', in trigger statements. */ const char* raw_trg_on_table_name_begin; /** End of 'ON table', in trigger statements. */ const char* raw_trg_on_table_name_end; /* Partition info structure filled in by PARTITION BY parse part */ partition_info *part_info; /* The definer of the object being created (view, trigger, stored routine). I.e. the value of DEFINER clause. */ LEX_USER *definer; /* Used in ALTER/CREATE user to store account locking options */ Account_options account_options; Table_type table_type; /* Used for SHOW CREATE */ List<Key_part_spec> ref_list; List<LEX_USER> users_list; List<Item> *insert_list= nullptr,field_list,value_list,update_list; List<List_item> many_values; List<set_var_base> var_list; List<set_var_base> stmt_var_list; //SET_STATEMENT values List<set_var_base> old_var_list; // SET STATEMENT old values private: Query_arena_memroot *arena_for_set_stmt; MEM_ROOT *mem_root_for_set_stmt; bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock, class sp_label **splabel); bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive); bool sp_exit_block(THD *thd, sp_label *lab); bool sp_exit_block(THD *thd, sp_label *lab, Item *when, const LEX_CSTRING &expr_str); bool sp_continue_loop(THD *thd, sp_label *lab); bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop); /* Check if Item_field and Item_ref are allowed in the current statement. @retval false OK (fields are allowed) @retval true ERROR (fields are not allowed). Error is raised. */ bool check_expr_allows_fields_or_error(THD *thd, const char *name) const; protected: bool sp_continue_loop(THD *thd, sp_label *lab, Item *when, const LEX_CSTRING &expr_str); public: void parse_error(uint err_number= ER_SYNTAX_ERROR); inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;} bool set_arena_for_set_stmt(Query_arena *backup); void reset_arena_for_set_stmt(Query_arena *backup); void free_arena_for_set_stmt(); void print(String *str, enum_query_type qtype); List<Item_func_set_user_var> set_var_list; // in-query assignment list List<Item_param> param_list; List<LEX_CSTRING> view_list; // view list (list of field names in view) List<LEX_STRING> *column_list; // list of column names (in ANALYZE) List<LEX_STRING> *index_list; // list of index names (in ANALYZE) /* A stack of name resolution contexts for the query. This stack is used at parse time to set local name resolution contexts for various parts of a query. For example, in a JOIN ... ON (some_condition) clause the Items in 'some_condition' must be resolved only against the operands of the join, and not against the whole clause. Similarly, Items in subqueries should be resolved against the subqueries (and outer queries). The stack is used in the following way: when the parser detects that all Items in some clause need a local context, it creates a new context and pushes it on the stack. All newly created Items always store the top-most context in the stack. Once the parser leaves the clause that required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1]; uint select_stack_top; /* Usually this is set to 0, but for INSERT/REPLACE SELECT it is set to 1. When parsing such statements the pointer to the most outer select is placed into the second element of select_stack rather than into the first. */ uint select_stack_outer_barrier; SQL_I_List<ORDER> proc_list; SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list; Column_definition *last_field; Table_function_json_table *json_table; Item_sum *in_sum_func; udf_func udf; HA_CHECK_OPT check_opt; // check/repair options Table_specification_st create_info; Key *last_key; LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_SERVER_OPTIONS server_options; LEX_CSTRING relay_log_connection_name; LEX_RESET_SLAVE reset_slave_info; ulonglong type; ulong next_binlog_file_number; /* The following is used by KILL */ killed_state kill_signal; killed_type kill_type; uint current_select_number; // valid for statment LEX (not view) /* The following bool variables should not be bit fields as they are not reset for every query */ bool autocommit; // Often used, better as bool bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling /* Bit fields, reset for every query */ bool is_shutdown_wait_for_slaves:1; bool selects_allow_procedure:1; /* A special command "PARSE_VCOL_EXPR" is defined for the parser to translate a defining expression of a virtual column into an Item object. The following flag is used to prevent other applications to use this command. */ bool parse_vcol_expr:1; bool analyze_stmt:1; /* TRUE<=> this is "ANALYZE $stmt" */ bool explain_json:1; /* true <=> The parsed fragment requires resolution of references to CTE at the end of parsing. This name resolution process involves searching for possible dependencies between CTE defined in the parsed fragment and detecting possible recursive references. The flag is set to true if the fragment contains CTE definitions. */ bool with_cte_resolution:1; /* true <=> only resolution of references to CTE are required in the parsed fragment, no checking of dependencies between CTE is required. This flag is used only when parsing clones of CTE specifications. */ bool only_cte_resolution:1; bool local_file:1; bool check_exists:1; bool verbose:1, no_write_to_binlog:1; bool safe_to_cache_query:1; bool ignore:1; bool next_is_main:1; // use "main" SELECT_LEX for nrxt allocation; bool next_is_down:1; // use "main" SELECT_LEX for nrxt allocation; /* field_list was created for view and should be removed before PS/SP rexecuton */ bool empty_field_list_on_rset:1; /** During name resolution search only in the table list given by Name_resolution_context::first_name_resolution_table and Name_resolution_context::last_name_resolution_table (see Item_field::fix_fields()). */ bool use_only_table_context:1; bool escape_used:1; bool default_used:1; /* using default() function */ bool with_rownum:1; /* Using rownum() function */ bool is_lex_started:1; /* If lex_start() did run. For debugging. */ bool without_validation:1; /* exchange or convert partition WITHOUT VALIDATION */ /* This variable is used in post-parse stage to declare that sum-functions, or functions which have sense only if GROUP BY is present, are allowed. For example in a query SELECT ... FROM ...WHERE MIN(i) == 1 GROUP BY ... HAVING MIN(i) > 2 MIN(i) in the WHERE clause is not allowed in the opposite to MIN(i) in the HAVING clause. Due to possible nesting of select construct the variable can contain 0 or 1 for each nest level. */ nesting_map allow_sum_func; Sql_cmd *m_sql_cmd; /* Usually `expr` rule of yacc is quite reused but some commands better not support subqueries which comes standard with this rule, like KILL, HA_READ, CREATE/ALTER EVENT etc. Set this to a non-NULL clause name to get an error. */ const char *clause_that_disallows_subselect; enum enum_duplicates duplicates; enum enum_tx_isolation tx_isolation; enum enum_ha_read_modes ha_read_mode; union { enum ha_rkey_function ha_rkey_mode; enum xa_option_words xa_opt; bool with_admin_option; // GRANT role bool with_persistent_for_clause; // uses PERSISTENT FOR clause (in ANALYZE) }; enum enum_var_type option_type; enum enum_drop_mode drop_mode; enum backup_stages backup_stage; enum Foreign_key::fk_match_opt fk_match_option; enum_fk_option fk_update_opt; enum_fk_option fk_delete_opt; enum enum_yes_no_unknown tx_chain, tx_release; st_parsing_options parsing_options; /* In sql_cache we store SQL_CACHE flag as specified by user to be able to restore SELECT statement from internal structures. */ enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE }; e_sql_cache sql_cache; uint slave_thd_opt, start_transaction_opt; uint profile_query_id; uint profile_options; int nest_level; /* In LEX representing update which were transformed to multi-update stores total number of tables. For LEX representing multi-delete holds number of tables from which we will delete records. */ uint table_count_update; uint8 describe; /* A flag that indicates what kinds of derived tables are present in the query (0 if no derived tables, otherwise a combination of flags DERIVED_SUBQUERY and DERIVED_VIEW). */ uint8 derived_tables; uint8 context_analysis_only; uint8 lex_options; // see OPTION_LEX_* Alter_info alter_info; Lex_prepared_stmt prepared_stmt; /* For CREATE TABLE statement last element of table list which is not part of SELECT or LIKE part (i.e. either element for table we are creating or last of tables referenced by foreign keys). */ TABLE_LIST *create_last_non_select_table; sp_head *sphead; sp_name *spname; MEM_ROOT sp_mem_root, *sp_mem_root_ptr; sp_pcontext *spcont; st_sp_chistics sp_chistics; Event_parse_data *event_parse_data; /* Characterstics of trigger being created */ st_trg_chistics trg_chistics; /* stmt_definition_begin is intended to point to the next word after DEFINER-clause in the following statements: - CREATE TRIGGER (points to "TRIGGER"); - CREATE PROCEDURE (points to "PROCEDURE"); - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); - CREATE EVENT (points to "EVENT") This pointer is required to add possibly omitted DEFINER-clause to the DDL-statement before dumping it to the binlog. keyword_delayed_begin_offset is the offset to the beginning of the DELAYED keyword in INSERT DELAYED statement. keyword_delayed_end_offset is the offset to the character right after the DELAYED keyword. */ union { const char *stmt_definition_begin; uint keyword_delayed_begin_offset; }; union { const char *stmt_definition_end; uint keyword_delayed_end_offset; }; /** Collects create options for KEY */ engine_option_value *option_list; /** Helper pointer to the end of the list when parsing options for LEX::create_info.option_list (for table) LEX::last_field->option_list (for fields) LEX::option_list (for indexes) */ engine_option_value *option_list_last; /* The set of those tables whose fields are referenced in all subqueries of the query. TODO: possibly this it is incorrect to have used tables in LEX because with subquery, it is not clear what does the field mean. To fix this we should aggregate used tables information for selected expressions into the select_lex. */ table_map used_tables; /** Maximum number of rows and/or keys examined by the query, both read, changed or written. This is the argument of LIMIT ROWS EXAMINED. The limit is represented by two variables - the Item is needed because in case of parameters we have to delay its evaluation until execution. Once evaluated, its value is stored in examined_rows_limit_cnt. */ Item *limit_rows_examined; ulonglong limit_rows_examined_cnt; /** Holds a set of domain_ids for deletion at FLUSH..DELETE_DOMAIN_ID */ DYNAMIC_ARRAY delete_gtid_domain; static const ulong initial_gtid_domain_buffer_size= 16; uint32 gtid_domain_static_buffer[initial_gtid_domain_buffer_size]; /* Activates enforcement of the LIMIT ROWS EXAMINED clause, if present in the query. */ bool has_returning_list; void set_limit_rows_examined() { if (limit_rows_examined) limit_rows_examined_cnt= limit_rows_examined->val_uint(); } /** Deactivates enforcement of the LIMIT ROWS EXAMINED clause and returns its prior state. Return value: - false: LIMIT ROWS EXAMINED was not activated - true: LIMIT ROWS EXAMINED was activated */ bool deactivate_limit_rows_examined() { bool was_activated= (limit_rows_examined_cnt != ULONGLONG_MAX); limit_rows_examined_cnt= ULONGLONG_MAX; // Unreachable value return was_activated; } LEX_CSTRING *win_ref; Window_frame *win_frame; Window_frame_bound *frame_top_bound; Window_frame_bound *frame_bottom_bound; Window_spec *win_spec; Item *upd_del_where; /* System Versioning */ vers_select_conds_t vers_conditions; vers_select_conds_t period_conditions; inline void free_set_stmt_mem_root() { DBUG_ASSERT(!is_arena_for_set_stmt()); if (mem_root_for_set_stmt) { free_root(mem_root_for_set_stmt, MYF(0)); delete mem_root_for_set_stmt; mem_root_for_set_stmt= 0; } } LEX(); virtual ~LEX() { free_set_stmt_mem_root(); destroy_query_tables_list(); plugin_unlock_list(NULL, (plugin_ref *)plugins.buffer, plugins.elements); delete_dynamic(&plugins); } virtual class Query_arena *query_arena() { DBUG_ASSERT(0); return NULL; } void start(THD *thd); inline bool is_ps_or_view_context_analysis() { return (context_analysis_only & (CONTEXT_ANALYSIS_ONLY_PREPARE | CONTEXT_ANALYSIS_ONLY_VCOL_EXPR | CONTEXT_ANALYSIS_ONLY_VIEW)); } inline bool is_view_context_analysis() { return (context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW); } /** Mark all queries in this lex structure as uncacheable for the cause given @param cause the reason queries are to be marked as uncacheable Note, any cause is sufficient for st_select_lex_unit::can_be_merged() to disallow query merges. */ inline void uncacheable(uint8 cause) { safe_to_cache_query= 0; if (current_select) // initialisation SP variables has no SELECT { /* There are no sense to mark select_lex and union fields of LEX, but we should merk all subselects as uncacheable from current till most upper */ SELECT_LEX *sl; SELECT_LEX_UNIT *un; for (sl= current_select, un= sl->master_unit(); un && un != &unit; sl= sl->outer_select(), un= (sl ? sl->master_unit() : NULL)) { sl->uncacheable|= cause; un->uncacheable|= cause; } if (sl) sl->uncacheable|= cause; } if (first_select_lex()) first_select_lex()->uncacheable|= cause; } void set_trg_event_type_for_tables(); TABLE_LIST *unlink_first_table(bool *link_to_local); void link_first_table_back(TABLE_LIST *first, bool link_to_local); void first_lists_tables_same(); void fix_first_select_number(); bool can_be_merged(); bool can_use_merged(); bool can_not_use_merged(); bool only_view_structure(); bool need_correct_ident(); uint8 get_effective_with_check(TABLE_LIST *view); /* Is this update command where 'WHITH CHECK OPTION' clause is important SYNOPSIS LEX::which_check_option_applicable() RETURN TRUE have to take 'WHITH CHECK OPTION' clause into account FALSE 'WHITH CHECK OPTION' clause do not need */ inline bool which_check_option_applicable() { switch (sql_command) { case SQLCOM_UPDATE: case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE: case SQLCOM_DELETE_MULTI: case SQLCOM_INSERT: case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: case SQLCOM_LOAD: return TRUE; default: return FALSE; } } void cleanup_after_one_table_open(); bool push_context(Name_resolution_context *context); Name_resolution_context *pop_context(); SELECT_LEX *select_stack_head() { if (likely(select_stack_top)) return select_stack[select_stack_top - 1]; return NULL; } bool push_select(SELECT_LEX *select_lex) { DBUG_ENTER("LEX::push_select"); DBUG_PRINT("info", ("Top Select was %p (%d) depth: %u pushed: %p (%d)", select_stack_head(), select_stack_top, (select_stack_top ? select_stack_head()->select_number : 0), select_lex, select_lex->select_number)); DBUG_ASSERT(select_lex); if (unlikely(select_stack_top > MAX_SELECT_NESTING)) { my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0)); DBUG_RETURN(TRUE); } if (push_context(&select_lex->context)) DBUG_RETURN(TRUE); select_stack[select_stack_top++]= select_lex; current_select= select_lex; DBUG_RETURN(FALSE); } SELECT_LEX *pop_select() { DBUG_ENTER("LEX::pop_select"); SELECT_LEX *select_lex; if (likely(select_stack_top)) select_lex= select_stack[--select_stack_top]; else select_lex= 0; DBUG_PRINT("info", ("Top Select is %p (%d) depth: %u poped: %p (%d)", select_stack_head(), select_stack_top, (select_stack_top ? select_stack_head()->select_number : 0), select_lex, (select_lex ? select_lex->select_number : 0))); DBUG_ASSERT(select_lex); pop_context(); if (unlikely(!select_stack_top)) { current_select= &builtin_select; DBUG_PRINT("info", ("Top Select is empty -> sel builtin: %p service: %u", current_select, builtin_select.is_service_select)); builtin_select.is_service_select= false; } else current_select= select_stack[select_stack_top - 1]; DBUG_RETURN(select_lex); } SELECT_LEX *current_select_or_default() { return current_select ? current_select : &builtin_select; } bool copy_db_to(LEX_CSTRING *to); void inc_select_stack_outer_barrier() { select_stack_outer_barrier++; } SELECT_LEX *parser_current_outer_select() { return select_stack_top - 1 == select_stack_outer_barrier ? 0 : select_stack[select_stack_top - 2]; } Name_resolution_context *current_context() { return context_stack.head(); } /* Restore the LEX and THD in case of a parse error. */ static void cleanup_lex_after_parse_error(THD *thd); void reset_n_backup_query_tables_list(Query_tables_list *backup); void restore_backup_query_tables_list(Query_tables_list *backup); bool table_or_sp_used(); bool is_partition_management() const; #ifdef WITH_PARTITION_STORAGE_ENGINE bool part_values_current(THD *thd); bool part_values_history(THD *thd); #endif /** @brief check if the statement is a single-level join @return result of the check @retval TRUE The statement doesn't contain subqueries, unions and stored procedure calls. @retval FALSE There are subqueries, UNIONs or stored procedure calls. */ bool is_single_level_stmt() { /* This check exploits the fact that the last added to all_select_list is on its top. So select_lex (as the first added) will be at the tail of the list. */ if (first_select_lex() == all_selects_list && !sroutines.records) { return TRUE; } return FALSE; } bool save_prep_leaf_tables(); int print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze, bool is_json_format, bool *printed_anything); bool restore_set_statement_var(); void init_last_field(Column_definition *field, const LEX_CSTRING *name); bool last_field_generated_always_as_row_start_or_end(Lex_ident *p, const char *type, uint flags); bool last_field_generated_always_as_row_start(); bool last_field_generated_always_as_row_end(); bool new_sp_instr_stmt(THD *, const LEX_CSTRING &prefix, const LEX_CSTRING &suffix); bool sp_proc_stmt_statement_finalize_buf(THD *, const LEX_CSTRING &qbuf); bool sp_proc_stmt_statement_finalize(THD *, bool no_lookahead); sp_variable *sp_param_init(LEX_CSTRING *name); bool sp_param_fill_definition(sp_variable *spvar, const Lex_field_type_st &def); bool sf_return_fill_definition(const Lex_field_type_st &def); int case_stmt_action_then(); bool setup_select_in_parentheses(); bool set_names(const char *pos, CHARSET_INFO *cs, const Lex_extended_collation_st &coll, bool no_lookahead); bool set_trigger_new_row(const LEX_CSTRING *name, Item *val, const LEX_CSTRING &expr_str); bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2, Item *val, const LEX_CSTRING &expr_str); bool set_system_variable(enum_var_type var_type, sys_var *var, const Lex_ident_sys_st *base_name, Item *val); bool set_system_variable(enum_var_type var_type, const Lex_ident_sys_st *name, Item *val); bool set_system_variable(THD *thd, enum_var_type var_type, const Lex_ident_sys_st *name1, const Lex_ident_sys_st *name2, Item *val); bool set_default_system_variable(enum_var_type var_type, const Lex_ident_sys_st *name, Item *val); bool set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val); void set_stmt_init(); sp_name *make_sp_name(THD *thd, const Lex_ident_sys_st &name); sp_name *make_sp_name(THD *thd, const Lex_ident_sys_st &name1, const Lex_ident_sys_st &name2); sp_name *make_sp_name_package_routine(THD *thd, const Lex_ident_sys_st &name); sp_lex_local *package_routine_start(THD *thd, const Sp_handler *sph, const Lex_ident_sys_st &name); sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph, enum_sp_aggregate_type agg_type); sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name, const Sp_handler *sph, enum_sp_aggregate_type agg_type); bool sp_body_finalize_routine(THD *); bool sp_body_finalize_trigger(THD *); bool sp_body_finalize_event(THD *); bool sp_body_finalize_function(THD *); bool sp_body_finalize_procedure(THD *); bool sp_body_finalize_procedure_standalone(THD *, const sp_name *end_name); sp_package *create_package_start(THD *thd, const Sp_handler *sph, const sp_name *name, DDL_options_st options, const st_sp_chistics &chistics); bool create_package_finalize(THD *thd, const sp_name *name, const sp_name *name2, const char *cpp_body_end); bool show_routine_code_start(THD *thd, enum_sql_command cmd, sp_name *name); bool call_statement_start(THD *thd, sp_name *name); bool call_statement_start(THD *thd, const Lex_ident_sys_st *name); bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1, const Lex_ident_sys_st *name2); bool call_statement_start(THD *thd, const Lex_ident_sys_st *db, const Lex_ident_sys_st *pkg, const Lex_ident_sys_st *proc); sp_variable *find_variable(const LEX_CSTRING *name, sp_pcontext **ctx, const Sp_rcontext_handler **rh) const; sp_variable *find_variable(const LEX_CSTRING *name, const Sp_rcontext_handler **rh) const { sp_pcontext *not_used_ctx; return find_variable(name, ¬_used_ctx, rh); } sp_fetch_target *make_fetch_target(THD *thd, const Lex_ident_sys_st &name); bool set_variable(const Lex_ident_sys_st *name, Item *item, const LEX_CSTRING &expr_str); bool set_variable(const Lex_ident_sys_st *name1, const Lex_ident_sys_st *name2, Item *item, const LEX_CSTRING &expr_str); void sp_variable_declarations_init(THD *thd, int nvars); bool sp_variable_declarations_finalize(THD *thd, int nvars, const Column_definition *cdef, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_row_finalize(THD *thd, int nvars, Row_definition_list *row, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars, Qualified_column_ident *col, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars, Qualified_column_ident *, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars, uint offset, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars, const LEX_CSTRING &db, const LEX_CSTRING &table, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_column_type_finalize(THD *thd, int nvars, const Qualified_column_ident *ref, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_vartype_finalize(THD *thd, int nvars, const LEX_CSTRING &name, Item *def, const LEX_CSTRING &expr_str); bool sp_variable_declarations_copy_type_finalize(THD *thd, int nvars, const Column_definition &ref, Row_definition_list *fields, Item *def, const LEX_CSTRING &expr_str); LEX_USER *current_user_for_set_password(THD *thd); bool sp_create_set_password_instr(THD *thd, LEX_USER *user, USER_AUTH *auth, bool no_lookahead); bool sp_create_set_password_instr(THD *thd, USER_AUTH *auth, bool no_lookahead) { LEX_USER *user; return !(user= current_user_for_set_password(thd)) || sp_create_set_password_instr(thd, user, auth, no_lookahead); } bool sp_handler_declaration_init(THD *thd, int type); bool sp_handler_declaration_finalize(THD *thd, int type); bool sp_declare_cursor(THD *thd, const LEX_CSTRING *name, class sp_lex_cursor *cursor_stmt, sp_pcontext *param_ctx, bool add_cpush_instr); bool sp_open_cursor(THD *thd, const LEX_CSTRING *name, List<sp_assignment_lex> *parameters); Item_splocal *create_item_for_sp_var(const Lex_ident_cli_st *name, sp_variable *spvar); Item *create_item_qualified_asterisk(THD *thd, const Lex_ident_sys_st *name); Item *create_item_qualified_asterisk(THD *thd, const Lex_ident_sys_st *a, const Lex_ident_sys_st *b); Item *create_item_qualified_asterisk(THD *thd, const Lex_ident_cli_st *cname) { Lex_ident_sys name(thd, cname); if (name.is_null()) return NULL; // EOM return create_item_qualified_asterisk(thd, &name); } Item *create_item_qualified_asterisk(THD *thd, const Lex_ident_cli_st *ca, const Lex_ident_cli_st *cb) { Lex_ident_sys a(thd, ca), b(thd, cb); if (a.is_null() || b.is_null()) return NULL; // EOM return create_item_qualified_asterisk(thd, &a, &b); } Item *create_item_ident_field(THD *thd, const Lex_ident_sys_st &db, const Lex_ident_sys_st &table, const Lex_ident_sys_st &name); Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name) { return create_item_ident_field(thd, Lex_ident_sys(), Lex_ident_sys(), *name); } Item *create_item_ident_sp(THD *thd, Lex_ident_sys_st *name, const char *start, const char *end); Item *create_item_ident(THD *thd, Lex_ident_cli_st *cname) { Lex_ident_sys name(thd, cname); if (name.is_null()) return NULL; // EOM return sphead ? create_item_ident_sp(thd, &name, cname->pos(), cname->end()) : create_item_ident_nosp(thd, &name); } /* Create an Item corresponding to a qualified name: a.b when the parser is out of an SP context. @param THD - THD, for mem_root @param a - the first name @param b - the second name @retval - a pointer to a created item, or NULL on error. Possible Item types that can be created: - Item_trigger_field - Item_field - Item_ref */ Item *create_item_ident_nospvar(THD *thd, const Lex_ident_sys_st *a, const Lex_ident_sys_st *b); /* Create an Item corresponding to a ROW field valiable: var.field @param THD - THD, for mem_root @param rh [OUT] - the rcontext handler (local vs package variables) @param var - the ROW variable name @param field - the ROW variable field name @param spvar - the variable that was previously found by name using "var_name". @param start - position in the query (for binary log) @param end - end in the query (for binary log) */ Item_splocal *create_item_spvar_row_field(THD *thd, const Sp_rcontext_handler *rh, const Lex_ident_sys *var, const Lex_ident_sys *field, sp_variable *spvar, const char *start, const char *end); /* Create an item from its qualified name. Depending on context, it can be either a ROW variable field, or trigger, table field, table field reference. See comments to create_item_spvar_row_field() and create_item_ident_nospvar(). @param thd - THD, for mem_root @param a - the first name @param b - the second name @retval - NULL on error, or a pointer to a new Item. */ Item *create_item_ident(THD *thd, const Lex_ident_cli_st *a, const Lex_ident_cli_st *b); /* Create an item from its qualified name. Depending on context, it can be a table field, a table field reference, or a sequence NEXTVAL and CURRVAL. @param thd - THD, for mem_root @param a - the first name @param b - the second name @param c - the third name @retval - NULL on error, or a pointer to a new Item. */ Item *create_item_ident(THD *thd, const Lex_ident_sys_st *a, const Lex_ident_sys_st *b, const Lex_ident_sys_st *c); Item *create_item_ident(THD *thd, const Lex_ident_cli_st *ca, const Lex_ident_cli_st *cb, const Lex_ident_cli_st *cc) { Lex_ident_sys b(thd, cb), c(thd, cc); if (b.is_null() || c.is_null()) return NULL; if (ca->pos() == cb->pos()) // SELECT .t1.col1 { DBUG_ASSERT(ca->length == 0); Lex_ident_sys none; return create_item_ident(thd, &none, &b, &c); } Lex_ident_sys a(thd, ca); return a.is_null() ? NULL : create_item_ident(thd, &a, &b, &c); } /* Create an item for "NEXT VALUE FOR sequence_name" */ Item *create_item_func_nextval(THD *thd, Table_ident *ident); Item *create_item_func_nextval(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *name); /* Create an item for "PREVIOUS VALUE FOR sequence_name" */ Item *create_item_func_lastval(THD *thd, Table_ident *ident); Item *create_item_func_lastval(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *name); /* Create an item for "SETVAL(sequence_name, value [, is_used [, round]]) */ Item *create_item_func_setval(THD *thd, Table_ident *ident, longlong value, ulonglong round, bool is_used); /* Create an item for a name in LIMIT clause: LIMIT var @param THD - THD, for mem_root @param var_name - the variable name @retval - a new Item corresponding to the SP variable, or NULL on error (non in SP, unknown variable, wrong data type). */ Item *create_item_limit(THD *thd, const Lex_ident_cli_st *var_name); /* Create an item for a qualified name in LIMIT clause: LIMIT var.field @param THD - THD, for mem_root @param var_name - the variable name @param field_name - the variable field name @param start - start in the query (for binary log) @param end - end in the query (for binary log) @retval - a new Item corresponding to the SP variable, or NULL on error (non in SP, unknown variable, unknown ROW field, wrong data type). */ Item *create_item_limit(THD *thd, const Lex_ident_cli_st *var_name, const Lex_ident_cli_st *field_name); Item *create_item_query_expression(THD *thd, st_select_lex_unit *unit); Item *make_item_func_sysdate(THD *thd, uint fsp); static const Schema * find_func_schema_by_name_or_error(const Lex_ident_sys &schema_name, const Lex_ident_sys &func_name); Item *make_item_func_replace(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, Item *org, Item *find, Item *replace); Item *make_item_func_replace(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, List<Item> *args); Item *make_item_func_substr(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, const Lex_substring_spec_st &spec); Item *make_item_func_substr(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, List<Item> *args); Item *make_item_func_trim(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, const Lex_trim_st &spec); Item *make_item_func_trim(THD *thd, const Lex_ident_cli_st &schema_name, const Lex_ident_cli_st &func_name, List<Item> *args); Item *make_item_func_call_generic(THD *thd, const Lex_ident_cli_st *db, const Lex_ident_cli_st *name, List<Item> *args); Item *make_item_func_call_generic(THD *thd, const Lex_ident_sys &db, const Lex_ident_sys &name, List<Item> *args); Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db, Lex_ident_cli_st *pkg, Lex_ident_cli_st *name, List<Item> *args); Item *make_item_func_call_native_or_parse_error(THD *thd, Lex_ident_cli_st &name, List<Item> *args); my_var *create_outvar(THD *thd, const LEX_CSTRING *name); /* Create a my_var instance for a ROW field variable that was used as an OUT SP parameter: CALL p1(var.field); @param THD - THD, for mem_root @param var_name - the variable name @param field_name - the variable field name */ my_var *create_outvar(THD *thd, const LEX_CSTRING *var_name, const LEX_CSTRING *field_name); bool is_trigger_new_or_old_reference(const LEX_CSTRING *name) const; Item *create_and_link_Item_trigger_field(THD *thd, const LEX_CSTRING *name, bool new_row); // For syntax with colon, e.g. :NEW.a or :OLD.a Item *make_item_colon_ident_ident(THD *thd, const Lex_ident_cli_st *a, const Lex_ident_cli_st *b); // PLSQL: cursor%ISOPEN etc Item *make_item_plsql_cursor_attr(THD *thd, const LEX_CSTRING *name, plsql_cursor_attr_t attr); // For "SELECT @@var", "SELECT @@var.field" Item *make_item_sysvar(THD *thd, enum_var_type type, const LEX_CSTRING *name) { return make_item_sysvar(thd, type, name, &null_clex_str); } Item *make_item_sysvar(THD *thd, enum_var_type type, const LEX_CSTRING *name, const LEX_CSTRING *component); void sp_block_init(THD *thd, const LEX_CSTRING *label); void sp_block_init(THD *thd) { // Unlabeled blocks get an empty label sp_block_init(thd, &empty_clex_str); } bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock) { class sp_label *tmp; return sp_block_finalize(thd, spblock, &tmp); } bool sp_block_finalize(THD *thd) { return sp_block_finalize(thd, Lex_spblock()); } bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock, const LEX_CSTRING *end_label); bool sp_block_finalize(THD *thd, const LEX_CSTRING *end_label) { return sp_block_finalize(thd, Lex_spblock(), end_label); } bool sp_declarations_join(Lex_spblock_st *res, const Lex_spblock_st b1, const Lex_spblock_st b2) const { if ((b2.vars || b2.conds) && (b1.curs || b1.hndlrs)) { my_error(ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0)); return true; } if (b2.curs && b1.hndlrs) { my_error(ER_SP_CURSOR_AFTER_HANDLER, MYF(0)); return true; } res->join(b1, b2); return false; } bool sp_block_with_exceptions_finalize_declarations(THD *thd); bool sp_block_with_exceptions_finalize_executable_section(THD *thd, uint executable_section_ip); bool sp_block_with_exceptions_finalize_exceptions(THD *thd, uint executable_section_ip, uint exception_count); bool sp_block_with_exceptions_add_empty(THD *thd); bool sp_exit_statement(THD *thd, Item *when, const LEX_CSTRING &expr_str); bool sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item, const LEX_CSTRING &expr_str); bool sp_leave_statement(THD *thd, const LEX_CSTRING *label_name); bool sp_goto_statement(THD *thd, const LEX_CSTRING *label_name); bool sp_continue_statement(THD *thd); bool sp_continue_statement(THD *thd, const LEX_CSTRING *label_name); bool sp_iterate_statement(THD *thd, const LEX_CSTRING *label_name); bool maybe_start_compound_statement(THD *thd); bool sp_push_loop_label(THD *thd, const LEX_CSTRING *label_name); bool sp_push_loop_empty_label(THD *thd); bool sp_pop_loop_label(THD *thd, const LEX_CSTRING *label_name); void sp_pop_loop_empty_label(THD *thd); bool sp_while_loop_expression(THD *thd, Item *expr, const LEX_CSTRING &expr_str); bool sp_while_loop_finalize(THD *thd); bool sp_if_after_statements(THD *thd); bool sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name); Item_param *add_placeholder(THD *thd, const LEX_CSTRING *name, const char *start, const char *end); /* Integer range FOR LOOP methods */ sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name, Item *value, const LEX_CSTRING &expr_str); sp_variable *sp_add_for_loop_target_bound(THD *thd, Item *value, const LEX_CSTRING &expr_str) { LEX_CSTRING name= { STRING_WITH_LEN("[target_bound]") }; return sp_add_for_loop_variable(thd, &name, value, expr_str); } bool sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop, const LEX_CSTRING *index, const Lex_for_loop_bounds_st &bounds); bool sp_for_loop_intrange_condition_test(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_intrange_iterate(THD *thd, const Lex_for_loop_st &loop); /* Cursor FOR LOOP methods */ bool sp_for_loop_cursor_declarations(THD *thd, Lex_for_loop_st *loop, const LEX_CSTRING *index, const Lex_for_loop_bounds_st &bounds); sp_variable *sp_add_for_loop_cursor_variable(THD *thd, const LEX_CSTRING *name, const class sp_pcursor *cur, uint coffset, sp_assignment_lex *param_lex, Item_args *parameters); bool sp_for_loop_implicit_cursor_statement(THD *thd, Lex_for_loop_bounds_st *bounds, sp_lex_cursor *cur); bool sp_for_loop_cursor_condition_test(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_cursor_iterate(THD *thd, const Lex_for_loop_st &); /* Generic FOR LOOP methods*/ /* Generate FOR loop declarations and initialize "loop" from "index" and "bounds". @param [IN] thd - current THD, for mem_root and error reporting @param [OUT] loop - the loop generated SP variables are stored here, together with additional loop characteristics. @param [IN] index - the loop index variable name @param [IN] bounds - the loop bounds (in sp_assignment_lex format) and additional loop characteristics, as created by the sp_for_loop_bounds rule. @retval true - on error @retval false - on success This methods adds declarations: - An explicit integer or cursor%ROWTYPE "index" variable - An implicit integer upper bound variable, in case of integer range loops - A CURSOR, in case of an implicit CURSOR loops The generated variables are stored into "loop". Additional loop characteristics are copied from "bounds" to "loop". */ bool sp_for_loop_declarations(THD *thd, Lex_for_loop_st *loop, const LEX_CSTRING *index, const Lex_for_loop_bounds_st &bounds) { return bounds.is_for_loop_cursor() ? sp_for_loop_cursor_declarations(thd, loop, index, bounds) : sp_for_loop_intrange_declarations(thd, loop, index, bounds); } /* Generate a conditional jump instruction to leave the loop, using a proper condition depending on the loop type: - Item_func_le -- integer range loops - Item_func_ge -- integer range reverse loops - Item_func_cursor_found -- cursor loops */ bool sp_for_loop_condition_test(THD *thd, const Lex_for_loop_st &loop) { return loop.is_for_loop_cursor() ? sp_for_loop_cursor_condition_test(thd, loop) : sp_for_loop_intrange_condition_test(thd, loop); } /* Generate "increment" instructions followed by a jump to the condition test in the beginnig of the loop. "Increment" depends on the loop type and can be: - index:= index + 1; -- integer range loops - index:= index - 1; -- integer range reverse loops - FETCH cursor INTO index; -- cursor loops */ bool sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop) { if (loop.is_for_loop_cursor() ? sp_for_loop_cursor_iterate(thd, loop) : sp_for_loop_intrange_iterate(thd, loop)) return true; // Generate a jump to the beginning of the loop return sp_while_loop_finalize(thd); } bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop); /* Make an Item when an identifier is found in the FOR loop bounds: FOR rec IN cursor FOR rec IN var1 .. var2 FOR rec IN row1.field1 .. xxx */ Item *create_item_for_loop_bound(THD *thd, const LEX_CSTRING *a, const LEX_CSTRING *b, const LEX_CSTRING *c); /* End of FOR LOOP methods */ bool add_signal_statement(THD *thd, const class sp_condition_value *value); bool add_resignal_statement(THD *thd, const class sp_condition_value *value); // Check if "KEY IF NOT EXISTS name" used outside of ALTER context bool check_add_key(DDL_options_st ddl) { if (ddl.if_not_exists() && sql_command != SQLCOM_ALTER_TABLE) { parse_error(); return true; } return false; } // Add a key as a part of CREATE TABLE or ALTER TABLE bool add_key(Key::Keytype key_type, const LEX_CSTRING *key_name, ha_key_alg algorithm, DDL_options_st ddl) { if (check_add_key(ddl) || !(last_key= new Key(key_type, key_name, algorithm, false, ddl))) return true; alter_info.key_list.push_back(last_key); return false; } // Add a key for a CREATE INDEX statement bool add_create_index(Key::Keytype key_type, const LEX_CSTRING *key_name, ha_key_alg algorithm, DDL_options_st ddl) { if (check_create_options(ddl) || !(last_key= new Key(key_type, key_name, algorithm, false, ddl))) return true; alter_info.key_list.push_back(last_key); return false; } bool add_create_index_prepare(Table_ident *table) { sql_command= SQLCOM_CREATE_INDEX; if (!current_select->add_table_to_list(thd, table, NULL, TL_OPTION_UPDATING, TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE)) return true; alter_info.reset(); alter_info.flags= ALTER_ADD_INDEX; option_list= NULL; return false; } /* Add an UNIQUE or PRIMARY key which is a part of a column definition: CREATE TABLE t1 (a INT PRIMARY KEY); */ void add_key_to_list(LEX_CSTRING *field_name, enum Key::Keytype type, bool check_exists); // Add a constraint as a part of CREATE TABLE or ALTER TABLE bool add_constraint(const LEX_CSTRING &name, Virtual_column_info *constr, bool if_not_exists) { constr->name= name; constr->if_not_exists= if_not_exists; alter_info.check_constraint_list.push_back(constr); return false; } bool add_alter_list(LEX_CSTRING par_name, Virtual_column_info *expr, bool par_exists); bool add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name, bool exists); bool add_alter_list_item_convert_to_charset(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs) { if (create_info.add_table_option_convert_charset(used, map, cs)) return true; alter_info.flags|= ALTER_CONVERT_TO; return false; } bool add_alter_list_item_convert_to_charset(Sql_used *used, const Charset_collation_map_st &map, CHARSET_INFO *cs, const Lex_extended_collation_st &cl) { if (create_info.add_table_option_convert_charset(used, map, cs) || create_info.add_table_option_convert_collation(used, map, cl)) return true; alter_info.flags|= ALTER_CONVERT_TO; return false; } void set_command(enum_sql_command command, DDL_options_st options) { sql_command= command; create_info.set(options); } void set_command(enum_sql_command command, uint scope, DDL_options_st options) { set_command(command, options); create_info.options|= scope; // HA_LEX_CREATE_TMP_TABLE or 0 } bool check_create_options(DDL_options_st options) { if (options.or_replace() && options.if_not_exists()) { my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", "IF NOT EXISTS"); return true; } return false; } bool set_create_options_with_check(DDL_options_st options) { create_info.set(options); return check_create_options(create_info); } bool add_create_options_with_check(DDL_options_st options) { create_info.add(options); return check_create_options(create_info); } sp_instr_cfetch *sp_add_instr_cfetch(THD *thd, const LEX_CSTRING *name); bool sp_add_agg_cfetch(); bool set_command_with_check(enum_sql_command command, uint scope, DDL_options_st options) { set_command(command, scope, options); return check_create_options(options); } bool set_command_with_check(enum_sql_command command, DDL_options_st options) { set_command(command, options); return check_create_options(options); } /* DROP shares lex->create_info to store TEMPORARY and IF EXISTS options to save on extra initialization in lex_start(). Add some wrappers, to avoid direct use of lex->create_info in the caller code processing DROP statements (which might look confusing). */ bool tmp_table() const { return create_info.tmp_table(); } bool if_exists() const { return create_info.if_exists(); } /* Run specified phases for derived tables/views in the given list @param table_list - list of derived tables/view to handle @param phase - phases to process tables/views through @details This method runs phases specified by the 'phases' on derived tables/views found in the 'table_list' with help of the TABLE_LIST::handle_derived function. 'this' is passed as an argument to the TABLE_LIST::handle_derived. @return false - ok @return true - error */ bool handle_list_of_derived(TABLE_LIST *table_list, uint phases) { for (TABLE_LIST *tl= table_list; tl; tl= tl->next_local) { if (tl->is_view_or_derived() && tl->handle_derived(this, phases)) return true; } return false; } bool create_like() const { DBUG_ASSERT(!create_info.like() || !first_select_lex()->item_list.elements); return create_info.like(); } bool create_select() const { DBUG_ASSERT(!create_info.like() || !first_select_lex()->item_list.elements); return first_select_lex()->item_list.elements; } bool create_simple() const { return !create_like() && !create_select(); } SELECT_LEX *exclude_last_select(); SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude); void check_automatic_up(enum sub_select_type type); bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident); bool add_alter_view(THD *thd, uint16 algorithm, enum_view_suid suid, Table_ident *table_ident); bool add_create_view(THD *thd, DDL_options_st ddl, uint16 algorithm, enum_view_suid suid, Table_ident *table_ident); bool add_grant_command(THD *thd, const List<LEX_COLUMN> &columns); bool stmt_grant_table(THD *thd, Grant_privilege *grant, const Lex_grant_object_name &ident, privilege_t grant_option); bool stmt_revoke_table(THD *thd, Grant_privilege *grant, const Lex_grant_object_name &ident); bool stmt_grant_sp(THD *thd, Grant_privilege *grant, const Lex_grant_object_name &ident, const Sp_handler &sph, privilege_t grant_option); bool stmt_revoke_sp(THD *thd, Grant_privilege *grant, const Lex_grant_object_name &ident, const Sp_handler &sph); bool stmt_grant_proxy(THD *thd, LEX_USER *user, privilege_t grant_option); bool stmt_revoke_proxy(THD *thd, LEX_USER *user); Vers_parse_info &vers_get_info() { return create_info.vers_info; } /* The list of history-generating DML commands */ bool vers_history_generating() const { switch (sql_command) { case SQLCOM_DELETE: return !vers_conditions.delete_history; case SQLCOM_UPDATE: case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE_MULTI: case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: return true; case SQLCOM_INSERT: case SQLCOM_INSERT_SELECT: return duplicates == DUP_UPDATE; case SQLCOM_LOAD: return duplicates == DUP_REPLACE; default: /* Row injections (i.e. row binlog events and BINLOG statements) should generate history. */ return is_stmt_row_injection(); } } int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end) { if (check_column_name(name)) { my_error(ER_WRONG_COLUMN_NAME, MYF(0), name.str); return 1; } if (lex_string_cmp(system_charset_info, &start, &end) == 0) { my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), start.str); return 1; } Table_period_info &info= create_info.period_info; if (check_exists && info.name.streq(name)) return 0; if (info.is_set()) { my_error(ER_MORE_THAN_ONE_PERIOD, MYF(0)); return 1; } info.set_period(start, end); info.name= name; info.constr= new Virtual_column_info(); info.constr->expr= lt_creator.create(thd, create_item_ident_nosp(thd, &start), create_item_ident_nosp(thd, &end)); add_constraint(null_clex_str, info.constr, false); return 0; } sp_package *get_sp_package() const; /** Check if the select is a simple select (not an union). @retval 0 ok @retval 1 error ; In this case the error messege is sent to the client */ bool check_simple_select(const LEX_CSTRING *option) { if (current_select != &builtin_select) { char command[80]; strmake(command, option->str, MY_MIN(option->length, sizeof(command)-1)); my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); return true; } return false; } SELECT_LEX_UNIT *alloc_unit(); SELECT_LEX *alloc_select(bool is_select); SELECT_LEX_UNIT *create_unit(SELECT_LEX*); SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit); SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel); void init_select() { current_select->init_select(); wild= 0; exchange= 0; } bool main_select_push(bool service= false); bool insert_select_hack(SELECT_LEX *sel); SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest, SELECT_LEX *attach_to); bool set_main_unit(st_select_lex_unit *u) { unit.options= u->options; unit.uncacheable= u->uncacheable; unit.register_select_chain(u->first_select()); unit.first_select()->options|= builtin_select.options; unit.fake_select_lex= u->fake_select_lex; unit.union_distinct= u->union_distinct; unit.set_with_clause(u->with_clause); builtin_select.exclude_from_global(); return false; } bool check_main_unit_semantics(); SELECT_LEX_UNIT *parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2, enum sub_select_type unit_type, bool distinct); SELECT_LEX_UNIT *parsed_select_expr_cont(SELECT_LEX_UNIT *unit, SELECT_LEX *s2, enum sub_select_type unit_type, bool distinct, bool oracle); bool parsed_multi_operand_query_expression_body(SELECT_LEX_UNIT *unit); SELECT_LEX_UNIT *add_tail_to_query_expression_body(SELECT_LEX_UNIT *unit, Lex_order_limit_lock *l); SELECT_LEX_UNIT * add_tail_to_query_expression_body_ext_parens(SELECT_LEX_UNIT *unit, Lex_order_limit_lock *l); SELECT_LEX_UNIT *parsed_body_ext_parens_primary(SELECT_LEX_UNIT *unit, SELECT_LEX *primary, enum sub_select_type unit_type, bool distinct); SELECT_LEX_UNIT * add_primary_to_query_expression_body(SELECT_LEX_UNIT *unit, SELECT_LEX *sel, enum sub_select_type unit_type, bool distinct, bool oracle); SELECT_LEX_UNIT * add_primary_to_query_expression_body(SELECT_LEX_UNIT *unit, SELECT_LEX *sel, enum sub_select_type unit_type, bool distinct); SELECT_LEX_UNIT * add_primary_to_query_expression_body_ext_parens( SELECT_LEX_UNIT *unit, SELECT_LEX *sel, enum sub_select_type unit_type, bool distinct); SELECT_LEX *parsed_subselect(SELECT_LEX_UNIT *unit); bool parsed_insert_select(SELECT_LEX *firs_select); void save_values_list_state(); void restore_values_list_state(); bool parsed_TVC_start(); SELECT_LEX *parsed_TVC_end(); TABLE_LIST *parsed_derived_table(SELECT_LEX_UNIT *unit, int for_system_time, LEX_CSTRING *alias); bool parsed_create_view(SELECT_LEX_UNIT *unit, int check); bool select_finalize(st_select_lex_unit *expr); bool select_finalize(st_select_lex_unit *expr, Lex_select_lock l); void relink_hack(st_select_lex *select_lex); bool stmt_install_plugin(const DDL_options_st &opt, const Lex_ident_sys_st &name, const LEX_CSTRING &soname); void stmt_install_plugin(const LEX_CSTRING &soname); bool stmt_uninstall_plugin_by_name(const DDL_options_st &opt, const Lex_ident_sys_st &name); bool stmt_uninstall_plugin_by_soname(const DDL_options_st &opt, const LEX_CSTRING &soname); bool stmt_prepare_validate(const char *stmt_type); bool stmt_prepare(const Lex_ident_sys_st &ident, Item *code); bool stmt_execute(const Lex_ident_sys_st &ident, List<Item> *params); bool stmt_execute_immediate(Item *code, List<Item> *params); void stmt_deallocate_prepare(const Lex_ident_sys_st &ident); bool stmt_alter_table_exchange_partition(Table_ident *table); bool stmt_alter_table(Table_ident *table); void stmt_purge_to(const LEX_CSTRING &to); bool stmt_purge_before(Item *item); SELECT_LEX *returning() { return &builtin_select; } bool has_returning() { return has_returning_list; } private: bool stmt_create_routine_start(const DDL_options_st &options) { create_info.set(options); return main_select_push() || check_create_options(options); } public: bool stmt_create_function_start(const DDL_options_st &options) { sql_command= SQLCOM_CREATE_SPFUNCTION; return stmt_create_routine_start(options); } bool stmt_create_procedure_start(const DDL_options_st &options) { sql_command= SQLCOM_CREATE_PROCEDURE; return stmt_create_routine_start(options); } void stmt_create_routine_finalize() { pop_select(); // main select } bool stmt_create_stored_function_start(const DDL_options_st &options, enum_sp_aggregate_type, const sp_name *name); bool stmt_create_stored_function_finalize_standalone(const sp_name *end_name); bool stmt_create_udf_function(const DDL_options_st &options, enum_sp_aggregate_type agg_type, const Lex_ident_sys_st &name, Item_result return_type, const LEX_CSTRING &soname); bool stmt_drop_routine(const Sp_handler *sph, const DDL_options_st &options, const Lex_ident_sys_st &db, const Lex_ident_sys_st &name); bool stmt_alter_function_start(sp_name *name); bool stmt_alter_procedure_start(sp_name *name); sp_condition_value *stmt_signal_value(const Lex_ident_sys_st &ident); Spvar_definition *row_field_name(THD *thd, const Lex_ident_sys_st &name); bool set_field_type_udt(Lex_field_type_st *type, const LEX_CSTRING &name, const Lex_length_and_dec_st &attr); bool set_cast_type_udt(Lex_cast_type_st *type, const LEX_CSTRING &name); bool map_data_type(const Lex_ident_sys_st &schema, Lex_field_type_st *type) const; void mark_first_table_as_inserting(); bool fields_are_impossible() { // no select or it is last select with no tables (service select) return !select_stack_head() || (select_stack_top == 1 && select_stack[0]->is_service_select); } bool add_table_foreign_key(const LEX_CSTRING *name, const LEX_CSTRING *constraint_name, Table_ident *table_name, DDL_options ddl_options); bool add_column_foreign_key(const LEX_CSTRING *name, const LEX_CSTRING *constraint_name, Table_ident *ref_table_name, DDL_options ddl_options); bool check_dependencies_in_with_clauses(); bool prepare_unreferenced_in_with_clauses(); bool check_cte_dependencies_and_resolve_references(); bool resolve_references_to_cte(TABLE_LIST *tables, TABLE_LIST **tables_last, st_select_lex_unit *excl_spec); /** Turn on the SELECT_DESCRIBE flag for every SELECT_LEX involved into the statement being processed in case the statement is EXPLAIN UPDATE/DELETE. @param lex current LEX */ void promote_select_describe_flag_if_needed() { if (describe) builtin_select.options |= SELECT_DESCRIBE; } /** Check if the current statement uses meta-data (uses a table or a stored routine). */ bool is_metadata_used() const { return query_tables != nullptr || sroutines.records > 0; } virtual sp_lex_cursor* get_lex_for_cursor() { return nullptr; } }; /** Set_signal_information is a container used in the parsed tree to represent the collection of assignments to condition items in the SIGNAL and RESIGNAL statements. */ class Set_signal_information { public: /** Empty default constructor, use clear() */ Set_signal_information() = default; /** Copy constructor. */ Set_signal_information(const Set_signal_information& set); /** Destructor. */ ~Set_signal_information() = default; /** Clear all items. */ void clear(); /** For each condition item assignment, m_item[] contains the parsed tree that represents the expression assigned, if any. m_item[] is an array indexed by Diag_condition_item_name. */ Item *m_item[LAST_DIAG_SET_PROPERTY+1]; }; /** The internal state of the syntax parser. This object is only available during parsing, and is private to the syntax parser implementation (sql_yacc.yy). */ class Yacc_state { public: Yacc_state() : yacc_yyss(NULL), yacc_yyvs(NULL) { reset(); } void reset() { if (yacc_yyss != NULL) { my_free(yacc_yyss); yacc_yyss = NULL; } if (yacc_yyvs != NULL) { my_free(yacc_yyvs); yacc_yyvs = NULL; } m_set_signal_info.clear(); m_lock_type= TL_READ_DEFAULT; m_mdl_type= MDL_SHARED_READ; } ~Yacc_state(); /** Reset part of the state which needs resetting before parsing substatement. */ void reset_before_substatement() { m_lock_type= TL_READ_DEFAULT; m_mdl_type= MDL_SHARED_READ; } /** Bison internal state stack, yyss, when dynamically allocated using my_yyoverflow(). */ uchar *yacc_yyss; /** Bison internal semantic value stack, yyvs, when dynamically allocated using my_yyoverflow(). */ uchar *yacc_yyvs; /** Fragments of parsed tree, used during the parsing of SIGNAL and RESIGNAL. */ Set_signal_information m_set_signal_info; /** Type of lock to be used for tables being added to the statement's table list in table_factor, table_alias_ref, single_multi and table_wild_one rules. Statements which use these rules but require lock type different from one specified by this member have to override it by using st_select_lex::set_lock_for_tables() method. The default value of this member is TL_READ_DEFAULT. The only two cases in which we change it are: - When parsing SELECT HIGH_PRIORITY. - Rule for DELETE. In which we use this member to pass information about type of lock from delete to single_multi part of rule. We should try to avoid introducing new use cases as we would like to get rid of this member eventually. */ thr_lock_type m_lock_type; /** The type of requested metadata lock for tables added to the statement table list. */ enum_mdl_type m_mdl_type; /* TODO: move more attributes from the LEX structure here. */ }; /** Internal state of the parser. The complete state consist of: - state data used during lexical parsing, - state data used during syntactic parsing. */ class Parser_state { public: Parser_state() : m_yacc() {} /** Object initializer. Must be called before usage. @retval FALSE OK @retval TRUE Error */ bool init(THD *thd, char *buff, size_t length) { return m_lip.init(thd, buff, length); } ~Parser_state() = default; Lex_input_stream m_lip; Yacc_state m_yacc; /** Current performance digest instrumentation. */ PSI_digest_locker* m_digest_psi; void reset(char *found_semicolon, unsigned int length) { m_lip.reset(found_semicolon, length); m_yacc.reset(); } }; extern sql_digest_state * digest_add_token(sql_digest_state *state, uint token, LEX_YYSTYPE yylval); extern sql_digest_state * digest_reduce_token(sql_digest_state *state, uint token_left, uint token_right); struct st_lex_local: public LEX, public Sql_alloc { /** List of Item_param instances that should be re-used on re-parsing of a SP instruction's statement */ List<Item_param> sp_statement_param_values; /** Iterator to the next Item_param in the list above to be processed by the method LEX::add_placeholder() */ List<Item_param>::iterator param_values_it; }; /** An st_lex_local extension with automatic initialization for SP purposes. Used to parse sub-expressions and SP sub-statements. This class is reused for: 1. sp_head::reset_lex() based constructs - SP variable assignments (e.g. SET x=10;) - FOR loop conditions and index variable increments - Cursor statements - SP statements - SP function RETURN statements - CASE statements - REPEAT..UNTIL expressions - WHILE expressions - EXIT..WHEN and CONTINUE..WHEN statements 2. sp_assignment_lex based constructs: - CURSOR parameter assignments */ class sp_lex_local: public st_lex_local { public: sp_lex_local(THD *thd, const LEX *oldlex) { /* Reset most stuff. */ start(thd); /* Keep the parent SP stuff */ sphead= oldlex->sphead; spcont= oldlex->spcont; /* Keep the parent trigger stuff too */ trg_chistics= oldlex->trg_chistics; sp_lex_in_use= false; } }; class sp_lex_set_var: public sp_lex_local { public: sp_lex_set_var(THD *thd, const LEX *oldlex) :sp_lex_local(thd, oldlex) { // Set new LEX as if we at start of set rule init_select(); sql_command= SQLCOM_SET_OPTION; var_list.empty(); autocommit= 0; option_type= oldlex->option_type; // Inherit from the outer lex } }; class sp_expr_lex: public sp_lex_local { Item *m_item; // The expression LEX_CSTRING m_expr_str; public: sp_expr_lex(THD *thd, LEX *oldlex) :sp_lex_local(thd, oldlex), m_item(nullptr), m_expr_str(empty_clex_str) { } void set_item(Item *item) { m_item= item; } Item *get_item() const { return m_item; } bool sp_continue_when_statement(THD *thd); bool sp_continue_when_statement(THD *thd, const LEX_CSTRING *label_name); int case_stmt_action_expr(); int case_stmt_action_when(bool simple); bool sp_while_loop_expression(THD *thd) { return LEX::sp_while_loop_expression(thd, get_item(), m_expr_str); } bool sp_repeat_loop_finalize(THD *thd); bool sp_if_expr(THD *thd); void set_expr_str(const LEX_CSTRING &expr_str) { m_expr_str= expr_str; } const LEX_CSTRING &get_expr_str() const { return m_expr_str; } }; /** An assignment specific LEX, which additionally has an Item (an expression) and an associated with the Item free_list, which is usually freed after the expression is calculated. Note, consider changing some of sp_lex_local to sp_assignment_lex, as the latter allows to use a simpler grammar in sql_yacc.yy (IMO). If the expression is simple (e.g. does not have function calls), then m_item and m_free_list point to the same Item. If the expressions is complex (e.g. have function calls), then m_item points to the leftmost Item, while m_free_list points to the rightmost item. For example: f1(COALESCE(f2(10), f2(20))) - m_item points to Item_func_sp for f1 (the leftmost Item) - m_free_list points to Item_int for 20 (the rightmost Item) Note, we could avoid storing m_item at all, as we can always reach the leftmost item from the rightmost item by iterating through m_free_list. But with a separate m_item the code should be faster. */ class sp_assignment_lex: public sp_lex_local { Item *m_item; // The expression Item *m_free_list; // The associated free_list (sub-expressions) LEX_CSTRING m_expr_str; public: sp_assignment_lex(THD *thd, LEX *oldlex) :sp_lex_local(thd, oldlex), m_item(NULL), m_free_list(nullptr), m_expr_str(empty_clex_str) { } void set_item_and_free_list(Item *item, Item *free_list) { m_item= item; m_free_list= free_list; } Item *get_item() const { return m_item; } Item *get_free_list() const { return m_free_list; } void set_expr_str(const LEX_CSTRING &expr_str) { m_expr_str= expr_str; } const LEX_CSTRING &get_expr_str() const { return m_expr_str; } }; extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); extern void lex_end_nops(LEX *lex); extern void lex_unlock_plugins(LEX *lex); void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex); int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex); extern int MYSQLlex(union YYSTYPE *yylval, THD *thd); extern int ORAlex(union YYSTYPE *yylval, THD *thd); inline void trim_whitespace(CHARSET_INFO *cs, LEX_CSTRING *str, size_t * prefix_length = 0) { *str= Lex_cstring(*str).trim_whitespace(cs, prefix_length); } extern bool is_lex_native_function(const LEX_CSTRING *name); extern bool is_native_function(THD *thd, const LEX_CSTRING *name); extern bool is_native_function_with_warn(THD *thd, const LEX_CSTRING *name); /** @} (End of group Semantic_Analysis) */ void my_missing_function_error(const LEX_CSTRING &token, const char *name); bool is_keyword(const char *name, uint len); int set_statement_var_if_exists(THD *thd, const char *var_name, size_t var_name_length, ulonglong value); Virtual_column_info *add_virtual_expression(THD *thd, Item *expr); Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, Item *expr); bool sp_create_assignment_lex(THD *thd, const char *pos); bool sp_create_assignment_instr(THD *thd, bool no_lookahead, bool need_set_keyword= true); void mark_or_conds_to_avoid_pushdown(Item *cond); inline bool TABLE_LIST::is_pure_alias() const { return !db.length || (table_options & TL_OPTION_ALIAS); } #endif /* MYSQL_SERVER */ #endif /* SQL_LEX_INCLUDED */ dur_prop.h 0000644 00000002072 15156036144 0006555 0 ustar 00 /* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _my_dur_prop_h #define _my_dur_prop_h enum durability_properties { /* Preserves the durability properties defined by the engine */ HA_REGULAR_DURABILITY= 0, /* Ignore the durability properties defined by the engine and write only in-memory entries. */ HA_IGNORE_DURABILITY= 1 }; #endif /* _my_dur_prop_h */ sql_schema.h 0000644 00000006347 15156036145 0007054 0 ustar 00 #ifndef SQL_SCHEMA_H_INCLUDED #define SQL_SCHEMA_H_INCLUDED /* Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "mysqld.h" #include "lex_string.h" class Lex_ident_sys; class Create_func; class Schema { LEX_CSTRING m_name; public: Schema(const LEX_CSTRING &name) :m_name(name) { } virtual ~Schema() = default; const LEX_CSTRING &name() const { return m_name; } virtual const Type_handler *map_data_type(THD *thd, const Type_handler *src) const { return src; } /** Find a native function builder, return an error if not found, build an Item otherwise. */ Item *make_item_func_call_native(THD *thd, const Lex_ident_sys &name, List<Item> *args) const; /** Find the native function builder associated with a given function name. @param thd The current thread @param name The native function name @return The native function builder associated with the name, or NULL */ virtual Create_func *find_native_function_builder(THD *thd, const LEX_CSTRING &name) const; // Builders for native SQL function with a special syntax in sql_yacc.yy virtual Item *make_item_func_replace(THD *thd, Item *subj, Item *find, Item *replace) const; virtual Item *make_item_func_substr(THD *thd, const Lex_substring_spec_st &spec) const; virtual Item *make_item_func_trim(THD *thd, const Lex_trim_st &spec) const; /* For now we have *hard-coded* compatibility schemas: schema_mariadb, schema_oracle, schema_maxdb. But eventually we'll turn then into real databases on disk. So the code below compares names according to the filesystem case sensitivity, like it is done for regular databases. Note, this is different to information_schema, whose name is always case insensitive. This is intentional! The assymetry will be gone when we'll implement SQL standard regular and delimited identifiers. */ bool eq_name(const LEX_CSTRING &name) const { return !table_alias_charset->strnncoll(m_name.str, m_name.length, name.str, name.length); } static Schema *find_by_name(const LEX_CSTRING &name); static Schema *find_implied(THD *thd); }; extern Schema mariadb_schema; extern const Schema &oracle_schema_ref; #endif // SQL_SCHEMA_H_INCLUDED lex_token.h 0000644 00000124006 15156036145 0006716 0 ustar 00 /* Copyright (c) 2011, 2018, Oracle, MariaDB Corporation Ab and others. */ /* This file is generated, do not edit. See file sql/gen_lex_token.cc. */ struct lex_token_string { const char *m_token_string; int m_token_length; bool m_append_space; bool m_start_expr; }; typedef struct lex_token_string lex_token_string; #ifdef LEX_TOKEN_WITH_DEFINITION lex_token_string lex_token_array[]= { /* PART 1: character tokens. */ /* 000 */ { "\x00", 1, true, false}, /* 001 */ { "\x01", 1, true, false}, /* 002 */ { "\x02", 1, true, false}, /* 003 */ { "\x03", 1, true, false}, /* 004 */ { "\x04", 1, true, false}, /* 005 */ { "\x05", 1, true, false}, /* 006 */ { "\x06", 1, true, false}, /* 007 */ { "\x07", 1, true, false}, /* 008 */ { "\x08", 1, true, false}, /* 009 */ { "\x09", 1, true, false}, /* 010 */ { "\x0a", 1, true, false}, /* 011 */ { "\x0b", 1, true, false}, /* 012 */ { "\x0c", 1, true, false}, /* 013 */ { "\x0d", 1, true, false}, /* 014 */ { "\x0e", 1, true, false}, /* 015 */ { "\x0f", 1, true, false}, /* 016 */ { "\x10", 1, true, false}, /* 017 */ { "\x11", 1, true, false}, /* 018 */ { "\x12", 1, true, false}, /* 019 */ { "\x13", 1, true, false}, /* 020 */ { "\x14", 1, true, false}, /* 021 */ { "\x15", 1, true, false}, /* 022 */ { "\x16", 1, true, false}, /* 023 */ { "\x17", 1, true, false}, /* 024 */ { "\x18", 1, true, false}, /* 025 */ { "\x19", 1, true, false}, /* 026 */ { "\x1a", 1, true, false}, /* 027 */ { "\x1b", 1, true, false}, /* 028 */ { "\x1c", 1, true, false}, /* 029 */ { "\x1d", 1, true, false}, /* 030 */ { "\x1e", 1, true, false}, /* 031 */ { "\x1f", 1, true, false}, /* 032 */ { "\x20", 1, true, false}, /* 033 */ { "\x21", 1, true, false}, /* 034 */ { "\x22", 1, true, false}, /* 035 */ { "\x23", 1, true, false}, /* 036 */ { "\x24", 1, true, false}, /* 037 */ { "\x25", 1, true, true}, /* 038 */ { "\x26", 1, true, true}, /* 039 */ { "\x27", 1, true, false}, /* 040 */ { "\x28", 1, true, true}, /* 041 */ { "\x29", 1, true, false}, /* 042 */ { "\x2a", 1, true, true}, /* 043 */ { "\x2b", 1, true, true}, /* 044 */ { "\x2c", 1, true, true}, /* 045 */ { "\x2d", 1, true, true}, /* 046 */ { "\x2e", 1, true, false}, /* 047 */ { "\x2f", 1, true, true}, /* 048 */ { "\x30", 1, true, false}, /* 049 */ { "\x31", 1, true, false}, /* 050 */ { "\x32", 1, true, false}, /* 051 */ { "\x33", 1, true, false}, /* 052 */ { "\x34", 1, true, false}, /* 053 */ { "\x35", 1, true, false}, /* 054 */ { "\x36", 1, true, false}, /* 055 */ { "\x37", 1, true, false}, /* 056 */ { "\x38", 1, true, false}, /* 057 */ { "\x39", 1, true, false}, /* 058 */ { "\x3a", 1, true, false}, /* 059 */ { "\x3b", 1, true, false}, /* 060 */ { "\x3c", 1, true, false}, /* 061 */ { "\x3d", 1, true, false}, /* 062 */ { "\x3e", 1, true, false}, /* 063 */ { "\x3f", 1, true, false}, /* 064 */ { "\x40", 1, false, false}, /* 065 */ { "\x41", 1, true, false}, /* 066 */ { "\x42", 1, true, false}, /* 067 */ { "\x43", 1, true, false}, /* 068 */ { "\x44", 1, true, false}, /* 069 */ { "\x45", 1, true, false}, /* 070 */ { "\x46", 1, true, false}, /* 071 */ { "\x47", 1, true, false}, /* 072 */ { "\x48", 1, true, false}, /* 073 */ { "\x49", 1, true, false}, /* 074 */ { "\x4a", 1, true, false}, /* 075 */ { "\x4b", 1, true, false}, /* 076 */ { "\x4c", 1, true, false}, /* 077 */ { "\x4d", 1, true, false}, /* 078 */ { "\x4e", 1, true, false}, /* 079 */ { "\x4f", 1, true, false}, /* 080 */ { "\x50", 1, true, false}, /* 081 */ { "\x51", 1, true, false}, /* 082 */ { "\x52", 1, true, false}, /* 083 */ { "\x53", 1, true, false}, /* 084 */ { "\x54", 1, true, false}, /* 085 */ { "\x55", 1, true, false}, /* 086 */ { "\x56", 1, true, false}, /* 087 */ { "\x57", 1, true, false}, /* 088 */ { "\x58", 1, true, false}, /* 089 */ { "\x59", 1, true, false}, /* 090 */ { "\x5a", 1, true, false}, /* 091 */ { "\x5b", 1, true, false}, /* 092 */ { "\x5c", 1, true, false}, /* 093 */ { "\x5d", 1, true, false}, /* 094 */ { "\x5e", 1, true, true}, /* 095 */ { "\x5f", 1, true, false}, /* 096 */ { "\x60", 1, true, false}, /* 097 */ { "\x61", 1, true, false}, /* 098 */ { "\x62", 1, true, false}, /* 099 */ { "\x63", 1, true, false}, /* 100 */ { "\x64", 1, true, false}, /* 101 */ { "\x65", 1, true, false}, /* 102 */ { "\x66", 1, true, false}, /* 103 */ { "\x67", 1, true, false}, /* 104 */ { "\x68", 1, true, false}, /* 105 */ { "\x69", 1, true, false}, /* 106 */ { "\x6a", 1, true, false}, /* 107 */ { "\x6b", 1, true, false}, /* 108 */ { "\x6c", 1, true, false}, /* 109 */ { "\x6d", 1, true, false}, /* 110 */ { "\x6e", 1, true, false}, /* 111 */ { "\x6f", 1, true, false}, /* 112 */ { "\x70", 1, true, false}, /* 113 */ { "\x71", 1, true, false}, /* 114 */ { "\x72", 1, true, false}, /* 115 */ { "\x73", 1, true, false}, /* 116 */ { "\x74", 1, true, false}, /* 117 */ { "\x75", 1, true, false}, /* 118 */ { "\x76", 1, true, false}, /* 119 */ { "\x77", 1, true, false}, /* 120 */ { "\x78", 1, true, false}, /* 121 */ { "\x79", 1, true, false}, /* 122 */ { "\x7a", 1, true, false}, /* 123 */ { "\x7b", 1, true, false}, /* 124 */ { "\x7c", 1, true, true}, /* 125 */ { "\x7d", 1, true, false}, /* 126 */ { "\x7e", 1, true, false}, /* 127 */ { "\x7f", 1, true, false}, /* 128 */ { "\x80", 1, true, false}, /* 129 */ { "\x81", 1, true, false}, /* 130 */ { "\x82", 1, true, false}, /* 131 */ { "\x83", 1, true, false}, /* 132 */ { "\x84", 1, true, false}, /* 133 */ { "\x85", 1, true, false}, /* 134 */ { "\x86", 1, true, false}, /* 135 */ { "\x87", 1, true, false}, /* 136 */ { "\x88", 1, true, false}, /* 137 */ { "\x89", 1, true, false}, /* 138 */ { "\x8a", 1, true, false}, /* 139 */ { "\x8b", 1, true, false}, /* 140 */ { "\x8c", 1, true, false}, /* 141 */ { "\x8d", 1, true, false}, /* 142 */ { "\x8e", 1, true, false}, /* 143 */ { "\x8f", 1, true, false}, /* 144 */ { "\x90", 1, true, false}, /* 145 */ { "\x91", 1, true, false}, /* 146 */ { "\x92", 1, true, false}, /* 147 */ { "\x93", 1, true, false}, /* 148 */ { "\x94", 1, true, false}, /* 149 */ { "\x95", 1, true, false}, /* 150 */ { "\x96", 1, true, false}, /* 151 */ { "\x97", 1, true, false}, /* 152 */ { "\x98", 1, true, false}, /* 153 */ { "\x99", 1, true, false}, /* 154 */ { "\x9a", 1, true, false}, /* 155 */ { "\x9b", 1, true, false}, /* 156 */ { "\x9c", 1, true, false}, /* 157 */ { "\x9d", 1, true, false}, /* 158 */ { "\x9e", 1, true, false}, /* 159 */ { "\x9f", 1, true, false}, /* 160 */ { "\xa0", 1, true, false}, /* 161 */ { "\xa1", 1, true, false}, /* 162 */ { "\xa2", 1, true, false}, /* 163 */ { "\xa3", 1, true, false}, /* 164 */ { "\xa4", 1, true, false}, /* 165 */ { "\xa5", 1, true, false}, /* 166 */ { "\xa6", 1, true, false}, /* 167 */ { "\xa7", 1, true, false}, /* 168 */ { "\xa8", 1, true, false}, /* 169 */ { "\xa9", 1, true, false}, /* 170 */ { "\xaa", 1, true, false}, /* 171 */ { "\xab", 1, true, false}, /* 172 */ { "\xac", 1, true, false}, /* 173 */ { "\xad", 1, true, false}, /* 174 */ { "\xae", 1, true, false}, /* 175 */ { "\xaf", 1, true, false}, /* 176 */ { "\xb0", 1, true, false}, /* 177 */ { "\xb1", 1, true, false}, /* 178 */ { "\xb2", 1, true, false}, /* 179 */ { "\xb3", 1, true, false}, /* 180 */ { "\xb4", 1, true, false}, /* 181 */ { "\xb5", 1, true, false}, /* 182 */ { "\xb6", 1, true, false}, /* 183 */ { "\xb7", 1, true, false}, /* 184 */ { "\xb8", 1, true, false}, /* 185 */ { "\xb9", 1, true, false}, /* 186 */ { "\xba", 1, true, false}, /* 187 */ { "\xbb", 1, true, false}, /* 188 */ { "\xbc", 1, true, false}, /* 189 */ { "\xbd", 1, true, false}, /* 190 */ { "\xbe", 1, true, false}, /* 191 */ { "\xbf", 1, true, false}, /* 192 */ { "\xc0", 1, true, false}, /* 193 */ { "\xc1", 1, true, false}, /* 194 */ { "\xc2", 1, true, false}, /* 195 */ { "\xc3", 1, true, false}, /* 196 */ { "\xc4", 1, true, false}, /* 197 */ { "\xc5", 1, true, false}, /* 198 */ { "\xc6", 1, true, false}, /* 199 */ { "\xc7", 1, true, false}, /* 200 */ { "\xc8", 1, true, false}, /* 201 */ { "\xc9", 1, true, false}, /* 202 */ { "\xca", 1, true, false}, /* 203 */ { "\xcb", 1, true, false}, /* 204 */ { "\xcc", 1, true, false}, /* 205 */ { "\xcd", 1, true, false}, /* 206 */ { "\xce", 1, true, false}, /* 207 */ { "\xcf", 1, true, false}, /* 208 */ { "\xd0", 1, true, false}, /* 209 */ { "\xd1", 1, true, false}, /* 210 */ { "\xd2", 1, true, false}, /* 211 */ { "\xd3", 1, true, false}, /* 212 */ { "\xd4", 1, true, false}, /* 213 */ { "\xd5", 1, true, false}, /* 214 */ { "\xd6", 1, true, false}, /* 215 */ { "\xd7", 1, true, false}, /* 216 */ { "\xd8", 1, true, false}, /* 217 */ { "\xd9", 1, true, false}, /* 218 */ { "\xda", 1, true, false}, /* 219 */ { "\xdb", 1, true, false}, /* 220 */ { "\xdc", 1, true, false}, /* 221 */ { "\xdd", 1, true, false}, /* 222 */ { "\xde", 1, true, false}, /* 223 */ { "\xdf", 1, true, false}, /* 224 */ { "\xe0", 1, true, false}, /* 225 */ { "\xe1", 1, true, false}, /* 226 */ { "\xe2", 1, true, false}, /* 227 */ { "\xe3", 1, true, false}, /* 228 */ { "\xe4", 1, true, false}, /* 229 */ { "\xe5", 1, true, false}, /* 230 */ { "\xe6", 1, true, false}, /* 231 */ { "\xe7", 1, true, false}, /* 232 */ { "\xe8", 1, true, false}, /* 233 */ { "\xe9", 1, true, false}, /* 234 */ { "\xea", 1, true, false}, /* 235 */ { "\xeb", 1, true, false}, /* 236 */ { "\xec", 1, true, false}, /* 237 */ { "\xed", 1, true, false}, /* 238 */ { "\xee", 1, true, false}, /* 239 */ { "\xef", 1, true, false}, /* 240 */ { "\xf0", 1, true, false}, /* 241 */ { "\xf1", 1, true, false}, /* 242 */ { "\xf2", 1, true, false}, /* 243 */ { "\xf3", 1, true, false}, /* 244 */ { "\xf4", 1, true, false}, /* 245 */ { "\xf5", 1, true, false}, /* 246 */ { "\xf6", 1, true, false}, /* 247 */ { "\xf7", 1, true, false}, /* 248 */ { "\xf8", 1, true, false}, /* 249 */ { "\xf9", 1, true, false}, /* 250 */ { "\xfa", 1, true, false}, /* 251 */ { "\xfb", 1, true, false}, /* 252 */ { "\xfc", 1, true, false}, /* 253 */ { "\xfd", 1, true, false}, /* 254 */ { "\xfe", 1, true, false}, /* 255 */ { "\xff", 1, true, false}, /* PART 2: named tokens. */ /* 256 */ { "(unknown)", 9, true, false}, /* 257 */ { "(unknown)", 9, true, false}, /* 258 */ { "(unknown)", 9, true, false}, /* 259 */ { "(unknown)", 9, true, false}, /* 260 */ { "(unknown)", 9, true, false}, /* 261 */ { "", 0, true, false}, /* 262 */ { "(unknown)", 9, true, false}, /* 263 */ { "?", 1, true, false}, /* 264 */ { "FOR SYSTEM_TIME", 15, true, false}, /* 265 */ { "(unknown)", 9, true, false}, /* 266 */ { "(unknown)", 9, true, false}, /* 267 */ { "(unknown)", 9, true, false}, /* 268 */ { "(unknown)", 9, true, false}, /* 269 */ { "(unknown)", 9, true, false}, /* 270 */ { "WITH CUBE", 9, true, false}, /* 271 */ { "WITH ROLLUP", 11, true, false}, /* 272 */ { "WITH SYSTEM", 11, true, false}, /* 273 */ { "(id)", 4, true, false}, /* 274 */ { "(id_quoted)", 11, true, false}, /* 275 */ { "(hostname)", 10, true, false}, /* 276 */ { "(_charset)", 10, true, false}, /* 277 */ { "(bin)", 5, true, false}, /* 278 */ { "(decimal)", 9, true, false}, /* 279 */ { "(float)", 7, true, false}, /* 280 */ { "(hex)", 5, true, false}, /* 281 */ { "(unknown)", 9, true, false}, /* 282 */ { "(long)", 6, true, false}, /* 283 */ { "(nchar)", 7, true, false}, /* 284 */ { "(num)", 5, true, false}, /* 285 */ { "(text)", 6, true, false}, /* 286 */ { "(ulonglong)", 11, true, false}, /* 287 */ { "&&", 2, true, true}, /* 288 */ { "(unknown)", 9, true, false}, /* 289 */ { "<=>", 3, true, false}, /* 290 */ { ">=", 2, true, false}, /* 291 */ { "<=", 2, true, false}, /* 292 */ { "(unknown)", 9, true, false}, /* 293 */ { "!=", 2, true, false}, /* 294 */ { "!", 1, true, false}, /* 295 */ { "||", 2, true, true}, /* 296 */ { ":=", 2, true, false}, /* 297 */ { "<<", 2, true, true}, /* 298 */ { ">>", 2, true, true}, /* 299 */ { "ACCESSIBLE", 10, true, false}, /* 300 */ { "ADD", 3, true, false}, /* 301 */ { "ALL", 3, true, false}, /* 302 */ { "ALTER", 5, true, false}, /* 303 */ { "ANALYZE", 7, true, false}, /* 304 */ { "AND", 3, true, true}, /* 305 */ { "ASC", 3, true, false}, /* 306 */ { "ASENSITIVE", 10, true, false}, /* 307 */ { "AS", 2, true, false}, /* 308 */ { "BEFORE", 6, true, false}, /* 309 */ { "BETWEEN", 7, true, true}, /* 310 */ { "INT8", 4, true, false}, /* 311 */ { "BINARY", 6, true, false}, /* 312 */ { "BIT_AND", 7, true, false}, /* 313 */ { "BIT_OR", 6, true, false}, /* 314 */ { "BIT_XOR", 7, true, false}, /* 315 */ { "BLOB", 4, true, false}, /* 316 */ { "(unknown)", 9, true, false}, /* 317 */ { "(unknown)", 9, true, false}, /* 318 */ { "BOTH", 4, true, false}, /* 319 */ { "BY", 2, true, false}, /* 320 */ { "CALL", 4, true, false}, /* 321 */ { "CASCADE", 7, true, false}, /* 322 */ { "CASE", 4, true, true}, /* 323 */ { "CAST", 4, true, false}, /* 324 */ { "CHANGE", 6, true, false}, /* 325 */ { "CHARACTER", 9, true, false}, /* 326 */ { "CHECK", 5, true, false}, /* 327 */ { "COLLATE", 7, true, false}, /* 328 */ { "CONDITION", 9, true, false}, /* 329 */ { "CONSTRAINT", 10, true, false}, /* 330 */ { "CONTINUE", 8, true, false}, /* 331 */ { "(unknown)", 9, true, false}, /* 332 */ { "CONVERT", 7, true, false}, /* 333 */ { "COUNT", 5, true, false}, /* 334 */ { "CREATE", 6, true, false}, /* 335 */ { "CROSS", 5, true, false}, /* 336 */ { "CUME_DIST", 9, true, false}, /* 337 */ { "CURDATE", 7, true, false}, /* 338 */ { "CURRENT_ROLE", 12, true, false}, /* 339 */ { "CURRENT_USER", 12, true, false}, /* 340 */ { "CURSOR", 6, true, false}, /* 341 */ { "CURTIME", 7, true, false}, /* 342 */ { "SCHEMA", 6, true, false}, /* 343 */ { "SCHEMAS", 7, true, false}, /* 344 */ { "DATE_ADD", 8, true, false}, /* 345 */ { "DATE_SUB", 8, true, false}, /* 346 */ { "DAY_HOUR", 8, true, false}, /* 347 */ { "DAY_MICROSECOND", 15, true, false}, /* 348 */ { "DAY_MINUTE", 10, true, false}, /* 349 */ { "DAY_SECOND", 10, true, false}, /* 350 */ { "DECIMAL", 7, true, false}, /* 351 */ { "DECLARE", 7, true, false}, /* 352 */ { "(unknown)", 9, true, false}, /* 353 */ { "DEFAULT", 7, true, true}, /* 354 */ { "DELETE_DOMAIN_ID", 16, true, false}, /* 355 */ { "DELETE", 6, true, false}, /* 356 */ { "DENSE_RANK", 10, true, false}, /* 357 */ { "EXPLAIN", 7, true, false}, /* 358 */ { "DESC", 4, true, false}, /* 359 */ { "DETERMINISTIC", 13, true, false}, /* 360 */ { "DISTINCTROW", 11, true, false}, /* 361 */ { "DIV", 3, true, true}, /* 362 */ { "DO_DOMAIN_IDS", 13, true, false}, /* 363 */ { "FLOAT8", 6, true, false}, /* 364 */ { "DROP", 4, true, false}, /* 365 */ { "DUAL", 4, true, false}, /* 366 */ { "EACH", 4, true, false}, /* 367 */ { "ELSEIF", 6, true, true}, /* 368 */ { "ELSE", 4, true, false}, /* 369 */ { "(unknown)", 9, true, false}, /* 370 */ { "EMPTY", 5, true, false}, /* 371 */ { "ENCLOSED", 8, true, false}, /* 372 */ { "ESCAPED", 7, true, false}, /* 373 */ { "EXCEPT", 6, true, false}, /* 374 */ { "EXISTS", 6, true, false}, /* 375 */ { "EXTRACT", 7, true, false}, /* 376 */ { "FALSE", 5, true, false}, /* 377 */ { "FETCH", 5, true, false}, /* 378 */ { "FIRST_VALUE", 11, true, false}, /* 379 */ { "FLOAT4", 6, true, false}, /* 380 */ { "FOREIGN", 7, true, false}, /* 381 */ { "FOR", 3, true, false}, /* 382 */ { "FROM", 4, true, false}, /* 383 */ { "FULLTEXT", 8, true, false}, /* 384 */ { "(unknown)", 9, true, false}, /* 385 */ { "GRANT", 5, true, false}, /* 386 */ { "GROUP_CONCAT", 12, true, false}, /* 387 */ { "JSON_ARRAYAGG", 13, true, false}, /* 388 */ { "JSON_OBJECTAGG", 14, true, false}, /* 389 */ { "JSON_TABLE", 10, true, false}, /* 390 */ { "GROUP", 5, true, false}, /* 391 */ { "HAVING", 6, true, false}, /* 392 */ { "HOUR_MICROSECOND", 16, true, false}, /* 393 */ { "HOUR_MINUTE", 11, true, false}, /* 394 */ { "HOUR_SECOND", 11, true, false}, /* 395 */ { "IF", 2, true, true}, /* 396 */ { "IGNORE_DOMAIN_IDS", 17, true, false}, /* 397 */ { "IGNORE", 6, true, false}, /* 398 */ { "IGNORED", 7, true, false}, /* 399 */ { "INDEX", 5, true, false}, /* 400 */ { "INFILE", 6, true, false}, /* 401 */ { "INNER", 5, true, false}, /* 402 */ { "INOUT", 5, true, false}, /* 403 */ { "INSENSITIVE", 11, true, false}, /* 404 */ { "INSERT", 6, true, false}, /* 405 */ { "IN", 2, true, false}, /* 406 */ { "INTERSECT", 9, true, false}, /* 407 */ { "INTERVAL", 8, true, true}, /* 408 */ { "INTO", 4, true, false}, /* 409 */ { "INTEGER", 7, true, false}, /* 410 */ { "IS", 2, true, false}, /* 411 */ { "ITERATE", 7, true, false}, /* 412 */ { "JOIN", 4, true, false}, /* 413 */ { "KEYS", 4, true, false}, /* 414 */ { "KEY", 3, true, false}, /* 415 */ { "KILL", 4, true, false}, /* 416 */ { "LAG", 3, true, false}, /* 417 */ { "LEADING", 7, true, false}, /* 418 */ { "LEAD", 4, true, false}, /* 419 */ { "LEAVE", 5, true, false}, /* 420 */ { "LEFT", 4, true, false}, /* 421 */ { "LIKE", 4, true, true}, /* 422 */ { "LIMIT", 5, true, false}, /* 423 */ { "LINEAR", 6, true, false}, /* 424 */ { "LINES", 5, true, false}, /* 425 */ { "LOAD", 4, true, false}, /* 426 */ { "LOCATOR", 7, true, false}, /* 427 */ { "LOCK", 4, true, false}, /* 428 */ { "LONGBLOB", 8, true, false}, /* 429 */ { "LONG", 4, true, false}, /* 430 */ { "LONGTEXT", 8, true, false}, /* 431 */ { "LOOP", 4, true, false}, /* 432 */ { "LOW_PRIORITY", 12, true, false}, /* 433 */ { "MASTER_SSL_VERIFY_SERVER_CERT", 29, true, false}, /* 434 */ { "MATCH", 5, true, false}, /* 435 */ { "MAX", 3, true, false}, /* 436 */ { "MAXVALUE", 8, true, false}, /* 437 */ { "MEDIAN", 6, true, false}, /* 438 */ { "MEDIUMBLOB", 10, true, false}, /* 439 */ { "MIDDLEINT", 9, true, false}, /* 440 */ { "MEDIUMTEXT", 10, true, false}, /* 441 */ { "MIN", 3, true, false}, /* 442 */ { "MINUS", 5, true, false}, /* 443 */ { "MINUTE_MICROSECOND", 18, true, false}, /* 444 */ { "MINUTE_SECOND", 13, true, false}, /* 445 */ { "MODIFIES", 8, true, false}, /* 446 */ { "MOD", 3, true, true}, /* 447 */ { "NATURAL", 7, true, false}, /* 448 */ { "~", 1, true, false}, /* 449 */ { "NESTED", 6, true, false}, /* 450 */ { "NOT", 3, true, true}, /* 451 */ { "NO_WRITE_TO_BINLOG", 18, true, false}, /* 452 */ { "NOW", 3, true, false}, /* 453 */ { "NTH_VALUE", 9, true, false}, /* 454 */ { "NTILE", 5, true, false}, /* 455 */ { "NULL", 4, true, false}, /* 456 */ { "NUMERIC", 7, true, false}, /* 457 */ { "ON", 2, true, false}, /* 458 */ { "OPTIMIZE", 8, true, false}, /* 459 */ { "OPTIONALLY", 10, true, false}, /* 460 */ { "ORDER", 5, true, false}, /* 461 */ { "ORDINALITY", 10, true, false}, /* 462 */ { "OR", 2, true, true}, /* 463 */ { "(unknown)", 9, true, false}, /* 464 */ { "OUTER", 5, true, false}, /* 465 */ { "OUTFILE", 7, true, false}, /* 466 */ { "OUT", 3, true, false}, /* 467 */ { "OVER", 4, true, false}, /* 468 */ { "(unknown)", 9, true, false}, /* 469 */ { "PAGE_CHECKSUM", 13, true, false}, /* 470 */ { "PARSE_VCOL_EXPR", 15, true, false}, /* 471 */ { "PARTITION", 9, true, false}, /* 472 */ { "PATH", 4, true, false}, /* 473 */ { "PERCENTILE_CONT", 15, true, false}, /* 474 */ { "PERCENTILE_DISC", 15, true, false}, /* 475 */ { "PERCENT_RANK", 12, true, false}, /* 476 */ { "PORTION", 7, true, false}, /* 477 */ { "POSITION", 8, true, false}, /* 478 */ { "PRECISION", 9, true, false}, /* 479 */ { "PRIMARY", 7, true, false}, /* 480 */ { "PROCEDURE", 9, true, false}, /* 481 */ { "PURGE", 5, true, false}, /* 482 */ { "(unknown)", 9, true, false}, /* 483 */ { "RANGE", 5, true, false}, /* 484 */ { "RANK", 4, true, false}, /* 485 */ { "READS", 5, true, false}, /* 486 */ { "READ", 4, true, false}, /* 487 */ { "READ_WRITE", 10, true, false}, /* 488 */ { "REAL", 4, true, false}, /* 489 */ { "RECURSIVE", 9, true, false}, /* 490 */ { "REFERENCES", 10, true, false}, /* 491 */ { "REF_SYSTEM_ID", 13, true, false}, /* 492 */ { "RLIKE", 5, true, true}, /* 493 */ { "RELEASE", 7, true, false}, /* 494 */ { "RENAME", 6, true, false}, /* 495 */ { "REPEAT", 6, true, false}, /* 496 */ { "REQUIRE", 7, true, false}, /* 497 */ { "RESIGNAL", 8, true, false}, /* 498 */ { "RESTRICT", 8, true, false}, /* 499 */ { "RETURNING", 9, true, false}, /* 500 */ { "RETURN", 6, true, true}, /* 501 */ { "(unknown)", 9, true, true}, /* 502 */ { "REVOKE", 6, true, false}, /* 503 */ { "RIGHT", 5, true, false}, /* 504 */ { "ROW_NUMBER", 10, true, false}, /* 505 */ { "ROWS", 4, true, false}, /* 506 */ { "(unknown)", 9, true, false}, /* 507 */ { "SECOND_MICROSECOND", 18, true, false}, /* 508 */ { "SELECT", 6, true, true}, /* 509 */ { "SENSITIVE", 9, true, false}, /* 510 */ { "SEPARATOR", 9, true, false}, /* 511 */ { "SERVER_OPTIONS", 14, true, false}, /* 512 */ { "SET", 3, true, false}, /* 513 */ { "SHOW", 4, true, false}, /* 514 */ { "SIGNAL", 6, true, false}, /* 515 */ { "SMALLINT", 8, true, false}, /* 516 */ { "SPATIAL", 7, true, false}, /* 517 */ { "SPECIFIC", 8, true, false}, /* 518 */ { "SQL_BIG_RESULT", 14, true, false}, /* 519 */ { "SQLEXCEPTION", 12, true, false}, /* 520 */ { "SQL_SMALL_RESULT", 16, true, false}, /* 521 */ { "SQLSTATE", 8, true, false}, /* 522 */ { "SQL", 3, true, false}, /* 523 */ { "SQLWARNING", 10, true, false}, /* 524 */ { "SSL", 3, true, false}, /* 525 */ { "STARTING", 8, true, false}, /* 526 */ { "STATS_AUTO_RECALC", 17, true, false}, /* 527 */ { "STATS_PERSISTENT", 16, true, false}, /* 528 */ { "STATS_SAMPLE_PAGES", 18, true, false}, /* 529 */ { "STDDEV_SAMP", 11, true, false}, /* 530 */ { "STDDEV_POP", 10, true, false}, /* 531 */ { "STRAIGHT_JOIN", 13, true, false}, /* 532 */ { "SUM", 3, true, false}, /* 533 */ { "SYSDATE", 7, true, false}, /* 534 */ { "TABLE_REF_PRIORITY", 18, true, false}, /* 535 */ { "TABLE", 5, true, false}, /* 536 */ { "TERMINATED", 10, true, false}, /* 537 */ { "THEN", 4, true, false}, /* 538 */ { "TINYBLOB", 8, true, false}, /* 539 */ { "TINYINT", 7, true, false}, /* 540 */ { "TINYTEXT", 8, true, false}, /* 541 */ { "TO", 2, true, false}, /* 542 */ { "TRAILING", 8, true, false}, /* 543 */ { "TRIGGER", 7, true, false}, /* 544 */ { "TRUE", 4, true, false}, /* 545 */ { "UNDO", 4, true, false}, /* 546 */ { "UNION", 5, true, false}, /* 547 */ { "UNIQUE", 6, true, false}, /* 548 */ { "UNLOCK", 6, true, false}, /* 549 */ { "UNSIGNED", 8, true, false}, /* 550 */ { "UPDATE", 6, true, false}, /* 551 */ { "USAGE", 5, true, false}, /* 552 */ { "USE", 3, true, false}, /* 553 */ { "USING", 5, true, false}, /* 554 */ { "UTC_DATE", 8, true, false}, /* 555 */ { "UTC_TIMESTAMP", 13, true, false}, /* 556 */ { "UTC_TIME", 8, true, false}, /* 557 */ { "VALUES IN", 9, true, false}, /* 558 */ { "VALUES LESS", 11, true, false}, /* 559 */ { "VALUES", 6, true, false}, /* 560 */ { "VARBINARY", 9, true, false}, /* 561 */ { "VARCHARACTER", 12, true, false}, /* 562 */ { "VAR_POP", 7, true, false}, /* 563 */ { "VAR_SAMP", 8, true, false}, /* 564 */ { "VARYING", 7, true, false}, /* 565 */ { "WHEN", 4, true, true}, /* 566 */ { "WHERE", 5, true, false}, /* 567 */ { "WHILE", 5, true, true}, /* 568 */ { "WITH", 4, true, false}, /* 569 */ { "XOR", 3, true, true}, /* 570 */ { "YEAR_MONTH", 10, true, false}, /* 571 */ { "ZEROFILL", 8, true, false}, /* 572 */ { "BODY", 4, true, false}, /* 573 */ { "(unknown)", 9, true, true}, /* 574 */ { "ELSIF", 5, true, false}, /* 575 */ { "(unknown)", 9, true, false}, /* 576 */ { "GOTO", 4, true, false}, /* 577 */ { "OTHERS", 6, true, false}, /* 578 */ { "PACKAGE", 7, true, false}, /* 579 */ { "RAISE", 5, true, false}, /* 580 */ { "ROWTYPE", 7, true, false}, /* 581 */ { "ROWNUM", 6, true, false}, /* 582 */ { "REPLACE", 7, true, false}, /* 583 */ { "SUBSTRING", 9, true, false}, /* 584 */ { "TRIM", 4, true, false}, /* 585 */ { "ACCOUNT", 7, true, false}, /* 586 */ { "ACTION", 6, true, false}, /* 587 */ { "ADMIN", 5, true, false}, /* 588 */ { "ADDDATE", 7, true, false}, /* 589 */ { "AFTER", 5, true, false}, /* 590 */ { "AGAINST", 7, true, false}, /* 591 */ { "AGGREGATE", 9, true, false}, /* 592 */ { "ALGORITHM", 9, true, false}, /* 593 */ { "ALWAYS", 6, true, false}, /* 594 */ { "SOME", 4, true, false}, /* 595 */ { "ASCII", 5, true, false}, /* 596 */ { "AT", 2, true, true}, /* 597 */ { "ATOMIC", 6, true, false}, /* 598 */ { "AUTHORS", 7, true, false}, /* 599 */ { "AUTOEXTEND_SIZE", 15, true, false}, /* 600 */ { "AUTO_INCREMENT", 14, true, false}, /* 601 */ { "AUTO", 4, true, false}, /* 602 */ { "AVG_ROW_LENGTH", 14, true, false}, /* 603 */ { "AVG", 3, true, false}, /* 604 */ { "BACKUP", 6, true, false}, /* 605 */ { "BEGIN", 5, true, false}, /* 606 */ { "(unknown)", 9, true, false}, /* 607 */ { "BINLOG", 6, true, false}, /* 608 */ { "BIT", 3, true, false}, /* 609 */ { "BLOCK", 5, true, false}, /* 610 */ { "BOOL", 4, true, false}, /* 611 */ { "BOOLEAN", 7, true, false}, /* 612 */ { "BTREE", 5, true, false}, /* 613 */ { "BYTE", 4, true, false}, /* 614 */ { "CACHE", 5, true, false}, /* 615 */ { "CASCADED", 8, true, false}, /* 616 */ { "CATALOG_NAME", 12, true, false}, /* 617 */ { "CHAIN", 5, true, false}, /* 618 */ { "CHANGED", 7, true, false}, /* 619 */ { "CHANNEL", 7, true, false}, /* 620 */ { "CHARSET", 7, true, false}, /* 621 */ { "CHECKPOINT", 10, true, false}, /* 622 */ { "CHECKSUM", 8, true, false}, /* 623 */ { "CIPHER", 6, true, false}, /* 624 */ { "CLASS_ORIGIN", 12, true, false}, /* 625 */ { "CLIENT", 6, true, false}, /* 626 */ { "CLOB", 4, true, false}, /* 627 */ { "(unknown)", 9, true, false}, /* 628 */ { "CLOSE", 5, true, false}, /* 629 */ { "COALESCE", 8, true, false}, /* 630 */ { "CODE", 4, true, false}, /* 631 */ { "COLLATION", 9, true, false}, /* 632 */ { "FIELDS", 6, true, false}, /* 633 */ { "COLUMN_ADD", 10, true, false}, /* 634 */ { "COLUMN_CHECK", 12, true, false}, /* 635 */ { "COLUMN_CREATE", 13, true, false}, /* 636 */ { "COLUMN_DELETE", 13, true, false}, /* 637 */ { "COLUMN_GET", 10, true, false}, /* 638 */ { "COLUMN", 6, true, false}, /* 639 */ { "COLUMN_NAME", 11, true, false}, /* 640 */ { "COMMENT", 7, true, false}, /* 641 */ { "COMMITTED", 9, true, false}, /* 642 */ { "COMMIT", 6, true, false}, /* 643 */ { "COMPACT", 7, true, false}, /* 644 */ { "COMPLETION", 10, true, false}, /* 645 */ { "COMPRESSED", 10, true, false}, /* 646 */ { "CONCURRENT", 10, true, false}, /* 647 */ { "CONNECTION", 10, true, false}, /* 648 */ { "CONSISTENT", 10, true, false}, /* 649 */ { "CONSTRAINT_CATALOG", 18, true, false}, /* 650 */ { "CONSTRAINT_NAME", 15, true, false}, /* 651 */ { "CONSTRAINT_SCHEMA", 17, true, false}, /* 652 */ { "CONTAINS", 8, true, false}, /* 653 */ { "CONTEXT", 7, true, false}, /* 654 */ { "CONTRIBUTORS", 12, true, false}, /* 655 */ { "CPU", 3, true, false}, /* 656 */ { "CUBE", 4, true, false}, /* 657 */ { "CURRENT", 7, true, false}, /* 658 */ { "CURRENT_POS", 11, true, false}, /* 659 */ { "CURSOR_NAME", 11, true, false}, /* 660 */ { "CYCLE", 5, true, false}, /* 661 */ { "DATAFILE", 8, true, false}, /* 662 */ { "DATA", 4, true, false}, /* 663 */ { "DATETIME", 8, true, false}, /* 664 */ { "DATE", 4, true, false}, /* 665 */ { "SQL_TSI_DAY", 11, true, false}, /* 666 */ { "DEALLOCATE", 10, true, false}, /* 667 */ { "DEFINER", 7, true, false}, /* 668 */ { "DELAYED", 7, true, false}, /* 669 */ { "DELAY_KEY_WRITE", 15, true, false}, /* 670 */ { "DES_KEY_FILE", 12, true, false}, /* 671 */ { "DIAGNOSTICS", 11, true, false}, /* 672 */ { "DIRECTORY", 9, true, false}, /* 673 */ { "DISABLE", 7, true, false}, /* 674 */ { "DISCARD", 7, true, false}, /* 675 */ { "DISK", 4, true, false}, /* 676 */ { "DO", 2, true, false}, /* 677 */ { "DUMPFILE", 8, true, false}, /* 678 */ { "DUPLICATE", 9, true, false}, /* 679 */ { "DYNAMIC", 7, true, false}, /* 680 */ { "ENABLE_GOVERNOR", 15, true, false}, /* 681 */ { "ENABLE_GOVERNOR_RECON", 21, true, false}, /* 682 */ { "ENABLE_GOVERNOR_LVE", 19, true, false}, /* 683 */ { "ENABLE_GOVERNOR_RECON_LVE", 25, true, false}, /* 684 */ { "ENABLE", 6, true, false}, /* 685 */ { "END", 3, true, false}, /* 686 */ { "ENDS", 4, true, true}, /* 687 */ { "ENGINES", 7, true, false}, /* 688 */ { "ENGINE", 6, true, false}, /* 689 */ { "ENUM", 4, true, false}, /* 690 */ { "ERROR", 5, true, false}, /* 691 */ { "ERRORS", 6, true, false}, /* 692 */ { "ESCAPE", 6, true, false}, /* 693 */ { "EVENTS", 6, true, false}, /* 694 */ { "EVENT", 5, true, false}, /* 695 */ { "EVERY", 5, true, true}, /* 696 */ { "EXCHANGE", 8, true, false}, /* 697 */ { "EXAMINED", 8, true, false}, /* 698 */ { "EXCLUDE", 7, true, false}, /* 699 */ { "EXECUTE", 7, true, false}, /* 700 */ { "EXCEPTION", 9, true, false}, /* 701 */ { "EXIT", 4, true, false}, /* 702 */ { "(unknown)", 9, true, false}, /* 703 */ { "EXPANSION", 9, true, false}, /* 704 */ { "EXPIRE", 6, true, false}, /* 705 */ { "EXPORT", 6, true, false}, /* 706 */ { "EXTENDED", 8, true, false}, /* 707 */ { "EXTENT_SIZE", 11, true, false}, /* 708 */ { "FAST", 4, true, false}, /* 709 */ { "FAULTS", 6, true, false}, /* 710 */ { "FEDERATED", 9, true, false}, /* 711 */ { "FILE", 4, true, false}, /* 712 */ { "FIRST", 5, true, false}, /* 713 */ { "FIXED", 5, true, false}, /* 714 */ { "FLUSH", 5, true, false}, /* 715 */ { "FOLLOWS", 7, true, false}, /* 716 */ { "FOLLOWING", 9, true, false}, /* 717 */ { "FORCE", 5, true, false}, /* 718 */ { "FORMAT", 6, true, false}, /* 719 */ { "FOUND", 5, true, false}, /* 720 */ { "FULL", 4, true, false}, /* 721 */ { "FUNCTION", 8, true, false}, /* 722 */ { "GENERAL", 7, true, false}, /* 723 */ { "GENERATED", 9, true, false}, /* 724 */ { "GET_FORMAT", 10, true, false}, /* 725 */ { "GET", 3, true, false}, /* 726 */ { "GLOBAL", 6, true, false}, /* 727 */ { "GRANTS", 6, true, false}, /* 728 */ { "HANDLER", 7, true, false}, /* 729 */ { "HARD", 4, true, false}, /* 730 */ { "HASH", 4, true, false}, /* 731 */ { "HELP", 4, true, false}, /* 732 */ { "HIGH_PRIORITY", 13, true, false}, /* 733 */ { "HISTORY", 7, true, false}, /* 734 */ { "HOST", 4, true, false}, /* 735 */ { "HOSTS", 5, true, false}, /* 736 */ { "SQL_TSI_HOUR", 12, true, false}, /* 737 */ { "ID", 2, true, false}, /* 738 */ { "IDENTIFIED", 10, true, false}, /* 739 */ { "IGNORE_SERVER_IDS", 17, true, false}, /* 740 */ { "IMMEDIATE", 9, true, false}, /* 741 */ { "IMPORT", 6, true, false}, /* 742 */ { "INCREMENT", 9, true, false}, /* 743 */ { "INDEXES", 7, true, false}, /* 744 */ { "INITIAL_SIZE", 12, true, false}, /* 745 */ { "INSERT_METHOD", 13, true, false}, /* 746 */ { "INSTALL", 7, true, false}, /* 747 */ { "INVOKER", 7, true, false}, /* 748 */ { "IO", 2, true, false}, /* 749 */ { "IPC", 3, true, false}, /* 750 */ { "ISOLATION", 9, true, false}, /* 751 */ { "ISOPEN", 6, true, false}, /* 752 */ { "ISSUER", 6, true, false}, /* 753 */ { "INVISIBLE", 9, true, false}, /* 754 */ { "JSON", 4, true, false}, /* 755 */ { "KEY_BLOCK_SIZE", 14, true, false}, /* 756 */ { "LANGUAGE", 8, true, false}, /* 757 */ { "LAST", 4, true, false}, /* 758 */ { "LAST_VALUE", 10, true, false}, /* 759 */ { "LASTVAL", 7, true, false}, /* 760 */ { "LEAVES", 6, true, false}, /* 761 */ { "LESS", 4, true, false}, /* 762 */ { "LEVEL", 5, true, false}, /* 763 */ { "LIST", 4, true, false}, /* 764 */ { "LOCAL", 5, true, false}, /* 765 */ { "LOCKED", 6, true, false}, /* 766 */ { "LOCKS", 5, true, false}, /* 767 */ { "LOGFILE", 7, true, false}, /* 768 */ { "LOGS", 4, true, false}, /* 769 */ { "MASTER_CONNECT_RETRY", 20, true, false}, /* 770 */ { "MASTER_DELAY", 12, true, false}, /* 771 */ { "MASTER_GTID_POS", 15, true, false}, /* 772 */ { "MASTER_HOST", 11, true, false}, /* 773 */ { "MASTER_LOG_FILE", 15, true, false}, /* 774 */ { "MASTER_LOG_POS", 14, true, false}, /* 775 */ { "MASTER_PASSWORD", 15, true, false}, /* 776 */ { "MASTER_PORT", 11, true, false}, /* 777 */ { "MASTER_SERVER_ID", 16, true, false}, /* 778 */ { "MASTER_SSL_CAPATH", 17, true, false}, /* 779 */ { "MASTER_SSL_CA", 13, true, false}, /* 780 */ { "MASTER_SSL_CERT", 15, true, false}, /* 781 */ { "MASTER_SSL_CIPHER", 17, true, false}, /* 782 */ { "MASTER_SSL_CRL", 14, true, false}, /* 783 */ { "MASTER_SSL_CRLPATH", 18, true, false}, /* 784 */ { "MASTER_SSL_KEY", 14, true, false}, /* 785 */ { "MASTER_SSL", 10, true, false}, /* 786 */ { "MASTER", 6, true, false}, /* 787 */ { "MASTER_USER", 11, true, false}, /* 788 */ { "MASTER_USE_GTID", 15, true, false}, /* 789 */ { "MASTER_HEARTBEAT_PERIOD", 23, true, false}, /* 790 */ { "MASTER_DEMOTE_TO_SLAVE", 22, true, false}, /* 791 */ { "MAX_CONNECTIONS_PER_HOUR", 24, true, false}, /* 792 */ { "MAX_QUERIES_PER_HOUR", 20, true, false}, /* 793 */ { "MAX_ROWS", 8, true, false}, /* 794 */ { "MAX_SIZE", 8, true, false}, /* 795 */ { "MAX_UPDATES_PER_HOUR", 20, true, false}, /* 796 */ { "MAX_STATEMENT_TIME", 18, true, false}, /* 797 */ { "MAX_USER_CONNECTIONS", 20, true, false}, /* 798 */ { "MEDIUM", 6, true, false}, /* 799 */ { "MEMORY", 6, true, false}, /* 800 */ { "MERGE", 5, true, false}, /* 801 */ { "MESSAGE_TEXT", 12, true, false}, /* 802 */ { "MICROSECOND", 11, true, false}, /* 803 */ { "MIGRATE", 7, true, false}, /* 804 */ { "SQL_TSI_MINUTE", 14, true, false}, /* 805 */ { "MINVALUE", 8, true, false}, /* 806 */ { "MIN_ROWS", 8, true, false}, /* 807 */ { "MODE", 4, true, false}, /* 808 */ { "MODIFY", 6, true, false}, /* 809 */ { "MONITOR", 7, true, false}, /* 810 */ { "SQL_TSI_MONTH", 13, true, false}, /* 811 */ { "MUTEX", 5, true, false}, /* 812 */ { "MYSQL", 5, true, false}, /* 813 */ { "MYSQL_ERRNO", 11, true, false}, /* 814 */ { "NAMES", 5, true, false}, /* 815 */ { "NAME", 4, true, false}, /* 816 */ { "NATIONAL", 8, true, false}, /* 817 */ { "NCHAR", 5, true, false}, /* 818 */ { "NEVER", 5, true, false}, /* 819 */ { "NEXT", 4, true, false}, /* 820 */ { "NEXTVAL", 7, true, false}, /* 821 */ { "NOCACHE", 7, true, false}, /* 822 */ { "NOCYCLE", 7, true, false}, /* 823 */ { "NODEGROUP", 9, true, false}, /* 824 */ { "NONE", 4, true, false}, /* 825 */ { "NOTFOUND", 8, true, false}, /* 826 */ { "NO", 2, true, false}, /* 827 */ { "NOMAXVALUE", 10, true, false}, /* 828 */ { "NOMINVALUE", 10, true, false}, /* 829 */ { "NO_WAIT", 7, true, false}, /* 830 */ { "NOWAIT", 6, true, false}, /* 831 */ { "NUMBER", 6, true, false}, /* 832 */ { "(unknown)", 9, true, false}, /* 833 */ { "NVARCHAR", 8, true, false}, /* 834 */ { "OF", 2, true, false}, /* 835 */ { "OFFSET", 6, true, false}, /* 836 */ { "OLD_PASSWORD", 12, true, false}, /* 837 */ { "ONE", 3, true, false}, /* 838 */ { "ONLY", 4, true, false}, /* 839 */ { "ONLINE", 6, true, false}, /* 840 */ { "OPEN", 4, true, false}, /* 841 */ { "OPTIONS", 7, true, false}, /* 842 */ { "OPTION", 6, true, false}, /* 843 */ { "OVERLAPS", 8, true, false}, /* 844 */ { "OWNER", 5, true, false}, /* 845 */ { "PACK_KEYS", 9, true, false}, /* 846 */ { "PAGE", 4, true, false}, /* 847 */ { "PARSER", 6, true, false}, /* 848 */ { "PARTIAL", 7, true, false}, /* 849 */ { "PARTITIONS", 10, true, false}, /* 850 */ { "PARTITIONING", 12, true, false}, /* 851 */ { "PASSWORD", 8, true, false}, /* 852 */ { "PERIOD", 6, true, false}, /* 853 */ { "PERSISTENT", 10, true, false}, /* 854 */ { "PHASE", 5, true, false}, /* 855 */ { "PLUGINS", 7, true, false}, /* 856 */ { "PLUGIN", 6, true, false}, /* 857 */ { "PORT", 4, true, false}, /* 858 */ { "PRECEDES", 8, true, false}, /* 859 */ { "PRECEDING", 9, true, false}, /* 860 */ { "PREPARE", 7, true, false}, /* 861 */ { "PRESERVE", 8, true, false}, /* 862 */ { "PREV", 4, true, false}, /* 863 */ { "PREVIOUS", 8, true, false}, /* 864 */ { "PRIVILEGES", 10, true, false}, /* 865 */ { "PROCESS", 7, true, false}, /* 866 */ { "PROCESSLIST", 11, true, false}, /* 867 */ { "PROFILE", 7, true, false}, /* 868 */ { "PROFILES", 8, true, false}, /* 869 */ { "PROXY", 5, true, false}, /* 870 */ { "SQL_TSI_QUARTER", 15, true, false}, /* 871 */ { "QUERY", 5, true, false}, /* 872 */ { "QUICK", 5, true, false}, /* 873 */ { "RAW", 3, true, false}, /* 874 */ { "(unknown)", 9, true, false}, /* 875 */ { "READ_ONLY", 9, true, false}, /* 876 */ { "REBUILD", 7, true, false}, /* 877 */ { "RECOVER", 7, true, false}, /* 878 */ { "REDOFILE", 8, true, false}, /* 879 */ { "REDO_BUFFER_SIZE", 16, true, false}, /* 880 */ { "REDUNDANT", 9, true, false}, /* 881 */ { "RELAY", 5, true, false}, /* 882 */ { "RELAYLOG", 8, true, false}, /* 883 */ { "RELAY_LOG_FILE", 14, true, false}, /* 884 */ { "RELAY_LOG_POS", 13, true, false}, /* 885 */ { "RELAY_THREAD", 12, true, false}, /* 886 */ { "RELOAD", 6, true, false}, /* 887 */ { "REMOVE", 6, true, false}, /* 888 */ { "REORGANIZE", 10, true, false}, /* 889 */ { "REPAIR", 6, true, false}, /* 890 */ { "REPEATABLE", 10, true, false}, /* 891 */ { "REPLAY", 6, true, false}, /* 892 */ { "REPLICATION", 11, true, false}, /* 893 */ { "RESET", 5, true, false}, /* 894 */ { "RESTART", 7, true, false}, /* 895 */ { "USER_RESOURCES", 14, true, false}, /* 896 */ { "RESTORE", 7, true, false}, /* 897 */ { "RESUME", 6, true, false}, /* 898 */ { "RETURNED_SQLSTATE", 17, true, false}, /* 899 */ { "RETURNS", 7, true, false}, /* 900 */ { "REUSE", 5, true, false}, /* 901 */ { "REVERSE", 7, true, false}, /* 902 */ { "ROLE", 4, true, false}, /* 903 */ { "ROLLBACK", 8, true, false}, /* 904 */ { "ROLLUP", 6, true, false}, /* 905 */ { "ROUTINE", 7, true, false}, /* 906 */ { "ROWCOUNT", 8, true, false}, /* 907 */ { "ROW", 3, true, false}, /* 908 */ { "ROW_COUNT", 9, true, false}, /* 909 */ { "ROW_FORMAT", 10, true, false}, /* 910 */ { "RTREE", 5, true, false}, /* 911 */ { "SAVEPOINT", 9, true, false}, /* 912 */ { "SCHEDULE", 8, true, false}, /* 913 */ { "SCHEMA_NAME", 11, true, false}, /* 914 */ { "SQL_TSI_SECOND", 14, true, false}, /* 915 */ { "SECURITY", 8, true, false}, /* 916 */ { "SEQUENCE", 8, true, false}, /* 917 */ { "SERIALIZABLE", 12, true, false}, /* 918 */ { "SERIAL", 6, true, false}, /* 919 */ { "SESSION", 7, true, false}, /* 920 */ { "SERVER", 6, true, false}, /* 921 */ { "SETVAL", 6, true, false}, /* 922 */ { "SHARE", 5, true, false}, /* 923 */ { "SHUTDOWN", 8, true, false}, /* 924 */ { "SIGNED", 6, true, false}, /* 925 */ { "SIMPLE", 6, true, false}, /* 926 */ { "SKIP", 4, true, false}, /* 927 */ { "SLAVE", 5, true, false}, /* 928 */ { "SLAVES", 6, true, false}, /* 929 */ { "SLAVE_POS", 9, true, false}, /* 930 */ { "SLOW", 4, true, false}, /* 931 */ { "SNAPSHOT", 8, true, false}, /* 932 */ { "SOCKET", 6, true, false}, /* 933 */ { "SOFT", 4, true, false}, /* 934 */ { "SONAME", 6, true, false}, /* 935 */ { "SOUNDS", 6, true, false}, /* 936 */ { "SOURCE", 6, true, false}, /* 937 */ { "SQL_AFTER_GTIDS", 15, true, false}, /* 938 */ { "SQL_BEFORE_GTIDS", 16, true, false}, /* 939 */ { "SQL_BUFFER_RESULT", 17, true, false}, /* 940 */ { "SQL_CACHE", 9, true, false}, /* 941 */ { "SQL_CALC_FOUND_ROWS", 19, true, false}, /* 942 */ { "SQL_NO_CACHE", 12, true, false}, /* 943 */ { "SQL_THREAD", 10, true, false}, /* 944 */ { "STAGE", 5, true, false}, /* 945 */ { "STARTS", 6, true, true}, /* 946 */ { "START", 5, true, false}, /* 947 */ { "STATEMENT", 9, true, false}, /* 948 */ { "STATUS", 6, true, false}, /* 949 */ { "STOP", 4, true, false}, /* 950 */ { "STORAGE", 7, true, false}, /* 951 */ { "STORED", 6, true, false}, /* 952 */ { "STRING", 6, true, false}, /* 953 */ { "SUBCLASS_ORIGIN", 15, true, false}, /* 954 */ { "SUBDATE", 7, true, false}, /* 955 */ { "SUBJECT", 7, true, false}, /* 956 */ { "SUBPARTITIONS", 13, true, false}, /* 957 */ { "SUBPARTITION", 12, true, false}, /* 958 */ { "SUPER", 5, true, false}, /* 959 */ { "SUSPEND", 7, true, false}, /* 960 */ { "SWAPS", 5, true, false}, /* 961 */ { "SWITCHES", 8, true, false}, /* 962 */ { "SYSTEM", 6, true, false}, /* 963 */ { "SYSTEM_TIME", 11, true, false}, /* 964 */ { "TABLES", 6, true, false}, /* 965 */ { "TABLESPACE", 10, true, false}, /* 966 */ { "TABLE_CHECKSUM", 14, true, false}, /* 967 */ { "TABLE_NAME", 10, true, false}, /* 968 */ { "TEMPORARY", 9, true, false}, /* 969 */ { "TEMPTABLE", 9, true, false}, /* 970 */ { "TEXT", 4, true, false}, /* 971 */ { "THAN", 4, true, false}, /* 972 */ { "TIES", 4, true, false}, /* 973 */ { "TIMESTAMP", 9, true, false}, /* 974 */ { "TIMESTAMPADD", 12, true, false}, /* 975 */ { "TIMESTAMPDIFF", 13, true, false}, /* 976 */ { "TIME", 4, true, false}, /* 977 */ { "TRANSACTION", 11, true, false}, /* 978 */ { "TRANSACTIONAL", 13, true, false}, /* 979 */ { "THREADS", 7, true, false}, /* 980 */ { "TRIGGERS", 8, true, false}, /* 981 */ { "TRIM_ORACLE", 11, true, false}, /* 982 */ { "TRUNCATE", 8, true, false}, /* 983 */ { "TYPE", 4, true, false}, /* 984 */ { "UDF_RETURNS", 11, true, false}, /* 985 */ { "UNBOUNDED", 9, true, false}, /* 986 */ { "UNCOMMITTED", 11, true, false}, /* 987 */ { "UNDEFINED", 9, true, false}, /* 988 */ { "UNDOFILE", 8, true, false}, /* 989 */ { "UNDO_BUFFER_SIZE", 16, true, false}, /* 990 */ { "UNICODE", 7, true, false}, /* 991 */ { "UNINSTALL", 9, true, false}, /* 992 */ { "UNKNOWN", 7, true, false}, /* 993 */ { "UNTIL", 5, true, true}, /* 994 */ { "UPGRADE", 7, true, false}, /* 995 */ { "SYSTEM_USER", 11, true, false}, /* 996 */ { "USE_FRM", 7, true, false}, /* 997 */ { "VALIDATION", 10, true, false}, /* 998 */ { "VALUE", 5, true, false}, /* 999 */ { "VARCHAR2", 8, true, false}, /* 1000 */ { "(unknown)", 9, true, false}, /* 1001 */ { "VARIABLES", 9, true, false}, /* 1002 */ { "VERSIONING", 10, true, false}, /* 1003 */ { "VIA", 3, true, false}, /* 1004 */ { "VIEW", 4, true, false}, /* 1005 */ { "VISIBLE", 7, true, false}, /* 1006 */ { "VIRTUAL", 7, true, false}, /* 1007 */ { "WAIT", 4, true, false}, /* 1008 */ { "WARNINGS", 8, true, false}, /* 1009 */ { "WEEK", 4, true, false}, /* 1010 */ { "WEIGHT_STRING", 13, true, false}, /* 1011 */ { "WINDOW", 6, true, false}, /* 1012 */ { "WITHIN", 6, true, false}, /* 1013 */ { "WITHOUT", 7, true, false}, /* 1014 */ { "WORK", 4, true, false}, /* 1015 */ { "WRAPPER", 7, true, false}, /* 1016 */ { "WRITE", 5, true, false}, /* 1017 */ { "X509", 4, true, false}, /* 1018 */ { "XA", 2, true, false}, /* 1019 */ { "XML", 3, true, false}, /* 1020 */ { "YEAR", 4, true, false}, /* 1021 */ { "?", 1, true, false}, /* 1022 */ { "?, ...", 6, true, false}, /* 1023 */ { "(?)", 3, true, false}, /* 1024 */ { "(?) /* , ... */", 15, true, false}, /* 1025 */ { "(...)", 5, true, false}, /* 1026 */ { "(...) /* , ... */", 17, true, false}, /* 1027 */ { "(tok_id)", 8, true, false}, /* 1028 */ { "UNUSED", 6, true, false}, /* DUMMY */ { "", 0, false, false} }; #endif /* LEX_TOKEN_WITH_DEFINITION */ /* DIGEST specific tokens. */ #define TOK_GENERIC_VALUE 1021 #define TOK_GENERIC_VALUE_LIST 1022 #define TOK_ROW_SINGLE_VALUE 1023 #define TOK_ROW_SINGLE_VALUE_LIST 1024 #define TOK_ROW_MULTIPLE_VALUE 1025 #define TOK_ROW_MULTIPLE_VALUE_LIST 1026 #define TOK_IDENT 1027 #define TOK_UNUSED 1028 json_schema.h 0000644 00000062323 15156036145 0007222 0 ustar 00 #ifndef JSON_SCHEMA_INCLUDED #define JSON_SCHEMA_INCLUDED /* Copyright (c) 2016, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file defines all json schema classes. */ #include "sql_class.h" #include "sql_type_json.h" #include "json_schema_helper.h" struct st_json_schema_keyword_map; class Json_schema_keyword : public Sql_alloc { public: Json_schema_keyword *alternate_schema; st_json_schema_keyword_map *keyword_map; double value; uint priority; bool allowed; Json_schema_keyword() : alternate_schema(NULL), keyword_map(NULL), value(0), priority(0), allowed(true) { } virtual ~Json_schema_keyword() = default; /* Called for each keyword on the current level. */ virtual bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) { return false; } virtual bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) { return false; } virtual List<Json_schema_keyword>* get_validation_keywords() { return NULL; } void set_alternate_schema(Json_schema_keyword *schema) { alternate_schema= schema; } virtual bool fall_back_on_alternate_schema(const json_engine_t *je, const uchar* k_start= NULL, const uchar* k_end= NULL); virtual bool validate_as_alternate(const json_engine_t *je, const uchar* k_start= NULL, const uchar* k_end= NULL) { return false; } virtual bool validate_schema_items(const json_engine_t *je, List<Json_schema_keyword>*schema_items); virtual void set_alternate_schema_choice(Json_schema_keyword *schema1, Json_schema_keyword *schema2) { return; } virtual void set_dependents(Json_schema_keyword *schema1, Json_schema_keyword *schema2) { return; } }; /* Additional and unvaluated keywords and items handle keywords and validate schema in same way, so it makes sense to have a base class for them. */ class Json_schema_additional_and_unevaluated : public Json_schema_keyword { public: List<Json_schema_keyword> schema_list; Json_schema_additional_and_unevaluated() { allowed= true; } void set_allowed(bool allowed_val) { allowed= allowed_val; } bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override { return false; } bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, const uchar *k_end) override; }; class Json_schema_annotation : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_format : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; typedef List<Json_schema_keyword> List_schema_keyword; class Json_schema_type : public Json_schema_keyword { private: uint type; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_type() { type= 0; } }; class Json_schema_const : public Json_schema_keyword { private: char *const_json_value; public: enum json_value_types type; bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_const() { const_json_value= NULL; } }; class Json_schema_enum : public Json_schema_keyword { private: HASH enum_values; uint enum_scalar; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_enum() { enum_scalar= 0; } ~Json_schema_enum() { my_hash_free(&enum_values); } }; class Json_schema_maximum : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_minimum : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_multiple_of : public Json_schema_keyword { private: longlong multiple_of; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_ex_maximum : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_ex_minimum : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_max_len : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_min_len : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_pattern : public Json_schema_keyword { private: Regexp_processor_pcre re; Item *pattern; Item_string *str; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_pattern() { str= NULL; pattern= NULL; } ~Json_schema_pattern() { re.cleanup(); } }; class Json_schema_max_items : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_min_items : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_max_contains : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_min_contains : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; /* The value of max_contains and min_contains is only relevant when contains keyword is present. Hence the pointers to access them directly. */ class Json_schema_contains : public Json_schema_keyword { public: List <Json_schema_keyword> contains; Json_schema_keyword *max_contains; Json_schema_keyword *min_contains; bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; void set_dependents(Json_schema_keyword *min, Json_schema_keyword *max) override { min_contains= min; max_contains= max; } }; class Json_schema_unique_items : public Json_schema_keyword { private: bool is_unique; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_prefix_items : public Json_schema_keyword { public: List <List_schema_keyword> prefix_items; bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_prefix_items() { priority= 1; } }; class Json_schema_unevaluated_items : public Json_schema_additional_and_unevaluated { public: Json_schema_unevaluated_items() { priority= 4; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; }; class Json_schema_additional_items : public Json_schema_additional_and_unevaluated { public: Json_schema_additional_items() { priority= 3; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; }; class Json_schema_items : public Json_schema_keyword { private: List<Json_schema_keyword> items_schema; public: Json_schema_items() { priority= 2; } void set_allowed(bool allowed_val) { allowed= allowed_val; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, const uchar *k_end) override; }; class Json_schema_property_names : public Json_schema_keyword { protected: List <Json_schema_keyword> property_names; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; typedef struct property { List<Json_schema_keyword> *curr_schema; char *key_name; } st_property; class Json_schema_properties : public Json_schema_keyword { private: HASH properties; bool is_hash_inited; public: Json_schema_properties() { priority= 1; is_hash_inited= false; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; ~Json_schema_properties() { if (is_hash_inited) my_hash_free(&properties); } bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, const uchar *k_end) override; }; class Json_schema_dependent_schemas : public Json_schema_keyword { private: HASH properties; bool is_hash_inited; public: ~Json_schema_dependent_schemas() { if (is_hash_inited) my_hash_free(&properties); } Json_schema_dependent_schemas() { is_hash_inited= false; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_additional_properties : public Json_schema_additional_and_unevaluated { public: Json_schema_additional_properties() { priority= 3; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; }; class Json_schema_unevaluated_properties : public Json_schema_additional_and_unevaluated { public: Json_schema_unevaluated_properties() { priority= 4; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; }; typedef struct pattern_to_property : public Sql_alloc { Regexp_processor_pcre re; Item *pattern; List<Json_schema_keyword> *curr_schema; }st_pattern_to_property; class Json_schema_pattern_properties : public Json_schema_keyword { private: Item_string *str; List<st_pattern_to_property> pattern_properties; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_pattern_properties() { priority= 2; } ~Json_schema_pattern_properties() { str= NULL; if (!pattern_properties.is_empty()) { st_pattern_to_property *curr_pattern_to_property= NULL; List_iterator<st_pattern_to_property> it(pattern_properties); while((curr_pattern_to_property= it++)) { curr_pattern_to_property->re.cleanup(); curr_pattern_to_property->pattern= NULL; delete curr_pattern_to_property; curr_pattern_to_property= nullptr; } } } bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, const uchar *k_end) override; }; class Json_schema_max_prop : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_min_prop : public Json_schema_keyword { public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_required : public Json_schema_keyword { private: List <String> required_properties; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; typedef struct dependent_keyowrds { String *property; List <String> dependents; } st_dependent_keywords; class Json_schema_dependent_required : public Json_schema_keyword { private: List<st_dependent_keywords> dependent_required; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; enum logic_enum { HAS_ALL_OF= 2, HAS_ANY_OF= 4, HAS_ONE_OF= 8, HAS_NOT= 16}; class Json_schema_logic : public Json_schema_keyword { protected: uint logic_flag; List <List_schema_keyword> schema_items; Json_schema_keyword *alternate_choice1, *alternate_choice2; public: bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; Json_schema_logic() { logic_flag= 0; alternate_choice1= alternate_choice2= NULL; priority= 1; } virtual bool validate_count(uint* count, uint* total) { return false; } void set_alternate_schema_choice(Json_schema_keyword *schema1, Json_schema_keyword* schema2) override { alternate_choice1= schema1; alternate_choice2= schema2; } bool check_validation(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL); }; class Json_schema_not : public Json_schema_logic { private: List <Json_schema_keyword> schema_list; public: Json_schema_not() { logic_flag= HAS_NOT; } bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; bool validate_count(uint *count, uint *total) override { return *count !=0; } }; class Json_schema_one_of : public Json_schema_logic { public: Json_schema_one_of() { logic_flag= HAS_ONE_OF; } bool validate_count(uint *count, uint *total) override { return !(*count == 1); } }; class Json_schema_any_of : public Json_schema_logic { public: Json_schema_any_of() { logic_flag= HAS_ANY_OF; } bool validate_count(uint *count, uint *total) override { return *count == 0; } }; class Json_schema_all_of : public Json_schema_logic { public: Json_schema_all_of() { logic_flag= HAS_ALL_OF; } bool validate_count(uint *count, uint *total) override { return *count != *total; } }; class Json_schema_conditional : public Json_schema_keyword { private: Json_schema_keyword *if_cond, *else_cond, *then_cond; public: List<Json_schema_keyword> conditions_schema; Json_schema_conditional() { if_cond= NULL; then_cond= NULL; else_cond= NULL; } bool validate(const json_engine_t *je, const uchar *k_start= NULL, const uchar *k_end= NULL) override; bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; void set_conditions(Json_schema_keyword *if_val, Json_schema_keyword* then_val, Json_schema_keyword *else_val) { if_cond= if_val; then_cond= then_val; else_cond= else_val; } List<Json_schema_keyword>* get_validation_keywords() override { return &conditions_schema; } }; class Json_schema_if : public Json_schema_conditional { }; class Json_schema_else : public Json_schema_conditional { }; class Json_schema_then : public Json_schema_conditional { }; class Json_schema_media_string : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; class Json_schema_reference : public Json_schema_keyword { public: bool handle_keyword(THD *thd, json_engine_t *je, const char* key_start, const char* key_end, List<Json_schema_keyword> *all_keywords) override; }; bool create_object_and_handle_keyword(THD *thd, json_engine_t *je, List<Json_schema_keyword> *keyword_list, List<Json_schema_keyword> *all_keywords); const uchar *get_key_name_for_property(const void *key_name, size_t *length, my_bool); const uchar *get_key_name_for_func(const void *key_name, size_t *length, my_bool); enum keyword_flag { JSON_SCHEMA_COMMON_KEYWORD= 0, JSON_SCHEMA_NUMBER_KEYWORD= 1, JSON_SCHEMA_STRING_KEYWORD= 2, JSON_SCHEMA_ARRAY_KEYWORD= 3, JSON_SCHEMA_OBJECT_KEYWORD= 4, JSON_SCHEMA_LOGIC_KEYWORD= 5, JSON_SCHEMA_CONDITION_KEYWORD= 6, JSON_SCHEMA_ANNOTATION_KEYWORD= 7, JSON_SCHEMA_FORMAT_KEYWORD= 8, JSON_SCHEMA_MEDIA_KEYWORD= 9, JSON_SCHEMA_REFERENCE_KEYWORD= 10, JSON_SCHEMA_EMPTY_KEYWORD= 11 }; typedef struct st_json_schema_keyword_map { LEX_CSTRING func_name; Json_schema_keyword*(*func)(THD*); enum keyword_flag flag; } json_schema_keyword_map; bool setup_json_schema_keyword_hash(); void cleanup_json_schema_keyword_hash(); #endif char_buffer.h 0000644 00000006141 15156036145 0007173 0 ustar 00 #ifndef CHAR_BUFFER_INCLUDED #define CHAR_BUFFER_INCLUDED /* Copyright (c) 2023, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* A string buffer with length. This template class is useful to store things like database, table names, whose maximum length a small fixed known value. Mainly to be used as stack variables to store temporary values. Can store exact string copies or casefolded string copies. The stored value is returned as a LEX_CSTRING. */ template<size_t buff_sz> class CharBuffer { char m_buff[buff_sz + 1 /* one extra byte for '\0' */]; size_t m_length; bool is_sane() const { return m_length <= buff_sz; // One byte is still left for '\0' } bool buffer_overlaps(const LEX_CSTRING &str) const { return str.str + str.length >= m_buff && str.str <= m_buff + sizeof(m_buff); } public: constexpr size_t max_data_size() const { return buff_sz; // The maximum data size, without the trailing '\0' byte. } CharBuffer() :m_length(0) { m_buff[0]= '\0'; } CharBuffer<buff_sz> & copy_bin(const LEX_CSTRING &str) { DBUG_ASSERT(!buffer_overlaps(str)); m_length= MY_MIN(buff_sz, str.length); memcpy(m_buff, str.str, m_length); m_buff[m_length]= '\0'; return *this; } CharBuffer<buff_sz> & copy_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str) { DBUG_ASSERT(!buffer_overlaps(str)); m_length= cs->cset->casedn(cs, str.str, str.length, m_buff, buff_sz); /* casedn() never writes outsize of buff_sz (unless a bug in casedn()), so it's safe to write '\0' at the position m_length: */ DBUG_ASSERT(is_sane()); m_buff[m_length]= '\0'; return *this; } CharBuffer<buff_sz> & copy_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str, bool casedn) { casedn ? copy_casedn(cs, str) : copy_bin(str); return *this; } // Append a string with casedn conversion CharBuffer<buff_sz> & append_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str) { DBUG_ASSERT(is_sane()); DBUG_ASSERT(!buffer_overlaps(str)); size_t casedn_length= cs->casedn(str.str, str.length, m_buff + m_length, buff_sz - m_length); m_length+= casedn_length; DBUG_ASSERT(is_sane()); m_buff[m_length]= '\0'; return *this; } LEX_CSTRING to_lex_cstring() const { return LEX_CSTRING{m_buff, m_length}; } const char *ptr() const { return m_buff; } size_t length() const { return m_length; } }; #endif // CHAR_BUFFER_INCLUDED table_cache.h 0000644 00000010210 15156036145 0007127 0 ustar 00 #ifndef TABLE_CACHE_H_INCLUDED #define TABLE_CACHE_H_INCLUDED /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2011 Monty Program Ab Copyright (C) 2013 Sergey Vojtovich and MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ struct Share_free_tables { typedef I_P_List <TABLE, TABLE_share> List; List list; /** Avoid false sharing between instances */ char pad[CPU_LEVEL1_DCACHE_LINESIZE]; }; struct TDC_element { uchar m_key[NAME_LEN + 1 + NAME_LEN + 1]; uint m_key_length; bool flushed; TABLE_SHARE *share; /** Protects ref_count, m_flush_tickets, all_tables, flushed, all_tables_refs. */ mysql_mutex_t LOCK_table_share; mysql_cond_t COND_release; TDC_element *next, **prev; /* Link to unused shares */ uint ref_count; /* How many TABLE objects uses this */ uint all_tables_refs; /* Number of refs to all_tables */ /** List of tickets representing threads waiting for the share to be flushed. */ Wait_for_flush_list m_flush_tickets; /* Doubly-linked (back-linked) lists of used and unused TABLE objects for this share. */ All_share_tables_list all_tables; /** Avoid false sharing between TDC_element and free_tables */ char pad[CPU_LEVEL1_DCACHE_LINESIZE]; Share_free_tables free_tables[1]; inline void wait_for_refs(uint my_refs); void flush(THD *thd, bool mark_flushed); void flush_unused(bool mark_flushed); }; extern ulong tdc_size; extern ulong tc_size; extern uint32 tc_instances; extern bool tdc_init(void); extern void tdc_start_shutdown(void); extern void tdc_deinit(void); extern ulong tdc_records(void); extern void tdc_purge(bool all); extern TDC_element *tdc_lock_share(THD *thd, const char *db, const char *table_name); extern void tdc_unlock_share(TDC_element *element); int tdc_share_is_cached(THD *thd, const char *db, const char *table_name); extern TABLE_SHARE *tdc_acquire_share(THD *thd, TABLE_LIST *tl, uint flags, TABLE **out_table= 0); extern void tdc_release_share(TABLE_SHARE *share); void tdc_remove_referenced_share(THD *thd, TABLE_SHARE *share); void tdc_remove_table(THD *thd, const char *db, const char *table_name); extern int tdc_wait_for_old_version(THD *thd, const char *db, const char *table_name, ulong wait_timeout, uint deadlock_weight); extern int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, bool no_dups= false); extern uint tc_records(void); int show_tc_active_instances(THD *thd, SHOW_VAR *var, void *buff, system_status_var *, enum enum_var_type scope); extern void tc_purge(); extern void tc_add_table(THD *thd, TABLE *table); extern void tc_release_table(TABLE *table); extern TABLE *tc_acquire_table(THD *thd, TDC_element *element); /** Create a table cache key for non-temporary table. @param key Buffer for key (must be at least NAME_LEN*2+2 bytes). @param db Database name. @param table_name Table name. @return Length of key. */ inline uint tdc_create_key(char *key, const char *db, const char *table_name) { /* In theory caller should ensure that both db and table_name are not longer than NAME_LEN bytes. In practice we play safe to avoid buffer overruns. */ return (uint) (strmake(strmake(key, db, NAME_LEN) + 1, table_name, NAME_LEN) - key + 1); } #endif /* TABLE_CACHE_H_INCLUDED */ sql_table.h 0000644 00000023030 15156036145 0006667 0 ustar 00 /* Copyright (c) 2006, 2014, Oracle and/or its affiliates. Copyright (c) 2011, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TABLE_INCLUDED #define SQL_TABLE_INCLUDED #include <my_sys.h> // pthread_mutex_t #include "m_string.h" // LEX_CUSTRING #include "lex_charset.h" #define ERROR_INJECT(code) \ ((DBUG_IF("crash_" code) && (DBUG_SUICIDE(), 0)) || \ (DBUG_IF("fail_" code) && (my_error(ER_UNKNOWN_ERROR, MYF(0)), 1))) class Alter_info; class Alter_table_ctx; class Column_definition; class Create_field; struct TABLE_LIST; class THD; struct TABLE; struct handlerton; class handler; class String; typedef struct st_ha_check_opt HA_CHECK_OPT; struct HA_CREATE_INFO; struct Table_specification_st; typedef struct st_key KEY; typedef struct st_key_cache KEY_CACHE; typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE; typedef struct st_order ORDER; typedef struct st_ddl_log_state DDL_LOG_STATE; enum enum_explain_filename_mode { EXPLAIN_ALL_VERBOSE= 0, EXPLAIN_PARTITIONS_VERBOSE, EXPLAIN_PARTITIONS_AS_COMMENT }; /* depends on errmsg.txt Database `db`, Table `t` ... */ #define EXPLAIN_FILENAME_MAX_EXTRA_LENGTH 63 /* See mysql_write_frm function comment for explanations of these flags */ #define WFRM_WRITE_SHADOW 1 #define WFRM_INSTALL_SHADOW 2 #define WFRM_KEEP_SHARE 4 #define WFRM_WRITE_CONVERTED_TO 8 #define WFRM_BACKUP_ORIGINAL 16 #define WFRM_ALTER_INFO_PREPARED 32 /* Flags for conversion functions. */ static const uint FN_FROM_IS_TMP= 1 << 0; static const uint FN_TO_IS_TMP= 1 << 1; static const uint FN_IS_TMP= FN_FROM_IS_TMP | FN_TO_IS_TMP; static const uint NO_FRM_RENAME= 1 << 2; static const uint FRM_ONLY= 1 << 3; /** Don't remove table in engine. Remove only .FRM and maybe .PAR files. */ static const uint NO_HA_TABLE= 1 << 4; /** Don't resolve MySQL's fake "foo.sym" symbolic directory names. */ static const uint SKIP_SYMDIR_ACCESS= 1 << 5; /** Don't check foreign key constraints while renaming table */ static const uint NO_FK_CHECKS= 1 << 6; /* Don't delete .par table in quick_rm_table() */ static const uint NO_PAR_TABLE= 1 << 7; uint filename_to_tablename(const char *from, char *to, size_t to_length, bool stay_quiet = false); uint tablename_to_filename(const char *from, char *to, size_t to_length); uint check_n_cut_mysql50_prefix(const char *from, char *to, size_t to_length); bool check_mysql50_prefix(const char *name); uint build_table_filename(char *buff, size_t bufflen, const char *db, const char *table, const char *ext, uint flags); uint build_table_shadow_filename(char *buff, size_t bufflen, ALTER_PARTITION_PARAM_TYPE *lpt, bool backup= false); void build_lower_case_table_filename(char *buff, size_t bufflen, const LEX_CSTRING *db, const LEX_CSTRING *table, uint flags); uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen); bool add_keyword_to_query(THD *thd, String *result, const LEX_CSTRING *keyword, const LEX_CSTRING *add); /* mysql_create_table_no_lock can be called in one of the following mutually exclusive situations: - Just a normal ordinary CREATE TABLE statement that explicitly defines the table structure. - CREATE TABLE ... SELECT. It is special, because only in this case, the list of fields is allowed to have duplicates, as long as one of the duplicates comes from the select list, and the other doesn't. For example in CREATE TABLE t1 (a int(5) NOT NUL) SELECT b+10 as a FROM t2; the list in alter_info->create_list will have two fields `a`. - ALTER TABLE, that creates a temporary table #sql-xxx, which will be later renamed to replace the original table. - ALTER TABLE as above, but which only modifies the frm file, it only creates an frm file for the #sql-xxx, the table in the engine is not created. - Assisted discovery, CREATE TABLE statement without the table structure. These situations are distinguished by the following "create table mode" values, where a CREATE ... SELECT is denoted by any non-negative number (which should be the number of fields in the SELECT ... part), and other cases use constants as defined below. */ #define C_CREATE_SELECT(X) ((X) > 0 ? (X) : 0) #define C_ORDINARY_CREATE 0 #define C_ASSISTED_DISCOVERY -1 #define C_ALTER_TABLE -2 #define C_ALTER_TABLE_FRM_ONLY -3 int mysql_create_table_no_lock(THD *thd, DDL_LOG_STATE *ddl_log_state, DDL_LOG_STATE *ddl_log_state_rm, Table_specification_st *create_info, Alter_info *alter_info, bool *is_trans, int create_table_mode, TABLE_LIST *table); handler *mysql_create_frm_image(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, int create_table_mode, KEY **key_info, uint *key_count, LEX_CUSTRING *frm); int mysql_discard_or_import_tablespace(THD *thd, TABLE_LIST *table_list, bool discard); bool mysql_prepare_alter_table(THD *thd, TABLE *table, Table_specification_st *create_info, Alter_info *alter_info, Alter_table_ctx *alter_ctx); bool mysql_trans_prepare_alter_copy_data(THD *thd); bool mysql_trans_commit_alter_copy_data(THD *thd); bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *new_name, Table_specification_st *create_info, TABLE_LIST *table_list, class Recreate_info *recreate_info, Alter_info *alter_info, uint order_num, ORDER *order, bool ignore, bool if_exists); bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, bool *metadata_equal); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, class Recreate_info *recreate_info, bool table_copy); bool mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db, const LEX_CSTRING *old_name, const LEX_CSTRING *new_db, const LEX_CSTRING *new_name, LEX_CUSTRING *id, uint flags); bool mysql_backup_table(THD* thd, TABLE_LIST* table_list); bool mysql_restore_table(THD* thd, TABLE_LIST* table_list); template<typename T> class List; void fill_checksum_table_metadata_fields(THD *thd, List<Item> *fields); bool mysql_checksum_table(THD* thd, TABLE_LIST* table_list, HA_CHECK_OPT* check_opt); bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool drop_sequence, bool dont_log_query); int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, const LEX_CSTRING *db, DDL_LOG_STATE *ddl_log_state, bool if_exists, bool drop_temporary, bool drop_view, bool drop_sequence, bool dont_log_query, bool dont_free_locks); bool log_drop_table(THD *thd, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name, const LEX_CSTRING *handler, bool partitioned, const LEX_CUSTRING *id, bool temporary_table); bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db, const LEX_CSTRING *table_name, uint flags, const char *table_path=0); void close_cached_table(THD *thd, TABLE *table); void sp_prepare_create_field(THD *thd, Column_definition *sql_field); bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags); int write_bin_log(THD *thd, bool clear_error, char const *query, ulong query_length, bool is_trans= FALSE); int write_bin_log_with_if_exists(THD *thd, bool clear_error, bool is_trans, bool add_if_exists, bool commit_alter= false); void promote_first_timestamp_column(List<Create_field> *column_definitions); /* These prototypes where under INNODB_COMPATIBILITY_HOOKS. */ uint explain_filename(THD* thd, const char *from, char *to, uint to_length, enum_explain_filename_mode explain_mode); extern MYSQL_PLUGIN_IMPORT const LEX_CSTRING primary_key_name; bool check_engine(THD *, const char *, const char *, HA_CREATE_INFO *); #endif /* SQL_TABLE_INCLUDED */ sql_plist.h 0000644 00000017037 15156036145 0006745 0 ustar 00 #ifndef SQL_PLIST_H #define SQL_PLIST_H /* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ template <typename T, typename L> class I_P_List_iterator; class I_P_List_null_counter; template <typename T> class I_P_List_no_push_back; /** Intrusive parameterized list. Unlike I_List does not require its elements to be descendant of ilink class and therefore allows them to participate in several such lists simultaneously. Unlike List is doubly-linked list and thus supports efficient deletion of element without iterator. @param T Type of elements which will belong to list. @param B Class which via its methods specifies which members of T should be used for participating in this list. Here is typical layout of such class: struct B { static inline T **next_ptr(T *el) { return &el->next; } static inline T ***prev_ptr(T *el) { return &el->prev; } }; @param C Policy class specifying how counting of elements in the list should be done. Instance of this class is also used as a place where information about number of list elements is stored. @sa I_P_List_null_counter, I_P_List_counter @param I Policy class specifying whether I_P_List should support efficient push_back() operation. Instance of this class is used as place where we store information to support this operation. @sa I_P_List_no_push_back, I_P_List_fast_push_back. */ template <typename T, typename B, typename C = I_P_List_null_counter, typename I = I_P_List_no_push_back<T> > class I_P_List : public C, public I { T *m_first; /* Do not prohibit copying of I_P_List object to simplify their usage in backup/restore scenarios. Note that performing any operations on such is a bad idea. */ public: I_P_List() : I(&m_first), m_first(NULL) {}; /* empty() is used in many places in the code instead of a constructor, to initialize a bzero-ed I_P_List instance. */ inline void empty() { m_first= NULL; C::reset(); I::set_last(&m_first); } inline bool is_empty() const { return (m_first == NULL); } inline void push_front(T* a) { *B::next_ptr(a)= m_first; if (m_first) *B::prev_ptr(m_first)= B::next_ptr(a); else I::set_last(B::next_ptr(a)); m_first= a; *B::prev_ptr(a)= &m_first; C::inc(); } inline void push_back(T *a) { T **last= I::get_last(); *B::next_ptr(a)= *last; *last= a; *B::prev_ptr(a)= last; I::set_last(B::next_ptr(a)); C::inc(); } inline void insert_after(T *pos, T *a) { if (pos == NULL) push_front(a); else { *B::next_ptr(a)= *B::next_ptr(pos); *B::prev_ptr(a)= B::next_ptr(pos); *B::next_ptr(pos)= a; if (*B::next_ptr(a)) { T *old_next= *B::next_ptr(a); *B::prev_ptr(old_next)= B::next_ptr(a); } else I::set_last(B::next_ptr(a)); C::inc(); } } inline void remove(T *a) { T *next= *B::next_ptr(a); if (next) *B::prev_ptr(next)= *B::prev_ptr(a); else I::set_last(*B::prev_ptr(a)); **B::prev_ptr(a)= next; C::dec(); } inline T* front() { return m_first; } inline const T *front() const { return m_first; } inline T* pop_front() { T *result= front(); if (result) remove(result); return result; } void swap(I_P_List<T, B, C> &rhs) { swap_variables(T *, m_first, rhs.m_first); I::swap(rhs); if (m_first) *B::prev_ptr(m_first)= &m_first; else I::set_last(&m_first); if (rhs.m_first) *B::prev_ptr(rhs.m_first)= &rhs.m_first; else I::set_last(&rhs.m_first); C::swap(rhs); } typedef B Adapter; typedef I_P_List<T, B, C, I> Base; typedef I_P_List_iterator<T, Base> Iterator; typedef I_P_List_iterator<const T, Base> Const_Iterator; friend class I_P_List_iterator<T, Base>; friend class I_P_List_iterator<const T, Base>; }; /** Iterator for I_P_List. */ template <typename T, typename L> class I_P_List_iterator { const L *list; T *current; public: I_P_List_iterator(const L &a) : list(&a), current(a.m_first) {} I_P_List_iterator(const L &a, T* current_arg) : list(&a), current(current_arg) {} inline void init(const L &a) { list= &a; current= a.m_first; } /** Operator for it++ @note since we save next element pointer, caller may remove current element. Such modification doesn't invalidate iterator. */ inline T* operator++(int) { T *result= current; if (result) current= *L::Adapter::next_ptr(current); return result; } /* Operator for ++it */ inline T* operator++() { current= *L::Adapter::next_ptr(current); return current; } inline void rewind() { current= list->m_first; } }; /** Hook class which via its methods specifies which members of T should be used for participating in a intrusive list. */ template <typename T, T* T::*next, T** T::*prev> struct I_P_List_adapter { static inline T **next_ptr(T *el) { return &(el->*next); } static inline const T* const* next_ptr(const T *el) { return &(el->*next); } static inline T ***prev_ptr(T *el) { return &(el->*prev); } }; /** Element counting policy class for I_P_List to be used in cases when no element counting should be done. */ class I_P_List_null_counter { protected: void reset() {} void inc() {} void dec() {} void swap(I_P_List_null_counter &) {} }; /** Element counting policy class for I_P_List which provides basic element counting. */ class I_P_List_counter { uint m_counter; protected: I_P_List_counter() : m_counter (0) {} void reset() {m_counter= 0;} void inc() {m_counter++;} void dec() {m_counter--;} void swap(I_P_List_counter &rhs) { swap_variables(uint, m_counter, rhs.m_counter); } public: uint elements() const { return m_counter; } }; /** A null insertion policy class for I_P_List to be used in cases when push_back() operation is not necessary. */ template <typename T> class I_P_List_no_push_back { protected: I_P_List_no_push_back(T **) {} void set_last(T **) {} /* T** get_last() const method is intentionally left unimplemented in order to prohibit usage of push_back() method in lists which use this policy. */ void swap(I_P_List_no_push_back<T> &) {} }; /** An insertion policy class for I_P_List which can be used when fast push_back() operation is required. */ template <typename T> class I_P_List_fast_push_back { T **m_last; protected: I_P_List_fast_push_back(T **a) : m_last(a) { }; void set_last(T **a) { m_last= a; } T** get_last() const { return m_last; } void swap(I_P_List_fast_push_back<T> &rhs) { swap_variables(T**, m_last, rhs.m_last); } }; #endif sql_help.h 0000644 00000001743 15156036145 0006537 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_HELP_INCLUDED #define SQL_HELP_INCLUDED class THD; /* Function prototypes */ bool mysqld_help (THD *thd, const char *text); bool mysqld_help_prepare(THD *thd, const char *text, List<Item> *fields); #endif /* SQL_HELP_INCLUDED */ message.h 0000644 00000002253 15156036145 0006351 0 ustar 00 /* To change or add messages mysqld writes to the Windows error log, run mc.exe message.mc and checkin generated messages.h, messages.rc and msg000001.bin under the source control. mc.exe can be installed with Windows SDK, some Visual Studio distributions do not include it. */ // // Values are 32 bit values laid out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +---+-+-+-----------------------+-------------------------------+ // |Sev|C|R| Facility | Code | // +---+-+-+-----------------------+-------------------------------+ // // where // // Sev - is the severity code // // 00 - Success // 01 - Informational // 10 - Warning // 11 - Error // // C - is the Customer code flag // // R - is a reserved bit // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes // // // Define the severity codes // // // MessageId: MSG_DEFAULT // // MessageText: // // %1 // // #define MSG_DEFAULT 0xC0000064L sql_connect.h 0000644 00000007726 15156036146 0007250 0 ustar 00 /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_CONNECT_INCLUDED #define SQL_CONNECT_INCLUDED #include <my_sys.h> /* pthread_handler_t */ #include "mysql_com.h" /* enum_server_command */ #include "structs.h" #include <mysql/psi/mysql_socket.h> #include <hash.h> #include "violite.h" /* Object to hold connect information to be given to the newly created thread */ struct scheduler_functions; class CONNECT : public ilink { public: MYSQL_SOCKET sock; #ifdef _WIN32 HANDLE pipe; CONNECT(HANDLE pipe_arg): pipe(pipe_arg), vio_type(VIO_TYPE_NAMEDPIPE), scheduler(thread_scheduler), thread_id(0), prior_thr_create_utime(0) { count++; } #endif enum enum_vio_type vio_type; scheduler_functions *scheduler; my_thread_id thread_id; /* Own variables */ ulonglong prior_thr_create_utime; static Atomic_counter<uint32_t> count; CONNECT(MYSQL_SOCKET sock_arg, enum enum_vio_type vio_type_arg, scheduler_functions *scheduler_arg): sock(sock_arg), vio_type(vio_type_arg), scheduler(scheduler_arg), thread_id(0), prior_thr_create_utime(0) { count++; } ~CONNECT() { count--; DBUG_ASSERT(vio_type == VIO_CLOSED); } void close_and_delete(uint err); void close_with_error(uint sql_errno, const char *message, uint close_error); THD *create_thd(THD *thd); }; class THD; typedef struct user_conn USER_CONN; void init_max_user_conn(void); void init_global_user_stats(void); void init_global_table_stats(void); void init_global_index_stats(void); void init_global_client_stats(void); void free_max_user_conn(void); void free_global_user_stats(void); void free_global_table_stats(void); void free_global_index_stats(void); void free_global_client_stats(void); pthread_handler_t handle_one_connection(void *arg); void do_handle_one_connection(CONNECT *connect, bool put_in_cache); bool init_new_connection_handler_thread(); void reset_mqh(LEX_USER *lu, bool get_them); bool check_mqh(THD *thd, uint check_command); void time_out_user_resource_limits(THD *thd, USER_CONN *uc); #ifndef NO_EMBEDDED_ACCESS_CHECKS void decrease_user_connections(USER_CONN *uc); #else #define decrease_user_connections(X) do { } while(0) /* nothing */ #endif bool thd_init_client_charset(THD *thd, uint cs_number); void setup_connection_thread_globals(THD *thd); bool thd_prepare_connection(THD *thd); bool thd_is_connection_alive(THD *thd); int thd_set_peer_addr(THD *thd, sockaddr_storage *addr, const char *ip, uint port, bool check_proxy_networks, uint *host_errors); void prepare_new_connection_state(THD* thd); void end_connection(THD *thd); void update_global_user_stats(THD* thd, bool create_user, time_t now); int get_or_create_user_conn(THD *thd, const char *user, const char *host, const USER_RESOURCES *mqh); int check_for_max_user_connections(THD *thd, USER_CONN *uc); extern HASH global_user_stats; extern HASH global_client_stats; extern HASH global_table_stats; extern HASH global_index_stats; extern mysql_mutex_t LOCK_global_user_client_stats; extern mysql_mutex_t LOCK_global_table_stats; extern mysql_mutex_t LOCK_global_index_stats; extern mysql_mutex_t LOCK_stats; #endif /* SQL_CONNECT_INCLUDED */ semisync_master_ack_receiver.h 0000644 00000021005 15156036146 0012631 0 ustar 00 /* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEMISYNC_MASTER_ACK_RECEIVER_DEFINED #define SEMISYNC_MASTER_ACK_RECEIVER_DEFINED #include "my_global.h" #include "my_pthread.h" #include "sql_class.h" #include "semisync.h" #include "socketpair.h" #include <vector> struct Slave :public ilink { THD *thd; Vio vio; #ifdef HAVE_POLL uint m_fds_index; #endif bool active; my_socket sock_fd() const { return vio.mysql_socket.fd; } uint server_id() const { return thd->variables.server_id; } }; typedef I_List<Slave> Slave_ilist; typedef I_List_iterator<Slave> Slave_ilist_iterator; /** Ack_receiver is responsible to control ack receive thread and maintain slave information used by ack receive thread. There are mainly four operations on ack receive thread: start: start ack receive thread stop: stop ack receive thread add_slave: maintain a new semisync slave's information remove_slave: remove a semisync slave's information */ class Ack_receiver : public Repl_semi_sync_base { public: Ack_receiver(); ~Ack_receiver() = default; void cleanup(); /** Notify ack receiver to receive acks on the dump session. It adds the given dump thread into the slave list and wakes up ack thread if it is waiting for any slave coming. @param[in] thd THD of a dump thread. @return it return false if succeeds, otherwise true is returned. */ bool add_slave(THD *thd); /** Notify ack receiver not to receive ack on the dump session. it removes the given dump thread from slave list. @param[in] thd THD of a dump thread. */ void remove_slave(THD *thd); /** Start ack receive thread @return it return false if succeeds, otherwise true is returned. */ bool start(); /** Stop ack receive thread */ void stop(); /** The core of ack receive thread. It monitors all slaves' sockets and receives acks when they come. */ void run(); void set_trace_level(unsigned long trace_level) { m_trace_level= trace_level; } bool running() { return m_status != ST_DOWN; } private: enum status {ST_UP, ST_DOWN, ST_STOPPING}; enum status m_status; /* Protect m_status, m_slaves_changed and m_slaves. ack thread and other session may access the variables at the same time. */ mysql_mutex_t m_mutex; mysql_cond_t m_cond, m_cond_reply; /* If slave list is updated(add or remove). */ bool m_slaves_changed; Slave_ilist m_slaves; pthread_t m_pid; /* Declare them private, so no one can copy the object. */ Ack_receiver(const Ack_receiver &ack_receiver); Ack_receiver& operator=(const Ack_receiver &ack_receiver); void set_stage_info(const PSI_stage_info &stage); void wait_for_slave_connection(THD *thd); }; extern my_socket global_ack_signal_fd; class Ack_listener { public: my_socket local_read_signal; const Slave_ilist &m_slaves; int error; Ack_listener(const Slave_ilist &slaves) :local_read_signal(-1), m_slaves(slaves), error(0) { my_socket pipes[2]; #ifdef _WIN32 error= create_socketpair(pipes); #else if (!pipe(pipes)) { fcntl(pipes[0], F_SETFL, O_NONBLOCK); fcntl(pipes[1], F_SETFL, O_NONBLOCK); } else { pipes[0]= pipes[1]= -1; } #endif /* _WIN32 */ local_read_signal= pipes[0]; global_ack_signal_fd= pipes[1]; } virtual ~Ack_listener() { #ifdef _WIN32 my_socket pipes[2]; pipes[0]= local_read_signal; pipes[1]= global_ack_signal_fd; close_socketpair(pipes); #else if (global_ack_signal_fd >= 0) close(global_ack_signal_fd); if (local_read_signal >= 0) close(local_read_signal); #endif /* _WIN32 */ global_ack_signal_fd= local_read_signal= -1; } int got_error() { return error; } virtual bool has_signal_data()= 0; /* Clear data sent by signal_listener() to abort read */ void clear_signal() { if (has_signal_data()) { char buff[100]; /* Clear the signal message */ #ifndef _WIN32 (void) !read(local_read_signal, buff, sizeof(buff)); #else recv(local_read_signal, buff, sizeof(buff), 0); #endif /* _WIN32 */ } } }; static inline void signal_listener() { #ifndef _WIN32 my_write(global_ack_signal_fd, (uchar*) "a", 1, MYF(0)); #else send(global_ack_signal_fd, "a", 1, 0); #endif /* _WIN32 */ } #ifdef HAVE_POLL #include <sys/poll.h> class Poll_socket_listener final : public Ack_listener { private: std::vector<pollfd> m_fds; public: Poll_socket_listener(const Slave_ilist &slaves) :Ack_listener(slaves) {} virtual ~Poll_socket_listener() = default; bool listen_on_sockets() { return poll(m_fds.data(), m_fds.size(), -1); } bool is_socket_active(const Slave *slave) { return m_fds[slave->m_fds_index].revents & POLLIN; } bool is_socket_hangup(const Slave *slave) { return m_fds[slave->m_fds_index].revents & POLLHUP; } void clear_socket_info(const Slave *slave) { m_fds[slave->m_fds_index].fd= -1; m_fds[slave->m_fds_index].events= 0; } bool has_signal_data() override { /* The signal fd is always first */ return (m_fds[0].revents & POLLIN); } int init_slave_sockets() { Slave_ilist_iterator it(const_cast<Slave_ilist&>(m_slaves)); Slave *slave; uint fds_index= 0; pollfd poll_fd; m_fds.clear(); /* First put in the signal socket */ poll_fd.fd= local_read_signal; poll_fd.events= POLLIN; m_fds.push_back(poll_fd); fds_index++; while ((slave= it++)) { slave->active= 1; pollfd poll_fd; poll_fd.fd= slave->sock_fd(); poll_fd.events= POLLIN; m_fds.push_back(poll_fd); slave->m_fds_index= fds_index++; } return fds_index; } }; #else //NO POLL class Select_socket_listener final : public Ack_listener { private: my_socket m_max_fd; fd_set m_init_fds; fd_set m_fds; public: Select_socket_listener(const Slave_ilist &slaves) :Ack_listener(slaves), m_max_fd(INVALID_SOCKET) {} virtual ~Select_socket_listener() = default; bool listen_on_sockets() { /* Reinitialize the fds with active fds before calling select */ m_fds= m_init_fds; /* select requires max fd + 1 for the first argument */ return select((int) m_max_fd+1, &m_fds, NULL, NULL, NULL); } bool is_socket_active(const Slave *slave) { return FD_ISSET(slave->sock_fd(), &m_fds); } bool is_socket_hangup(const Slave *slave) { return 0; } bool has_signal_data() override { return FD_ISSET(local_read_signal, &m_fds); } void clear_socket_info(const Slave *slave) { FD_CLR(slave->sock_fd(), &m_init_fds); } int init_slave_sockets() { Slave_ilist_iterator it(const_cast<Slave_ilist&>(m_slaves)); Slave *slave; uint fds_index= 0; FD_ZERO(&m_init_fds); m_max_fd= -1; /* First put in the signal socket */ FD_SET(local_read_signal, &m_init_fds); fds_index++; set_if_bigger(m_max_fd, local_read_signal); #ifndef _WIN32 if (local_read_signal > FD_SETSIZE) { int socket_id= local_read_signal; sql_print_error("Semisync slave socket fd is %u. " "select() cannot handle if the socket fd is " "greater than %u (FD_SETSIZE).", socket_id, FD_SETSIZE); return -1; } #endif while ((slave= it++)) { my_socket socket_id= slave->sock_fd(); set_if_bigger(m_max_fd, socket_id); #ifndef _WIN32 if (socket_id > FD_SETSIZE) { sql_print_error("Semisync slave socket fd is %u. " "select() cannot handle if the socket fd is " "greater than %u (FD_SETSIZE).", socket_id, FD_SETSIZE); it.remove(); continue; } #endif //_WIN32 FD_SET(socket_id, &m_init_fds); fds_index++; slave->active= 1; } return fds_index; } my_socket get_max_fd() { return m_max_fd; } }; #endif //HAVE_POLL extern Ack_receiver ack_receiver; #endif my_cpu.h 0000644 00000011367 15156036146 0006230 0 ustar 00 #ifndef MY_CPU_INCLUDED #define MY_CPU_INCLUDED /* Copyright (c) 2013, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* instructions for specific cpu's */ /* Macros for adjusting thread priority (hardware multi-threading) The defines are the same ones used by the linux kernel */ #ifdef _ARCH_PWR8 #ifdef __GLIBC__ #include <sys/platform/ppc.h> /* Very low priority */ #define HMT_very_low() __ppc_set_ppr_very_low() /* Low priority */ #define HMT_low() __ppc_set_ppr_low() /* Medium low priority */ #define HMT_medium_low() __ppc_set_ppr_med_low() /* Medium priority */ #define HMT_medium() __ppc_set_ppr_med() /* Medium high priority */ #define HMT_medium_high() __ppc_set_ppr_med_high() /* High priority */ #define HMT_high() asm volatile("or 3,3,3") #else /* GLIBC */ #if defined(__FreeBSD__) #include <sys/types.h> #include <sys/sysctl.h> #endif #define HMT_very_low() __asm__ volatile ("or 31,31,31") #define HMT_low() __asm__ volatile ("or 1,1,1") #define HMT_medium_low() __asm__ volatile ("or 6,6,6") #define HMT_medium() __asm__ volatile ("or 2,2,2") #define HMT_medium_high() __asm__ volatile ("or 5,5,5") #define HMT_high() asm volatile("or 3,3,3") #endif /* GLIBC */ #else #define HMT_very_low() #define HMT_low() #define HMT_medium_low() #define HMT_medium() #define HMT_medium_high() #define HMT_high() #endif #if defined __i386__ || defined __x86_64__ || defined _WIN32 # define HAVE_PAUSE_INSTRUCTION /* added in Intel Pentium 4 */ #endif #ifdef _WIN32 #elif defined HAVE_PAUSE_INSTRUCTION #elif defined(_ARCH_PWR8) #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) #else # include "my_global.h" # include "my_atomic.h" #endif static inline void MY_RELAX_CPU(void) { #ifdef _WIN32 /* In the Win32 API, the x86 PAUSE instruction is executed by calling the YieldProcessor macro defined in WinNT.h. It is a CPU architecture- independent way by using YieldProcessor. */ YieldProcessor(); #elif defined HAVE_PAUSE_INSTRUCTION /* According to the gcc info page, asm volatile means that the instruction has important side-effects and must not be removed. Also asm volatile may trigger a memory barrier (spilling all registers to memory). */ #ifdef __SUNPRO_CC asm ("pause" ); #else __asm__ __volatile__ ("pause"); #endif #elif defined(_ARCH_PWR8) /* Changed from __ppc_get_timebase for musl and clang compatibility */ __builtin_ppc_get_timebase(); #elif defined __GNUC__ && defined __riscv /* The GCC-only __builtin_riscv_pause() or the pause instruction is encoded like a fence instruction with special parameters. On RISC-V implementations that do not support arch=+zihintpause this instruction could be interpreted as a more expensive memory fence; it should not be an illegal instruction. */ __asm__ volatile(".long 0x0100000f" ::: "memory"); #elif defined __GNUC__ /* Mainly, prevent the compiler from optimizing away delay loops */ __asm__ __volatile__ ("":::"memory"); #endif } #ifdef HAVE_PAUSE_INSTRUCTION # ifdef __cplusplus extern "C" { # endif extern unsigned my_cpu_relax_multiplier; void my_cpu_init(void); # ifdef __cplusplus } # endif #else # define my_cpu_relax_multiplier 200 # define my_cpu_init() /* nothing */ #endif /* LF_BACKOFF should be used to improve performance on hyperthreaded CPUs. Intel recommends to use it in spin loops also on non-HT machines to reduce power consumption (see e.g http://softwarecommunity.intel.com/articles/eng/2004.htm) Running benchmarks for spinlocks implemented with InterlockedCompareExchange and YieldProcessor shows that much better performance is achieved by calling YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting loop count in the range 200-300 brought best results. */ static inline int LF_BACKOFF(void) { unsigned i= my_cpu_relax_multiplier; while (i--) MY_RELAX_CPU(); return 1; } /** Run a delay loop while waiting for a shared resource to be released. @param delay originally, roughly microseconds on 100 MHz Intel Pentium */ static inline void ut_delay(unsigned delay) { unsigned i= my_cpu_relax_multiplier / 4 * delay; HMT_low(); while (i--) MY_RELAX_CPU(); HMT_medium(); } #endif opt_rewrite_date_cmp.h 0000644 00000007536 15156036146 0011136 0 ustar 00 /* Copyright (c) 2023, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef OPT_REWRITE_DATE_CMP_INCLUDED #define OPT_REWRITE_DATE_CMP_INCLUDED class Item_func_eq; class Item_func_ge; class Item_func_gt; class Item_func_le; class Item_func_lt; class Item_bool_rowready_func2; /* @brief Class responsible for rewriting datetime comparison condition. It rewrites non-sargable conditions into sargable. @detail The intent of this class is to do equivalent rewrites as follows: YEAR(col) <= val -> col <= year_end(val) YEAR(col) < val -> col < year_start(val) YEAR(col) >= val -> col >= year_start(val) YEAR(col) > val -> col > year_end(val) YEAR(col) = val -> col >= year_start(val) AND col<=year_end(val) Also the same is done for comparisons with DATE(col): DATE(col) <= val -> col <= day_end(val) if col has a DATE type (not DATETIME), then the rewrite becomes: DATE(col) <= val -> col <= val @usage Date_cmp_func_rewriter rwr(thd, item_func); Item *new_item= rwr.get_rewrite_result(); Returned new_item points to an item that item_func was rewritten to. new_item already has fixed fields (fix_fields() was called). If no rewrite happened, new_item points to the initial item_func parameter @todo Also handle conditions in form "YEAR(date_col) BETWEEN 2014 AND 2017" and "YEAR(col) = c1 AND MONTH(col) = c2" */ class Date_cmp_func_rewriter { public: Date_cmp_func_rewriter(THD* thd, Item_func_eq *item_func); Date_cmp_func_rewriter(THD* thd, Item_func_ge *item_func); Date_cmp_func_rewriter(THD* thd, Item_func_gt *item_func); Date_cmp_func_rewriter(THD* thd, Item_func_le *item_func); Date_cmp_func_rewriter(THD* thd, Item_func_lt *item_func); Item* get_rewrite_result() const { return result; } Date_cmp_func_rewriter() = delete; Date_cmp_func_rewriter(const Date_cmp_func_rewriter&) = delete; Date_cmp_func_rewriter(Date_cmp_func_rewriter&&) = delete; private: bool check_cond_match_and_prepare(Item_bool_rowready_func2 *item_func); Item_field *is_date_rounded_field(Item* item, const Type_handler *comparison_type, Item_func::Functype *out_func_type) const; void rewrite_le_gt_lt_ge(); Item *create_bound(uint month, uint day, const TimeOfDay6 &td) const; Item *create_start_bound() const { return create_bound(1, 1, TimeOfDay6()); } Item *create_end_bound() const { return create_bound(12, 31, TimeOfDay6::end_of_day(field_ref->decimals)); } Item *create_cmp_func(Item_func::Functype func_type, Item *arg1, Item *arg2); THD *thd= nullptr; Item *const_arg_value= nullptr; Item_func::Functype rewrite_func_type= Item_func::UNKNOWN_FUNC; Item_func::Functype argument_func_type= Item_func::UNKNOWN_FUNC; Item_field *field_ref= nullptr; Item *result= nullptr; }; void trace_date_item_rewrite(THD *thd,Item *new_item, Item *old_item); template<typename T> Item* do_date_conds_transformation(THD *thd, T *item) { Date_cmp_func_rewriter rwr(thd, item); /* If the rewrite failed for some reason, we get the original item */ Item *new_item= rwr.get_rewrite_result(); trace_date_item_rewrite(thd, new_item, item); return new_item; } #endif my_stacktrace.h 0000644 00000006217 15156036146 0007563 0 ustar 00 /* Copyright (c) 2001, 2011, Oracle and/or its affiliates. Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_stacktrace_h_ #define _my_stacktrace_h_ #ifdef TARGET_OS_LINUX #if defined (__x86_64__) || defined (__i386__) || \ (defined(__alpha__) && defined(__GNUC__)) #define HAVE_STACKTRACE 1 #endif #elif defined(_WIN32) || defined(HAVE_PRINTSTACK) #define HAVE_STACKTRACE 1 #endif #if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE 1 #endif #define HAVE_WRITE_CORE #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS && HAVE_ABI_CXA_DEMANGLE && \ HAVE_WEAK_SYMBOL #define BACKTRACE_DEMANGLE 1 #endif C_MODE_START #if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack, my_bool silent); int my_safe_print_str(const char* val, size_t max_len); void my_write_core(int sig); # if BACKTRACE_DEMANGLE char *my_demangle(const char *mangled_name, int *status); # endif /* BACKTRACE_DEMANGLE */ # ifdef _WIN32 # define my_setup_stacktrace() void my_set_exception_pointers(EXCEPTION_POINTERS *ep); # else void my_setup_stacktrace(void); # endif /* _WIN32 */ #else # define my_setup_stacktrace() #endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */ #ifndef _WIN32 #define MY_ADDR_RESOLVE_FORK #endif #if defined(HAVE_BFD_H) || defined(MY_ADDR_RESOLVE_FORK) #define HAVE_MY_ADDR_RESOLVE 1 #endif typedef struct { const char *file; const char *func; uint line; } my_addr_loc; #ifdef HAVE_MY_ADDR_RESOLVE int my_addr_resolve(void *ptr, my_addr_loc *loc); const char *my_addr_resolve_init(); #else #define my_addr_resolve_init() (0) #define my_addr_resolve(A,B) (1) #endif #ifdef HAVE_WRITE_CORE void my_write_core(int sig); #endif /** A (very) limited version of snprintf, which writes the result to STDERR. @sa my_safe_snprintf Implemented with simplicity, and async-signal-safety in mind. @note Has an internal buffer capacity of 512 bytes, which should suffice for our signal handling routines. */ size_t my_safe_printf_stderr(const char* fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2); /** Writes up to count bytes from buffer to STDERR. Implemented with simplicity, and async-signal-safety in mind. @param buf Buffer containing data to be written. @param count Number of bytes to write. @returns Number of bytes written. */ size_t my_write_stderr(const void *buf, size_t count); C_MODE_END #endif /* _my_stacktrace_h_ */ item_xmlfunc.h 0000644 00000011052 15156036146 0007415 0 ustar 00 #ifndef ITEM_XMLFUNC_INCLUDED #define ITEM_XMLFUNC_INCLUDED /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file defines all XML functions */ typedef struct my_xml_node_st MY_XML_NODE; /* Structure to store nodeset elements */ class MY_XPATH_FLT { public: uint num; // Absolute position in MY_XML_NODE array uint pos; // Relative position in context uint size; // Context size public: MY_XPATH_FLT(uint32 num_arg, uint32 pos_arg) :num(num_arg), pos(pos_arg), size(0) { } MY_XPATH_FLT(uint32 num_arg, uint32 pos_arg, uint32 size_arg) :num(num_arg), pos(pos_arg), size(size_arg) { } bool append_to(Native *to) const { return to->append((const char*) this, (uint32) sizeof(*this)); } }; class NativeNodesetBuffer: public NativeBuffer<16*sizeof(MY_XPATH_FLT)> { public: const MY_XPATH_FLT &element(uint i) const { const MY_XPATH_FLT *p= (MY_XPATH_FLT*) (ptr() + i * sizeof(MY_XPATH_FLT)); return *p; } uint32 elements() const { return length() / (uint32) sizeof(MY_XPATH_FLT); } }; class Item_xml_str_func: public Item_str_func { protected: /* A helper class to store raw and parsed XML. */ class XML { bool m_cached; String *m_raw_ptr; // Pointer to text representation String m_raw_buf; // Cached text representation String m_parsed_buf; // Array of MY_XML_NODEs, pointing to raw_buffer bool parse(); void reset() { m_cached= false; m_raw_ptr= (String *) 0; } public: XML() { reset(); } void set_charset(CHARSET_INFO *cs) { m_parsed_buf.set_charset(cs); } String *raw() { return m_raw_ptr; } String *parsed() { return &m_parsed_buf; } const MY_XML_NODE *node(uint idx); bool cached() { return m_cached; } bool parse(String *raw, bool cache); bool parse(Item *item, bool cache) { String *res; if (!(res= item->val_str(&m_raw_buf))) { m_raw_ptr= (String *) 0; m_cached= cache; return true; } return parse(res, cache); } }; String m_xpath_query; // XPath query text Item *nodeset_func; XML xml; bool get_xml(XML *xml_arg, bool cache= false) { if (!cache && xml_arg->cached()) return xml_arg->raw() == 0; return xml_arg->parse(args[0], cache); } public: Item_xml_str_func(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) { set_maybe_null(); } Item_xml_str_func(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) { set_maybe_null(); } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; bool const_item() const override { return const_item_cache && (!nodeset_func || nodeset_func->const_item()); } }; class Item_func_xml_extractvalue: public Item_xml_str_func { public: Item_func_xml_extractvalue(THD *thd, Item *a, Item *b): Item_xml_str_func(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("extractvalue") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_xml_extractvalue>(thd, this); } }; class Item_func_xml_update: public Item_xml_str_func { NativeNodesetBuffer tmp_native_value2; String tmp_value3; bool collect_result(String *str, const MY_XML_NODE *cut, const String *replace); public: Item_func_xml_update(THD *thd, Item *a, Item *b, Item *c): Item_xml_str_func(thd, a, b, c) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("updatexml") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_xml_update>(thd, this); } }; #endif /* ITEM_XMLFUNC_INCLUDED */ sql_error.h 0000644 00000116624 15156036146 0006746 0 ustar 00 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_ERROR_H #define SQL_ERROR_H #include "sql_list.h" /* Sql_alloc, MEM_ROOT, list */ #include "sql_type_int.h" // Longlong_hybrid #include "sql_string.h" /* String */ #include "sql_plist.h" /* I_P_List */ #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */ #include "my_time.h" /* MYSQL_TIME */ #include "decimal.h" class THD; class my_decimal; class sp_condition_value; /* Types of LOG warnings, used by note_verbosity */ #define NOTE_VERBOSITY_NORMAL (1U << 0) /* Show warnings about keys parts that cannot be used */ #define NOTE_VERBOSITY_UNUSABLE_KEYS (1U << 1) /* Show warnings in explain for key parts that cannot be used */ #define NOTE_VERBOSITY_EXPLAIN (1U << 2) /////////////////////////////////////////////////////////////////////////// class Sql_state { protected: /** This member is always NUL terminated. */ char m_sqlstate[SQLSTATE_LENGTH + 1]; public: Sql_state() { memset(m_sqlstate, 0, sizeof(m_sqlstate)); } Sql_state(const char *sqlstate) { set_sqlstate(sqlstate); } const char* get_sqlstate() const { return m_sqlstate; } void set_sqlstate(const Sql_state *other) { *this= *other; } void set_sqlstate(const char *sqlstate) { memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH); m_sqlstate[SQLSTATE_LENGTH]= '\0'; } bool eq(const Sql_state *other) const { return strcmp(m_sqlstate, other->m_sqlstate) == 0; } bool has_sql_state() const { return m_sqlstate[0] != '\0'; } /** Checks if this SQL state defines a WARNING condition. Note: m_sqlstate must contain a valid SQL-state. @retval true if this SQL state defines a WARNING condition. @retval false otherwise. */ inline bool is_warning() const { return m_sqlstate[0] == '0' && m_sqlstate[1] == '1'; } /** Checks if this SQL state defines a NOT FOUND condition. Note: m_sqlstate must contain a valid SQL-state. @retval true if this SQL state defines a NOT FOUND condition. @retval false otherwise. */ inline bool is_not_found() const { return m_sqlstate[0] == '0' && m_sqlstate[1] == '2'; } /** Checks if this SQL state defines an EXCEPTION condition. Note: m_sqlstate must contain a valid SQL-state. @retval true if this SQL state defines an EXCEPTION condition. @retval false otherwise. */ inline bool is_exception() const { return m_sqlstate[0] != '0' || m_sqlstate[1] > '2'; } }; class Sql_state_errno: public Sql_state { protected: /** MySQL extension, MYSQL_ERRNO condition item. SQL error number. One of ER_ codes from share/errmsg.txt. Set by set_error_status. */ uint m_sql_errno; public: Sql_state_errno() :m_sql_errno(0) { } Sql_state_errno(uint sql_errno) :m_sql_errno(sql_errno) { } Sql_state_errno(uint sql_errno, const char *sql_state) :Sql_state(sql_state), m_sql_errno(sql_errno) { } /** Get the SQL_ERRNO of this condition. @return the sql error number condition item. */ uint get_sql_errno() const { return m_sql_errno; } void set(uint sql_errno, const char *sqlstate) { m_sql_errno= sql_errno; set_sqlstate(sqlstate); } void clear() { m_sql_errno= 0; } }; class Sql_state_errno_level: public Sql_state_errno { public: /* Enumeration value describing the severity of the error. Note that these enumeration values must correspond to the indices of the sql_print_message_handlers array. */ enum enum_warning_level { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END}; protected: /** Severity (error, warning, note) of this condition. */ enum_warning_level m_level; void assign_defaults(const Sql_state_errno *value); public: /** Get the error level of this condition. @return the error level condition item. */ enum_warning_level get_level() const { return m_level; } Sql_state_errno_level() :m_level(WARN_LEVEL_ERROR) { } Sql_state_errno_level(uint sqlerrno, const char* sqlstate, enum_warning_level level) :Sql_state_errno(sqlerrno, sqlstate), m_level(level) { } Sql_state_errno_level(const Sql_state_errno &state_errno, enum_warning_level level) :Sql_state_errno(state_errno), m_level(level) { } void clear() { m_level= WARN_LEVEL_ERROR; Sql_state_errno::clear(); } }; /* class Sql_user_condition_identity. Instances of this class uniquely idetify user defined conditions (EXCEPTION). SET sql_mode=ORACLE; CREATE PROCEDURE p1 AS a EXCEPTION; BEGIN RAISE a; EXCEPTION WHEN a THEN NULL; END; Currently a user defined condition is identified by a pointer to its parse time sp_condition_value instance. This can change when we add packages. See MDEV-10591. */ class Sql_user_condition_identity { protected: const sp_condition_value *m_user_condition_value; public: Sql_user_condition_identity() :m_user_condition_value(NULL) { } Sql_user_condition_identity(const sp_condition_value *value) :m_user_condition_value(value) { } const sp_condition_value *get_user_condition_value() const { return m_user_condition_value; } void set(const Sql_user_condition_identity &identity) { *this= identity; } void clear() { m_user_condition_value= NULL; } }; /** class Sql_condition_identity. Instances of this class uniquely identify conditions (including user-defined exceptions for sql_mode=ORACLE) and store everything that is needed for handler search purposes in sp_pcontext::find_handler(). */ class Sql_condition_identity: public Sql_state_errno_level, public Sql_user_condition_identity { public: Sql_condition_identity() = default; Sql_condition_identity(const Sql_state_errno_level &st, const Sql_user_condition_identity &ucid) :Sql_state_errno_level(st), Sql_user_condition_identity(ucid) { } Sql_condition_identity(const Sql_state_errno &st, enum_warning_level level, const Sql_user_condition_identity &ucid) :Sql_state_errno_level(st, level), Sql_user_condition_identity(ucid) { } Sql_condition_identity(uint sqlerrno, const char* sqlstate, enum_warning_level level, const Sql_user_condition_identity &ucid) :Sql_state_errno_level(sqlerrno, sqlstate, level), Sql_user_condition_identity(ucid) { } void clear() { Sql_state_errno_level::clear(); Sql_user_condition_identity::clear(); } }; class Sql_condition_items { protected: /** SQL CLASS_ORIGIN condition item. */ String m_class_origin; /** SQL SUBCLASS_ORIGIN condition item. */ String m_subclass_origin; /** SQL CONSTRAINT_CATALOG condition item. */ String m_constraint_catalog; /** SQL CONSTRAINT_SCHEMA condition item. */ String m_constraint_schema; /** SQL CONSTRAINT_NAME condition item. */ String m_constraint_name; /** SQL CATALOG_NAME condition item. */ String m_catalog_name; /** SQL SCHEMA_NAME condition item. */ String m_schema_name; /** SQL TABLE_NAME condition item. */ String m_table_name; /** SQL COLUMN_NAME condition item. */ String m_column_name; /** SQL CURSOR_NAME condition item. */ String m_cursor_name; /** SQL ROW_NUMBER condition item. */ ulong m_row_number; Sql_condition_items() :m_class_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_subclass_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_constraint_schema((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_constraint_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_catalog_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_schema_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_table_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_column_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_cursor_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_row_number(0) { } void clear() { m_class_origin.length(0); m_subclass_origin.length(0); m_constraint_catalog.length(0); m_constraint_schema.length(0); m_constraint_name.length(0); m_catalog_name.length(0); m_schema_name.length(0); m_table_name.length(0); m_column_name.length(0); m_cursor_name.length(0); m_row_number= 0; } }; /** Representation of a SQL condition. A SQL condition can be a completion condition (note, warning), or an exception condition (error, not found). */ class Sql_condition : public Sql_alloc, public Sql_condition_identity, public Sql_condition_items { public: /** Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits to WARN_LEVEL_XXX */ static enum_warning_level time_warn_level(uint warnings) { return MYSQL_TIME_WARN_HAVE_WARNINGS(warnings) ? WARN_LEVEL_WARN : WARN_LEVEL_NOTE; } /** Get the MESSAGE_TEXT of this condition. @return the message text. */ const char* get_message_text() const; /** Get the MESSAGE_OCTET_LENGTH of this condition. @return the length in bytes of the message text. */ int get_message_octet_length() const; private: /* The interface of Sql_condition is mostly private, by design, so that only the following code: - various raise_error() or raise_warning() methods in class THD, - the implementation of SIGNAL / RESIGNAL / GET DIAGNOSTICS - catch / re-throw of SQL conditions in stored procedures (sp_rcontext) is allowed to create / modify a SQL condition. Enforcing this policy prevents confusion, since the only public interface available to the rest of the server implementation is the interface offered by the THD methods (THD::raise_error()), which should be used. */ friend class THD; friend class Warning_info; friend class Sql_cmd_common_signal; friend class Sql_cmd_signal; friend class Sql_cmd_resignal; friend class sp_rcontext; friend class Condition_information_item; /** Default constructor. This constructor is usefull when allocating arrays. Note that the init() method should be called to complete the Sql_condition. */ Sql_condition() :m_mem_root(NULL) { } /** Complete the Sql_condition initialisation. @param mem_root The memory root to use for the condition items of this condition */ void init(MEM_ROOT *mem_root) { DBUG_ASSERT(mem_root != NULL); DBUG_ASSERT(m_mem_root == NULL); m_mem_root= mem_root; } /** Constructor. @param mem_root The memory root to use for the condition items of this condition */ Sql_condition(MEM_ROOT *mem_root) :m_mem_root(mem_root) { DBUG_ASSERT(mem_root != NULL); } Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid) :Sql_condition_identity(Sql_state_errno_level(), ucid), m_mem_root(mem_root) { DBUG_ASSERT(mem_root != NULL); } /** Constructor for a fixed message text. @param mem_root - memory root @param value - the error number and the sql state for this condition @param level - the error level for this condition @param msg - the message text for this condition */ Sql_condition(MEM_ROOT *mem_root, const Sql_condition_identity &value, const char *msg, ulong current_row_for_warning) : Sql_condition_identity(value), m_mem_root(mem_root) { DBUG_ASSERT(value.get_sql_errno() != 0); DBUG_ASSERT(msg != NULL); set_builtin_message_text(msg); m_row_number= current_row_for_warning; } /** Destructor. */ ~Sql_condition() = default; /** Copy optional condition items attributes. @param cond the condition to copy. */ void copy_opt_attributes(const Sql_condition *cond); /** Set the condition message test. @param str Message text, expressed in the character set derived from the server --language option */ void set_builtin_message_text(const char* str); /** Set the CLASS_ORIGIN of this condition. */ void set_class_origin(); /** Set the SUBCLASS_ORIGIN of this condition. */ void set_subclass_origin(); /** Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT' default values of a condition. @param thd - current thread, to access to localized error messages @param from - copy condition items from here (can be NULL) */ void assign_defaults(THD *thd, const Sql_state_errno *from); /** Clear this SQL condition. */ void clear() { Sql_condition_identity::clear(); Sql_condition_items::clear(); m_message_text.length(0); } private: /** Message text, expressed in the character set implied by --language. */ String m_message_text; /** Pointers for participating in the list of conditions. */ Sql_condition *next_in_wi; Sql_condition **prev_in_wi; /** Memory root to use to hold condition item values. */ MEM_ROOT *m_mem_root; }; /////////////////////////////////////////////////////////////////////////// /** Information about warnings of the current connection. */ class Warning_info { /** The type of the counted and doubly linked list of conditions. */ typedef I_P_List<Sql_condition, I_P_List_adapter<Sql_condition, &Sql_condition::next_in_wi, &Sql_condition::prev_in_wi>, I_P_List_counter, I_P_List_fast_push_back<Sql_condition> > Sql_condition_list; /** A memory root to allocate warnings and errors */ MEM_ROOT m_warn_root; /** List of warnings of all severities (levels). */ Sql_condition_list m_warn_list; /** A break down of the number of warnings per severity (level). */ uint m_warn_count[(uint) Sql_condition::WARN_LEVEL_END]; /** The number of warnings of the current statement. Warning_info life cycle differs from statement life cycle -- it may span multiple statements. In that case we get m_current_statement_warn_count 0, whereas m_warn_list is not empty. */ uint m_current_statement_warn_count; /* Row counter, to print in errors and warnings. Not increased in create_sort_index(); may differ from examined_row_count. */ ulong m_current_row_for_warning; /** Used to optionally clear warnings only once per statement. */ ulonglong m_warn_id; /** A pointer to an element of m_warn_list. It determines SQL-condition instance which corresponds to the error state in Diagnostics_area. This is needed for properly processing SQL-conditions in SQL-handlers. When an SQL-handler is found for the current error state in Diagnostics_area, this pointer is needed to remove the corresponding SQL-condition from the Warning_info list. @note m_error_condition might be NULL in the following cases: - Diagnostics_area set to fatal error state (like OOM); - Max number of Warning_info elements has been reached (thus, there is no corresponding SQL-condition object in Warning_info). */ const Sql_condition *m_error_condition; /** Indicates if push_warning() allows unlimited number of warnings. */ bool m_allow_unlimited_warnings; bool initialized; /* Set to 1 if init() has been called */ /** Read only status. */ bool m_read_only; /** Pointers for participating in the stack of Warning_info objects. */ Warning_info *m_next_in_da; Warning_info **m_prev_in_da; List<Sql_condition> m_marked_sql_conditions; public: Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings, bool initialized); ~Warning_info(); /* Allocate memory for structures */ void init(); void free_memory(); private: Warning_info(const Warning_info &rhs); /* Not implemented */ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */ /** Checks if Warning_info contains SQL-condition with the given message. @param message_str Message string. @param message_length Length of message string. @return true if the Warning_info contains an SQL-condition with the given message. */ bool has_sql_condition(const char *message_str, size_t message_length) const; /** Checks if Warning_info contains SQL-condition with the given error id @param sql_errno SQL-condition error number @return true if the Warning_info contains an SQL-condition with the given error id. */ bool has_sql_condition(uint sql_errno) const; /** Reset the warning information. Clear all warnings, the number of warnings, reset current row counter to point to the first row. @param new_id new Warning_info id. */ void clear(ulonglong new_id); /** Only clear warning info if haven't yet done that already for the current query. Allows to be issued at any time during the query, without risk of clearing some warnings that have been generated by the current statement. @todo: This is a sign of sloppy coding. Instead we need to designate one place in a statement life cycle where we call Warning_info::clear(). @param query_id Current query id. */ void opt_clear(ulonglong query_id) { if (query_id != m_warn_id) clear(query_id); } /** Concatenate the list of warnings. It's considered tolerable to lose an SQL-condition in case of OOM-error, or if the number of SQL-conditions in the Warning_info reached top limit. @param thd Thread context. @param source Warning_info object to copy SQL-conditions from. */ void append_warning_info(THD *thd, const Warning_info *source); /** Reset between two COM_ commands. Warnings are preserved between commands, but statement_warn_count indicates the number of warnings of this particular statement only. */ void reset_for_next_command() { m_current_statement_warn_count= 0; } /** Mark active SQL-conditions for later removal. This is done to simulate stacked DAs for HANDLER statements. */ void mark_sql_conditions_for_removal(); /** Unmark SQL-conditions, which were marked for later removal. This is done to simulate stacked DAs for HANDLER statements. */ void unmark_sql_conditions_from_removal() { m_marked_sql_conditions.empty(); } /** Remove SQL-conditions that are marked for deletion. This is done to simulate stacked DAs for HANDLER statements. */ void remove_marked_sql_conditions(); /** Check if the given SQL-condition is marked for removal in this Warning_info instance. @param cond the SQL-condition. @retval true if the given SQL-condition is marked for removal in this Warning_info instance. @retval false otherwise. */ bool is_marked_for_removal(const Sql_condition *cond) const; /** Mark a single SQL-condition for removal (add the given SQL-condition to the removal list of this Warning_info instance). */ void mark_condition_for_removal(Sql_condition *cond) { m_marked_sql_conditions.push_back(cond, &m_warn_root); } /** Used for @@warning_count system variable, which prints the number of rows returned by SHOW WARNINGS. */ ulong warn_count() const { /* This may be higher than warn_list.elements() if we have had more warnings than thd->variables.max_error_count. */ return (m_warn_count[(uint) Sql_condition::WARN_LEVEL_NOTE] + m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] + m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]); } /** The number of errors, or number of rows returned by SHOW ERRORS, also the value of session variable @@error_count. */ ulong error_count() const { return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; } /** The number of conditions (errors, warnings and notes) in the list. */ uint cond_count() const { return m_warn_list.elements(); } /** Id of the warning information area. */ ulonglong id() const { return m_warn_id; } /** Set id of the warning information area. */ void id(ulonglong id_arg) { m_warn_id= id_arg; } /** Do we have any errors and warnings that we can *show*? */ bool is_empty() const { return m_warn_list.is_empty(); } /** Increment the current row counter to point at the next row. */ void inc_current_row_for_warning() { m_current_row_for_warning++; } /** Reset the current row counter. Start counting from the first row. */ void reset_current_row_for_warning(int n) { m_current_row_for_warning= n; } ulong set_current_row_for_warning(ulong row) { ulong old_row= m_current_row_for_warning; m_current_row_for_warning= row; return old_row; } /** Return the current counter value. */ ulong current_row_for_warning() const { return m_current_row_for_warning; } /** Return the number of warnings thrown by the current statement. */ ulong current_statement_warn_count() const { return m_current_statement_warn_count; } /** Make sure there is room for the given number of conditions. */ void reserve_space(THD *thd, uint count); /** Add a new SQL-condition to the current list and increment the respective counters. @param thd Thread context. @param identity SQL-condition identity @param msg SQL-condition message. @return a pointer to the added SQL-condition. */ Sql_condition *push_warning(THD *thd, const Sql_condition_identity *identity, const char* msg, ulong current_row_number); /** Add a new SQL-condition to the current list and increment the respective counters. @param thd Thread context. @param sql_condition SQL-condition to copy values from. @return a pointer to the added SQL-condition. */ Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition); /** Set the read only status for this statement area. This is a privileged operation, reserved for the implementation of diagnostics related statements, to enforce that the statement area is left untouched during execution. The diagnostics statements are: - SHOW WARNINGS - SHOW ERRORS - GET DIAGNOSTICS @param read_only the read only property to set. */ void set_read_only(bool read_only_arg) { m_read_only= read_only_arg; } /** Read only status. @return the read only property. */ bool is_read_only() const { return m_read_only; } /** @return SQL-condition, which corresponds to the error state in Diagnostics_area. @see m_error_condition. */ const Sql_condition *get_error_condition() const { return m_error_condition; } /** Set SQL-condition, which corresponds to the error state in Diagnostics_area. @see m_error_condition. */ void set_error_condition(const Sql_condition *error_condition) { m_error_condition= error_condition; } /** Reset SQL-condition, which corresponds to the error state in Diagnostics_area. @see m_error_condition. */ void clear_error_condition() { m_error_condition= NULL; } // for: // - m_next_in_da / m_prev_in_da // - is_marked_for_removal() friend class Diagnostics_area; }; extern size_t err_conv(char *buff, uint to_length, const char *from, uint from_length, CHARSET_INFO *from_cs); class ErrBuff { protected: mutable char err_buffer[MYSQL_ERRMSG_SIZE]; public: ErrBuff() { err_buffer[0]= '\0'; } const char *ptr() const { return err_buffer; } LEX_CSTRING set_longlong(const Longlong_hybrid &nr) const { int radix= nr.is_unsigned() ? 10 : -10; const char *end= longlong10_to_str(nr.value(), err_buffer, radix); DBUG_ASSERT(end >= err_buffer); return {err_buffer, (size_t) (end - err_buffer)}; } LEX_CSTRING set_double(double nr) const { size_t length= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0); return {err_buffer, length}; } LEX_CSTRING set_decimal(const decimal_t *d) const { int length= sizeof(err_buffer); decimal2string(d, err_buffer, &length, 0, 0, ' '); DBUG_ASSERT(length >= 0); return {err_buffer, (size_t) length}; } LEX_CSTRING set_str(const char *str, size_t len, CHARSET_INFO *cs) const { DBUG_ASSERT(len < UINT_MAX32); len= err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs); return {err_buffer, len}; } LEX_CSTRING set_strq(const char *str, size_t len, CHARSET_INFO *cs) const { DBUG_ASSERT(len < UINT_MAX32); len= err_conv(err_buffer+1, (uint) sizeof(err_buffer)-2, str, (uint) len, cs); err_buffer[0]= err_buffer[len+1]= '\''; err_buffer[len+2]= 0; return {err_buffer, len+2}; } LEX_CSTRING set_mysql_time(const MYSQL_TIME *ltime) const { int length= my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS); DBUG_ASSERT(length >= 0); return {err_buffer, (size_t) length}; } }; class ErrConv: public ErrBuff { public: ErrConv() = default; virtual ~ErrConv() = default; virtual LEX_CSTRING lex_cstring() const= 0; inline const char *ptr() const { return lex_cstring().str; } }; class ErrConvString : public ErrConv { protected: const char *str; size_t len; CHARSET_INFO *cs; public: ErrConvString(const char *str_arg, size_t len_arg, CHARSET_INFO *cs_arg) : ErrConv(), str(str_arg), len(len_arg), cs(cs_arg) {} ErrConvString(const char *str_arg, CHARSET_INFO *cs_arg) : ErrConv(), str(str_arg), len(strlen(str_arg)), cs(cs_arg) {} ErrConvString(const String *s) : ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {} LEX_CSTRING lex_cstring() const override { return set_str(str, len, cs); } }; class ErrConvStringQ : public ErrConvString { public: using ErrConvString::ErrConvString; LEX_CSTRING lex_cstring() const override { return set_strq(str, len, cs); } }; class ErrConvInteger : public ErrConv, public Longlong_hybrid { public: ErrConvInteger(const Longlong_hybrid &nr) : ErrConv(), Longlong_hybrid(nr) { } LEX_CSTRING lex_cstring() const override { return set_longlong(static_cast<Longlong_hybrid>(*this)); } }; class ErrConvDouble: public ErrConv { double num; public: ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {} LEX_CSTRING lex_cstring() const override { return set_double(num); } }; class ErrConvTime : public ErrConv { const MYSQL_TIME *ltime; public: ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {} LEX_CSTRING lex_cstring() const override { return set_mysql_time(ltime); } }; class ErrConvDecimal : public ErrConv { const decimal_t *d; public: ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {} LEX_CSTRING lex_cstring() const override { return set_decimal(d); } }; /////////////////////////////////////////////////////////////////////////// /** Stores status of the currently executed statement. Cleared at the beginning of the statement, and then can hold either OK, ERROR, or EOF status. Can not be assigned twice per statement. */ class Diagnostics_area: public Sql_state_errno, public Sql_user_condition_identity { private: /** The type of the counted and doubly linked list of conditions. */ typedef I_P_List<Warning_info, I_P_List_adapter<Warning_info, &Warning_info::m_next_in_da, &Warning_info::m_prev_in_da>, I_P_List_counter, I_P_List_fast_push_back<Warning_info> > Warning_info_list; public: /** Const iterator used to iterate through the warning list. */ typedef Warning_info::Sql_condition_list::Const_Iterator Sql_condition_iterator; enum enum_diagnostics_status { /** The area is cleared at start of a statement. */ DA_EMPTY= 0, /** Set whenever one calls my_ok(). */ DA_OK, /** Set whenever one calls my_eof(). */ DA_EOF, /** Set whenever one calls my_ok() in PS bulk mode. */ DA_OK_BULK, /** Set whenever one calls my_eof() in PS bulk mode. */ DA_EOF_BULK, /** Set whenever one calls my_error() or my_message(). */ DA_ERROR, /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */ DA_DISABLED }; void set_overwrite_status(bool can_overwrite_status) { m_can_overwrite_status= can_overwrite_status; } /** True if status information is sent to the client. */ bool is_sent() const { return m_is_sent; } void set_is_sent(bool is_sent_arg) { m_is_sent= is_sent_arg; } void set_ok_status(ulonglong affected_rows, ulonglong last_insert_id, const char *message); void set_eof_status(THD *thd); void set_error_status(uint sql_errno); void set_error_status(uint sql_errno, const char *message, const char *sqlstate, const Sql_user_condition_identity &ucid, const Sql_condition *error_condition); void set_error_status(uint sql_errno, const char *message, const char *sqlstate, const Sql_condition *error_condition) { set_error_status(sql_errno, message, sqlstate, Sql_user_condition_identity(), error_condition); } void disable_status(); void reset_diagnostics_area(); bool is_set() const { return m_status != DA_EMPTY; } bool is_error() const { return m_status == DA_ERROR; } bool is_eof() const { return m_status == DA_EOF; } bool is_ok() const { return m_status == DA_OK; } bool is_disabled() const { return m_status == DA_DISABLED; } void set_bulk_execution(bool bulk) { is_bulk_execution= bulk; } bool is_bulk_op() const { return is_bulk_execution; } enum_diagnostics_status status() const { return m_status; } const char *message() const { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK || m_status == DA_OK_BULK || m_status == DA_EOF_BULK); return m_message; } uint sql_errno() const { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state_errno::get_sql_errno(); } const char* get_sqlstate() const { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); } ulonglong affected_rows() const { DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK); return m_affected_rows; } void set_message(const char *msg) { strmake_buf(m_message, msg); } ulonglong last_insert_id() const { DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK); return m_last_insert_id; } uint statement_warn_count() const { DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK || m_status == DA_EOF ||m_status == DA_EOF_BULK ); return m_statement_warn_count; } uint unsafe_statement_warn_count() const { return m_statement_warn_count; } /** Get the current errno, state and id of the user defined condition and return them as Sql_condition_identity. */ Sql_condition_identity get_error_condition_identity() const { DBUG_ASSERT(m_status == DA_ERROR); return Sql_condition_identity(*this /*Sql_state_errno*/, Sql_condition::WARN_LEVEL_ERROR, *this /*Sql_user_condition_identity*/); } /* Used to count any warnings pushed after calling set_ok_status(). */ void increment_warning() { if (m_status != DA_EMPTY) m_statement_warn_count++; } Diagnostics_area(bool initialize); Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings, bool initialize); void init() { m_main_wi.init() ; } void free_memory() { m_main_wi.free_memory() ; } void push_warning_info(Warning_info *wi) { m_wi_stack.push_front(wi); } void pop_warning_info() { DBUG_ASSERT(m_wi_stack.elements() > 0); m_wi_stack.remove(m_wi_stack.front()); } void set_warning_info_id(ulonglong id) { get_warning_info()->id(id); } ulonglong warning_info_id() const { return get_warning_info()->id(); } /** Compare given current warning info and current warning info and see if they are different. They will be different if warnings have been generated or statements that use tables have been executed. This is checked by comparing m_warn_id. @param wi Warning info to compare with current Warning info. @return false if they are equal, true if they are not. */ bool warning_info_changed(const Warning_info *wi) const { return get_warning_info()->id() != wi->id(); } bool is_warning_info_empty() const { return get_warning_info()->is_empty(); } ulong current_statement_warn_count() const { return get_warning_info()->current_statement_warn_count(); } bool has_sql_condition(const char *message_str, size_t message_length) const { return get_warning_info()->has_sql_condition(message_str, message_length); } bool has_sql_condition(uint sql_errno) const { return get_warning_info()->has_sql_condition(sql_errno); } void reset_for_next_command() { get_warning_info()->reset_for_next_command(); } void clear_warning_info(ulonglong id) { get_warning_info()->clear(id); } void opt_clear_warning_info(ulonglong query_id) { get_warning_info()->opt_clear(query_id); } long set_current_row_for_warning(long row) { return get_warning_info()->set_current_row_for_warning(row); } ulong current_row_for_warning() const { return get_warning_info()->current_row_for_warning(); } void inc_current_row_for_warning() { get_warning_info()->inc_current_row_for_warning(); } void reset_current_row_for_warning(int n) { get_warning_info()->reset_current_row_for_warning(n); } bool is_warning_info_read_only() const { return get_warning_info()->is_read_only(); } void set_warning_info_read_only(bool read_only_arg) { get_warning_info()->set_read_only(read_only_arg); } ulong error_count() const { return get_warning_info()->error_count(); } ulong warn_count() const { return get_warning_info()->warn_count(); } uint cond_count() const { return get_warning_info()->cond_count(); } Sql_condition_iterator sql_conditions() const { return get_warning_info()->m_warn_list; } void reserve_space(THD *thd, uint count) { get_warning_info()->reserve_space(thd, count); } Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition) { return get_warning_info()->push_warning(thd, sql_condition); } Sql_condition *push_warning(THD *thd, uint sql_errno_arg, const char* sqlstate, Sql_condition::enum_warning_level level, const Sql_user_condition_identity &ucid, const char* msg, ulong current_row_number) { Sql_condition_identity tmp(sql_errno_arg, sqlstate, level, ucid); return get_warning_info()->push_warning(thd, &tmp, msg, current_row_number); } Sql_condition *push_warning(THD *thd, uint sqlerrno, const char* sqlstate, Sql_condition::enum_warning_level level, const char* msg) { return push_warning(thd, sqlerrno, sqlstate, level, Sql_user_condition_identity(), msg, 0); } void mark_sql_conditions_for_removal() { get_warning_info()->mark_sql_conditions_for_removal(); } void unmark_sql_conditions_from_removal() { get_warning_info()->unmark_sql_conditions_from_removal(); } void remove_marked_sql_conditions() { get_warning_info()->remove_marked_sql_conditions(); } const Sql_condition *get_error_condition() const { return get_warning_info()->get_error_condition(); } void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const { dst_wi->append_warning_info(thd, get_warning_info()); } void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi) { get_warning_info()->append_warning_info(thd, src_wi); } void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi); private: Warning_info *get_warning_info() { return m_wi_stack.front(); } const Warning_info *get_warning_info() const { return m_wi_stack.front(); } private: /** True if status information is sent to the client. */ bool m_is_sent; /** Set to make set_error_status after set_{ok,eof}_status possible. */ bool m_can_overwrite_status; /** Message buffer. Can be used by OK or ERROR status. */ char m_message[MYSQL_ERRMSG_SIZE]; /** The number of rows affected by the last statement. This is semantically close to thd->m_row_count_func, but has a different life cycle. thd->m_row_count_func stores the value returned by function ROW_COUNT() and is cleared only by statements that update its value, such as INSERT, UPDATE, DELETE and few others. This member is cleared at the beginning of the next statement. We could possibly merge the two, but life cycle of thd->m_row_count_func can not be changed. */ ulonglong m_affected_rows; /** Similarly to the previous member, this is a replacement of thd->first_successful_insert_id_in_prev_stmt, which is used to implement LAST_INSERT_ID(). */ ulonglong m_last_insert_id; /** Number of warnings of this last statement. May differ from the number of warnings returned by SHOW WARNINGS e.g. in case the statement doesn't clear the warnings, and doesn't generate them. */ uint m_statement_warn_count; enum_diagnostics_status m_status; my_bool is_bulk_execution; Warning_info m_main_wi; Warning_info_list m_wi_stack; }; /////////////////////////////////////////////////////////////////////////// void convert_error_to_warning(THD *thd); void push_warning(THD *thd, Sql_condition::enum_warning_level level, uint code, const char *msg); void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level, uint code, const char *format, ...); bool mysqld_show_warnings(THD *thd, ulong levels_to_show); size_t convert_error_message(char *to, size_t to_length, CHARSET_INFO *to_cs, const char *from, size_t from_length, CHARSET_INFO *from_cs, uint *errors); extern const LEX_CSTRING warning_level_names[]; bool is_sqlstate_valid(const LEX_CSTRING *sqlstate); /** Checks if the specified SQL-state-string defines COMPLETION condition. This function assumes that the given string contains a valid SQL-state. @param s the condition SQLSTATE. @retval true if the given string defines COMPLETION condition. @retval false otherwise. */ inline bool is_sqlstate_completion(const char *s) { return s[0] == '0' && s[1] == '0'; } #endif // SQL_ERROR_H sql_callback.h 0000644 00000003006 15156036146 0007336 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_CALLBACK_INCLUDED #define SQL_CALLBACK_INCLUDED /** Macro used for an internal callback. The macro will check that the object exists and that the function is defined. If that is the case, it will call the function with the given parameters. If the object or the function is not defined, the callback will be considered successful (nothing needed to be done) and will therefore return no error. */ #define MYSQL_CALLBACK(OBJ, FUNC, PARAMS) \ do { \ if ((OBJ) && ((OBJ)->FUNC)) \ (OBJ)->FUNC PARAMS; \ } while (0) #define MYSQL_CALLBACK_ELSE(OBJ, FUNC, PARAMS, ELSE) \ (((OBJ) && ((OBJ)->FUNC)) ? (OBJ)->FUNC PARAMS : (ELSE)) #endif /* SQL_CALLBACK_INCLUDED */ vers_string.h 0000644 00000004621 15156036147 0007275 0 ustar 00 /* Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef VERS_STRING_INCLUDED #define VERS_STRING_INCLUDED #include "lex_string.h" /* LEX_CSTRING with comparison semantics. */ // db and table names: case sensitive (or insensitive) in table_alias_charset struct Compare_table_names { int operator()(const LEX_CSTRING& a, const LEX_CSTRING& b) const { DBUG_ASSERT(a.str[a.length] == 0); DBUG_ASSERT(b.str[b.length] == 0); return table_alias_charset->strnncoll(a.str, a.length, b.str, b.length); } }; // column names and other identifiers: case insensitive in system_charset_info struct Compare_identifiers { int operator()(const LEX_CSTRING& a, const LEX_CSTRING& b) const { DBUG_ASSERT(a.str != NULL); DBUG_ASSERT(b.str != NULL); DBUG_ASSERT(a.str[a.length] == 0); DBUG_ASSERT(b.str[b.length] == 0); return my_strcasecmp(system_charset_info, a.str, b.str); } }; template <class Compare> struct Lex_cstring_with_compare : public Lex_cstring { public: Lex_cstring_with_compare() = default; Lex_cstring_with_compare(const char *_str, size_t _len) : Lex_cstring(_str, _len) { } Lex_cstring_with_compare(const LEX_CSTRING src) : Lex_cstring(src.str, src.length) { } explicit Lex_cstring_with_compare(const char *_str) : Lex_cstring(_str, strlen(_str)) { } bool streq(const Lex_cstring_with_compare& b) const { return Lex_cstring::length == b.length && 0 == Compare()(*this, b); } operator const char* () const { return str; } operator bool () const { return str != NULL; } }; typedef Lex_cstring_with_compare<Compare_identifiers> Lex_ident; typedef Lex_cstring_with_compare<Compare_table_names> Lex_table_name; #endif // VERS_STRING_INCLUDED ha_partition.h 0000644 00000176656 15156036147 0007433 0 ustar 00 #ifndef HA_PARTITION_INCLUDED #define HA_PARTITION_INCLUDED /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_partition.h" /* part_id_range, partition_element */ #include "queues.h" /* QUEUE */ struct Ordered_blob_storage { String blob; bool set_read_value; Ordered_blob_storage() : set_read_value(false) {} }; #define PAR_EXT ".par" #define PARTITION_BYTES_IN_POS 2 #define ORDERED_PART_NUM_OFFSET sizeof(Ordered_blob_storage **) #define ORDERED_REC_OFFSET (ORDERED_PART_NUM_OFFSET + PARTITION_BYTES_IN_POS) /** Struct used for partition_name_hash */ typedef struct st_part_name_def { uchar *partition_name; uint length; uint32 part_id; my_bool is_subpart; } PART_NAME_DEF; /** class where to save partitions Handler_share's */ class Parts_share_refs { public: uint num_parts; /**< Size of ha_share array */ Handler_share **ha_shares; /**< Storage for each part */ Parts_share_refs() { num_parts= 0; ha_shares= NULL; } ~Parts_share_refs() { uint i; for (i= 0; i < num_parts; i++) delete ha_shares[i]; delete[] ha_shares; } bool init(uint arg_num_parts) { DBUG_ASSERT(!num_parts && !ha_shares); num_parts= arg_num_parts; /* Allocate an array of Handler_share pointers */ ha_shares= new Handler_share *[num_parts]; if (!ha_shares) { num_parts= 0; return true; } memset(ha_shares, 0, sizeof(Handler_share*) * num_parts); return false; } }; class ha_partition; /* Partition Full Text Search info */ struct st_partition_ft_info { struct _ft_vft *please; st_partition_ft_info *next; ha_partition *file; FT_INFO **part_ft_info; }; #ifdef HAVE_PSI_MUTEX_INTERFACE extern PSI_mutex_key key_partition_auto_inc_mutex; #endif /** Partition specific Handler_share. */ class Partition_share : public Handler_share { public: bool auto_inc_initialized; mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */ ulonglong next_auto_inc_val; /**< first non reserved value */ /** Hash of partition names. Initialized in the first ha_partition::open() for the table_share. After that it is read-only, i.e. no locking required. */ bool partition_name_hash_initialized; HASH partition_name_hash; const char *partition_engine_name; /** Storage for each partitions Handler_share */ Parts_share_refs partitions_share_refs; Partition_share() : auto_inc_initialized(false), next_auto_inc_val(0), partition_name_hash_initialized(false), partition_engine_name(NULL), partition_names(NULL) { mysql_mutex_init(key_partition_auto_inc_mutex, &auto_inc_mutex, MY_MUTEX_INIT_FAST); } ~Partition_share() { mysql_mutex_destroy(&auto_inc_mutex); if (partition_names) { my_free(partition_names); } if (partition_name_hash_initialized) { my_hash_free(&partition_name_hash); } } bool init(uint num_parts); /** Release reserved auto increment values not used. @param thd Thread. @param table_share Table Share @param next_insert_id Next insert id (first non used auto inc value). @param max_reserved End of reserved auto inc range. */ void release_auto_inc_if_possible(THD *thd, TABLE_SHARE *table_share, const ulonglong next_insert_id, const ulonglong max_reserved); /** lock mutex protecting auto increment value next_auto_inc_val. */ inline void lock_auto_inc() { mysql_mutex_lock(&auto_inc_mutex); } /** unlock mutex protecting auto increment value next_auto_inc_val. */ inline void unlock_auto_inc() { mysql_mutex_unlock(&auto_inc_mutex); } /** Populate partition_name_hash with partition and subpartition names from part_info. @param part_info Partition info containing all partitions metadata. @return Operation status. @retval false Success. @retval true Failure. */ bool populate_partition_name_hash(partition_info *part_info); /** Get partition name. @param part_id Partition id (for subpartitioned table only subpartition names will be returned.) @return partition name or NULL if error. */ const char *get_partition_name(size_t part_id) const; private: const uchar **partition_names; /** Insert [sub]partition name into partition_name_hash @param name Partition name. @param part_id Partition id. @param is_subpart True if subpartition else partition. @return Operation status. @retval false Success. @retval true Failure. */ bool insert_partition_name_in_hash(const char *name, uint part_id, bool is_subpart); }; /* List of ranges to be scanned by ha_partition's MRR implementation This object is - A KEY_MULTI_RANGE structure (the MRR range) - Storage for the range endpoints that the KEY_MULTI_RANGE has pointers to - list of such ranges (connected through the "next" pointer). */ typedef struct st_partition_key_multi_range { /* Number of the range. The ranges are numbered in the order RANGE_SEQ_IF has emitted them, starting from 1. The numbering in used by ordered MRR scans. */ uint id; uchar *key[2]; /* Sizes of allocated memory in key[]. These may be larger then the actual values as this structure is reused across MRR scans */ uint length[2]; /* The range. key_multi_range.ptr is a pointer to the this PARTITION_KEY_MULTI_RANGE object */ KEY_MULTI_RANGE key_multi_range; // Range id from the SQL layer range_id_t ptr; // The next element in the list of MRR ranges. st_partition_key_multi_range *next; } PARTITION_KEY_MULTI_RANGE; /* List of ranges to be scanned in a certain [sub]partition The idea is that there's a list of ranges to be scanned in the table (formed by PARTITION_KEY_MULTI_RANGE structures), and for each [sub]partition, we only need to scan a subset of that list. PKMR1 --> PKMR2 --> PKMR3 -->... // list of PARTITION_KEY_MULTI_RANGE ^ ^ | | PPKMR1 ----------> PPKMR2 -->... // list of PARTITION_PART_KEY_MULTI_RANGE This way, per-partition lists of PARTITION_PART_KEY_MULTI_RANGE have pointers to the elements of the global list of PARTITION_KEY_MULTI_RANGE. */ typedef struct st_partition_part_key_multi_range { PARTITION_KEY_MULTI_RANGE *partition_key_multi_range; st_partition_part_key_multi_range *next; } PARTITION_PART_KEY_MULTI_RANGE; class ha_partition; /* The structure holding information about range sequence to be used with one partition. (pointer to this is used as seq_init_param for RANGE_SEQ_IF structure when invoking MRR for an individual partition) */ typedef struct st_partition_part_key_multi_range_hld { /* Owner object */ ha_partition *partition; /* id of the partition this structure is for */ uint32 part_id; /* Current range we're iterating through */ PARTITION_PART_KEY_MULTI_RANGE *partition_part_key_multi_range; } PARTITION_PART_KEY_MULTI_RANGE_HLD; extern "C" int cmp_key_part_id(void *key_p, const void *ref1, const void *ref2); extern "C" int cmp_key_rowid_part_id(void *ptr, const void *ref1, const void *ref2); class ha_partition final :public handler { private: enum partition_index_scan_type { partition_index_read= 0, partition_index_first= 1, partition_index_last= 3, partition_index_read_last= 4, partition_read_range = 5, partition_no_index_scan= 6, partition_read_multi_range = 7, partition_ft_read= 8 }; /* Data for the partition handler */ int m_mode; // Open mode uint m_open_test_lock; // Open test_if_locked uchar *m_file_buffer; // Content of the .par file char *m_name_buffer_ptr; // Pointer to first partition name MEM_ROOT m_mem_root; plugin_ref *m_engine_array; // Array of types of the handlers handler **m_file; // Array of references to handler inst. uint m_file_tot_parts; // Debug handler **m_new_file; // Array of references to new handlers handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors LEX_CSTRING *m_connect_string; partition_info *m_part_info; // local reference to partition Field **m_part_field_array; // Part field array locally to save acc uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan st_partition_ft_info *ft_first; st_partition_ft_info *ft_current; /* Current index. When used in key_rec_cmp: If clustered pk, index compare must compare pk if given index is same for two rows. So normally m_curr_key_info[0]= current index and m_curr_key[1]= NULL, and if clustered pk, [0]= current index, [1]= pk, [2]= NULL */ KEY *m_curr_key_info[3]; // Current index const uchar *m_err_rec; // record which gave error QUEUE m_queue; // Prio queue used by sorted read /* Length of an element in m_ordered_rec_buffer. The elements are composed of [part_no] [table->record copy] [underlying_table_rowid] underlying_table_rowid is only stored when the table has no extended keys. */ size_t m_priority_queue_rec_len; /* If true, then sorting records by key value also sorts them by their underlying_table_rowid. */ bool m_using_extended_keys; /* Since the partition handler is a handler on top of other handlers, it is necessary to keep information about what the underlying handler characteristics is. It is not possible to keep any handler instances for this since the MySQL Server sometimes allocating the handler object without freeing them. */ enum enum_handler_status { handler_not_initialized= 0, handler_initialized, handler_opened, handler_closed }; enum_handler_status m_handler_status; uint m_reorged_parts; // Number of reorganised parts uint m_tot_parts; // Total number of partitions; uint m_num_locks; // For engines like ha_blackhole, which needs no locks uint m_last_part; // Last file that we update,write,read part_id_range m_part_spec; // Which parts to scan uint m_scan_value; // Value passed in rnd_init // call uint m_ref_length; // Length of position in this // handler object key_range m_start_key; // index read key range enum partition_index_scan_type m_index_scan_type;// What type of index // scan uint m_top_entry; // Which partition is to // deliver next result uint m_rec_length; // Local copy of record length bool m_ordered; // Ordered/Unordered index scan bool m_create_handler; // Handler used to create table bool m_is_sub_partitioned; // Is subpartitioned bool m_ordered_scan_ongoing; bool m_rnd_init_and_first; bool m_ft_init_and_first; /* If set, this object was created with ha_partition::clone and doesn't "own" the m_part_info structure. */ ha_partition *m_is_clone_of; MEM_ROOT *m_clone_mem_root; /* We keep track if all underlying handlers are MyISAM since MyISAM has a great number of extra flags not needed by other handlers. */ bool m_myisam; // Are all underlying handlers // MyISAM /* We keep track of InnoDB handlers below since it requires proper setting of query_id in fields at index_init and index_read calls. */ bool m_innodb; // Are all underlying handlers // InnoDB bool m_myisammrg; // Are any of the handlers of type MERGE /* When calling extra(HA_EXTRA_CACHE) we do not pass this to the underlying handlers immediately. Instead we cache it and call the underlying immediately before starting the scan on the partition. This is to prevent allocating a READ CACHE for each partition in parallel when performing a full table scan on MyISAM partitioned table. This state is cleared by extra(HA_EXTRA_NO_CACHE). */ bool m_extra_cache; uint m_extra_cache_size; /* The same goes for HA_EXTRA_PREPARE_FOR_UPDATE */ bool m_extra_prepare_for_update; /* Which partition has active cache */ uint m_extra_cache_part_id; void init_handler_variables(); /* Variables for lock structures. */ bool auto_increment_lock; /**< lock reading/updating auto_inc */ /** Flag to keep the auto_increment lock through out the statement. This to ensure it will work with statement based replication. */ bool auto_increment_safe_stmt_log_lock; /** For optimizing ha_start_bulk_insert calls */ MY_BITMAP m_bulk_insert_started; ha_rows m_bulk_inserted_rows; /** used for prediction of start_bulk_insert rows */ enum_monotonicity_info m_part_func_monotonicity_info; part_id_range m_direct_update_part_spec; bool m_pre_calling; bool m_pre_call_use_parallel; /* Keep track of bulk access requests */ bool bulk_access_executing; /** keep track of locked partitions */ MY_BITMAP m_locked_partitions; /** Stores shared auto_increment etc. */ Partition_share *part_share; void sum_copy_info(handler *file); void sum_copy_infos(); void reset_copy_info() override; /** Temporary storage for new partitions Handler_shares during ALTER */ List<Parts_share_refs> m_new_partitions_share_refs; /** Sorted array of partition ids in descending order of number of rows. */ uint32 *m_part_ids_sorted_by_num_of_records; /* Compare function for my_qsort2, for reversed order. */ static int compare_number_of_records(void *me, const void *a, const void *b); /** keep track of partitions to call ha_reset */ MY_BITMAP m_partitions_to_reset; /** partitions that returned HA_ERR_KEY_NOT_FOUND. */ MY_BITMAP m_key_not_found_partitions; bool m_key_not_found; List<String> *m_partitions_to_open; MY_BITMAP m_opened_partitions; /** This is one of the m_file-s that it guaranteed to be opened. */ /** It is set in open_read_partitions() */ handler *m_file_sample; public: handler **get_child_handlers() { return m_file; } ha_partition *get_clone_source() { return m_is_clone_of; } part_id_range *get_part_spec() { return &m_part_spec; } uint get_no_current_part_id() { return NO_CURRENT_PART_ID; } Partition_share *get_part_share() { return part_share; } handler *clone(const char *name, MEM_ROOT *mem_root) override; void set_part_info(partition_info *part_info) override { m_part_info= part_info; m_is_sub_partitioned= part_info->is_sub_partitioned(); } Compare_keys compare_key_parts( const Field &old_field, const Column_definition &new_field, const KEY_PART_INFO &old_part, const KEY_PART_INFO &new_part) const override; void return_record_by_parent() override; bool vers_can_native(THD *thd) override { if (thd->lex->part_info) { // PARTITION BY SYSTEM_TIME is not supported for now return thd->lex->part_info->part_type != VERSIONING_PARTITION; } else { bool can= true; for (uint i= 0; i < m_tot_parts && can; i++) can= can && m_file[i]->vers_can_native(thd); return can; } } /* ------------------------------------------------------------------------- MODULE create/delete handler object ------------------------------------------------------------------------- Object create/delete method. Normally called when a table object exists. There is also a method to create the handler object with only partition information. This is used from mysql_create_table when the table is to be created and the engine type is deduced to be the partition handler. ------------------------------------------------------------------------- */ ha_partition(handlerton *hton, TABLE_SHARE * table); ha_partition(handlerton *hton, partition_info * part_info); ha_partition(handlerton *hton, TABLE_SHARE *share, partition_info *part_info_arg, ha_partition *clone_arg, MEM_ROOT *clone_mem_root_arg); ~ha_partition(); void ha_partition_init(); /* A partition handler has no characteristics in itself. It only inherits those from the underlying handlers. Here we set-up those constants to enable later calls of the methods to retrieve constants from the under- lying handlers. Returns false if not successful. */ bool initialize_partition(MEM_ROOT *mem_root); /* ------------------------------------------------------------------------- MODULE meta data changes ------------------------------------------------------------------------- Meta data routines to CREATE, DROP, RENAME table and often used at ALTER TABLE (update_create_info used from ALTER TABLE and SHOW ..). create_partitioning_metadata is called before opening a new handler object with openfrm to call create. It is used to create any local handler object needed in opening the object in openfrm ------------------------------------------------------------------------- */ int delete_table(const char *from) override; int rename_table(const char *from, const char *to) override; int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info) override; int create_partitioning_metadata(const char *name, const char *old_name, chf_create_flags action_flag, bool ignore_delete_error) override; bool check_if_updates_are_ignored(const char *op) const override; void update_create_info(HA_CREATE_INFO *create_info) override; int change_partitions(HA_CREATE_INFO *create_info, const char *path, ulonglong * const copied, ulonglong * const deleted, const uchar *pack_frm_data, size_t pack_frm_len) override; int drop_partitions(const char *path) override; int rename_partitions(const char *path) override; bool get_no_parts(const char *, uint *num_parts) override { DBUG_ENTER("ha_partition::get_no_parts"); *num_parts= m_tot_parts; DBUG_RETURN(0); } void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share) override; bool check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) override; void update_part_create_info(HA_CREATE_INFO *create_info, uint part_id) { m_file[part_id]->update_create_info(create_info); } void column_bitmaps_signal() override { for (uint i= bitmap_get_first_set(&m_opened_partitions); i < m_tot_parts; i= bitmap_get_next_set(&m_opened_partitions, i)) { m_file[i]->column_bitmaps_signal(); } } private: int copy_partitions(ulonglong * const copied, ulonglong * const deleted); void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, handler *file, const char *part_name, partition_element *p_elem); /* delete_table and rename_table uses very similar logic which is packed into this routine. */ uint del_ren_table(const char *from, const char *to); /* One method to create the table_name.par file containing the names of the underlying partitions, their engine and the number of partitions. And one method to read it in. */ bool create_handler_file(const char *name); bool setup_engine_array(MEM_ROOT *mem_root, handlerton *first_engine); int read_par_file(const char *name); handlerton *get_def_part_engine(const char *name); bool get_from_handler_file(const char *name, MEM_ROOT *mem_root, bool is_clone); bool re_create_par_file(const char *name); bool new_handlers_from_part_info(MEM_ROOT *mem_root); bool create_handlers(MEM_ROOT *mem_root); void clear_handler_file(); int set_up_table_before_create(TABLE *table_arg, const char *partition_name_with_path, HA_CREATE_INFO *info, partition_element *p_elem); partition_element *find_partition_element(uint part_id); bool insert_partition_name_in_hash(const char *name, uint part_id, bool is_subpart); bool populate_partition_name_hash(); Partition_share *get_share(); bool set_ha_share_ref(Handler_share **ha_share) override; void fix_data_dir(char* path); bool init_partition_bitmaps(); void free_partition_bitmaps(); public: /* ------------------------------------------------------------------------- MODULE open/close object ------------------------------------------------------------------------- Open and close handler object to ensure all underlying files and objects allocated and deallocated for query handling is handled properly. ------------------------------------------------------------------------- A handler object is opened as part of its initialisation and before being used for normal queries (not before meta-data changes always. If the object was opened it will also be closed before being deleted. */ int open(const char *name, int mode, uint test_if_locked) override; int close() override; /* ------------------------------------------------------------------------- MODULE start/end statement ------------------------------------------------------------------------- This module contains methods that are used to understand start/end of statements, transaction boundaries, and aid for proper concurrency control. The partition handler need not implement abort and commit since this will be handled by any underlying handlers implementing transactions. There is only one call to each handler type involved per transaction and these go directly to the handlers supporting transactions ------------------------------------------------------------------------- */ THR_LOCK_DATA **store_lock(THD * thd, THR_LOCK_DATA ** to, enum thr_lock_type lock_type) override; int external_lock(THD * thd, int lock_type) override; LEX_CSTRING *engine_name() override { return hton_name(partition_ht()); } /* When table is locked a statement is started by calling start_stmt instead of external_lock */ int start_stmt(THD * thd, thr_lock_type lock_type) override; /* Lock count is number of locked underlying handlers (I assume) */ uint lock_count() const override; /* Call to unlock rows not to be updated in transaction */ void unlock_row() override; /* Check if semi consistent read */ bool was_semi_consistent_read() override; /* Call to hint about semi consistent read */ void try_semi_consistent_read(bool) override; /* NOTE: due to performance and resource issues with many partitions, we only use the m_psi on the ha_partition handler, excluding all partitions m_psi. */ #ifdef HAVE_M_PSI_PER_PARTITION /* Bind the table/handler thread to track table i/o. */ virtual void unbind_psi(); virtual int rebind(); #endif int discover_check_version() override; /* ------------------------------------------------------------------------- MODULE change record ------------------------------------------------------------------------- This part of the handler interface is used to change the records after INSERT, DELETE, UPDATE, REPLACE method calls but also other special meta-data operations as ALTER TABLE, LOAD DATA, TRUNCATE. ------------------------------------------------------------------------- These methods are used for insert (write_row), update (update_row) and delete (delete_row). All methods to change data always work on one row at a time. update_row and delete_row also contains the old row. delete_all_rows will delete all rows in the table in one call as a special optimisation for DELETE from table; Bulk inserts are supported if all underlying handlers support it. start_bulk_insert and end_bulk_insert is called before and after a number of calls to write_row. */ int write_row(const uchar * buf) override; bool start_bulk_update() override; int exec_bulk_update(ha_rows *dup_key_found) override; int end_bulk_update() override; int bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found) override; int update_row(const uchar * old_data, const uchar * new_data) override; int direct_update_rows_init(List<Item> *update_fields) override; int pre_direct_update_rows_init(List<Item> *update_fields) override; int direct_update_rows(ha_rows *update_rows, ha_rows *found_rows) override; int pre_direct_update_rows() override; bool start_bulk_delete() override; int end_bulk_delete() override; int delete_row(const uchar * buf) override; int direct_delete_rows_init() override; int pre_direct_delete_rows_init() override; int direct_delete_rows(ha_rows *delete_rows) override; int pre_direct_delete_rows() override; int delete_all_rows() override; int truncate() override; void start_bulk_insert(ha_rows rows, uint flags) override; int end_bulk_insert() override; private: ha_rows guess_bulk_insert_rows(); void start_part_bulk_insert(THD *thd, uint part_id); long estimate_read_buffer_size(long original_size); public: /* Method for truncating a specific partition. (i.e. ALTER TABLE t1 TRUNCATE PARTITION p). @remark This method is a partitioning-specific hook and thus not a member of the general SE API. */ int truncate_partition(Alter_info *, bool *binlog_stmt); bool is_fatal_error(int error, uint flags) override { if (!handler::is_fatal_error(error, flags) || error == HA_ERR_NO_PARTITION_FOUND || error == HA_ERR_NOT_IN_LOCK_PARTITIONS) return FALSE; return TRUE; } /* ------------------------------------------------------------------------- MODULE full table scan ------------------------------------------------------------------------- This module is used for the most basic access method for any table handler. This is to fetch all data through a full table scan. No indexes are needed to implement this part. It contains one method to start the scan (rnd_init) that can also be called multiple times (typical in a nested loop join). Then proceeding to the next record (rnd_next) and closing the scan (rnd_end). To remember a record for later access there is a method (position) and there is a method used to retrieve the record based on the stored position. The position can be a file position, a primary key, a ROWID dependent on the handler below. ------------------------------------------------------------------------- */ /* unlike index_init(), rnd_init() can be called two times without rnd_end() in between (it only makes sense if scan=1). then the second call should prepare for the new table scan (e.g if rnd_init allocates the cursor, second call should position it to the start of the table, no need to deallocate and allocate it again */ int rnd_init(bool scan) override; int rnd_end() override; int rnd_next(uchar * buf) override; int rnd_pos(uchar * buf, uchar * pos) override; int rnd_pos_by_record(uchar *record) override; void position(const uchar * record) override; /* ------------------------------------------------------------------------- MODULE index scan ------------------------------------------------------------------------- This part of the handler interface is used to perform access through indexes. The interface is defined as a scan interface but the handler can also use key lookup if the index is a unique index or a primary key index. Index scans are mostly useful for SELECT queries but are an important part also of UPDATE, DELETE, REPLACE and CREATE TABLE table AS SELECT and so forth. Naturally an index is needed for an index scan and indexes can either be ordered, hash based. Some ordered indexes can return data in order but not necessarily all of them. There are many flags that define the behavior of indexes in the various handlers. These methods are found in the optimizer module. ------------------------------------------------------------------------- index_read is called to start a scan of an index. The find_flag defines the semantics of the scan. These flags are defined in include/my_base.h index_read_idx is the same but also initializes index before calling doing the same thing as index_read. Thus it is similar to index_init followed by index_read. This is also how we implement it. index_read/index_read_idx does also return the first row. Thus for key lookups, the index_read will be the only call to the handler in the index scan. index_init initializes an index before using it and index_end does any end processing needed. */ int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) override; int index_init(uint idx, bool sorted) override; int index_end() override; /** @breif Positions an index cursor to the index specified in the handle. Fetches the row if available. If the key value is null, begin at first key of the index. */ int index_read_idx_map(uchar *buf, uint index, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) override; /* These methods are used to jump to next or previous entry in the index scan. There are also methods to jump to first and last entry. */ int index_next(uchar * buf) override; int index_prev(uchar * buf) override; int index_first(uchar * buf) override; int index_last(uchar * buf) override; int index_next_same(uchar * buf, const uchar * key, uint keylen) override; int index_read_last_map(uchar *buf, const uchar *key, key_part_map keypart_map) override; /* read_first_row is virtual method but is only implemented by handler.cc, no storage engine has implemented it so neither will the partition handler. int read_first_row(uchar *buf, uint primary_key) override; */ int read_range_first(const key_range * start_key, const key_range * end_key, bool eq_range, bool sorted) override; int read_range_next() override; HANDLER_BUFFER *m_mrr_buffer; uint *m_mrr_buffer_size; uchar *m_mrr_full_buffer; uint m_mrr_full_buffer_size; uint m_mrr_new_full_buffer_size; MY_BITMAP m_mrr_used_partitions; uint *m_stock_range_seq; /* not used: uint m_current_range_seq; */ /* Value of mrr_mode passed to ha_partition::multi_range_read_init */ uint m_mrr_mode; /* Value of n_ranges passed to ha_partition::multi_range_read_init */ uint m_mrr_n_ranges; /* Ordered MRR mode: m_range_info[N] has the range_id of the last record that we've got from partition N */ range_id_t *m_range_info; /* TRUE <=> This ha_partition::multi_range_read_next() call is the first one */ bool m_multi_range_read_first; /* not used: uint m_mrr_range_init_flags; */ /* Number of elements in the list pointed by m_mrr_range_first. Not used */ uint m_mrr_range_length; /* Linked list of ranges to scan */ PARTITION_KEY_MULTI_RANGE *m_mrr_range_first; PARTITION_KEY_MULTI_RANGE *m_mrr_range_current; /* For each partition: number of ranges MRR scan will scan in the partition */ uint *m_part_mrr_range_length; /* For each partition: List of ranges to scan in this partition */ PARTITION_PART_KEY_MULTI_RANGE **m_part_mrr_range_first; PARTITION_PART_KEY_MULTI_RANGE **m_part_mrr_range_current; PARTITION_PART_KEY_MULTI_RANGE_HLD *m_partition_part_key_multi_range_hld; /* Sequence of ranges to be scanned (TODO: why not store this in handler::mrr_{iter,funcs}?) */ range_seq_t m_seq; RANGE_SEQ_IF *m_seq_if; /* Range iterator structure to be supplied to partitions */ RANGE_SEQ_IF m_part_seq_if; int multi_range_key_create_key( RANGE_SEQ_IF *seq, range_seq_t seq_it ); ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, void *seq_init_param, uint n_ranges, uint *bufsz, uint *mrr_mode, ha_rows limit, Cost_estimate *cost) override; ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys, uint key_parts, uint *bufsz, uint *mrr_mode, Cost_estimate *cost) override; int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, uint n_ranges, uint mrr_mode, HANDLER_BUFFER *buf) override; int multi_range_read_next(range_id_t *range_info) override; int multi_range_read_explain_info(uint mrr_mode, char *str, size_t size) override; uint last_part() { return m_last_part; } private: bool init_record_priority_queue(); void destroy_record_priority_queue(); int common_index_read(uchar * buf, bool have_start_key); int common_first_last(uchar * buf); int partition_scan_set_up(uchar * buf, bool idx_read_flag); bool check_parallel_search(); int handle_pre_scan(bool reverse_order, bool use_parallel); int handle_unordered_next(uchar * buf, bool next_same); int handle_unordered_scan_next_partition(uchar * buf); int handle_ordered_index_scan(uchar * buf, bool reverse_order); int handle_ordered_index_scan_key_not_found(); int handle_ordered_next(uchar * buf, bool next_same); int handle_ordered_prev(uchar * buf); void return_top_record(uchar * buf); void swap_blobs(uchar* rec_buf, Ordered_blob_storage ** storage, bool restore); public: /* ------------------------------------------------------------------------- MODULE information calls ------------------------------------------------------------------------- This calls are used to inform the handler of specifics of the ongoing scans and other actions. Most of these are used for optimisation purposes. ------------------------------------------------------------------------- */ int info(uint) override; void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id) override; void set_partitions_to_open(List<String> *partition_names) override; int change_partitions_to_open(List<String> *partition_names) override; int open_read_partitions(char *name_buff, size_t name_buff_size); int extra(enum ha_extra_function operation) override; int extra_opt(enum ha_extra_function operation, ulong arg) override; int reset() override; uint count_query_cache_dependant_tables(uint8 *tables_type) override; my_bool register_query_cache_dependant_tables(THD *thd, Query_cache *cache, Query_cache_block_table **block, uint *n) override; private: typedef int handler_callback(handler *, void *); my_bool reg_query_cache_dependant_table(THD *thd, char *engine_key, uint engine_key_len, char *query_key, uint query_key_len, uint8 type, Query_cache *cache, Query_cache_block_table **block_table, handler *file, uint *n); static const uint NO_CURRENT_PART_ID= NOT_A_PARTITION_ID; int loop_partitions(handler_callback callback, void *param); int loop_partitions_over_map(const MY_BITMAP *map, handler_callback callback, void *param); int loop_read_partitions(handler_callback callback, void *param); int loop_extra_alter(enum ha_extra_function operations); void late_extra_cache(uint partition_id); void late_extra_no_cache(uint partition_id); void prepare_extra_cache(uint cachesize); handler *get_open_file_sample() const { return m_file_sample; } public: /* ------------------------------------------------------------------------- MODULE optimiser support ------------------------------------------------------------------------- ------------------------------------------------------------------------- */ /* NOTE !!!!!! ------------------------------------------------------------------------- ------------------------------------------------------------------------- One important part of the public handler interface that is not depicted in the methods is the attribute records which is defined in the base class. This is looked upon directly and is set by calling info(HA_STATUS_INFO) ? ------------------------------------------------------------------------- */ private: /* Helper functions for optimizer hints. */ ha_rows min_rows_for_estimate(); uint get_biggest_used_partition(uint *part_index); public: /* keys_to_use_for_scanning can probably be implemented as the intersection of all underlying handlers if mixed handlers are used. This method is used to derive whether an index can be used for index-only scanning when performing an ORDER BY query. Only called from one place in sql_select.cc */ const key_map *keys_to_use_for_scanning() override; /* Called in test_quick_select to determine if indexes should be used. */ IO_AND_CPU_COST scan_time() override; IO_AND_CPU_COST key_scan_time(uint inx, ha_rows rows) override; IO_AND_CPU_COST keyread_time(uint inx, ulong ranges, ha_rows rows, ulonglong blocks) override; IO_AND_CPU_COST rnd_pos_time(ha_rows rows) override; /* For the given range how many records are estimated to be in this range. Used by optimiser to calculate cost of using a particular index. */ ha_rows records_in_range(uint inx, const key_range * min_key, const key_range * max_key, page_range *pages) override; /* Upper bound of number records returned in scan is sum of all underlying handlers. */ ha_rows estimate_rows_upper_bound() override; /* table_cache_type is implemented by the underlying handler but all underlying handlers must have the same implementation for it to work. */ uint8 table_cache_type() override; ha_rows records() override; /* Calculate hash value for PARTITION BY KEY tables. */ static uint32 calculate_key_hash_value(Field **field_array); /* ------------------------------------------------------------------------- MODULE print messages ------------------------------------------------------------------------- This module contains various methods that returns text messages for table types, index type and error messages. ------------------------------------------------------------------------- */ /* The name of the index type that will be used for display Here we must ensure that all handlers use the same index type for each index created. */ const char *index_type(uint inx) override; /* The name of the table type that will be used for display purposes */ const char *real_table_type() const override; /* The name of the row type used for the underlying tables. */ enum row_type get_row_type() const override; /* Handler specific error messages */ void print_error(int error, myf errflag) override; bool get_error_message(int error, String * buf) override; /* ------------------------------------------------------------------------- MODULE handler characteristics ------------------------------------------------------------------------- This module contains a number of methods defining limitations and characteristics of the handler. The partition handler will calculate this characteristics based on underlying handler characteristics. ------------------------------------------------------------------------- This is a list of flags that says what the storage engine implements. The current table flags are documented in handler.h The partition handler will support whatever the underlying handlers support except when specifically mentioned below about exceptions to this rule. NOTE: This cannot be cached since it can depend on TRANSACTION ISOLATION LEVEL which is dynamic, see bug#39084. HA_TABLE_SCAN_ON_INDEX: Used to avoid scanning full tables on an index. If this flag is set then the handler always has a primary key (hidden if not defined) and this index is used for scanning rather than a full table scan in all situations. (InnoDB, Federated) HA_REC_NOT_IN_SEQ: This flag is set for handlers that cannot guarantee that the rows are returned according to incremental positions (0, 1, 2, 3...). This also means that rnd_next() should return HA_ERR_RECORD_DELETED if it finds a deleted row. (MyISAM (not fixed length row), HEAP, InnoDB) HA_CAN_GEOMETRY: Can the storage engine handle spatial data. Used to check that no spatial attributes are declared unless the storage engine is capable of handling it. (MyISAM) HA_FAST_KEY_READ: Setting this flag indicates that the handler is equally fast in finding a row by key as by position. This flag is used in a very special situation in conjunction with filesort's. For further explanation see intro to init_read_record. (HEAP, InnoDB) HA_NULL_IN_KEY: Is NULL values allowed in indexes. If this is not allowed then it is not possible to use an index on a NULLable field. (HEAP, MyISAM, InnoDB) HA_DUPLICATE_POS: Tells that we can the position for the conflicting duplicate key record is stored in table->file->dupp_ref. (insert uses rnd_pos() on this to find the duplicated row) (MyISAM) HA_CAN_INDEX_BLOBS: Is the storage engine capable of defining an index of a prefix on a BLOB attribute. (Federated, MyISAM, InnoDB) HA_AUTO_PART_KEY: Auto increment fields can be part of a multi-part key. For second part auto-increment keys, the auto_incrementing is done in handler.cc (Federated, MyISAM) HA_REQUIRE_PRIMARY_KEY: Can't define a table without primary key (and cannot handle a table with hidden primary key) (No handler has this limitation currently) HA_STATS_RECORDS_IS_EXACT: Does the counter of records after the info call specify an exact value or not. If it does this flag is set. Only MyISAM and HEAP uses exact count. HA_CAN_INSERT_DELAYED: Can the storage engine support delayed inserts. To start with the partition handler will not support delayed inserts. Further investigation needed. (HEAP, MyISAM) HA_PRIMARY_KEY_IN_READ_INDEX: This parameter is set when the handler will also return the primary key when doing read-only-key on another index. HA_NOT_DELETE_WITH_CACHE: Seems to be an old MyISAM feature that is no longer used. No handler has it defined but it is checked in init_read_record. Further investigation needed. (No handler defines it) HA_NO_PREFIX_CHAR_KEYS: Indexes on prefixes of character fields is not allowed. (Federated) HA_CAN_FULLTEXT: Does the storage engine support fulltext indexes The partition handler will start by not supporting fulltext indexes. (MyISAM) HA_CAN_SQL_HANDLER: Can the HANDLER interface in the MySQL API be used towards this storage engine. (MyISAM, InnoDB) HA_NO_AUTO_INCREMENT: Set if the storage engine does not support auto increment fields. (Currently not set by any handler) HA_HAS_CHECKSUM: Special MyISAM feature. Has special SQL support in CREATE TABLE. No special handling needed by partition handler. (MyISAM) HA_FILE_BASED: Should file names always be in lower case (used by engines that map table names to file names. Since partition handler has a local file this flag is set. (Federated, MyISAM) HA_CAN_BIT_FIELD: Is the storage engine capable of handling bit fields? (MyISAM) HA_NEED_READ_RANGE_BUFFER: Is Read Multi-Range supported => need multi read range buffer This parameter specifies whether a buffer for read multi range is needed by the handler. Whether the handler supports this feature or not is dependent of whether the handler implements read_multi_range* calls or not. The only handler currently supporting this feature is NDB so the partition handler need not handle this call. There are methods in handler.cc that will transfer those calls into index_read and other calls in the index scan module. (No handler defines it) HA_PRIMARY_KEY_REQUIRED_FOR_POSITION: Does the storage engine need a PK for position? (InnoDB) HA_FILE_BASED is always set for partition handler since we use a special file for handling names of partitions, engine types. HA_REC_NOT_IN_SEQ is always set for partition handler since we cannot guarantee that the records will be returned in sequence. HA_DUPLICATE_POS, HA_CAN_INSERT_DELAYED, HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is disabled until further investigated. */ Table_flags table_flags() const override; /* This is a bitmap of flags that says how the storage engine implements indexes. The current index flags are documented in handler.h. If you do not implement indexes, just return zero here. part is the key part to check. First key part is 0 If all_parts it's set, MySQL want to know the flags for the combined index up to and including 'part'. HA_READ_NEXT: Does the index support read next, this is assumed in the server code and never checked so all indexes must support this. Note that the handler can be used even if it doesn't have any index. (HEAP, MyISAM, Federated, InnoDB) HA_READ_PREV: Can the index be used to scan backwards. (HEAP, MyISAM, InnoDB) HA_READ_ORDER: Can the index deliver its record in index order. Typically true for all ordered indexes and not true for hash indexes. In first step this is not true for partition handler until a merge sort has been implemented in partition handler. Used to set keymap part_of_sortkey This keymap is only used to find indexes usable for resolving an ORDER BY in the query. Thus in most cases index_read will work just fine without order in result production. When this flag is set it is however safe to order all output started by index_read since most engines do this. With read_multi_range calls there is a specific flag setting order or not order so in those cases ordering of index output can be avoided. (InnoDB, HEAP, MyISAM) HA_READ_RANGE: Specify whether index can handle ranges, typically true for all ordered indexes and not true for hash indexes. Used by optimiser to check if ranges (as key >= 5) can be optimised by index. (InnoDB, MyISAM, HEAP) HA_ONLY_WHOLE_INDEX: Can't use part key searches. This is typically true for hash indexes and typically not true for ordered indexes. (Federated, HEAP) HA_KEYREAD_ONLY: Does the storage engine support index-only scans on this index. Enables use of HA_EXTRA_KEYREAD and HA_EXTRA_NO_KEYREAD Used to set key_map keys_for_keyread and to check in optimiser for index-only scans. When doing a read under HA_EXTRA_KEYREAD the handler only have to fill in the columns the key covers. If HA_PRIMARY_KEY_IN_READ_INDEX is set then also the PRIMARY KEY columns must be updated in the row. (InnoDB, MyISAM) */ ulong index_flags(uint inx, uint part, bool all_parts) const override { /* The following code is not safe if you are using different storage engines or different index types per partition. */ ulong part_flags= m_file[0]->index_flags(inx, part, all_parts); /* The underlying storage engine might support Rowid Filtering. But ha_partition does not forward the needed SE API calls, so the feature will not be used. Note: It's the same with IndexConditionPushdown, except for its variant of IndexConditionPushdown+BatchedKeyAccess (that one works). Because of that, we do not clear HA_DO_INDEX_COND_PUSHDOWN here. */ return part_flags & ~HA_DO_RANGE_FILTER_PUSHDOWN; } /** wrapper function for handlerton alter_table_flags, since the ha_partition_hton cannot know all its capabilities */ alter_table_operations alter_table_flags(alter_table_operations flags) override; /* unireg.cc will call the following to make sure that the storage engine can handle the data it is about to send. The maximum supported values is the minimum of all handlers in the table */ uint min_of_the_max_uint(uint (handler::*operator_func)(void) const) const; uint max_supported_record_length() const override; uint max_supported_keys() const override; uint max_supported_key_parts() const override; uint max_supported_key_length() const override; uint max_supported_key_part_length() const override; uint min_record_length(uint options) const override; /* ------------------------------------------------------------------------- MODULE compare records ------------------------------------------------------------------------- cmp_ref checks if two references are the same. For most handlers this is a simple memcmp of the reference. However some handlers use primary key as reference and this can be the same even if memcmp says they are different. This is due to character sets and end spaces and so forth. For the partition handler the reference is first two bytes providing the partition identity of the referred record and then the reference of the underlying handler. Thus cmp_ref for the partition handler always returns FALSE for records not in the same partition and uses cmp_ref on the underlying handler to check whether the rest of the reference part is also the same. ------------------------------------------------------------------------- */ int cmp_ref(const uchar * ref1, const uchar * ref2) override; /* ------------------------------------------------------------------------- MODULE auto increment ------------------------------------------------------------------------- This module is used to handle the support of auto increments. This variable in the handler is used as part of the handler interface It is maintained by the parent handler object and should not be touched by child handler objects (see handler.cc for its use). auto_increment_column_changed ------------------------------------------------------------------------- */ bool need_info_for_auto_inc() override; bool can_use_for_auto_inc_init() override; void get_auto_increment(ulonglong offset, ulonglong increment, ulonglong nb_desired_values, ulonglong *first_value, ulonglong *nb_reserved_values) override; void release_auto_increment() override; private: int reset_auto_increment(ulonglong value) override; int update_next_auto_inc_val(); void lock_auto_increment() { /* lock already taken */ if (auto_increment_safe_stmt_log_lock) return; if (table_share->tmp_table == NO_TMP_TABLE) { part_share->lock_auto_inc(); DBUG_ASSERT(!auto_increment_lock); auto_increment_lock= TRUE; } } void unlock_auto_increment() { /* If auto_increment_safe_stmt_log_lock is true, we have to keep the lock. It will be set to false and thus unlocked at the end of the statement by ha_partition::release_auto_increment. */ if (auto_increment_lock && !auto_increment_safe_stmt_log_lock) { auto_increment_lock= FALSE; part_share->unlock_auto_inc(); } } void set_auto_increment_if_higher(Field *field) { ulonglong nr= (((Field_num*) field)->unsigned_flag || field->val_int() > 0) ? field->val_int() : 0; update_next_auto_inc_val(); lock_auto_increment(); /* must check when the mutex is taken */ if (nr >= part_share->next_auto_inc_val) part_share->next_auto_inc_val= nr + 1; unlock_auto_increment(); } void check_insert_or_replace_autoincrement() { /* If we INSERT or REPLACE into the table having the AUTO_INCREMENT column, we have to read all partitions for the next autoincrement value unless we already did it. */ if (!part_share->auto_inc_initialized && (ha_thd()->lex->sql_command == SQLCOM_INSERT || ha_thd()->lex->sql_command == SQLCOM_INSERT_SELECT || ha_thd()->lex->sql_command == SQLCOM_REPLACE || ha_thd()->lex->sql_command == SQLCOM_REPLACE_SELECT) && table->found_next_number_field) bitmap_set_all(&m_part_info->read_partitions); } public: /* ------------------------------------------------------------------------- MODULE initialize handler for HANDLER call ------------------------------------------------------------------------- This method is a special InnoDB method called before a HANDLER query. ------------------------------------------------------------------------- */ void init_table_handle_for_HANDLER() override; /* The remainder of this file defines the handler methods not implemented by the partition handler */ /* ------------------------------------------------------------------------- MODULE foreign key support ------------------------------------------------------------------------- The following methods are used to implement foreign keys as supported by InnoDB. Implement this ?? get_foreign_key_create_info is used by SHOW CREATE TABLE to get a textual description of how the CREATE TABLE part to define FOREIGN KEY's is done. free_foreign_key_create_info is used to free the memory area that provided this description. can_switch_engines checks if it is ok to switch to a new engine based on the foreign key info in the table. ------------------------------------------------------------------------- virtual char* get_foreign_key_create_info() virtual void free_foreign_key_create_info(char* str) virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) bool referenced_by_foreign_key() const noexcept override */ bool can_switch_engines() override; /* ------------------------------------------------------------------------- MODULE fulltext index ------------------------------------------------------------------------- */ void ft_close_search(FT_INFO *handler); int ft_init() override; int pre_ft_init() override; void ft_end() override; int pre_ft_end() override; FT_INFO *ft_init_ext(uint flags, uint inx, String *key) override; int ft_read(uchar *buf) override; int pre_ft_read(bool use_parallel) override; /* ------------------------------------------------------------------------- MODULE restart full table scan at position (MyISAM) ------------------------------------------------------------------------- The following method is only used by MyISAM when used as temporary tables in a join. int restart_rnd_next(uchar *buf, uchar *pos) override; */ /* ------------------------------------------------------------------------- MODULE in-place ALTER TABLE ------------------------------------------------------------------------- These methods are in the handler interface. (used by innodb-plugin) They are used for in-place alter table: ------------------------------------------------------------------------- */ enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info) override; bool prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) override; bool inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) override; bool commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit) override; /* ------------------------------------------------------------------------- MODULE tablespace support ------------------------------------------------------------------------- Admin of table spaces is not applicable to the partition handler (InnoDB) This means that the following method is not implemented: ------------------------------------------------------------------------- virtual int discard_or_import_tablespace(my_bool discard) */ /* ------------------------------------------------------------------------- MODULE admin MyISAM ------------------------------------------------------------------------- ------------------------------------------------------------------------- OPTIMIZE TABLE, CHECK TABLE, ANALYZE TABLE and REPAIR TABLE are mapped to a routine that handles looping over a given set of partitions and those routines send a flag indicating to execute on all partitions. ------------------------------------------------------------------------- */ int optimize(THD* thd, HA_CHECK_OPT *check_opt) override; int analyze(THD* thd, HA_CHECK_OPT *check_opt) override; int check(THD* thd, HA_CHECK_OPT *check_opt) override; int repair(THD* thd, HA_CHECK_OPT *check_opt) override; bool check_and_repair(THD *thd) override; bool auto_repair(int error) const override; bool is_crashed() const override; int check_for_upgrade(HA_CHECK_OPT *check_opt) override; /* ------------------------------------------------------------------------- MODULE condition pushdown ------------------------------------------------------------------------- */ const COND *cond_push(const COND *cond) override; void cond_pop() override; int info_push(uint info_type, void *info) override; private: int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, uint flags); int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt, uint part_id, uint flag); /** Check if the rows are placed in the correct partition. If the given argument is true, then move the rows to the correct partition. */ int check_misplaced_rows(uint read_part_id, bool repair); void append_row_to_str(String &str); public: int pre_calculate_checksum() override; int calculate_checksum() override; /* Enabled keycache for performance reasons, WL#4571 */ int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) override; int preload_keys(THD* thd, HA_CHECK_OPT* check_opt) override; TABLE_LIST *get_next_global_for_child() override; /* ------------------------------------------------------------------------- MODULE enable/disable indexes ------------------------------------------------------------------------- Enable/Disable Indexes are only supported by HEAP and MyISAM. ------------------------------------------------------------------------- */ int disable_indexes(key_map map, bool persist) override; int enable_indexes(key_map map, bool persist) override; int indexes_are_disabled() override; /* ------------------------------------------------------------------------- MODULE append_create_info ------------------------------------------------------------------------- append_create_info is only used by MyISAM MERGE tables and the partition handler will not support this handler as underlying handler. Implement this?? ------------------------------------------------------------------------- virtual void append_create_info(String *packet) */ /* the following heavily relies on the fact that all partitions are in the same storage engine. When this limitation is lifted, the following hack should go away, and a proper interface for engines needs to be introduced: an PARTITION_SHARE structure that has a pointer to the TABLE_SHARE. is given to engines everywhere where TABLE_SHARE is used now has members like option_struct, ha_data perhaps TABLE needs to be split the same way too... this can also be done before partition will support a mix of engines, but preferably together with other incompatible API changes. */ handlerton *partition_ht() const override { handlerton *h= m_file[0]->ht; for (uint i=1; i < m_tot_parts; i++) DBUG_ASSERT(h == m_file[i]->ht); return h; } bool partition_engine() override { return 1;} /** Get the number of records in part_elem and its subpartitions, if any. */ ha_rows part_records(partition_element *part_elem) { DBUG_ASSERT(m_part_info); uint32 sub_factor= m_part_info->num_subparts ? m_part_info->num_subparts : 1; uint32 part_id= part_elem->id * sub_factor; uint32 part_id_end= part_id + sub_factor; DBUG_ASSERT(part_id_end <= m_tot_parts); ha_rows part_recs= 0; for (; part_id < part_id_end; ++part_id) { handler *file= m_file[part_id]; file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_OPEN); part_recs+= file->stats.records; } return part_recs; } int notify_tabledef_changed(LEX_CSTRING *db, LEX_CSTRING *table, LEX_CUSTRING *frm, LEX_CUSTRING *version); friend int cmp_key_rowid_part_id(void *ptr, const void *ref1, const void *ref2); friend int cmp_key_part_id(void *key_p, const void *ref1, const void *ref2); bool can_convert_nocopy(const Field &field, const Column_definition &new_field) const override; void handler_stats_updated() override; void set_optimizer_costs(THD *thd) override; void update_optimizer_costs(OPTIMIZER_COSTS *costs) override; virtual ulonglong index_blocks(uint index, uint ranges, ha_rows rows) override; virtual ulonglong row_blocks() override; }; #endif /* HA_PARTITION_INCLUDED */ sql_window.h 0000644 00000015236 15156036147 0007122 0 ustar 00 /* Copyright (c) 2016, 2022 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_WINDOW_INCLUDED #define SQL_WINDOW_INCLUDED #include "filesort.h" class Item_window_func; /* Window functions module. Each instance of window function has its own element in SELECT_LEX::window_specs. */ class Window_frame_bound : public Sql_alloc { public: enum Bound_precedence_type { PRECEDING, CURRENT, // Used for CURRENT ROW window frame bounds FOLLOWING }; Bound_precedence_type precedence_type; /* For UNBOUNDED PRECEDING / UNBOUNDED FOLLOWING window frame bounds precedence type is seto to PRECEDING / FOLLOWING and offset is set to NULL. The offset is not meaningful with precedence type CURRENT */ Item *offset; Window_frame_bound(Bound_precedence_type prec_type, Item *offset_val) : precedence_type(prec_type), offset(offset_val) {} bool is_unbounded() { return offset == NULL; } void print(String *str, enum_query_type query_type); }; class Window_frame : public Sql_alloc { public: enum Frame_units { UNITS_ROWS, UNITS_RANGE }; enum Frame_exclusion { EXCL_NONE, EXCL_CURRENT_ROW, EXCL_GROUP, EXCL_TIES }; Frame_units units; Window_frame_bound *top_bound; Window_frame_bound *bottom_bound; Frame_exclusion exclusion; Window_frame(Frame_units win_frame_units, Window_frame_bound *win_frame_top_bound, Window_frame_bound *win_frame_bottom_bound, Frame_exclusion win_frame_exclusion) : units(win_frame_units), top_bound(win_frame_top_bound), bottom_bound(win_frame_bottom_bound), exclusion(win_frame_exclusion) {} bool check_frame_bounds(); void print(String *str, enum_query_type query_type); }; class Window_spec : public Sql_alloc { bool window_names_are_checked; public: virtual ~Window_spec() = default; LEX_CSTRING *window_ref; SQL_I_List<ORDER> *partition_list; SQL_I_List<ORDER> *save_partition_list; SQL_I_List<ORDER> *order_list; SQL_I_List<ORDER> *save_order_list; Window_frame *window_frame; Window_spec *referenced_win_spec; /* Window_spec objects are numbered by the number of their appearance in the query. This is used by compare_order_elements() to provide a predictable ordering of PARTITION/ORDER BY clauses. */ int win_spec_number; Window_spec(LEX_CSTRING *win_ref, SQL_I_List<ORDER> *part_list, SQL_I_List<ORDER> *ord_list, Window_frame *win_frame) : window_names_are_checked(false), window_ref(win_ref), partition_list(part_list), save_partition_list(NULL), order_list(ord_list), save_order_list(NULL), window_frame(win_frame), referenced_win_spec(NULL) {} virtual const char *name() { return NULL; } bool check_window_names(List_iterator_fast<Window_spec> &it); const char *window_reference() { return window_ref ? window_ref->str : NULL; } void join_partition_and_order_lists() { *(partition_list->next)= order_list->first; } void disjoin_partition_and_order_lists() { *(partition_list->next)= NULL; } void print(String *str, enum_query_type query_type); void print_order(String *str, enum_query_type query_type); void print_partition(String *str, enum_query_type query_type); }; class Window_def : public Window_spec { public: LEX_CSTRING *window_name; Window_def(LEX_CSTRING *win_name, LEX_CSTRING *win_ref, SQL_I_List<ORDER> *part_list, SQL_I_List<ORDER> *ord_list, Window_frame *win_frame) : Window_spec(win_ref, part_list, ord_list, win_frame), window_name(win_name) {} const char *name() override { return window_name->str; } }; int setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List<Item> &all_fields, List<Window_spec> &win_specs, List<Item_window_func> &win_funcs); ////////////////////////////////////////////////////////////////////////////// // Classes that make window functions computation a part of SELECT's query plan ////////////////////////////////////////////////////////////////////////////// class Frame_cursor; /* This handles computation of one window function. Currently, we make a spearate filesort() call for each window function. */ class Window_func_runner : public Sql_alloc { public: /* Add the function to be computed during the execution pass */ bool add_function_to_run(Item_window_func *win_func); /* Compute and fill the fields in the table. */ bool exec(THD *thd, TABLE *tbl, SORT_INFO *filesort_result); private: /* A list of window functions for which this Window_func_runner will compute values during the execution phase. */ List<Item_window_func> window_functions; }; /* Represents a group of window functions that require the same sorting of rows and so share the filesort() call. */ class Window_funcs_sort : public Sql_alloc { public: bool setup(THD *thd, SQL_SELECT *sel, List_iterator<Item_window_func> &it, st_join_table *join_tab); bool exec(JOIN *join, bool keep_filesort_result); void cleanup() { delete filesort; } friend class Window_funcs_computation; private: Window_func_runner runner; /* Window functions can be computed over this sorting */ Filesort *filesort; }; struct st_join_table; class Explain_aggr_window_funcs; /* This is a "window function computation phase": a single object of this class takes care of computing all window functions in a SELECT. - JOIN optimizer is exected to call setup() during query optimization. - JOIN::exec() should call exec() once it has collected join output in a temporary table. */ class Window_funcs_computation : public Sql_alloc { List<Window_funcs_sort> win_func_sorts; public: bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab); bool exec(JOIN *join, bool keep_last_filesort_result); Explain_aggr_window_funcs *save_explain_plan(MEM_ROOT *mem_root, bool is_analyze); void cleanup(); }; #endif /* SQL_WINDOW_INCLUDED */ optimizer_costs.h 0000644 00000013620 15156036147 0010164 0 ustar 00 #ifndef OPTIMIZER_COSTS_INCLUDED #define OPTIMIZER_COSTS_INCLUDED /* Copyright (c) 2022, MariaDB AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file defines costs structures and cost functions used by the optimizer */ /* OPTIMIZER_COSTS stores cost variables for each engine. They are stored in linked_optimizer_costs (pointed to by handlerton) and TABLE_SHARE. */ #define OPTIMIZER_COST_UNDEF -1.0 struct OPTIMIZER_COSTS { double disk_read_cost; double index_block_copy_cost; double key_cmp_cost; double key_copy_cost; double key_lookup_cost; double key_next_find_cost; double disk_read_ratio; double row_copy_cost; double row_lookup_cost; double row_next_find_cost; double rowid_cmp_cost; double rowid_copy_cost; double initialized; // Set if default or connected with handlerton }; /* Default optimizer costs */ extern OPTIMIZER_COSTS default_optimizer_costs; /* These are used to avoid taking mutex while creating tmp tables These are created once after the server is started so they are not dynamic. */ extern OPTIMIZER_COSTS heap_optimizer_costs, tmp_table_optimizer_costs; /* Interface to the engine cost variables. See optimizer_defaults.h for the default values. */ #define DISK_READ_RATIO costs->disk_read_ratio #define KEY_LOOKUP_COST costs->key_lookup_cost #define ROW_LOOKUP_COST costs->row_lookup_cost #define INDEX_BLOCK_COPY_COST costs->index_block_copy_cost #define KEY_COPY_COST costs->key_copy_cost #define ROW_COPY_COST costs->row_copy_cost #define ROW_COPY_COST_THD(THD) default_optimizer_costs.row_copy_cost #define KEY_NEXT_FIND_COST costs->key_next_find_cost #define ROW_NEXT_FIND_COST costs->row_next_find_cost #define KEY_COMPARE_COST costs->key_cmp_cost #define SORT_INDEX_CMP_COST default_optimizer_costs.key_cmp_cost #define DISK_READ_COST costs->disk_read_cost #define DISK_READ_COST_THD(thd) default_optimizer_costs.disk_read_cost /* Cost of comparing two rowids. This is set relative to KEY_COMPARE_COST */ #define ROWID_COMPARE_COST costs->rowid_cmp_cost #define ROWID_COMPARE_COST_THD(THD) default_optimizer_costs.rowid_cmp_cost /* Cost of comparing two rowids. This is set relative to KEY_COPY_COST */ #define ROWID_COPY_COST costs->rowid_copy_cost /* Engine unrelated costs. Stored in THD so that the user can change them */ #define WHERE_COST optimizer_where_cost #define WHERE_COST_THD(THD) ((THD)->variables.optimizer_where_cost) #define TABLE_SCAN_SETUP_COST optimizer_scan_setup_cost #define TABLE_SCAN_SETUP_COST_THD(THD) (THD)->variables.optimizer_scan_setup_cost #define INDEX_SCAN_SETUP_COST optimizer_scan_setup_cost/2 /* Cost for doing duplicate removal in test_quick_select */ #define DUPLICATE_REMOVAL_COST default_optimizer_costs.key_copy_cost /* Default fill factors of an (b-tree) index block is assumed to be 0.75 */ #define INDEX_BLOCK_FILL_FACTOR_DIV 3 #define INDEX_BLOCK_FILL_FACTOR_MUL 4 /* These constants impact the cost of QSORT and priority queue sorting, scaling the "n * log(n)" operations cost proportionally. These factors are < 1.0 to scale down the sorting cost to be comparable to 'read a row' = 1.0, (or 0.55 with default caching). A factor of 0.1 makes the cost of get_pq_sort_cost(10, 10, false) =0.52 (Reading 10 rows into a priority queue of 10 elements). One consenquence if this factor is too high is that priority_queue will not use addon fields (to solve the sort without having to do an extra re-read of rows) even if the number of LIMIT is low. */ #define QSORT_SORT_SLOWNESS_CORRECTION_FACTOR (0.1) #define PQ_SORT_SLOWNESS_CORRECTION_FACTOR (0.1) /* Creating a record from the join cache is faster than getting a row from the engine. JOIN_CACHE_ROW_COPY_COST_FACTOR is the factor used to take this into account. This is multiplied with ROW_COPY_COST. */ #define JOIN_CACHE_ROW_COPY_COST_FACTOR(thd) 1.0 /* cost1 is better that cost2 only if cost1 + COST_EPS < cost2 The main purpose of this is to ensure we use the first index or plan when there are identical plans. Without COST_EPS some plans in the test suite would vary depending on floating point calculations done in different paths. */ #define COST_EPS 0.0000001 #define COST_MAX (DBL_MAX * (1.0 - DBL_EPSILON)) static inline double COST_ADD(double c, double d) { DBUG_ASSERT(c >= 0); DBUG_ASSERT(d >= 0); return (COST_MAX - (d) > (c) ? (c) + (d) : COST_MAX); } static inline double COST_MULT(double c, double f) { DBUG_ASSERT(c >= 0); DBUG_ASSERT(f >= 0); return (COST_MAX / (f) > (c) ? (c) * (f) : COST_MAX); } OPTIMIZER_COSTS *get_optimizer_costs(const LEX_CSTRING *cache_name); OPTIMIZER_COSTS *create_optimizer_costs(const char *name, size_t length); OPTIMIZER_COSTS *get_or_create_optimizer_costs(const char *name, size_t length); bool create_default_optimizer_costs(); void copy_tmptable_optimizer_costs(); void free_all_optimizer_costs(); struct TABLE; extern "C" { typedef int (*process_optimizer_costs_t) (const LEX_CSTRING *, OPTIMIZER_COSTS *, TABLE *); bool process_optimizer_costs(process_optimizer_costs_t func, TABLE *param); } #endif /* OPTIMIZER_COSTS_INCLUDED */ pfs_statement_provider.h 0000644 00000010373 15156036147 0011517 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_STATEMENT_PROVIDER_H #define PFS_STATEMENT_PROVIDER_H /** @file include/pfs_statement_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_STATEMENT_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_STATEMENT_CALL(M) pfs_ ## M ## _v1 #define PSI_DIGEST_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_statement_v1(const char *category, PSI_statement_info_v1 *info, int count); PSI_statement_locker* pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state, PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); PSI_statement_locker* pfs_refine_statement_v1(PSI_statement_locker *locker, PSI_statement_key key); void pfs_start_statement_v1(PSI_statement_locker *locker, const char *db, uint db_len, const char *src_file, uint src_line); void pfs_set_statement_text_v1(PSI_statement_locker *locker, const char *text, uint text_len); void pfs_set_statement_lock_time_v1(PSI_statement_locker *locker, ulonglong count); void pfs_set_statement_rows_sent_v1(PSI_statement_locker *locker, ulonglong count); void pfs_set_statement_rows_examined_v1(PSI_statement_locker *locker, ulonglong count); void pfs_inc_statement_created_tmp_disk_tables_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_created_tmp_tables_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_select_full_join_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_select_full_range_join_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_select_range_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_select_range_check_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_select_scan_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_sort_merge_passes_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_sort_range_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_sort_rows_v1(PSI_statement_locker *locker, ulong count); void pfs_inc_statement_sort_scan_v1(PSI_statement_locker *locker, ulong count); void pfs_set_statement_no_index_used_v1(PSI_statement_locker *locker); void pfs_set_statement_no_good_index_used_v1(PSI_statement_locker *locker); void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da); PSI_digest_locker *pfs_digest_start_v1(PSI_statement_locker *locker); void pfs_digest_end_v1(PSI_digest_locker *locker, const sql_digest_storage *digest); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_STATEMENT_INTERFACE */ #endif scheduler.h 0000644 00000006177 15156036147 0006716 0 ustar 00 #ifndef SCHEDULER_INCLUDED #define SCHEDULER_INCLUDED /* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Classes for the thread scheduler */ #ifdef USE_PRAGMA_INTERFACE #pragma interface #endif class THD; /* Functions used when manipulating threads */ struct scheduler_functions { uint max_threads; Atomic_counter<uint> *connection_count; ulong *max_connections; bool (*init)(void); void (*add_connection)(CONNECT *connect); void (*thd_wait_begin)(THD *thd, int wait_type); void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); void (*end)(void); /** resume previous unfinished command (threadpool only)*/ void (*thd_resume)(THD* thd); }; /** Scheduler types enumeration. The default of --thread-handling is the first one in the thread_handling_names array, this array has to be consistent with the order in this array, so to change default one has to change the first entry in this enum and the first entry in the thread_handling_names array. @note The last entry of the enumeration is also used to mark the thread handling as dynamic. In this case the name of the thread handling is fetched from the name of the plugin that implements it. */ enum scheduler_types { /* The default of --thread-handling is the first one in the thread_handling_names array, this array has to be consistent with the order in this array, so to change default one has to change the first entry in this enum and the first entry in the thread_handling_names array. */ SCHEDULER_ONE_THREAD_PER_CONNECTION=0, SCHEDULER_NO_THREADS, SCHEDULER_TYPES_COUNT }; void one_thread_per_connection_scheduler(scheduler_functions *func, ulong *arg_max_connections, Atomic_counter<uint> *arg_connection_count); void one_thread_scheduler(scheduler_functions *func, Atomic_counter<uint> *arg_connection_count); extern void scheduler_init(); extern void post_kill_notification(THD *); /* To be used for pool-of-threads (implemeneted differently on various OSs) */ struct thd_scheduler { public: void *data; /* scheduler-specific data structure */ }; #ifdef HAVE_POOL_OF_THREADS void pool_of_threads_scheduler(scheduler_functions* func, ulong *arg_max_connections, Atomic_counter<uint> *arg_connection_count); #else #define pool_of_threads_scheduler(A,B,C) \ one_thread_per_connection_scheduler(A, B, C) #endif /*HAVE_POOL_OF_THREADS*/ #endif /* SCHEDULER_INCLUDED */ item_row.h 0000644 00000012155 15156036147 0006556 0 ustar 00 #ifndef ITEM_ROW_INCLUDED #define ITEM_ROW_INCLUDED /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** Row items used for comparing rows and IN operations on rows: @verbatim (a, b, c) > (10, 10, 30) (a, b, c) = (select c, d, e, from t1 where x=12) (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8) (a, b, c) IN (select c, d, e, from t1) @endverbatim */ /** Item which stores (x,y,...) and ROW(x,y,...). Note that this can be recursive: ((x,y),(z,t)) is a ROW of ROWs. */ class Item_row: public Item_fixed_hybrid, private Item_args, private Used_tables_and_const_cache { table_map not_null_tables_cache; /** If elements are made only of constants, of which one or more are NULL. For example, this item is (1,2,NULL), or ( (1,NULL), (2,3) ). */ bool with_null; public: Item_row(THD *thd, List<Item> &list) :Item_fixed_hybrid(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0) { } Item_row(THD *thd, Item_row *row) :Item_fixed_hybrid(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(), not_null_tables_cache(0), with_null(0) { } enum Type type() const override { return ROW_ITEM; }; const Type_handler *type_handler() const override { return &type_handler_row; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return NULL; // Check with Vicentiu why it's called for Item_row } void illegal_method_call(const char *); bool is_null() override { return null_value; } void make_send_field(THD *thd, Send_field *) override { illegal_method_call((const char*)"make_send_field"); }; double val_real() override { illegal_method_call((const char*)"val"); return 0; }; longlong val_int() override { illegal_method_call((const char*)"val_int"); return 0; }; String *val_str(String *) override { illegal_method_call((const char*)"val_str"); return 0; }; my_decimal *val_decimal(my_decimal *) override { illegal_method_call((const char*)"val_decimal"); return 0; }; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { illegal_method_call((const char*)"get_date"); return true; } bool fix_fields(THD *thd, Item **ref) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; void cleanup() override; void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override; table_map used_tables() const override { return used_tables_cache; }; bool const_item() const override { return const_item_cache; }; void update_used_tables() override { used_tables_and_const_cache_init(); used_tables_and_const_cache_update_and_join(arg_count, args); } table_map not_null_tables() const override { return not_null_tables_cache; } void print(String *str, enum_query_type query_type) override; bool walk(Item_processor processor, bool walk_subquery, void *arg) override { if (walk_args(processor, walk_subquery, arg)) return true; return (this->*processor)(arg); } Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override; bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; uint cols() const override { return arg_count; } Item* element_index(uint i) override { return args[i]; } Item** addr(uint i) override { return args + i; } bool check_cols(uint c) override; bool null_inside() override { return with_null; }; void bring_value() override; Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { Item_args::propagate_equal_fields(thd, Context_identity(), cond); return this; } bool excl_dep_on_table(table_map tab_map) override { return Item_args::excl_dep_on_table(tab_map); } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { return Item_args::excl_dep_on_grouping_fields(sel); } bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override { return Item_args::excl_dep_on_in_subq_left_part(subq_pred); } bool check_vcol_func_processor(void *arg) override {return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_row>(thd, this); } Item *deep_copy(THD *thd) const override; }; #endif /* ITEM_ROW_INCLUDED */ rpl_parallel.h 0000644 00000043464 15156036147 0007411 0 ustar 00 #ifndef RPL_PARALLEL_H #define RPL_PARALLEL_H #include "log_event.h" struct rpl_parallel; struct rpl_parallel_entry; struct rpl_parallel_thread_pool; extern struct rpl_parallel_thread_pool pool_bkp_for_pfs; class Relay_log_info; struct inuse_relaylog; /* Structure used to keep track of the parallel replication of a batch of event-groups that group-committed together on the master. It is used to ensure that every event group in one batch has reached the commit stage before the next batch starts executing. Note the lifetime of this structure: - It is allocated when the first event in a new batch of group commits is queued, from the free list rpl_parallel_entry::gco_free_list. - The gco for the batch currently being queued is owned by rpl_parallel_entry::current_gco. The gco for a previous batch that has been fully queued is owned by the gco->prev_gco pointer of the gco for the following batch. - The worker thread waits on gco->COND_group_commit_orderer for rpl_parallel_entry::count_committing_event_groups to reach wait_count before starting; the first waiter links the gco into the next_gco pointer of the gco of the previous batch for signalling. - When an event group reaches the commit stage, it signals the COND_group_commit_orderer if its gco->next_gco pointer is non-NULL and rpl_parallel_entry::count_committing_event_groups has reached gco->next_gco->wait_count. - The gco lives until all its event groups have completed their commit. This is detected by rpl_parallel_entry::last_committed_sub_id being greater than or equal gco->last_sub_id. Once this happens, the gco is freed. Note that since update of last_committed_sub_id can happen out-of-order, the thread that frees a given gco can be for any later event group, not necessarily an event group from the gco being freed. */ struct group_commit_orderer { /* Wakeup condition, used with rpl_parallel_entry::LOCK_parallel_entry. */ mysql_cond_t COND_group_commit_orderer; uint64 wait_count; group_commit_orderer *prev_gco; group_commit_orderer *next_gco; /* The sub_id of last event group in the previous GCO. Only valid if prev_gco != NULL. */ uint64 prior_sub_id; /* The sub_id of the last event group in this GCO. Only valid when next_gco is non-NULL. */ uint64 last_sub_id; /* This flag is set when this GCO has been installed into the next_gco pointer of the previous GCO. */ bool installed; enum force_switch_bits { /* This flag is set for a GCO in which we have event groups with multiple different commit_id values from the master. This happens when we optimistically try to execute in parallel transactions not known to be conflict-free. When this flag is set, in case of DDL we need to start a new GCO regardless of current commit_id, as DDL is not safe to speculatively apply in parallel with prior event groups. */ MULTI_BATCH= 1, /* This flag is set for a GCO that contains DDL. If set, it forces a switch to a new GCO upon seeing a new commit_id, as DDL is not safe to speculatively replicate in parallel with subsequent transactions. */ FORCE_SWITCH= 2 }; uint8 flags; #ifndef DBUG_OFF /* Flag set when the GCO has been freed and entered the free list, to catch (in debug) errors in the complex lifetime of this object. */ bool gc_done; #endif }; struct rpl_parallel_thread { bool delay_start; bool running; bool stop; bool pause_for_ftwrl; /* 0 = No start alter assigned >0 = Start alter assigned */ uint64 current_start_alter_id; uint32 current_start_alter_domain_id; /* This flag is true when Start Alter just needs to be binlogged only. This scenario will happens when there is congestion , and we can not allocate independent worker to start alter. */ bool reserved_start_alter_thread; mysql_mutex_t LOCK_rpl_thread; mysql_cond_t COND_rpl_thread; mysql_cond_t COND_rpl_thread_queue; mysql_cond_t COND_rpl_thread_stop; struct rpl_parallel_thread *next; /* For free list. */ struct rpl_parallel_thread_pool *pool; THD *thd; /* Who owns the thread, if any (it's a pointer into the rpl_parallel_entry::rpl_threads array. */ struct rpl_parallel_thread **current_owner; /* The rpl_parallel_entry of the owner. */ rpl_parallel_entry *current_entry; struct queued_event { queued_event *next; /* queued_event can hold either an event to be executed, or just a binlog position to be updated without any associated event. */ enum queued_event_t { QUEUED_EVENT, QUEUED_POS_UPDATE, QUEUED_MASTER_RESTART } typ; union { Log_event *ev; /* QUEUED_EVENT */ rpl_parallel_entry *entry_for_queued; /* QUEUED_POS_UPDATE and QUEUED_MASTER_RESTART */ }; rpl_group_info *rgi; inuse_relaylog *ir; ulonglong future_event_relay_log_pos; char event_relay_log_name[FN_REFLEN]; char future_event_master_log_name[FN_REFLEN]; ulonglong event_relay_log_pos; my_off_t future_event_master_log_pos; size_t event_size; } *event_queue, *last_in_queue; uint64 queued_size; /* These free lists are protected by LOCK_rpl_thread. */ queued_event *qev_free_list; rpl_group_info *rgi_free_list; group_commit_orderer *gco_free_list; /* These free lists are local to the thread, so need not be protected by any lock. They are moved to the global free lists in batches in the function batch_free(), to reduce LOCK_rpl_thread contention. The lists are not NULL-terminated (as we do not need to traverse them). Instead, if they are non-NULL, the loc_XXX_last_ptr_ptr points to the `next' pointer of the last element, which is used to link into the front of the global freelists. */ queued_event *loc_qev_list, **loc_qev_last_ptr_ptr; size_t loc_qev_size; uint64 qev_free_pending; rpl_group_info *loc_rgi_list, **loc_rgi_last_ptr_ptr; group_commit_orderer *loc_gco_list, **loc_gco_last_ptr_ptr; /* These keep track of batch update of inuse_relaylog refcounts. */ inuse_relaylog *accumulated_ir_last; uint64 accumulated_ir_count; char channel_name[MAX_CONNECTION_NAME]; uint channel_name_length; rpl_gtid last_seen_gtid; int last_error_number; char last_error_message[MAX_SLAVE_ERRMSG]; ulonglong last_error_timestamp; ulonglong worker_idle_time; ulong last_trans_retry_count; ulonglong start_time; void start_time_tracker() { start_time= microsecond_interval_timer(); } ulonglong compute_time_lapsed() { return (ulonglong)((microsecond_interval_timer() - start_time) / 1000000.0); } void add_to_worker_idle_time_and_reset() { worker_idle_time+= compute_time_lapsed(); start_time=0; } ulonglong get_worker_idle_time() { if (start_time) return (worker_idle_time + compute_time_lapsed()); else return worker_idle_time; } void enqueue(queued_event *qev) { if (last_in_queue) last_in_queue->next= qev; else event_queue= qev; last_in_queue= qev; queued_size+= qev->event_size; } void dequeue1(queued_event *list) { DBUG_ASSERT(list == event_queue); event_queue= last_in_queue= NULL; } void dequeue2(size_t dequeue_size) { queued_size-= dequeue_size; } queued_event *get_qev_common(Log_event *ev, ulonglong event_size); queued_event *get_qev(Log_event *ev, ulonglong event_size, Relay_log_info *rli); queued_event *retry_get_qev(Log_event *ev, queued_event *orig_qev, const char *relay_log_name, ulonglong event_pos, ulonglong event_size); /* Put a qev on the local free list, to be later released to the global free list by batch_free(). */ void loc_free_qev(queued_event *qev); /* Release an rgi immediately to the global free list. Requires holding the LOCK_rpl_thread mutex. */ void free_qev(queued_event *qev); rpl_group_info *get_rgi(Relay_log_info *rli, Gtid_log_event *gtid_ev, rpl_parallel_entry *e, ulonglong event_size); /* Put an gco on the local free list, to be later released to the global free list by batch_free(). */ void loc_free_rgi(rpl_group_info *rgi); /* Release an rgi immediately to the global free list. Requires holding the LOCK_rpl_thread mutex. */ void free_rgi(rpl_group_info *rgi); group_commit_orderer *get_gco(uint64 wait_count, group_commit_orderer *prev, uint64 first_sub_id); /* Put a gco on the local free list, to be later released to the global free list by batch_free(). */ void loc_free_gco(group_commit_orderer *gco); /* Move all local free lists to the global ones. Requires holding LOCK_rpl_thread. */ void batch_free(); /* Update inuse_relaylog refcounts with what we have accumulated so far. */ void inuse_relaylog_refcount_update(); rpl_parallel_thread(); }; struct pool_bkp_for_pfs{ uint32 count; bool inited, is_valid; struct rpl_parallel_thread **rpl_thread_arr; void init(uint32 thd_count) { DBUG_ASSERT(thd_count); rpl_thread_arr= (rpl_parallel_thread **) my_malloc(PSI_INSTRUMENT_ME, thd_count * sizeof(rpl_parallel_thread*), MYF(MY_WME | MY_ZEROFILL)); for (uint i=0; i<thd_count; i++) rpl_thread_arr[i]= (rpl_parallel_thread *) my_malloc(PSI_INSTRUMENT_ME, sizeof(rpl_parallel_thread), MYF(MY_WME | MY_ZEROFILL)); count= thd_count; inited= true; } void destroy() { if (inited) { for (uint i=0; i<count; i++) my_free(rpl_thread_arr[i]); my_free(rpl_thread_arr); rpl_thread_arr= NULL; } inited= false; } }; struct rpl_parallel_thread_pool { struct rpl_parallel_thread **threads; struct rpl_parallel_thread *free_list; mysql_mutex_t LOCK_rpl_thread_pool; mysql_cond_t COND_rpl_thread_pool; uint32 count; bool inited; /* Lock first LOCK_rpl_thread_pool and then LOCK_rpl_thread to update this variable. */ uint32 current_start_alters; /* While FTWRL runs, this counter is incremented to make SQL thread or STOP/START slave not try to start new activity while that operation is in progress. */ bool busy; struct pool_bkp_for_pfs pfs_bkp; rpl_parallel_thread_pool(); void copy_pool_for_pfs(Relay_log_info *rli); int init(uint32 size); void destroy(); void deactivate(); void destroy_cond_mutex(); struct rpl_parallel_thread *get_thread(rpl_parallel_thread **owner, rpl_parallel_entry *entry); void release_thread(rpl_parallel_thread *rpt); }; struct rpl_parallel_entry { /* A small struct to put worker threads references into a FIFO (using an I_List) for round-robin scheduling. */ struct sched_bucket : public ilink { sched_bucket() : thr(nullptr) { } rpl_parallel_thread *thr; }; /* A struct to keep track of into which "generation" an XA XID was last scheduled. A "generation" means that we know that every worker thread slot in the rpl_parallel_entry was scheduled at least once. When more that two generations have passed, we can safely reuse the XID in a different worker. */ struct xid_active_generation { uint64 generation; sched_bucket *thr; xid_t xid; }; mysql_mutex_t LOCK_parallel_entry; mysql_cond_t COND_parallel_entry; uint32 domain_id; /* Incremented by wait_for_workers_idle() and rpl_pause_for_ftwrl() to show that they are waiting, so that finish_event_group knows to signal them when last_committed_sub_id is increased. */ uint32 need_sub_id_signal; uint64 last_commit_id; uint32 pending_start_alters; bool active; /* Set when SQL thread is shutting down, and no more events can be processed, so worker threads must force abort any current transactions without waiting for event groups to complete. */ bool force_abort; /* At STOP SLAVE (force_abort=true), we do not want to process all events in the queue (which could unnecessarily delay stop, if a lot of events happen to be queued). The stop_sub_id provides a safe point at which to stop, so that everything before becomes committed and nothing after does. The value corresponds to rpl_group_info::gtid_sub_id; if that is less than or equal to stop_sub_id, we execute the associated event group, else we skip it (and all following) and stop. */ uint64 stop_sub_id; /* Array recording the last rpl_thread_max worker threads that we queued event for. This is used to limit how many workers a single domain can occupy (--slave-domain-parallel-threads). The array is structured as a FIFO using an I_List thread_sched_fifo. Note that workers are never explicitly deleted from the array. Instead, we need to check (under LOCK_rpl_thread) that the thread still belongs to us before re-using (rpl_thread::current_owner). */ sched_bucket *rpl_threads; I_List<sched_bucket> *thread_sched_fifo; uint32 rpl_thread_max; /* Keep track of all XA XIDs that may still be active in a worker thread. The elements are of type xid_active_generation. */ DYNAMIC_ARRAY maybe_active_xid; /* Keeping track of the current scheduling generation. A new generation means that every worker thread in the rpl_threads array have been scheduled at least one event group. When we have scheduled to slot current_generation_idx= 0, 1, ..., N-1 in this order, we know that (at least) one generation has passed. */ uint64 current_generation; uint32 current_generation_idx; /* The sub_id of the last transaction to commit within this domain_id. Must be accessed under LOCK_parallel_entry protection. Event groups commit in order, so the rpl_group_info for an event group will be alive (at least) as long as rpl_group_info::gtid_sub_id > last_committed_sub_id. This can be used to safely refer back to previous event groups if they are still executing, and ignore them if they completed, without requiring explicit synchronisation between the threads. */ uint64 last_committed_sub_id; /* The sub_id of the last event group in this replication domain that was queued for execution by a worker thread. */ uint64 current_sub_id; /* The largest sub_id that has started its transaction. Protected by LOCK_parallel_entry. (Transactions can start out-of-order, so this value signifies that no transactions with larger sub_id have started, but not necessarily that all transactions with smaller sub_id have started). */ uint64 largest_started_sub_id; rpl_group_info *current_group_info; /* If we get an error in some event group, we set the sub_id of that event group here. Then later event groups (with higher sub_id) can know not to try to start (event groups that already started will be rolled back when wait_for_prior_commit() returns error). The value is ULONGLONG_MAX when no error occurred. */ uint64 stop_on_error_sub_id; /* During FLUSH TABLES WITH READ LOCK, transactions with sub_id larger than this value must not start, but wait until the global read lock is released. The value is set to ULONGLONG_MAX when no FTWRL is pending. */ uint64 pause_sub_id; /* Total count of event groups queued so far. */ uint64 count_queued_event_groups; /* Count of event groups that have started (but not necessarily completed) the commit phase. We use this to know when every event group in a previous batch of master group commits have started committing on the slave, so that it is safe to start executing the events in the following batch. */ uint64 count_committing_event_groups; /* The group_commit_orderer object for the events currently being queued. */ group_commit_orderer *current_gco; /* Relay log info of replication source for this entry. */ Relay_log_info *rli; void check_scheduling_generation(sched_bucket *cur); sched_bucket *check_xa_xid_dependency(xid_t *xid); rpl_parallel_thread * choose_thread(rpl_group_info *rgi, bool *did_enter_cond, PSI_stage_info *old_stage, Gtid_log_event *gtid_ev); rpl_parallel_thread * choose_thread_internal(sched_bucket *cur_thr, bool *did_enter_cond, rpl_group_info *rgi, PSI_stage_info *old_stage); int queue_master_restart(rpl_group_info *rgi, Format_description_log_event *fdev); /* the initial size of maybe_ array corresponds to the case of each worker receives perhaps unlikely XA-PREPARE and XA-COMMIT within the same generation. */ inline uint active_xid_init_alloc() { return 3 * 2 * rpl_thread_max; } }; struct rpl_parallel { HASH domain_hash; rpl_parallel_entry *current; bool sql_thread_stopping; rpl_parallel(); ~rpl_parallel(); void reset(); rpl_parallel_entry *find(uint32 domain_id, Relay_log_info *rli); void wait_for_done(THD *thd, Relay_log_info *rli); void stop_during_until(); int wait_for_workers_idle(THD *thd); int do_event(rpl_group_info *serial_rgi, Log_event *ev, ulonglong event_size); }; extern struct rpl_parallel_thread_pool global_rpl_thread_pool; extern void wait_for_pending_deadlock_kill(THD *thd, rpl_group_info *rgi); extern int rpl_parallel_resize_pool_if_no_slaves(void); extern int rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool); extern int rpl_parallel_inactivate_pool(rpl_parallel_thread_pool *pool); extern bool process_gtid_for_restart_pos(Relay_log_info *rli, rpl_gtid *gtid); extern int rpl_pause_for_ftwrl(THD *thd); extern void rpl_unpause_after_ftwrl(THD *thd); #endif /* RPL_PARALLEL_H */ wsrep_condition_variable.h 0000644 00000002714 15156036147 0012004 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_CONDITION_VARIABLE_H #define WSREP_CONDITION_VARIABLE_H /* wsrep-lib */ #include "wsrep/condition_variable.hpp" /* implementation */ #include "my_pthread.h" class Wsrep_condition_variable : public wsrep::condition_variable { public: Wsrep_condition_variable(mysql_cond_t* cond) : m_cond(cond) { } ~Wsrep_condition_variable() = default; void notify_one() override { mysql_cond_signal(m_cond); } void notify_all() override { mysql_cond_broadcast(m_cond); } void wait(wsrep::unique_lock<wsrep::mutex>& lock) override { mysql_mutex_t* mutex= static_cast<mysql_mutex_t*>(lock.mutex()->native()); mysql_cond_wait(m_cond, mutex); } private: mysql_cond_t* m_cond; }; #endif /* WSREP_CONDITION_VARIABLE_H */ sql_type_real.h 0000644 00000002351 15156036147 0007571 0 ustar 00 /* Copyright (c) 2019 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_TYPE_REAL_INCLUDED #define SQL_TYPE_REAL_INCLUDED #include <cmath> class Float { float m_value; public: Float(float nr) :m_value(nr) { DBUG_ASSERT(!std::isnan(nr)); DBUG_ASSERT(!std::isinf(nr)); } Float(double nr) :m_value((float) nr) { DBUG_ASSERT(!std::isnan(nr)); DBUG_ASSERT(!std::isinf(nr)); DBUG_ASSERT(nr <= FLT_MAX); DBUG_ASSERT(nr >= -FLT_MAX); } Float(const uchar *ptr) { float4get(m_value, ptr); } bool to_string(String *to, uint dec) const; }; #endif // SQL_TYPE_REAL_INCLUDED thr_timer.h 0000644 00000003033 15156036150 0006713 0 ustar 00 /* Copyright (c) 2014 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 or later of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Prototypes when using thr_timer functions */ #ifndef THR_TIMER_INCLUDED #define THR_TIMER_INCLUDED #ifdef __cplusplus extern "C" { #endif typedef struct st_timer { struct timespec expire_time; ulonglong period; my_bool expired; uint index_in_queue; void (*func)(void*); void *func_arg; } thr_timer_t; /* Main functions for library */ my_bool init_thr_timer(uint init_size_for_timer_queue); void end_thr_timer(); /* Functions for handling one timer */ void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), void *arg); void thr_timer_set_period(thr_timer_t* timer_data, ulonglong microseconds); my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds); void thr_timer_end(thr_timer_t *timer_data); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* THR_TIMER_INCLUDED */ sql_do.h 0000644 00000001672 15156036150 0006206 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DO_INCLUDED #define SQL_DO_INCLUDED #include "sql_list.h" /* List */ class THD; class Item; bool mysql_do(THD *thd, List<Item> &values); #endif /* SQL_DO_INCLUDED */ item_sum.h 0000644 00000215767 15156036150 0006563 0 ustar 00 #ifndef ITEM_SUM_INCLUDED #define ITEM_SUM_INCLUDED /* Copyright (c) 2000, 2013 Oracle and/or its affiliates. Copyright (c) 2008, 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* classes for sum functions */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include <my_tree.h> #include "sql_udf.h" /* udf_handler */ class Item_sum; class Aggregator_distinct; class Aggregator_simple; /** The abstract base class for the Aggregator_* classes. It implements the data collection functions (setup/add/clear) as either pass-through to the real functionality or as collectors into an Unique (for distinct) structure. Note that update_field/reset_field are not in that class, because they're simply not called when GROUP BY/DISTINCT can be handled with help of index on grouped fields (quick_group = 0); */ class Aggregator : public Sql_alloc { friend class Item_sum; friend class Item_sum_sum; friend class Item_sum_count; friend class Item_sum_avg; /* All members are protected as this class is not usable outside of an Item_sum descendant. */ protected: /* the aggregate function class to act on */ Item_sum *item_sum; public: Aggregator (Item_sum *arg): item_sum(arg) {} virtual ~Aggregator () = default; /* Keep gcc happy */ enum Aggregator_type { SIMPLE_AGGREGATOR, DISTINCT_AGGREGATOR }; virtual Aggregator_type Aggrtype() = 0; /** Called before adding the first row. Allocates and sets up the internal aggregation structures used, e.g. the Unique instance used to calculate distinct. */ virtual bool setup(THD *) = 0; /** Called when we need to wipe out all the data from the aggregator : all the values acumulated and all the state. Cleans up the internal structures and resets them to their initial state. */ virtual void clear() = 0; /** Called when there's a new value to be aggregated. Updates the internal state of the aggregator to reflect the new value. */ virtual bool add() = 0; /** Called when there are no more data and the final value is to be retrieved. Finalises the state of the aggregator, so the final result can be retrieved. */ virtual void endup() = 0; /** Decimal value of being-aggregated argument */ virtual my_decimal *arg_val_decimal(my_decimal * value) = 0; /** Floating point value of being-aggregated argument */ virtual double arg_val_real() = 0; /** NULLness of being-aggregated argument. @param use_null_value Optimization: to determine if the argument is NULL we must, in the general case, call is_null() on it, which itself might call val_*() on it, which might be costly. If you just have called arg_val*(), you can pass use_null_value=true; this way, arg_is_null() might avoid is_null() and instead do a cheap read of the Item's null_value (updated by arg_val*()). */ virtual bool arg_is_null(bool use_null_value) = 0; }; class st_select_lex; class Window_spec; /** Class Item_sum is the base class used for special expressions that SQL calls 'set functions'. These expressions are formed with the help of aggregate functions such as SUM, MAX, GROUP_CONCAT etc. GENERAL NOTES A set function cannot be used in certain positions where expressions are accepted. There are some quite explicable restrictions for the usage of set functions. In the query: SELECT AVG(b) FROM t1 WHERE SUM(b) > 20 GROUP by a the usage of the set function AVG(b) is legal, while the usage of SUM(b) is illegal. A WHERE condition must contain expressions that can be evaluated for each row of the table. Yet the expression SUM(b) can be evaluated only for each group of rows with the same value of column a. In the query: SELECT AVG(b) FROM t1 WHERE c > 30 GROUP BY a HAVING SUM(b) > 20 both set function expressions AVG(b) and SUM(b) are legal. We can say that in a query without nested selects an occurrence of a set function in an expression of the SELECT list or/and in the HAVING clause is legal, while in the WHERE clause it's illegal. The general rule to detect whether a set function is legal in a query with nested subqueries is much more complicated. Consider the following query: SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL (SELECT t2.c FROM t2 WHERE SUM(t1.b) < t2.c). The set function SUM(b) is used here in the WHERE clause of the subquery. Nevertheless it is legal since it is under the HAVING clause of the query to which this function relates. The expression SUM(t1.b) is evaluated for each group defined in the main query, not for groups of the subquery. The problem of finding the query where to aggregate a particular set function is not so simple as it seems to be. In the query: SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.c FROM t2 GROUP BY t2.c HAVING SUM(t1.a) < t2.c) the set function can be evaluated for both outer and inner selects. If we evaluate SUM(t1.a) for the outer query then we get the value of t1.a multiplied by the cardinality of a group in table t1. In this case in each correlated subquery SUM(t1.a) is used as a constant. But we also can evaluate SUM(t1.a) for the inner query. In this case t1.a will be a constant for each correlated subquery and summation is performed for each group of table t2. (Here it makes sense to remind that the query SELECT c FROM t GROUP BY a HAVING SUM(1) < a is quite legal in our SQL). So depending on what query we assign the set function to we can get different result sets. The general rule to detect the query where a set function is to be evaluated can be formulated as follows. Consider a set function S(E) where E is an expression with occurrences of column references C1, ..., CN. Resolve these column references against subqueries that contain the set function S(E). Let Q be the innermost subquery of those subqueries. (It should be noted here that S(E) in no way can be evaluated in the subquery embedding the subquery Q, otherwise S(E) would refer to at least one unbound column reference) If S(E) is used in a construct of Q where set functions are allowed then we evaluate S(E) in Q. Otherwise we look for a innermost subquery containing S(E) of those where usage of S(E) is allowed. Let's demonstrate how this rule is applied to the following queries. 1. SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c HAVING SUM(t1.a+t2.b) < t3.c)) For this query the set function SUM(t1.a+t2.b) depends on t1.a and t2.b with t1.a defined in the outermost query, and t2.b defined for its subquery. The set function is in the HAVING clause of the subquery and can be evaluated in this subquery. 2. SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.b FROM t2 WHERE t2.b > ALL (SELECT t3.c FROM t3 GROUP BY t3.c HAVING SUM(t1.a+t2.b) < t3.c)) Here the set function SUM(t1.a+t2.b)is in the WHERE clause of the second subquery - the most upper subquery where t1.a and t2.b are defined. If we evaluate the function in this subquery we violate the context rules. So we evaluate the function in the third subquery (over table t3) where it is used under the HAVING clause. 3. SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.b FROM t2 WHERE t2.b > ALL (SELECT t3.c FROM t3 WHERE SUM(t1.a+t2.b) < t3.c)) In this query evaluation of SUM(t1.a+t2.b) is not legal neither in the second nor in the third subqueries. So this query is invalid. Mostly set functions cannot be nested. In the query SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20 the expression SUM(b) is not acceptable, though it is under a HAVING clause. Yet it is acceptable in the query: SELECT t.1 FROM t1 GROUP BY t1.a HAVING SUM(t1.b) > 20. An argument of a set function does not have to be a reference to a table column as we saw it in examples above. This can be a more complex expression SELECT t1.a FROM t1 GROUP BY t1.a HAVING SUM(t1.b+1) > 20. The expression SUM(t1.b+1) has a very clear semantics in this context: we sum up the values of t1.b+1 where t1.b varies for all values within a group of rows that contain the same t1.a value. A set function for an outer query yields a constant within a subquery. So the semantics of the query SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+SUM(t1.b)) > 20) is still clear. For a group of the rows with the same t1.a values we calculate the value of SUM(t1.b). This value 's' is substituted in the the subquery: SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+s) than returns some result set. By the same reason the following query with a subquery SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(SUM(t1.b)) > 20) is also acceptable. IMPLEMENTATION NOTES Three methods were added to the class to check the constraints specified in the previous section. These methods utilize several new members. The field 'nest_level' contains the number of the level for the subquery containing the set function. The main SELECT is of level 0, its subqueries are of levels 1, the subqueries of the latter are of level 2 and so on. The field 'aggr_level' is to contain the nest level of the subquery where the set function is aggregated. The field 'max_arg_level' is for the maximum of the nest levels of the unbound column references occurred in the set function. A column reference is unbound within a set function if it is not bound by any subquery used as a subexpression in this function. A column reference is bound by a subquery if it is a reference to the column by which the aggregation of some set function that is used in the subquery is calculated. For the set function used in the query SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c HAVING SUM(t1.a+t2.b) < t3.c)) the value of max_arg_level is equal to 1 since t1.a is bound in the main query, and t2.b is bound by the first subquery whose nest level is 1. Obviously a set function cannot be aggregated in the subquery whose nest level is less than max_arg_level. (Yet it can be aggregated in the subqueries whose nest level is greater than max_arg_level.) In the query SELECT t.a FROM t1 HAVING AVG(t1.a+(SELECT MIN(t2.c) FROM t2)) the value of the max_arg_level for the AVG set function is 0 since the reference t2.c is bound in the subquery. The field 'max_sum_func_level' is to contain the maximum of the nest levels of the set functions that are used as subexpressions of the arguments of the given set function, but not aggregated in any subquery within this set function. A nested set function s1 can be used within set function s0 only if s1.max_sum_func_level < s0.max_sum_func_level. Set function s1 is considered as nested for set function s0 if s1 is not calculated in any subquery within s0. A set function that is used as a subexpression in an argument of another set function refers to the latter via the field 'in_sum_func'. The condition imposed on the usage of set functions are checked when we traverse query subexpressions with the help of the recursive method fix_fields. When we apply this method to an object of the class Item_sum, first, on the descent, we call the method init_sum_func_check that initialize members used at checking. Then, on the ascent, we call the method check_sum_func that validates the set function usage and reports an error if it is illegal. The method register_sum_func serves to link the items for the set functions that are aggregated in the embedding (sub)queries. Circular chains of such functions are attached to the corresponding st_select_lex structures through the field inner_sum_func_list. Exploiting the fact that the members mentioned above are used in one recursive function we could have allocated them on the thread stack. Yet we don't do it now. We assume that the nesting level of subquries does not exceed 127. TODO: to catch queries where the limit is exceeded to make the code clean here. @note The implementation takes into account the used strategy: - Items resolved at optimization phase return 0 from Item_sum::used_tables(). - Items that depend on the number of join output records, but not columns of any particular table (like COUNT(*)), returm 0 from Item_sum::used_tables(), but still return false from Item_sum::const_item(). */ class Item_sum :public Item_func_or_sum { friend class Aggregator_distinct; friend class Aggregator_simple; protected: /** Aggregator class instance. Not set initially. Allocated only after it is determined if the incoming data are already distinct. */ Aggregator *aggr; private: /** Used in making ROLLUP. Set for the ROLLUP copies of the original Item_sum and passed to create_tmp_field() to cause it to work over the temp table buffer that is referenced by Item_result_field::result_field. */ bool force_copy_fields; /** Indicates how the aggregate function was specified by the parser : 1 if it was written as AGGREGATE(DISTINCT), 0 if it was AGGREGATE() */ bool with_distinct; /* TRUE if this is aggregate function of a window function */ bool window_func_sum_expr_flag; public: bool has_force_copy_fields() const { return force_copy_fields; } bool has_with_distinct() const { return with_distinct; } enum Sumfunctype { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC, VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC, ROW_NUMBER_FUNC, RANK_FUNC, DENSE_RANK_FUNC, PERCENT_RANK_FUNC, CUME_DIST_FUNC, NTILE_FUNC, FIRST_VALUE_FUNC, LAST_VALUE_FUNC, NTH_VALUE_FUNC, LEAD_FUNC, LAG_FUNC, PERCENTILE_CONT_FUNC, PERCENTILE_DISC_FUNC, SP_AGGREGATE_FUNC, JSON_ARRAYAGG_FUNC, JSON_OBJECTAGG_FUNC }; Item **ref_by; /* pointer to a ref to the object used to register it */ Item_sum *next; /* next in the circular chain of registered objects */ Item_sum *in_sum_func; /* embedding set function if any */ st_select_lex * aggr_sel; /* select where the function is aggregated */ int8 nest_level; /* number of the nesting level of the set function */ int8 aggr_level; /* nesting level of the aggregating subquery */ int8 max_arg_level; /* max level of unbound column references */ int8 max_sum_func_level;/* max level of aggregation for embedded functions */ /* true (the default value) means this aggregate function can be computed with TemporaryTableWithPartialSums algorithm (see end_update()). false means this aggregate function needs OrderedGroupBy algorithm (see end_write_group()). */ bool quick_group; /* This list is used by the check for mixing non aggregated fields and sum functions in the ONLY_FULL_GROUP_BY_MODE. We save all outer fields directly or indirectly used under this function it as it's unclear at the moment of fixing outer field whether it's aggregated or not. */ List<Item_field> outer_fields; protected: /* Copy of the arguments list to hold the original set of arguments. Used in EXPLAIN EXTENDED instead of the current argument list because the current argument list can be altered by usage of temporary tables. */ Item **orig_args, *tmp_orig_args[2]; static size_t ram_limitation(THD *thd); public: // Methods used by ColumnStore Item **get_orig_args() const { return orig_args; } public: void mark_as_sum_func(); Item_sum(THD *thd): Item_func_or_sum(thd), quick_group(1) { mark_as_sum_func(); init_aggregator(); } Item_sum(THD *thd, Item *a): Item_func_or_sum(thd, a), quick_group(1), orig_args(tmp_orig_args) { mark_as_sum_func(); init_aggregator(); } Item_sum(THD *thd, Item *a, Item *b): Item_func_or_sum(thd, a, b), quick_group(1), orig_args(tmp_orig_args) { mark_as_sum_func(); init_aggregator(); } Item_sum(THD *thd, List<Item> &list); //Copy constructor, need to perform subselects with temporary tables Item_sum(THD *thd, Item_sum *item); enum Type type() const override { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; bool is_aggr_sum_func() { switch (sum_func()) { case COUNT_FUNC: case COUNT_DISTINCT_FUNC: case SUM_FUNC: case SUM_DISTINCT_FUNC: case AVG_FUNC: case AVG_DISTINCT_FUNC: case MIN_FUNC: case MAX_FUNC: case STD_FUNC: case VARIANCE_FUNC: case SUM_BIT_FUNC: case UDF_SUM_FUNC: case GROUP_CONCAT_FUNC: case JSON_ARRAYAGG_FUNC: return true; default: return false; } } /** Resets the aggregate value to its default and aggregates the current value of its attribute(s). */ inline bool reset_and_add() { aggregator_clear(); return aggregator_add(); }; /* Called when new group is started and results are being saved in a temporary table. Similarly to reset_and_add() it resets the value to its default and aggregates the value of its attribute(s), but must also store it in result_field. This set of methods (result_item(), reset_field, update_field()) of Item_sum is used only if quick_group is not null. Otherwise copy_or_same() is used to obtain a copy of this item. */ virtual void reset_field()=0; /* Called for each new value in the group, when temporary table is in use. Similar to add(), but uses temporary table field to obtain current value, Updated value is then saved in the field. */ virtual void update_field()=0; bool fix_length_and_dec(THD *thd) override { set_maybe_null(); null_value=1; return FALSE; } virtual Item *result_item(THD *thd, Field *field); void update_used_tables() override; COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override { /* Item_sum (and derivants) of the original WHERE/HAVING clauses should already be replaced to Item_aggregate_ref by the time when build_equal_items() is called. See Item::split_sum_func2(). */ DBUG_ASSERT(0); return Item::build_equal_items(thd, inherited, link_item_fields, cond_equal_ref); } bool is_null() override { return null_value; } /** make_const() Called if we've managed to calculate the value of this Item in opt_sum_query(), hence it can be considered constant at all subsequent steps. */ void make_const () { used_tables_cache= 0; const_item_cache= true; } void reset_forced_const() { const_item_cache= false; } bool const_during_execution() const override { return false; } void print(String *str, enum_query_type query_type) override; void fix_num_length_and_dec(); /** Mark an aggregate as having no rows. This function is called by the execution engine to assign 'NO ROWS FOUND' value to an aggregate item, when the underlying result set has no rows. Such value, in a general case, may be different from the default value of the item after 'clear()': e.g. a numeric item may be initialized to 0 by clear() and to NULL by no_rows_in_result(). */ void no_rows_in_result() override { set_aggregator(current_thd, with_distinct ? Aggregator::DISTINCT_AGGREGATOR : Aggregator::SIMPLE_AGGREGATOR); aggregator_clear(); } virtual void make_unique() { force_copy_fields= TRUE; } virtual Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table); Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return create_tmp_field(root, param->group(), table); } bool collect_outer_ref_processor(void *param) override; bool init_sum_func_check(THD *thd); bool check_sum_func(THD *thd, Item **ref); bool register_sum_func(THD *thd, Item **ref); st_select_lex *depended_from() { return (nest_level == aggr_level ? 0 : aggr_sel); } Item *get_arg(uint i) const { return args[i]; } Item *set_arg(uint i, THD *thd, Item *new_val); uint get_arg_count() const { return arg_count; } virtual Item **get_args() { return fixed() ? orig_args : args; } /* Initialization of distinct related members */ void init_aggregator() { aggr= NULL; with_distinct= FALSE; force_copy_fields= FALSE; } /** Called to initialize the aggregator. */ inline bool aggregator_setup(THD *thd) { return aggr->setup(thd); }; /** Called to cleanup the aggregator. */ inline void aggregator_clear() { aggr->clear(); } /** Called to add value to the aggregator. */ inline bool aggregator_add() { return aggr->add(); }; /* stores the declared DISTINCT flag (from the parser) */ void set_distinct(bool distinct) { with_distinct= distinct; quick_group= with_distinct ? 0 : 1; } /* Set the type of aggregation : DISTINCT or not. May be called multiple times. */ int set_aggregator(THD *thd, Aggregator::Aggregator_type aggregator); virtual void clear()= 0; virtual bool add()= 0; virtual bool setup(THD *thd) { return false; } virtual bool supports_removal() const { return false; } virtual void remove() { DBUG_ASSERT(0); } void cleanup() override; bool check_vcol_func_processor(void *arg) override; virtual void setup_window_func(THD *thd, Window_spec *window_spec) {} void mark_as_window_func_sum_expr() { window_func_sum_expr_flag= true; } bool is_window_func_sum_expr() { return window_func_sum_expr_flag; } virtual void setup_caches(THD *thd) {}; virtual void set_partition_row_count(ulonglong count) { DBUG_ASSERT(0); } /* While most Item_sum descendants employ standard aggregators configured through Item_sum::set_aggregator() call, there are exceptions like Item_func_group_concat, which implements its own custom aggregators for deduplication values. This function distinguishes between the use of standard and custom aggregators by the object */ virtual bool uses_non_standard_aggregator_for_distinct() const { return false; } }; class Unique; /** The distinct aggregator. Implements AGGFN (DISTINCT ..) Collects all the data into an Unique (similarly to what Item_sum does currently when with_distinct=true) and then (if applicable) iterates over the list of unique values and pumps them back into its object */ class Aggregator_distinct : public Aggregator { friend class Item_sum_sum; /* flag to prevent consecutive runs of endup(). Normally in endup there are expensive calculations (like walking the distinct tree for example) which we must do only once if there are no data changes. We can re-use the data for the second and subsequent val_xxx() calls. endup_done set to TRUE also means that the calculated values for the aggregate functions are correct and don't need recalculation. */ bool endup_done; /* Used depending on the type of the aggregate function and the presence of blob columns in it: - For COUNT(DISTINCT) and no blob fields this points to a real temporary table. It's used as a hash table. - For AVG/SUM(DISTINCT) or COUNT(DISTINCT) with blob fields only the in-memory data structure of a temporary table is constructed. It's used by the Field classes to transform data into row format. */ TABLE *table; /* An array of field lengths on row allocated and used only for COUNT(DISTINCT) with multiple columns and no blobs. Used in Aggregator_distinct::composite_key_cmp (called from Unique to compare nodes */ uint32 *field_lengths; /* Used in conjunction with 'table' to support the access to Field classes for COUNT(DISTINCT). Needed by copy_fields()/copy_funcs(). */ TMP_TABLE_PARAM *tmp_table_param; /* If there are no blobs in the COUNT(DISTINCT) arguments, we can use a tree, which is faster than heap table. In that case, we still use the table to help get things set up, but we insert nothing in it. For AVG/SUM(DISTINCT) we always use this tree (as it takes a single argument) to get the distinct rows. */ Unique *tree; /* The length of the temp table row. Must be a member of the class as it gets passed down to simple_raw_key_cmp () as a compare function argument to Unique. simple_raw_key_cmp () is used as a fast comparison function when the entire row can be binary compared. */ uint tree_key_length; /* Set to true if the result is known to be always NULL. If set deactivates creation and usage of the temporary table (in the 'table' member) and the Unique instance (in the 'tree' member) as well as the calculation of the final value on the first call to Item_[sum|avg|count]::val_xxx(). */ bool always_null; /** When feeding back the data in endup() from Unique/temp table back to Item_sum::add() methods we must read the data from Unique (and not recalculate the functions that are given as arguments to the aggregate function. This flag is to tell the arg_*() methods to take the data from the Unique instead of calling the relevant val_..() method. */ bool use_distinct_values; public: Aggregator_distinct (Item_sum *sum) : Aggregator(sum), table(NULL), tmp_table_param(NULL), tree(NULL), always_null(false), use_distinct_values(false) {} virtual ~Aggregator_distinct (); Aggregator_type Aggrtype() override { return DISTINCT_AGGREGATOR; } bool setup(THD *) override; void clear() override; bool add() override; void endup() override; my_decimal *arg_val_decimal(my_decimal * value) override; double arg_val_real() override; bool arg_is_null(bool use_null_value) override; bool unique_walk_function(void *element); bool unique_walk_function_for_count(void *element); static int composite_key_cmp(void *arg, const void *key1, const void *key2); }; /** The pass-through aggregator. Implements AGGFN (DISTINCT ..) by knowing it gets distinct data on input. So it just pumps them back to the Item_sum descendant class. */ class Aggregator_simple : public Aggregator { public: Aggregator_simple (Item_sum *sum) : Aggregator(sum) {} Aggregator_type Aggrtype() override { return Aggregator::SIMPLE_AGGREGATOR; } bool setup(THD * thd) override { return item_sum->setup(thd); } void clear() override { item_sum->clear(); } bool add() override { return item_sum->add(); } void endup() override {}; my_decimal *arg_val_decimal(my_decimal * value) override; double arg_val_real() override; bool arg_is_null(bool use_null_value) override; }; class Item_sum_num :public Item_sum { public: Item_sum_num(THD *thd): Item_sum(thd) {} Item_sum_num(THD *thd, Item *item_par): Item_sum(thd, item_par) {} Item_sum_num(THD *thd, Item *a, Item* b): Item_sum(thd, a, b) {} Item_sum_num(THD *thd, List<Item> &list): Item_sum(thd, list) {} Item_sum_num(THD *thd, Item_sum_num *item): Item_sum(thd, item) {} bool fix_fields(THD *, Item **) override; }; class Item_sum_double :public Item_sum_num { public: Item_sum_double(THD *thd): Item_sum_num(thd) {} Item_sum_double(THD *thd, Item *item_par): Item_sum_num(thd, item_par) {} Item_sum_double(THD *thd, List<Item> &list): Item_sum_num(thd, list) {} Item_sum_double(THD *thd, Item_sum_double *item) :Item_sum_num(thd, item) {} longlong val_int() override { return val_int_from_real(); } String *val_str(String*str) override { return val_string_from_real(str); } my_decimal *val_decimal(my_decimal *to) override { return val_decimal_from_real(to); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_real(thd, ltime, fuzzydate); } const Type_handler *type_handler() const override { return &type_handler_double; } }; class Item_sum_int :public Item_sum_num { public: Item_sum_int(THD *thd): Item_sum_num(thd) {} Item_sum_int(THD *thd, Item *item_par): Item_sum_num(thd, item_par) {} Item_sum_int(THD *thd, List<Item> &list): Item_sum_num(thd, list) {} Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} double val_real() override { DBUG_ASSERT(fixed()); return (double) val_int(); } String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_int(thd, ltime, fuzzydate); } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=21; base_flags&= ~item_base_t::MAYBE_NULL; null_value=0; return false; } }; class Item_sum_sum :public Item_sum_num, public Type_handler_hybrid_field_type { protected: bool direct_added; bool direct_reseted_field; bool direct_sum_is_null; double direct_sum_real; double sum; my_decimal direct_sum_decimal; my_decimal dec_buffs[2]; uint curr_dec_buff; bool fix_length_and_dec(THD *thd) override; public: Item_sum_sum(THD *thd, Item *item_par, bool distinct): Item_sum_num(thd, item_par), direct_added(FALSE), direct_reseted_field(FALSE) { set_distinct(distinct); } Item_sum_sum(THD *thd, Item_sum_sum *item); enum Sumfunctype sum_func() const override { return has_with_distinct() ? SUM_DISTINCT_FUNC : SUM_FUNC; } void cleanup() override; void direct_add(my_decimal *add_sum_decimal); void direct_add(double add_sum_real, bool add_sum_is_null); void clear() override; bool add() override; double val_real() override; longlong val_int() override; String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); void reset_field() override; void update_field() override; void no_rows_in_result() override {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name_distinct= { STRING_WITH_LEN("sum(distinct ")}; static LEX_CSTRING name_normal= { STRING_WITH_LEN("sum(") }; return has_with_distinct() ? name_distinct : name_normal; } Item *copy_or_same(THD* thd) override; void remove() override; bool supports_removal() const override { return true; } private: void add_helper(bool perform_removal); ulonglong count; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_sum>(thd, this); } }; class Item_sum_count :public Item_sum_int { bool direct_counted; bool direct_reseted_field; longlong direct_count; longlong count; friend class Aggregator_distinct; void clear() override; bool add() override; void cleanup() override; void remove() override; public: Item_sum_count(THD *thd, Item *item_par): Item_sum_int(thd, item_par), direct_counted(FALSE), direct_reseted_field(FALSE), count(0) {} /** Constructs an instance for COUNT(DISTINCT) @param list a list of the arguments to the aggregate function This constructor is called by the parser only for COUNT (DISTINCT). */ Item_sum_count(THD *thd, List<Item> &list): Item_sum_int(thd, list), direct_counted(FALSE), direct_reseted_field(FALSE), count(0) { set_distinct(TRUE); } Item_sum_count(THD *thd, Item_sum_count *item): Item_sum_int(thd, item), direct_counted(FALSE), direct_reseted_field(FALSE), count(item->count) {} enum Sumfunctype sum_func () const override { return has_with_distinct() ? COUNT_DISTINCT_FUNC : COUNT_FUNC; } void no_rows_in_result() override { count=0; } void make_const(longlong count_arg) { count=count_arg; Item_sum::make_const(); } const Type_handler *type_handler() const override { return &type_handler_slonglong; } longlong val_int() override; void reset_field() override; void update_field() override; void direct_add(longlong add_count); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name_distinct= { STRING_WITH_LEN("count(distinct ")}; static LEX_CSTRING name_normal= { STRING_WITH_LEN("count(") }; return has_with_distinct() ? name_distinct : name_normal; } Item *copy_or_same(THD* thd) override; bool supports_removal() const override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_count>(thd, this); } }; class Item_sum_avg :public Item_sum_sum { public: // TODO-cvicentiu given that Item_sum_sum now uses a counter of its own, in // order to implement remove(), it is possible to remove this member. ulonglong count; uint prec_increment; uint f_precision, f_scale, dec_bin_size; Item_sum_avg(THD *thd, Item *item_par, bool distinct): Item_sum_sum(thd, item_par, distinct), count(0) {} Item_sum_avg(THD *thd, Item_sum_avg *item) :Item_sum_sum(thd, item), count(item->count), prec_increment(item->prec_increment) {} void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); bool fix_length_and_dec(THD *thd) override; enum Sumfunctype sum_func () const override { return has_with_distinct() ? AVG_DISTINCT_FUNC : AVG_FUNC; } void clear() override; bool add() override; void remove() override; double val_real() override; // In SPs we might force the "wrong" type with select into a declare variable longlong val_int() override { return val_int_from_real(); } my_decimal *val_decimal(my_decimal *) override; String *val_str(String *str) override; void reset_field() override; void update_field() override; Item *result_item(THD *thd, Field *field) override; void no_rows_in_result() override {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name_distinct= { STRING_WITH_LEN("avg(distinct ")}; static LEX_CSTRING name_normal= { STRING_WITH_LEN("avg(") }; return has_with_distinct() ? name_distinct : name_normal; } Item *copy_or_same(THD* thd) override; Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table) override; void cleanup() override { count= 0; Item_sum_sum::cleanup(); } bool supports_removal() const override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_avg>(thd, this); } }; /* variance(a) = = sum (ai - avg(a))^2 / count(a) ) = sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a) = (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) = = (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) = = (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) = = (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) = = (sum(ai^2) - sum(a)^2/count(a))/count(a) But, this falls prey to catastrophic cancellation. Instead, use the recurrence formulas M_{1} = x_{1}, ~ M_{k} = M_{k-1} + (x_{k} - M_{k-1}) / k newline S_{1} = 0, ~ S_{k} = S_{k-1} + (x_{k} - M_{k-1}) times (x_{k} - M_{k}) newline for 2 <= k <= n newline ital variance = S_{n} / (n-1) */ class Stddev { double m_m; double m_s; ulonglong m_count; public: Stddev() :m_m(0), m_s(0), m_count(0) { } Stddev(double nr) :m_m(nr), m_s(0.0), m_count(1) { } Stddev(const uchar *); void to_binary(uchar *) const; void recurrence_next(double nr); double result(bool is_simple_variance); ulonglong count() const { return m_count; } static uint32 binary_size() { return (uint32) (sizeof(double) * 2 + sizeof(ulonglong)); }; }; class Item_sum_variance :public Item_sum_double { Stddev m_stddev; bool fix_length_and_dec(THD *thd) override; public: uint sample; uint prec_increment; Item_sum_variance(THD *thd, Item *item_par, uint sample_arg): Item_sum_double(thd, item_par), sample(sample_arg) {} Item_sum_variance(THD *thd, Item_sum_variance *item); Sumfunctype sum_func () const override { return VARIANCE_FUNC; } void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); void clear() override final; bool add() override final; double val_real() override; void reset_field() override final; void update_field() override final; Item *result_item(THD *thd, Field *field) override; void no_rows_in_result() override final {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name_sample= { STRING_WITH_LEN("var_samp(")}; static LEX_CSTRING name_normal= { STRING_WITH_LEN("variance(") }; return sample ? name_sample : name_normal; } Item *copy_or_same(THD* thd) override; Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table) override final; void cleanup() override final { m_stddev= Stddev(); Item_sum_double::cleanup(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_variance>(thd, this); } }; /* standard_deviation(a) = sqrt(variance(a)) */ class Item_sum_std final :public Item_sum_variance { public: Item_sum_std(THD *thd, Item *item_par, uint sample_arg): Item_sum_variance(thd, item_par, sample_arg) {} Item_sum_std(THD *thd, Item_sum_std *item) :Item_sum_variance(thd, item) {} enum Sumfunctype sum_func () const override final { return STD_FUNC; } double val_real() override final; Item *result_item(THD *thd, Field *field) override final; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING std_name= {STRING_WITH_LEN("std(") }; static LEX_CSTRING stddev_samp_name= {STRING_WITH_LEN("stddev_samp(") }; return sample ? stddev_samp_name : std_name; } Item *copy_or_same(THD* thd) override final; protected: Item *shallow_copy(THD *thd) const override final { return get_item_copy<Item_sum_std>(thd, this); } }; class Item_sum_hybrid : public Item_sum, public Type_handler_hybrid_field_type { public: Item_sum_hybrid(THD *thd, Item *item_par): Item_sum(thd, item_par), Type_handler_hybrid_field_type(&type_handler_slonglong) { collation.set(&my_charset_bin); } Item_sum_hybrid(THD *thd, Item *a, Item *b): Item_sum(thd, a, b), Type_handler_hybrid_field_type(&type_handler_slonglong) { collation.set(&my_charset_bin); } Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) :Item_sum(thd, item), Type_handler_hybrid_field_type(item) { } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } bool fix_length_and_dec_generic(); bool fix_length_and_dec_numeric(const Type_handler *h); bool fix_length_and_dec_sint_ge0(); bool fix_length_and_dec_string(); }; // This class is a string or number function depending on num_func class Arg_comparator; class Item_cache; class Item_sum_min_max :public Item_sum_hybrid { protected: bool direct_added; Item *direct_item; Item_cache *value, *arg_cache; Arg_comparator *cmp; int cmp_sign; bool was_values; // Set if we have found at least one row (for max/min only) bool was_null_value; public: Item_sum_min_max(THD *thd, Item *item_par,int sign): Item_sum_hybrid(thd, item_par), direct_added(FALSE), value(0), arg_cache(0), cmp(0), cmp_sign(sign), was_values(TRUE) { collation.set(&my_charset_bin); } Item_sum_min_max(THD *thd, Item_sum_min_max *item) :Item_sum_hybrid(thd, item), direct_added(FALSE), value(item->value), arg_cache(0), cmp_sign(item->cmp_sign), was_values(item->was_values) { } bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override; void setup_hybrid(THD *thd, Item *item, Item *value_arg); void clear() override; void direct_add(Item *item); double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; void reset_field() override; String *val_str(String *) override; bool val_native(THD *thd, Native *) override; const Type_handler *real_type_handler() const override { return get_arg(0)->real_type_handler(); } const TYPELIB *get_typelib() const override { return args[0]->get_typelib(); } void update_field() override; void min_max_update_str_field(); void min_max_update_real_field(); void min_max_update_int_field(); void min_max_update_decimal_field(); void min_max_update_native_field(); void cleanup() override; bool any_value() { return was_values; } void no_rows_in_result() override; void restore_to_before_no_rows_in_result() override; Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table) override; void setup_caches(THD *thd) override { setup_hybrid(thd, arguments()[0], NULL); } }; class Item_sum_min final :public Item_sum_min_max { public: Item_sum_min(THD *thd, Item *item_par): Item_sum_min_max(thd, item_par, 1) {} Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_min_max(thd, item) {} enum Sumfunctype sum_func () const override {return MIN_FUNC;} bool add() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_name= {STRING_WITH_LEN("min(") }; return sum_name; } Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_min>(thd, this); } }; class Item_sum_max final :public Item_sum_min_max { public: Item_sum_max(THD *thd, Item *item_par): Item_sum_min_max(thd, item_par, -1) {} Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_min_max(thd, item) {} enum Sumfunctype sum_func() const override {return MAX_FUNC;} bool add() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_name= {STRING_WITH_LEN("max(") }; return sum_name; } Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_max>(thd, this); } }; class Item_sum_bit :public Item_sum_int { public: Item_sum_bit(THD *thd, Item *item_par, ulonglong reset_arg): Item_sum_int(thd, item_par), reset_bits(reset_arg), bits(reset_arg), as_window_function(FALSE), num_values_added(0) {} Item_sum_bit(THD *thd, Item_sum_bit *item): Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits), as_window_function(item->as_window_function), num_values_added(item->num_values_added) { if (as_window_function) memcpy(bit_counters, item->bit_counters, sizeof(bit_counters)); } enum Sumfunctype sum_func () const override { return SUM_BIT_FUNC;} void clear() override; longlong val_int() override; void reset_field() override; void update_field() override; const Type_handler *type_handler() const override { return &type_handler_ulonglong; } bool fix_length_and_dec(THD *thd) override { if (args[0]->check_type_can_return_int(func_name_cstring())) return true; decimals= 0; max_length=21; unsigned_flag= 1; base_flags&= ~item_base_t::MAYBE_NULL; null_value= 0; return FALSE; } void cleanup() override { bits= reset_bits; if (as_window_function) clear_as_window(); Item_sum_int::cleanup(); } void setup_window_func(THD *, Window_spec *) override { as_window_function= TRUE; clear_as_window(); } void remove() override { if (as_window_function) { remove_as_window(args[0]->val_int()); return; } // Unless we're counting bits, we can not remove anything. DBUG_ASSERT(0); } bool supports_removal() const override { return true; } protected: enum bit_counters { NUM_BIT_COUNTERS= 64 }; ulonglong reset_bits,bits; /* Marks whether the function is to be computed as a window function. */ bool as_window_function; // When used as an aggregate window function, we need to store // this additional information. ulonglong num_values_added; ulonglong bit_counters[NUM_BIT_COUNTERS]; bool add_as_window(ulonglong value); bool remove_as_window(ulonglong value); bool clear_as_window(); virtual void set_bits_from_counters()= 0; }; class Item_sum_or final :public Item_sum_bit { public: Item_sum_or(THD *thd, Item *item_par): Item_sum_bit(thd, item_par, 0) {} Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} bool add() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_name= {STRING_WITH_LEN("bit_or(") }; return sum_name; } Item *copy_or_same(THD* thd) override; private: void set_bits_from_counters() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_or>(thd, this); } }; class Item_sum_and final :public Item_sum_bit { public: Item_sum_and(THD *thd, Item *item_par): Item_sum_bit(thd, item_par, ULONGLONG_MAX) {} Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} bool add() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_min_name= {STRING_WITH_LEN("bit_and(") }; return sum_min_name; } Item *copy_or_same(THD* thd) override; private: void set_bits_from_counters() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_and>(thd, this); } }; class Item_sum_xor final :public Item_sum_bit { public: Item_sum_xor(THD *thd, Item *item_par): Item_sum_bit(thd, item_par, 0) {} Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} bool add() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_min_name= {STRING_WITH_LEN("bit_xor(") }; return sum_min_name; } Item *copy_or_same(THD* thd) override; private: void set_bits_from_counters() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_xor>(thd, this); } }; class sp_head; class sp_name; class Query_arena; struct st_sp_security_context; /* Item_sum_sp handles STORED AGGREGATE FUNCTIONS Each Item_sum_sp represents a custom aggregate function. Inside the function's body, we require at least one occurrence of FETCH GROUP NEXT ROW instruction. This cursor is what makes custom stored aggregates possible. During computation the function's add method is called. This in turn performs an execution of the function. The function will execute from the current function context (and instruction), if one exists, or from the start if not. See Item_sp for more details. Upon encounter of FETCH GROUP NEXT ROW instruction, the function will pause execution. We assume that the user has performed the necessary additions for a row, between two encounters of FETCH GROUP NEXT ROW. Example: create aggregate function f1(x INT) returns int begin declare continue handler for not found return s; declare s int default 0 loop fetch group next row; set s = s + x; end loop; end The function will always stop after an encounter of FETCH GROUP NEXT ROW, except (!) on first encounter, as the value for the first row in the group is already set in the argument x. This behaviour is done so when a user writes a function, he should "logically" include FETCH GROUP NEXT ROW before any "add" instructions in the stored function. This means however that internally, the first occurrence doesn't stop the function. See the implementation of FETCH GROUP NEXT ROW for details as to how it happens. Either way, one should assume that after calling "Item_sum_sp::add()" that the values for that particular row have been added to the aggregation. To produce values for val_xxx methods we need an extra syntactic construct. We require a continue handler when "no more rows are available". val_xxx methods force a function return by executing the function again, while setting a server flag that no more rows have been found. This implies that val_xxx methods should only be called once per group however. Example: DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN ret_val; */ class Item_sum_sp :public Item_sum, public Item_sp { private: bool execute(); public: Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, sp_head *sp); Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, sp_head *sp, List<Item> &list); Item_sum_sp(THD *thd, Item_sum_sp *item); enum Sumfunctype sum_func () const override { return SP_AGGREGATE_FUNC; } Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return create_table_field_from_handler(root, table); } bool fix_length_and_dec(THD *thd) override; bool fix_fields(THD *thd, Item **ref) override; LEX_CSTRING func_name_cstring() const override; const Type_handler *type_handler() const override; bool add() override; /* val_xx functions */ longlong val_int() override { if(execute()) return 0; return sp_result_field->val_int(); } double val_real() override { if(execute()) return 0.0; return sp_result_field->val_real(); } my_decimal *val_decimal(my_decimal *dec_buf) override { if(execute()) return NULL; return sp_result_field->val_decimal(dec_buf); } bool val_native(THD *thd, Native *to) override { return (null_value= execute()) || sp_result_field->val_native(to); } String *val_str(String *str) override { String buf; char buff[20]; buf.set(buff, 20, str->charset()); buf.length(0); if (execute()) return NULL; /* result_field will set buf pointing to internal buffer of the resul_field. Due to this it will change any time when SP is executed. In order to prevent occasional corruption of returned value, we make here a copy. */ sp_result_field->val_str(&buf); str->copy(buf); return str; } void reset_field() override{DBUG_ASSERT(0);} void update_field() override{DBUG_ASSERT(0);} void clear() override; void cleanup() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return execute() || sp_result_field->get_date(ltime, fuzzydate); } inline Field *get_sp_result_field() { return sp_result_field; } Item *copy_or_same(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_sp>(thd, this); } }; /* Items to get the value of a stored sum function */ class Item_sum_field :public Item { protected: Field *field; public: Item_sum_field(THD *thd, Item_sum *item) :Item(thd), field(item->result_field) { name= item->name; set_maybe_null(); decimals= item->decimals; max_length= item->max_length; unsigned_flag= item->unsigned_flag; } table_map used_tables() const override { return (table_map) 1L; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return create_tmp_field_ex_simple(root, table, src, param); } void save_in_result_field(bool no_conversions) override { DBUG_ASSERT(0); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(name.str, arg, VCOL_IMPOSSIBLE); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; class Item_avg_field :public Item_sum_field { protected: uint prec_increment; public: Item_avg_field(THD *thd, Item_sum_avg *item) :Item_sum_field(thd, item), prec_increment(item->prec_increment) { } enum Type type() const override { return FIELD_AVG_ITEM; } bool is_null() override { update_null_value(); return null_value; } }; class Item_avg_field_double :public Item_avg_field { public: Item_avg_field_double(THD *thd, Item_sum_avg *item) :Item_avg_field(thd, item) { } const Type_handler *type_handler() const override { return &type_handler_double; } longlong val_int() override { return val_int_from_real(); } my_decimal *val_decimal(my_decimal *dec) override { return val_decimal_from_real(dec); } String *val_str(String *str) override { return val_string_from_real(str); } double val_real() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_avg_field_double>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_avg_field_decimal :public Item_avg_field { uint f_precision, f_scale, dec_bin_size; public: Item_avg_field_decimal(THD *thd, Item_sum_avg *item) :Item_avg_field(thd, item), f_precision(item->f_precision), f_scale(item->f_scale), dec_bin_size(item->dec_bin_size) { } const Type_handler *type_handler() const override { return &type_handler_newdecimal; } double val_real() override { return VDec(this).to_double(); } longlong val_int() override { return VDec(this).to_longlong(unsigned_flag); } String *val_str(String *str) override { return VDec(this).to_string_round(str, decimals); } my_decimal *val_decimal(my_decimal *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_avg_field_decimal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_variance_field :public Item_sum_field { uint sample; public: Item_variance_field(THD *thd, Item_sum_variance *item) :Item_sum_field(thd, item), sample(item->sample) { } enum Type type() const override {return FIELD_VARIANCE_ITEM; } double val_real() override; longlong val_int() override { return val_int_from_real(); } String *val_str(String *str) override { return val_string_from_real(str); } my_decimal *val_decimal(my_decimal *dec_buf) override { return val_decimal_from_real(dec_buf); } bool is_null() override { update_null_value(); return null_value; } const Type_handler *type_handler() const override { return &type_handler_double; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_variance_field>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_std_field :public Item_variance_field { public: Item_std_field(THD *thd, Item_sum_std *item) :Item_variance_field(thd, item) { } enum Type type() const override { return FIELD_STD_ITEM; } double val_real() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_std_field>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* User defined aggregates */ #ifdef HAVE_DLOPEN class Item_udf_sum : public Item_sum { protected: udf_handler udf; public: Item_udf_sum(THD *thd, udf_func *udf_arg): Item_sum(thd), udf(udf_arg) { quick_group=0; } Item_udf_sum(THD *thd, udf_func *udf_arg, List<Item> &list): Item_sum(thd, list), udf(udf_arg) { quick_group=0;} Item_udf_sum(THD *thd, Item_udf_sum *item) :Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; } LEX_CSTRING func_name_cstring() const override { const char *tmp= udf.name(); return {tmp, strlen(tmp) }; } bool fix_fields(THD *thd, Item **ref) override { DBUG_ASSERT(fixed() == 0); if (init_sum_func_check(thd)) return TRUE; base_flags|= item_base_t::FIXED; /* We set const_item_cache to false in constructors. It can be later changed to "true", in a Item_sum::make_const() call. No make_const() calls should have happened so far. */ DBUG_ASSERT(!const_item_cache); if (udf.fix_fields(thd, this, this->arg_count, this->args)) return TRUE; /** The above call for udf.fix_fields() updates the Used_tables_and_const_cache part of "this" as if it was a regular non-aggregate UDF function and can change both const_item_cache and used_tables_cache members. - The used_tables_cache will be re-calculated in update_used_tables() which is called from check_sum_func() below. So we don't care about its current value. - The const_item_cache must stay "false" until a Item_sum::make_const() call happens, if ever. So we need to reset const_item_cache back to "false" here. */ const_item_cache= false; memcpy (orig_args, args, sizeof (Item *) * arg_count); return check_sum_func(thd, ref); } enum Sumfunctype sum_func () const override { return UDF_SUM_FUNC; } virtual bool have_field_update(void) const { return 0; } void clear() override; bool add() override; bool supports_removal() const override; void remove() override; void reset_field() override {}; void update_field() override {} void cleanup() override; void print(String *str, enum_query_type query_type) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; class Item_sum_udf_float :public Item_udf_sum { public: Item_sum_udf_float(THD *thd, udf_func *udf_arg): Item_udf_sum(thd, udf_arg) {} Item_sum_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_sum(thd, udf_arg, list) {} Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_udf_sum(thd, item) {} longlong val_int() override { return val_int_from_real(); } double val_real() override; String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *) override; const Type_handler *type_handler() const override { return &type_handler_double; } bool fix_length_and_dec(THD *thd) override { fix_num_length_and_dec(); return FALSE; } Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_udf_float>(thd, this); } }; class Item_sum_udf_int :public Item_udf_sum { public: Item_sum_udf_int(THD *thd, udf_func *udf_arg): Item_udf_sum(thd, udf_arg) {} Item_sum_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_sum(thd, udf_arg, list) {} Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_udf_sum(thd, item) {} longlong val_int() override; double val_real() override { DBUG_ASSERT(fixed()); return (double) Item_sum_udf_int::val_int(); } String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *) override; const Type_handler *type_handler() const override { if (unsigned_flag) return &type_handler_ulonglong; return &type_handler_slonglong; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=21; return FALSE; } Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_udf_int>(thd, this); } }; class Item_sum_udf_str :public Item_udf_sum { public: Item_sum_udf_str(THD *thd, udf_func *udf_arg): Item_udf_sum(thd, udf_arg) {} Item_sum_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_sum(thd, udf_arg, list) {} Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_udf_sum(thd, item) {} String *val_str(String *) override; double val_real() override { int err_not_used; char *end_not_used; String *res; res=val_str(&str_value); return res ? res->charset()->strntod((char*) res->ptr(),res->length(), &end_not_used, &err_not_used) : 0.0; } longlong val_int() override { int err_not_used; char *end; String *res; CHARSET_INFO *cs; if (!(res= val_str(&str_value))) return 0; /* Null value */ cs= res->charset(); end= (char*) res->ptr()+res->length(); return cs->strtoll10(res->ptr(), &end, &err_not_used); } my_decimal *val_decimal(my_decimal *dec) override; const Type_handler *type_handler() const override { return string_type_handler(); } bool fix_length_and_dec(THD *thd) override; Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_udf_str>(thd, this); } }; class Item_sum_udf_decimal :public Item_udf_sum { public: Item_sum_udf_decimal(THD *thd, udf_func *udf_arg): Item_udf_sum(thd, udf_arg) {} Item_sum_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_sum(thd, udf_arg, list) {} Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) :Item_udf_sum(thd, item) {} String *val_str(String *str) override { return VDec(this).to_string_round(str, decimals); } double val_real() override { return VDec(this).to_double(); } longlong val_int() override { return VDec(this).to_longlong(unsigned_flag); } my_decimal *val_decimal(my_decimal *) override; const Type_handler *type_handler() const override { return &type_handler_newdecimal; } bool fix_length_and_dec(THD *thd) override { fix_num_length_and_dec(); return FALSE; } Item *copy_or_same(THD* thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_udf_decimal>(thd, this); } }; #else /* Dummy functions to get yy_*.cc files compiled */ class Item_sum_udf_float :public Item_sum_double { public: Item_sum_udf_float(THD *thd, udf_func *udf_arg): Item_sum_double(thd) {} Item_sum_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): Item_sum_double(thd) {} Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_sum_double(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val_real() { DBUG_ASSERT(fixed()); return 0.0; } void clear() {} bool add() { return 0; } void reset_field() { DBUG_ASSERT(0); }; void update_field() {} }; class Item_sum_udf_int :public Item_sum_double { public: Item_sum_udf_int(THD *thd, udf_func *udf_arg): Item_sum_double(thd) {} Item_sum_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): Item_sum_double(thd) {} Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_sum_double(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } longlong val_int() { DBUG_ASSERT(fixed()); return 0; } double val_real() { DBUG_ASSERT(fixed()); return 0; } void clear() {} bool add() { return 0; } void reset_field() { DBUG_ASSERT(0); }; void update_field() {} }; class Item_sum_udf_decimal :public Item_sum_double { public: Item_sum_udf_decimal(THD *thd, udf_func *udf_arg): Item_sum_double(thd) {} Item_sum_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_sum_double(thd) {} Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item) :Item_sum_double(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val_real() { DBUG_ASSERT(fixed()); return 0.0; } my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed()); return 0; } void clear() {} bool add() { return 0; } void reset_field() { DBUG_ASSERT(0); }; void update_field() {} }; class Item_sum_udf_str :public Item_sum_double { public: Item_sum_udf_str(THD *thd, udf_func *udf_arg): Item_sum_double(thd) {} Item_sum_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): Item_sum_double(thd) {} Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_sum_double(thd, item) {} String *val_str(String *) { DBUG_ASSERT(fixed()); null_value=1; return 0; } double val_real() { DBUG_ASSERT(fixed()); null_value=1; return 0.0; } longlong val_int() { DBUG_ASSERT(fixed()); null_value=1; return 0; } bool fix_length_and_dec(THD *thd) override { base_flags|= item_base_t::MAYBE_NULL; max_length=0; return FALSE; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } void clear() {} bool add() { return 0; } void reset_field() { DBUG_ASSERT(0); }; void update_field() {} }; #endif /* HAVE_DLOPEN */ C_MODE_START int group_concat_key_cmp_with_distinct(void *arg, const void *key1, const void *key2); int group_concat_key_cmp_with_distinct_with_nulls(void *arg, const void *key1, const void *key2); int group_concat_key_cmp_with_order(void *arg, const void *key1, const void *key2); int group_concat_key_cmp_with_order_with_nulls(void *arg, const void *key1, const void *key2); int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); C_MODE_END class Item_func_group_concat : public Item_sum { protected: TMP_TABLE_PARAM *tmp_table_param; String result; String *separator; TREE tree_base; TREE *tree; size_t tree_len; Item **ref_pointer_array; /** If DISTINCT is used with this GROUP_CONCAT, this member is used to filter out duplicates. @see Item_func_group_concat::setup @see Item_func_group_concat::add @see Item_func_group_concat::clear */ Unique *unique_filter; TABLE *table; ORDER **order; Name_resolution_context *context; /** The number of ORDER BY items. */ uint arg_count_order; /** The number of selected items, aka the expr list. */ uint arg_count_field; uint row_count; bool distinct; bool warning_for_row; bool always_null; bool force_copy_fields; /** True if entire result of GROUP_CONCAT has been written to output buffer. */ bool result_finalized; /** Limits the rows in the result */ Item *row_limit; /** Skips a particular number of rows in from the result*/ Item *offset_limit; bool limit_clause; /* copy of the offset limit */ ulonglong copy_offset_limit; /*copy of the row limit */ ulonglong copy_row_limit; /* Following is 0 normal object and pointer to original one for copy (to correctly free resources) */ Item_func_group_concat *original; /* Used by Item_func_group_concat and Item_func_json_arrayagg. The latter needs null values but the former doesn't. */ bool add(bool exclude_nulls); friend int group_concat_key_cmp_with_distinct(void *arg, const void *key1, const void *key2); friend int group_concat_key_cmp_with_distinct_with_nulls(void *arg, const void *key1, const void *key2); friend int group_concat_key_cmp_with_order(void *arg, const void *key1, const void *key2); friend int group_concat_key_cmp_with_order_with_nulls(void *arg, const void *key1, const void *key2); friend int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); bool repack_tree(THD *thd); /* Says whether the function should skip NULL arguments or add them to the result. Redefined in JSON_ARRAYAGG. */ virtual bool skip_nulls() const { return true; } virtual String *get_str_from_item(Item *i, String *tmp) { return i->val_str(tmp); } virtual String *get_str_from_field(Item *i, Field *f, String *tmp, const uchar *key, size_t offset) { return f->val_str(tmp, key + offset); } virtual void cut_max_length(String *result, uint old_length, uint max_length) const; bool uses_non_standard_aggregator_for_distinct() const override { return distinct; } public: // Methods used by ColumnStore bool get_distinct() const { return distinct; } uint get_count_field() const { return arg_count_field; } uint get_order_field() const { return arg_count_order; } const String* get_separator() const { return separator; } ORDER** get_order() const { return order; } public: Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List<Item> *is_select, const SQL_I_List<ORDER> &is_order, String *is_separator, bool limit_clause, Item *row_limit, Item *offset_limit); Item_func_group_concat(THD *thd, Item_func_group_concat *item); ~Item_func_group_concat(); void cleanup() override; enum Sumfunctype sum_func () const override {return GROUP_CONCAT_FUNC;} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING sum_name= {STRING_WITH_LEN("group_concat(") }; return sum_name; } const Type_handler *type_handler() const override { if (too_big_for_varchar()) return &type_handler_blob; return &type_handler_varchar; } void clear() override; bool add() override { return add(skip_nulls()); } void reset_field() override { DBUG_ASSERT(0); } // not used void update_field() override { DBUG_ASSERT(0); } // not used bool fix_fields(THD *,Item **) override; bool setup(THD *thd) override; void make_unique() override; double val_real() override { int error; const char *end; String *res; if (!(res= val_str(&str_value))) return 0.0; end= res->ptr() + res->length(); return (my_strtod(res->ptr(), (char**) &end, &error)); } longlong val_int() override { String *res; char *end_ptr; int error; if (!(res= val_str(&str_value))) return (longlong) 0; end_ptr= (char*) res->ptr()+ res->length(); return my_strtoll10(res->ptr(), &end_ptr, &error); } my_decimal *val_decimal(my_decimal *decimal_value) override { return val_decimal_from_string(decimal_value); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_string(thd, ltime, fuzzydate); } String *val_str(String *str) override; Item *copy_or_same(THD* thd) override; void no_rows_in_result() override {} void print(String *str, enum_query_type query_type) override; bool change_context_processor(void *cntx) override { context= (Name_resolution_context *)cntx; return FALSE; } qsort_cmp2 get_comparator_function_for_distinct(); qsort_cmp2 get_comparator_function_for_order_by(); uchar* get_record_pointer(); uint get_null_bytes(); protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_group_concat>(thd, this); } }; #endif /* ITEM_SUM_INCLUDED */ sql_explain.h 0000644 00000074622 15156036150 0007251 0 ustar 00 /* Copyright (c) 2013 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* == EXPLAIN/ANALYZE architecture == === [SHOW] EXPLAIN data === Query optimization produces two data structures: 1. execution data structures themselves (eg. JOINs, JOIN_TAB, etc, etc) 2. Explain data structures. #2 are self contained set of data structures that has sufficient info to produce output of SHOW EXPLAIN, EXPLAIN [FORMAT=JSON], or ANALYZE [FORMAT=JSON], without accessing the execution data structures. The exception is that Explain data structures have Item* pointers. See ExplainDataStructureLifetime below for details. === ANALYZE data === EXPLAIN data structures have embedded ANALYZE data structures. These are objects that are used to track how the parts of query plan were executed: how many times each part of query plan was invoked, how many rows were read/returned, etc. Each execution data structure keeps a direct pointer to its ANALYZE data structure. It is needed so that execution code can quickly increment the counters. (note that this increases the set of data that is frequently accessed during the execution. What is the impact of this?) Since ANALYZE/EXPLAIN data structures are separated from execution data structures, it is easy to have them survive until the end of the query, where we can return ANALYZE [FORMAT=JSON] output to the user, or print it into the slow query log. */ #ifndef SQL_EXPLAIN_INCLUDED #define SQL_EXPLAIN_INCLUDED class String_list: public List<char> { public: const char *append_str(MEM_ROOT *mem_root, const char *str); }; class Json_writer; /************************************************************************************** Data structures for producing EXPLAIN outputs. These structures - Can be produced inexpensively from query plan. - Store sufficient information to produce tabular EXPLAIN output (the goal is to be able to produce JSON also) *************************************************************************************/ class Explain_query; /* A node can be either a SELECT, or a UNION. */ class Explain_node : public Sql_alloc { public: Explain_node(MEM_ROOT *root) : cache_tracker(NULL), subq_materialization(NULL), connection_type(EXPLAIN_NODE_OTHER), children(root) {} /* A type specifying what kind of node this is */ enum explain_node_type { EXPLAIN_UNION, EXPLAIN_SELECT, EXPLAIN_BASIC_JOIN, EXPLAIN_UPDATE, EXPLAIN_DELETE, EXPLAIN_INSERT }; /* How this node is connected */ enum explain_connection_type { EXPLAIN_NODE_OTHER, EXPLAIN_NODE_DERIVED, /* Materialized derived table */ EXPLAIN_NODE_NON_MERGED_SJ /* aka JTBM semi-join */ }; virtual enum explain_node_type get_type()= 0; virtual uint get_select_id()= 0; /** expression cache statistics */ Expression_cache_tracker* cache_tracker; /** If not NULL, this node is a SELECT (or UNION) in a materialized IN-subquery. */ Explain_subq_materialization* subq_materialization; /* How this node is connected to its parent. (NOTE: EXPLAIN_NODE_NON_MERGED_SJ is set very late currently) */ enum explain_connection_type connection_type; protected: /* A node may have children nodes. When a node's explain structure is created, children nodes may not yet have QPFs. This is why we store ids. */ Dynamic_array<int> children; public: void add_child(int select_no) { children.append(select_no); } virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze)=0; virtual void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze)= 0; int print_explain_for_children(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); void print_explain_json_for_children(Explain_query *query, Json_writer *writer, bool is_analyze); bool print_explain_json_cache(Json_writer *writer, bool is_analyze); bool print_explain_json_subq_materialization(Json_writer *writer, bool is_analyze); virtual ~Explain_node() = default; }; class Explain_table_access; /* A basic join. This is only used for SJ-Materialization nests. Basic join doesn't have ORDER/GROUP/DISTINCT operations. It also cannot be degenerate. It has its own select_id. */ class Explain_basic_join : public Explain_node { public: enum explain_node_type get_type() override { return EXPLAIN_BASIC_JOIN; } Explain_basic_join(MEM_ROOT *root) : Explain_node(root), join_tabs(NULL) {} ~Explain_basic_join(); bool add_table(Explain_table_access *tab, Explain_query *query); uint get_select_id() override { return select_id; } uint select_id; int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; void print_explain_json_interns(Explain_query *query, Json_writer *writer, bool is_analyze); /* A flat array of Explain structs for tables. */ Explain_table_access** join_tabs; uint n_join_tabs; }; class Explain_aggr_node; /* EXPLAIN structure for a SELECT. A select can be: 1. A degenerate case. In this case, message!=NULL, and it contains a description of what kind of degenerate case it is (e.g. "Impossible WHERE"). 2. a non-degenrate join. In this case, join_tabs describes the join. In the non-degenerate case, a SELECT may have a GROUP BY/ORDER BY operation. In both cases, the select may have children nodes. class Explain_node provides a way get node's children. */ class Explain_select : public Explain_basic_join { public: enum explain_node_type get_type() override { return EXPLAIN_SELECT; } Explain_select(MEM_ROOT *root, bool is_analyze) : Explain_basic_join(root), #ifndef DBUG_OFF select_lex(NULL), #endif linkage(UNSPECIFIED_TYPE), is_lateral(false), message(NULL), having(NULL), having_value(Item::COND_UNDEF), using_temporary(false), using_filesort(false), cost(0.0), time_tracker(is_analyze), aggr_tree(NULL) {} void add_linkage(Json_writer *writer); public: #ifndef DBUG_OFF SELECT_LEX *select_lex; #endif const char *select_type; enum sub_select_type linkage; bool is_lateral; /* If message != NULL, this is a degenerate join plan, and all subsequent members have no info */ const char *message; /* Expensive constant condition */ Item *exec_const_cond; Item *outer_ref_cond; Item *pseudo_bits_cond; /* HAVING condition */ Item *having; Item::cond_result having_value; /* Global join attributes. In tabular form, they are printed on the first row */ bool using_temporary; bool using_filesort; double cost; /* ANALYZE members */ Time_and_counter_tracker time_tracker; /* Part of query plan describing sorting, temp.table usage, and duplicate removal */ Explain_aggr_node* aggr_tree; int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; Table_access_tracker *get_using_temporary_read_tracker() { return &using_temporary_read_tracker; } private: Table_access_tracker using_temporary_read_tracker; }; ///////////////////////////////////////////////////////////////////////////// // EXPLAIN structures for ORDER/GROUP operations. ///////////////////////////////////////////////////////////////////////////// typedef enum { AGGR_OP_TEMP_TABLE, AGGR_OP_FILESORT, //AGGR_OP_READ_SORTED_FILE, // need this? AGGR_OP_REMOVE_DUPLICATES, AGGR_OP_WINDOW_FUNCS //AGGR_OP_JOIN // Need this? } enum_explain_aggr_node_type; class Explain_aggr_node : public Sql_alloc { public: virtual enum_explain_aggr_node_type get_type()= 0; virtual ~Explain_aggr_node() = default; Explain_aggr_node *child; }; class Explain_aggr_filesort : public Explain_aggr_node { List<Item> sort_items; List<ORDER::enum_order> sort_directions; public: enum_explain_aggr_node_type get_type() override { return AGGR_OP_FILESORT; } Filesort_tracker tracker; Explain_aggr_filesort(MEM_ROOT *mem_root, bool is_analyze, Filesort *filesort); void print_json_members(Json_writer *writer, bool is_analyze); }; class Explain_aggr_tmp_table : public Explain_aggr_node { public: enum_explain_aggr_node_type get_type() override { return AGGR_OP_TEMP_TABLE; } }; class Explain_aggr_remove_dups : public Explain_aggr_node { public: enum_explain_aggr_node_type get_type() override { return AGGR_OP_REMOVE_DUPLICATES; } }; class Explain_aggr_window_funcs : public Explain_aggr_node { List<Explain_aggr_filesort> sorts; public: enum_explain_aggr_node_type get_type() override { return AGGR_OP_WINDOW_FUNCS; } void print_json_members(Json_writer *writer, bool is_analyze); friend class Window_funcs_computation; }; ///////////////////////////////////////////////////////////////////////////// extern const char *unit_operation_text[4]; extern const char *pushed_unit_operation_text[4]; extern const char *pushed_derived_text; extern const char *pushed_select_text; /* Explain structure for a UNION [ALL]. A UNION may or may not have "Using filesort". */ class Explain_union : public Explain_node { public: Explain_union(MEM_ROOT *root, bool is_analyze) : Explain_node(root), union_members(PSI_INSTRUMENT_MEM), is_recursive_cte(false), is_pushed_down_to_engine(false), fake_select_lex_explain(root, is_analyze) {} enum explain_node_type get_type() override { return EXPLAIN_UNION; } unit_common_op operation; uint get_select_id() override { DBUG_ASSERT(union_members.elements() > 0); return union_members.at(0); } /* Members of the UNION. Note: these are different from UNION's "children". Example: (select * from t1) union (select * from t2) order by (select col1 from t3 ...) here - select-from-t1 and select-from-t2 are "union members", - select-from-t3 is the only "child". */ Dynamic_array<int> union_members; void add_select(int select_no) { union_members.append(select_no); } int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; void print_explain_json_regular(Explain_query *query, Json_writer *writer, bool is_analyze); void print_explain_json_pushed_down(Explain_query *query, Json_writer *writer, bool is_analyze); const char *fake_select_type; bool using_filesort; bool using_tmp; bool is_recursive_cte; bool is_pushed_down_to_engine; /* Explain data structure for "fake_select_lex" (i.e. for the degenerate SELECT that reads UNION result). It doesn't have a query plan, but we still need execution tracker, etc. */ Explain_select fake_select_lex_explain; Table_access_tracker *get_fake_select_lex_tracker() { return &fake_select_lex_tracker; } Table_access_tracker *get_tmptable_read_tracker() { return &tmptable_read_tracker; } private: uint make_union_table_name(char *buf); int print_explain_regular(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); int print_explain_pushed_down(select_result_sink *output, uint8 explain_flags, bool is_analyze); Table_access_tracker fake_select_lex_tracker; /* This one is for reading after ORDER BY */ Table_access_tracker tmptable_read_tracker; }; class Explain_update; class Explain_delete; class Explain_insert; /* Explain structure for a query (i.e. a statement). This should be able to survive when the query plan was deleted. Currently, we do not intend for it survive until after query's MEM_ROOT is freed. == ExplainDataStructureLifetime == >dispatch_command | >mysql_parse | | ... | | | | explain->query_plan_ready(); // (1) | | | | some_join->cleanup(); // (2) | | | | explain->notify_tables_are_closed(); // (3) | | close_thread_tables(); // (4) | | ... | | free_items(); // (5) | | ... | | | <mysql_parse | | log_slow_statement() // (6) | | free_root() | >dispatch_command (1) - Query plan construction is finished and it is available for reading. (2) - Temporary tables are freed (with exception of derived tables which are freed at step (4)). The tables are no longer accessible but one can still call item->print(), even for items that refer to temp.tables (see Item_field::print() for details) (3) - Notification about (4). (4) - Tables used by the query are closed. One consequence of this is that the values of the const tables' fields are not available anymore. We could adjust the code in Item_field::print() to handle this but instead we make step (3) disallow production of FORMAT=JSON output. We also disable processing of SHOW EXPLAIN|ANALYZE output because the query is about to finish anyway. (5) - Item objects are freed. After this, it's certainly not possible to print them into FORMAT=JSON output. (6) - We may decide to log tabular EXPLAIN output to the slow query log. */ class Explain_query : public Sql_alloc { public: Explain_query(THD *thd, MEM_ROOT *root); ~Explain_query(); /* Add a new node */ void add_node(Explain_node *node); void add_insert_plan(Explain_insert *insert_plan_arg); void add_upd_del_plan(Explain_update *upd_del_plan_arg); /* This will return a select, or a union */ Explain_node *get_node(uint select_id); /* This will return a select (even if there is a union with this id) */ Explain_select *get_select(uint select_id); Explain_union *get_union(uint select_id); /* Produce a tabular EXPLAIN output */ int print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze); /* Send tabular EXPLAIN to the client */ int send_explain(THD *thd, bool extended); /* Return tabular EXPLAIN output as a text string */ bool print_explain_str(THD *thd, String *out_str, bool is_analyze); int print_explain_json(select_result_sink *output, bool is_analyze, ulonglong query_time_in_progress_ms= 0); /* If true, at least part of EXPLAIN can be printed */ bool have_query_plan() { return insert_plan || upd_del_plan|| get_node(1) != NULL; } void query_plan_ready(); void notify_tables_are_closed(); MEM_ROOT *mem_root; Explain_update *get_upd_del_plan() { return upd_del_plan; } private: bool print_query_blocks_json(Json_writer *writer, const bool is_analyze); void print_query_optimization_json(Json_writer *writer); void send_explain_json_to_output(Json_writer *writer, select_result_sink *output); /* Explain_delete inherits from Explain_update */ Explain_update *upd_del_plan; /* Query "plan" for INSERTs */ Explain_insert *insert_plan; Dynamic_array<Explain_union*> unions; Dynamic_array<Explain_select*> selects; THD *stmt_thd; // for APC start/stop bool apc_enabled; /* Debugging aid: count how many times add_node() was called. Ideally, it should be one, we currently allow O(1) query plan saves for each select or union. The goal is not to have O(#rows_in_some_table), which is unacceptable. */ longlong operations; #ifndef DBUG_OFF bool can_print_json= false; #endif Exec_time_tracker optimization_time_tracker; }; /* Some of the tags have matching text. See extra_tag_text for text names, and Explain_table_access::append_tag_name() for code to convert from tag form to text form. */ enum explain_extra_tag { ET_none= 0, /* not-a-tag */ ET_USING_INDEX_CONDITION, ET_USING_INDEX_CONDITION_BKA, ET_USING, /* For quick selects of various kinds */ ET_RANGE_CHECKED_FOR_EACH_RECORD, ET_USING_WHERE_WITH_PUSHED_CONDITION, ET_USING_WHERE, ET_NOT_EXISTS, ET_USING_INDEX, ET_FULL_SCAN_ON_NULL_KEY, ET_SKIP_OPEN_TABLE, ET_OPEN_FRM_ONLY, ET_OPEN_FULL_TABLE, ET_SCANNED_0_DATABASES, ET_SCANNED_1_DATABASE, ET_SCANNED_ALL_DATABASES, ET_USING_INDEX_FOR_GROUP_BY, ET_USING_MRR, // does not print "Using mrr". ET_DISTINCT, ET_LOOSESCAN, ET_START_TEMPORARY, ET_END_TEMPORARY, ET_FIRST_MATCH, ET_USING_JOIN_BUFFER, ET_CONST_ROW_NOT_FOUND, ET_UNIQUE_ROW_NOT_FOUND, ET_IMPOSSIBLE_ON_CONDITION, ET_TABLE_FUNCTION, ET_total }; /* Explain data structure describing join buffering use. */ class EXPLAIN_BKA_TYPE { public: EXPLAIN_BKA_TYPE() : join_alg(NULL) {} size_t join_buffer_size; bool incremental; /* NULL if no join buferring used. Other values: BNL, BNLH, BKA, BKAH. */ const char *join_alg; /* Information about MRR usage. */ StringBuffer<64> mrr_type; bool is_using_jbuf() { return (join_alg != NULL); } }; /* Data about how an index is used by some access method */ class Explain_index_use : public Sql_alloc { char *key_name; uint key_len; char *filter_name; uint filter_len; public: String_list key_parts_list; Explain_index_use() { clear(); } void clear() { key_name= NULL; key_len= (uint)-1; filter_name= NULL; filter_len= (uint)-1; } bool set(MEM_ROOT *root, KEY *key_name, uint key_len_arg); bool set_pseudo_key(MEM_ROOT *root, const char *key_name); inline const char *get_key_name() const { return key_name; } inline uint get_key_len() const { return key_len; } //inline const char *get_filter_name() const { return filter_name; } }; /* Query Plan data structure for Rowid filter. */ class Explain_rowid_filter : public Sql_alloc { public: /* Quick select used to collect the rowids into filter */ Explain_quick_select *quick; /* How many rows the above quick select is expected to return */ ha_rows rows; /* Expected selectivity for the filter */ double selectivity; /* Tracker with the information about how rowid filter is executed */ Rowid_filter_tracker *tracker; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze); /* TODO: Here should be ANALYZE members: - r_rows for the quick select - An object that tracked the table access time - real selectivity of the filter. */ }; /* QPF for quick range selects, as well as index_merge select */ class Explain_quick_select : public Sql_alloc { public: Explain_quick_select(int quick_type_arg) : quick_type(quick_type_arg) {} const int quick_type; bool is_basic() { return (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE || quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC || quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX); } /* This is used when quick_type == QUICK_SELECT_I::QS_TYPE_RANGE */ Explain_index_use range; /* Used in all other cases */ List<Explain_quick_select> children; void print_extra(String *str); void print_key(String *str); void print_key_len(String *str); void print_json(Json_writer *writer); void print_extra_recursive(String *str); private: const char *get_name_by_type(); }; /* Data structure for "range checked for each record". It's a set of keys, tabular explain prints hex bitmap, json prints key names. */ typedef const char* NAME; class Explain_range_checked_fer : public Sql_alloc { public: String_list key_set; key_map keys_map; private: ha_rows full_scan, index_merge; ha_rows *keys_stat; NAME *keys_stat_names; uint keys; public: Explain_range_checked_fer() :Sql_alloc(), full_scan(0), index_merge(0), keys_stat(0), keys_stat_names(0), keys(0) {} int append_possible_keys_stat(MEM_ROOT *alloc, TABLE *table, key_map possible_keys); void collect_data(QUICK_SELECT_I *quick); void print_json(Json_writer *writer, bool is_analyze); }; /* EXPLAIN data structure for a single JOIN_TAB. */ class Explain_table_access : public Sql_alloc { public: Explain_table_access(MEM_ROOT *root, bool timed) : derived_select_number(0), non_merged_sjm_number(0), cost(0.0), loops(0.0), extra_tags(root), range_checked_fer(NULL), full_scan_on_null_key(false), start_dups_weedout(false), end_dups_weedout(false), where_cond(NULL), cache_cond(NULL), pushed_index_cond(NULL), sjm_nest(NULL), pre_join_sort(NULL), handler_for_stats(NULL), jbuf_unpack_tracker(timed), rowid_filter(NULL) {} ~Explain_table_access() { delete sjm_nest; } void push_extra(enum explain_extra_tag extra_tag); /* Internals */ /* id and 'select_type' are cared-of by the parent Explain_select */ StringBuffer<32> table_name; StringBuffer<32> used_partitions; String_list used_partitions_list; // valid with ET_USING_MRR StringBuffer<32> mrr_type; StringBuffer<32> firstmatch_table_name; /* Non-zero number means this is a derived table. The number can be used to find the query plan for the derived table */ int derived_select_number; /* TODO: join with the previous member. */ int non_merged_sjm_number; enum join_type type; bool used_partitions_set; /* Empty means "NULL" will be printed */ String_list possible_keys; bool rows_set; /* not set means 'NULL' should be printed */ bool filtered_set; /* not set means 'NULL' should be printed */ // Valid if ET_USING_INDEX_FOR_GROUP_BY is present bool loose_scan_is_scanning; /* Index use: key name and length. Note: that when one is accessing I_S tables, those may show use of non-existant indexes. key.key_name == NULL means 'NULL' will be shown in tabular output. key.key_len == (uint)-1 means 'NULL' will be shown in tabular output. */ Explain_index_use key; /* when type==JT_HASH_NEXT, 'key' stores the hash join pseudo-key. hash_next_key stores the table's key. */ Explain_index_use hash_next_key; String_list ref_list; ha_rows rows; double filtered; /* Total cost incurred during one execution of this select */ double cost; double loops; /* Contents of the 'Extra' column. Some are converted into strings, some have parameters, values for which are stored below. */ Dynamic_array<enum explain_extra_tag> extra_tags; // Valid if ET_USING tag is present Explain_quick_select *quick_info; /* Non-NULL value means this tab uses "range checked for each record" */ Explain_range_checked_fer *range_checked_fer; bool full_scan_on_null_key; // valid with ET_USING_JOIN_BUFFER EXPLAIN_BKA_TYPE bka_type; bool start_dups_weedout; bool end_dups_weedout; /* Note: lifespan of WHERE condition is less than lifespan of this object. The below two are valid if tags include "ET_USING_WHERE". (TODO: indexsubquery may put ET_USING_WHERE without setting where_cond?) */ Item *where_cond; Item *cache_cond; /* This is either pushed index condition, or BKA's index condition. (the latter refers to columns of other tables and so can only be checked by BKA code). Examine extra_tags to tell which one it is. */ Item *pushed_index_cond; Explain_basic_join *sjm_nest; /* This describes a possible filesort() call that is done before doing the join operation. */ Explain_aggr_filesort *pre_join_sort; /* ANALYZE members */ /* Tracker for reading the table */ Table_access_tracker tracker; Exec_time_tracker op_tracker; Gap_time_tracker extra_time_tracker; /* Handler object to get the handler_stats from. Notes: This pointer is only valid until notify_tables_are_closed() is called. After that, the tables may be freed or reused, together with their handler_stats objects. notify_tables_are_closed() disables printing of FORMAT=JSON output. r_engine_stats is only printed in FORMAT=JSON output, so we're fine. We do not store pointers to temporary (aka "work") tables here. Temporary tables may be freed (e.g. by JOIN::cleanup()) or re-created during query execution (when HEAP table is converted into Aria). */ handler *handler_for_stats; /* When using join buffer: Track the reads from join buffer */ Table_access_tracker jbuf_tracker; /* When using join buffer: time spent unpacking rows from the join buffer */ Time_and_counter_tracker jbuf_unpack_tracker; /* When using join buffer: time spent after unpacking rows from the join buffer. This will capture the time spent checking the Join Condition: the condition that depends on this table and preceding tables. */ Gap_time_tracker jbuf_extra_time_tracker; /* When using join buffer: Track the number of incoming record combinations */ Counter_tracker jbuf_loops_tracker; Explain_rowid_filter *rowid_filter; int print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze, uint select_id, const char *select_type, bool using_temporary, bool using_filesort); void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze); private: void append_tag_name(String *str, enum explain_extra_tag tag); void fill_key_str(String *key_str, bool is_json) const; void fill_key_len_str(String *key_len_str, bool is_json) const; double get_r_filtered(); void tag_to_json(Json_writer *writer, enum explain_extra_tag tag); }; /* EXPLAIN structure for single-table UPDATE. This is similar to Explain_table_access, except that it is more restrictive. Also, it can have UPDATE operation options, but currently there aren't any. Explain_delete inherits from this. */ class Explain_update : public Explain_node { public: Explain_update(MEM_ROOT *root, bool is_analyze) : Explain_node(root), filesort_tracker(NULL), command_tracker(is_analyze), handler_for_stats(NULL) {} enum explain_node_type get_type() override { return EXPLAIN_UPDATE; } uint get_select_id() override { return 1; /* always root */ } const char *select_type; StringBuffer<32> used_partitions; String_list used_partitions_list; bool used_partitions_set; bool impossible_where; bool no_partitions; StringBuffer<64> table_name; enum join_type jtype; String_list possible_keys; /* Used key when doing a full index scan (possibly with limit) */ Explain_index_use key; /* MRR that's used with quick select. This should probably belong to the quick select */ StringBuffer<64> mrr_type; Explain_quick_select *quick_info; bool using_where; Item *where_cond; ha_rows rows; bool using_io_buffer; /* Tracker for doing reads when filling the buffer */ Table_access_tracker buf_tracker; bool is_using_filesort() { return filesort_tracker? true: false; } /* Non-null value of filesort_tracker means "using filesort" if we are using filesort, then table_tracker is for the io done inside filesort. 'tracker' is for tracking post-filesort reads. */ Filesort_tracker *filesort_tracker; /* ANALYZE members and methods */ Table_access_tracker tracker; /* This tracks execution of the whole command */ Time_and_counter_tracker command_tracker; /* TODO: This tracks time to read rows from the table */ Exec_time_tracker table_tracker; Gap_time_tracker extra_time_tracker; /* The same as Explain_table_access::handler_for_stats */ handler *handler_for_stats; int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; }; /* EXPLAIN data structure for an INSERT. At the moment this doesn't do much as we don't really have any query plans for INSERT statements. */ class Explain_insert : public Explain_node { public: Explain_insert(MEM_ROOT *root) : Explain_node(root) {} StringBuffer<64> table_name; enum explain_node_type get_type() override { return EXPLAIN_INSERT; } uint get_select_id() override { return 1; /* always root */ } int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; }; /* EXPLAIN data of a single-table DELETE. */ class Explain_delete: public Explain_update { public: Explain_delete(MEM_ROOT *root, bool is_analyze) : Explain_update(root, is_analyze) {} /* TRUE means we're going to call handler->delete_all_rows() and not read any rows. */ bool deleting_all_rows; enum explain_node_type get_type() override { return EXPLAIN_DELETE; } uint get_select_id() override { return 1; /* always root */ } int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) override; void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) override; }; /* EXPLAIN data structure for subquery materialization. All decisions are made at execution time so here we just store the tracker that has all the info. */ class Explain_subq_materialization : public Sql_alloc { public: Explain_subq_materialization(MEM_ROOT *mem_root) : tracker(mem_root) {} Subq_materialization_tracker *get_tracker() { return &tracker; } void print_explain_json(Json_writer *writer, bool is_analyze); private: Subq_materialization_tracker tracker; }; #endif //SQL_EXPLAIN_INCLUDED partition_element.h 0000644 00000012464 15156036150 0010450 0 ustar 00 #ifndef PARTITION_ELEMENT_INCLUDED #define PARTITION_ELEMENT_INCLUDED /* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_base.h" /* ha_rows */ #include "handler.h" /* UNDEF_NODEGROUP */ /** * An enum and a struct to handle partitioning and subpartitioning. */ enum partition_type { NOT_A_PARTITION= 0, RANGE_PARTITION, HASH_PARTITION, LIST_PARTITION, VERSIONING_PARTITION }; enum partition_state { PART_NORMAL= 0, PART_IS_DROPPED= 1, PART_TO_BE_DROPPED= 2, PART_TO_BE_ADDED= 3, PART_TO_BE_REORGED= 4, PART_REORGED_DROPPED= 5, PART_CHANGED= 6, PART_IS_CHANGED= 7, PART_IS_ADDED= 8, PART_ADMIN= 9 }; /* This struct is used to keep track of column expressions as part of the COLUMNS concept in conjunction with RANGE and LIST partitioning. The value can be either of MINVALUE, MAXVALUE and an expression that must be constant and evaluate to the same type as the column it represents. The data in this fixed in two steps. The parser will only fill in whether it is a max_value or provide an expression. Filling in column_value, part_info, partition_id, null_value is done by the function fix_column_value_function. However the item tree needs fixed also before writing it into the frm file (in add_column_list_values). To distinguish between those two variants, fixed= 1 after the fixing in add_column_list_values and fixed= 2 otherwise. This is since the fixing in add_column_list_values isn't a complete fixing. */ typedef struct p_column_list_val { void* column_value; Item* item_expression; partition_info *part_info; uint partition_id; bool max_value; // MAXVALUE for RANGE type or DEFAULT value for LIST type bool null_value; char fixed; } part_column_list_val; /* This struct is used to contain the value of an element in the VALUES IN struct. It needs to keep knowledge of whether it is a signed/unsigned value and whether it is NULL or not. */ typedef struct p_elem_val { longlong value; uint added_items; bool null_value; bool unsigned_flag; part_column_list_val *col_val_array; } part_elem_value; struct st_ddl_log_memory_entry; enum stat_trx_field { STAT_TRX_END= 0 }; class partition_element :public Sql_alloc { public: enum elem_type_enum { CONVENTIONAL= 0, CURRENT, HISTORY }; List<partition_element> subpartitions; List<part_elem_value> list_val_list; ha_rows part_max_rows; ha_rows part_min_rows; longlong range_value; const char *partition_name; struct st_ddl_log_memory_entry *log_entry; const char* part_comment; const char* data_file_name; const char* index_file_name; handlerton *engine_type; LEX_CSTRING connect_string; enum partition_state part_state; uint16 nodegroup_id; bool has_null_value; bool signed_flag; // Range value signed bool max_value; // MAXVALUE range uint32 id; bool empty; elem_type_enum type; engine_option_value *option_list; // create options for partition ha_table_option_struct *option_struct; // structure with parsed options partition_element() : part_max_rows(0), part_min_rows(0), range_value(0), partition_name(NULL), log_entry(NULL), part_comment(NULL), data_file_name(NULL), index_file_name(NULL), engine_type(NULL), connect_string(null_clex_str), part_state(PART_NORMAL), nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), signed_flag(FALSE), max_value(FALSE), id(UINT_MAX32), empty(true), type(CONVENTIONAL), option_list(NULL), option_struct(NULL) {} partition_element(partition_element *part_elem) : part_max_rows(part_elem->part_max_rows), part_min_rows(part_elem->part_min_rows), range_value(0), partition_name(NULL), log_entry(NULL), part_comment(part_elem->part_comment), data_file_name(part_elem->data_file_name), index_file_name(part_elem->index_file_name), engine_type(part_elem->engine_type), connect_string(null_clex_str), part_state(part_elem->part_state), nodegroup_id(part_elem->nodegroup_id), has_null_value(FALSE), signed_flag(part_elem->signed_flag), max_value(part_elem->max_value), id(part_elem->id), empty(part_elem->empty), type(CONVENTIONAL), option_list(part_elem->option_list), option_struct(part_elem->option_struct) {} ~partition_element() = default; part_column_list_val& get_col_val(uint idx) { part_elem_value *ev= list_val_list.head(); DBUG_ASSERT(ev); DBUG_ASSERT(ev->col_val_array); return ev->col_val_array[idx]; } }; #endif /* PARTITION_ELEMENT_INCLUDED */ my_uctype.h 0000644 00000207630 15156036150 0006745 0 ustar 00 #ifndef MY_UCTYPE_INCLUDED #define MY_UCTYPE_INCLUDED /* Copyright (c) 2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Unicode ctype data Generated from UnicodeData-5.0.0d9.txt */ static unsigned char uctype_page00[256]= { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 16, 16, 16, 16, 16, 16, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 32, 16, 16, 16, 16, 20, 20, 16, 2, 16, 16, 16, 20, 2, 16, 20, 20, 20, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2 }; static unsigned char uctype_page01[256]= { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2 }; static unsigned char uctype_page02[256]= { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static unsigned char uctype_page03[256]= { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 2, 2, 2, 2, 16, 0, 0, 0, 0, 0, 16, 16, 1, 16, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 16, 1, 2, 1, 1, 2, 2, 1, 1, 1 }; static unsigned char uctype_page04[256]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 16, 18, 18, 18, 18, 0, 18, 18, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 }; static unsigned char uctype_page05[256]= { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 16, 16, 16, 16, 16, 16, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 16, 16, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 18, 16, 18, 18, 16, 18, 18, 16, 18, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page06[256]= { 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 16, 0, 0, 16, 16, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 2, 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 18, 18, 18, 18, 18, 18, 18, 32, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, 16, 18, 18, 18, 18, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 16, 16, 2 }; static unsigned char uctype_page07[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 32, 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 2, 16, 16, 16, 16, 2, 0, 0, 0, 0, 0 }; static unsigned char uctype_page09[256]= { 0, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 2, 18, 18, 18, 18, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 0, 0, 18, 18, 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 16, 16, 20, 20, 20, 20, 20, 20, 16, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0A[256]= { 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 18, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0B[256]= { 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0C[256]= { 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0D[256]= { 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 18, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0E[256]= { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 16, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 0, 18, 18, 2, 0, 0, 2, 2, 2, 2, 2, 0, 2, 0, 18, 18, 18, 18, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page0F[256]= { 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 18, 16, 18, 16, 18, 16, 16, 16, 16, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 18, 18, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 16, 16, 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page10[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 0, 0, 0 }; static unsigned char uctype_page11[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page12[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static unsigned char uctype_page13[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page14[256]= { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static unsigned char uctype_page16[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page17[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 32, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 16, 16, 2, 16, 16, 16, 16, 2, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page18[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 8, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page19[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 16, 0, 0, 0, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static unsigned char uctype_page1A[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page1B[256]= { 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page1D[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18 }; static unsigned char uctype_page1E[256]= { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page1F[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 2, 16, 16, 16, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, 2, 2, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 0, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, 0, 0, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 0 }; static unsigned char uctype_page20[256]= { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 32, 32, 32, 32, 32, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 20, 2, 0, 0, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page21[256]= { 16, 16, 1, 16, 16, 16, 16, 1, 16, 16, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 16, 1, 16, 16, 16, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, 16, 1, 16, 1, 16, 1, 16, 1, 1, 1, 1, 16, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 1, 1, 16, 16, 16, 16, 16, 1, 2, 2, 2, 2, 16, 16, 16, 16, 2, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static unsigned char uctype_page23[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page24[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }; static unsigned char uctype_page26[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page27[256]= { 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 16, 16, 16, 16, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static unsigned char uctype_page2B[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page2C[256]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 20, 16, 16 }; static unsigned char uctype_page2D[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page2E[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_page2F[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0 }; static unsigned char uctype_page30[256]= { 8, 16, 16, 16, 16, 2, 2, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 18, 18, 18, 18, 18, 16, 2, 2, 2, 2, 2, 16, 16, 7, 7, 7, 2, 2, 16, 16, 16, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 18, 16, 16, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2 }; static unsigned char uctype_page31[256]= { 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static unsigned char uctype_page32[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0 }; static unsigned char uctype_page4D[256]= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static unsigned char uctype_page9F[256]= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageA4[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageA7[256]= { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageA8[256]= { 2, 2, 18, 2, 2, 2, 18, 2, 2, 2, 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageD7[256]= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageD8[256]= { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageDB[256]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 }; static unsigned char uctype_pageDC[256]= { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageDF[256]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 }; static unsigned char uctype_pageE0[256]= { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageF8[256]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 }; static unsigned char uctype_pageFA[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char uctype_pageFB[256]= { 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static unsigned char uctype_pageFD[256]= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0 }; static unsigned char uctype_pageFE[256]= { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 32 }; static unsigned char uctype_pageFF[256]= { 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 16, 16, 0, 0 }; MY_UNI_CTYPE my_uni_ctype[256]={ {0,uctype_page00}, {0,uctype_page01}, {0,uctype_page02}, {0,uctype_page03}, {0,uctype_page04}, {0,uctype_page05}, {0,uctype_page06}, {0,uctype_page07}, {0,NULL}, {0,uctype_page09}, {0,uctype_page0A}, {0,uctype_page0B}, {0,uctype_page0C}, {0,uctype_page0D}, {0,uctype_page0E}, {0,uctype_page0F}, {0,uctype_page10}, {0,uctype_page11}, {0,uctype_page12}, {0,uctype_page13}, {0,uctype_page14}, {2,NULL}, {0,uctype_page16}, {0,uctype_page17}, {0,uctype_page18}, {0,uctype_page19}, {0,uctype_page1A}, {0,uctype_page1B}, {0,NULL}, {0,uctype_page1D}, {0,uctype_page1E}, {0,uctype_page1F}, {0,uctype_page20}, {0,uctype_page21}, {16,NULL}, {0,uctype_page23}, {0,uctype_page24}, {16,NULL}, {0,uctype_page26}, {0,uctype_page27}, {16,NULL}, {16,NULL}, {16,NULL}, {0,uctype_page2B}, {0,uctype_page2C}, {0,uctype_page2D}, {0,uctype_page2E}, {0,uctype_page2F}, {0,uctype_page30}, {0,uctype_page31}, {0,uctype_page32}, {16,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {0,uctype_page4D}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {0,uctype_page9F}, {2,NULL}, {2,NULL}, {2,NULL}, {2,NULL}, {0,uctype_pageA4}, {0,NULL}, {0,NULL}, {0,uctype_pageA7}, {0,uctype_pageA8}, {0,NULL}, {0,NULL}, {0,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {3,NULL}, {0,uctype_pageD7}, {0,uctype_pageD8}, {0,NULL}, {0,NULL}, {0,uctype_pageDB}, {0,uctype_pageDC}, {0,NULL}, {0,NULL}, {0,uctype_pageDF}, {0,uctype_pageE0}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, {0,uctype_pageF8}, {2,NULL}, {0,uctype_pageFA}, {0,uctype_pageFB}, {2,NULL}, {0,uctype_pageFD}, {0,uctype_pageFE}, {0,uctype_pageFF} }; #endif /* MY_UCTYPE_INCLUDED */ sp_instr.h 0000644 00000120650 15156036150 0006564 0 ustar 00 #ifndef _SP_INSTR_H_ #define _SP_INSTR_H_ #include "mariadb.h" #include "sql_alloc.h" // Sql_alloc #include "sql_class.h" // THD, Query_arena #include "sql_lex.h" // class sp_lex_local #include "sp_pcontext.h" // class sp_pcontext #include "sp_head.h" // class sp_head /* Sufficient max length of frame offsets. */ static const int SP_INSTR_UINT_MAXLEN= 8; class sp_lex_cursor: public sp_lex_local, public Query_arena { public: sp_lex_cursor(THD *thd, const LEX *oldlex, MEM_ROOT *mem_root_arg) : sp_lex_local(thd, oldlex), Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP), m_expr_str(empty_clex_str) {} sp_lex_cursor(THD *thd, const LEX *oldlex) : sp_lex_local(thd, oldlex), Query_arena(thd->lex->sphead->get_main_mem_root(), STMT_INITIALIZED_FOR_SP), m_expr_str(empty_clex_str) {} ~sp_lex_cursor() { free_items(); } bool cleanup_stmt(bool /*restore_set_statement_vars*/) override { return false; } Query_arena *query_arena() override { return this; } bool validate() { DBUG_ASSERT(sql_command == SQLCOM_SELECT); if (result) { my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0)); return true; } return false; } bool stmt_finalize(THD *thd) { if (validate()) return true; sp_lex_in_use= true; free_list= thd->free_list; thd->free_list= nullptr; return false; } void set_expr_str(const LEX_CSTRING &expr_str) { m_expr_str= expr_str; } const LEX_CSTRING &get_expr_str() const { return m_expr_str; } sp_lex_cursor* get_lex_for_cursor() override { return this; } private: LEX_CSTRING m_expr_str; }; // // "Instructions"... // // Forward declaration for use in the method sp_instr::opt_move(). class sp_instr_opt_meta; class sp_instr :public Query_arena, public Sql_alloc { sp_instr(const sp_instr &); /**< Prevent use of these */ void operator=(sp_instr &); public: uint marked; uint m_ip; ///< My index sp_pcontext *m_ctx; ///< My parse context uint m_lineno; /// Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) : Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx), m_lineno(0) #ifdef PROTECT_STATEMENT_MEMROOT , m_has_been_run(NON_RUN) #endif {} virtual ~sp_instr() { free_items(); } /** Execute this instruction @param thd Thread handle @param[out] nextp index of the next instruction to execute. (For most instructions this will be the instruction following this one). Note that this parameter is undefined in case of errors, use get_cont_dest() to find the continuation instruction for CONTINUE error handlers. @retval 0 on success, @retval other if some error occurred */ virtual int execute(THD *thd, uint *nextp) = 0; /** Execute <code>open_and_lock_tables()</code> for this statement. Open and lock the tables used by this statement, as a pre-requisite to execute the core logic of this instruction with <code>exec_core()</code>. @param thd the current thread @param tables the list of tables to open and lock @return zero on success, non zero on failure. */ int exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables); /** Get the continuation destination of this instruction. @return the continuation destination */ virtual uint get_cont_dest() const; /* Execute core function of instruction after all preparations (e.g. setting of proper LEX, saving part of the thread context have been done). Should be implemented for instructions using expressions or whole statements (thus having to have own LEX). Used in concert with sp_lex_keeper class and its descendants (there are none currently). */ virtual int exec_core(THD *thd, uint *nextp); virtual void print(String *str) = 0; virtual void backpatch(uint dest, sp_pcontext *dst_ctx) {} /** Mark this instruction as reachable during optimization and return the index to the next instruction. Jump instruction will add their destination to the leads list. */ virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads) { marked= 1; return m_ip+1; } /** Short-cut jumps to jumps during optimization. This is used by the jump instructions' opt_mark() methods. 'start' is the starting point, used to prevent the mark sweep from looping for ever. Return the end destination. */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; } /** Inform the instruction that it has been moved during optimization. Most instructions will simply update its index, but jump instructions must also take care of their destination pointers. Forward jumps get pushed to the backpatch list 'ibp'. */ virtual void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) { m_ip= dst; } virtual PSI_statement_info* get_psi_info() = 0; virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list() { return nullptr; } #ifdef PROTECT_STATEMENT_MEMROOT bool has_been_run() const { return m_has_been_run == RUN; } void mark_as_qc_used() { m_has_been_run= QC; } void mark_as_run() { if (m_has_been_run == QC) m_has_been_run= NON_RUN; // answer was from WC => not really executed else m_has_been_run= RUN; } void mark_as_not_run() { m_has_been_run= NON_RUN; } private: enum {NON_RUN, QC, RUN} m_has_been_run; #endif }; // class sp_instr : public Sql_alloc class sp_instr; class sp_lex_instr; /** Auxilary class to which instructions delegate responsibility for handling LEX and preparations before executing statement or calculating complex expression. Exist mainly to avoid having double hierarchy between instruction classes. @todo Add ability to not store LEX and do any preparations if expression used is simple. */ class sp_lex_keeper final { /** Prevent use of these */ sp_lex_keeper(const sp_lex_keeper &); void operator=(sp_lex_keeper &); public: sp_lex_keeper(LEX *lex, bool lex_resp) : m_lex(lex), m_lex_resp(lex_resp), prelocking_tables(nullptr), lex_query_tables_own_last(nullptr), m_first_execution(true) { lex->sp_lex_in_use= true; } ~sp_lex_keeper() { if (m_lex_resp) { m_lex_resp= false; /* Prevent endless recursion. */ m_lex->sphead= nullptr; delete m_lex->result; lex_end(m_lex); delete m_lex; } } /** Prepare execution of instruction using LEX, if requested check whenever we have read access to tables used and open/lock them, call instruction's exec_core() method, perform cleanup afterwards. @todo Conflicting comment in sp_head.cc */ int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, sp_instr* instr, bool rerun_the_same_instr); /** Do several attempts to execute an instruction. This method installs Reprepare_observer to catch possible metadata changes on depending database objects, then calls reset_lex_and_exec_core() to execute the instruction. If execution of the instruction fails, does re-parsing of the instruction and re-execute it. @param thd Thread context. @param[out] nextp Pointer for storing a next instruction to execute @param open_tables Flag to specify if the function should check read access to tables in LEX's table list and open and lock them (used in instructions which need to calculate some expression and don't execute complete statement). @param instr instruction which we prepare context and run. @return 0 on success, 1 on error */ int validate_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, sp_lex_instr* instr); int cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, sp_lex_instr *instr); /** (Re-)parse the query corresponding to this instruction and return a new LEX-object. @param thd Thread context. @param sp The stored program. @return new LEX-object or NULL in case of failure. */ LEX *parse_expr(THD *thd, const sp_head *sp); inline uint sql_command() const { return (uint)m_lex->sql_command; } void disable_query_cache() { m_lex->safe_to_cache_query= 0; } private: /** Clean up and destroy owned LEX object. */ void free_lex(THD *thd); /** Set LEX object. @param lex LEX-object */ void set_lex(LEX *lex); private: LEX *m_lex; /** Indicates whenever this sp_lex_keeper instance responsible for LEX deletion. */ bool m_lex_resp; /* Support for being able to execute this statement in two modes: a) inside prelocked mode set by the calling procedure or its ancestor. b) outside of prelocked mode, when this statement enters/leaves prelocked mode itself. */ /** List of additional tables this statement needs to lock when it enters/leaves prelocked mode on its own. */ TABLE_LIST *prelocking_tables; /** The value m_lex->query_tables_own_last should be set to this when the statement enters/leaves prelocked mode on its own. */ TABLE_LIST **lex_query_tables_own_last; bool m_first_execution; }; /** The base class for any stored program instruction that need to get access to a LEX object on execution. */ class sp_lex_instr : public sp_instr { public: sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner) : sp_instr(ip, ctx), m_lex_keeper(lex, is_lex_owner), m_mem_root_for_reparsing(nullptr) {} ~sp_lex_instr() override { if (m_mem_root_for_reparsing) { /* Free items owned by an instance of sp_lex_instr and call m_lex_keeper's destructor explicitly to avoid referencing a deallocated memory owned by the memory root m_mem_root_for_reparsing that else would take place in case their implicit invocations (in that case, m_lex_keeper's destructor and the method free_items() called by ~sp_instr are invoked after the memory owned by the memory root m_mem_root_for_reparsing be freed, that would result in abnormal server termination) */ free_items(); m_lex_keeper.~sp_lex_keeper(); free_root(m_mem_root_for_reparsing, MYF(0)); m_mem_root_for_reparsing= nullptr; } } virtual bool is_invalid() const = 0; virtual void invalidate() = 0; /** Return the query string, which can be passed to the parser, that is a valid SQL-statement. @param[out] sql_query SQL-statement query string. */ virtual void get_query(String *sql_query) const; /** (Re-)parse the query corresponding to this instruction and return a new LEX-object. @param thd Thread context. @param sp The stored program. @param lex SP instruction's lex @return new LEX-object or NULL in case of failure. */ LEX *parse_expr(THD *thd, sp_head *sp, LEX *lex); SQL_I_List<Item_trigger_field>* get_instr_trig_field_list() override { return &m_cur_trigger_stmt_items; } protected: /** @return the expression query string. This string can't be passed directly to the parser as it is most likely not a valid SQL-statement. */ virtual LEX_CSTRING get_expr_query() const = 0; /** Some expressions may be re-parsed as SELECT statements. This method is overridden in derived classes for instructions those SQL command should be adjusted. */ virtual void adjust_sql_command(LEX *) {} /** Callback method which is called after an expression string successfully parsed and the thread context has not been switched to the outer context. The thread context contains new LEX-object corresponding to the parsed expression string. @param thd Thread context. @return Error flag. */ virtual bool on_after_expr_parsing(THD *) { return false; } sp_lex_keeper m_lex_keeper; private: /** List of Item_trigger_field objects created on parsing of a SQL statement corresponding to this SP-instruction. */ SQL_I_List<Item_trigger_field> m_cur_trigger_stmt_items; /** MEM_ROOT used for allocation of memory on re-parsing of a statement caused failure of SP-instruction execution */ MEM_ROOT *m_mem_root_for_reparsing; /** Clean up items previously created on behalf of the current instruction. @return a list of Item_param instances representing position parameters specified for the instruction that is a part of a prepared statement */ List<Item_param> cleanup_before_parsing(enum_sp_type sp_type); /** Set up field object for every NEW/OLD item of the trigger and move the list of Item_trigger_field objects, created on parsing the current trigger's instruction, from sp_head to trigger's SP instruction object. @param thd current thread @param sp sp_head object of the trigger @param next_trig_items_list pointer to the next list of Item_trigger_field objects that used as a link between lists to support list of lists structure. @return false on success, true on failure */ bool setup_table_fields_for_trigger( THD *thd, sp_head *sp, SQL_I_List<Item_trigger_field> *next_trig_items_list); bool setup_memroot_for_reparsing(sp_head *sphead, bool *new_memroot_allocated); void put_back_item_params(THD *thd, LEX *lex, const List<Item_param>& param_values); }; /** The class sp_instr_stmt represents almost all conventional SQL-statements. */ class sp_instr_stmt : public sp_lex_instr { sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */ void operator=(sp_instr_stmt &); /** Flag to tell whether a metadata this instruction depends on has been changed and a LEX object should be reinitialized. */ bool m_valid; LEX_STRING m_query; ///< For thd->query public: sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex, const LEX_STRING& query) : sp_lex_instr(ip, ctx, lex, true), m_valid(true), m_query(query) {} virtual ~sp_instr_stmt() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; bool is_invalid() const override { return !m_valid; } void invalidate() override { m_valid= false; } void get_query(String *sql_query) const override { sql_query->append(get_expr_query()); } protected: LEX_CSTRING get_expr_query() const override { return m_query; } bool on_after_expr_parsing(THD *) override { m_valid= true; return false; } public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_stmt : public sp_lex_instr class sp_instr_set : public sp_lex_instr, public sp_rcontext_addr { sp_instr_set(const sp_instr_set &); /**< Prevent use of these */ void operator=(sp_instr_set &); public: sp_instr_set(uint ip, sp_pcontext *ctx, const Sp_rcontext_handler *rh, uint offset, Item *val, LEX *lex, bool lex_resp, const LEX_CSTRING &expr_str) : sp_lex_instr(ip, ctx, lex, lex_resp), sp_rcontext_addr(rh, offset), m_value(val), m_expr_str(expr_str) {} virtual ~sp_instr_set() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; bool is_invalid() const override { return m_value == nullptr; } void invalidate() override { m_value= nullptr; } protected: LEX_CSTRING get_expr_query() const override { return m_expr_str; } void adjust_sql_command(LEX *lex) override { DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT); lex->sql_command= SQLCOM_SET_OPTION; } bool on_after_expr_parsing(THD *thd) override { DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1); m_value= thd->lex->current_select->item_list.head(); DBUG_ASSERT(m_value != nullptr); // Return error in release version if m_value == nullptr return m_value == nullptr; } sp_rcontext *get_rcontext(THD *thd) const; Item *m_value; private: LEX_CSTRING m_expr_str; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_set : public sp_lex_instr /* This class handles assignments of a ROW fields: DECLARE rec ROW (a INT,b INT); SET rec.a= 10; */ class sp_instr_set_row_field : public sp_instr_set { sp_instr_set_row_field(const sp_instr_set_row_field &); // Prevent use of this void operator=(sp_instr_set_row_field &); uint m_field_offset; public: sp_instr_set_row_field(uint ip, sp_pcontext *ctx, const Sp_rcontext_handler *rh, uint offset, uint field_offset, Item *val, LEX *lex, bool lex_resp, const LEX_CSTRING &value_query) : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query), m_field_offset(field_offset) {} virtual ~sp_instr_set_row_field() = default; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; }; // class sp_instr_set_field : public sp_instr_set /** This class handles assignment instructions like this: DECLARE CURSOR cur IS SELECT * FROM t1; rec cur%ROWTYPE; BEGIN rec.column1:= 10; -- This instruction END; The idea is that during sp_rcontext::create() we do not know the extact structure of "rec". It gets resolved at run time, during the corresponding sp_instr_cursor_copy_struct::exec_core(). So sp_instr_set_row_field_by_name searches for ROW fields by name, while sp_instr_set_row_field (see above) searches for ROW fields by index. */ class sp_instr_set_row_field_by_name : public sp_instr_set { // Prevent use of this sp_instr_set_row_field_by_name(const sp_instr_set_row_field &); void operator=(sp_instr_set_row_field_by_name &); const LEX_CSTRING m_field_name; public: sp_instr_set_row_field_by_name(uint ip, sp_pcontext *ctx, const Sp_rcontext_handler *rh, uint offset, const LEX_CSTRING &field_name, Item *val, LEX *lex, bool lex_resp, const LEX_CSTRING &value_query) : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query), m_field_name(field_name) {} virtual ~sp_instr_set_row_field_by_name() = default; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; }; // class sp_instr_set_field_by_name : public sp_instr_set /** Set NEW/OLD row field value instruction. Used in triggers. */ class sp_instr_set_trigger_field : public sp_lex_instr { sp_instr_set_trigger_field(const sp_instr_set_trigger_field &); void operator=(sp_instr_set_trigger_field &); public: sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, Item_trigger_field *trg_fld, Item *val, LEX *lex, const LEX_CSTRING &value_query) : sp_lex_instr(ip, ctx, lex, true), trigger_field(trg_fld), value(val), m_expr_str(value_query) { m_trigger_field_name= LEX_CSTRING{strdup_root(current_thd->mem_root, trg_fld->field_name.str), trg_fld->field_name.length}; } virtual ~sp_instr_set_trigger_field() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; bool is_invalid() const override { return value == nullptr; } void invalidate() override { value= nullptr; } protected: LEX_CSTRING get_expr_query() const override { return m_expr_str; } bool on_after_expr_parsing(THD *thd) override; private: Item_trigger_field *trigger_field; Item *value; /** SQL clause corresponding to the expression value. */ LEX_CSTRING m_expr_str; LEX_CSTRING m_trigger_field_name; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_trigger_field : public sp_lex_instr /** An abstract class for all instructions with destinations that needs to be updated by the optimizer. Even if not all subclasses will use both the normal destination and the continuation destination, we put them both here for simplicity. */ class sp_instr_opt_meta { public: uint m_dest; ///< Where we will go uint m_cont_dest; ///< Where continue handlers will go explicit sp_instr_opt_meta(uint dest) : m_dest(dest), m_cont_dest(0), m_optdest(0), m_cont_optdest(0) {} virtual ~sp_instr_opt_meta() = default; virtual void set_destination(uint old_dest, uint new_dest) = 0; protected: sp_instr *m_optdest; ///< Used during optimization sp_instr *m_cont_optdest; ///< Used during optimization }; // class sp_instr_opt_meta class sp_instr_jump : public sp_instr, public sp_instr_opt_meta { sp_instr_jump(const sp_instr_jump &); /**< Prevent use of these */ void operator=(sp_instr_jump &); public: sp_instr_jump(uint ip, sp_pcontext *ctx) : sp_instr(ip, ctx), sp_instr_opt_meta(0) {} sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest) : sp_instr(ip, ctx), sp_instr_opt_meta(dest) {} virtual ~sp_instr_jump() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override; uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override; void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override; void backpatch(uint dest, sp_pcontext *dst_ctx) override { /* Calling backpatch twice is a logic flaw in jump resolution. */ DBUG_ASSERT(m_dest == 0); m_dest= dest; } uint get_cont_dest() const override { return m_cont_dest; } /** Update the destination; used by the optimizer. */ void set_destination(uint old_dest, uint new_dest) override { if (m_dest == old_dest) m_dest= new_dest; } public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_jump : public sp_instr, public sp_instr_opt_meta class sp_instr_jump_if_not : public sp_lex_instr, public sp_instr_opt_meta { /**< Prevent use of these */ sp_instr_jump_if_not(const sp_instr_jump_if_not &); void operator=(sp_instr_jump_if_not &); public: sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex, const LEX_CSTRING &expr_query) : sp_lex_instr(ip, ctx, lex, true), sp_instr_opt_meta(0), m_expr(i), m_expr_str(expr_query) {} sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex, const LEX_CSTRING &expr_query) : sp_lex_instr(ip, ctx, lex, true), sp_instr_opt_meta(dest), m_expr(i), m_expr_str(expr_query) {} virtual ~sp_instr_jump_if_not() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override; /** Override sp_instr_jump's shortcut; we stop here */ uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override { return m_ip; } void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override; uint get_cont_dest() const override { return m_cont_dest; } void set_destination(uint old_dest, uint new_dest) override { if (m_dest == old_dest) m_dest= new_dest; if (m_cont_dest == old_dest) m_cont_dest= new_dest; } void backpatch(uint dest, sp_pcontext *dst_ctx) override { /* Calling backpatch twice is a logic flaw in jump resolution. */ DBUG_ASSERT(m_dest == 0); m_dest= dest; } bool is_invalid() const override { return m_expr == nullptr; } void invalidate() override { m_expr= nullptr; } protected: LEX_CSTRING get_expr_query() const override { return m_expr_str; } void adjust_sql_command(LEX *lex) override { assert(lex->sql_command == SQLCOM_SELECT); lex->sql_command= SQLCOM_END; } bool on_after_expr_parsing(THD *thd) override { DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1); m_expr= thd->lex->current_select->item_list.head(); DBUG_ASSERT(m_expr != nullptr); // Return error in release version if m_expr == nullptr return m_expr == nullptr; } private: Item *m_expr; ///< The condition LEX_CSTRING m_expr_str; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_jump_if_not class sp_instr_preturn : public sp_instr { sp_instr_preturn(const sp_instr_preturn &); /**< Prevent use of these */ void operator=(sp_instr_preturn &); public: sp_instr_preturn(uint ip, sp_pcontext *ctx) : sp_instr(ip, ctx) {} virtual ~sp_instr_preturn() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override { marked= 1; return UINT_MAX; } public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_preturn : public sp_instr class sp_instr_freturn : public sp_lex_instr { sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */ void operator=(sp_instr_freturn &); public: sp_instr_freturn(uint ip, sp_pcontext *ctx, Item *val, const Type_handler *handler, sp_expr_lex *lex) : sp_lex_instr(ip, ctx, lex, true), m_value(val), m_type_handler(handler), m_expr_str(lex->get_expr_str()) {} virtual ~sp_instr_freturn() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override { marked= 1; return UINT_MAX; } bool is_invalid() const override { return m_value == nullptr; } void invalidate() override { m_value= nullptr; } protected: LEX_CSTRING get_expr_query() const override { return m_expr_str; } bool on_after_expr_parsing(THD *thd) override { DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1); m_value= thd->lex->current_select->item_list.head(); DBUG_ASSERT(m_value != nullptr); // Return error in release version if m_value == nullptr return m_value == nullptr; } Item *m_value; const Type_handler *m_type_handler; private: /** SQL-query corresponding to the RETURN-expression. */ LEX_CSTRING m_expr_str; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_freturn : public sp_lex_instr class sp_instr_hpush_jump : public sp_instr_jump { sp_instr_hpush_jump(const sp_instr_hpush_jump &); /**< Prevent use of these */ void operator=(sp_instr_hpush_jump &); public: sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, sp_handler *handler) : sp_instr_jump(ip, ctx), m_handler(handler), m_opt_hpop(0), m_frame(ctx->current_var_count()) { DBUG_ASSERT(m_handler->condition_values.elements == 0); } ~sp_instr_hpush_jump() override { m_handler->condition_values.empty(); m_handler= nullptr; } int execute(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override; /** Override sp_instr_jump's shortcut; we stop here. */ uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override { return m_ip; } void backpatch(uint dest, sp_pcontext *dst_ctx) override { DBUG_ASSERT(!m_dest || !m_opt_hpop); if (!m_dest) m_dest= dest; else m_opt_hpop= dest; } void add_condition(sp_condition_value *condition_value) { m_handler->condition_values.push_back(condition_value); } sp_handler *get_handler() { return m_handler; } private: /// Handler. sp_handler *m_handler; /// hpop marking end of handler scope. uint m_opt_hpop; // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in // debug version only). It's used in print(). uint m_frame; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_hpush_jump : public sp_instr_jump class sp_instr_hpop : public sp_instr { sp_instr_hpop(const sp_instr_hpop &); /**< Prevent use of these */ void operator=(sp_instr_hpop &); public: sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count) : sp_instr(ip, ctx), m_count(count) {} virtual ~sp_instr_hpop() = default; void update_count(uint count) { m_count= count; } int execute(THD *thd, uint *nextp) override; void print(String *str) override; private: uint m_count; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_hpop : public sp_instr class sp_instr_hreturn : public sp_instr_jump { sp_instr_hreturn(const sp_instr_hreturn &); /**< Prevent use of these */ void operator=(sp_instr_hreturn &); public: sp_instr_hreturn(uint ip, sp_pcontext *ctx) : sp_instr_jump(ip, ctx), m_frame(ctx->current_var_count()) {} virtual ~sp_instr_hreturn() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; /* This instruction will not be short cut optimized. */ uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override { return m_ip; } uint opt_mark(sp_head *sp, List<sp_instr> *leads) override; private: uint m_frame; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_hreturn : public sp_instr_jump /** Get a query text associated with the cursor. */ static inline LEX_CSTRING get_cursor_query(const LEX_CSTRING &cursor_stmt) { /* Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't move a pointer on cpp_buf after the token FOR/IS so skip it explicitly in order to get correct value of cursor's query string. */ if (strncasecmp(cursor_stmt.str, "FOR", 3) == 0 && my_isspace(current_thd->variables.character_set_client, cursor_stmt.str[3])) return LEX_CSTRING{cursor_stmt.str + 4, cursor_stmt.length - 4}; if (strncasecmp(cursor_stmt.str, "IS", 2) == 0 && my_isspace(current_thd->variables.character_set_client, cursor_stmt.str[2])) return LEX_CSTRING{cursor_stmt.str + 3, cursor_stmt.length - 3}; return cursor_stmt; } /** This is DECLARE CURSOR */ class sp_instr_cpush : public sp_lex_instr, public sp_cursor { sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */ void operator=(sp_instr_cpush &); public: sp_instr_cpush(uint ip, sp_pcontext *ctx, sp_lex_cursor *lex, uint offset) : sp_lex_instr(ip, ctx, lex, true), m_cursor(offset), m_metadata_changed(false), m_cursor_stmt(lex->get_expr_str()) {} virtual ~sp_instr_cpush() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; /** This call is used to cleanup the instruction when a sensitive cursor is closed. For now stored procedures always use materialized cursors and the call is not used. */ bool cleanup_stmt(bool /*restore_set_statement_vars*/) override { return false; } bool is_invalid() const override { return m_metadata_changed; } void invalidate() override { m_metadata_changed= true; } sp_lex_keeper *get_lex_keeper() override { return &m_lex_keeper; } void get_query(String *sql_query) const override { sql_query->append(get_expr_query()); } sp_instr_cpush *get_push_instr() override { return this; } protected: LEX_CSTRING get_expr_query() const override { return get_cursor_query(m_cursor_stmt); } bool on_after_expr_parsing(THD *) override { m_metadata_changed= false; return false; } private: uint m_cursor; /**< Frame offset (for debugging) */ /** Flag if a statement's metadata has been changed in result of running DDL on depending database objects used in the statement. */ bool m_metadata_changed; LEX_CSTRING m_cursor_stmt; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_cpush : public sp_instr class sp_instr_cpop : public sp_instr { sp_instr_cpop(const sp_instr_cpop &); /**< Prevent use of these */ void operator=(sp_instr_cpop &); public: sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count) : sp_instr(ip, ctx), m_count(count) {} virtual ~sp_instr_cpop() = default; void update_count(uint count) { m_count= count; } int execute(THD *thd, uint *nextp) override; void print(String *str) override; private: uint m_count; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_cpop : public sp_instr class sp_instr_copen : public sp_instr { sp_instr_copen(const sp_instr_copen &); /**< Prevent use of these */ void operator=(sp_instr_copen &); public: sp_instr_copen(uint ip, sp_pcontext *ctx, uint c) : sp_instr(ip, ctx), m_cursor(c) {} virtual ~sp_instr_copen() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; private: uint m_cursor; ///< Stack index public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_copen : public sp_instr_stmt /** Initialize the structure of a cursor%ROWTYPE variable from the LEX containing the cursor SELECT statement. */ class sp_instr_cursor_copy_struct: public sp_lex_instr { /**< Prevent use of these */ sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &); void operator=(sp_instr_cursor_copy_struct &); uint m_cursor; uint m_var; /** Flag to tell whether metadata has been changed and the LEX object should be reinitialized. */ bool m_valid; LEX_CSTRING m_cursor_stmt; public: sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs, sp_lex_cursor *lex, uint voffs) : sp_lex_instr(ip, ctx, lex, false), m_cursor(coffs), m_var(voffs), m_valid(true), m_cursor_stmt(lex->get_expr_str()) {} virtual ~sp_instr_cursor_copy_struct() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; bool is_invalid() const override { return !m_valid; } void invalidate() override { m_valid= false; } void get_query(String *sql_query) const override { sql_query->append(get_expr_query()); } protected: LEX_CSTRING get_expr_query() const override { return get_cursor_query(m_cursor_stmt); } bool on_after_expr_parsing(THD *) override { m_valid= true; return false; } public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; class sp_instr_cclose : public sp_instr { sp_instr_cclose(const sp_instr_cclose &); /**< Prevent use of these */ void operator=(sp_instr_cclose &); public: sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c) : sp_instr(ip, ctx), m_cursor(c) {} virtual ~sp_instr_cclose() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; private: uint m_cursor; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_cclose : public sp_instr class sp_instr_cfetch : public sp_instr { sp_instr_cfetch(const sp_instr_cfetch &); /**< Prevent use of these */ void operator=(sp_instr_cfetch &); public: sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c, bool error_on_no_data) : sp_instr(ip, ctx), m_cursor(c), m_error_on_no_data(error_on_no_data) { m_fetch_target_list.empty(); } virtual ~sp_instr_cfetch() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; bool add_to_fetch_target_list(sp_fetch_target *target) { return m_fetch_target_list.push_back(target); } void set_fetch_target_list(List<sp_fetch_target> *list) { m_fetch_target_list= *list; } private: uint m_cursor; List<sp_fetch_target> m_fetch_target_list; bool m_error_on_no_data; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_cfetch : public sp_instr /* This class is created for the special fetch instruction FETCH GROUP NEXT ROW, used in the user-defined aggregate functions */ class sp_instr_agg_cfetch : public sp_instr { sp_instr_agg_cfetch(const sp_instr_cfetch &); /**< Prevent use of these */ void operator=(sp_instr_cfetch &); public: sp_instr_agg_cfetch(uint ip, sp_pcontext *ctx) : sp_instr(ip, ctx) {} virtual ~sp_instr_agg_cfetch() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_agg_cfetch : public sp_instr class sp_instr_error : public sp_instr { sp_instr_error(const sp_instr_error &); /**< Prevent use of these */ void operator=(sp_instr_error &); public: sp_instr_error(uint ip, sp_pcontext *ctx, int errcode) : sp_instr(ip, ctx), m_errcode(errcode) {} virtual ~sp_instr_error() = default; int execute(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override { marked= 1; return UINT_MAX; } private: int m_errcode; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_error : public sp_instr class sp_instr_set_case_expr : public sp_lex_instr, public sp_instr_opt_meta { public: sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id, Item *case_expr, LEX *lex, const LEX_CSTRING &case_expr_query) : sp_lex_instr(ip, ctx, lex, true), sp_instr_opt_meta(0), m_case_expr_id(case_expr_id), m_case_expr(case_expr), m_expr_str(case_expr_query) {} virtual ~sp_instr_set_case_expr() = default; int execute(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override; void print(String *str) override; uint opt_mark(sp_head *sp, List<sp_instr> *leads) override; void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override; uint get_cont_dest() const override { return m_cont_dest; } void set_destination(uint old_dest, uint new_dest) override { if (m_cont_dest == old_dest) m_cont_dest= new_dest; } bool is_invalid() const override { return m_case_expr == nullptr; } void invalidate() override { m_case_expr= nullptr; } protected: LEX_CSTRING get_expr_query() const override { return m_expr_str; } void adjust_sql_command(LEX *lex) override { assert(lex->sql_command == SQLCOM_SELECT); lex->sql_command= SQLCOM_END; } bool on_after_expr_parsing(THD *thd) override { DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1); m_case_expr= thd->lex->current_select->item_list.head(); DBUG_ASSERT(m_case_expr != nullptr); // Return error in release version if m_case_expr == nullptr return m_case_expr == nullptr; } private: uint m_case_expr_id; Item *m_case_expr; LEX_CSTRING m_expr_str; public: PSI_statement_info* get_psi_info() override { return & psi_info; } static PSI_statement_info psi_info; }; // class sp_instr_set_case_expr : public sp_lex_instr, #endif opt_range.h 0000644 00000202224 15156036150 0006677 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* classes to use when handling where clause */ #ifndef _opt_range_h #define _opt_range_h #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "records.h" /* READ_RECORD */ #include "queues.h" /* QUEUE */ #include "filesort.h" /* SORT_INFO */ /* It is necessary to include set_var.h instead of item.h because there are dependencies on include order for set_var.h and item.h. This will be resolved later. */ #include "sql_class.h" // set_var.h: THD #include "set_var.h" /* Item */ class JOIN; class Item_sum; /* When processing an OR clause with more than MAX_OR_ELEMENTS_FOR_INDEX_MERGE disjuncts (i.e. OR-parts), do not construct index_merge plans from it. Some users have OR clauses with extremely large number of disjuncts, like: (key1=1 AND key2=10) OR (key1=2 AND key2=20) OR (key1=3 AND key2=30) OR ... When processing this, the optimizer would try to build a lot of potential index_merge plans. Hypothetically this could be useful as the cheapest plan could be to pick a specific index for each disjunct and build: index_merge(key1 IN (1,3,8,15...), key2 IN (20, 40, 50 ...)) In practice this causes combinatorial amount of time to be spent in the range analyzer, and most variants will be discarded when the range optimizer tries to avoid this combinatorial explosion (which may or may not work depending on the form of the WHERE clause). In practice, very long ORs are served well enough by just considering range accesses on individual indexes. */ const int MAX_OR_ELEMENTS_FOR_INDEX_MERGE=100; struct KEY_PART { uint16 key,part; /* See KEY_PART_INFO for meaning of the next two: */ uint16 store_length, length; uint8 null_bit; /* Keypart flags (0 when this structure is used by partition pruning code for fake partitioning index description) */ uint8 flag; Field *field; Field::imagetype image_type; }; /** A helper function to invert min flags to max flags for DESC key parts. It changes NEAR_MIN, NO_MIN_RANGE to NEAR_MAX, NO_MAX_RANGE appropriately */ inline uint invert_min_flag(uint min_flag) { uint max_flag_out = min_flag & ~(NEAR_MIN | NO_MIN_RANGE); if (min_flag & NEAR_MIN) max_flag_out |= NEAR_MAX; if (min_flag & NO_MIN_RANGE) max_flag_out |= NO_MAX_RANGE; return max_flag_out; } /** A helper function to invert max flags to min flags for DESC key parts. It changes NEAR_MAX, NO_MAX_RANGE to NEAR_MIN, NO_MIN_RANGE appropriately */ inline uint invert_max_flag(uint max_flag) { uint min_flag_out = max_flag & ~(NEAR_MAX | NO_MAX_RANGE); if (max_flag & NEAR_MAX) min_flag_out |= NEAR_MIN; if (max_flag & NO_MAX_RANGE) min_flag_out |= NO_MIN_RANGE; return min_flag_out; } class RANGE_OPT_PARAM; /* A construction block of the SEL_ARG-graph. The following description only covers graphs of SEL_ARG objects with sel_arg->type==KEY_RANGE: One SEL_ARG object represents an "elementary interval" in form min_value <=? table.keypartX <=? max_value The interval is a non-empty interval of any kind: with[out] minimum/maximum bound, [half]open/closed, single-point interval, etc. 1. SEL_ARG GRAPH STRUCTURE SEL_ARG objects are linked together in a graph. The meaning of the graph is better demostrated by an example: tree->keys[i] | | $ $ | part=1 $ part=2 $ part=3 | $ $ | +-------+ $ +-------+ $ +--------+ | | kp1<1 |--$-->| kp2=5 |--$-->| kp3=10 | | +-------+ $ +-------+ $ +--------+ | | $ $ | | | $ $ +--------+ | | $ $ | kp3=12 | | | $ $ +--------+ | +-------+ $ $ \->| kp1=2 |--$--------------$-+ +-------+ $ $ | +--------+ | $ $ ==>| kp3=11 | +-------+ $ $ | +--------+ | kp1=3 |--$--------------$-+ | +-------+ $ $ +--------+ | $ $ | kp3=14 | ... $ $ +--------+ The entire graph is partitioned into "interval lists". An interval list is a sequence of ordered disjoint intervals over the same key part. SEL_ARG are linked via "next" and "prev" pointers. Additionally, all intervals in the list form an RB-tree, linked via left/right/parent pointers. The RB-tree root SEL_ARG object will be further called "root of the interval list". In the example pic, there are 4 interval lists: "kp<1 OR kp1=2 OR kp1=3", "kp2=5", "kp3=10 OR kp3=12", "kp3=11 OR kp3=13". The vertical lines represent SEL_ARG::next/prev pointers. In an interval list, each member X may have SEL_ARG::next_key_part pointer pointing to the root of another interval list Y. The pointed interval list must cover a key part with greater number (i.e. Y->part > X->part). In the example pic, the next_key_part pointers are represented by horisontal lines. 2. SEL_ARG GRAPH SEMANTICS It represents a condition in a special form (we don't have a name for it ATM) The SEL_ARG::next/prev is "OR", and next_key_part is "AND". For example, the picture represents the condition in form: (kp1 < 1 AND kp2=5 AND (kp3=10 OR kp3=12)) OR (kp1=2 AND (kp3=11 OR kp3=14)) OR (kp1=3 AND (kp3=11 OR kp3=14)) 3. SEL_ARG GRAPH USE Use get_mm_tree() to construct SEL_ARG graph from WHERE condition. Then walk the SEL_ARG graph and get a list of dijsoint ordered key intervals (i.e. intervals in form (constA1, .., const1_K) < (keypart1,.., keypartK) < (constB1, .., constB_K) Those intervals can be used to access the index. The uses are in: - check_quick_select() - Walk the SEL_ARG graph and find an estimate of how many table records are contained within all intervals. - get_quick_select() - Walk the SEL_ARG, materialize the key intervals, and create QUICK_RANGE_SELECT object that will read records within these intervals. 4. SPACE COMPLEXITY NOTES SEL_ARG graph is a representation of an ordered disjoint sequence of intervals over the ordered set of index tuple values. For multi-part keys, one can construct a WHERE expression such that its list of intervals will be of combinatorial size. Here is an example: (keypart1 IN (1,2, ..., n1)) AND (keypart2 IN (1,2, ..., n2)) AND (keypart3 IN (1,2, ..., n3)) For this WHERE clause the list of intervals will have n1*n2*n3 intervals of form (keypart1, keypart2, keypart3) = (k1, k2, k3), where 1 <= k{i} <= n{i} SEL_ARG graph structure aims to reduce the amount of required space by "sharing" the elementary intervals when possible (the pic at the beginning of this comment has examples of such sharing). The sharing may prevent combinatorial blowup: There are WHERE clauses that have combinatorial-size interval lists but will be represented by a compact SEL_ARG graph. Example: (keypartN IN (1,2, ..., n1)) AND ... (keypart2 IN (1,2, ..., n2)) AND (keypart1 IN (1,2, ..., n3)) but not in all cases: - There are WHERE clauses that do have a compact SEL_ARG-graph representation but get_mm_tree() and its callees will construct a graph of combinatorial size. Example: (keypart1 IN (1,2, ..., n1)) AND (keypart2 IN (1,2, ..., n2)) AND ... (keypartN IN (1,2, ..., n3)) - There are WHERE clauses for which the minimal possible SEL_ARG graph representation will have combinatorial size. Example: By induction: Let's take any interval on some keypart in the middle: kp15=c0 Then let's AND it with this interval 'structure' from preceding and following keyparts: (kp14=c1 AND kp16=c3) OR keypart14=c2) (*) We will obtain this SEL_ARG graph: kp14 $ kp15 $ kp16 $ $ +---------+ $ +---------+ $ +---------+ | kp14=c1 |--$-->| kp15=c0 |--$-->| kp16=c3 | +---------+ $ +---------+ $ +---------+ | $ $ +---------+ $ +---------+ $ | kp14=c2 |--$-->| kp15=c0 | $ +---------+ $ +---------+ $ $ $ Note that we had to duplicate "kp15=c0" and there was no way to avoid that. The induction step: AND the obtained expression with another "wrapping" expression like (*). When the process ends because of the limit on max. number of keyparts we'll have: WHERE clause length is O(3*#max_keyparts) SEL_ARG graph size is O(2^(#max_keyparts/2)) (it is also possible to construct a case where instead of 2 in 2^n we have a bigger constant, e.g. 4, and get a graph with 4^(31/2)= 2^31 nodes) We avoid consuming too much memory by setting a limit on the number of SEL_ARG object we can construct during one range analysis invocation. 5. SEL_ARG GRAPH WEIGHT A SEL_ARG graph has a property we call weight, and we define it as follows: <definition> If the SEL_ARG graph does not have any node with multiple incoming next_key_part edges, then its weight is the number of SEL_ARG objects used. If there is a node with multiple incoming next_key_part edges, clone that node, (and the nodes connected to it via prev/next links) and redirect one of the incoming next_key_part edges to the clone. Continue with cloning until we get a graph that has no nodes with multiple incoming next_key_part edges. Then, the number of SEL_ARG objects in the graph is the weight of the original graph. </definition> Example: kp1 $ kp2 $ kp3 $ $ | +-------+ $ $ \->| kp1=2 |--$--------------$-+ +-------+ $ $ | +--------+ | $ $ ==>| kp3=11 | +-------+ $ $ | +--------+ | kp1>3 |--$--------------$-+ | +-------+ $ $ +--------+ $ $ | kp3=14 | $ $ +--------+ $ $ | $ $ +--------+ $ $ | kp3=14 | $ $ +--------+ Here, the weight is 2 + 2*3=8. The rationale behind using this definition of weight is: - it has the same order-of-magnitude as the number of ranges that the SEL_ARG graph is describing, - it is a lot easier to compute than computing the number of ranges, - it can be updated incrementally when performing AND/OR operations on parts of the graph. 6. For handling DESC keyparts, See HowRangeOptimizerHandlesDescKeyparts */ class SEL_ARG :public Sql_alloc { static int sel_cmp(Field *field, uchar *a, uchar *b, uint8 a_flag, uint8 b_flag); bool min_max_are_equal() const; public: uint8 min_flag,max_flag,maybe_flag; uint8 part; // Which key part uint8 maybe_null; /* The ordinal number the least significant component encountered in the ranges of the SEL_ARG tree (the first component has number 1) Note: this number is currently not precise, it is an upper bound. @seealso SEL_ARG::get_max_key_part() */ uint16 max_part_no; /* Number of children of this element in the RB-tree, plus 1 for this element itself. */ uint32 elements; /* Valid only for elements which are RB-tree roots: Number of times this RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by SEL_TREE::keys[i] or by a temporary SEL_ARG* variable) */ ulong use_count; Field *field; uchar *min_value,*max_value; // Pointer to range /* eq_tree() requires that left == right == 0 if the type is MAYBE_KEY. */ SEL_ARG *left,*right; /* R-B tree children */ SEL_ARG *next,*prev; /* Links for bi-directional interval list */ SEL_ARG *parent; /* R-B tree parent */ SEL_ARG *next_key_part; enum leaf_color { BLACK,RED } color; enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type; /* For R-B root nodes only: the graph weight, as defined above in the SEL_ARG GRAPH WEIGHT section. */ uint weight; enum { MAX_WEIGHT = 32000 }; #ifndef DBUG_OFF uint verify_weight(); #endif /* See RANGE_OPT_PARAM::alloced_sel_args */ enum { DEFAULT_MAX_SEL_ARGS = 16000 }; SEL_ARG() = default; SEL_ARG(SEL_ARG &); SEL_ARG(Field *, const uchar *, const uchar *); SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); /* This is used to construct degenerate SEL_ARGS like ALWAYS, IMPOSSIBLE, etc */ SEL_ARG(enum Type type_arg) :min_flag(0), max_part_no(0) /* first key part means 1. 0 mean 'no parts'*/, elements(1),use_count(1),left(0),right(0), next_key_part(0), color(BLACK), type(type_arg), weight(1) {} /** returns true if a range predicate is equal. Use all_same() to check for equality of all the predicates on this keypart. */ inline bool is_same(const SEL_ARG *arg) const { if (type != arg->type || part != arg->part) return false; if (type != KEY_RANGE) return true; return cmp_min_to_min(arg) == 0 && cmp_max_to_max(arg) == 0; } uint get_max_key_part() const; /** returns true if all the predicates in the keypart tree are equal */ bool all_same(const SEL_ARG *arg) const { if (type != arg->type || part != arg->part) return false; if (type != KEY_RANGE) return true; if (arg == this) return true; const SEL_ARG *cmp_arg= arg->first(); const SEL_ARG *cur_arg= first(); for (; cur_arg && cmp_arg && cur_arg->is_same(cmp_arg); cur_arg= cur_arg->next, cmp_arg= cmp_arg->next) ; if (cur_arg || cmp_arg) return false; return true; } int number_of_eq_groups(uint group_key_parts) const; inline void merge_flags(SEL_ARG *arg) { maybe_flag|=arg->maybe_flag; } inline void maybe_smaller() { maybe_flag=1; } /* Return true iff it's a single-point null interval */ inline bool is_null_interval() { return maybe_null && max_value[0] == 1; } inline int cmp_min_to_min(const SEL_ARG* arg) const { return sel_cmp(field,min_value, arg->min_value, min_flag, arg->min_flag); } inline int cmp_min_to_max(const SEL_ARG* arg) const { return sel_cmp(field,min_value, arg->max_value, min_flag, arg->max_flag); } inline int cmp_max_to_max(const SEL_ARG* arg) const { return sel_cmp(field,max_value, arg->max_value, max_flag, arg->max_flag); } inline int cmp_max_to_min(const SEL_ARG* arg) const { return sel_cmp(field,max_value, arg->min_value, max_flag, arg->min_flag); } SEL_ARG *clone_and(THD *thd, SEL_ARG* arg) { // Get overlapping range uchar *new_min,*new_max; uint8 flag_min,flag_max; if (cmp_min_to_min(arg) >= 0) { new_min=min_value; flag_min=min_flag; } else { new_min=arg->min_value; flag_min=arg->min_flag; /* purecov: deadcode */ } if (cmp_max_to_max(arg) <= 0) { new_max=max_value; flag_max=max_flag; } else { new_max=arg->max_value; flag_max=arg->max_flag; } return new (thd->mem_root) SEL_ARG(field, part, new_min, new_max, flag_min, flag_max, MY_TEST(maybe_flag && arg->maybe_flag)); } SEL_ARG *clone_first(SEL_ARG *arg) { // min <= X < arg->min return new SEL_ARG(field, part, min_value, arg->min_value, min_flag, arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX, maybe_flag | arg->maybe_flag); } SEL_ARG *clone_last(SEL_ARG *arg) { // min <= X <= key_max return new SEL_ARG(field, part, min_value, arg->max_value, min_flag, arg->max_flag, maybe_flag | arg->maybe_flag); } SEL_ARG *clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next); bool copy_min(SEL_ARG* arg) { // Get overlapping range if (cmp_min_to_min(arg) > 0) { min_value=arg->min_value; min_flag=arg->min_flag; if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) == (NO_MAX_RANGE | NO_MIN_RANGE)) return 1; // Full range } maybe_flag|=arg->maybe_flag; return 0; } bool copy_max(SEL_ARG* arg) { // Get overlapping range if (cmp_max_to_max(arg) <= 0) { max_value=arg->max_value; max_flag=arg->max_flag; if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) == (NO_MAX_RANGE | NO_MIN_RANGE)) return 1; // Full range } maybe_flag|=arg->maybe_flag; return 0; } void copy_min_to_min(SEL_ARG *arg) { min_value=arg->min_value; min_flag=arg->min_flag; } void copy_min_to_max(SEL_ARG *arg) { max_value=arg->min_value; max_flag=arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX; } void copy_max_to_min(SEL_ARG *arg) { min_value=arg->max_value; min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN; } /* returns a number of keypart values (0 or 1) appended to the key buffer */ int store_min(uint length, uchar **min_key,uint min_key_flag) { /* "(kp1 > c1) AND (kp2 OP c2) AND ..." -> (kp1 > c1) */ if ((min_flag & GEOM_FLAG) || (!(min_flag & NO_MIN_RANGE) && !(min_key_flag & (NO_MIN_RANGE | NEAR_MIN)))) { if (maybe_null && *min_value) { **min_key=1; bzero(*min_key+1,length-1); } else memcpy(*min_key,min_value,length); (*min_key)+= length; return 1; } return 0; } /* returns a number of keypart values (0 or 1) appended to the key buffer */ int store_max(uint length, uchar **max_key, uint max_key_flag) { if (!(max_flag & NO_MAX_RANGE) && !(max_key_flag & (NO_MAX_RANGE | NEAR_MAX))) { if (maybe_null && *max_value) { **max_key=1; bzero(*max_key+1,length-1); } else memcpy(*max_key,max_value,length); (*max_key)+= length; return 1; } return 0; } /* Save minimum and maximum, taking index order into account */ void store_min_max(KEY_PART *kp, uint length, uchar **min_key, uint min_flag, uchar **max_key, uint max_flag, int *min_part, int *max_part) { if (kp[part].flag & HA_REVERSE_SORT) { *max_part += store_min(length, max_key, min_flag); *min_part += store_max(length, min_key, max_flag); } else { *min_part += store_min(length, min_key, min_flag); *max_part += store_max(length, max_key, max_flag); } } /* Get the flag for range's starting endpoint, taking index order into account. */ uint get_min_flag(KEY_PART *kp) { return (kp[part].flag & HA_REVERSE_SORT)? invert_max_flag(max_flag) : min_flag; } /* Get the flag for range's starting endpoint, taking index order into account. */ uint get_max_flag(KEY_PART *kp) { return (kp[part].flag & HA_REVERSE_SORT)? invert_min_flag(min_flag) : max_flag ; } /* Get the previous interval, taking index order into account */ inline SEL_ARG* index_order_prev(KEY_PART *kp) { return (kp[part].flag & HA_REVERSE_SORT)? next : prev; } /* Get the next interval, taking index order into account */ inline SEL_ARG* index_order_next(KEY_PART *kp) { return (kp[part].flag & HA_REVERSE_SORT)? prev : next; } /* Produce a single multi-part interval, taking key part ordering into account. */ void store_next_min_max_keys(KEY_PART *key, uchar **cur_min_key, uint *cur_min_flag, uchar **cur_max_key, uint *cur_max_flag, int *min_part, int *max_part); /* Returns a number of keypart values appended to the key buffer for min key and max key. This function is used by both Range Analysis and Partition pruning. For partition pruning we have to ensure that we don't store also subpartition fields. Thus we have to stop at the last partition part and not step into the subpartition fields. For Range Analysis we set last_part to MAX_KEY which we should never reach. */ int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag, uint last_part, bool start_key) { SEL_ARG *key_tree= first(); uint res= key_tree->store_min(key[key_tree->part].store_length, range_key, *range_key_flag); // add flags only if a key_part is written to the buffer if (!res) return 0; *range_key_flag|= key_tree->min_flag; SEL_ARG *nkp= key_tree->next_key_part; if (nkp && nkp->type == SEL_ARG::KEY_RANGE && key_tree->part != last_part && nkp->part == key_tree->part+1 && !(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN))) { const bool asc = !(key[key_tree->part].flag & HA_REVERSE_SORT); if (start_key == asc) { res+= nkp->store_min_key(key, range_key, range_key_flag, last_part, start_key); } else { uint tmp_flag = invert_min_flag(*range_key_flag); res += nkp->store_max_key(key, range_key, &tmp_flag, last_part, start_key); *range_key_flag = invert_max_flag(tmp_flag); } } return res; } /* returns a number of keypart values appended to the key buffer */ int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag, uint last_part, bool start_key) { SEL_ARG *key_tree= last(); uint res=key_tree->store_max(key[key_tree->part].store_length, range_key, *range_key_flag); if (!res) return 0; *range_key_flag|= key_tree->max_flag; SEL_ARG *nkp= key_tree->next_key_part; if (nkp && nkp->type == SEL_ARG::KEY_RANGE && key_tree->part != last_part && nkp->part == key_tree->part+1 && !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX))) { const bool asc = !(key[key_tree->part].flag & HA_REVERSE_SORT); if ((!start_key && asc) || (start_key && !asc)) { res += nkp->store_max_key(key, range_key, range_key_flag, last_part, start_key); } else { uint tmp_flag = invert_max_flag(*range_key_flag); res += nkp->store_min_key(key, range_key, &tmp_flag, last_part, start_key); *range_key_flag = invert_min_flag(tmp_flag); } } return res; } SEL_ARG *insert(SEL_ARG *key); SEL_ARG *tree_delete(SEL_ARG *key); SEL_ARG *find_range(SEL_ARG *key); SEL_ARG *rb_insert(SEL_ARG *leaf); friend SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key, SEL_ARG *par); #ifdef EXTRA_DEBUG friend int test_rb_tree(SEL_ARG *element,SEL_ARG *parent); void test_use_count(SEL_ARG *root); #endif SEL_ARG *first(); const SEL_ARG *first() const; SEL_ARG *last(); void make_root(); inline bool simple_key() { return !next_key_part && elements == 1; } void increment_use_count(long count) { if (next_key_part) { next_key_part->use_count+=count; count*= (next_key_part->use_count-count); for (SEL_ARG *pos=next_key_part->first(); pos ; pos=pos->next) if (pos->next_key_part) pos->increment_use_count(count); } } void incr_refs() { increment_use_count(1); use_count++; } void incr_refs_all() { for (SEL_ARG *pos=first(); pos ; pos=pos->next) { pos->increment_use_count(1); } use_count++; } void free_tree() { for (SEL_ARG *pos=first(); pos ; pos=pos->next) if (pos->next_key_part) { pos->next_key_part->use_count--; pos->next_key_part->free_tree(); } } inline SEL_ARG **parent_ptr() { return parent->left == this ? &parent->left : &parent->right; } /* Check if this SEL_ARG object represents a single-point interval SYNOPSIS is_singlepoint() DESCRIPTION Check if this SEL_ARG object (not tree) represents a single-point interval, i.e. if it represents a "keypart = const" or "keypart IS NULL". RETURN TRUE This SEL_ARG object represents a singlepoint interval FALSE Otherwise */ bool is_singlepoint() const { /* Check for NEAR_MIN ("strictly less") and NO_MIN_RANGE (-inf < field) flags, and the same for right edge. */ if (min_flag || max_flag) return FALSE; uchar *min_val= min_value; uchar *max_val= max_value; if (maybe_null) { /* First byte is a NULL value indicator */ if (*min_val != *max_val) return FALSE; if (*min_val) return TRUE; /* This "x IS NULL" */ min_val++; max_val++; } return !field->key_cmp(min_val, max_val); } SEL_ARG *clone_tree(RANGE_OPT_PARAM *param); }; /* HowRangeOptimizerHandlesDescKeyparts ==================================== Starting with MySQL-8.0 and MariaDB 10.8, index key parts may be descending, for example: INDEX idx1(col1, col2 DESC, col3, col4 DESC) Range Optimizer handles this as follows: Other than that, the SEL_ARG graph is built without any regard to DESC keyparts. For example, for an index INDEX idx2(kp1 DESC, kp2) and range kp1 BETWEEN 10 and 20 (RANGE-1) the SEL_ARG will have min_value=10, max_value=20 The ordering of key parts is taken into account when SEL_ARG graph is linearized to ranges, in sel_arg_range_seq_next() and get_quick_keys(). The storage engine expects the first bound to be the first in the index and the last bound to be the last, that is, for (RANGE-1) we will flip min and max and generate these key_range structures: start.key='20' , end.key='10' See SEL_ARG::store_min_max(). The flag values are flipped as well, see SEL_ARG::get_min_flag(), get_max_flag(). == Handling multiple key parts == For multi-part keys, the order of key parts has an effect on which ranges are generated. Consider kp1 >= 10 AND kp2 >'foo' for INDEX(kp1 ASC, kp2 ASC) the range will be (kp1, kp2) > (10, 'foo') while for INDEX(kp1 ASC, kp2 DESC) it will be just kp1 >= 10 Another example: (kp1 BETWEEN 10 AND 20) AND (kp2 BETWEEN 'foo' AND 'quux') with INDEX (kp1 ASC, kp2 ASC) will generate (10, 'foo') <= (kp1, kp2) < (20, 'quux') while with index INDEX (kp1 ASC, kp2 DESC) it will generate (10, 'quux') <= (kp1, kp2) < (20, 'foo') This is again achieved by sel_arg_range_seq_next() and get_quick_keys() flipping SEL_ARG's min,max, their flags and next/prev as needed. */ extern MYSQL_PLUGIN_IMPORT SEL_ARG null_element; class SEL_ARG_IMPOSSIBLE: public SEL_ARG { public: SEL_ARG_IMPOSSIBLE(Field *field) :SEL_ARG(field, 0, 0) { type= SEL_ARG::IMPOSSIBLE; } }; class RANGE_OPT_PARAM { public: THD *thd; /* Current thread handle */ TABLE *table; /* Table being analyzed */ table_map prev_tables; table_map read_tables; table_map current_table; /* Bit of the table being analyzed */ /* Array of parts of all keys for which range analysis is performed */ KEY_PART *key_parts; KEY_PART *key_parts_end; MEM_ROOT *mem_root; /* Memory that will be freed when range analysis completes */ MEM_ROOT *old_root; /* Memory that will last until the query end */ /* Number of indexes used in range analysis (In SEL_TREE::keys only first #keys elements are not empty) */ uint keys; /* If true, the index descriptions describe real indexes (and it is ok to call field->optimize_range(real_keynr[...], ...). Otherwise index description describes fake indexes. */ bool using_real_indexes; /* Aggressively remove "scans" that do not have conditions on first keyparts. Such scans are usable when doing partition pruning but not regular range optimization. */ bool remove_jump_scans; /* TRUE <=> Range analyzer should remove parts of condition that are found to be always FALSE. */ bool remove_false_where_parts; /* If TRUE, do not construct index_merge plans */ bool disable_index_merge_plans; /* Which functions should give SQL notes for unusable keys. */ Item_func::Bitmap note_unusable_keys; /* used_key_no -> table_key_no translation table. Only makes sense if using_real_indexes==TRUE */ uint real_keynr[MAX_KEY]; /* Used to store 'current key tuples', in both range analysis and partitioning (list) analysis */ uchar *min_key; uchar *max_key; /* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */ uint alloced_sel_args; bool force_default_mrr; KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */ bool statement_should_be_aborted() const { return thd->killed || thd->is_error() || alloced_sel_args > thd->variables.optimizer_max_sel_args; } }; class Explain_quick_select; /* A "MIN_TUPLE < tbl.key_tuple < MAX_TUPLE" interval. One of endpoints may be absent. 'flags' member has flags which tell whether the endpoints are '<' or '<='. */ class QUICK_RANGE :public Sql_alloc { public: uchar *min_key,*max_key; uint16 min_length,max_length,flag; key_part_map min_keypart_map, // bitmap of used keyparts in min_key max_keypart_map; // bitmap of used keyparts in max_key #ifdef HAVE_valgrind uint16 dummy; /* Avoid warnings on 'flag' */ #endif QUICK_RANGE(); /* Full range */ QUICK_RANGE(THD *thd, const uchar *min_key_arg, uint min_length_arg, key_part_map min_keypart_map_arg, const uchar *max_key_arg, uint max_length_arg, key_part_map max_keypart_map_arg, uint flag_arg) : min_key((uchar*) thd->memdup(min_key_arg, min_length_arg + 1)), max_key((uchar*) thd->memdup(max_key_arg, max_length_arg + 1)), min_length((uint16) min_length_arg), max_length((uint16) max_length_arg), flag((uint16) flag_arg), min_keypart_map(min_keypart_map_arg), max_keypart_map(max_keypart_map_arg) { #ifdef HAVE_valgrind dummy=0; #endif } /** Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the minimum endpoint of the interval represented by this QUICK_RANGE into an index range endpoint specifier for the engine. @param Pointer to an uninitialized key_range C struct. @param prefix_length The length of the search key prefix to be used for lookup. @param keypart_map A set (bitmap) of keyparts to be used. */ void make_min_endpoint(key_range *kr, uint prefix_length, key_part_map keypart_map) { make_min_endpoint(kr); kr->length= MY_MIN(kr->length, prefix_length); kr->keypart_map&= keypart_map; } /** Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the minimum endpoint of the interval represented by this QUICK_RANGE into an index range endpoint specifier for the engine. @param Pointer to an uninitialized key_range C struct. */ void make_min_endpoint(key_range *kr) { kr->key= (const uchar*)min_key; kr->length= min_length; kr->keypart_map= min_keypart_map; kr->flag= ((flag & NEAR_MIN) ? HA_READ_AFTER_KEY : (flag & EQ_RANGE) ? HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); } /** Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the maximum endpoint of the interval represented by this QUICK_RANGE into an index range endpoint specifier for the engine. @param Pointer to an uninitialized key_range C struct. @param prefix_length The length of the search key prefix to be used for lookup. @param keypart_map A set (bitmap) of keyparts to be used. */ void make_max_endpoint(key_range *kr, uint prefix_length, key_part_map keypart_map) { make_max_endpoint(kr); kr->length= MY_MIN(kr->length, prefix_length); kr->keypart_map&= keypart_map; } /** Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the maximum endpoint of the interval represented by this QUICK_RANGE into an index range endpoint specifier for the engine. @param Pointer to an uninitialized key_range C struct. */ void make_max_endpoint(key_range *kr) { kr->key= (const uchar*)max_key; kr->length= max_length; kr->keypart_map= max_keypart_map; /* We use READ_AFTER_KEY here because if we are reading on a key prefix we want to find all keys with this prefix */ kr->flag= (flag & NEAR_MAX ? HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY); } }; /* Quick select interface. This class is a parent for all QUICK_*_SELECT and FT_SELECT classes. The usage scenario is as follows: 1. Create quick select quick= new QUICK_XXX_SELECT(...); 2. Perform lightweight initialization. This can be done in 2 ways: 2.a: Regular initialization if (quick->init()) { //the only valid action after failed init() call is delete delete quick; } 2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT if (quick->init_ror_merged_scan()) delete quick; 3. Perform zero, one, or more scans. while (...) { // initialize quick select for scan. This may allocate // buffers and/or prefetch rows. if (quick->reset()) { //the only valid action after failed reset() call is delete delete quick; //abort query } // perform the scan do { res= quick->get_next(); } while (res && ...) } 4. Delete the select: delete quick; NOTE quick select doesn't use Sql_alloc/MEM_ROOT allocation because "range checked for each record" functionality may create/destroy O(#records_in_some_table) quick selects during query execution. */ class QUICK_SELECT_I { public: ha_rows records; /* estimate of # of records to be retrieved */ double read_time; /* time to perform this retrieval */ TABLE *head; /* Index this quick select uses, or MAX_KEY for quick selects that use several indexes */ uint index; /* Total length of first used_key_parts parts of the key. Applicable if index!= MAX_KEY. */ uint max_used_key_length; /* Max. number of (first) key parts this quick select uses for retrieval. eg. for "(key1p1=c1 AND key1p2=c2) OR key1p1=c2" used_key_parts == 2. Applicable if index!= MAX_KEY. For QUICK_GROUP_MIN_MAX_SELECT it includes MIN/MAX argument keyparts. */ uint used_key_parts; /* Set to 1 if we used group by optimization to calculate number of rows in the result, stored in table->opt_range_condition_rows. This is only used for asserts. */ bool group_by_optimization_used; QUICK_SELECT_I(); virtual ~QUICK_SELECT_I() = default;; /* Do post-constructor initialization. SYNOPSIS init() init() performs initializations that should have been in constructor if it was possible to return errors from constructors. The join optimizer may create and then delete quick selects without retrieving any rows so init() must not contain any IO or CPU intensive code. If init() call fails the only valid action is to delete this quick select, reset() and get_next() must not be called. RETURN 0 OK other Error code */ virtual int init() = 0; /* Initialize quick select for row retrieval. SYNOPSIS reset() reset() should be called when it is certain that row retrieval will be necessary. This call may do heavyweight initialization like buffering first N records etc. If reset() call fails get_next() must not be called. Note that reset() may be called several times if * the quick select is executed in a subselect * a JOIN buffer is used RETURN 0 OK other Error code */ virtual int reset(void) = 0; virtual int get_next() = 0; /* get next record to retrieve */ /* Range end should be called when we have looped over the whole index */ virtual void range_end() {} virtual bool reverse_sorted() = 0; virtual bool unique_key_range() { return false; } /* Request that this quick select produces sorted output. Not all quick selects can do it, the caller is responsible for calling this function only for those quick selects that can. */ virtual void need_sorted_output() = 0; enum { QS_TYPE_RANGE = 0, QS_TYPE_INDEX_INTERSECT = 1, QS_TYPE_INDEX_MERGE = 2, QS_TYPE_RANGE_DESC = 3, QS_TYPE_FULLTEXT = 4, QS_TYPE_ROR_INTERSECT = 5, QS_TYPE_ROR_UNION = 6, QS_TYPE_GROUP_MIN_MAX = 7 }; /* Get type of this quick select - one of the QS_TYPE_* values */ virtual int get_type() = 0; /* Initialize this quick select as a merged scan inside a ROR-union or a ROR- intersection scan. The caller must not additionally call init() if this function is called. SYNOPSIS init_ror_merged_scan() reuse_handler If true, the quick select may use table->handler, otherwise it must create and use a separate handler object. RETURN 0 Ok other Error */ virtual int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc) { DBUG_ASSERT(0); return 1; } /* Save ROWID of last retrieved row in file->ref. This used in ROR-merging. */ virtual void save_last_pos(){}; void add_key_and_length(String *key_names, String *used_lengths, bool *first); /* Append comma-separated list of keys this quick select uses to key_names; append comma-separated list of corresponding used lengths to used_lengths. This is used by select_describe. */ virtual void add_keys_and_lengths(String *key_names, String *used_lengths)=0; void add_key_name(String *str, bool *first); /* Save information about quick select's query plan */ virtual Explain_quick_select* get_explain(MEM_ROOT *alloc)= 0; /* Return 1 if any index used by this quick select uses field which is marked in passed bitmap. */ virtual bool is_keys_used(const MY_BITMAP *fields); /** Simple sanity check that the quick select has been set up correctly. Function is overridden by quick selects that merge indices. */ virtual bool is_valid() { return index != MAX_KEY; }; /* rowid of last row retrieved by this quick select. This is used only when doing ROR-index_merge selects */ uchar *last_rowid; /* Table record buffer used by this quick select. */ uchar *record; virtual void replace_handler(handler *new_file) { DBUG_ASSERT(0); /* Only supported in QUICK_RANGE_SELECT */ } #ifndef DBUG_OFF /* Print quick select information to DBUG_FILE. Caller is responsible for locking DBUG_FILE before this call and unlocking it afterwards. */ virtual void dbug_dump(int indent, bool verbose)= 0; #endif /* Returns a QUICK_SELECT with reverse order of to the index. */ virtual QUICK_SELECT_I *make_reverse(uint used_key_parts_arg) { return NULL; } /* Add the key columns used by the quick select into table's read set. This is used by an optimization in filesort. */ virtual void add_used_key_part_to_set()=0; }; inline bool is_index_merge(int qtype) { return qtype == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT || qtype == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || qtype == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || qtype == QUICK_SELECT_I::QS_TYPE_ROR_UNION; } struct st_qsel_param; class PARAM; /* MRR range sequence, array<QUICK_RANGE> implementation: sequence traversal context. */ typedef struct st_quick_range_seq_ctx { QUICK_RANGE **first; QUICK_RANGE **cur; QUICK_RANGE **last; } QUICK_RANGE_SEQ_CTX; range_seq_t quick_range_seq_init(void *init_param, uint n_ranges, uint flags); bool quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range); /* Quick select that does a range scan on a single key. The records are returned in key order. */ class QUICK_RANGE_SELECT : public QUICK_SELECT_I { protected: THD *thd; bool no_alloc; MEM_ROOT *parent_alloc; /* true if we enabled key only reads */ handler *file; /* Members to deal with case when this quick select is a ROR-merged scan */ bool in_ror_merged_scan; MY_BITMAP column_bitmap; bool free_file; /* TRUE <=> this->file is "owned" by this quick select */ /* Range pointers to be used when not using MRR interface */ /* Members needed to use the MRR interface */ QUICK_RANGE_SEQ_CTX qr_traversal_ctx; public: uint mrr_flags; /* Flags to be used with MRR interface */ protected: uint mrr_buf_size; /* copy from thd->variables.mrr_buff_size */ HANDLER_BUFFER *mrr_buf_desc; /* the handler buffer */ /* Info about index we're scanning */ DYNAMIC_ARRAY ranges; /* ordered array of range ptrs */ QUICK_RANGE **cur_range; /* current element in ranges */ QUICK_RANGE *last_range; KEY_PART *key_parts; KEY_PART_INFO *key_part_info; bool dont_free; /* Used by QUICK_SELECT_DESC */ int cmp_next(QUICK_RANGE *range); int cmp_prev(QUICK_RANGE *range); bool row_in_ranges(); public: MEM_ROOT alloc; QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc, MEM_ROOT *parent_alloc, bool *create_err); ~QUICK_RANGE_SELECT(); virtual QUICK_RANGE_SELECT *clone(bool *create_error) { return new QUICK_RANGE_SELECT(thd, head, index, no_alloc, parent_alloc, create_error); } void need_sorted_output() override; int init() override; int reset(void) override; int get_next() override; void range_end() override; int get_next_prefix(uint prefix_length, uint group_key_parts, uchar *cur_prefix); bool reverse_sorted() override { return 0; } bool unique_key_range() override; int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc) override; void save_last_pos() override { file->position(record); } int get_type() override { return QS_TYPE_RANGE; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; Explain_quick_select *get_explain(MEM_ROOT *alloc) override; #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose) override; #endif void replace_handler(handler *new_file) override { file= new_file; } QUICK_SELECT_I *make_reverse(uint used_key_parts_arg) override; void add_used_key_part_to_set() override; private: /* Default copy ctor used by QUICK_SELECT_DESC */ friend class TRP_ROR_INTERSECT; friend QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, struct st_table_ref *ref, ha_rows records); friend bool get_quick_keys(PARAM *param, QUICK_RANGE_SELECT *quick, KEY_PART *key, SEL_ARG *key_tree, uchar *min_key, uint min_key_flag, uchar *max_key, uint max_key_flag); friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx, SEL_ARG *key_tree, uint mrr_flags, uint mrr_buf_size, MEM_ROOT *alloc); friend class QUICK_SELECT_DESC; friend class QUICK_INDEX_SORT_SELECT; friend class QUICK_INDEX_MERGE_SELECT; friend class QUICK_ROR_INTERSECT_SELECT; friend class QUICK_INDEX_INTERSECT_SELECT; friend class QUICK_GROUP_MIN_MAX_SELECT; friend bool quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range); friend range_seq_t quick_range_seq_init(void *init_param, uint n_ranges, uint flags); friend int read_keys_and_merge_scans(THD *thd, TABLE *head, List<QUICK_RANGE_SELECT> quick_selects, QUICK_RANGE_SELECT *pk_quick_select, READ_RECORD *read_record, bool intersection, key_map *filtered_scans, Unique **unique_ptr); }; class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT { public: QUICK_RANGE_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg, bool no_alloc, MEM_ROOT *parent_alloc, bool *create_err) :QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc, create_err) {}; QUICK_RANGE_SELECT *clone(bool *create_error) override { DBUG_ASSERT(0); return new QUICK_RANGE_SELECT_GEOM(thd, head, index, no_alloc, parent_alloc, create_error); } int get_next() override; }; /* QUICK_INDEX_SORT_SELECT is the base class for the common functionality of: - QUICK_INDEX_MERGE_SELECT, access based on multi-index merge/union - QUICK_INDEX_INTERSECT_SELECT, access based on multi-index intersection QUICK_INDEX_SORT_SELECT uses * QUICK_RANGE_SELECTs to get rows * Unique class - to remove duplicate rows for QUICK_INDEX_MERGE_SELECT - to intersect rows for QUICK_INDEX_INTERSECT_SELECT INDEX MERGE OPTIMIZER Current implementation doesn't detect all cases where index merge could be used, in particular: * index_merge+'using index' is not supported * If WHERE part contains complex nested AND and OR conditions, some ways to retrieve rows using index merge will not be considered. The choice of read plan may depend on the order of conjuncts/disjuncts in WHERE part of the query, see comments near imerge_list_or_list and SEL_IMERGE::or_sel_tree_with_checks functions for details. * There is no "index_merge_ref" method (but index merge on non-first table in join is possible with 'range checked for each record'). ROW RETRIEVAL ALGORITHM index merge/intersection uses Unique class for duplicates removal. index merge/intersection takes advantage of Clustered Primary Key (CPK) if the table has one. The index merge/intersection algorithm consists of two phases: Phase 1 (implemented by a QUICK_INDEX_MERGE_SELECT::read_keys_and_merge call): prepare() { activate 'index only'; while(retrieve next row for non-CPK scan) { if (there is a CPK scan and row will be retrieved by it) skip this row; else put its rowid into Unique; } deactivate 'index only'; } Phase 2 (implemented as sequence of QUICK_INDEX_MERGE_SELECT::get_next calls): fetch() { retrieve all rows from row pointers stored in Unique (merging/intersecting them); free Unique; if (! intersection) retrieve all rows for CPK scan; } */ class QUICK_INDEX_SORT_SELECT : public QUICK_SELECT_I { protected: Unique *unique; public: QUICK_INDEX_SORT_SELECT(THD *thd, TABLE *table); ~QUICK_INDEX_SORT_SELECT(); int init() override; void need_sorted_output() override { DBUG_ASSERT(0); /* Can't do it */ } int reset(void) override; bool reverse_sorted() override { return false; } bool unique_key_range() override { return false; } bool is_keys_used(const MY_BITMAP *fields) override; #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose) override; #endif Explain_quick_select *get_explain(MEM_ROOT *alloc) override; bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range); /* range quick selects this index merge/intersect consists of */ List<QUICK_RANGE_SELECT> quick_selects; /* quick select that uses clustered primary key (NULL if none) */ QUICK_RANGE_SELECT* pk_quick_select; MEM_ROOT alloc; THD *thd; bool is_valid() override { List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); QUICK_RANGE_SELECT *quick; bool valid= true; while ((quick= it++)) { if (!quick->is_valid()) { valid= false; break; } } return valid; } virtual int read_keys_and_merge()= 0; /* used to get rows collected in Unique */ READ_RECORD read_record; void add_used_key_part_to_set() override; }; /* Index merge sort union */ class QUICK_INDEX_MERGE_SELECT : public QUICK_INDEX_SORT_SELECT { private: /* true if this select is currently doing a clustered PK scan */ bool doing_pk_scan; protected: int read_keys_and_merge() override; public: QUICK_INDEX_MERGE_SELECT(THD *thd_arg, TABLE *table) :QUICK_INDEX_SORT_SELECT(thd_arg, table) {} int get_next() override; int get_type() override { return QS_TYPE_INDEX_MERGE; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; }; /* Index merge sort intersection */ class QUICK_INDEX_INTERSECT_SELECT : public QUICK_INDEX_SORT_SELECT { protected: int read_keys_and_merge() override; public: QUICK_INDEX_INTERSECT_SELECT(THD *thd_arg, TABLE *table) :QUICK_INDEX_SORT_SELECT(thd_arg, table) {} key_map filtered_scans; int get_next() override; int get_type() override { return QS_TYPE_INDEX_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; Explain_quick_select *get_explain(MEM_ROOT *alloc) override; }; /* Index merge intersection Rowid-Ordered Retrieval (ROR) index intersection quick select. This quick select produces intersection of row sequences returned by several QUICK_RANGE_SELECTs it "merges". All merged QUICK_RANGE_SELECTs must return rowids in rowid order. QUICK_ROR_INTERSECT_SELECT will return rows in rowid order, too. All merged quick selects retrieve {rowid, covered_fields} tuples (not full table records). QUICK_ROR_INTERSECT_SELECT retrieves full records if it is not being used by QUICK_ROR_INTERSECT_SELECT and all merged quick selects together don't cover needed all fields. If one of the merged quick selects is a Clustered PK range scan, it is used only to filter rowid sequence produced by other merged quick selects. */ class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I { public: QUICK_ROR_INTERSECT_SELECT(THD *thd, TABLE *table, bool retrieve_full_rows, MEM_ROOT *parent_alloc); ~QUICK_ROR_INTERSECT_SELECT(); int init() override; void need_sorted_output() override { DBUG_ASSERT(0); /* Can't do it */ } int reset(void) override; int get_next() override; bool reverse_sorted() override { return false; } bool unique_key_range() override { return false; } int get_type() override { return QS_TYPE_ROR_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; Explain_quick_select *get_explain(MEM_ROOT *alloc) override; bool is_keys_used(const MY_BITMAP *fields) override; void add_used_key_part_to_set() override; #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose) override; #endif int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc) override; bool push_quick_back(MEM_ROOT *alloc, QUICK_RANGE_SELECT *quick_sel_range); class QUICK_SELECT_WITH_RECORD : public Sql_alloc { public: QUICK_RANGE_SELECT *quick; uchar *key_tuple; ~QUICK_SELECT_WITH_RECORD() { delete quick; } }; /* Range quick selects this intersection consists of, not including cpk_quick. */ List<QUICK_SELECT_WITH_RECORD> quick_selects; bool is_valid() override { List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); QUICK_SELECT_WITH_RECORD *quick; bool valid= true; while ((quick= it++)) { if (!quick->quick->is_valid()) { valid= false; break; } } return valid; } /* Merged quick select that uses Clustered PK, if there is one. This quick select is not used for row retrieval, it is used for row retrieval. */ QUICK_RANGE_SELECT *cpk_quick; MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */ THD *thd; /* current thread */ bool need_to_fetch_row; /* if true, do retrieve full table records. */ /* in top-level quick select, true if merged scans where initialized */ bool scans_inited; }; /* Index merge union Rowid-Ordered Retrieval index union select. This quick select produces union of row sequences returned by several quick select it "merges". All merged quick selects must return rowids in rowid order. QUICK_ROR_UNION_SELECT will return rows in rowid order, too. All merged quick selects are set not to retrieve full table records. ROR-union quick select always retrieves full records. */ class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I { public: QUICK_ROR_UNION_SELECT(THD *thd, TABLE *table); ~QUICK_ROR_UNION_SELECT(); int init() override; void need_sorted_output() override { DBUG_ASSERT(0); /* Can't do it */ } int reset(void) override; int get_next() override; bool reverse_sorted() override { return false; } bool unique_key_range() override { return false; } int get_type() override { return QS_TYPE_ROR_UNION; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; Explain_quick_select *get_explain(MEM_ROOT *alloc) override; bool is_keys_used(const MY_BITMAP *fields) override; void add_used_key_part_to_set() override; #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose) override; #endif bool push_quick_back(QUICK_SELECT_I *quick_sel_range); List<QUICK_SELECT_I> quick_selects; /* Merged quick selects */ bool is_valid() override { List_iterator_fast<QUICK_SELECT_I> it(quick_selects); QUICK_SELECT_I *quick; bool valid= true; while ((quick= it++)) { if (!quick->is_valid()) { valid= false; break; } } return valid; } QUEUE queue; /* Priority queue for merge operation */ MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */ THD *thd; /* current thread */ uchar *cur_rowid; /* buffer used in get_next() */ uchar *prev_rowid; /* rowid of last row returned by get_next() */ bool have_prev_rowid; /* true if prev_rowid has valid data */ uint rowid_length; /* table rowid length */ private: bool scans_inited; }; /* Index scan for GROUP-BY queries with MIN/MAX aggregate functions. This class provides a specialized index access method for GROUP-BY queries of the forms: SELECT A_1,...,A_k, [B_1,...,B_m], [MIN(C)], [MAX(C)] FROM T WHERE [RNG(A_1,...,A_p ; where p <= k)] [AND EQ(B_1,...,B_m)] [AND PC(C)] [AND PA(A_i1,...,A_iq)] GROUP BY A_1,...,A_k; or SELECT DISTINCT A_i1,...,A_ik FROM T WHERE [RNG(A_1,...,A_p ; where p <= k)] [AND PA(A_i1,...,A_iq)]; where all selected fields are parts of the same index. The class of queries that can be processed by this quick select is fully specified in the description of get_best_trp_group_min_max() in opt_range.cc. The get_next() method directly produces result tuples, thus obviating the need to call end_send_group() because all grouping is already done inside get_next(). Since one of the requirements is that all select fields are part of the same index, this class produces only index keys, and not complete records. */ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I { private: handler * const file; /* The handler used to get data. */ JOIN *join; /* Descriptor of the current query */ KEY *index_info; /* The index chosen for data access */ uchar *record; /* Buffer where the next record is returned. */ uchar *tmp_record; /* Temporary storage for next_min(), next_max(). */ uchar *group_prefix; /* Key prefix consisting of the GROUP fields. */ const uint group_prefix_len; /* Length of the group prefix. */ uint group_key_parts; /* A number of keyparts in the group prefix */ bool have_min; /* Specify whether we are computing */ bool have_max; /* a MIN, a MAX, or both. */ bool have_agg_distinct;/* aggregate_function(DISTINCT ...). */ bool seen_first_key; /* Denotes whether the first key was retrieved.*/ bool doing_key_read; /* true if we enabled key only reads */ KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */ /* of all MIN/MAX functions. */ uint min_max_arg_len; /* The length of the MIN/MAX argument field */ uchar *key_infix; /* Infix of constants from equality predicates. */ uint key_infix_len; DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */ uint real_prefix_len; /* Length of key prefix extended with key_infix. */ uint real_key_parts; /* A number of keyparts in the above value. */ List<Item_sum> *min_functions; List<Item_sum> *max_functions; List_iterator<Item_sum> *min_functions_it; List_iterator<Item_sum> *max_functions_it; /* Use index scan to get the next different key instead of jumping into it through index read */ bool is_index_scan; public: /* The following two members are public to allow easy access from TRP_GROUP_MIN_MAX::make_quick() */ MEM_ROOT alloc; /* Memory pool for this and quick_prefix_select data. */ QUICK_RANGE_SELECT *quick_prefix_select;/* For retrieval of group prefixes. */ private: int next_prefix(); int next_min_in_range(); int next_max_in_range(); int next_min(); int next_max(); void update_min_result(); void update_max_result(); int cmp_min_max_key(const uchar *key, uint16 length); public: QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min, bool have_max, bool have_agg_distinct, KEY_PART_INFO *min_max_arg_part, uint group_prefix_len, uint group_key_parts, uint used_key_parts, KEY *index_info, uint use_index, double read_cost, ha_rows records, uint key_infix_len, uchar *key_infix, MEM_ROOT *parent_alloc, bool is_index_scan); ~QUICK_GROUP_MIN_MAX_SELECT(); bool add_range(SEL_ARG *sel_range); void update_key_stat(); void adjust_prefix_ranges(); bool alloc_buffers(); int init() override; void need_sorted_output() override { /* always do it */ } int reset() override; int get_next() override; bool reverse_sorted() override { return false; } bool unique_key_range() override { return false; } int get_type() override { return QS_TYPE_GROUP_MIN_MAX; } void add_keys_and_lengths(String *key_names, String *used_lengths) override; void add_used_key_part_to_set() override; #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose) override; #endif bool is_agg_distinct() { return have_agg_distinct; } bool loose_scan_is_scanning() { return is_index_scan; } Explain_quick_select *get_explain(MEM_ROOT *alloc) override; }; bool using_with_ties_and_group_min_max(JOIN *join); class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT { public: QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts); QUICK_RANGE_SELECT *clone(bool *create_error) override { DBUG_ASSERT(0); return new QUICK_SELECT_DESC(this, used_key_parts); } int get_next() override; bool reverse_sorted() override { return 1; } int get_type() override { return QS_TYPE_RANGE_DESC; } QUICK_SELECT_I *make_reverse(uint used_key_parts_arg) override { return this; // is already reverse sorted } private: bool range_reads_after_key(QUICK_RANGE *range); int reset(void) override { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } List<QUICK_RANGE> rev_ranges; List_iterator<QUICK_RANGE> rev_it; uint used_key_parts; }; class SQL_SELECT :public Sql_alloc { public: QUICK_SELECT_I *quick; // If quick-select used COND *cond; // where condition /* When using Index Condition Pushdown: condition that we've had before extracting and pushing index condition. In other cases, NULL. */ Item *pre_idx_push_select_cond; TABLE *head; IO_CACHE file; // Positions to used records ha_rows records; // Records in use if read from file ALL_READ_COST read_cost; // Cost of reading rows double read_time; // Time to read rows (from read_cost) key_map quick_keys; // Possible quick keys key_map needed_reg; // Possible quick keys after prev tables. table_map const_tables,read_tables; /* See PARAM::possible_keys */ key_map possible_keys; bool free_cond; /* Currently not used and always FALSE */ SQL_SELECT(); ~SQL_SELECT(); void cleanup(); void set_quick(QUICK_SELECT_I *new_quick) { delete quick; quick= new_quick; } /* @return true - for ERROR and IMPOSSIBLE_RANGE false - Ok */ bool check_quick(THD *thd, bool force_quick_range, ha_rows limit, Item_func::Bitmap note_unusable_keys) { key_map tmp; tmp.set_all(); return test_quick_select(thd, tmp, 0, limit, force_quick_range, FALSE, FALSE, FALSE, note_unusable_keys) != OK; } /* RETURN 0 if record must be skipped <-> (cond && cond->val_bool() == false) -1 if error 1 otherwise */ inline int skip_record(THD *thd) { int rc= MY_TEST(!cond || cond->val_bool()); if (thd->is_error()) rc= -1; return rc; } enum quick_select_return_type { IMPOSSIBLE_RANGE = -1, ERROR, OK }; enum quick_select_return_type test_quick_select(THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range, bool ordered_output, bool remove_false_parts_of_where, bool only_single_index_range_scan, Item_func::Bitmap note_unusable_keys); }; typedef enum SQL_SELECT::quick_select_return_type quick_select_return; class SQL_SELECT_auto { SQL_SELECT *select; public: SQL_SELECT_auto(): select(NULL) {} ~SQL_SELECT_auto() { delete select; } SQL_SELECT_auto& operator= (SQL_SELECT *_select) { select= _select; return *this; } operator SQL_SELECT * () const { return select; } SQL_SELECT * operator-> () const { return select; } operator bool () const { return select; } }; class FT_SELECT: public QUICK_RANGE_SELECT { public: FT_SELECT(THD *thd, TABLE *table, uint key, bool *create_err) : QUICK_RANGE_SELECT (thd, table, key, 1, NULL, create_err) { (void) init(); } ~FT_SELECT() { file->ft_end(); } QUICK_RANGE_SELECT *clone(bool *create_error) override { DBUG_ASSERT(0); return new FT_SELECT(thd, head, index, create_error); } int init() override { return file->ft_init(); } int reset() override { return 0; } int get_next() override { return file->ha_ft_read(record); } int get_type() override { return QS_TYPE_FULLTEXT; } }; FT_SELECT *get_ft_select(THD *thd, TABLE *table, uint key); QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, struct st_table_ref *ref, ha_rows records); SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, SORT_INFO* filesort, bool allow_null_cond, int *error); bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond); bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param, uint limit); #ifdef WITH_PARTITION_STORAGE_ENGINE bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond); #endif void store_key_image_to_rec(Field *field, uchar *ptr, uint len); extern String null_string; /* check this number of rows (default value) */ #define SELECTIVITY_SAMPLING_LIMIT 100 /* but no more then this part of table (10%) */ #define SELECTIVITY_SAMPLING_SHARE 0.10 /* do not check if we are going check less then this number of records */ #define SELECTIVITY_SAMPLING_THRESHOLD 10 #endif gcalc_tools.h 0000644 00000027174 15156036150 0007223 0 ustar 00 /* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved. Copyright (C) 2011 Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef GCALC_TOOLS_INCLUDED #define GCALC_TOOLS_INCLUDED #include "gcalc_slicescan.h" #include "sql_string.h" /* The Gcalc_function class objects are used to check for a binary relation. The relation can be constructed with the prefix notation using predicates as op_not (as !A) op_union ( A || B || C... ) op_intersection ( A && B && C ... ) op_symdifference ( A+B+C+... == 1 ) op_difference ( A && !(B||C||..)) with the calls of the add_operation(operation, n_operands) method. The relation is calculated over a set of shapes, that in turn have to be added with the add_new_shape() method. All the 'shapes' can be set to 0 with clear_shapes() method and single value can be changed with the invert_state() method. Then the value of the relation can be calculated with the count() method. Frequently used method is find_function(Gcalc_scan_iterator it) that iterates through the 'it' until the relation becomes TRUE. */ class Gcalc_function { private: String shapes_buffer; String function_buffer; int *i_states; int *b_states; uint32 cur_object_id; uint n_shapes; int count_internal(const char *cur_func, uint set_type, const char **end); public: enum op_type { v_empty= 0x00000000, v_find_t= 0x01000000, v_find_f= 0x02000000, v_t_found= 0x03000000, v_f_found= 0x04000000, v_mask= 0x07000000, op_not= 0x80000000, op_shape= 0x00000000, op_union= 0x10000000, op_intersection= 0x20000000, op_symdifference= 0x30000000, op_difference= 0x40000000, op_repeat= 0x50000000, op_border= 0x60000000, op_internals= 0x70000000, op_false= 0x08000000, op_any= 0x78000000 /* The mask to get any of the operations */ }; enum shape_type { shape_point= 0, shape_line= 1, shape_polygon= 2, shape_hole= 3 }; enum count_result { result_false= 0, result_true= 1, result_unknown= 2 }; Gcalc_function() : n_shapes(0) {} gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind); /* Adds the leaf operation that returns the shape value. Also adds the shape to the list of operands. */ int single_shape_op(shape_type shape_kind, gcalc_shape_info *si); void add_operation(uint operation, uint32 n_operands); void add_not_operation(op_type operation, uint32 n_operands); uint32 get_next_expression_pos() { return function_buffer.length(); } void add_operands_to_op(uint32 operation_pos, uint32 n_operands); int repeat_expression(uint32 exp_pos); void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; } int reserve_shape_buffer(uint n_shapes); int reserve_op_buffer(uint n_ops); uint get_nshapes() const { return n_shapes; } shape_type get_shape_kind(gcalc_shape_info si) const { return (shape_type) uint4korr(shapes_buffer.ptr() + (si*4)); } void set_states(int *shape_states) { i_states= shape_states; } int alloc_states(); void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; } void set_i_state(gcalc_shape_info shape) { i_states[shape]= 1; } void clear_i_state(gcalc_shape_info shape) { i_states[shape]= 0; } void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; } void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; } int get_state(gcalc_shape_info shape) { return i_states[shape] | b_states[shape]; } int get_i_state(gcalc_shape_info shape) { return i_states[shape]; } int get_b_state(gcalc_shape_info shape) { return b_states[shape]; } int count() { return count_internal(function_buffer.ptr(), 0, 0); } int count_last() { return count_internal(function_buffer.ptr(), 1, 0); } void clear_i_states(); void clear_b_states(); void reset(); int check_function(Gcalc_scan_iterator &scan_it); }; /* Gcalc_operation_transporter class extends the Gcalc_shape_transporter. In addition to the parent's functionality, it fills the Gcalc_function object so it has the function that determines the proper shape. For example Multipolyline will be represented as an union of polylines. */ class Gcalc_operation_transporter : public Gcalc_shape_transporter { protected: Gcalc_function *m_fn; gcalc_shape_info m_si; public: Gcalc_operation_transporter(Gcalc_function *fn, Gcalc_heap *heap) : Gcalc_shape_transporter(heap), m_fn(fn) {} int single_point(double x, double y) override; int start_line() override; int complete_line() override; int start_poly() override; int complete_poly() override; int start_ring() override; int complete_ring() override; int add_point(double x, double y) override; int start_collection(int n_objects) override; int empty_shape() override; }; /* When we calculate the result of an spatial operation like Union or Intersection, we receive vertexes of the result one-by-one, and probably need to treat them in variative ways. So, the Gcalc_result_receiver class designed to get these vertexes and construct shapes/objects out of them. and to store the result in an appropriate format */ class Gcalc_result_receiver { String buffer; uint32 n_points; Gcalc_function::shape_type common_shapetype; bool collection_result; uint32 n_shapes; uint32 n_holes; Gcalc_function::shape_type cur_shape; uint32 shape_pos; double first_x, first_y, prev_x, prev_y; double shape_area; public: Gcalc_result_receiver() : n_points(0), common_shapetype(Gcalc_function::shape_point), collection_result(FALSE), n_shapes(0), n_holes(0), cur_shape(Gcalc_function::shape_point), shape_pos(0) {} int start_shape(Gcalc_function::shape_type shape); int add_point(double x, double y); int complete_shape(); int single_point(double x, double y); int done(); void reset(); const char *result() { return buffer.ptr(); } uint length() { return buffer.length(); } int get_nshapes() { return n_shapes; } int get_nholes() { return n_holes; } int get_result_typeid(); uint32 position() { return buffer.length(); } int move_hole(uint32 dest_position, uint32 source_position, uint32 *position_shift); }; /* Gcalc_operation_reducer class incapsulates the spatial operation functionality. It analyses the slices generated by the slicescan and calculates the shape of the result defined by some Gcalc_function. */ class Gcalc_operation_reducer : public Gcalc_dyn_list { public: enum modes { /* Numeric values important here - careful with changing */ default_mode= 0, prefer_big_with_holes= 1, polygon_selfintersections_allowed= 2, /* allowed in the result */ line_selfintersections_allowed= 4 /* allowed in the result */ }; Gcalc_operation_reducer(size_t blk_size=8192); Gcalc_operation_reducer(const Gcalc_operation_reducer &gor); void init(Gcalc_function *fn, modes mode= default_mode); Gcalc_operation_reducer(Gcalc_function *fn, modes mode= default_mode, size_t blk_size=8192); GCALC_DECL_TERMINATED_STATE(killed) int count_slice(Gcalc_scan_iterator *si); int count_all(Gcalc_heap *hp); int get_result(Gcalc_result_receiver *storage); void reset(); #ifndef GCALC_DBUG_OFF int n_res_points; #endif /*GCALC_DBUG_OFF*/ class res_point : public Gcalc_dyn_list::Item { public: int intersection_point; union { const Gcalc_heap::Info *pi; res_point *first_poly_node; }; union { res_point *outer_poly; uint32 poly_position; }; res_point *up; res_point *down; res_point *glue; Gcalc_function::shape_type type; Gcalc_dyn_list::Item **prev_hook; #ifndef GCALC_DBUG_OFF int point_n; #endif /*GCALC_DBUG_OFF*/ void set(const Gcalc_scan_iterator *si); res_point *get_next() { return (res_point *)next; } }; class active_thread : public Gcalc_dyn_list::Item { public: res_point *rp; res_point *thread_start; const Gcalc_heap::Info *p1, *p2; res_point *enabled() { return rp; } active_thread *get_next() { return (active_thread *)next; } }; class poly_instance : public Gcalc_dyn_list::Item { public: uint32 *after_poly_position; poly_instance *get_next() { return (poly_instance *)next; } }; class line : public Gcalc_dyn_list::Item { public: active_thread *t; int incoming; const Gcalc_scan_iterator::point *p; line *get_next() { return (line *)next; } }; class poly_border : public Gcalc_dyn_list::Item { public: active_thread *t; int incoming; int prev_state; const Gcalc_scan_iterator::point *p; poly_border *get_next() { return (poly_border *)next; } }; line *m_lines; Gcalc_dyn_list::Item **m_lines_hook; poly_border *m_poly_borders; Gcalc_dyn_list::Item **m_poly_borders_hook; line *new_line() { return (line *) new_item(); } poly_border *new_poly_border() { return (poly_border *) new_item(); } int add_line(int incoming, active_thread *t, const Gcalc_scan_iterator::point *p); int add_poly_border(int incoming, active_thread *t, int prev_state, const Gcalc_scan_iterator::point *p); protected: Gcalc_function *m_fn; Gcalc_dyn_list::Item **m_res_hook; res_point *m_result; int m_mode; res_point *result_heap; active_thread *m_first_active_thread; res_point *add_res_point(Gcalc_function::shape_type type); active_thread *new_active_thread() { return (active_thread *)new_item(); } poly_instance *new_poly() { return (poly_instance *) new_item(); } private: int start_line(active_thread *t, const Gcalc_scan_iterator::point *p, const Gcalc_scan_iterator *si); int end_line(active_thread *t, const Gcalc_scan_iterator *si); int connect_threads(int incoming_a, int incoming_b, active_thread *ta, active_thread *tb, const Gcalc_scan_iterator::point *pa, const Gcalc_scan_iterator::point *pb, active_thread *prev_range, const Gcalc_scan_iterator *si, Gcalc_function::shape_type s_t); int add_single_point(const Gcalc_scan_iterator *si); poly_border *get_pair_border(poly_border *b1); int continue_range(active_thread *t, const Gcalc_heap::Info *p, const Gcalc_heap::Info *p_next); int continue_i_range(active_thread *t, const Gcalc_heap::Info *ii); int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p); int get_single_result(res_point *res, Gcalc_result_receiver *storage); int get_result_thread(res_point *cur, Gcalc_result_receiver *storage, int move_upward, res_point *first_poly_node); int get_polygon_result(res_point *cur, Gcalc_result_receiver *storage, res_point *first_poly_node); int get_line_result(res_point *cur, Gcalc_result_receiver *storage); void free_result(res_point *res); }; #endif /*GCALC_TOOLS_INCLUDED*/ wsrep_schema.h 0000644 00000012750 15156036150 0007404 0 ustar 00 /* Copyright (C) 2015-2024 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef WSREP_SCHEMA_H #define WSREP_SCHEMA_H /* wsrep-lib */ #include "wsrep_types.h" #include "mysqld.h" #include "wsrep_mysqld.h" /* Forward decls */ class THD; class Relay_log_info; struct TABLE; struct TABLE_LIST; struct st_mysql_lex_string; typedef struct st_mysql_lex_string LEX_STRING; class Gtid_log_event; /** Name of the table in `wsrep_schema_str` used for storing streaming replication data. In an InnoDB full format, e.g. "database/tablename". */ extern const char* wsrep_sr_table_name_full; class Wsrep_schema { public: Wsrep_schema(); ~Wsrep_schema(); /* Initialize wsrep schema. Storage engines must be running before calling this function. */ int init(); /* Store wsrep view info into wsrep schema. */ int store_view(THD*, const Wsrep_view& view); /* Restore view info from stable storage. */ Wsrep_view restore_view(THD* thd, const Wsrep_id& own_id) const; /** Append transaction fragment to fragment storage. Transaction must have been started for THD before this call. In order to make changes durable, transaction must be committed separately after this call. @param thd THD object @param server_id Wsrep server identifier @param transaction_id Transaction identifier @param flags Flags for the fragment @param data Fragment data buffer @return Zero in case of success, non-zero on failure. */ int append_fragment(THD* thd, const wsrep::id& server_id, wsrep::transaction_id transaction_id, wsrep::seqno seqno, int flags, const wsrep::const_buffer& data); /** Update existing fragment meta data. The fragment must have been inserted before using append_fragment(). @param thd THD object @param ws_meta Wsrep meta data @return Zero in case of success, non-zero on failure. */ int update_fragment_meta(THD* thd, const wsrep::ws_meta& ws_meta); /** Remove fragments from storage. This method must be called inside active transaction. Fragment removal will be committed once the transaction commits. @param thd Pointer to THD object @param server_id Identifier of the running server @param transaction_id Identifier of the current transaction @param fragments Vector of fragment seqnos to be removed */ int remove_fragments(THD* thd, const wsrep::id& server_id, wsrep::transaction_id transaction_id, const std::vector<wsrep::seqno>& fragments); /** Replay a transaction from stored fragments. The caller must have started a transaction for a thd. @param thd Pointer to THD object @param ws_meta Write set meta data for commit fragment. @param fragments Vector of fragments to be replayed @return Zero on success, non-zero on failure. */ int replay_transaction(THD* thd, Relay_log_info* rli, const wsrep::ws_meta& ws_meta, const std::vector<wsrep::seqno>& fragments); /** Recover streaming transactions from SR table. This method should be called after storage enignes are initialized. It will scan SR table and replay found streaming transactions. @param orig_thd The THD object of the calling thread. @return Zero on success, non-zero on failure. */ int recover_sr_transactions(THD* orig_thd); /** Store GTID-event to mysql.gtid_slave_pos table. @param thd The THD object of the calling thread. @param gtid GTID event from binlog. @return Zero on success, non-zero on failure. */ int store_gtid_event(THD* thd, const Gtid_log_event *gtid); /** Delete all rows on bootstrap from `wsrep_allowlist` variable */ void clear_allowlist(); /** Store allowlist ip on bootstrap from `wsrep_allowlist` variable */ void store_allowlist(std::vector<std::string>& ip_allowlist); /** Scan white list table against accepted connection. Allow if ip is found in table or if table is empty. @param key Which allowlist column to compare @param value Value to be checked against allowlist @return True if found or empty table, false on not found */ bool allowlist_check(Wsrep_allowlist_key key, const std::string& val); private: /* Non-copyable */ Wsrep_schema(const Wsrep_schema&); Wsrep_schema& operator=(const Wsrep_schema&); }; extern Wsrep_schema* wsrep_schema; extern LEX_CSTRING WSREP_LEX_SCHEMA; extern LEX_CSTRING WSREP_LEX_STREAMING; extern LEX_CSTRING WSREP_LEX_CLUSTER; extern LEX_CSTRING WSREP_LEX_MEMBERS; extern LEX_CSTRING WSREP_LEX_ALLOWLIST; #endif /* !WSREP_SCHEMA_H */ events.h 0000644 00000011147 15156036151 0006230 0 ustar 00 #ifndef _EVENT_H_ #define _EVENT_H_ /* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @defgroup Event_Scheduler Event Scheduler @ingroup Runtime_Environment @{ @file events.h A public interface of Events_Scheduler module. */ #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_event_scheduler_LOCK_scheduler_state; extern PSI_cond_key key_event_scheduler_COND_state; extern PSI_thread_key key_thread_event_scheduler, key_thread_event_worker; #endif /* HAVE_PSI_INTERFACE */ extern PSI_memory_key key_memory_event_basic_root; /* Always defined, for SHOW PROCESSLIST. */ extern PSI_stage_info stage_waiting_on_empty_queue; extern PSI_stage_info stage_waiting_for_next_activation; extern PSI_stage_info stage_waiting_for_scheduler_to_stop; #include "sql_string.h" /* LEX_CSTRING */ #include "my_time.h" /* interval_type */ class Event_db_repository; class Event_parse_data; class Event_queue; class Event_scheduler; struct TABLE_LIST; class THD; typedef class Item COND; int sortcmp_lex_string(const LEX_CSTRING *s, const LEX_CSTRING *t, const CHARSET_INFO *cs); /** @brief A facade to the functionality of the Event Scheduler. Every public operation against the scheduler has to be executed via the interface provided by a static method of this class. No instance of this class is ever created and it has no non-static data members. The life cycle of the Events module is the following: At server start up: init_mutexes() -> init() When the server is running: create_event(), drop_event(), start_or_stop_event_scheduler(), etc At shutdown: deinit(), destroy_mutexes(). The peculiar initialization and shutdown cycle is an adaptation to the outside server startup/shutdown framework and mimics the rest of MySQL subsystems (ACL, time zone tables, etc). */ class Events { public: /* the following block is to support --event-scheduler command line option and the @@global.event_scheduler SQL variable. See sys_var.cc */ enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED, EVENTS_ORIGINAL }; /* Protected using LOCK_global_system_variables only. */ static ulong opt_event_scheduler, startup_state; static ulong inited; static bool check_if_system_tables_error(); static bool start(int *err_no); static bool stop(); public: /* A hack needed for Event_queue_element */ static Event_db_repository * get_db_repository() { return db_repository; } static bool init(THD *thd, bool opt_noacl); static void deinit(); static void init_mutexes(); static void destroy_mutexes(); static bool create_event(THD *thd, Event_parse_data *parse_data); static bool update_event(THD *thd, Event_parse_data *parse_data, LEX_CSTRING *new_dbname, LEX_CSTRING *new_name); static bool drop_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name, bool if_exists); static void drop_schema_events(THD *thd, const LEX_CSTRING &db); static bool show_create_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name); /* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */ static int reconstruct_interval_expression(String *buf, interval_type interval, longlong expression); static int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */); static void dump_internal_status(); static void set_original_state(ulong startup_state_org) { startup_state= startup_state_org; } private: static bool load_events_from_db(THD *thd); private: static Event_queue *event_queue; static Event_scheduler *scheduler; static Event_db_repository *db_repository; private: /* Prevent use of these */ Events(const Events &); void operator=(Events &); }; /** @} (end of group Event Scheduler) */ #endif /* _EVENT_H_ */ json_table.h 0000644 00000022703 15156036151 0007044 0 ustar 00 #ifndef JSON_TABLE_INCLUDED #define JSON_TABLE_INCLUDED /* Copyright (c) 2020, MariaDB Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <json_lib.h> class Json_table_column; /* The Json_table_nested_path represents the 'current nesting' level for a set of JSON_TABLE columns. Each column (Json_table_column instance) is linked with corresponding 'nested path' object and gets its piece of JSON to parse during the computation phase. The root 'nested_path' is always present as a part of Table_function_json_table, then other 'nested_paths' can be created and linked into a tree structure when new 'NESTED PATH' is met. The nested 'nested_paths' are linked with 'm_nested', the same-level 'nested_paths' are linked with 'm_next_nested'. So for instance JSON_TABLE( '...', '$[*]' COLUMNS( a INT PATH '$.a' , NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$', NESTED PATH '$.c[*]' COLUMNS(x INT PATH '$')), NESTED PATH '$.n[*]' COLUMNS (z INT PATH '$')) results in 4 'nested_path' created: root nested_b nested_c nested_n m_path '$[*]' '$.b[*]' '$.c[*]' '$.n[*] m_nested &nested_b &nested_c NULL NULL n_next_nested NULL &nested_n NULL NULL and 4 columns created: a b x z m_nest &root &nested_b &nested_c &nested_n */ class Json_table_nested_path : public Sql_alloc { public: json_path_t m_path; /* The JSON Path to get the rows from */ bool m_null; // TRUE <=> producing a NULL-complemented row. /*** Construction interface ***/ Json_table_nested_path(): m_null(TRUE), m_nested(NULL), m_next_nested(NULL) {} int set_path(THD *thd, const LEX_CSTRING &path); /*** Methods for performing a scan ***/ void scan_start(CHARSET_INFO *i_cs, const uchar *str, const uchar *end); int scan_next(); bool check_error(const char *str); /*** Members for getting the values we've scanned to ***/ const uchar *get_value() { return m_engine.value_begin; } const uchar *get_value_end() { return m_engine.s.str_end; } /* Counts the rows produced. Used by FOR ORDINALITY columns */ longlong m_ordinality_counter; int print(THD *thd, Field ***f, String *str, List_iterator_fast<Json_table_column> &it, Json_table_column **last_column); private: /* The head of the list of nested NESTED PATH statements. */ Json_table_nested_path *m_nested; /* in the above list items are linked with the */ Json_table_nested_path *m_next_nested; /*** Members describing NESTED PATH structure ***/ /* Parent nested path. The "root" path has this NULL */ Json_table_nested_path *m_parent; /*** Members describing current JSON Path scan state ***/ /* The JSON Parser and JSON Path evaluator */ json_engine_t m_engine; /* The path the parser is currently pointing to */ json_path_t m_cur_path; /* The child NESTED PATH we're currently scanning */ Json_table_nested_path *m_cur_nested; static bool column_in_this_or_nested(const Json_table_nested_path *p, const Json_table_column *jc); friend class Table_function_json_table; }; /* @brief Describes the column definition in JSON_TABLE(...) syntax. @detail Has methods for printing/handling errors but otherwise it's a static object. */ class Json_table_column : public Sql_alloc { public: enum enum_type { FOR_ORDINALITY, PATH, EXISTS_PATH }; enum enum_on_type { ON_EMPTY, ON_ERROR }; enum enum_on_response { RESPONSE_NOT_SPECIFIED, RESPONSE_ERROR, RESPONSE_NULL, RESPONSE_DEFAULT }; struct On_response { public: Json_table_column::enum_on_response m_response; Item *m_default; int respond(Json_table_column *jc, Field *f, uint error_num); int print(const char *name, String *str) const; bool specified() const { return m_response != RESPONSE_NOT_SPECIFIED; } }; enum_type m_column_type; bool m_format_json; json_path_t m_path; On_response m_on_error; On_response m_on_empty; Create_field *m_field; Json_table_nested_path *m_nest; CHARSET_INFO *m_explicit_cs; void set(enum_type ctype) { m_column_type= ctype; } int set(THD *thd, enum_type ctype, const LEX_CSTRING &path, CHARSET_INFO *cs); int set(THD *thd, enum_type ctype, const LEX_CSTRING &path, const Lex_column_charset_collation_attrs_st &cl); Json_table_column(Create_field *f, Json_table_nested_path *nest) : m_field(f), m_nest(nest), m_explicit_cs(NULL) { m_on_error.m_response= RESPONSE_NOT_SPECIFIED; m_on_empty.m_response= RESPONSE_NOT_SPECIFIED; m_format_json= false; } int print(THD *tnd, Field **f, String *str); }; /* Class represents the table function, the function that returns the table as a result so supposed to appear in the FROM list of the SELECT statement. At the moment there is only one such function JSON_TABLE, so the class named after it, but should be refactored into the hierarchy root if we create more of that functions. As the parser finds the table function in the list it creates an instance of Table_function_json_table storing it into the TABLE_LIST::table_function. Then the ha_json_table instance is created based on it in the create_table_for_function(). == Replication: whether JSON_TABLE is deterministic == In sql_yacc.yy, we set BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION whenever JSON_TABLE is used. The reasoning behind this is as follows: In the current MariaDB code, evaluation of JSON_TABLE is deterministic, that is, for a given input string JSON_TABLE will always produce the same set of rows in the same order. However one can think of JSON documents that one can consider indentical which will produce different output. In order to be feature-proof and withstand changes like: - sorting JSON object members by name (like MySQL does) - changing the way duplicate object members are handled we mark the function as SBR-unsafe. (If there is ever an issue with this, marking the function as SBR-safe is a non-intrusive change we will always be able to make) */ class Table_function_json_table : public Sql_alloc { public: /*** Basic properties of the original JSON_TABLE(...) ***/ Item *m_json; /* The JSON value to be parsed. */ /* The COLUMNS(...) part representation. */ Json_table_nested_path m_nested_path; /* The list of table column definitions. */ List<Json_table_column> m_columns; /*** Name resolution functions ***/ bool setup(THD *thd, TABLE_LIST *sql_table, SELECT_LEX *s_lex); int walk_items(Item_processor processor, bool walk_subquery, void *argument); /*** Functions for interaction with the Query Optimizer ***/ void fix_after_pullout(TABLE_LIST *sql_table, st_select_lex *new_parent, bool merge); void update_used_tables() { m_json->update_used_tables(); } table_map used_tables() const { return m_json->used_tables(); } bool join_cache_allowed() const { /* Can use join cache when we have an outside reference. If there's dependency on any other table or randomness, cannot use it. */ return !(used_tables() & ~OUTER_REF_TABLE_BIT); } void get_estimates(ha_rows *out_rows, double *scan_time, double *startup_cost); int print(THD *thd, TABLE_LIST *sql_table, String *str, enum_query_type query_type); /*** Construction interface to be used from the parser ***/ Table_function_json_table(Item *json): m_json(json), m_context_setup_done(false) { cur_parent= &m_nested_path; last_sibling_hook= &m_nested_path.m_nested; } void start_nested_path(Json_table_nested_path *np); void end_nested_path(); Json_table_nested_path *get_cur_nested_path() { return cur_parent; } void set_name_resolution_context(Name_resolution_context *arg) { m_context= arg; } /* SQL Parser: current column in JSON_TABLE (...) syntax */ Json_table_column *m_cur_json_table_column; private: /* Context to be used for resolving the first argument. */ Name_resolution_context *m_context; bool m_context_setup_done; /* Current NESTED PATH level being parsed */ Json_table_nested_path *cur_parent; /* Pointer to the list tail where we add the next NESTED PATH. It points to the cur_parnt->m_nested for the first nested and prev_nested->m_next_nested for the coesequent ones. */ Json_table_nested_path **last_sibling_hook; }; bool push_table_function_arg_context(LEX *lex, MEM_ROOT *alloc); TABLE *create_table_for_function(THD *thd, TABLE_LIST *sql_table); table_map add_table_function_dependencies(List<TABLE_LIST> *join_list, table_map nest_tables, bool *error); #endif /* JSON_TABLE_INCLUDED */ my_service_manager.h 0000644 00000004105 15156036151 0010557 0 ustar 00 /* Copyright (c) 2015 Daniel Black. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MY_SERVICE_MANAGER_INCLUDED #define MY_SERVICE_MANAGER_INCLUDED #if defined(HAVE_SYSTEMD) && !defined(EMBEDDED_LIBRARY) /* sd-daemon.h may include inttypes.h. Explicitly request format macros before the first inclusion of inttypes.h. */ #if !defined(__STDC_FORMAT_MACROS) #define __STDC_FORMAT_MACROS #endif // !defined(__STDC_FORMAT_MACROS) #include <systemd/sd-daemon.h> /** INTERVAL in seconds followed by printf style status */ #define service_manager_extend_timeout(INTERVAL, FMTSTR, ...) \ sd_notifyf(0, "STATUS=" FMTSTR "\nEXTEND_TIMEOUT_USEC=%u\n", ##__VA_ARGS__, INTERVAL * 1000000) /* sd_listen_fds_with_names added v227 however RHEL/Centos7 has v219, fallback to sd_listen_fds */ #ifndef HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES #define sd_listen_fds_with_names(FD, NAMES) sd_listen_fds(FD) #endif #else #define sd_listen_fds(FD) (0) #define sd_listen_fds_with_names(FD, NAMES) (0) #define sd_is_socket_unix(FD, TYPE, LISTENING, PATH, SIZE) (0) #define sd_is_socket_inet(FD, FAMILY, TYPE, LISTENING, PORT) (0) #define SD_LISTEN_FDS_START (0) #define sd_notify(X, Y) #define sd_notifyf(E, F, ...) #if defined (_WIN32) && !defined(EMBEDDED_LIBRARY) #define service_manager_extend_timeout(I, F, ...) \ mysqld_win_extend_service_timeout(I) #else #define service_manager_extend_timeout(I, FMTSTR, ...) #endif #endif #endif /* MY_SERVICE_MANAGER_INCLUDED */ item_windowfunc.h 0000644 00000103374 15156036151 0010131 0 ustar 00 /* Copyright (c) 2016, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ITEM_WINDOWFUNC_INCLUDED #define ITEM_WINDOWFUNC_INCLUDED #include "item.h" class Window_spec; int test_if_group_changed(List<Cached_item> &list); /* A wrapper around test_if_group_changed */ class Group_bound_tracker { public: Group_bound_tracker(THD *thd, SQL_I_List<ORDER> *list) { for (ORDER *curr = list->first; curr; curr=curr->next) { Cached_item *tmp= new_Cached_item(thd, curr->item[0], TRUE); group_fields.push_back(tmp); } } void init() { first_check= true; } /* Check if the current row is in a different group than the previous row this function was called for. XXX: Side-effect: The new row's group becomes the current row's group. Returns true if there is a change between the current_group and the cached value, or if it is the first check after a call to init. */ bool check_if_next_group() { if (test_if_group_changed(group_fields) > -1 || first_check) { first_check= false; return true; } return false; } /* Check if the current row is in a different group than the previous row check_if_next_group was called for. Compares the groups without the additional side effect of updating the current cached values. */ int compare_with_cache() { List_iterator<Cached_item> li(group_fields); Cached_item *ptr; int res; while ((ptr= li++)) { if ((res= ptr->cmp_read_only())) return res; } return 0; } ~Group_bound_tracker() { group_fields.delete_elements(); } private: List<Cached_item> group_fields; /* During the first check_if_next_group, the list of cached_items is not initialized. The compare function will return that the items match if the field's value is the same as the Cached_item's default value (0). This flag makes sure that we always return true during the first check. XXX This is better to be implemented within test_if_group_changed, but since it is used in other parts of the codebase, we keep it here for now. */ bool first_check; }; /* ROW_NUMBER() OVER (...) @detail - This is a Window function (not just an aggregate) - It can be computed by doing one pass over select output, provided the output is sorted according to the window definition. */ class Item_sum_row_number: public Item_sum_int { longlong count; public: Item_sum_row_number(THD *thd) : Item_sum_int(thd), count(0) {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } void clear() override { count= 0; } bool add() override { count++; return false; } void reset_field() override { DBUG_ASSERT(0); } void update_field() override {} enum Sumfunctype sum_func() const override { return ROW_NUMBER_FUNC; } longlong val_int() override { return count; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("row_number") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_row_number>(thd, this); } }; /* RANK() OVER (...) Windowing function @detail - This is a Window function (not just an aggregate) - It can be computed by doing one pass over select output, provided the output is sorted according to the window definition. The function is defined as: "The rank of row R is defined as 1 (one) plus the number of rows that precede R and are not peers of R" "This implies that if two or more rows are not distinct with respect to the window ordering, then there will be one or more" */ class Item_sum_rank: public Item_sum_int { protected: longlong row_number; // just ROW_NUMBER() longlong cur_rank; // current value Group_bound_tracker *peer_tracker; public: Item_sum_rank(THD *thd) : Item_sum_int(thd), peer_tracker(NULL) {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } void clear() override { /* This is called on partition start */ cur_rank= 1; row_number= 0; } bool add() override; longlong val_int() override { return cur_rank; } void reset_field() override { DBUG_ASSERT(0); } void update_field() override {} enum Sumfunctype sum_func () const override { return RANK_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rank") }; return name; } void setup_window_func(THD *thd, Window_spec *window_spec) override; void cleanup() override { if (peer_tracker) { delete peer_tracker; peer_tracker= NULL; } Item_sum_int::cleanup(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_rank>(thd, this); } }; /* DENSE_RANK() OVER (...) Windowing function @detail - This is a Window function (not just an aggregate) - It can be computed by doing one pass over select output, provided the output is sorted according to the window definition. The function is defined as: "If DENSE_RANK is specified, then the rank of row R is defined as the number of rows preceding and including R that are distinct with respect to the window ordering" "This implies that there are no gaps in the sequential rank numbering of rows in each window partition." */ class Item_sum_dense_rank: public Item_sum_int { longlong dense_rank; bool first_add; Group_bound_tracker *peer_tracker; public: /* XXX(cvicentiu) This class could potentially be implemented in the rank class, with a switch for the DENSE case. */ void clear() override { dense_rank= 0; first_add= true; } bool add() override; void reset_field() override { DBUG_ASSERT(0); } void update_field() override {} longlong val_int() override { return dense_rank; } Item_sum_dense_rank(THD *thd) : Item_sum_int(thd), dense_rank(0), first_add(true), peer_tracker(NULL) {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } enum Sumfunctype sum_func () const override { return DENSE_RANK_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("dense_rank") }; return name; } void setup_window_func(THD *thd, Window_spec *window_spec) override; void cleanup() override { if (peer_tracker) { delete peer_tracker; peer_tracker= NULL; } Item_sum_int::cleanup(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_dense_rank>(thd, this); } }; class Item_sum_hybrid_simple : public Item_sum_hybrid { public: Item_sum_hybrid_simple(THD *thd, Item *arg): Item_sum_hybrid(thd, arg), value(NULL) { } Item_sum_hybrid_simple(THD *thd, Item *arg1, Item *arg2): Item_sum_hybrid(thd, arg1, arg2), value(NULL) { } bool add() override; bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override; void setup_hybrid(THD *thd, Item *item); double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; void reset_field() override; String *val_str(String *) override; bool val_native(THD *thd, Native *to) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } void update_field() override; Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table) override; void clear() override { value->clear(); null_value= 1; } private: Item_cache *value; }; /* This item will remember the first value added to it. It will not update the value unless it is cleared. */ class Item_sum_first_value : public Item_sum_hybrid_simple { public: Item_sum_first_value(THD* thd, Item* arg_expr) : Item_sum_hybrid_simple(thd, arg_expr) {} enum Sumfunctype sum_func () const override { return FIRST_VALUE_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("first_value") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_first_value>(thd, this); } }; /* This item will remember the last value added to it. This item does not support removal, and can be cleared only by calling clear(). */ class Item_sum_last_value : public Item_sum_hybrid_simple { public: Item_sum_last_value(THD* thd, Item* arg_expr) : Item_sum_hybrid_simple(thd, arg_expr) {} enum Sumfunctype sum_func() const override { return LAST_VALUE_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("last_value") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_last_value>(thd, this); } }; class Item_sum_nth_value : public Item_sum_hybrid_simple { public: Item_sum_nth_value(THD *thd, Item *arg_expr, Item* offset_expr) : Item_sum_hybrid_simple(thd, arg_expr, offset_expr) {} enum Sumfunctype sum_func() const override { return NTH_VALUE_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("nth_value") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_nth_value>(thd, this); } }; class Item_sum_lead : public Item_sum_hybrid_simple { public: Item_sum_lead(THD *thd, Item *arg_expr, Item* offset_expr) : Item_sum_hybrid_simple(thd, arg_expr, offset_expr) {} enum Sumfunctype sum_func() const override { return LEAD_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("lead") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_lead>(thd, this); } }; class Item_sum_lag : public Item_sum_hybrid_simple { public: Item_sum_lag(THD *thd, Item *arg_expr, Item* offset_expr) : Item_sum_hybrid_simple(thd, arg_expr, offset_expr) {} enum Sumfunctype sum_func() const override { return LAG_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("lag") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_lag>(thd, this); } }; class Partition_row_count { public: Partition_row_count() :partition_row_count_(0) { } void set_partition_row_count(ulonglong count) { partition_row_count_ = count; } double calc_val_real(bool *null_value, ulonglong current_row_count) { if ((*null_value= (partition_row_count_ == 0))) return 0; return static_cast<double>(current_row_count) / partition_row_count_; } protected: longlong get_row_count() { return partition_row_count_; } ulonglong partition_row_count_; }; class Current_row_count { public: Current_row_count() :current_row_count_(0) { } protected: ulonglong get_row_number() { return current_row_count_ ; } ulonglong current_row_count_; }; /* @detail "The relative rank of a row R is defined as (RK-1)/(NR-1), where RK is defined to be the RANK of R and NR is defined to be the number of rows in the window partition of R." Computation of this function requires two passes: - First pass to find #rows in the partition This is held within the row_count context. - Second pass to compute rank of current row and the value of the function */ class Item_sum_percent_rank: public Item_sum_double, public Partition_row_count { public: Item_sum_percent_rank(THD *thd) : Item_sum_double(thd), cur_rank(1), peer_tracker(NULL) {} longlong val_int() override { /* Percent rank is a real value so calling the integer value should never happen. It makes no sense as it gets truncated to either 0 or 1. */ DBUG_ASSERT(0); return 0; } double val_real() override { /* We can not get the real value without knowing the number of rows in the partition. Don't divide by 0. */ ulonglong partition_rows = get_row_count(); null_value= partition_rows > 0 ? false : true; return partition_rows > 1 ? static_cast<double>(cur_rank - 1) / (partition_rows - 1) : 0; } enum Sumfunctype sum_func () const override { return PERCENT_RANK_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("percent_rank") }; return name; } void update_field() override {} void clear() override { cur_rank= 1; row_number= 0; } bool add() override; const Type_handler *type_handler() const override { return &type_handler_double; } bool fix_length_and_dec(THD *thd) override { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. return FALSE; } void setup_window_func(THD *thd, Window_spec *window_spec) override; void reset_field() override { DBUG_ASSERT(0); } void set_partition_row_count(ulonglong count) override { Partition_row_count::set_partition_row_count(count); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_percent_rank>(thd, this); } private: longlong cur_rank; // Current rank of the current row. longlong row_number; // Value if this were ROW_NUMBER() function. Group_bound_tracker *peer_tracker; void cleanup() override { if (peer_tracker) { delete peer_tracker; peer_tracker= NULL; } Item_sum_num::cleanup(); } }; /* @detail "The relative rank of a row R is defined as NP/NR, where - NP is defined to be the number of rows preceding or peer with R in the window ordering of the window partition of R - NR is defined to be the number of rows in the window partition of R. Just like with Item_sum_percent_rank, computation of this function requires two passes. */ class Item_sum_cume_dist: public Item_sum_double, public Partition_row_count, public Current_row_count { public: Item_sum_cume_dist(THD *thd) :Item_sum_double(thd) { } Item_sum_cume_dist(THD *thd, Item *arg) :Item_sum_double(thd, arg) { } double val_real() override { return calc_val_real(&null_value, current_row_count_); } bool add() override { current_row_count_++; return false; } enum Sumfunctype sum_func() const override { return CUME_DIST_FUNC; } void clear() override { current_row_count_= 0; partition_row_count_= 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cume_dist") }; return name; } void update_field() override {} const Type_handler *type_handler() const override { return &type_handler_double; } bool fix_length_and_dec(THD *thd) override { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. return FALSE; } void reset_field() override { DBUG_ASSERT(0); } void set_partition_row_count(ulonglong count) override { Partition_row_count::set_partition_row_count(count); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_cume_dist>(thd, this); } }; class Item_sum_ntile : public Item_sum_int, public Partition_row_count, public Current_row_count { public: Item_sum_ntile(THD* thd, Item* num_quantiles_expr) : Item_sum_int(thd, num_quantiles_expr), n_old_val_(0) { } longlong val_int() override { if (get_row_count() == 0) { null_value= true; return 0; } longlong num_quantiles= get_num_quantiles(); if (num_quantiles <= 0 || (static_cast<ulonglong>(num_quantiles) != n_old_val_ && n_old_val_ > 0)) { my_error(ER_INVALID_NTILE_ARGUMENT, MYF(0)); return true; } n_old_val_= static_cast<ulonglong>(num_quantiles); null_value= false; ulonglong quantile_size = get_row_count() / num_quantiles; ulonglong extra_rows = get_row_count() - quantile_size * num_quantiles; if (current_row_count_ <= extra_rows * (quantile_size + 1)) return (current_row_count_ - 1) / (quantile_size + 1) + 1; return (current_row_count_ - 1 - extra_rows) / quantile_size + 1; } bool add() override { current_row_count_++; return false; } enum Sumfunctype sum_func() const override { return NTILE_FUNC; } void clear() override { current_row_count_= 0; partition_row_count_= 0; n_old_val_= 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ntile") }; return name; } void update_field() override {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } void reset_field() override { DBUG_ASSERT(0); } void set_partition_row_count(ulonglong count) override { Partition_row_count::set_partition_row_count(count); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_ntile>(thd, this); } private: longlong get_num_quantiles() { return args[0]->val_int(); } ulonglong n_old_val_; }; class Item_sum_percentile_disc : public Item_sum_num, public Type_handler_hybrid_field_type, public Partition_row_count, public Current_row_count { public: Item_sum_percentile_disc(THD *thd, Item* arg) : Item_sum_num(thd, arg), Type_handler_hybrid_field_type(&type_handler_slonglong), value(NULL), val_calculated(FALSE), first_call(TRUE), prev_value(0), order_item(NULL){} double val_real() override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return 0; } null_value= false; return value->val_real(); } longlong val_int() override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return 0; } null_value= false; return value->val_int(); } my_decimal* val_decimal(my_decimal* dec) override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return 0; } null_value= false; return value->val_decimal(dec); } String* val_str(String *str) override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return 0; } null_value= false; return value->val_str(str); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return true; } null_value= false; return value->get_date(thd, ltime, fuzzydate); } bool val_native(THD *thd, Native *to) override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return true; } null_value= false; return value->val_native(thd, to); } bool add() override { Item *arg= get_arg(0); if (arg->is_null()) return false; if (first_call) { prev_value= arg->val_real(); if (prev_value > 1 || prev_value < 0) { my_error(ER_ARGUMENT_OUT_OF_RANGE, MYF(0), func_name()); return true; } first_call= false; } double arg_val= arg->val_real(); if (prev_value != arg_val) { my_error(ER_ARGUMENT_NOT_CONSTANT, MYF(0), func_name()); return true; } if (val_calculated) return false; value->store(order_item); value->cache_value(); if (value->null_value) return false; current_row_count_++; double val= calc_val_real(&null_value, current_row_count_); if (val >= prev_value && !val_calculated) val_calculated= true; return false; } enum Sumfunctype sum_func() const override { return PERCENTILE_DISC_FUNC; } void clear() override { val_calculated= false; first_call= true; value->clear(); partition_row_count_= 0; current_row_count_= 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("percentile_disc") }; return name; } void update_field() override {} const Type_handler *type_handler() const override {return Type_handler_hybrid_field_type::type_handler();} bool fix_length_and_dec(THD *thd) override { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. return FALSE; } void reset_field() override { DBUG_ASSERT(0); } void set_partition_row_count(ulonglong count) override { Partition_row_count::set_partition_row_count(count); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_percentile_disc>(thd, this); } public: void setup_window_func(THD *thd, Window_spec *window_spec) override; void setup_hybrid(THD *thd, Item *item); bool fix_fields(THD *thd, Item **ref) override; private: Item_cache *value; bool val_calculated; bool first_call; double prev_value; Item *order_item; }; class Item_sum_percentile_cont : public Item_sum_double, public Partition_row_count, public Current_row_count { public: Item_sum_percentile_cont(THD *thd, Item* arg) : Item_sum_double(thd, arg), floor_value(NULL), ceil_value(NULL), first_call(TRUE),prev_value(0), ceil_val_calculated(FALSE), floor_val_calculated(FALSE), order_item(NULL){} double val_real() override { if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; return 0; } null_value= false; double val= 1 + prev_value * (get_row_count()-1); /* Applying the formula to get the value If (CRN = FRN = RN) then the result is (value of expression from row at RN) Otherwise the result is (CRN - RN) * (value of expression for row at FRN) + (RN - FRN) * (value of expression for row at CRN) */ if(ceil(val) == floor(val)) return floor_value->val_real(); double ret_val= ((val - floor(val)) * ceil_value->val_real()) + ((ceil(val) - val) * floor_value->val_real()); return ret_val; } bool add() override { Item *arg= get_arg(0); if (arg->is_null()) return false; if (first_call) { first_call= false; prev_value= arg->val_real(); if (prev_value > 1 || prev_value < 0) { my_error(ER_ARGUMENT_OUT_OF_RANGE, MYF(0), func_name()); return true; } } double arg_val= arg->val_real(); if (prev_value != arg_val) { my_error(ER_ARGUMENT_NOT_CONSTANT, MYF(0), func_name()); return true; } if (!floor_val_calculated) { floor_value->store(order_item); floor_value->cache_value(); if (floor_value->null_value) return false; } if (floor_val_calculated && !ceil_val_calculated) { ceil_value->store(order_item); ceil_value->cache_value(); if (ceil_value->null_value) return false; } current_row_count_++; double val= 1 + prev_value * (get_row_count()-1); if (!floor_val_calculated && get_row_number() == floor(val)) floor_val_calculated= true; if (!ceil_val_calculated && get_row_number() == ceil(val)) ceil_val_calculated= true; return false; } enum Sumfunctype sum_func() const override { return PERCENTILE_CONT_FUNC; } void clear() override { first_call= true; floor_value->clear(); ceil_value->clear(); floor_val_calculated= false; ceil_val_calculated= false; partition_row_count_= 0; current_row_count_= 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("percentile_cont") }; return name; } void update_field() override {} bool fix_length_and_dec(THD *thd) override { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. return FALSE; } void reset_field() override { DBUG_ASSERT(0); } void set_partition_row_count(ulonglong count) override { Partition_row_count::set_partition_row_count(count); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_sum_percentile_cont>(thd, this); } public: void setup_window_func(THD *thd, Window_spec *window_spec) override; void setup_hybrid(THD *thd, Item *item); bool fix_fields(THD *thd, Item **ref) override; private: Item_cache *floor_value; Item_cache *ceil_value; bool first_call; double prev_value; bool ceil_val_calculated; bool floor_val_calculated; Item *order_item; }; class Item_window_func : public Item_func_or_sum { /* Window function parameters as we've got them from the parser */ public: LEX_CSTRING *window_name; public: Window_spec *window_spec; public: Item_window_func(THD *thd, Item_sum *win_func, LEX_CSTRING *win_name) : Item_func_or_sum(thd, (Item *) win_func), window_name(win_name), window_spec(NULL), force_return_blank(true), read_value_from_result_field(false) {} Item_window_func(THD *thd, Item_sum *win_func, Window_spec *win_spec) : Item_func_or_sum(thd, (Item *) win_func), window_name(NULL), window_spec(win_spec), force_return_blank(true), read_value_from_result_field(false) {} Item_sum *window_func() const { return (Item_sum *) args[0]; } void update_used_tables() override; /* This is used by filesort to mark the columns it needs to read (because they participate in the sort criteria and/or row retrieval. Window functions can only be used in sort criteria). Sorting by window function value is only done after the window functions have been computed. In that case, window function will need to read its temp.table field. In order to allow that, mark that field in the read_set. */ bool register_field_in_read_map(void *arg) override { TABLE *table= (TABLE*) arg; if (result_field && (result_field->table == table || !table)) { bitmap_set_bit(result_field->table->read_set, result_field->field_index); } return 0; } bool is_frame_prohibited() const { switch (window_func()->sum_func()) { case Item_sum::ROW_NUMBER_FUNC: case Item_sum::RANK_FUNC: case Item_sum::DENSE_RANK_FUNC: case Item_sum::PERCENT_RANK_FUNC: case Item_sum::CUME_DIST_FUNC: case Item_sum::NTILE_FUNC: case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: return true; default: return false; } } bool requires_special_cursors() const { switch (window_func()->sum_func()) { case Item_sum::FIRST_VALUE_FUNC: case Item_sum::LAST_VALUE_FUNC: case Item_sum::NTH_VALUE_FUNC: case Item_sum::LAG_FUNC: case Item_sum::LEAD_FUNC: return true; default: return false; } } bool requires_partition_size() const { switch (window_func()->sum_func()) { case Item_sum::PERCENT_RANK_FUNC: case Item_sum::CUME_DIST_FUNC: case Item_sum::NTILE_FUNC: case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: return true; default: return false; } } bool requires_peer_size() const { switch (window_func()->sum_func()) { case Item_sum::CUME_DIST_FUNC: return true; default: return false; } } bool is_order_list_mandatory() const { switch (window_func()->sum_func()) { case Item_sum::RANK_FUNC: case Item_sum::DENSE_RANK_FUNC: case Item_sum::PERCENT_RANK_FUNC: case Item_sum::CUME_DIST_FUNC: case Item_sum::LAG_FUNC: case Item_sum::LEAD_FUNC: case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: return true; default: return false; } } bool only_single_element_order_list() const { switch (window_func()->sum_func()){ case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: return true; default: return false; } } bool check_result_type_of_order_item(); /* Computation functions. TODO: consoder merging these with class Group_bound_tracker. */ void setup_partition_border_check(THD *thd); const Type_handler *type_handler() const override { return ((Item_sum *) args[0])->type_handler(); } enum Item::Type type() const override { return Item::WINDOW_FUNC_ITEM; } private: /* Window functions are very special functions, so val_() methods have special meaning for them: - Phase#1, "Initial" we run the join and put its result into temporary table. For window functions, we write the default value (NULL?) as a placeholder. - Phase#2: "Computation": executor does the scan in {PARTITION, ORDER BY} order of this window function. It calls appropriate methods to inform the window function about rows entering/leaving the window. It calls window_func()->val_int() so that current window function value can be saved and stored in the temp.table. - Phase#3: "Retrieval" the temporary table is read and passed to query output. However, Item_window_func still remains in the select list, so item_windowfunc->val_int() will be called. During Phase#3, read_value_from_result_field= true. */ bool force_return_blank; bool read_value_from_result_field; void print_for_percentile_functions(String *str, enum_query_type query_type); public: void set_phase_to_initial() { force_return_blank= true; read_value_from_result_field= false; } void set_phase_to_computation() { force_return_blank= false; read_value_from_result_field= false; } void set_phase_to_retrieval() { force_return_blank= false; read_value_from_result_field= true; } bool is_null() override { if (force_return_blank) return true; if (read_value_from_result_field) return result_field->is_null(); return window_func()->is_null(); } double val_real() override { double res; if (force_return_blank) { res= 0.0; null_value= true; } else if (read_value_from_result_field) { res= result_field->val_real(); null_value= result_field->is_null(); } else { res= window_func()->val_real(); null_value= window_func()->null_value; } return res; } longlong val_int() override { longlong res; if (force_return_blank) { res= 0; null_value= true; } else if (read_value_from_result_field) { res= result_field->val_int(); null_value= result_field->is_null(); } else { res= window_func()->val_int(); null_value= window_func()->null_value; } return res; } String* val_str(String* str) override { String *res; if (force_return_blank) { null_value= true; res= NULL; } else if (read_value_from_result_field) { if ((null_value= result_field->is_null())) res= NULL; else res= result_field->val_str(str); } else { res= window_func()->val_str(str); null_value= window_func()->null_value; } return res; } bool val_native(THD *thd, Native *to) override { if (force_return_blank) return null_value= true; if (read_value_from_result_field) return val_native_from_field(result_field, to); return val_native_from_item(thd, window_func(), to); } my_decimal* val_decimal(my_decimal* dec) override { my_decimal *res; if (force_return_blank) { null_value= true; res= NULL; } else if (read_value_from_result_field) { if ((null_value= result_field->is_null())) res= NULL; else res= result_field->val_decimal(dec); } else { res= window_func()->val_decimal(dec); null_value= window_func()->null_value; } return res; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { bool res; if (force_return_blank) { null_value= true; res= true; } else if (read_value_from_result_field) { if ((null_value= result_field->is_null())) res= true; else res= result_field->get_date(ltime, fuzzydate); } else { res= window_func()->get_date(thd, ltime, fuzzydate); null_value= window_func()->null_value; } return res; } void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override; bool fix_length_and_dec(THD *thd) override { Type_std_attributes::set(window_func()); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("WF") }; return name; } bool fix_fields(THD *thd, Item **ref) override; bool resolve_window_name(THD *thd); void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; #endif /* ITEM_WINDOWFUNC_INCLUDED */ sql_repl.h 0000644 00000005772 15156036151 0006554 0 ustar 00 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_REPL_INCLUDED #define SQL_REPL_INCLUDED #include "rpl_filter.h" #ifdef HAVE_REPLICATION #include "slave.h" struct slave_connection_state; extern my_bool opt_show_slave_auth_info; extern char *master_host, *master_info_file; extern int max_binlog_dump_events; extern my_bool opt_sporadic_binlog_dump_fail; int start_slave(THD* thd, Master_info* mi, bool net_report); int stop_slave(THD* thd, Master_info* mi, bool net_report); bool change_master(THD* thd, Master_info* mi, bool *master_info_added); bool mysql_show_binlog_events(THD* thd); int reset_slave(THD *thd, Master_info* mi); int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len, ulong next_log_number); bool purge_master_logs(THD* thd, const char* to_log); bool purge_master_logs_before_date(THD* thd, time_t purge_time); int log_in_use(const char* log_name, uint min_connections); void adjust_linfo_offsets(my_off_t purge_offset); void show_binlogs_get_fields(THD *thd, List<Item> *field_list); bool show_binlogs(THD* thd); extern int init_master_info(Master_info* mi); bool kill_zombie_dump_threads(THD *thd, uint32 slave_server_id); int check_binlog_magic(IO_CACHE* log, const char** errmsg); int compare_log_name(const char *log_1, const char *log_2); struct LOAD_FILE_IO_CACHE : public IO_CACHE { THD* thd; my_off_t last_pos_in_file; bool wrote_create_file, log_delayed; int (*real_read_function)(struct st_io_cache *,uchar *,size_t); }; int log_loaded_block(IO_CACHE* file, uchar *Buffer, size_t Count); int init_replication_sys_vars(); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state; #endif void rpl_init_gtid_slave_state(); void rpl_deinit_gtid_slave_state(); void rpl_init_gtid_waiting(); void rpl_deinit_gtid_waiting(); int gtid_state_from_binlog_pos(const char *name, uint32 pos, String *out_str); int rpl_append_gtid_state(String *dest, bool use_binlog); int rpl_load_gtid_state(slave_connection_state *state, bool use_binlog); bool rpl_gtid_pos_check(THD *thd, char *str, size_t len); bool rpl_gtid_pos_update(THD *thd, char *str, size_t len); #else struct LOAD_FILE_IO_CACHE : public IO_CACHE { }; #endif /* HAVE_REPLICATION */ #endif /* SQL_REPL_INCLUDED */ lex_ident.h 0000644 00000012233 15156036151 0006674 0 ustar 00 #ifndef LEX_IDENT_INCLUDED #define LEX_IDENT_INCLUDED /* Copyright (c) 2023, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "char_buffer.h" extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset; /* Identifiers for the database objects stored on disk, e.g. databases, tables, triggers. */ class Lex_ident_fs: public LEX_CSTRING { public: Lex_ident_fs() :LEX_CSTRING({0,0}) { } Lex_ident_fs(const char *str, size_t length) :LEX_CSTRING({str, length}) { } explicit Lex_ident_fs(const LEX_CSTRING &str) :LEX_CSTRING(str) { } static bool check_body(const char *name, size_t length, bool disallow_path_chars); bool check_db_name() const; bool check_db_name_with_error() const; #ifndef DBUG_OFF bool is_in_lower_case() const; bool ok_for_lower_case_names() const; #endif #if MYSQL_VERSION_ID<=110501 private: static bool is_valid_ident(const LEX_CSTRING &str) { // NULL identifier, or 0-terminated identifier return (str.str == NULL && str.length == 0) || str.str[str.length] == 0; } public: static CHARSET_INFO *charset_info() { return table_alias_charset; } bool streq(const LEX_CSTRING &rhs) const { DBUG_ASSERT(is_valid_ident(*this)); DBUG_ASSERT(is_valid_ident(rhs)); return length == rhs.length && my_strcasecmp(charset_info(), str, rhs.str) == 0; } #else /* Starting from 11.5.1 streq() is inherited from the base. The above implementations of charset_info(), streq() and is_valid_ident() should be removed. */ #error Remove streq() above. #endif // MYSQL_VERSION_ID<=110501 }; /** A valid database name identifier, checked with check_db_name(). It's not known if it was lower-cased or is in the user typed way. */ class Lex_ident_db: public Lex_ident_fs { bool is_null() const { return length == 0 && str == NULL; } // {empty_c_string,0} is used by derived tables bool is_empty() const { return length == 0 && str != NULL; } public: Lex_ident_db() :Lex_ident_fs(NULL, 0) { } explicit Lex_ident_db(const LEX_CSTRING &str) :Lex_ident_fs(str) { DBUG_SLOW_ASSERT(is_null() || is_empty() || !check_db_name()); } Lex_ident_db(const char *str, size_t length) :Lex_ident_fs(str, length) { DBUG_SLOW_ASSERT(is_null() || is_empty() || !check_db_name()); } }; /** A normalized database name: - checked with check_db_name() - lower-cased if lower_case_table_names>0 */ class Lex_ident_db_normalized: public Lex_ident_db { public: Lex_ident_db_normalized(const char *str, size_t length) :Lex_ident_db(str, length) { DBUG_SLOW_ASSERT(ok_for_lower_case_names()); } explicit Lex_ident_db_normalized(const LEX_CSTRING &str) :Lex_ident_db(str.str, str.length) { DBUG_SLOW_ASSERT(ok_for_lower_case_names()); } }; class Lex_ident_table: public Lex_ident_fs { public: using Lex_ident_fs::Lex_ident_fs; }; template<size_t buff_sz> class IdentBuffer: public CharBuffer<buff_sz> { constexpr static CHARSET_INFO *charset() { return &my_charset_utf8mb3_general_ci; } public: IdentBuffer() { } IdentBuffer<buff_sz> & copy_casedn(const LEX_CSTRING &str) { CharBuffer<buff_sz>::copy_casedn(charset(), str); return *this; } }; template<size_t buff_sz> class IdentBufferCasedn: public IdentBuffer<buff_sz> { public: IdentBufferCasedn(const LEX_CSTRING &str) { IdentBuffer<buff_sz>::copy_casedn(str); } }; /* A helper class to store temporary database names in a buffer. After constructing it's typically should be checked using Lex_ident_fs::check_db_name(). Note, the database name passed to the constructor can originally come from the parser and can be of an atribtrary long length. Let's reserve additional buffer space for one extra character (SYSTEM_CHARSET_MBMAXLEN bytes), so check_db_name() can still detect too long names even if the constructor cuts the data. */ class DBNameBuffer: public CharBuffer<SAFE_NAME_LEN + MY_CS_MBMAXLEN> { public: DBNameBuffer() { } DBNameBuffer(const LEX_CSTRING &db, bool casedn) { copy_casedn(&my_charset_utf8mb3_general_ci, db, casedn); } Lex_ident_db to_lex_ident_db() const { const LEX_CSTRING tmp= to_lex_cstring(); if (Lex_ident_fs(tmp).check_db_name()) return Lex_ident_db(); return Lex_ident_db(tmp.str, tmp.length); } Lex_ident_db to_lex_ident_db_with_error() const { const LEX_CSTRING tmp= to_lex_cstring(); if (Lex_ident_fs(tmp).check_db_name_with_error()) return Lex_ident_db(); return Lex_ident_db(tmp.str, tmp.length); } }; #endif // LEX_IDENT_INCLUDED rpl_reporting.h 0000644 00000007201 15156036151 0007606 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_REPORTING_H #define RPL_REPORTING_H #include <my_sys.h> /* loglevel */ /** Maximum size of an error message from a slave thread. */ #define MAX_SLAVE_ERRMSG 1024 /** Mix-in to handle the message logging and reporting for relay log info and master log info structures. By inheriting from this class, the class is imbued with capabilities to do slave reporting. */ class Slave_reporting_capability { public: /** lock used to synchronize m_last_error on 'SHOW SLAVE STATUS' **/ mutable mysql_mutex_t err_lock; /** Constructor. @param thread_name Printable name of the slave thread that is reporting. */ Slave_reporting_capability(char const *thread_name); mutable my_thread_id err_thread_id; /** Writes a message and, if it's an error message, to Last_Error (which will be displayed by SHOW SLAVE STATUS). @param level The severity level @param err_code The error code @param msg The message (usually related to the error code, but can contain more information), in printf() format. */ void report(loglevel level, int err_code, const char *extra_info, const char *msg, ...) const ATTRIBUTE_FORMAT(printf, 5, 6); /** Clear errors. They will not show up under <code>SHOW SLAVE STATUS</code>. */ void clear_error() { mysql_mutex_lock(&err_lock); m_last_error.clear(); mysql_mutex_unlock(&err_lock); } /** Error information structure. */ class Error { friend class Slave_reporting_capability; public: Error() { clear(); } void clear() { number= 0; message[0]= '\0'; timestamp[0]= '\0'; } void update_timestamp() { struct tm tm_tmp; struct tm *start; skr= my_time(0); localtime_r(&skr, &tm_tmp); start=&tm_tmp; snprintf(timestamp, sizeof(timestamp), "%02d%02d%02d %02d:%02d:%02d", start->tm_year % 100, start->tm_mon+1, start->tm_mday, start->tm_hour, start->tm_min, start->tm_sec); timestamp[15]= '\0'; } /** Error code */ uint32 number; /** Error message */ char message[MAX_SLAVE_ERRMSG]; /** Error timestamp as string */ char timestamp[64]; /** Error timestamp as time_t variable. Used in performance_schema */ time_t skr; }; Error const& last_error() const { return m_last_error; } virtual ~Slave_reporting_capability()= 0; private: /** Last error produced by the I/O or SQL thread respectively. */ mutable Error m_last_error; char const *const m_thread_name; // not implemented Slave_reporting_capability(const Slave_reporting_capability& rhs); Slave_reporting_capability& operator=(const Slave_reporting_capability& rhs); }; #endif // RPL_REPORTING_H sql_prepare.h 0000644 00000026626 15156036151 0007251 0 ustar 00 #ifndef SQL_PREPARE_H #define SQL_PREPARE_H /* Copyright (c) 1995-2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_error.h" #define LAST_STMT_ID 0xFFFFFFFF #define STMT_ID_MASK 0x7FFFFFFF class THD; struct LEX; /** An interface that is used to take an action when the locking module notices that a table version has changed since the last execution. "Table" here may refer to any kind of table -- a base table, a temporary table, a view or an information schema table. When we open and lock tables for execution of a prepared statement, we must verify that they did not change since statement prepare. If some table did change, the statement parse tree *may* be no longer valid, e.g. in case it contains optimizations that depend on table metadata. This class provides an interface (a method) that is invoked when such a situation takes place. The implementation of the method simply reports an error, but the exact details depend on the nature of the SQL statement. At most 1 instance of this class is active at a time, in which case THD::m_reprepare_observer is not NULL. @sa check_and_update_table_version() for details of the version tracking algorithm @sa Open_tables_state::m_reprepare_observer for the life cycle of metadata observers. */ class Reprepare_observer { public: /** Check if a change of metadata is OK. In future the signature of this method may be extended to accept the old and the new versions, but since currently the check is very simple, we only need the THD to report an error. */ bool report_error(THD *thd); bool is_invalidated() const { return m_invalidated; } void reset_reprepare_observer() { m_invalidated= FALSE; } bool can_retry() const { // The method must be called only for a statement that is invalidated assert(is_invalidated()); return m_attempt <= MAX_REPREPARE_ATTEMPTS; } private: bool m_invalidated{false}; int m_attempt{0}; static const int MAX_REPREPARE_ATTEMPTS= 3; }; void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length); void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length); void mysqld_stmt_execute_bulk(THD *thd, char *packet, uint packet_length); void mysqld_stmt_bulk_execute(THD *thd, char *packet, uint packet_length); void mysqld_stmt_close(THD *thd, char *packet); void mysql_sql_stmt_prepare(THD *thd); void mysql_sql_stmt_execute(THD *thd); void mysql_sql_stmt_execute_immediate(THD *thd); void mysql_sql_stmt_close(THD *thd); void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length); void mysqld_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); void reinit_stmt_before_use(THD *thd, LEX *lex); my_bool bulk_parameters_iterations(THD *thd); my_bool bulk_parameters_set(THD *thd); /** Execute a fragment of server code in an isolated context, so that it doesn't leave any effect on THD. THD must have no open tables. The code must not leave any open tables around. The result of execution (if any) is stored in Ed_result. */ class Server_runnable { public: virtual bool execute_server_code(THD *thd)= 0; virtual ~Server_runnable(); }; /** Execute direct interface. @todo Implement support for prelocked mode. */ class Ed_row; /** Ed_result_set -- a container with result set rows. @todo Implement support for result set metadata and automatic type conversion. */ class Ed_result_set { public: operator List<Ed_row>&() { return *m_rows; } unsigned int size() const { return m_rows->elements; } Ed_result_set(List<Ed_row> *rows_arg, size_t column_count, MEM_ROOT *mem_root_arg); /** We don't call member destructors, they all are POD types. */ ~Ed_result_set() = default; size_t get_field_count() const { return m_column_count; } static void *operator new(size_t size, MEM_ROOT *mem_root) { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) throw (); static void operator delete(void *, MEM_ROOT *){} private: Ed_result_set(const Ed_result_set &); /* not implemented */ Ed_result_set &operator=(Ed_result_set &); /* not implemented */ private: MEM_ROOT m_mem_root; size_t m_column_count; List<Ed_row> *m_rows; Ed_result_set *m_next_rset; friend class Ed_connection; }; class Ed_connection { public: /** Construct a new "execute direct" connection. The connection can be used to execute SQL statements. If the connection failed to initialize, the error will be returned on the attempt to execute a statement. @pre thd must have no open tables while the connection is used. However, Ed_connection works okay in LOCK TABLES mode. Other properties of THD, such as the current warning information, errors, etc. do not matter and are preserved by Ed_connection. One thread may have many Ed_connections created for it. */ Ed_connection(THD *thd); /** Execute one SQL statement. Until this method is executed, no other methods of Ed_connection can be used. Life cycle of Ed_connection is: Initialized -> a statement has been executed -> look at result, move to next result -> look at result, move to next result -> ... moved beyond the last result == Initialized. This method can be called repeatedly. Once it's invoked, results of the previous execution are lost. A result of execute_direct() can be either: - success, no result set rows. In this case get_field_count() returns 0. This happens after execution of INSERT, UPDATE, DELETE, DROP and similar statements. Some other methods, such as get_affected_rows() can be used to retrieve additional result information. - success, there are some result set rows (maybe 0). E.g. happens after SELECT. In this case get_field_count() returns the number of columns in a result set and store_result() can be used to retrieve a result set.. - an error, methods to retrieve error information can be used. @return execution status @retval FALSE success, use get_field_count() to determine what to do next. @retval TRUE error, use get_last_error() to see the error number. */ bool execute_direct(Protocol *p, LEX_STRING sql_text); /** Same as the previous, but takes an instance of Server_runnable instead of SQL statement text. @return execution status @retval FALSE success, use get_field_count() if your code fragment is supposed to return a result set @retval TRUE failure */ bool execute_direct(Protocol *p, Server_runnable *server_runnable); /** Get the number of affected (deleted, updated) rows for the current statement. Can be used for statements with get_field_count() == 0. @sa Documentation for C API function mysql_affected_rows(). */ ulonglong get_affected_rows() const { return m_diagnostics_area.affected_rows(); } /** Get the last insert id, if any. @sa Documentation for mysql_insert_id(). */ ulonglong get_last_insert_id() const { return m_diagnostics_area.last_insert_id(); } /** Get the total number of warnings for the last executed statement. Note, that there is only one warning list even if a statement returns multiple results. @sa Documentation for C API function mysql_num_warnings(). */ ulong get_warn_count() const { return m_diagnostics_area.warn_count(); } /** The following members are only valid if execute_direct() or move_to_next_result() returned an error. They never fail, but if they are called when there is no result, or no error, the result is not defined. */ const char *get_last_error() const { return m_diagnostics_area.message(); } unsigned int get_last_errno() const { return m_diagnostics_area.sql_errno(); } const char *get_last_sqlstate() const { return m_diagnostics_area.get_sqlstate(); } /** Provided get_field_count() is not 0, this never fails. You don't need to free the result set, this is done automatically when you advance to the next result set or destroy the connection. Not returning const because of List iterator not accepting Should be used when you would like Ed_connection to manage result set memory for you. */ Ed_result_set *use_result_set() { return m_current_rset; } /** Provided get_field_count() is not 0, this never fails. You must free the returned result set. This can be called only once after execute_direct(). Should be used when you would like to get the results and destroy the connection. */ Ed_result_set *store_result_set(); /** If the query returns multiple results, this method can be checked if there is another result beyond the next one. Never fails. */ bool has_next_result() const { return MY_TEST(m_current_rset->m_next_rset); } /** Only valid to call if has_next_result() returned true. Otherwise the result is undefined. */ bool move_to_next_result() { m_current_rset= m_current_rset->m_next_rset; return MY_TEST(m_current_rset); } ~Ed_connection() { free_old_result(); } private: Diagnostics_area m_diagnostics_area; /** Execute direct interface does not support multi-statements, only multi-results. So we never have a situation when we have a mix of result sets and OK or error packets. We either have a single result set, a single error, or a single OK, or we have a series of result sets, followed by an OK or error. */ THD *m_thd; Ed_result_set *m_rsets; Ed_result_set *m_current_rset; private: void free_old_result(); void add_result_set(Ed_result_set *ed_result_set); private: Ed_connection(const Ed_connection &); /* not implemented */ Ed_connection &operator=(Ed_connection &); /* not implemented */ }; /** One result set column. */ struct Ed_column: public LEX_STRING { /** Implementation note: destructor for this class is never called. */ }; /** One result set record. */ class Ed_row: public Sql_alloc { public: const Ed_column &operator[](const unsigned int column_index) const { return *get_column(column_index); } const Ed_column *get_column(const unsigned int column_index) const { DBUG_ASSERT(column_index < size()); return m_column_array + column_index; } size_t size() const { return m_column_count; } Ed_row(Ed_column *column_array_arg, size_t column_count_arg) :m_column_array(column_array_arg), m_column_count(column_count_arg) {} private: Ed_column *m_column_array; size_t m_column_count; /* TODO: change to point to metadata */ }; extern Atomic_counter<uint32_t> local_connection_thread_count; #endif // SQL_PREPARE_H hostname.h 0000644 00000012453 15156036151 0006543 0 ustar 00 /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef HOSTNAME_INCLUDED #define HOSTNAME_INCLUDED #include "my_net.h" #include "hash_filo.h" struct Host_errors { public: Host_errors(); ~Host_errors(); void reset(); void aggregate(const Host_errors *errors); /** Number of connect errors. */ ulong m_connect; /** Number of host blocked errors. */ ulong m_host_blocked; /** Number of transient errors from getnameinfo(). */ ulong m_nameinfo_transient; /** Number of permanent errors from getnameinfo(). */ ulong m_nameinfo_permanent; /** Number of errors from is_hostname_valid(). */ ulong m_format; /** Number of transient errors from getaddrinfo(). */ ulong m_addrinfo_transient; /** Number of permanent errors from getaddrinfo(). */ ulong m_addrinfo_permanent; /** Number of errors from Forward-Confirmed reverse DNS checks. */ ulong m_FCrDNS; /** Number of errors from host grants. */ ulong m_host_acl; /** Number of errors from missing auth plugin. */ ulong m_no_auth_plugin; /** Number of errors from auth plugin. */ ulong m_auth_plugin; /** Number of errors from authentication plugins. */ ulong m_handshake; /** Number of errors from proxy user. */ ulong m_proxy_user; /** Number of errors from proxy user acl. */ ulong m_proxy_user_acl; /** Number of errors from authentication. */ ulong m_authentication; /** Number of errors from ssl. */ ulong m_ssl; /** Number of errors from max user connection. */ ulong m_max_user_connection; /** Number of errors from max user connection per hour. */ ulong m_max_user_connection_per_hour; /** Number of errors from the default database. */ ulong m_default_database; /** Number of errors from init_connect. */ ulong m_init_connect; /** Number of errors from the server itself. */ ulong m_local; bool has_error() const { return ((m_host_blocked != 0) || (m_nameinfo_transient != 0) || (m_nameinfo_permanent != 0) || (m_format != 0) || (m_addrinfo_transient != 0) || (m_addrinfo_permanent != 0) || (m_FCrDNS != 0) || (m_host_acl != 0) || (m_no_auth_plugin != 0) || (m_auth_plugin != 0) || (m_handshake != 0) || (m_proxy_user != 0) || (m_proxy_user_acl != 0) || (m_authentication != 0) || (m_ssl != 0) || (m_max_user_connection != 0) || (m_max_user_connection_per_hour != 0) || (m_default_database != 0) || (m_init_connect != 0) || (m_local != 0)); } void sum_connect_errors() { /* Current (historical) behavior: */ m_connect= m_handshake; } void clear_connect_errors() { m_connect= 0; } }; /** Size of IP address string in the hash cache. */ #define HOST_ENTRY_KEY_SIZE INET6_ADDRSTRLEN /** An entry in the hostname hash table cache. Host name cache does two things: - caches host names to save DNS look ups; - counts errors from IP. Host name can be empty (that means DNS look up failed), but errors still are counted. */ class Host_entry : public hash_filo_element { public: Host_entry *next() { return (Host_entry*) hash_filo_element::next(); } /** Client IP address. This is the key used with the hash table. The client IP address is always expressed in IPv6, even when the network IPv6 stack is not present. This IP address is never used to connect to a socket. */ char ip_key[HOST_ENTRY_KEY_SIZE]; /** One of the host names for the IP address. May be a zero length string. */ char m_hostname[HOSTNAME_LENGTH + 1]; /** Length in bytes of @c m_hostname. */ uint m_hostname_length; /** The hostname is validated and used for authorization. */ bool m_host_validated; ulonglong m_first_seen; ulonglong m_last_seen; ulonglong m_first_error_seen; ulonglong m_last_error_seen; /** Error statistics. */ Host_errors m_errors; void set_error_timestamps(ulonglong now) { if (m_first_error_seen == 0) m_first_error_seen= now; m_last_error_seen= now; } }; /** The size of the host_cache. */ extern ulong host_cache_size; #define RC_OK 0 #define RC_BLOCKED_HOST 1 int ip_to_hostname(struct sockaddr_storage *ip_storage, const char *ip_string, const char **hostname, uint *connect_errors); void inc_host_errors(const char *ip_string, Host_errors *errors); void reset_host_connect_errors(const char *ip_string); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); uint hostname_cache_size(); void hostname_cache_resize(uint size); void hostname_cache_lock(); void hostname_cache_unlock(); Host_entry *hostname_cache_first(); #endif /* HOSTNAME_INCLUDED */ thread_cache.h 0000644 00000013421 15156036152 0007314 0 ustar 00 /* Copyright (C) 2020 MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** MariaDB thread cache for "one thread per connection" scheduler. Thread cache allows to re-use threads (as well as THD objects) for subsequent connections. */ class Thread_cache { mutable mysql_cond_t COND_thread_cache; mutable mysql_cond_t COND_flush_thread_cache; mutable mysql_mutex_t LOCK_thread_cache; /** Queue of new connection requests. */ I_List<CONNECT> list; /** Number of threads parked in the cache. */ ulong cached_thread_count; /** Number of active flush requests. */ uint32_t kill_cached_threads; /** PFS stuff, only used during initialization. Unfortunately needs to survive till destruction. */ PSI_cond_key key_COND_thread_cache, key_COND_flush_thread_cache; PSI_mutex_key key_LOCK_thread_cache; public: void init() { #ifdef HAVE_PSI_INTERFACE PSI_cond_info conds[]= { { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL }, { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL } }; PSI_mutex_info mutexes[]= { { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL } }; mysql_mutex_register("sql", mutexes, array_elements(mutexes)); mysql_cond_register("sql", conds, array_elements(conds)); #endif mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, 0); mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, 0); list.empty(); kill_cached_threads= 0; cached_thread_count= 0; } void destroy() { DBUG_ASSERT(cached_thread_count == 0); DBUG_ASSERT(list.is_empty()); mysql_cond_destroy(&COND_flush_thread_cache); mysql_cond_destroy(&COND_thread_cache); mysql_mutex_destroy(&LOCK_thread_cache); } /** Flushes thread cache. Awakes parked threads and requests them to shutdown. Waits until last parked thread leaves the cache. */ void flush() { mysql_mutex_lock(&LOCK_thread_cache); kill_cached_threads++; while (cached_thread_count) { mysql_cond_broadcast(&COND_thread_cache); mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache); } kill_cached_threads--; mysql_mutex_unlock(&LOCK_thread_cache); } /** Flushes thread cache and forbids threads parking in the cache. This is a pre-shutdown hook. */ void final_flush() { kill_cached_threads++; flush(); } /** Requests parked thread to serve new connection. @return @retval true connection is enqueued and parked thread is about to serve it @retval false thread cache is empty */ bool enqueue(CONNECT *connect) { mysql_mutex_lock(&LOCK_thread_cache); if (cached_thread_count) { list.push_back(connect); cached_thread_count--; mysql_mutex_unlock(&LOCK_thread_cache); mysql_cond_signal(&COND_thread_cache); return true; } mysql_mutex_unlock(&LOCK_thread_cache); return false; } /** Parks thread in the cache. Thread execution is suspended until either of the following occurs: - thread is requested to serve new connection; - thread cache is flushed; - THREAD_CACHE_TIMEOUT elapsed. @return @retval pointer to CONNECT if requested to serve new connection @retval 0 if thread cache is flushed or on timeout */ CONNECT *park() { struct timespec abstime; CONNECT *connect; bool flushed= false; DBUG_ENTER("Thread_cache::park"); set_timespec(abstime, THREAD_CACHE_TIMEOUT); /* Delete the instrumentation for the job that just completed, before parking this pthread in the cache (blocked on COND_thread_cache). */ PSI_CALL_delete_current_thread(); #ifndef DBUG_OFF while (_db_is_pushed_()) _db_pop_(); #endif mysql_mutex_lock(&LOCK_thread_cache); if ((connect= list.get())) cached_thread_count++; else if (cached_thread_count < thread_cache_size && !kill_cached_threads) { /* Don't kill the thread, just put it in cache for reuse */ DBUG_PRINT("info", ("Adding thread to cache")); cached_thread_count++; for (;;) { int error= mysql_cond_timedwait(&COND_thread_cache, &LOCK_thread_cache, &abstime); flushed= kill_cached_threads; if ((connect= list.get())) break; else if (flushed || error == ETIMEDOUT || error == ETIME) { /* If timeout, end thread. If a new thread is requested, we will handle the call, even if we got a timeout (as we are already awake and free) */ cached_thread_count--; break; } } } mysql_mutex_unlock(&LOCK_thread_cache); if (flushed) mysql_cond_signal(&COND_flush_thread_cache); DBUG_RETURN(connect); } /** Returns the number of parked threads. */ ulong size() const { mysql_mutex_lock(&LOCK_thread_cache); ulong r= cached_thread_count; mysql_mutex_unlock(&LOCK_thread_cache); return r; } }; extern Thread_cache thread_cache; json_schema_helper.h 0000644 00000002200 15156036152 0010543 0 ustar 00 #ifndef JSON_SCHEMA_HELPER #define JSON_SCHEMA_HELPER /* Copyright (c) 2016, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "sql_type_json.h" #include <m_string.h> #include "json_schema.h" bool json_key_equals(const char* key, LEX_CSTRING val, int key_len); bool json_assign_type(uint *curr_type, json_engine_t *je); const uchar *get_key_name(const void *key_name, size_t *length, my_bool); void json_get_normalized_string(json_engine_t *je, String *res, int *error); #endif rpl_tblmap.h 0000644 00000006151 15156036152 0007060 0 ustar 00 /* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef TABLE_MAPPING_H #define TABLE_MAPPING_H /* Forward declarations */ #ifndef MYSQL_CLIENT struct TABLE; #else class Table_map_log_event; typedef Table_map_log_event TABLE; void free_table_map_log_event(TABLE *table); #endif /* CLASS table_mapping RESPONSIBILITIES The table mapping is used to map table id's to table pointers COLLABORATION RELAY_LOG For mapping table id:s to tables when receiving events. */ /* Guilhem to Mats: in the table_mapping class, the memory is allocated and never freed (until destruction). So this is a good candidate for allocating inside a MEM_ROOT: it gives the efficient allocation in chunks (like in expand()). So I have introduced a MEM_ROOT. Note that inheriting from Sql_alloc had no effect: it has effects only when "ptr= new table_mapping" is called, and this is never called. And it would then allocate from thd->mem_root which is a highly volatile object (reset from example after executing each query, see dispatch_command(), it has a free_root() at end); as the table_mapping object is supposed to live longer than a query, it was dangerous. A dedicated MEM_ROOT needs to be used, see below. */ #include "hash.h" /* HASH */ class table_mapping { private: MEM_ROOT m_mem_root; public: enum enum_error { ERR_NO_ERROR = 0, ERR_LIMIT_EXCEEDED, ERR_MEMORY_ALLOCATION }; table_mapping(); ~table_mapping(); TABLE* get_table(ulonglong table_id); int set_table(ulonglong table_id, TABLE* table); int remove_table(ulonglong table_id); void clear_tables(); ulong count() const { return m_table_ids.records; } private: /* This is a POD (Plain Old Data). Keep it that way (we apply offsetof() to it, which only works for PODs) */ struct entry { ulonglong table_id; union { TABLE *table; entry *next; }; }; entry *find_entry(ulonglong table_id) { return (entry *) my_hash_search(&m_table_ids, (uchar*)&table_id, sizeof(table_id)); } int expand(); /* Head of the list of free entries; "free" in the sense that it's an allocated entry free for use, NOT in the sense that it's freed memory. */ entry *m_free; /* Correspondance between an id (a number) and a TABLE object */ HASH m_table_ids; }; #endif sp_cache.h 0000644 00000003765 15156036152 0006501 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_CACHE_H_ #define _SP_CACHE_H_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif /* Stored procedures/functions cache. This is used as follows: * Each thread has its own cache. * Each sp_head object is put into its thread cache before it is used, and then remains in the cache until deleted. */ class sp_head; class sp_cache; class Database_qualified_name; /* Cache usage scenarios: 1. Application-wide init: sp_cache_init(); 2. SP execution in thread: 2.1 While holding sp_head* pointers: // look up a routine in the cache (no checks if it is up to date or not) sp_cache_lookup(); sp_cache_insert(); sp_cache_invalidate(); 2.2 When not holding any sp_head* pointers: sp_cache_flush_obsolete(); 3. Before thread exit: sp_cache_clear(); */ void sp_cache_init(); void sp_cache_end(); void sp_cache_clear(sp_cache **cp); void sp_cache_insert(sp_cache **cp, sp_head *sp); sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name); void sp_cache_invalidate(); void sp_cache_remove(sp_cache **cp, sp_head **sp); ulong sp_cache_version(); void sp_cache_enforce_limit(sp_cache *cp, ulong upper_limit_for_elements); #endif /* _SP_CACHE_H_ */ waiting_threads.h 0000644 00000010664 15156036152 0010104 0 ustar 00 /* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _waiting_threads_h #define _waiting_threads_h #include <my_sys.h> #include <lf.h> C_MODE_START typedef struct st_wt_resource_id WT_RESOURCE_ID; typedef struct st_wt_resource WT_RESOURCE; typedef struct st_wt_resource_type { my_bool (*compare)(const void *a, const void *b); const void *(*make_key)(const WT_RESOURCE_ID *id, uint *len); /* not used */ } WT_RESOURCE_TYPE; struct st_wt_resource_id { ulonglong value; const WT_RESOURCE_TYPE *type; }; /* the below differs from sizeof(WT_RESOURCE_ID) by the amount of padding */ #define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*)) #define WT_WAIT_STATS 24 #define WT_CYCLE_STATS 32 extern ulonglong wt_wait_table[WT_WAIT_STATS]; extern uint32 wt_wait_stats[WT_WAIT_STATS+1]; extern uint32 wt_cycle_stats[2][WT_CYCLE_STATS+1]; extern uint32 wt_success_stats; typedef struct st_wt_thd { /* XXX there's no protection (mutex) against concurrent access of the dynarray below. it is assumed that a caller will have it anyway (not to protect this array but to protect its own - caller's - data structures), and we'll get it for free. A caller needs to ensure that a blocker won't release a resource before a blocked thread starts waiting, which is usually done with a mutex. If the above assumption is wrong, we'll need to add a mutex here. */ DYNAMIC_ARRAY my_resources; /* 'waiting_for' is modified under waiting_for->lock, and only by thd itself 'waiting_for' is read lock-free (using pinning protocol), but a thd object can read its own 'waiting_for' without any locks or tricks. */ WT_RESOURCE *waiting_for; LF_PINS *pins; /* pointers to values */ const ulong *timeout_short; const ulong *deadlock_search_depth_short; const ulong *timeout_long; const ulong *deadlock_search_depth_long; /* weight relates to the desirability of a transaction being killed if it's part of a deadlock. In a deadlock situation transactions with lower weights are killed first. Examples of using the weight to implement different selection strategies: 1. Latest Keep all weights equal. 2. Random Assign weights at random. (variant: modify a weight randomly before every lock request) 3. Youngest Set weight to -NOW() 4. Minimum locks count locks granted in your lock manager, store the value as a weight 5. Minimum work depends on the definition of "work". For example, store the number of rows modifies in this transaction (or a length of REDO log for a transaction) as a weight. It is only statistically relevant and is not protected by any locks. */ ulong volatile weight; /* 'killed' is indirectly protected by waiting_for->lock because a killed thread needs to clear its 'waiting_for' and thus needs a lock. That is a thread needs an exclusive lock to read 'killed' reliably. But other threads may change 'killed' from 0 to 1, a shared lock is enough for that. */ my_bool killed; #ifndef DBUG_OFF const char *name; #endif } WT_THD; #define WT_TIMEOUT ETIMEDOUT #define WT_OK 0 #define WT_DEADLOCK -1 #define WT_DEPTH_EXCEEDED -2 #define WT_FREE_TO_GO -3 void wt_init(void); void wt_end(void); void wt_thd_lazy_init(WT_THD *, const ulong *, const ulong *, const ulong *, const ulong *); void wt_thd_destroy(WT_THD *); int wt_thd_will_wait_for(WT_THD *, WT_THD *, const WT_RESOURCE_ID *); int wt_thd_cond_timedwait(WT_THD *, mysql_mutex_t *); void wt_thd_release(WT_THD *, const WT_RESOURCE_ID *); #define wt_thd_release_all(THD) wt_thd_release((THD), 0) my_bool wt_resource_id_memcmp(const void *, const void *); C_MODE_END #endif sql_insert.h 0000644 00000012065 15156036152 0007110 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_INSERT_INCLUDED #define SQL_INSERT_INCLUDED #include "sql_class.h" /* enum_duplicates */ #include "sql_list.h" /* Instead of including sql_lex.h we add this typedef here */ typedef List<Item> List_item; typedef struct st_copy_info COPY_INFO; int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, List<Item> &fields, List_item *values, List<Item> &update_fields, List<Item> &update_values, enum_duplicates duplic, bool ignore, COND **where, bool select_insert, bool * const cache_results); bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, List<List_item> &values, List<Item> &update_fields, List<Item> &update_values, enum_duplicates flag, bool ignore, select_result* result); int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, TABLE_LIST *table_list); int vers_insert_history_row(TABLE *table); int check_duplic_insert_without_overlaps(THD *thd, TABLE *table, enum_duplicates duplic); void kill_delayed_threads(void); bool binlog_create_table(THD *thd, TABLE *table, bool replace); bool binlog_drop_table(THD *thd, TABLE *table); int prepare_for_replace(TABLE *table, enum_duplicates handle_duplicates, bool ignore); int finalize_replace(TABLE *table, enum_duplicates handle_duplicates, bool ignore); static inline void restore_default_record_for_insert(TABLE *t) { restore_record(t,s->default_values); if (t->triggers) t->triggers->default_extra_null_bitmap(); } class Write_record { THD *thd; TABLE *table; COPY_INFO *info; ulonglong prev_insert_id; ulonglong insert_id_for_cur_row= 0; uchar *key; ushort key_nr; ushort last_unique_key; bool use_triggers; bool versioned; bool can_optimize; bool ignored_error; int (*incomplete_records_cb)(void *arg1, void *arg2); void *arg1, *arg2; select_result *sink; ushort get_last_unique_key() const; // FINALIZATION void notify_non_trans_table_modified(); int after_insert(ha_rows *inserted); int after_ins_trg(); int send_data(); int on_ha_error(int error); int restore_on_error(); bool is_fatal_error(int error); int prepare_handle_duplicate(int error); int locate_dup_record(); int replace_row(ha_rows *inserted, ha_rows *deleted); int insert_on_duplicate_update(ha_rows *inserted, ha_rows *updated); int single_insert(ha_rows *inserted); public: /** @param thd thread context @param info COPY_INFO structure describing handling of duplicates and which is used for counting number of records inserted and deleted. @param sink result sink for the RETURNING clause @param table @param versioned @param use_triggers */ Write_record(THD *thd, TABLE *table, COPY_INFO *info, bool versioned, bool use_triggers, select_result *sink, int (*incomplete_records_cb)(void *, void *), void *arg1, void* arg2): thd(thd), table(table), info(info), insert_id_for_cur_row(0), key(NULL), last_unique_key(get_last_unique_key()), use_triggers(use_triggers), versioned(versioned), incomplete_records_cb(incomplete_records_cb), arg1(arg1), arg2(arg2), sink(sink) { if (info->handle_duplicates == DUP_REPLACE) { bool has_delete_triggers= use_triggers && table->triggers->has_delete_triggers(); bool referenced_by_fk= table->file->referenced_by_foreign_key(); can_optimize= !referenced_by_fk && !has_delete_triggers && !versioned && !table->versioned(); } } Write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink= NULL): Write_record(thd, table, info, table->versioned(VERS_TIMESTAMP), table->triggers, sink, NULL, NULL, NULL) {} Write_record() = default; // dummy, to allow later (lazy) initializations /* Main entry point, see docs in sql_insert.cc */ int write_record(); int last_errno() { return info->last_errno; } }; #ifdef EMBEDDED_LIBRARY inline void kill_delayed_threads(void) {} #endif #endif /* SQL_INSERT_INCLUDED */ backup.h 0000644 00000003247 15156036152 0006174 0 ustar 00 #ifndef BACKUP_INCLUDED #define BACKUP_INCLUDED /* Copyright (c) 2018, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ enum backup_stages { BACKUP_START, BACKUP_FLUSH, BACKUP_WAIT_FOR_FLUSH, BACKUP_LOCK_COMMIT, BACKUP_END, BACKUP_FINISHED }; extern TYPELIB backup_stage_names; struct backup_log_info { LEX_CSTRING query; LEX_CUSTRING org_table_id; /* Unique id from frm */ LEX_CSTRING org_database, org_table; LEX_CSTRING org_storage_engine_name; LEX_CSTRING new_database, new_table; LEX_CSTRING new_storage_engine_name; LEX_CUSTRING new_table_id; /* Unique id from frm */ bool org_partitioned; bool new_partitioned; }; void backup_init(); bool run_backup_stage(THD *thd, backup_stages stage); bool backup_end(THD *thd); void backup_set_alter_copy_lock(THD *thd, TABLE *altered_table); bool backup_reset_alter_copy_lock(THD *thd); bool backup_lock(THD *thd, TABLE_LIST *table); void backup_unlock(THD *thd); void backup_log_ddl(const backup_log_info *info); #endif /* BACKUP_INCLUDED */ item_create.h 0000644 00000026364 15156036152 0007215 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. Copyright (c) 2008, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Functions to create an item. Used by sql/sql_yacc.yy */ #ifndef ITEM_CREATE_H #define ITEM_CREATE_H #include "item_func.h" // Cast_target typedef struct st_udf_func udf_func; /** Public function builder interface. The parser (sql/sql_yacc.yy) uses a factory / builder pattern to construct an <code>Item</code> object for each function call. All the concrete function builders implements this interface, either directly or indirectly with some adapter helpers. Keeping the function creation separated from the bison grammar allows to simplify the parser, and avoid the need to introduce a new token for each function, which has undesirable side effects in the grammar. */ class Create_func { public: /** The builder create method. Given the function name and list or arguments, this method creates an <code>Item</code> that represents the function call. In case or errors, a NULL item is returned, and an error is reported. Note that the <code>thd</code> object may be modified by the builder. In particular, the following members/methods can be set/called, depending on the function called and the function possible side effects. <ul> <li><code>thd->lex->binlog_row_based_if_mixed</code></li> <li><code>thd->lex->current_context()</code></li> <li><code>thd->lex->safe_to_cache_query</code></li> <li><code>thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT)</code></li> <li><code>thd->lex->uncacheable(UNCACHEABLE_RAND)</code></li> <li><code>thd->lex->add_time_zone_tables_to_query_tables(thd)</code></li> </ul> @param thd The current thread @param name The function name @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call, or NULL */ virtual Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) = 0; protected: /** Constructor */ Create_func() = default; /** Destructor */ virtual ~Create_func() = default; }; /** Adapter for functions that takes exactly zero arguments. */ class Create_func_arg0 : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** Builder method, with no arguments. @param thd The current thread @return An item representing the function call */ virtual Item *create_builder(THD *thd) = 0; protected: /** Constructor. */ Create_func_arg0() = default; /** Destructor. */ virtual ~Create_func_arg0() = default; }; /** Adapter for functions that takes exactly one argument. */ class Create_func_arg1 : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** Builder method, with one argument. @param thd The current thread @param arg1 The first argument of the function @return An item representing the function call */ virtual Item *create_1_arg(THD *thd, Item *arg1) = 0; protected: /** Constructor. */ Create_func_arg1() = default; /** Destructor. */ virtual ~Create_func_arg1() = default; }; /** Adapter for functions that takes exactly two arguments. */ class Create_func_arg2 : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** Builder method, with two arguments. @param thd The current thread @param arg1 The first argument of the function @param arg2 The second argument of the function @return An item representing the function call */ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0; protected: /** Constructor. */ Create_func_arg2() = default; /** Destructor. */ virtual ~Create_func_arg2() = default; }; /** Adapter for functions that takes exactly three arguments. */ class Create_func_arg3 : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** Builder method, with three arguments. @param thd The current thread @param arg1 The first argument of the function @param arg2 The second argument of the function @param arg3 The third argument of the function @return An item representing the function call */ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0; protected: /** Constructor. */ Create_func_arg3() = default; /** Destructor. */ virtual ~Create_func_arg3() = default; }; /** Adapter for native functions with a variable number of arguments. The main use of this class is to discard the following calls: <code>foo(expr1 AS name1, expr2 AS name2, ...)</code> which are syntactically correct (the syntax can refer to a UDF), but semantically invalid for native functions. */ class Create_native_func : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** Builder method, with no arguments. @param thd The current thread @param name The native function name @param item_list The function parameters, none of which are named @return An item representing the function call */ virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) = 0; protected: /** Constructor. */ Create_native_func() = default; /** Destructor. */ virtual ~Create_native_func() = default; }; /** Function builder for qualified functions. This builder is used with functions call using a qualified function name syntax, as in <code>db.func(expr, expr, ...)</code>. */ class Create_qfunc : public Create_func { public: /** The builder create method, for unqualified functions. This builder will use the current database for the database name. @param thd The current thread @param name The function name @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** The builder create method, for qualified functions. @param thd The current thread @param db The database name @param name The function name @param use_explicit_name Should the function be represented as 'db.name'? @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ virtual Item *create_with_db(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *name, bool use_explicit_name, List<Item> *item_list) = 0; protected: /** Constructor. */ Create_qfunc() = default; /** Destructor. */ virtual ~Create_qfunc() = default; }; /** Find the function builder for qualified functions. @param thd The current thread @return A function builder for qualified functions */ extern Create_qfunc * find_qualified_function_builder(THD *thd); #ifdef HAVE_DLOPEN /** Function builder for User Defined Functions. */ class Create_udf_func : public Create_func { public: Item *create_func(THD *thd, const LEX_CSTRING *name, List<Item> *item_list) override; /** The builder create method, for User Defined Functions. @param thd The current thread @param fct The User Defined Function metadata @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ Item *create(THD *thd, udf_func *fct, List<Item> *item_list); /** Singleton. */ static Create_udf_func s_singleton; protected: /** Constructor. */ Create_udf_func() = default; /** Destructor. */ virtual ~Create_udf_func() = default; }; #endif struct Native_func_registry { LEX_CSTRING name; Create_func *builder; }; class Native_functions_hash: public HASH { public: Native_functions_hash() { bzero((void*) this, sizeof(*this)); } ~Native_functions_hash() { /* No automatic free because objects of this type are expected to be declared statically. The code in cleanup() calls my_hash_free() which may not work correctly at the very end of mariadbd shutdown. The the upper level code should call cleanup() explicitly. Unfortunatelly, it's not possible to use DBUG_ASSERT(!records) here, because the server terminates using exit() in some cases, e.g. in the test main.named_pipe with the "Create named pipe failed" error. */ } bool init(size_t count); bool append(const Native_func_registry array[], size_t count); bool remove(const Native_func_registry array[], size_t count); bool replace(const Native_func_registry array[], size_t count) { DBUG_ENTER("Native_functions_hash::replace"); remove(array, count); DBUG_RETURN(append(array, count)); } void cleanup(); /** Find the native function builder associated with a given function name. @param thd The current thread @param name The native function name @return The native function builder associated with the name, or NULL */ Create_func *find(THD *thd, const LEX_CSTRING &name) const; }; extern MYSQL_PLUGIN_IMPORT Native_functions_hash native_functions_hash; extern MYSQL_PLUGIN_IMPORT Native_functions_hash native_functions_hash_oracle; extern const Native_func_registry func_array[]; extern const size_t func_array_length; int item_create_init(); void item_create_cleanup(); Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list); Item *create_func_dyncol_add(THD *thd, Item *str, List<DYNCALL_CREATE_DEF> &list); Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums); Item *create_func_dyncol_get(THD *thd, Item *num, Item *str, const Type_handler *handler, const Lex_length_and_dec_st &length_and_dec, CHARSET_INFO *cs); Item *create_func_dyncol_json(THD *thd, Item *str); class Native_func_registry_array { const Native_func_registry *m_elements; size_t m_count; public: Native_func_registry_array() :m_elements(NULL), m_count(0) { } Native_func_registry_array(const Native_func_registry *elements, size_t count) :m_elements(elements), m_count(count) { } const Native_func_registry& element(size_t i) const { DBUG_ASSERT(i < m_count); return m_elements[i]; } const Native_func_registry *elements() const { return m_elements; } size_t count() const { return m_count; } }; #endif my_stack_alloc.h 0000644 00000014535 15156036152 0007715 0 ustar 00 /* Copyright 2019 MariaDB corporation AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_stack_alloc_h #define _my_stack_alloc_h #ifdef _MSC_VER #include <intrin.h> // For MSVC-specific intrinsics #else #include <sys/resource.h> #endif /* Get the address of the current stack. This will fallback to using an estimate for the stack pointer in the cases where either the compiler or the architecture is not supported. */ static inline void *my_get_stack_pointer(void *default_stack) { void *stack_ptr= NULL; #if defined(__GNUC__) || defined(__clang__) /* GCC and Clang compilers */ #if defined(__i386__) /* Intel x86 (32-bit) */ __asm__ volatile ("movl %%esp, %0" : "=r" (stack_ptr)); #elif defined(__x86_64__) && defined (__ILP32__) /* Intel x86-64 (64-bit), X32 ABI */ __asm__ volatile ("movl %%esp, %0" : "=r" (stack_ptr)); #elif defined(__x86_64__) /* Intel x86-64 (64-bit) */ __asm__ volatile ("movq %%rsp, %0" : "=r" (stack_ptr)); #elif defined(__powerpc__) /* PowerPC (32-bit) */ __asm__ volatile ("mr %0, 1" : "=r" (stack_ptr)); /* GPR1 is the stack pointer */ #elif defined(__ppc64__) /* PowerPC (64-bit) */ __asm__ volatile ("mr %0, 1" : "=r" (stack_ptr)); #elif defined(__arm__) /* ARM 32-bit */ __asm__ volatile ("mov %0, sp" : "=r" (stack_ptr)); #elif defined(__aarch64__) /* ARM 64-bit */ __asm__ volatile ("mov %0, sp" : "=r" (stack_ptr)); #elif defined(__sparc__) /* SPARC 32-bit */ __asm__ volatile ("mov %%sp, %0" : "=r" (stack_ptr)); #elif defined(__sparc64__) /* SPARC 64-bit */ __asm__ volatile ("mov %%sp, %0" : "=r" (stack_ptr)); #elif defined(__s390x__) stack_ptr= __builtin_frame_address(0); #else /* Generic fallback for unsupported architectures in GCC/Clang */ stack_ptr= default_stack ? default_stack : (void*) &stack_ptr; #endif #elif defined(_MSC_VER) /* MSVC compiler (Intel only) */ #if defined(_M_IX86) /* Intel x86 (32-bit) */ __asm { mov stack_ptr, esp } #elif defined(_M_X64) /* Intel x86-64 (64-bit) */ /* rsp can’t be accessed directly in MSVC x64 */ stack_ptr= _AddressOfReturnAddress(); #else /* Generic fallback for unsupported architectures in MSVC */ stack_ptr= default_stack ? default_stack : (void*) &stack_ptr; #endif #else /* Generic fallback for unsupported compilers */ stack_ptr= default_stack ? default_stack : (void*) &stack_ptr; #endif return stack_ptr; } /* Do allocation through alloca if there is enough stack available. If not, use my_malloc() instead. The idea is that to be able to alloc as much as possible through the stack. To ensure this, we have two different limits, on for big blocks and one for small blocks. This will enable us to continue to do allocation for small blocks even when there is less stack space available. This is for example used by Aria when traversing the b-tree and the code needs to allocate one b-tree page and a few keys for each recursion. Even if there is not space to allocate the b-tree pages on stack we can still continue to allocate the keys. */ /* Default suggested allocations */ /* Allocate big blocks as long as there is this much left */ #define STACK_ALLOC_BIG_BLOCK 1024*64 /* Allocate small blocks as long as there is this much left */ #define STACK_ALLOC_SMALL_BLOCK 1024*32 /* Allocate small blocks as long as the block size is not bigger than */ #define STACK_ALLOC_SMALL_BLOCK_SIZE 4096 /* Allocate a block on stack or through malloc. The 'must_be_freed' variable will be set to 1 if malloc was called. 'must_be_freed' must be a variable on the stack! */ #ifdef HAVE_ALLOCA #define alloc_on_stack(stack_end, res, must_be_freed, size) \ do \ { \ size_t alloc_size= (size); \ void *stack= my_get_stack_pointer(0); \ size_t stack_left= available_stack_size(stack, (stack_end)); \ if (stack_left > alloc_size + STACK_ALLOC_SMALL_BLOCK && \ (stack_left > alloc_size + STACK_ALLOC_BIG_BLOCK || \ (STACK_ALLOC_SMALL_BLOCK_SIZE >= alloc_size))) \ { \ (must_be_freed)= 0; \ (res)= alloca(size); \ } \ else \ { \ (must_be_freed)= 1; \ (res)= my_malloc(PSI_INSTRUMENT_ME, size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ } \ } while(0) #else #define alloc_on_stack(stack_end, res, must_be_freed, size) \ do { \ (must_be_freed)= 1; \ (res)= my_malloc(PSI_INSTRUMENT_ME, size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ } while(0) #endif /* HAVE_ALLOCA */ /* Free memory allocated by stack_alloc */ static inline void stack_alloc_free(void *res, my_bool must_be_freed) { if (must_be_freed) my_free(res); } #endif /* _my_stack_alloc_h */ /* Get start and end of stack */ /* This is used in the case when we not know the exact stack start and have to estimate stack start with get_stack_pointer() */ #define MY_STACK_SAFE_MARGIN 8192 extern void my_get_stack_bounds(void **stack_start, void **stack_end, void *fallback_stack_start, size_t fallback_stack_size); opt_histogram_json.h 0000644 00000011333 15156036152 0010632 0 ustar 00 /* Copyright (c) 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_statistics.h" struct Histogram_bucket { // The left endpoint in KeyTupleFormat. The endpoint is inclusive, this // value is in this bucket. std::string start_value; // Cumulative fraction: The fraction of table rows that fall into this // and preceding buckets. double cum_fract; // Number of distinct values in the bucket. longlong ndv; }; /* An equi-height histogram which stores real values for bucket bounds. Handles @@histogram_type=JSON_HB Histogram format in JSON: { // The next three are saved but not currently analyzed: "target_histogram_size": nnn, "collected_at": "(date and time)", "collected_by": "(server version)", "histogram_hb": [ { "start": "value", "size":nnn.nn, "ndv": nnn }, ... // Optionally, start and/or end can be replaced with _hex variant { "start_hex: "value", "size":nnn.nn, "ndv":nnn}, ... { "start": "value", "size":nnn.nn, "ndv": nnn, "end": "value"}, ] } Histogram is a JSON object. It has some global properties and "histogram_hb" member whose value is a JSON array of histogram buckets. Each bucket is an object with these members: "start" - the first value in the bucket. "size" - fraction of table rows that is contained in the bucket. "ndv" - Number of Distinct Values in the bucket. "end" - Optionally, the last value in the bucket. A bucket is a single-point bucket if it has ndv=1. Most buckets have no "end" member: the bucket is assumed to contain all values up to the "start" of the next bucket. The exception is single-point buckets where last value is the same as the first value. start/end can be replaced with start_hex/end_hex. In _hex variant, the constant is encoded in hex. This encoding is used to handle so called "unassigned characters": some non-UTF8 charsets have byte combinations that are not mapped to any UTF8 character. */ class Histogram_json_hb final : public Histogram_base { size_t size; /* Number of elements in the histogram */ /* Collection-time only: collected histogram in the JSON form. */ std::string json_text; std::vector<Histogram_bucket> buckets; std::string last_bucket_end_endp; public: static constexpr const char* JSON_NAME="histogram_hb"; bool parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, Field *field, const char *hist_data, size_t hist_data_len) override; void serialize(Field *field) override; Histogram_builder *create_builder(Field *col, uint col_len, ha_rows rows) override; // returns number of buckets in the histogram uint get_width() override { return (uint)size; } Histogram_type get_type() override { return JSON_HB; } /* @brief This used to be the size of the histogram on disk, which was redundant (one can check the size directly). Return the number of buckets instead. */ uint get_size() override { return (uint)size; } void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, ulonglong size) override; double point_selectivity(Field *field, key_range *endpoint, double avg_sel) override; double range_selectivity(Field *field, key_range *min_endp, key_range *max_endp, double avg_sel) override; const std::vector<Histogram_bucket>& get_json_histogram() const { return buckets; } const std::string& get_last_bucket_end_endp() const { return last_bucket_end_endp; } void set_json_text(ulonglong sz, const char *json_text_arg, size_t json_text_len) { size= (size_t) sz; json_text.assign(json_text_arg, json_text_len); } private: int parse_bucket(json_engine_t *je, Field *field, double *cumulative_size, bool *assigned_last_end, const char **err); double get_left_fract(int idx); std::string& get_end_value(int idx); int find_bucket(const Field *field, const uchar *lookup_val, int *cmp); }; session_tracker.h 0000644 00000033401 15156036153 0010121 0 ustar 00 #ifndef SESSION_TRACKER_INCLUDED #define SESSION_TRACKER_INCLUDED /* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2016, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "m_string.h" #include "thr_lock.h" #include "sql_hset.h" #ifndef EMBEDDED_LIBRARY /* forward declarations */ class THD; class set_var; class String; class user_var_entry; enum enum_session_tracker { SESSION_SYSVARS_TRACKER, /* Session system variables */ CURRENT_SCHEMA_TRACKER, /* Current schema */ SESSION_STATE_CHANGE_TRACKER, TRANSACTION_INFO_TRACKER, /* Transaction state */ #ifdef USER_VAR_TRACKING USER_VARIABLES_TRACKER, #endif // USER_VAR_TRACKING SESSION_TRACKER_END /* must be the last */ }; /** State_tracker An abstract class that defines the interface for any of the server's 'session state change tracker'. A tracker, however, is a sub- class of this class which takes care of tracking the change in value of a part- icular session state type and thus defines various methods listed in this interface. The change information is later serialized and transmitted to the client through protocol's OK packet. Tracker system variables :- A tracker is normally mapped to a system variable. So in order to enable, disable or modify the sub-entities of a tracker, the user needs to modify the respective system variable either through SET command or via command line option. As required in system variable handling, this interface also includes two functions to help in the verification of the supplied value (ON_UPDATE) of the tracker system variable, namely - update(). */ class State_tracker { protected: /** Is tracking enabled for a particular session state type ? @note: it is a cache of the corresponding thd->variables.session_track_xxx variable */ bool m_enabled; void set_changed(THD *thd); private: /** Has the session state type changed ? */ bool m_changed; public: virtual ~State_tracker() = default; /** Getters */ bool is_enabled() const { return m_enabled; } bool is_changed() const { return m_changed; } void reset_changed() { m_changed= false; } /** Called by THD::init() when new connection is being created We may inherit m_changed from previous connection served by this THD if connection was broken or client didn't have session tracking capability. Thus we have to reset it here. */ virtual bool enable(THD *thd) { reset_changed(); return update(thd, 0); } /** To be invoked when the tracker's system variable is updated (ON_UPDATE).*/ virtual bool update(THD *thd, set_var *var)= 0; /** Store changed data into the given buffer. */ virtual bool store(THD *thd, String *buf)= 0; /** Mark the entity as changed. */ void mark_as_changed(THD *thd) { if (is_enabled()) set_changed(thd); } }; /** Session_sysvars_tracker This is a tracker class that enables & manages the tracking of session system variables. It internally maintains a hash of user supplied variable references and a boolean field to store if the variable was changed by the last statement. */ class Session_sysvars_tracker: public State_tracker { struct sysvar_node_st { sys_var *m_svar; bool *test_load; bool m_changed; }; class vars_list { /** Registered system variables. (@@session_track_system_variables) A hash to store the name of all the system variables specified by the user. */ HASH m_registered_sysvars; /** If TRUE then we want to check all session variable. */ bool track_all; void init() { my_hash_init(PSI_INSTRUMENT_ME, &m_registered_sysvars, &my_charset_bin, 0, 0, 0, sysvars_get_key, my_free, HASH_UNIQUE | (mysqld_server_initialized ? HASH_THREAD_SPECIFIC : 0)); } void free_hash() { DBUG_ASSERT(my_hash_inited(&m_registered_sysvars)); my_hash_free(&m_registered_sysvars); } sysvar_node_st *search(const sys_var *svar); sysvar_node_st *at(ulong i) { DBUG_ASSERT(i < m_registered_sysvars.records); return reinterpret_cast<sysvar_node_st*>( my_hash_element(&m_registered_sysvars, i)); } public: vars_list(): track_all(false) { init(); } ~vars_list() { if (my_hash_inited(&m_registered_sysvars)) free_hash(); } void deinit() { free_hash(); } sysvar_node_st *insert_or_search(const sys_var *svar) { sysvar_node_st *res= search(svar); if (!res) { if (track_all) { insert(svar); return search(svar); } } return res; } bool insert(const sys_var *svar); void reinit(); void reset(); inline bool is_enabled() { return track_all || m_registered_sysvars.records; } void copy(vars_list* from, THD *thd); bool parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error, CHARSET_INFO *char_set); bool construct_var_list(char *buf, size_t buf_len); bool store(THD *thd, String *buf); }; /** Two objects of vars_list type are maintained to manage various operations. */ vars_list orig_list; bool m_parsed; public: void init(THD *thd); void deinit(THD *thd); bool enable(THD *thd) override; bool update(THD *thd, set_var *var) override; bool store(THD *thd, String *buf) override; void mark_as_changed(THD *thd, const sys_var *var); void deinit() { orig_list.deinit(); } /* callback */ static const uchar *sysvars_get_key(const void *entry, size_t *length, my_bool); friend bool sysvartrack_global_update(THD *thd, char *str, size_t len); }; bool sysvartrack_validate_value(THD *thd, const char *str, size_t len); bool sysvartrack_global_update(THD *thd, char *str, size_t len); /** Current_schema_tracker, This is a tracker class that enables & manages the tracking of current schema for a particular connection. */ class Current_schema_tracker: public State_tracker { public: bool update(THD *thd, set_var *var) override; bool store(THD *thd, String *buf) override; }; /* Session_state_change_tracker This is a boolean tracker class that will monitor any change that contributes to a session state change. Attributes that contribute to session state change include: - Successful change to System variables - User defined variables assignments - temporary tables created, altered or deleted - prepared statements added or removed - change in current database - change of current role */ class Session_state_change_tracker: public State_tracker { public: bool update(THD *thd, set_var *var) override; bool store(THD *thd, String *buf) override; }; /* Transaction_state_tracker */ /** Transaction state (no transaction, transaction active, work attached, etc.) */ enum enum_tx_state { TX_EMPTY = 0, ///< "none of the below" TX_EXPLICIT = 1, ///< an explicit transaction is active TX_IMPLICIT = 2, ///< an implicit transaction is active TX_READ_TRX = 4, ///< transactional reads were done TX_READ_UNSAFE = 8, ///< non-transaction reads were done TX_WRITE_TRX = 16, ///< transactional writes were done TX_WRITE_UNSAFE = 32, ///< non-transactional writes were done TX_STMT_UNSAFE = 64, ///< "unsafe" (non-deterministic like UUID()) stmts TX_RESULT_SET = 128, ///< result set was sent TX_WITH_SNAPSHOT= 256, ///< WITH CONSISTENT SNAPSHOT was used TX_LOCKED_TABLES= 512 ///< LOCK TABLES is active }; /** Transaction access mode */ enum enum_tx_read_flags { TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.transaction_read_only TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or transaction_read_only=1 TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or transaction_read_only=0 }; /** Transaction isolation level */ enum enum_tx_isol_level { TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.transaction_isolation TX_ISOL_UNCOMMITTED = 1, TX_ISOL_COMMITTED = 2, TX_ISOL_REPEATABLE = 3, TX_ISOL_SERIALIZABLE= 4 }; /** Transaction tracking level */ enum enum_session_track_transaction_info { TX_TRACK_NONE = 0, ///< do not send tracker items on transaction info TX_TRACK_STATE = 1, ///< track transaction status TX_TRACK_CHISTICS = 2 ///< track status and characteristics }; /** This is a tracker class that enables & manages the tracking of current transaction info for a particular connection. */ class Transaction_state_tracker : public State_tracker { /** Helper function: turn table info into table access flag */ enum_tx_state calc_trx_state(THD *thd, thr_lock_type l, bool has_trx); public: bool enable(THD *thd) override { m_enabled= false; tx_changed= TX_CHG_NONE; tx_curr_state= TX_EMPTY; tx_reported_state= TX_EMPTY; tx_read_flags= TX_READ_INHERIT; tx_isol_level= TX_ISOL_INHERIT; return State_tracker::enable(thd); } bool update(THD *thd, set_var *var) override; bool store(THD *thd, String *buf) override; /** Change transaction characteristics */ void set_read_flags(THD *thd, enum enum_tx_read_flags flags); void set_isol_level(THD *thd, enum enum_tx_isol_level level); /** Change transaction state */ void clear_trx_state(THD *thd, uint clear); void add_trx_state(THD *thd, uint add); void inline add_trx_state(THD *thd, thr_lock_type l, bool has_trx) { add_trx_state(thd, calc_trx_state(thd, l, has_trx)); } void add_trx_state_from_thd(THD *thd); void end_trx(THD *thd); private: enum enum_tx_changed { TX_CHG_NONE = 0, ///< no changes from previous stmt TX_CHG_STATE = 1, ///< state has changed from previous stmt TX_CHG_CHISTICS = 2 ///< characteristics have changed from previous stmt }; /** any trackable changes caused by this statement? */ uint tx_changed; /** transaction state */ uint tx_curr_state, tx_reported_state; /** r/w or r/o set? session default? */ enum enum_tx_read_flags tx_read_flags; /** isolation level */ enum enum_tx_isol_level tx_isol_level; inline void update_change_flags(THD *thd) { tx_changed &= uint(~TX_CHG_STATE); tx_changed |= (tx_curr_state != tx_reported_state) ? TX_CHG_STATE : 0; if (tx_changed != TX_CHG_NONE) set_changed(thd); } }; #define TRANSACT_TRACKER(X) \ do { if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) \ thd->session_tracker.transaction_info.X; } while(0) /** User_variables_tracker This is a tracker class that enables & manages the tracking of user variables. */ #ifdef USER_VAR_TRACKING class User_variables_tracker: public State_tracker { Hash_set<const user_var_entry> m_changed_user_variables; public: User_variables_tracker(): m_changed_user_variables(PSI_INSTRUMENT_ME, &my_charset_bin, 0, 0, sizeof(const user_var_entry*), 0, 0, HASH_UNIQUE | mysqld_server_initialized ? HASH_THREAD_SPECIFIC : 0) {} bool update(THD *thd, set_var *var); bool store(THD *thd, String *buf); void mark_as_changed(THD *thd, const user_var_entry *var) { if (is_enabled()) { m_changed_user_variables.insert(var); set_changed(thd); } } void deinit() { m_changed_user_variables.~Hash_set(); } }; #endif // USER_VAR_TRACKING /** Session_tracker This class holds an object each for all tracker classes and provides methods necessary for systematic detection and generation of session state change information. */ class Session_tracker { State_tracker *m_trackers[SESSION_TRACKER_END]; /* The following two functions are private to disable copying. */ Session_tracker(Session_tracker const &other) { DBUG_ASSERT(FALSE); } Session_tracker& operator= (Session_tracker const &rhs) { DBUG_ASSERT(FALSE); return *this; } public: Current_schema_tracker current_schema; Session_state_change_tracker state_change; Transaction_state_tracker transaction_info; Session_sysvars_tracker sysvars; #ifdef USER_VAR_TRACKING User_variables_tracker user_variables; #endif // USER_VAR_TRACKING Session_tracker() { m_trackers[SESSION_SYSVARS_TRACKER]= &sysvars; m_trackers[CURRENT_SCHEMA_TRACKER]= ¤t_schema; m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change; m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info; #ifdef USER_VAR_TRACKING m_trackers[USER_VARIABLES_TRACKER]= &user_variables; #endif // USER_VAR_TRACKING } void enable(THD *thd) { for (int i= 0; i < SESSION_TRACKER_END; i++) m_trackers[i]->enable(thd); } void store(THD *thd, String *main_buf); }; int session_tracker_init(); #else #define TRANSACT_TRACKER(X) do{}while(0) class Session_tracker { class Dummy_tracker { public: void mark_as_changed(THD *thd) {} void mark_as_changed(THD *thd, const sys_var *var) {} }; public: Dummy_tracker current_schema; Dummy_tracker state_change; Dummy_tracker sysvars; }; #endif //EMBEDDED_LIBRARY #endif /* SESSION_TRACKER_INCLUDED */ sql_i_s.h 0000644 00000020447 15156036153 0006362 0 ustar 00 #ifndef SQL_I_S_INCLUDED #define SQL_I_S_INCLUDED /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_const.h" // MAX_FIELD_VARCHARLENGTH #include "sql_basic_types.h" // enum_nullability #include "sql_string.h" // strlen, MY_CS_CHARACTER_SET_NAME_SIZE #include "lex_string.h" // LEX_CSTRING #include "mysql_com.h" // enum_field_types #include "my_time.h" // TIME_SECOND_PART_DIGITS #include "sql_type.h" // Type_handler_xxx struct TABLE_LIST; struct TABLE; typedef class Item COND; #ifdef MYSQL_CLIENT #error MYSQL_CLIENT must not be defined #endif // MYSQL_CLIENT bool schema_table_store_record(THD *thd, TABLE *table); COND *make_cond_for_info_schema(THD *thd, COND *cond, TABLE_LIST *table); enum enum_show_open_table { SKIP_OPEN_TABLE= 0U, // do not open table OPEN_FRM_ONLY= 1U, // open FRM file only OPEN_FULL_TABLE= 2U // open FRM,MYD, MYI files }; namespace Show { class Type { /** This denotes data type for the column. For the most part, there seems to be one entry in the enum for each SQL data type, although there seem to be a number of additional entries in the enum. */ const Type_handler *m_type_handler; /** For string-type columns, this is the maximum number of characters. Otherwise, it is the 'display-length' for the column. */ uint m_char_length; uint m_unsigned_flag; const Typelib *m_typelib; public: Type(const Type_handler *th, uint length, uint unsigned_flag, const Typelib *typelib= NULL) :m_type_handler(th), m_char_length(length), m_unsigned_flag(unsigned_flag), m_typelib(typelib) { } const Type_handler *type_handler() const { return m_type_handler; } uint char_length() const { return m_char_length; } decimal_digits_t decimal_precision() const { return (decimal_digits_t) ((m_char_length / 100) % 100); } decimal_digits_t decimal_scale() const { return (decimal_digits_t) (m_char_length % 10); } uint fsp() const { DBUG_ASSERT(m_char_length <= TIME_SECOND_PART_DIGITS); return m_char_length; } uint unsigned_flag() const { return m_unsigned_flag; } const Typelib *typelib() const { return m_typelib; } }; } // namespace Show class ST_FIELD_INFO: public Show::Type { protected: LEX_CSTRING m_name; // I_S column name enum_nullability m_nullability; // NULLABLE or NOT NULL LEX_CSTRING m_old_name; // SHOW column name enum_show_open_table m_open_method; public: ST_FIELD_INFO(const LEX_CSTRING &name, const Type &type, enum_nullability nullability, LEX_CSTRING &old_name, enum_show_open_table open_method) :Type(type), m_name(name), m_nullability(nullability), m_old_name(old_name), m_open_method(open_method) { } ST_FIELD_INFO(const char *name, const Type &type, enum_nullability nullability, const char *old_name, enum_show_open_table open_method) :Type(type), m_nullability(nullability), m_open_method(open_method) { m_name.str= name; m_name.length= safe_strlen(name); m_old_name.str= old_name; m_old_name.length= safe_strlen(old_name); } const LEX_CSTRING &name() const { return m_name; } bool nullable() const { return m_nullability == NULLABLE; } const LEX_CSTRING &old_name() const { return m_old_name; } enum_show_open_table open_method() const { return m_open_method; } bool end_marker() const { return m_name.str == NULL; } }; namespace Show { class Enum: public Type { public: Enum(const Typelib *typelib) :Type(&type_handler_enum, 0, false, typelib) { } }; class Blob: public Type { public: Blob(uint length) :Type(&type_handler_blob, length, false) { } }; class Varchar: public Type { public: Varchar(uint length) :Type(&type_handler_varchar, length, false) { DBUG_ASSERT(length * 3 <= MAX_FIELD_VARCHARLENGTH); } }; class Longtext: public Type { public: Longtext(uint length) :Type(&type_handler_varchar, length, false) { } }; class Yes_or_empty: public Varchar { public: Yes_or_empty(): Varchar(3) { } static LEX_CSTRING value(bool val) { return val ? Lex_cstring(STRING_WITH_LEN("Yes")) : Lex_cstring(); } }; class Catalog: public Varchar { public: Catalog(): Varchar(FN_REFLEN) { } }; class Name: public Varchar { public: Name(): Varchar(NAME_CHAR_LEN) { } }; class Definer: public Varchar { public: Definer(): Varchar(DEFINER_CHAR_LENGTH) { } }; class Userhost: public Varchar { public: Userhost(): Varchar(USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 2) { } }; class CSName: public Varchar { public: CSName(): Varchar(MY_CS_CHARACTER_SET_NAME_SIZE) { } }; class CLName: public Varchar { public: CLName(): Varchar(MY_CS_COLLATION_NAME_SIZE) { } }; class SQLMode: public Varchar { public: SQLMode(): Varchar(32*256) { } }; class Datetime: public Type { public: Datetime(uint dec) :Type(&type_handler_datetime2, dec, false) { } }; class Decimal: public Type { public: Decimal(uint length) :Type(&type_handler_newdecimal, length, false) { } }; class ULonglong: public Type { public: ULonglong(uint length) :Type(&type_handler_ulonglong, length, true) { } ULonglong() :ULonglong(MY_INT64_NUM_DECIMAL_DIGITS) { } }; class ULong: public Type { public: ULong(uint length) :Type(&type_handler_ulong, length, true) { } ULong() :ULong(MY_INT32_NUM_DECIMAL_DIGITS) { } }; class SLonglong: public Type { public: SLonglong(uint length) :Type(&type_handler_slonglong, length, false) { } SLonglong() :SLonglong(MY_INT64_NUM_DECIMAL_DIGITS) { } }; class SLong: public Type { public: SLong(uint length) :Type(&type_handler_slong, length, false) { } SLong() :SLong(MY_INT32_NUM_DECIMAL_DIGITS) { } }; class SShort: public Type { public: SShort(uint length) :Type(&type_handler_sshort, length, false) { } }; class STiny: public Type { public: STiny(uint length) :Type(&type_handler_stiny, length, false) { } }; class Double: public Type { public: Double(uint length) :Type(&type_handler_double, length, false) { } }; class Float: public Type { public: Float(uint length) :Type(&type_handler_float, length, false) { } }; class Column: public ST_FIELD_INFO { public: Column(const char *name, const Type &type, enum_nullability nullability, const char *old_name, enum_show_open_table open_method= SKIP_OPEN_TABLE) :ST_FIELD_INFO(name, type, nullability, old_name, open_method) { } Column(const char *name, const Type &type, enum_nullability nullability, enum_show_open_table open_method= SKIP_OPEN_TABLE) :ST_FIELD_INFO(name, type, nullability, NullS, open_method) { } }; // End marker class CEnd: public Column { public: CEnd() :Column(NullS, Varchar(0), NOT_NULL, NullS, SKIP_OPEN_TABLE) { } }; } // namespace Show struct TABLE_LIST; typedef class Item COND; typedef struct st_schema_table { const char *table_name; ST_FIELD_INFO *fields_info; /* for FLUSH table_name */ int (*reset_table) (); /* Fill table with data */ int (*fill_table) (THD *thd, TABLE_LIST *tables, COND *cond); /* Handle fileds for old SHOW */ int (*old_format) (THD *thd, struct st_schema_table *schema_table); int (*process_table) (THD *thd, TABLE_LIST *tables, TABLE *table, bool res, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name); int idx_field1, idx_field2; bool hidden; uint i_s_requested_object; /* the object we need to open(TABLE | VIEW) */ } ST_SCHEMA_TABLE; #endif // SQL_I_S_INCLUDED item_geofunc.h 0000644 00000115274 15156036153 0007400 0 ustar 00 #ifndef ITEM_GEOFUNC_INCLUDED #define ITEM_GEOFUNC_INCLUDED /* Copyright (c) 2000, 2016 Oracle and/or its affiliates. Copyright (C) 2011, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file defines all spatial functions */ #ifdef HAVE_SPATIAL #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_type_geom.h" #include "item.h" #include "gstream.h" #include "spatial.h" #include "gcalc_slicescan.h" #include "gcalc_tools.h" class Item_geometry_func: public Item_str_func { public: Item_geometry_func(THD *thd): Item_str_func(thd) {} Item_geometry_func(THD *thd, Item *a): Item_str_func(thd, a) {} Item_geometry_func(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_geometry_func(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {} bool fix_length_and_dec(THD *thd) override; const Type_handler *type_handler() const override { return &type_handler_geometry; } }; /* Functions returning REAL measurements of a single GEOMETRY argument */ class Item_real_func_args_geometry: public Item_real_func { protected: String value; bool check_arguments() const override { DBUG_ASSERT(arg_count == 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } public: Item_real_func_args_geometry(THD *thd, Item *a) :Item_real_func(thd, a) {} }; /* Functions returning INT measurements of a single GEOMETRY argument */ class Item_long_func_args_geometry: public Item_long_func { bool check_arguments() const override { DBUG_ASSERT(arg_count == 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } protected: String value; public: Item_long_func_args_geometry(THD *thd, Item *a) :Item_long_func(thd, a) {} }; /* Functions returning BOOL measurements of a single GEOMETRY argument */ class Item_bool_func_args_geometry: public Item_bool_func { protected: String value; bool check_arguments() const override { DBUG_ASSERT(arg_count == 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } public: Item_bool_func_args_geometry(THD *thd, Item *a) :Item_bool_func(thd, a) {} }; /* Functions returning ASCII string measurements of a single GEOMETRY argument */ class Item_str_ascii_func_args_geometry: public Item_str_ascii_func { protected: bool check_arguments() const override { DBUG_ASSERT(arg_count >= 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } public: Item_str_ascii_func_args_geometry(THD *thd, Item *a) :Item_str_ascii_func(thd, a) {} Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b) :Item_str_ascii_func(thd, a, b) {} Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c) :Item_str_ascii_func(thd, a, b, c) {} }; /* Functions returning binary string measurements of a single GEOMETRY argument */ class Item_binary_func_args_geometry: public Item_str_func { protected: bool check_arguments() const override { DBUG_ASSERT(arg_count >= 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } public: Item_binary_func_args_geometry(THD *thd, Item *a) :Item_str_func(thd, a) {} }; /* Functions returning GEOMETRY measurements of a single GEOEMETRY argument */ class Item_geometry_func_args_geometry: public Item_geometry_func { protected: bool check_arguments() const override { DBUG_ASSERT(arg_count >= 1); return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]); } public: Item_geometry_func_args_geometry(THD *thd, Item *a) :Item_geometry_func(thd, a) {} Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b) :Item_geometry_func(thd, a, b) {} }; /* Functions returning REAL result relationships between two GEOMETRY arguments */ class Item_real_func_args_geometry_geometry: public Item_real_func { protected: bool check_arguments() const override { DBUG_ASSERT(arg_count >= 2); return Type_handler_geometry::check_types_geom_or_binary(func_name_cstring(), args, 0, 2); } public: Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b) :Item_real_func(thd, a, b) {} }; /* Functions returning BOOL result relationships between two GEOMETRY arguments */ class Item_bool_func_args_geometry_geometry: public Item_bool_func { protected: String value; bool check_arguments() const override { DBUG_ASSERT(arg_count >= 2); return Type_handler_geometry::check_types_geom_or_binary(func_name_cstring(), args, 0, 2); } public: Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c) :Item_bool_func(thd, a, b, c) {} }; class Item_func_geometry_from_text: public Item_geometry_func { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()) || check_argument_types_can_return_int(1, MY_MIN(2, arg_count)); } public: Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {} Item_func_geometry_from_text(THD *thd, Item *a, Item *srid): Item_geometry_func(thd, a, srid) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_geometryfromtext") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_geometry_from_text>(thd, this); } }; class Item_func_geometry_from_wkb: public Item_geometry_func { bool check_arguments() const override { return Type_handler_geometry::check_type_geom_or_binary(func_name_cstring(), args[0]) || check_argument_types_can_return_int(1, MY_MIN(2, arg_count)); } public: Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {} Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid): Item_geometry_func(thd, a, srid) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_geometryfromwkb") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_geometry_from_wkb>(thd, this); } }; class Item_func_geometry_from_json: public Item_geometry_func { String tmp_js; bool check_arguments() const override { // TODO: check with Alexey, for better args[1] and args[2] type control return args[0]->check_type_general_purpose_string(func_name_cstring()) || check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count)); } public: Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {} Item_func_geometry_from_json(THD *thd, Item *js, Item *opt): Item_geometry_func(thd, js, opt) {} Item_func_geometry_from_json(THD *thd, Item *js, Item *opt, Item *srid): Item_geometry_func(thd, js, opt, srid) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_geomfromgeojson") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_geometry_from_json>(thd, this); } }; class Item_func_as_wkt: public Item_str_ascii_func_args_geometry { public: Item_func_as_wkt(THD *thd, Item *a) :Item_str_ascii_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_astext") }; return name; } String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_as_wkt>(thd, this); } }; class Item_func_as_wkb: public Item_binary_func_args_geometry { public: Item_func_as_wkb(THD *thd, Item *a) :Item_binary_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_aswkb") }; return name; } String *val_str(String *) override; const Type_handler *type_handler() const override { return &type_handler_long_blob; } bool fix_length_and_dec(THD *thd) override { collation.set(&my_charset_bin); decimals=0; max_length= (uint32) UINT_MAX32; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_as_wkb>(thd, this); } }; class Item_func_as_geojson: public Item_str_ascii_func_args_geometry { bool check_arguments() const override { // TODO: check with Alexey, for better args[1] and args[2] type control return Item_str_ascii_func_args_geometry::check_arguments() || check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count)); } public: Item_func_as_geojson(THD *thd, Item *js) :Item_str_ascii_func_args_geometry(thd, js) {} Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits) :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {} Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt) :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_asgeojson") }; return name; } bool fix_length_and_dec(THD *thd) override; String *val_str_ascii(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_as_geojson>(thd, this); } }; class Item_func_geometry_type: public Item_str_ascii_func_args_geometry { public: Item_func_geometry_type(THD *thd, Item *a) :Item_str_ascii_func_args_geometry(thd, a) {} String *val_str_ascii(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_geometrytype") }; return name; } bool fix_length_and_dec(THD *thd) override { // "GeometryCollection" is the longest fix_length_and_charset(20, default_charset()); set_maybe_null(); return FALSE; }; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_geometry_type>(thd, this); } }; // #define HEAVY_CONVEX_HULL class Item_func_convexhull: public Item_geometry_func_args_geometry { class ch_node: public Gcalc_dyn_list::Item { public: const Gcalc_heap::Info *pi; ch_node *prev; Gcalc_dyn_list::Item *next; ch_node *get_next() { return (ch_node *) next; } }; Gcalc_heap collector; Gcalc_function func; Gcalc_dyn_list res_heap; Gcalc_result_receiver res_receiver; String tmp_value; #ifdef HEAVY_CONVEX_HULL Gcalc_scan_iterator scan_it; #endif /*HEAVY_CONVEX_HULL*/ ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); } int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi); public: Item_func_convexhull(THD *thd, Item *a) :Item_geometry_func_args_geometry(thd, a), res_heap(8192, sizeof(ch_node)) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_convexhull") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_convexhull>(thd, this); } }; class Item_func_centroid: public Item_geometry_func_args_geometry { public: Item_func_centroid(THD *thd, Item *a) :Item_geometry_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_centroid") }; return name; } String *val_str(String *) override; const Type_handler *type_handler() const override { return &type_handler_point; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_centroid>(thd, this); } }; class Item_func_envelope: public Item_geometry_func_args_geometry { public: Item_func_envelope(THD *thd, Item *a) :Item_geometry_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_envelope") }; return name; } String *val_str(String *) override; const Type_handler *type_handler() const override { return &type_handler_polygon; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_envelope>(thd, this); } }; class Item_func_boundary: public Item_geometry_func_args_geometry { class Transporter : public Gcalc_shape_transporter { Gcalc_result_receiver *m_receiver; uint n_points; Gcalc_function::shape_type current_type; double last_x, last_y; public: Transporter(Gcalc_result_receiver *receiver) : Gcalc_shape_transporter(NULL), m_receiver(receiver) {} int single_point(double x, double y) override; int start_line() override; int complete_line() override; int start_poly() override; int complete_poly() override; int start_ring() override; int complete_ring() override; int add_point(double x, double y) override; int start_collection(int n_objects) override; }; Gcalc_result_receiver res_receiver; public: Item_func_boundary(THD *thd, Item *a) :Item_geometry_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_boundary") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_boundary>(thd, this); } }; class Item_func_point: public Item_geometry_func { bool check_arguments() const override { return check_argument_types_can_return_real(0, 2); } public: Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {} Item_func_point(THD *thd, Item *a, Item *b, Item *srid): Item_geometry_func(thd, a, b, srid) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("point") }; return name; } String *val_str(String *) override; const Type_handler *type_handler() const override { return &type_handler_point; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_point>(thd, this); } }; class Item_func_spatial_decomp: public Item_geometry_func_args_geometry { enum Functype decomp_func; public: Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft): Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING startpoint= {STRING_WITH_LEN("st_startpoint") }; static LEX_CSTRING endpoint= {STRING_WITH_LEN("st_endpoint") }; static LEX_CSTRING exteriorring= {STRING_WITH_LEN("st_exteriorring") }; static LEX_CSTRING unknown= {STRING_WITH_LEN("spatial_decomp_unknown") }; switch (decomp_func) { case SP_STARTPOINT: return startpoint; case SP_ENDPOINT: return endpoint; case SP_EXTERIORRING: return exteriorring; default: DBUG_ASSERT(0); // Should never happened return unknown; } } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_decomp>(thd, this); } }; class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry { enum Functype decomp_func_n; bool check_arguments() const override { return Item_geometry_func_args_geometry::check_arguments() || args[1]->check_type_can_return_int(func_name_cstring()); } public: Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft) :Item_geometry_func_args_geometry(thd, a, b), decomp_func_n(ft) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING pointn= {STRING_WITH_LEN("st_pointn") }; static LEX_CSTRING geometryn= {STRING_WITH_LEN("st_geometryn") }; static LEX_CSTRING interiorringn= {STRING_WITH_LEN("st_interiorringn") }; static LEX_CSTRING unknown= {STRING_WITH_LEN("spatial_decomp_unknown") }; switch (decomp_func_n) { case SP_POINTN: return pointn; case SP_GEOMETRYN: return geometryn; case SP_INTERIORRINGN: return interiorringn; default: DBUG_ASSERT(0); // Should never happened return unknown; } } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_decomp_n>(thd, this); } }; class Item_func_spatial_collection: public Item_geometry_func { bool check_arguments() const override { return Type_handler_geometry::check_types_geom_or_binary(func_name_cstring(), args, 0, arg_count); } enum Geometry::wkbType coll_type; enum Geometry::wkbType item_type; public: Item_func_spatial_collection(THD *thd, List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it): Item_geometry_func(thd, list) { coll_type=ct; item_type=it; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { if (Item_geometry_func::fix_length_and_dec(thd)) return TRUE; for (unsigned int i= 0; i < arg_count; ++i) { if (args[i]->fixed() && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) { String str; args[i]->print(&str, QT_NO_DATA_EXPANSION); str.append('\0'); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric", str.ptr()); return TRUE; } } return FALSE; } }; class Item_func_geometrycollection: public Item_func_spatial_collection { public: Item_func_geometrycollection(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_geometrycollection, Geometry::wkb_point) { } const Type_handler *type_handler() const override { return &type_handler_geometrycollection; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("geometrycollection") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_geometrycollection>(thd, this); } }; class Item_func_linestring: public Item_func_spatial_collection { public: Item_func_linestring(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_linestring, Geometry::wkb_point) { } const Type_handler *type_handler() const override { return &type_handler_linestring; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("linestring") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_linestring>(thd, this); } }; class Item_func_polygon: public Item_func_spatial_collection { public: Item_func_polygon(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_polygon, Geometry::wkb_linestring) { } const Type_handler *type_handler() const override { return &type_handler_polygon; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("polygon") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_polygon>(thd, this); } }; class Item_func_multilinestring: public Item_func_spatial_collection { public: Item_func_multilinestring(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_multilinestring, Geometry::wkb_linestring) { } const Type_handler *type_handler() const override { return &type_handler_multilinestring; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("multilinestring") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_multilinestring>(thd, this); } }; class Item_func_multipoint: public Item_func_spatial_collection { public: Item_func_multipoint(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_multipoint, Geometry::wkb_point) { } const Type_handler *type_handler() const override { return &type_handler_multipoint; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("multipoint") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_multipoint>(thd, this); } }; class Item_func_multipolygon: public Item_func_spatial_collection { public: Item_func_multipolygon(THD *thd, List<Item> &list) :Item_func_spatial_collection(thd, list, Geometry::wkb_multipolygon, Geometry::wkb_polygon) { } const Type_handler *type_handler() const override { return &type_handler_multipolygon; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("multipolygon") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_multipolygon>(thd, this); } }; /* Spatial relations */ class Item_func_spatial_rel: public Item_bool_func2_with_rev { protected: enum Functype spatial_rel; String tmp_value1, tmp_value2; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value) override; bool check_arguments() const override { DBUG_ASSERT(arg_count >= 2); return Type_handler_geometry::check_types_geom_or_binary(func_name_cstring(), args, 0, 2); } public: Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel): Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel) { set_maybe_null(); } enum Functype functype() const override { return spatial_rel; } enum Functype rev_functype() const override { switch (spatial_rel) { case SP_CONTAINS_FUNC: return SP_WITHIN_FUNC; case SP_WITHIN_FUNC: return SP_CONTAINS_FUNC; default: return spatial_rel; } } bool is_null() override { (void) val_int(); return null_value; } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override { return add_key_fields_optimize_op(join, key_fields, and_level, usable_tables, sargables, false); } bool need_parentheses_in_default() override { return false; } Item *deep_copy(THD *thd) const override { return nullptr; } }; class Item_func_spatial_mbr_rel: public Item_func_spatial_rel { public: Item_func_spatial_mbr_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel): Item_func_spatial_rel(thd, a, b, sp_rel) { } bool val_bool() override; LEX_CSTRING func_name_cstring() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_mbr_rel>(thd, this); } }; class Item_func_spatial_precise_rel: public Item_func_spatial_rel { Gcalc_heap collector; Gcalc_scan_iterator scan_it; Gcalc_function func; public: Item_func_spatial_precise_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel): Item_func_spatial_rel(thd, a, b, sp_rel), collector() { } bool val_bool() override; LEX_CSTRING func_name_cstring() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_precise_rel>(thd, this); } }; class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry { Gcalc_heap collector; Gcalc_scan_iterator scan_it; Gcalc_function func; String tmp_value1, tmp_value2, tmp_matrix; bool check_arguments() const override { return Item_bool_func_args_geometry_geometry::check_arguments() || args[2]->check_type_general_purpose_string(func_name_cstring()); } public: Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix): Item_bool_func_args_geometry_geometry(thd, a, b, matrix) { } bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_relate") }; return name; } bool need_parentheses_in_default() override { return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_relate>(thd, this); } }; /* Spatial operations */ class Item_func_spatial_operation final: public Item_geometry_func { bool check_arguments() const override { DBUG_ASSERT(arg_count >= 2); return Type_handler_geometry::check_types_geom_or_binary(func_name_cstring(), args, 0, 2); } public: Gcalc_function::op_type spatial_op; Gcalc_heap collector; Gcalc_function func; Gcalc_result_receiver res_receiver; Gcalc_operation_reducer operation; String tmp_value1,tmp_value2; public: Item_func_spatial_operation(THD *thd, Item *a,Item *b, Gcalc_function::op_type sp_op): Item_geometry_func(thd, a, b), spatial_op(sp_op) {} virtual ~Item_func_spatial_operation(); String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override; void print(String *str, enum_query_type query_type) override { Item_func::print(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_spatial_operation>(thd, this); } }; class Item_func_buffer final : public Item_geometry_func_args_geometry { bool check_arguments() const override { return Item_geometry_func_args_geometry::check_arguments() || args[1]->check_type_can_return_real(func_name_cstring()); } protected: class Transporter : public Gcalc_operation_transporter { int m_npoints; double m_d; double x1,y1,x2,y2; double x00,y00,x01,y01; int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2); int add_last_edge_buffer(); int add_point_buffer(double x, double y); int complete(); int m_nshapes; Gcalc_function::op_type buffer_op; int last_shape_pos; bool skip_line; public: Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) : Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d), m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union : Gcalc_function::op_difference), skip_line(FALSE) {} int single_point(double x, double y) override; int start_line() override; int complete_line() override; int start_poly() override; int complete_poly() override; int start_ring() override; int complete_ring() override; int add_point(double x, double y) override; int start_collection(int n_objects) override; }; Gcalc_heap collector; Gcalc_function func; Gcalc_result_receiver res_receiver; Gcalc_operation_reducer operation; public: Item_func_buffer(THD *thd, Item *obj, Item *distance) :Item_geometry_func_args_geometry(thd, obj, distance) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_buffer") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_buffer>(thd, this); } }; class Item_func_isempty: public Item_bool_func_args_geometry { public: Item_func_isempty(THD *thd, Item *a) :Item_bool_func_args_geometry(thd, a) {} bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_isempty") }; return name; } bool fix_length_and_dec(THD *thd) override { set_maybe_null(); return FALSE; } bool need_parentheses_in_default() override { return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isempty>(thd, this); } }; class Item_func_issimple: public Item_long_func_args_geometry { Gcalc_heap collector; Gcalc_function func; Gcalc_scan_iterator scan_it; String tmp; public: Item_func_issimple(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_issimple") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2; return FALSE; } decimal_digits_t decimal_precision() const override { return 1; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_issimple>(thd, this); } }; class Item_func_isclosed: public Item_long_func_args_geometry { public: Item_func_isclosed(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_isclosed") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2; return FALSE; } decimal_digits_t decimal_precision() const override { return 1; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isclosed>(thd, this); } }; class Item_func_isring: public Item_func_issimple { public: Item_func_isring(THD *thd, Item *a): Item_func_issimple(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_isring") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isring>(thd, this); } }; class Item_func_dimension: public Item_long_func_args_geometry { public: Item_func_dimension(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_dimension") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dimension>(thd, this); } }; class Item_func_x: public Item_real_func_args_geometry { public: Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_x") }; return name; } bool fix_length_and_dec(THD *thd) override { if (Item_real_func::fix_length_and_dec(thd)) return TRUE; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_x>(thd, this); } }; class Item_func_y: public Item_real_func_args_geometry { public: Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_y") }; return name; } bool fix_length_and_dec(THD *thd) override { if (Item_real_func::fix_length_and_dec(thd)) return TRUE; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_y>(thd, this); } }; class Item_func_numgeometries: public Item_long_func_args_geometry { public: Item_func_numgeometries(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_numgeometries") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_numgeometries>(thd, this); } }; class Item_func_numinteriorring: public Item_long_func_args_geometry { public: Item_func_numinteriorring(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_numinteriorrings") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_numinteriorring>(thd, this); } }; class Item_func_numpoints: public Item_long_func_args_geometry { public: Item_func_numpoints(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_numpoints") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_numpoints>(thd, this); } }; class Item_func_area: public Item_real_func_args_geometry { public: Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_area") }; return name; } bool fix_length_and_dec(THD *thd) override { if (Item_real_func::fix_length_and_dec(thd)) return TRUE; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_area>(thd, this); } }; class Item_func_glength: public Item_real_func_args_geometry { String value; public: Item_func_glength(THD *thd, Item *a) :Item_real_func_args_geometry(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_length") }; return name; } bool fix_length_and_dec(THD *thd) override { if (Item_real_func::fix_length_and_dec(thd)) return TRUE; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_glength>(thd, this); } }; class Item_func_srid: public Item_long_func_args_geometry { public: Item_func_srid(THD *thd, Item *a) :Item_long_func_args_geometry(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("srid") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 10; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_srid>(thd, this); } }; class Item_func_distance: public Item_real_func_args_geometry_geometry { String tmp_value1; String tmp_value2; Gcalc_heap collector; Gcalc_function func; Gcalc_scan_iterator scan_it; public: Item_func_distance(THD *thd, Item *a, Item *b) :Item_real_func_args_geometry_geometry(thd, a, b) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_distance") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_distance>(thd, this); } }; class Item_func_sphere_distance: public Item_real_func { double spherical_distance_points(Geometry *g1, Geometry *g2, const double sphere_r); public: Item_func_sphere_distance(THD *thd, List<Item> &list): Item_real_func(thd, list) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_distance_sphere") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sphere_distance>(thd, this); } }; class Item_func_pointonsurface: public Item_geometry_func_args_geometry { String tmp_value; Gcalc_heap collector; Gcalc_function func; Gcalc_scan_iterator scan_it; public: Item_func_pointonsurface(THD *thd, Item *a) :Item_geometry_func_args_geometry(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_pointonsurface") }; return name; } String *val_str(String *) override; const Type_handler *type_handler() const override { return &type_handler_point; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_pointonsurface>(thd, this); } }; #ifndef DBUG_OFF class Item_func_gis_debug: public Item_long_func { public: Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a) { null_value= false; } bool fix_length_and_dec(THD *thd) override { fix_char_length(10); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("st_gis_debug") }; return name; } longlong val_int() override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_gis_debug>(thd, this); } }; #endif #define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor #define GEOM_TYPE(x) (x) #else /*HAVE_SPATIAL*/ #define GEOM_NEW(thd, obj_constructor) NULL #define GEOM_TYPE(x) NULL #endif /*HAVE_SPATIAL*/ #endif /* ITEM_GEOFUNC_INCLUDED */ my_tree.h 0000644 00000007627 15156036153 0006402 0 ustar 00 /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _tree_h #define _tree_h #ifdef __cplusplus extern "C" { #endif #include "my_base.h" /* get 'enum ha_rkey_function' */ #include "my_alloc.h" /* MEM_ROOT */ /* Worst case tree is half full. This gives use 2^(MAX_TREE_HEIGHT/2) leafs */ #define MAX_TREE_HEIGHT 64 #define ELEMENT_KEY(tree,element)\ (tree->offset_to_key ? (void*)((uchar*) element+tree->offset_to_key) :\ *((void**) (element+1))) #define tree_set_pointer(element,ptr) *((uchar **) (element+1))=((uchar*) (ptr)) /* A tree with its flag set to TREE_ONLY_DUPS behaves differently on inserting an element that is not in the tree: the element is not added at all, but instead tree_insert() returns a special address TREE_ELEMENT_UNIQUE as an indication that the function has not failed due to lack of memory. */ #define TREE_ELEMENT_UNIQUE ((TREE_ELEMENT *) 1) #define TREE_NO_DUPS 1 #define TREE_ONLY_DUPS 2 typedef enum { left_root_right, right_root_left } TREE_WALK; typedef uint32 element_count; typedef int (*tree_walk_action)(void *,element_count,void *); typedef enum { free_init, free_free, free_end } TREE_FREE; typedef int (*tree_element_free)(void*, TREE_FREE, void *); typedef struct st_tree_element { struct st_tree_element *left,*right; uint32 count:31, colour:1; /* black is marked as 1 */ } TREE_ELEMENT; #define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs)) typedef struct st_tree { TREE_ELEMENT *root; TREE_ELEMENT **parents[MAX_TREE_HEIGHT]; uint offset_to_key,elements_in_tree,size_of_element; size_t memory_limit, allocated; qsort_cmp2 compare; void *custom_arg; MEM_ROOT mem_root; my_bool with_delete; tree_element_free free; myf my_flags; uint flag; } TREE; /* Functions on whole tree */ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, int size, qsort_cmp2 compare, tree_element_free free_element, void *custom_arg, myf my_flags); int delete_tree(TREE*, my_bool abort); int reset_tree(TREE*); /* similar to delete tree, except we do not my_free() blocks in mem_root */ #define is_tree_inited(tree) ((tree)->root != 0) /* Functions on leafs */ TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size, void *custom_arg); void *tree_search(TREE *tree, void *key, void *custom_arg); int tree_walk(TREE *tree,tree_walk_action action, void *argument, TREE_WALK visit); int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg); void *tree_search_key(TREE *tree, const void *key, TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, enum ha_rkey_function flag, void *custom_arg); void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, int child_offs); void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, int r_offs); ha_rows tree_record_pos(TREE *tree, const void *key, enum ha_rkey_function search_flag, void *custom_arg); #define reset_free_element(tree) (tree)->free= 0 #define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*)) #ifdef __cplusplus } #endif #endif sql_mode.h 0000644 00000015117 15156036153 0006532 0 ustar 00 #ifndef SQL_MODE_H_INCLUDED #define SQL_MODE_H_INCLUDED /* Copyright (c) 2019, MariaDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_basic_types.h" /* class Sql_mode_dependency A combination of hard and soft dependency on sql_mode. Used to watch if a GENERATED ALWAYS AS expression guarantees consitent data written to its virtual column. A virtual column can appear in an index if: - the generation expression does not depend on any sql_mode flags, or - the generation expression has a soft dependency on an sql_mode flag, and the column knows how to handle this dependeny. A virtual column cannot appear in an index if: - its generation expression has a hard dependency - its generation expression has a soft dependency, but the column cannot handle it on store. An error is reported in such cases. How dependencies appear: - When a column return value depends on some sql_mode flag, its Item_field adds a corresponding bit to m_soft. For example, Item_field for a CHAR(N) column adds the PAD_CHAR_TO_FULL_LENGTH flag. - When an SQL function/operator return value depends on some sql_mode flag, it adds a corresponding bit to m_soft. For example, Item_func_minus adds the MODE_NO_UNSIGNED_SUBTRACTION in case of unsigned arguments. How dependency are processed (see examples below): - All SQL functions/operators bit-OR all hard dependencies from all arguments. - Some soft dependencies can be handled by the underlying Field on store, e.g. CHAR(N) can handle PAD_CHAR_TO_FULL_LENGTH. - Some soft dependencies can be handled by SQL functions and operators, e.g. RTRIM(expr) removes expr's soft dependency on PAD_CHAR_TO_FULL_LENGTH. If a function or operator handles a soft dependency on a certain sql_mode flag, it removes the corresponding bit from m_soft (see below). Note, m_hard is not touched in such cases. - When an expression with a soft dependency on a certain sql_mode flag goes as an argument to an SQL function/operator which cannot handle this flag, the dependency escalates from soft to hard (by moving the corresponding bit from m_soft to m_hard) and cannot be handled any more on the upper level, neither by a Field on store, nor by another SQL function/operator. There are four kinds of Items: 1. Items that generate a soft or hard dependency, e.g. - Item_field for CHAR(N) - generates soft/PAD_CHAR_TO_FULL_LENGTH - Item_func_minus - generates soft/NO_UNSIGNED_SUBTRACTION 2. Items that convert a soft dependency to a hard dependency. This happens e.g. when an Item_func instance gets a soft dependency from its arguments, and it does not know how to handle this dependency. Most Item_func descendants do this. 3. Items that remove soft dependencies, e.g.: - Item_func_rtrim - removes soft/PAD_CHAR_TO_FULL_LENGTH that came from args[0] (under certain conditions) - Item_func_rpad - removes soft/PAD_CJAR_TO_FULL_LENGTH that came from args[0] (under certain conditions) 4. Items that repeat soft dependency from its arguments to the caller. They are not implemented yet. But functions like Item_func_coalesce, Item_func_case, Item_func_case_abbreviation2 could do this. Examples: 1. CREATE OR REPLACE TABLE t1 (a CHAR(5), v CHAR(20) AS(a), KEY(v)); Here `v` has a soft dependency on `a`. The value of `a` depends on PAD_CHAR_TO_FULL_LENGTH, it can return: - 'a' - if PAD_CHAR_TO_FULL_LENGTH is disabled - 'a' followed by four spaces - if PAD_CHAR_TO_FULL_LENGTH is enabled But `v` will pad trailing spaces to the full length on store anyway. So Field_string handles this soft dependency on store. This combination of the virtial column data type and its generation expression is safe and provides consistent data in `v`, which is 'a' followed by four spaces, no matter what PAD_CHAR_TO_FULL_LENGTH is. 2. CREATE OR REPLACE TABLE t1 (a CHAR(5), v VARCHAR(20) AS(a), KEY(v)); Here `v` has a soft dependency on `a`. But Field_varstring does not pad spaces on store, so it cannot handle this dependency. This combination of the virtual column data type and its generation expression is not safe. An error is returned. 3. CREATE OR REPLACE TABLE t1 (a CHAR(5), v INT AS(LENGTH(a)), KEY(v)); Here `v` has a hard dependency on `a`, because the value of `a` is wrapped to the function LENGTH(). The value of `LENGTH(a)` depends on PAD_CHAR_TO_FULL_LENGTH, it can return: - 1 - if PAD_CHAR_TO_FULL_LENGTH is disabled - 4 - if PAD_CHAR_TO_FULL_LENGTH is enabled This combination cannot provide consistent data stored to `v`, therefore it's disallowed. */ class Sql_mode_dependency { sql_mode_t m_hard; sql_mode_t m_soft; public: Sql_mode_dependency() :m_hard(0), m_soft(0) { } Sql_mode_dependency(sql_mode_t hard, sql_mode_t soft) :m_hard(hard), m_soft(soft) { } sql_mode_t hard() const { return m_hard; } sql_mode_t soft() const { return m_soft; } operator bool () const { return m_hard > 0 || m_soft > 0; } Sql_mode_dependency operator|(const Sql_mode_dependency &other) const { return Sql_mode_dependency(m_hard | other.m_hard, m_soft | other.m_soft); } Sql_mode_dependency operator&(const Sql_mode_dependency &other) const { return Sql_mode_dependency(m_hard & other.m_hard, m_soft & other.m_soft); } Sql_mode_dependency &operator|=(const Sql_mode_dependency &other) { m_hard|= other.m_hard; m_soft|= other.m_soft; return *this; } Sql_mode_dependency &operator&=(const Sql_mode_dependency &other) { m_hard&= other.m_hard; m_soft&= other.m_soft; return *this; } Sql_mode_dependency &soft_to_hard() { m_hard|= m_soft; m_soft= 0; return *this; } void push_dependency_warnings(THD *thd) const; }; #endif // SQL_MODE_H_INCLUDED optimizer_defaults.h 0000644 00000016571 15156036153 0010645 0 ustar 00 #ifndef OPTIMIZER_DEFAULTS_INCLUDED #define OPTIMIZER_DEFAULTS_INCLUDED /* Copyright (c) 2022, MariaDB AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file contains costs constants used by the optimizer All costs should be based on milliseconds (1 cost = 1 ms) */ /* Cost for finding the first key in a key scan */ #define DEFAULT_KEY_LOOKUP_COST ((double) 0.000435777) /* Cost of finding a row based on row_ID */ #define DEFAULT_ROW_LOOKUP_COST ((double) 0.000130839) /* Cost of finding and copying key and row blocks from the storage engine index cache to an internal cache as part of an index scan. This includes all mutexes that needs to be taken to get exclusive access to a page. The number is taken from accessing an existing blocks from Aria page cache. Used in handler::scan_time() and handler::keyread_time() */ #define DEFAULT_INDEX_BLOCK_COPY_COST ((double) 3.56e-05) /* Cost of copying a row to 'table->record'. Used by scan_time() and rnd_pos_time() methods. If this is too small, then table scans will be prefered over 'ref' as with table scans there are no key read (KEY_LOOKUP_COST), fewer disk reads but more record copying and row comparisions. If it's too big then MariaDB will used key lookup even when table scan is better. */ #define DEFAULT_ROW_COPY_COST ((double) 0.000060866) /* Cost of copying the key to 'table->record' If this is too small, then, for small tables, index scans will be prefered over 'ref' as with index scans there are fewer disk reads. */ #define DEFAULT_KEY_COPY_COST ((double) 0.000015685) /* Cost of finding the next index entry and checking its rowid against filter This cost is very low as it's done inside the storage engine. Should be smaller than KEY_COPY_COST. */ #define DEFAULT_KEY_NEXT_FIND_COST ((double) 0.000082347) /* Cost of finding the next row when scanning a table */ #define DEFAULT_ROW_NEXT_FIND_COST ((double) 0.000045916) /** The cost of executing the WHERE clause as part of any row check. Increasing this would force the optimizer to use row combinations that reads fewer rows. The default cost comes from recording times from a simple where clause that compares two fields (date and a double) with constants. */ #define DEFAULT_WHERE_COST ((double) 3.2e-05) /* The cost of comparing a key when using range access or sorting */ #define DEFAULT_KEY_COMPARE_COST 0.000011361 /* Rowid compare is usually just a single memcmp of a short string */ #define DEFAULT_ROWID_COMPARE_COST 0.000002653 /* Rowid copy is usually just a single memcpy of a short string */ #define DEFAULT_ROWID_COPY_COST 0.000002653 /* Cost modifiers rowid_filter. These takes into account the overhead of using and calling Rowid_filter_sorted_array::check() from the engine */ #define ROWID_FILTER_PER_CHECK_MODIFIER 4 /* times key_copy_cost */ #define ROWID_FILTER_PER_ELEMENT_MODIFIER 1 /* times rowid_compare_cost */ /* Average disk seek time on a hard disk is 8-10 ms, which is also about the time to read a IO_SIZE (8192) block. A medium ssd is about 400MB/second, which gives us the time for reading an IO_SIZE block to IO_SIZE/400000000 = 0.0000204 sec= 0.02 ms. */ #define DEFAULT_DISK_READ_COST ((double) IO_SIZE / 400000000.0 * 1000) /* The follwoing is an old comment for hard-disks, please ignore the following, except if you like history: For sequential hard disk seeks the cost formula is: DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST * #blocks_to_skip The cost of average seek DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST*BLOCKS_IN_AVG_SEEK = 10. */ /* The table/index cache_miss/total_cache_request ratio. 1.0 means that a searched for key or row will never be in the cache while 0.0 means it always in the cache (and we don't have to do any disk reads). According to folklore, one should not have to access disk for more than 20% of the cache request for MariaDB to run very well. However in practice when we read rows or keys in a query, we will often read the same row over and over again. Because of this we set DEFAULT_DISK_READ_RATIO to 0.20/10 = 0.02. Increasing DISK_READ_RATIO will make MariaDB prefer key lookup over table scans as the impact of ROW_COPY_COST and INDEX_COPY cost will have a larger impact when more rows are examined.. We are not yet taking into account cache usage statistics as this could confuse users as the EXPLAIN and costs for a query would change between to query calls, which may confuse users (and also make the mtr tests very unpredictable). Note that the engine's avg_io_cost() (DEFAULT_DISK_READ_COST by default) is multiplied with this constant! */ #define DEFAULT_DISK_READ_RATIO 0.02 /* The following costs are mainly to ensure we don't do table and index scans for small tables, like the one we have in the mtr test suite. This is mostly to keep the mtr tests use indexes (as the optimizer would if the tables are large). It will also ensure that EXPLAIN is showing more key user for users where they are testing queries with small tables at the start of projects. This is probably OK for most a the execution time difference between table scan and index scan compared to key lookups so small when using small tables. It also helps to fill the index cache which will help mitigate the speed difference. */ /* Extra cost for full table and index scan. Used to prefer key and range over index and table scans INDEX_SCAN_SETUP_COST (defined in optimizer_costs.h) is half of table_scan_setup_cost to get the optimizer to prefer index scans to table scans as key copy is faster than row copy and index blocks provides more information in the cache. This will also help MyISAM as with MyISAM the table scans has a cost very close to index scans (they are fast but require a read call that we want to avoid even if it's small). 10 usec is about 10 MyISAM row lookups with optimizer_disk_read_ratio= 0.02 */ #define DEFAULT_TABLE_SCAN_SETUP_COST 0.01 // 10 usec /* Extra cost for doing a range scan. Used to prefer 'ref' over range */ #define MULTI_RANGE_READ_SETUP_COST KEY_LOOKUP_COST /* Temporary file and temporary table related costs Used with subquery materialization, derived tables etc */ #define TMPFILE_CREATE_COST 0.5 // Cost of creating and deleting files #define HEAP_TEMPTABLE_CREATE_COST 0.025 // ms /* Cost taken from HEAP_LOOKUP_COST in ha_heap.cc */ #define HEAP_TEMPTABLE_LOOKUP_COST (0.00016097) #define DISK_TEMPTABLE_LOOKUP_COST(thd) (tmp_table_optimizer_costs.key_lookup_cost + tmp_table_optimizer_costs.row_lookup_cost + tmp_table_optimizer_costs.row_copy_cost) #define DISK_TEMPTABLE_CREATE_COST TMPFILE_CREATE_COST*2 // 2 tmp tables #define DISK_TEMPTABLE_BLOCK_SIZE IO_SIZE #endif /* OPTIMIZER_DEFAULTS_INCLUDED */ lex_symbol.h 0000644 00000002453 15156036154 0007104 0 ustar 00 /* Copyright (c) 2000, 2001, 2004, 2006, 2007 MySQL AB Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This struct includes all reserved words and functions */ #ifndef _lex_symbol_h #define _lex_symbol_h struct st_sym_group; typedef struct st_symbol { const char *name; uint tok; uint length; struct st_sym_group *group; } SYMBOL; typedef struct st_lex_symbol { SYMBOL *symbol; char *str; uint length; } LEX_SYMBOL; typedef struct st_sym_group { const char *name; const char *needed_define; } SYM_GROUP; extern SYM_GROUP sym_group_common; extern SYM_GROUP sym_group_geom; extern SYM_GROUP sym_group_rtree; #endif /* _lex_symbol_h */ sql_hset.h 0000644 00000006511 15156036154 0006550 0 ustar 00 #ifndef SQL_HSET_INCLUDED #define SQL_HSET_INCLUDED /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_global.h" #include "hash.h" /** A type-safe wrapper around mysys HASH. */ template <typename T> class Hash_set { public: enum { START_SIZE= 8 }; /** Constructs an empty unique hash. */ Hash_set(PSI_memory_key psi_key, const uchar *(*K)(const void *, size_t *, my_bool), CHARSET_INFO *cs= &my_charset_bin) { my_hash_init(psi_key, &m_hash, cs, START_SIZE, 0, 0, K, 0, HASH_UNIQUE); } Hash_set(PSI_memory_key psi_key, CHARSET_INFO *charset, ulong default_array_elements, size_t key_offset, size_t key_length, my_hash_get_key get_key, void (*free_element)(void*), uint flags) { my_hash_init(psi_key, &m_hash, charset, default_array_elements, key_offset, key_length, get_key, free_element, flags); } /** Destroy the hash by freeing the buckets table. Does not call destructors for the elements. */ ~Hash_set() { my_hash_free(&m_hash); } /** Insert a single value into a hash. Does not tell whether the value was inserted -- if an identical value existed, it is not replaced. @retval TRUE Out of memory. @retval FALSE OK. The value either was inserted or existed in the hash. */ bool insert(T *value) { return my_hash_insert(&m_hash, reinterpret_cast<const uchar*>(value)); } bool remove(T *value) { return my_hash_delete(&m_hash, reinterpret_cast<uchar*>(value)); } T *find(const void *key, size_t klen) const { return (T*)my_hash_search(&m_hash, reinterpret_cast<const uchar *>(key), klen); } /** Is this hash set empty? */ bool is_empty() const { return m_hash.records == 0; } /** Returns the number of unique elements. */ size_t size() const { return static_cast<size_t>(m_hash.records); } /** Erases all elements from the container */ void clear() { my_hash_reset(&m_hash); } const T* at(size_t i) const { return reinterpret_cast<T*>(my_hash_element(const_cast<HASH*>(&m_hash), i)); } /** An iterator over hash elements. Is not insert-stable. */ class Iterator { public: Iterator(Hash_set &hash_set) : m_hash(&hash_set.m_hash), m_idx(0) {} /** Return the current element and reposition the iterator to the next element. */ inline T *operator++(int) { if (m_idx < m_hash->records) return reinterpret_cast<T*>(my_hash_element(m_hash, m_idx++)); return NULL; } void rewind() { m_idx= 0; } private: HASH *m_hash; uint m_idx; }; private: HASH m_hash; }; #endif // SQL_HSET_INCLUDED my_check_opt.h 0000644 00000005072 15156036154 0007373 0 ustar 00 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_check_opt_h #define _my_check_opt_h #ifdef __cplusplus extern "C" { #endif /* All given definitions needed for MyISAM storage engine: myisamchk.c or/and ha_myisam.cc or/and micheck.c Some definitions are needed by the MySQL parser. */ #define T_AUTO_INC (1UL << 0) #define T_AUTO_REPAIR (1UL << 1) #define T_BACKUP_DATA (1UL << 2) #define T_CALC_CHECKSUM (1UL << 3) #define T_CHECK (1UL << 4) #define T_CHECK_ONLY_CHANGED (1UL << 5) #define T_CREATE_MISSING_KEYS (1UL << 6) #define T_DESCRIPT (1UL << 7) #define T_DONT_CHECK_CHECKSUM (1UL << 8) #define T_EXTEND (1UL << 9) #define T_FAST (1UL << 10) #define T_FORCE_CREATE (1UL << 11) #define T_FORCE_UNIQUENESS (1UL << 12) #define T_INFO (1UL << 13) /** CHECK TABLE...MEDIUM (the default) */ #define T_MEDIUM (1UL << 14) /** CHECK TABLE...QUICK */ #define T_QUICK (1UL << 15) #define T_READONLY (1UL << 16) #define T_REP (1UL << 17) #define T_REP_BY_SORT (1UL << 18) #define T_REP_PARALLEL (1UL << 19) #define T_RETRY_WITHOUT_QUICK (1UL << 20) #define T_SAFE_REPAIR (1UL << 21) #define T_SILENT (1UL << 22) #define T_SORT_INDEX (1UL << 23) #define T_SORT_RECORDS (1UL << 24) #define T_STATISTICS (1UL << 25) #define T_UNPACK (1UL << 26) #define T_UPDATE_STATE (1UL << 27) #define T_VERBOSE (1UL << 28) #define T_VERY_SILENT (1UL << 29) #define T_WAIT_FOREVER (1UL << 30) #define T_WRITE_LOOP (1UL << 31) #define T_ZEROFILL (1ULL << 32) #define T_ZEROFILL_KEEP_LSN (1ULL << 33) /** If repair should not bump create_rename_lsn */ #define T_NO_CREATE_RENAME_LSN (1ULL << 34) /** If repair shouldn't do any locks */ #define T_NO_LOCKS (1ULL << 35) #define T_CREATE_UNIQUE_BY_SORT (1ULL << 36) #define T_SUPPRESS_ERR_HANDLING (1ULL << 37) #define T_FORCE_SORT_MEMORY (1ULL << 38) #define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL) #ifdef __cplusplus } #endif #endif semisync_slave.h 0000644 00000007230 15156036154 0007751 0 ustar 00 /* Copyright (c) 2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEMISYNC_SLAVE_H #define SEMISYNC_SLAVE_H #include "semisync.h" #include "my_global.h" #include "sql_priv.h" #include "rpl_mi.h" #include "mysql.h" #include <sql_common.h> class Master_info; /** The extension class for the slave of semi-synchronous replication */ class Repl_semi_sync_slave :public Repl_semi_sync_base { public: Repl_semi_sync_slave() :m_slave_enabled(false) {} ~Repl_semi_sync_slave() = default; void set_trace_level(unsigned long trace_level) { m_trace_level = trace_level; } /* Initialize this class after MySQL parameters are initialized. this * function should be called once at bootstrap time. */ int init_object(); inline bool get_slave_enabled() { return m_slave_enabled; } void set_slave_enabled(bool enabled) { m_slave_enabled = enabled; } inline bool is_delay_master(){ return m_delay_master; } void set_delay_master(bool enabled) { m_delay_master = enabled; } void set_kill_conn_timeout(unsigned int timeout) { m_kill_conn_timeout = timeout; } /* A slave reads the semi-sync packet header and separate the metadata * from the payload data. * * Input: * header - (IN) packet header pointer * total_len - (IN) total packet length: metadata + payload * semi_flags - (IN) store flags: SEMI_SYNC_SLAVE_DELAY_SYNC and SEMI_SYNC_NEED_ACK * payload - (IN) payload: the replication event * payload_len - (IN) payload length * * Return: * 0: success; non-zero: error */ int slave_read_sync_header(const uchar *header, unsigned long total_len, int *semi_flags, const uchar **payload, unsigned long *payload_len); /* A slave replies to the master indicating its replication process. It * indicates that the slave has received all events before the specified * binlog position. */ int slave_reply(Master_info* mi); void slave_start(Master_info *mi); void slave_stop(Master_info *mi); void slave_reconnect(Master_info *mi); int request_transmit(Master_info *mi); void kill_connection(Master_info *mi); private: /* True when init_object has been called */ bool m_init_done; bool m_slave_enabled; /* semi-sync is enabled on the slave */ bool m_delay_master; unsigned int m_kill_conn_timeout; }; /* System and status variables for the slave component */ extern my_bool global_rpl_semi_sync_slave_enabled; extern ulong rpl_semi_sync_slave_trace_level; extern Repl_semi_sync_slave repl_semisync_slave; extern char rpl_semi_sync_slave_delay_master; extern unsigned int rpl_semi_sync_slave_kill_conn_timeout; extern unsigned long long rpl_semi_sync_slave_send_ack; extern int rpl_semi_sync_enabled(THD *thd, SHOW_VAR *var, void *buff, system_status_var *status_var, enum_var_type scope); #endif /* SEMISYNC_SLAVE_H */ partition_info.h 0000644 00000046630 15156036154 0007760 0 ustar 00 #ifndef PARTITION_INFO_INCLUDED #define PARTITION_INFO_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_class.h" #include "partition_element.h" #include "sql_partition.h" class partition_info; struct TABLE_LIST; /* Some function typedefs */ typedef int (*get_part_id_func)(partition_info *part_info, uint32 *part_id, longlong *func_value); typedef int (*get_subpart_id_func)(partition_info *part_info, uint32 *part_id); typedef bool (*check_constants_func)(THD *thd, partition_info *part_info); struct st_ddl_log_memory_entry; #define MAX_PART_NAME_SIZE 8 struct Vers_part_info : public Sql_alloc { Vers_part_info() : limit(0), auto_hist(false), now_part(NULL), hist_part(NULL) { interval.type= INTERVAL_LAST; } Vers_part_info(const Vers_part_info &src) : interval(src.interval), limit(src.limit), auto_hist(src.auto_hist), now_part(NULL), hist_part(NULL) { } Vers_part_info& operator= (const Vers_part_info &src) { interval= src.interval; limit= src.limit; auto_hist= src.auto_hist; now_part= src.now_part; hist_part= src.hist_part; return *this; } bool initialized() { if (now_part) { DBUG_ASSERT(now_part->id != UINT_MAX32); DBUG_ASSERT(now_part->type == partition_element::CURRENT); if (hist_part) { DBUG_ASSERT(hist_part->id != UINT_MAX32); DBUG_ASSERT(hist_part->type == partition_element::HISTORY); } return true; } return false; } struct interval_t { my_time_t start; INTERVAL step; enum interval_type type; bool is_set() const { return type < INTERVAL_LAST; } bool operator==(const interval_t &rhs) const { /* TODO: equivalent intervals like 1 hour and 60 mins should be considered equal */ return start == rhs.start && type == rhs.type && !memcmp(&step, &rhs.step, sizeof(INTERVAL)); } } interval; ulonglong limit; bool auto_hist; partition_element *now_part; partition_element *hist_part; }; /* See generate_partition_syntax() for details of how the data is used in partition expression. */ class partition_info : public DDL_LOG_STATE, public Sql_alloc { public: /* * Here comes a set of definitions needed for partitioned table handlers. */ List<partition_element> partitions; List<partition_element> temp_partitions; /* These are mutually exclusive with part_expr/subpart_expr depending on what is specified in partitioning filter: expression or column list. */ List<const char> part_field_list; List<const char> subpart_field_list; /* If there is no subpartitioning, use only this func to get partition ids. If there is subpartitioning, use the this func to get partition id when you have both partition and subpartition fields. */ get_part_id_func get_partition_id; /* Get partition id when we don't have subpartition fields */ get_part_id_func get_part_partition_id; /* Get subpartition id when we have don't have partition fields by we do have subpartition ids. Mikael said that for given constant tuple {subpart_field1, ..., subpart_fieldN} the subpartition id will be the same in all subpartitions */ get_subpart_id_func get_subpartition_id; /* When we have various string fields we might need some preparation before and clean-up after calling the get_part_id_func's. We need one such method for get_part_partition_id and one for get_subpartition_id. */ get_part_id_func get_part_partition_id_charset; get_subpart_id_func get_subpartition_id_charset; check_constants_func check_constants; /* NULL-terminated array of fields used in partitioned expression */ Field **part_field_array; Field **subpart_field_array; Field **part_charset_field_array; Field **subpart_charset_field_array; /* Array of all fields used in partition and subpartition expression, without duplicates, NULL-terminated. */ Field **full_part_field_array; /* Set of all fields used in partition and subpartition expression. Required for testing of partition fields in write_set when updating. We need to set all bits in read_set because the row may need to be inserted in a different [sub]partition. */ MY_BITMAP full_part_field_set; /* When we have a field that requires transformation before calling the partition functions we must allocate field buffers for the field of the fields in the partition function. */ uchar **part_field_buffers; uchar **subpart_field_buffers; uchar **restore_part_field_ptrs; uchar **restore_subpart_field_ptrs; Item *part_expr; Item *subpart_expr; Item *item_free_list; /* Bitmaps of partitions used by the current query. * read_partitions - partitions to be used for reading. * lock_partitions - partitions that must be locked (read or write). Usually read_partitions is the same set as lock_partitions, but in case of UPDATE the WHERE clause can limit the read_partitions set, but not neccesarily the lock_partitions set. Usage pattern: * Initialized in ha_partition::open(). * read+lock_partitions is set according to explicit PARTITION, WL#5217, in open_and_lock_tables(). * Bits in read_partitions can be cleared in prune_partitions() in the optimizing step. (WL#4443 is about allowing prune_partitions() to affect lock_partitions and be done before locking too). * When the partition enabled handler get an external_lock call it locks all partitions in lock_partitions (and remembers which partitions it locked, so that it can unlock them later). In case of LOCK TABLES it will lock all partitions, and keep them locked while lock_partitions can change for each statement under LOCK TABLES. * Freed at the same time item_free_list is freed. */ MY_BITMAP read_partitions; MY_BITMAP lock_partitions; bool bitmaps_are_initialized; union { longlong *range_int_array; LIST_PART_ENTRY *list_array; part_column_list_val *range_col_array; part_column_list_val *list_col_array; }; Vers_part_info *vers_info; /******************************************** * INTERVAL ANALYSIS ********************************************/ /* Partitioning interval analysis function for partitioning, or NULL if interval analysis is not supported for this kind of partitioning. */ get_partitions_in_range_iter get_part_iter_for_interval; /* Partitioning interval analysis function for subpartitioning, or NULL if interval analysis is not supported for this kind of partitioning. */ get_partitions_in_range_iter get_subpart_iter_for_interval; /******************************************** * INTERVAL ANALYSIS ENDS ********************************************/ longlong err_value; char* part_info_string; partition_element *curr_part_elem; // part or sub part partition_element *current_partition; // partition part_elem_value *curr_list_val; uint curr_list_object; uint num_columns; TABLE *table; /* These key_map's are used for Partitioning to enable quick decisions on whether we can derive more information about which partition to scan just by looking at what index is used. */ key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF; key_map some_fields_in_PF; handlerton *default_engine_type; partition_type part_type; partition_type subpart_type; uint part_info_len; uint num_parts; uint num_subparts; uint count_curr_subparts; // used during parsing uint num_list_values; uint num_part_fields; uint num_subpart_fields; uint num_full_part_fields; uint has_null_part_id; uint32 default_partition_id; /* This variable is used to calculate the partition id when using LINEAR KEY/HASH. This functionality is kept in the MySQL Server but mainly of use to handlers supporting partitioning. */ uint16 linear_hash_mask; /* PARTITION BY KEY ALGORITHM=N Which algorithm to use for hashing the fields. N = 1 - Use 5.1 hashing (numeric fields are hashed as binary) N = 2 - Use 5.5 hashing (numeric fields are hashed like latin1 bytes) */ enum enum_key_algorithm { KEY_ALGORITHM_NONE= 0, KEY_ALGORITHM_51= 1, KEY_ALGORITHM_55= 2 }; enum_key_algorithm key_algorithm; /* Only the number of partitions defined (uses default names and options). */ bool use_default_partitions; bool use_default_num_partitions; /* Only the number of subpartitions defined (uses default names etc.). */ bool use_default_subpartitions; bool use_default_num_subpartitions; bool default_partitions_setup; bool defined_max_value; inline bool has_default_partititon() { return (part_type == LIST_PARTITION && defined_max_value); } bool list_of_part_fields; // KEY or COLUMNS PARTITIONING bool list_of_subpart_fields; // KEY SUBPARTITIONING bool linear_hash_ind; // LINEAR HASH/KEY bool fixed; bool is_auto_partitioned; bool has_null_value; bool column_list; // COLUMNS PARTITIONING, 5.5+ partition_info() : get_partition_id(NULL), get_part_partition_id(NULL), get_subpartition_id(NULL), part_field_array(NULL), subpart_field_array(NULL), part_charset_field_array(NULL), subpart_charset_field_array(NULL), full_part_field_array(NULL), part_field_buffers(NULL), subpart_field_buffers(NULL), restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL), part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), bitmaps_are_initialized(FALSE), list_array(NULL), vers_info(NULL), err_value(0), part_info_string(NULL), curr_part_elem(NULL), current_partition(NULL), curr_list_object(0), num_columns(0), table(NULL), default_engine_type(NULL), part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION), part_info_len(0), num_parts(0), num_subparts(0), count_curr_subparts(0), num_list_values(0), num_part_fields(0), num_subpart_fields(0), num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0), key_algorithm(KEY_ALGORITHM_NONE), use_default_partitions(TRUE), use_default_num_partitions(TRUE), use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE), default_partitions_setup(FALSE), defined_max_value(FALSE), list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), has_null_value(FALSE), column_list(FALSE) { bzero((DDL_LOG_STATE *) this, sizeof(DDL_LOG_STATE)); all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); all_fields_in_SPF.clear_all(); some_fields_in_PF.clear_all(); partitions.empty(); temp_partitions.empty(); part_field_list.empty(); subpart_field_list.empty(); } ~partition_info() = default; partition_info *get_clone(THD *thd, bool empty_data_and_index_file= FALSE); bool set_named_partition_bitmap(const char *part_name, size_t length); bool set_partition_bitmaps(List<String> *partition_names); /* Answers the question if subpartitioning is used for a certain table */ bool is_sub_partitioned() { return (subpart_type == NOT_A_PARTITION ? FALSE : TRUE); } /* Returns the total number of partitions on the leaf level */ uint get_tot_partitions() { return num_parts * (is_sub_partitioned() ? num_subparts : 1); } bool set_up_defaults_for_partitioning(THD *thd, handler *file, HA_CREATE_INFO *info, uint start_no); const char *find_duplicate_field(); char *find_duplicate_name(); bool check_engine_mix(handlerton *engine_type, bool default_engine); bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, partition_info *add_or_reorg_part= NULL); void print_no_partition_found(TABLE *table, myf errflag); void print_debug(const char *str, uint*); Item* get_column_item(Item *item, Field *field); int fix_partition_values(THD *thd, part_elem_value *val, partition_element *part_elem); bool fix_column_value_functions(THD *thd, part_elem_value *val, uint part_id); bool fix_parser_data(THD *thd); int add_max_value(THD *thd); void init_col_val(part_column_list_val *col_val, Item *item); int reorganize_into_single_field_col_val(THD *thd); part_column_list_val *add_column_value(THD *thd); bool set_part_expr(THD *thd, Item *item_ptr, bool is_subpart); bool set_up_charset_field_preps(THD *thd); bool check_partition_field_length(); bool init_column_part(THD *thd); bool add_column_list_value(THD *thd, Item *item); partition_element *get_part_elem(const char *partition_name, char *file_name, size_t file_name_size, uint32 *part_id); void report_part_expr_error(bool use_subpart_expr); bool has_same_partitioning(partition_info *new_part_info); bool error_if_requires_values() const; private: bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info, uint start_no); bool set_up_default_subpartitions(THD *thd, handler *file, HA_CREATE_INFO *info); char *create_default_partition_names(THD *thd, uint part_no, uint num_parts, uint start_no); char *create_default_subpartition_name(THD *thd, uint subpart_no, const char *part_name); bool prune_partition_bitmaps(List<String> *partition_names); // set_read_partitions() in 8.0 bool add_named_partition(const char *part_name, size_t length); public: bool has_unique_name(partition_element *element); bool field_in_partition_expr(Field *field) const; bool vers_init_info(THD *thd); bool vers_set_interval(THD *thd, Item *interval, interval_type int_type, Item *starts, bool auto_part, const char *table_name); bool vers_set_limit(ulonglong limit, bool auto_part, const char *table_name); bool vers_set_hist_part(THD* thd, uint *create_count); bool vers_require_hist_part(THD *thd) const { return part_type == VERSIONING_PARTITION && thd->lex->vers_history_generating(); } void vers_check_limit(THD *thd); bool vers_fix_field_list(THD *thd); void vers_update_el_ids(); partition_element *get_partition(uint part_id) { List_iterator<partition_element> it(partitions); partition_element *el; while ((el= it++)) { if (el->id == part_id) return el; } return NULL; } uint next_part_no(uint new_parts) const; int gen_part_type(THD *thd, String *str) const; }; void part_type_error(THD *thd, partition_info *work_part_info, const char *part_type, partition_info *tab_part_info); uint32 get_next_partition_id_range(struct st_partition_iter* part_iter); bool check_partition_dirs(partition_info *part_info); bool vers_create_partitions(THD* thd, TABLE_LIST* tl, uint num_parts); /* Initialize the iterator to return a single partition with given part_id */ static inline void init_single_partition_iterator(uint32 part_id, PARTITION_ITERATOR *part_iter) { part_iter->part_nums.start= part_iter->part_nums.cur= part_id; part_iter->part_nums.end= part_id+1; part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE; part_iter->get_next= get_next_partition_id_range; } /* Initialize the iterator to enumerate all partitions */ static inline void init_all_partitions_iterator(partition_info *part_info, PARTITION_ITERATOR *part_iter) { part_iter->part_nums.start= part_iter->part_nums.cur= 0; part_iter->part_nums.end= part_info->num_parts; part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE; part_iter->get_next= get_next_partition_id_range; } /** @brief Update part_field_list by row_end field name @returns true on error; false on success */ inline bool partition_info::vers_fix_field_list(THD * thd) { if (!table->versioned()) { // frm must be corrupted, normally CREATE/ALTER TABLE checks for that my_error(ER_FILE_CORRUPT, MYF(0), table->s->path.str); return true; } DBUG_ASSERT(part_type == VERSIONING_PARTITION); DBUG_ASSERT(table->versioned(VERS_TIMESTAMP)); Field *row_end= table->vers_end_field(); // needed in handle_list_of_fields() row_end->flags|= GET_FIXED_FIELDS_FLAG; Name_resolution_context *context= &thd->lex->current_select->context; Item *row_end_item= new (thd->mem_root) Item_field(thd, context, row_end); Item *row_end_ts= new (thd->mem_root) Item_func_unix_timestamp(thd, row_end_item); set_part_expr(thd, row_end_ts, false); return false; } inline void partition_info::vers_update_el_ids() { DBUG_ASSERT(part_type == VERSIONING_PARTITION); DBUG_ASSERT(table->versioned(VERS_TIMESTAMP)); List_iterator<partition_element> it(partitions); partition_element *el; for(uint32 id= 0; ((el= it++)); id++) { DBUG_ASSERT(el->type != partition_element::CONVENTIONAL); /* Newly added element is inserted before AS_OF_NOW. */ if (el->id == UINT_MAX32 || el->type == partition_element::CURRENT) { el->id= id; if (el->type == partition_element::CURRENT) break; } } } inline bool make_partition_name(char *move_ptr, uint i) { int res= snprintf(move_ptr, MAX_PART_NAME_SIZE + 1, "p%u", i); return res < 0 || res > MAX_PART_NAME_SIZE; } #ifdef WITH_PARTITION_STORAGE_ENGINE inline uint partition_info::next_part_no(uint new_parts) const { if (part_type != VERSIONING_PARTITION) return num_parts; DBUG_ASSERT(new_parts > 0); /* Choose first non-occupied name suffix */ uint32 suffix= num_parts - 1; DBUG_ASSERT(suffix > 0); char part_name[MAX_PART_NAME_SIZE + 1]; List_iterator_fast<partition_element> it(table->part_info->partitions); for (uint cur_part= 0; cur_part < new_parts; ++cur_part, ++suffix) { uint32 cur_suffix= suffix; if (make_partition_name(part_name, suffix)) return 0; partition_element *el; it.rewind(); while ((el= it++)) { if (0 == my_strcasecmp(&my_charset_latin1, el->partition_name, part_name)) { if (make_partition_name(part_name, ++suffix)) return 0; it.rewind(); } } if (cur_part > 0 && suffix > cur_suffix) cur_part= 0; } return suffix - new_parts; } #endif #endif /* PARTITION_INFO_INCLUDED */ sql_join_cache.h 0000644 00000137023 15156036154 0007672 0 ustar 00 /* Copyright (c) 2011, 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file contains declarations for implementations of block based join algorithms */ #define JOIN_CACHE_INCREMENTAL_BIT 1 #define JOIN_CACHE_HASHED_BIT 2 #define JOIN_CACHE_BKA_BIT 4 /* Categories of data fields of variable length written into join cache buffers. The value of any of these fields is written into cache together with the prepended length of the value. */ #define CACHE_BLOB 1 /* blob field */ #define CACHE_STRIPPED 2 /* field stripped of trailing spaces */ #define CACHE_VARSTR1 3 /* short string value (length takes 1 byte) */ #define CACHE_VARSTR2 4 /* long string value (length takes 2 bytes) */ #define CACHE_ROWID 5 /* ROWID field */ /* The CACHE_FIELD structure used to describe fields of records that are written into a join cache buffer from record buffers and backward. */ typedef struct st_cache_field { uchar *str; /**< buffer from/to where the field is to be copied */ uint length; /**< maximal number of bytes to be copied from/to str */ /* Field object for the moved field (0 - for a flag field, see JOIN_CACHE::create_flag_fields). */ Field *field; uint type; /**< category of the of the copied field (CACHE_BLOB et al.) */ /* The number of the record offset value for the field in the sequence of offsets placed after the last field of the record. These offset values are used to access fields referred to from other caches. If the value is 0 then no offset for the field is saved in the trailing sequence of offsets. */ uint referenced_field_no; /* The remaining structure fields are used as containers for temp values */ uint blob_length; /**< length of the blob to be copied */ uint offset; /**< field offset to be saved in cache buffer */ } CACHE_FIELD; class JOIN_TAB_SCAN; class EXPLAIN_BKA_TYPE; /* JOIN_CACHE is the base class to support the implementations of - Block Nested Loop (BNL) Join Algorithm, - Block Nested Loop Hash (BNLH) Join Algorithm, - Batched Key Access (BKA) Join Algorithm. The first algorithm is supported by the derived class JOIN_CACHE_BNL, the second algorithm is supported by the derived class JOIN_CACHE_BNLH, while the third algorithm is implemented in two variant supported by the classes JOIN_CACHE_BKA and JOIN_CACHE_BKAH. These three algorithms have a lot in common. Each of them first accumulates the records of the left join operand in a join buffer and then searches for matching rows of the second operand for all accumulated records. For the first two algorithms this strategy saves on logical I/O operations: the entire set of records from the join buffer requires only one look-through of the records provided by the second operand. For the third algorithm the accumulation of records allows to optimize fetching rows of the second operand from disk for some engines (MyISAM, InnoDB), or to minimize the number of round-trips between the Server and the engine nodes. */ class JOIN_CACHE :public Sql_alloc { private: /* Size of the offset of a record from the cache */ uint size_of_rec_ofs; /* Size of the length of a record in the cache */ uint size_of_rec_len; /* Size of the offset of a field within a record in the cache */ uint size_of_fld_ofs; /* This structure is used only for explain, not for execution */ bool for_explain_only; protected: /* 3 functions below actually do not use the hidden parameter 'this' */ /* Calculate the number of bytes used to store an offset value */ uint offset_size(size_t len) { return (len < 256 ? 1 : len < 256*256 ? 2 : 4); } /* Get the offset value that takes ofs_sz bytes at the position ptr */ ulong get_offset(uint ofs_sz, uchar *ptr) { switch (ofs_sz) { case 1: return uint(*ptr); case 2: return uint2korr(ptr); case 4: return uint4korr(ptr); } return 0; } /* Set the offset value ofs that takes ofs_sz bytes at the position ptr */ void store_offset(uint ofs_sz, uchar *ptr, ulong ofs) { switch (ofs_sz) { case 1: *ptr= (uchar) ofs; return; case 2: int2store(ptr, (uint16) ofs); return; case 4: int4store(ptr, (uint32) ofs); return; } } size_t calc_avg_record_length(); /* The maximum total length of the fields stored for a record in the cache. For blob fields only the sizes of the blob lengths are taken into account. */ uint length; /* Representation of the executed multi-way join through which all needed context can be accessed. */ JOIN *join; /* JOIN_TAB of the first table that can have it's fields in the join cache. That is, tables in the [start_tab, tab) range can have their fields in the join cache. If a join tab in the range represents an SJM-nest, then all tables from the nest can have their fields in the join cache, too. */ JOIN_TAB *start_tab; /* The total number of flag and data fields that can appear in a record written into the cache. Fields with null values are always skipped to save space. */ uint fields; /* The total number of flag fields in a record put into the cache. They are used for table null bitmaps, table null row flags, and an optional match flag. Flag fields go before other fields in a cache record with the match flag field placed always at the very beginning of the record. */ uint flag_fields; /* The total number of blob fields that are written into the cache */ uint blobs; /* The total number of fields referenced from field descriptors for other join caches. These fields are used to construct key values. When BKA join algorithm is employed the constructed key values serve to access matching rows with index lookups. The key values are put into a hash table when the BNLH join algorithm is employed and when BKAH is used for the join operation. */ uint referenced_fields; /* The current number of already created data field descriptors. This number can be useful for implementations of the init methods. */ uint data_field_count; /* The current number of already created pointers to the data field descriptors. This number can be useful for implementations of the init methods. */ uint data_field_ptr_count; /* Array of the descriptors of fields containing 'fields' elements. These are all fields that are stored for a record in the cache. */ CACHE_FIELD *field_descr; /* Array of pointers to the blob descriptors that contains 'blobs' elements. */ CACHE_FIELD **blob_ptr; /* This flag indicates that records written into the join buffer contain a match flag field. This is set to true for the first inner table of an outer join or a semi-join. The flag must be set by the init method. Currently any implementation of the virtial init method calls the function JOIN_CACHE::calc_record_fields() to set this flag. */ bool with_match_flag; /* This flag indicates that any record is prepended with the length of the record which allows us to skip the record or part of it without reading. */ bool with_length; /* The maximal number of bytes used for a record representation in the cache excluding the space for blob data. For future derived classes this representation may contains some redundant info such as a key value associated with the record. */ uint pack_length; /* The value of pack_length incremented by the total size of all pointers of a record in the cache to the blob data. */ uint pack_length_with_blob_ptrs; /* The total size of the record base prefix. The base prefix of record may include the following components: - the length of the record - the link to a record in a previous buffer. Each record in the buffer are supplied with the same set of the components. */ uint base_prefix_length; /* The expected length of a record in the join buffer together with all prefixes and postfixes */ size_t avg_record_length; /* The expected size of the space per record in the auxiliary buffer */ size_t avg_aux_buffer_incr; /* Pointer to the beginning of the join buffer */ uchar *buff; /* Size of the entire memory allocated for the join buffer. Part of this memory may be reserved for the auxiliary buffer. */ size_t buff_size; /* The minimal join buffer size when join buffer still makes sense to use */ size_t min_buff_size; /* The maximum expected size if the join buffer to be used */ size_t max_buff_size; /* Size of the auxiliary buffer */ size_t aux_buff_size; /* The number of records put into the join buffer */ size_t records; /* The number of records in the fully refilled join buffer of the minimal size equal to min_buff_size */ size_t min_records; /* Pointer to the current position in the join buffer. This member is used both when writing to buffer and when reading from it. */ uchar *pos; /* Pointer to the first free position in the join buffer, right after the last record into it. */ uchar *end_pos; /* Pointer to the beginning of the first field of the current read/write record from the join buffer. The value is adjusted by the get_record/put_record functions. */ uchar *curr_rec_pos; /* Pointer to the beginning of the first field of the last record from the join buffer. */ uchar *last_rec_pos; /* Flag is set if the blob data for the last record in the join buffer is in record buffers rather than in the join cache. */ bool last_rec_blob_data_is_in_rec_buff; /* Pointer to the position to the current record link. Record links are used only with linked caches. Record links allow to set connections between parts of one join record that are stored in different join buffers. In the simplest case a record link is just a pointer to the beginning of the record stored in the buffer. In a more general case a link could be a reference to an array of pointers to records in the buffer. */ uchar *curr_rec_link; /* This flag is set to TRUE if join_tab is the first inner table of an outer join and the latest record written to the join buffer is detected to be null complemented after checking on conditions over the outer tables for this outer join operation */ bool last_written_is_null_compl; /* The number of fields put in the join buffer of the join cache that are used in building keys to access the table join_tab */ uint local_key_arg_fields; /* The total number of the fields in the previous caches that are used in building keys to access the table join_tab */ uint external_key_arg_fields; /* This flag indicates that the key values will be read directly from the join buffer. It will save us building key values in the key buffer. */ bool use_emb_key; /* The length of an embedded key value */ uint emb_key_length; /* This flag is used only when 'not exists' optimization can be applied */ bool not_exists_opt_is_applicable; /* This object provides the methods to iterate over records of the joined table join_tab when looking for join matches between records from join buffer and records from join_tab. BNL and BNLH join algorithms retrieve all records from join_tab, while BKA/BKAH algorithm iterates only over those records from join_tab that can be accessed by look-ups with join keys built from records in join buffer. */ JOIN_TAB_SCAN *join_tab_scan; void calc_record_fields(); void collect_info_on_key_args(); int alloc_fields(); void create_flag_fields(); void create_key_arg_fields(); void create_remaining_fields(); void set_constants(); int alloc_buffer(); /* Shall reallocate the join buffer */ virtual int realloc_buffer(); /* Check the possibility to read the access keys directly from join buffer */ bool check_emb_key_usage(); uint get_size_of_rec_offset() { return size_of_rec_ofs; } uint get_size_of_rec_length() { return size_of_rec_len; } uint get_size_of_fld_offset() { return size_of_fld_ofs; } uchar *get_rec_ref(uchar *ptr) { return buff+get_offset(size_of_rec_ofs, ptr-size_of_rec_ofs); } ulong get_rec_length(uchar *ptr) { return (ulong) get_offset(size_of_rec_len, ptr); } ulong get_fld_offset(uchar *ptr) { return (ulong) get_offset(size_of_fld_ofs, ptr); } void store_rec_ref(uchar *ptr, uchar* ref) { store_offset(size_of_rec_ofs, ptr-size_of_rec_ofs, (ulong) (ref-buff)); } void store_rec_length(uchar *ptr, ulong len) { store_offset(size_of_rec_len, ptr, len); } void store_fld_offset(uchar *ptr, ulong ofs) { store_offset(size_of_fld_ofs, ptr, ofs); } /* Write record fields and their required offsets into the join buffer */ uint write_record_data(uchar *link, bool *is_full); /* Get the total length of all prefixes of a record in the join buffer */ virtual uint get_prefix_length() { return base_prefix_length; } /* Get maximum total length of all affixes of a record in the join buffer */ virtual uint get_record_max_affix_length(); /* Shall get maximum size of the additional space per record used for record keys */ virtual uint get_max_key_addon_space_per_record() { return 0; } /* This method must determine for how much the auxiliary buffer should be incremented when a new record is added to the join buffer. If no auxiliary buffer is needed the function should return 0. */ virtual uint aux_buffer_incr(size_t recno); /* Shall calculate how much space is remaining in the join buffer */ virtual size_t rem_space() { return MY_MAX(buff_size-(end_pos-buff)-aux_buff_size,0); } /* Shall calculate how much space is taken by allocation of the key for a record in the join buffer */ virtual uint extra_key_length() { return 0; } /* Read all flag and data fields of a record from the join buffer */ uint read_all_record_fields(); /* Read all flag fields of a record from the join buffer */ uint read_flag_fields(); /* Read a data record field from the join buffer */ uint read_record_field(CACHE_FIELD *copy, bool last_record); /* Read a referenced field from the join buffer */ bool read_referenced_field(CACHE_FIELD *copy, uchar *rec_ptr, uint *len); /* Shall skip record from the join buffer if its match flag is set to MATCH_FOUND */ virtual bool skip_if_matched(); /* Shall skip record from the join buffer if its match flag commands to do so */ virtual bool skip_if_not_needed_match(); /* True if rec_ptr points to the record whose blob data stay in record buffers */ bool blob_data_is_in_rec_buff(uchar *rec_ptr) { return rec_ptr == last_rec_pos && last_rec_blob_data_is_in_rec_buff; } /* Find matches from the next table for records from the join buffer */ virtual enum_nested_loop_state join_matching_records(bool skip_last); /* Shall set an auxiliary buffer up (currently used only by BKA joins) */ virtual int setup_aux_buffer(HANDLER_BUFFER &aux_buff) { DBUG_ASSERT(0); return 0; } /* Shall get the number of ranges in the cache buffer passed to the MRR interface */ virtual uint get_number_of_ranges_for_mrr() { return 0; }; /* Shall prepare to look for records from the join cache buffer that would match the record of the joined table read into the record buffer */ virtual bool prepare_look_for_matches(bool skip_last)= 0; /* Shall return a pointer to the record from join buffer that is checked as the next candidate for a match with the current record from join_tab. Each implementation of this virtual function should bare in mind that the record position it returns shall be exactly the position passed as the parameter to the implementations of the virtual functions skip_next_candidate_for_match and read_next_candidate_for_match. */ virtual uchar *get_next_candidate_for_match()= 0; /* Shall check whether the given record from the join buffer has its match flag settings commands to skip the record in the buffer. */ virtual bool skip_next_candidate_for_match(uchar *rec_ptr)= 0; /* Shall read the given record from the join buffer into the the corresponding record buffer */ virtual void read_next_candidate_for_match(uchar *rec_ptr)= 0; /* Shall return the location of the association label returned by the multi_read_range_next function for the current record loaded into join_tab's record buffer */ virtual uchar **get_curr_association_ptr() { return 0; }; /* Add null complements for unmatched outer records from the join buffer */ virtual enum_nested_loop_state join_null_complements(bool skip_last); /* Restore the fields of the last record from the join buffer */ virtual void restore_last_record(); /* Set match flag for a record in join buffer if it has not been set yet */ bool set_match_flag_if_none(JOIN_TAB *first_inner, uchar *rec_ptr); enum_nested_loop_state generate_full_extensions(uchar *rec_ptr); /* Check matching to a partial join record from the join buffer */ bool check_match(uchar *rec_ptr); /* This constructor creates an unlinked join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. */ JOIN_CACHE(JOIN *j, JOIN_TAB *tab) { join= j; join_tab= tab; prev_cache= next_cache= 0; buff= 0; min_buff_size= max_buff_size= 0; // Caches not_exists_opt_is_applicable= false; } /* This constructor creates a linked join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. */ JOIN_CACHE(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev) { join= j; join_tab= tab; next_cache= 0; prev_cache= prev; buff= 0; min_buff_size= max_buff_size= 0; // Caches if (prev) prev->next_cache= this; } public: /* The enumeration type Join_algorithm includes a mnemonic constant for each join algorithm that employs join buffers */ enum Join_algorithm { BNL_JOIN_ALG, /* Block Nested Loop Join algorithm */ BNLH_JOIN_ALG, /* Block Nested Loop Hash Join algorithm */ BKA_JOIN_ALG, /* Batched Key Access Join algorithm */ BKAH_JOIN_ALG /* Batched Key Access with Hash Table Join Algorithm */ }; /* The enumeration type Match_flag describes possible states of the match flag field stored for the records of the first inner tables of outer joins and semi-joins in the cases when the first match strategy is used for them. When a record with match flag field is written into the join buffer the state of the field usually is MATCH_NOT_FOUND unless this is a record of the first inner table of the outer join for which the on precondition (the condition from on expression over outer tables) has turned out not to be true. In the last case the state of the match flag is MATCH_IMPOSSIBLE. The state of the match flag field is changed to MATCH_FOUND as soon as the first full matching combination of inner tables of the outer join or the semi-join is discovered. */ enum Match_flag { MATCH_NOT_FOUND, MATCH_FOUND, MATCH_IMPOSSIBLE }; /* Table to be joined with the partial join records from the cache */ JOIN_TAB *join_tab; /* Pointer to the previous join cache if there is any */ JOIN_CACHE *prev_cache; /* Pointer to the next join cache if there is any */ JOIN_CACHE *next_cache; /* Shall initialize the join cache structure */ virtual int init(bool for_explain); /* Get the current size of the cache join buffer */ size_t get_join_buffer_size() { return buff_size; } /* Set the size of the cache join buffer to a new value */ void set_join_buffer_size(size_t sz) { buff_size= sz; } /* Get the minimum possible size of the cache join buffer */ size_t get_min_join_buffer_size(); /* Get the maximum possible size of the cache join buffer */ size_t get_max_join_buffer_size(bool optimize_buff_size, size_t min_buffer_size_arg); /* Shrink the size if the cache join buffer in a given ratio */ bool shrink_join_buffer_in_ratio(ulonglong n, ulonglong d); /* Shall return the type of the employed join algorithm */ virtual enum Join_algorithm get_join_alg()= 0; /* The function shall return TRUE only when there is a key access to the join table */ virtual bool is_key_access()= 0; /* Shall reset the join buffer for reading/writing */ virtual void reset(bool for_writing); /* This function shall add a record into the join buffer and return TRUE if it has been decided that it should be the last record in the buffer. */ virtual bool put_record(); /* This function shall read the next record into the join buffer and return TRUE if there is no more next records. */ virtual bool get_record(); /* This function shall read the record at the position rec_ptr in the join buffer */ virtual void get_record_by_pos(uchar *rec_ptr); /* Shall return the value of the match flag for the positioned record */ virtual enum Match_flag get_match_flag_by_pos(uchar *rec_ptr); /* Shall return the value of the match flag for the positioned record from the join buffer attached to the specified table */ virtual enum Match_flag get_match_flag_by_pos_from_join_buffer(uchar *rec_ptr, JOIN_TAB *tab); /* Shall return the position of the current record */ virtual uchar *get_curr_rec() { return curr_rec_pos; } /* Shall set the current record link */ virtual void set_curr_rec_link(uchar *link) { curr_rec_link= link; } /* Shall return the current record link */ virtual uchar *get_curr_rec_link() { return (curr_rec_link ? curr_rec_link : get_curr_rec()); } /* Join records from the join buffer with records from the next join table */ enum_nested_loop_state join_records(bool skip_last); /* Add a comment on the join algorithm employed by the join cache */ virtual bool save_explain_data(EXPLAIN_BKA_TYPE *explain); THD *thd(); virtual ~JOIN_CACHE() = default; void reset_join(JOIN *j) { join= j; } void free() { my_free(buff); buff= 0; } friend class JOIN_CACHE_HASHED; friend class JOIN_CACHE_BNL; friend class JOIN_CACHE_BKA; friend class JOIN_TAB_SCAN; friend class JOIN_TAB_SCAN_MRR; }; /* The class JOIN_CACHE_HASHED is the base class for the classes JOIN_CACHE_HASHED_BNL and JOIN_CACHE_HASHED_BKA. The first of them supports an implementation of Block Nested Loop Hash (BNLH) Join Algorithm, while the second is used for a variant of the BKA Join algorithm that performs only one lookup for any records from join buffer with the same key value. For a join cache of this class the records from the join buffer that have the same access key are linked into a chain attached to a key entry structure that either itself contains the key value, or, in the case when the keys are embedded, refers to its occurrence in one of the records from the chain. To build the chains with the same keys a hash table is employed. It is placed at the very end of the join buffer. The array of hash entries is allocated first at the very bottom of the join buffer, while key entries are placed before this array. A hash entry contains a header of the list of the key entries with the same hash value. Each key entry is a structure of the following type: struct st_join_cache_key_entry { union { uchar[] value; cache_ref *value_ref; // offset from the beginning of the buffer } hash_table_key; key_ref next_key; // offset backward from the beginning of hash table cache_ref *last_rec // offset from the beginning of the buffer } The references linking the records in a chain are always placed at the very beginning of the record info stored in the join buffer. The records are linked in a circular list. A new record is always added to the end of this list. The following picture represents a typical layout for the info stored in the join buffer of a join cache object of the JOIN_CACHE_HASHED class. buff V +----------------------------------------------------------------------------+ | |[*]record_1_1| | | ^ | | | | +--------------------------------------------------+ | | | |[*]record_2_1| | | | | ^ | V | | | | +------------------+ |[*]record_1_2| | | | +--------------------+-+ | | |+--+ +---------------------+ | | +-------------+ | || | | V | | | |||[*]record_3_1| |[*]record_1_3| |[*]record_2_2| | | ||^ ^ ^ | | ||+----------+ | | | | ||^ | |<---------------------------+-------------------+ | |++ | | ... mrr | buffer ... ... | | | | | | | | | +-----+--------+ | +-----|-------+ | | V | | | V | | | ||key_3|[/]|[*]| | | |key_2|[/]|[*]| | | | +-+---|-----------------------+ | | | V | | | | | | |key_1|[*]|[*]| | | ... |[*]| ... |[*]| ... | | +----------------------------------------------------------------------------+ ^ ^ ^ | i-th entry j-th entry hash table i-th hash entry: circular record chain for key_1: record_1_1 record_1_2 record_1_3 (points to record_1_1) circular record chain for key_3: record_3_1 (points to itself) j-th hash entry: circular record chain for key_2: record_2_1 record_2_2 (points to record_2_1) */ class JOIN_CACHE_HASHED: public JOIN_CACHE { typedef uint (JOIN_CACHE_HASHED::*Hash_func) (uchar *key, uint key_len); typedef bool (JOIN_CACHE_HASHED::*Hash_cmp_func) (uchar *key1, uchar *key2, uint key_len); private: /* Size of the offset of a key entry in the hash table */ uint size_of_key_ofs; /* Length of the key entry in the hash table. A key entry either contains the key value, or it contains a reference to the key value if use_emb_key flag is set for the cache. */ uint key_entry_length; /* The beginning of the hash table in the join buffer */ uchar *hash_table; /* Number of hash entries in the hash table */ uint hash_entries; /* The position of the currently retrieved key entry in the hash table */ uchar *curr_key_entry; /* The offset of the data fields from the beginning of the record fields */ uint data_fields_offset; inline uint get_hash_idx_simple(uchar *key, uint key_len); inline uint get_hash_idx_complex(uchar *key, uint key_len); inline bool equal_keys_simple(uchar *key1, uchar *key2, uint key_len); inline bool equal_keys_complex(uchar *key1, uchar *key2, uint key_len); int init_hash_table(); void cleanup_hash_table(); protected: /* Index info on the TABLE_REF object used by the hash join to look for matching records */ KEY *ref_key_info; /* Number of the key parts the TABLE_REF object used by the hash join to look for matching records */ uint ref_used_key_parts; /* The hash function used in the hash table, usually set by the init() method */ Hash_func hash_func; /* The function to check whether two key entries in the hash table are equal or not, usually set by the init() method */ Hash_cmp_func hash_cmp_func; /* Length of a key value. It is assumed that all key values have the same length. */ uint key_length; /* Buffer to store key values for probing */ uchar *key_buff; /* Number of key entries in the hash table (number of distinct keys) */ uint key_entries; /* The position of the last key entry in the hash table */ uchar *last_key_entry; /* The offset of the record fields from the beginning of the record representation. The record representation starts with a reference to the next record in the key record chain followed by the length of the trailing record data followed by a reference to the record segment in the previous cache, if any, followed by the record fields. */ uint rec_fields_offset; uint get_size_of_key_offset() { return size_of_key_ofs; } /* Get the position of the next_key_ptr field pointed to by a linking reference stored at the position key_ref_ptr. This reference is actually the offset backward from the beginning of hash table. */ uchar *get_next_key_ref(uchar *key_ref_ptr) { return hash_table-get_offset(size_of_key_ofs, key_ref_ptr); } /* Store the linking reference to the next_key_ptr field at the position key_ref_ptr. The position of the next_key_ptr field is pointed to by ref. The stored reference is actually the offset backward from the beginning of the hash table. */ void store_next_key_ref(uchar *key_ref_ptr, uchar *ref) { store_offset(size_of_key_ofs, key_ref_ptr, (ulong) (hash_table-ref)); } /* Check whether the reference to the next_key_ptr field at the position key_ref_ptr contains a nil value. */ bool is_null_key_ref(uchar *key_ref_ptr) { ulong nil= 0; return memcmp(key_ref_ptr, &nil, size_of_key_ofs ) == 0; } /* Set the reference to the next_key_ptr field at the position key_ref_ptr equal to nil. */ void store_null_key_ref(uchar *key_ref_ptr) { ulong nil= 0; store_offset(size_of_key_ofs, key_ref_ptr, nil); } uchar *get_next_rec_ref(uchar *ref_ptr) { return buff+get_offset(get_size_of_rec_offset(), ref_ptr); } void store_next_rec_ref(uchar *ref_ptr, uchar *ref) { store_offset(get_size_of_rec_offset(), ref_ptr, (ulong) (ref-buff)); } /* Get the position of the embedded key value for the current record pointed to by get_curr_rec(). */ uchar *get_curr_emb_key() { return get_curr_rec()+data_fields_offset; } /* Get the position of the embedded key value pointed to by a reference stored at ref_ptr. The stored reference is actually the offset from the beginning of the join buffer. */ uchar *get_emb_key(uchar *ref_ptr) { return buff+get_offset(get_size_of_rec_offset(), ref_ptr); } /* Store the reference to an embedded key at the position key_ref_ptr. The position of the embedded key is pointed to by ref. The stored reference is actually the offset from the beginning of the join buffer. */ void store_emb_key_ref(uchar *ref_ptr, uchar *ref) { store_offset(get_size_of_rec_offset(), ref_ptr, (ulong) (ref-buff)); } /* Get the total length of all prefixes of a record in hashed join buffer */ uint get_prefix_length() override { return base_prefix_length + get_size_of_rec_offset(); } /* Get maximum size of the additional space per record used for the hash table with record keys */ uint get_max_key_addon_space_per_record() override; /* Calculate how much space in the buffer would not be occupied by records, key entries and additional memory for the MMR buffer. */ size_t rem_space() override { return MY_MAX(last_key_entry-end_pos-aux_buff_size,0); } /* Calculate how much space is taken by allocation of the key entry for a record in the join buffer */ uint extra_key_length() override { return key_entry_length; } /* Skip record from a hashed join buffer if its match flag is set to MATCH_FOUND */ bool skip_if_matched() override; /* Skip record from a hashed join buffer if its match flag setting commands to do so */ bool skip_if_not_needed_match() override; /* Search for a key in the hash table of the join buffer */ bool key_search(uchar *key, uint key_len, uchar **key_ref_ptr); /* Reallocate the join buffer of a hashed join cache */ int realloc_buffer() override; /* This constructor creates an unlinked hashed join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. */ JOIN_CACHE_HASHED(JOIN *j, JOIN_TAB *tab) :JOIN_CACHE(j, tab) {} /* This constructor creates a linked hashed join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. */ JOIN_CACHE_HASHED(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev) :JOIN_CACHE(j, tab, prev) {} public: /* Initialize a hashed join cache */ int init(bool for_explain) override; /* Reset the buffer of a hashed join cache for reading/writing */ void reset(bool for_writing) override; /* Add a record into the buffer of a hashed join cache */ bool put_record() override; /* Read the next record from the buffer of a hashed join cache */ bool get_record() override; /* Shall check whether all records in a key chain have their match flags set on */ virtual bool check_all_match_flags_for_key(uchar *key_chain_ptr); uint get_next_key(uchar **key); /* Get the head of the record chain attached to the current key entry */ uchar *get_curr_key_chain() { return get_next_rec_ref(curr_key_entry+key_entry_length- get_size_of_rec_offset()); } }; /* The class JOIN_TAB_SCAN is a companion class for the classes JOIN_CACHE_BNL and JOIN_CACHE_BNLH. Actually the class implements the iterator over the table joinded by BNL/BNLH join algorithm. The virtual functions open, next and close are called for any iteration over the table. The function open is called to initiate the process of the iteration. The function next shall read the next record from the joined table. The record is read into the record buffer of the joined table. The record is to be matched with records from the join cache buffer. The function close shall perform the finalizing actions for the iteration. */ class JOIN_TAB_SCAN: public Sql_alloc { private: /* TRUE if this is the first record from the joined table to iterate over */ bool is_first_record; protected: /* The joined table to be iterated over */ JOIN_TAB *join_tab; /* The join cache used to join the table join_tab */ JOIN_CACHE *cache; /* Representation of the executed multi-way join through which all needed context can be accessed. */ JOIN *join; public: JOIN_TAB_SCAN(JOIN *j, JOIN_TAB *tab) { join= j; join_tab= tab; cache= join_tab->cache; } virtual ~JOIN_TAB_SCAN() = default; /* Shall calculate the increment of the auxiliary buffer for a record write if such a buffer is used by the table scan object */ virtual uint aux_buffer_incr(size_t recno) { return 0; } /* Initiate the process of iteration over the joined table */ virtual int open(); /* Shall read the next candidate for matches with records from the join buffer. */ virtual int next(); /* Perform the finalizing actions for the process of iteration over the joined_table. */ virtual void close(); }; /* The class JOIN_CACHE_BNL is used when the BNL join algorithm is employed to perform a join operation */ class JOIN_CACHE_BNL :public JOIN_CACHE { private: /* The number of the records in the join buffer that have to be checked yet for a match with the current record of join_tab read into the record buffer. */ uint rem_records; protected: bool prepare_look_for_matches(bool skip_last) override; uchar *get_next_candidate_for_match() override; bool skip_next_candidate_for_match(uchar *rec_ptr) override; void read_next_candidate_for_match(uchar *rec_ptr) override; public: /* This constructor creates an unlinked BNL join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. */ JOIN_CACHE_BNL(JOIN *j, JOIN_TAB *tab) :JOIN_CACHE(j, tab) {} /* This constructor creates a linked BNL join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. */ JOIN_CACHE_BNL(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev) :JOIN_CACHE(j, tab, prev) {} /* Initialize the BNL cache */ int init(bool for_explain) override; enum Join_algorithm get_join_alg() override { return BNL_JOIN_ALG; } bool is_key_access() override { return FALSE; } }; /* The class JOIN_CACHE_BNLH is used when the BNLH join algorithm is employed to perform a join operation */ class JOIN_CACHE_BNLH :public JOIN_CACHE_HASHED { protected: /* The pointer to the last record from the circular list of the records that match the join key built out of the record in the join buffer for the join_tab table */ uchar *last_matching_rec_ref_ptr; /* The pointer to the next current record from the circular list of the records that match the join key built out of the record in the join buffer for the join_tab table. This pointer is used by the class method get_next_candidate_for_match to iterate over records from the circular list. */ uchar *next_matching_rec_ref_ptr; /* Get the chain of records from buffer matching the current candidate record for join */ uchar *get_matching_chain_by_join_key(); bool prepare_look_for_matches(bool skip_last) override; uchar *get_next_candidate_for_match() override; bool skip_next_candidate_for_match(uchar *rec_ptr) override; void read_next_candidate_for_match(uchar *rec_ptr) override; public: /* This constructor creates an unlinked BNLH join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. */ JOIN_CACHE_BNLH(JOIN *j, JOIN_TAB *tab) : JOIN_CACHE_HASHED(j, tab) {} /* This constructor creates a linked BNLH join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. */ JOIN_CACHE_BNLH(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev) : JOIN_CACHE_HASHED(j, tab, prev) {} /* Initialize the BNLH cache */ int init(bool for_explain) override; enum Join_algorithm get_join_alg() override { return BNLH_JOIN_ALG; } bool is_key_access() override { return TRUE; } }; /* The class JOIN_TAB_SCAN_MRR is a companion class for the classes JOIN_CACHE_BKA and JOIN_CACHE_BKAH. Actually the class implements the iterator over the records from join_tab selected by BKA/BKAH join algorithm as the candidates to be joined. The virtual functions open, next and close are called for any iteration over join_tab record candidates. The function open is called to initiate the process of the iteration. The function next shall read the next record from the set of the record candidates. The record is read into the record buffer of the joined table. The function close shall perform the finalizing actions for the iteration. */ class JOIN_TAB_SCAN_MRR: public JOIN_TAB_SCAN { /* Interface object to generate key ranges for MRR */ RANGE_SEQ_IF range_seq_funcs; /* Number of ranges to be processed by the MRR interface */ uint ranges; /* Flag to be passed to the MRR interface */ uint mrr_mode; /* MRR buffer assotiated with this join cache */ HANDLER_BUFFER mrr_buff; /* Shall initialize the MRR buffer */ virtual void init_mrr_buff() { cache->setup_aux_buffer(mrr_buff); } public: JOIN_TAB_SCAN_MRR(JOIN *j, JOIN_TAB *tab, uint flags, RANGE_SEQ_IF rs_funcs) :JOIN_TAB_SCAN(j, tab), range_seq_funcs(rs_funcs), mrr_mode(flags) {} uint aux_buffer_incr(size_t recno) override; int open() override; int next() override; friend class JOIN_CACHE_BKA; /* it needs to add an mrr_mode flag after JOIN_CACHE::init() call */ }; /* The class JOIN_CACHE_BKA is used when the BKA join algorithm is employed to perform a join operation */ class JOIN_CACHE_BKA :public JOIN_CACHE { private: /* Flag to be passed to the companion JOIN_TAB_SCAN_MRR object */ uint mrr_mode; /* This value is set to 1 by the class prepare_look_for_matches method and back to 0 by the class get_next_candidate_for_match method */ uint rem_records; /* This field contains the current association label set by a call of the multi_range_read_next handler function. See the function JOIN_CACHE_BKA::get_curr_key_association() */ uchar *curr_association; protected: /* Get the number of ranges in the cache buffer passed to the MRR interface. For each record its own range is passed. */ uint get_number_of_ranges_for_mrr() override { return (uint)records; } /* Setup the MRR buffer as the space between the last record put into the join buffer and the very end of the join buffer */ int setup_aux_buffer(HANDLER_BUFFER &aux_buff) override { aux_buff.buffer= end_pos; aux_buff.buffer_end= buff+buff_size; return 0; } bool prepare_look_for_matches(bool skip_last) override; uchar *get_next_candidate_for_match() override; bool skip_next_candidate_for_match(uchar *rec_ptr) override; void read_next_candidate_for_match(uchar *rec_ptr) override; public: /* This constructor creates an unlinked BKA join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The MRR mode initially is set to 'flags'. */ JOIN_CACHE_BKA(JOIN *j, JOIN_TAB *tab, uint flags) :JOIN_CACHE(j, tab), mrr_mode(flags) {} /* This constructor creates a linked BKA join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. The MRR mode initially is set to 'flags'. */ JOIN_CACHE_BKA(JOIN *j, JOIN_TAB *tab, uint flags, JOIN_CACHE *prev) :JOIN_CACHE(j, tab, prev), mrr_mode(flags) {} JOIN_CACHE_BKA(JOIN_CACHE_BKA *bka) :JOIN_CACHE(bka->join, bka->join_tab, bka->prev_cache), mrr_mode(bka->mrr_mode) {} uchar **get_curr_association_ptr() override { return &curr_association; } /* Initialize the BKA cache */ int init(bool for_explain) override; enum Join_algorithm get_join_alg() override { return BKA_JOIN_ALG; } bool is_key_access() override { return TRUE; } /* Get the key built over the next record from the join buffer */ uint get_next_key(uchar **key); /* Check index condition of the joined table for a record from BKA cache */ bool skip_index_tuple(range_id_t range_info); bool save_explain_data(EXPLAIN_BKA_TYPE *explain) override; }; /* The class JOIN_CACHE_BKAH is used when the BKAH join algorithm is employed to perform a join operation */ class JOIN_CACHE_BKAH :public JOIN_CACHE_BNLH { private: /* Flag to be passed to the companion JOIN_TAB_SCAN_MRR object */ uint mrr_mode; /* This flag is set to TRUE if the implementation of the MRR interface cannot handle range association labels and does not return them to the caller of the multi_range_read_next handler function. E.g. the implementation of the MRR inteface for the Falcon engine could not return association labels to the caller of multi_range_read_next. The flag is set by JOIN_CACHE_BKA::init() and is not ever changed. */ bool no_association; /* This field contains the association label returned by the multi_range_read_next function. See the function JOIN_CACHE_BKAH::get_curr_key_association() */ uchar *curr_matching_chain; protected: uint get_number_of_ranges_for_mrr() override { return key_entries; } /* Initialize the MRR buffer allocating some space within the join buffer. The entire space between the last record put into the join buffer and the last key entry added to the hash table is used for the MRR buffer. */ int setup_aux_buffer(HANDLER_BUFFER &aux_buff) override { aux_buff.buffer= end_pos; aux_buff.buffer_end= last_key_entry; return 0; } bool prepare_look_for_matches(bool skip_last) override; /* The implementations of the methods - get_next_candidate_for_match - skip_recurrent_candidate_for_match - read_next_candidate_for_match are inherited from the JOIN_CACHE_BNLH class */ public: /* This constructor creates an unlinked BKAH join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The MRR mode initially is set to 'flags'. */ JOIN_CACHE_BKAH(JOIN *j, JOIN_TAB *tab, uint flags) :JOIN_CACHE_BNLH(j, tab), mrr_mode(flags) {} /* This constructor creates a linked BKAH join cache. The cache is to be used to join table 'tab' to the result of joining the previous tables specified by the 'j' parameter. The parameter 'prev' specifies the previous cache object to which this cache is linked. The MRR mode initially is set to 'flags'. */ JOIN_CACHE_BKAH(JOIN *j, JOIN_TAB *tab, uint flags, JOIN_CACHE *prev) :JOIN_CACHE_BNLH(j, tab, prev), mrr_mode(flags) {} JOIN_CACHE_BKAH(JOIN_CACHE_BKAH *bkah) :JOIN_CACHE_BNLH(bkah->join, bkah->join_tab, bkah->prev_cache), mrr_mode(bkah->mrr_mode) {} uchar **get_curr_association_ptr() override { return &curr_matching_chain; } /* Initialize the BKAH cache */ int init(bool for_explain) override; enum Join_algorithm get_join_alg() override { return BKAH_JOIN_ALG; } /* Check index condition of the joined table for a record from BKAH cache */ bool skip_index_tuple(range_id_t range_info); bool save_explain_data(EXPLAIN_BKA_TYPE *explain) override; }; sql_type_fixedbin.h 0000644 00000200060 15156036154 0010431 0 ustar 00 #ifndef SQL_TYPE_FIXEDBIN_H #define SQL_TYPE_FIXEDBIN_H /* Copyright (c) 2019,2021 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This is a common code for plugin (?) types that are generally handled like strings, but have their own fixed size on-disk binary storage format and their own (variable size) canonical string representation. Examples are INET6 and UUID types. */ #define MYSQL_SERVER #include "sql_class.h" // THD, SORT_FIELD_ATTR #include "opt_range.h" // SEL_ARG, null_element #include "sql_type_fixedbin_storage.h" /***********************************************************************/ template<class FbtImpl> class Type_collection_fbt; template<class FbtImpl, class TypeCollectionImpl = Type_collection_fbt<FbtImpl> > class Type_handler_fbt: public Type_handler { /* =[ internal helper classes ]=============================== */ public: class Fbt: public FbtImpl { protected: using FbtImpl::m_buffer; bool make_from_item(Item *item, bool warn) { if (item->type_handler() == singleton()) { Native tmp(m_buffer, sizeof(m_buffer)); bool rc= item->val_native(current_thd, &tmp); if (rc) return true; DBUG_ASSERT(tmp.length() == sizeof(m_buffer)); if (tmp.ptr() != m_buffer) memcpy(m_buffer, tmp.ptr(), sizeof(m_buffer)); return false; } StringBuffer<FbtImpl::max_char_length()+1> tmp; String *str= item->val_str(&tmp); return str ? make_from_character_or_binary_string(str, warn) : true; } bool character_string_to_fbt(const char *str, size_t str_length, CHARSET_INFO *cs) { if (cs->state & MY_CS_NONASCII) { char tmp[FbtImpl::max_char_length()+1]; String_copier copier; uint length= copier.well_formed_copy(&my_charset_latin1, tmp, sizeof(tmp), cs, str, str_length); return FbtImpl::ascii_to_fbt(tmp, length); } return FbtImpl::ascii_to_fbt(str, str_length); } bool make_from_character_or_binary_string(const String *str, bool warn) { if (str->charset() != &my_charset_bin) { bool rc= character_string_to_fbt(str->ptr(), str->length(), str->charset()); if (rc && warn) current_thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, singleton()->name().ptr(), ErrConvString(str).ptr()); return rc; } if (str->length() != sizeof(m_buffer)) { if (warn) current_thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, singleton()->name().ptr(), ErrConvString(str).ptr()); return true; } DBUG_ASSERT(str->ptr() != m_buffer); memcpy(m_buffer, str->ptr(), sizeof(m_buffer)); return false; } bool binary_to_fbt(const char *str, size_t length) { if (length != sizeof(m_buffer)) return true; memcpy(m_buffer, str, length); return false; } Fbt() { } public: static Fbt zero() { Fbt fbt; fbt.set_zero(); return fbt; } static Fbt record_to_memory(const char *ptr) { Fbt fbt; FbtImpl::record_to_memory(fbt.m_buffer, ptr); return fbt; } /* Check at Item's fix_fields() time if "item" can return a nullable value on conversion to Fbt, or conversion produces a NOT NULL Fbt value. */ static bool fix_fields_maybe_null_on_conversion_to_fbt(Item *item) { if (item->maybe_null()) return true; if (item->type_handler() == singleton()) return false; if (!item->const_item() || item->is_expensive()) return true; return Fbt_null(item, false).is_null(); } /* Check at fix_fields() time if any of the items can return a nullable value on conversion to Fbt. */ static bool fix_fields_maybe_null_on_conversion_to_fbt(Item **items, uint count) { for (uint i= 0; i < count; i++) { if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i])) return true; } return false; } public: Fbt(Item *item, bool *error, bool warn= true) { *error= make_from_item(item, warn); } void to_record(char *str, size_t str_size) const { DBUG_ASSERT(str_size >= sizeof(m_buffer)); FbtImpl::memory_to_record(str, m_buffer); } bool to_binary(String *to) const { return to->copy(m_buffer, sizeof(m_buffer), &my_charset_bin); } bool to_native(Native *to) const { return to->copy(m_buffer, sizeof(m_buffer)); } bool to_string(String *to) const { to->set_charset(&my_charset_latin1); if (to->alloc(FbtImpl::max_char_length()+1)) return true; to->length((uint32) FbtImpl::to_string(const_cast<char*>(to->ptr()), FbtImpl::max_char_length()+1)); return false; } bool to_bool() const { return !this->only_zero_bytes(m_buffer, FbtImpl::binary_length()); } int cmp(const Binary_string &other) const { return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring()); } int cmp(const Fbt &other) const { return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring()); } }; class Fbt_null: public Fbt, public Null_flag { public: // Initialize from a text representation Fbt_null(const char *str, size_t length, CHARSET_INFO *cs) :Null_flag(Fbt::character_string_to_fbt(str, length, cs)) { } Fbt_null(const String &str) :Fbt_null(str.ptr(), str.length(), str.charset()) { } // Initialize from a binary representation Fbt_null(const char *str, size_t length) :Null_flag(Fbt::binary_to_fbt(str, length)) { } Fbt_null(const Binary_string &str) :Fbt_null(str.ptr(), str.length()) { } // Initialize from an Item Fbt_null(Item *item, bool warn= true) :Null_flag(Fbt::make_from_item(item, warn)) { } public: const Fbt& to_fbt() const { DBUG_ASSERT(!is_null()); return *this; } void to_record(char *str, size_t str_size) const { to_fbt().to_record(str, str_size); } bool to_binary(String *to) const { return to_fbt().to_binary(to); } bool to_string(String *to) const { return to_fbt().to_string(to); } }; /* =[ API classes ]=========================================== */ class Type_std_attributes_fbt: public Type_std_attributes { public: Type_std_attributes_fbt() :Type_std_attributes( Type_numeric_attributes(FbtImpl::max_char_length(), 0, true), DTCollation_numeric()) { } }; class Item_literal_fbt: public Item_literal { Fbt m_value; public: Item_literal_fbt(THD *thd) :Item_literal(thd), m_value(Fbt::zero()) { } Item_literal_fbt(THD *thd, const Fbt &value) :Item_literal(thd), m_value(value) { } const Type_handler *type_handler() const override { return singleton(); } bool val_bool() override { return m_value.to_bool(); } longlong val_int() override { return 0; } double val_real() override { return 0; } String *val_str(String *to) override { return m_value.to_string(to) ? NULL : to; } my_decimal *val_decimal(my_decimal *to) override { my_decimal_set_zero(to); return to; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return false; } bool val_native(THD *thd, Native *to) override { return m_value.to_native(to); } void print(String *str, enum_query_type query_type) override { StringBuffer<FbtImpl::max_char_length()+64> tmp; tmp.append(singleton()->name().lex_cstring()); my_caseup_str(&my_charset_latin1, tmp.c_ptr()); str->append(tmp); str->append('\''); m_value.to_string(&tmp); str->append(tmp); str->append('\''); } // Non-overriding methods void set_value(const Fbt &value) { m_value= value; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_literal_fbt>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Field_fbt: public Field { static void set_min_value(char *ptr) { memset(ptr, 0, FbtImpl::binary_length()); } static void set_max_value(char *ptr) { memset(ptr, 0xFF, FbtImpl::binary_length()); } void store_warning(const ErrConv &str, Sql_condition::enum_warning_level level) { if (get_thd()->count_cuted_fields <= CHECK_FIELD_EXPRESSION) return; const TABLE_SHARE *s= table->s; static const Name type_name= singleton()->name(); get_thd()->push_warning_truncated_value_for_field(level, type_name.ptr(), str.ptr(), s ? s->db.str : nullptr, s ? s->table_name.str : nullptr, field_name.str); } int set_null_with_warn(const ErrConv &str) { store_warning(str, Sql_condition::WARN_LEVEL_WARN); set_null(); return 1; } int set_min_value_with_warn(const ErrConv &str) { store_warning(str, Sql_condition::WARN_LEVEL_WARN); set_min_value((char*) ptr); return 1; } int set_max_value_with_warn(const ErrConv &str) { store_warning(str, Sql_condition::WARN_LEVEL_WARN); set_max_value((char*) ptr); return 1; } int store_fbt_null_with_warn(const Fbt_null &fbt, const ErrConvString &err) { DBUG_ASSERT(marked_for_write_or_computed()); if (fbt.is_null()) return maybe_null() ? set_null_with_warn(err) : set_min_value_with_warn(err); fbt.to_record((char *) ptr, FbtImpl::binary_length()); return 0; } public: Field_fbt(const LEX_CSTRING *field_name_arg, const Record_addr &rec) :Field(rec.ptr(), FbtImpl::max_char_length(), rec.null_ptr(), rec.null_bit(), Field::NONE, field_name_arg) { flags|= BINARY_FLAG | UNSIGNED_FLAG; } const Type_handler *type_handler() const override { return singleton(); } uint32 max_display_length() const override { return field_length; } bool str_needs_quotes() const override { return true; } const DTCollation &dtcollation() const override { static DTCollation_numeric c; return c; } CHARSET_INFO *charset(void) const override { return &my_charset_numeric; } const CHARSET_INFO *sort_charset(void) const override { return &my_charset_bin; } /** This makes client-server protocol convert the value according to @@character_set_client. */ bool binary() const override { return false; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } bool is_equal(const Column_definition &new_field) const override { return new_field.type_handler() == type_handler(); } bool eq_def(const Field *field) const override { return Field::eq_def(field); } double pos_in_interval(Field *min, Field *max) override { return pos_in_interval_val_str(min, max, 0); } int cmp(const uchar *a, const uchar *b) const override { return memcmp(a, b, pack_length()); } void sort_string(uchar *to, uint length) override { DBUG_ASSERT(length == pack_length()); memcpy(to, ptr, length); } uint32 pack_length() const override { return FbtImpl::binary_length(); } uint pack_length_from_metadata(uint field_metadata) const override { return FbtImpl::binary_length(); } void sql_type(String &str) const override { static Name name= singleton()->name(); str.set_ascii(name.ptr(), name.length()); } void make_send_field(Send_field *to) override { Field::make_send_field(to); to->set_data_type_name(singleton()->name().lex_cstring()); } bool validate_value_in_record(THD *thd, const uchar *record) const override { return false; } bool val_native(Native *to) override { DBUG_ASSERT(marked_for_read()); if (to->alloc(FbtImpl::binary_length())) return true; to->length(FbtImpl::binary_length()); FbtImpl::record_to_memory((char*) to->ptr(), (const char*) ptr); return false; } Fbt to_fbt() const { DBUG_ASSERT(marked_for_read()); return Fbt::record_to_memory((const char*) ptr); } String *val_str(String *val_buffer, String *) override { return to_fbt().to_string(val_buffer) ? NULL : val_buffer; } my_decimal *val_decimal(my_decimal *to) override { DBUG_ASSERT(marked_for_read()); my_decimal_set_zero(to); return to; } longlong val_int() override { DBUG_ASSERT(marked_for_read()); return 0; } double val_real() override { DBUG_ASSERT(marked_for_read()); return 0; } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { DBUG_ASSERT(marked_for_read()); set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return false; } bool val_bool(void) override { DBUG_ASSERT(marked_for_read()); return !Fbt::only_zero_bytes((const char *) ptr, FbtImpl::binary_length()); } int store_native(const Native &value) override { DBUG_ASSERT(marked_for_write_or_computed()); DBUG_ASSERT(value.length() == FbtImpl::binary_length()); FbtImpl::memory_to_record((char*) ptr, value.ptr()); return 0; } int store(const char *str, size_t length, CHARSET_INFO *cs) override { return cs == &my_charset_bin ? store_binary(str, length) : store_text(str, length, cs); } int store_text(const char *str, size_t length, CHARSET_INFO *cs) override { return store_fbt_null_with_warn(Fbt_null(str, length, cs), ErrConvString(str, length, cs)); } int store_binary(const char *str, size_t length) override { return store_fbt_null_with_warn(Fbt_null(str, length), ErrConvString(str, length, &my_charset_bin)); } int store_hex_hybrid(const char *str, size_t length) override { return Field_fbt::store_binary(str, length); } int store_decimal(const my_decimal *num) override { DBUG_ASSERT(marked_for_write_or_computed()); return set_min_value_with_warn(ErrConvDecimal(num)); } int store(longlong nr, bool unsigned_flag) override { DBUG_ASSERT(marked_for_write_or_computed()); return set_min_value_with_warn( ErrConvInteger(Longlong_hybrid(nr, unsigned_flag))); } int store(double nr) override { DBUG_ASSERT(marked_for_write_or_computed()); return set_min_value_with_warn(ErrConvDouble(nr)); } int store_time_dec(const MYSQL_TIME *ltime, uint dec) override { DBUG_ASSERT(marked_for_write_or_computed()); return set_min_value_with_warn(ErrConvTime(ltime)); } /*** Field conversion routines ***/ int store_field(Field *from) override { // INSERT INTO t1 (fbt_field) SELECT different_field_type FROM t2; return from->save_in_field(this); } int save_in_field(Field *to) override { // INSERT INTO t2 (different_field_type) SELECT fbt_field FROM t1; if (to->charset() == &my_charset_bin && dynamic_cast<const Type_handler_general_purpose_string*> (to->type_handler())) { NativeBuffer<FbtImpl::binary_length()+1> res; val_native(&res); return to->store(res.ptr(), res.length(), &my_charset_bin); } return save_in_field_str(to); } Copy_func *get_copy_func(const Field *from) const override { // ALTER to FBT from another field return do_field_string; } Copy_func *get_copy_func_to(const Field *to) const override { if (type_handler() == to->type_handler()) { // ALTER from FBT to FBT DBUG_ASSERT(pack_length() == to->pack_length()); DBUG_ASSERT(charset() == to->charset()); DBUG_ASSERT(sort_charset() == to->sort_charset()); return Field::do_field_eq; } // ALTER from FBT to another fbt type if (to->charset() == &my_charset_bin && dynamic_cast<const Type_handler_general_purpose_string*> (to->type_handler())) { /* ALTER from FBT to a binary string type, e.g.: BINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB */ return do_field_fbt_native_to_binary; } return do_field_string; } static void do_field_fbt_native_to_binary(const Copy_field *copy) { NativeBuffer<FbtImpl::binary_length()+1> res; copy->from_field->val_native(&res); copy->to_field->store(res.ptr(), res.length(), &my_charset_bin); } bool memcpy_field_possible(const Field *from) const override { // INSERT INTO t1 (fbt_field) SELECT field2 FROM t2; return type_handler() == from->type_handler(); } enum_conv_type rpl_conv_type_from(const Conv_source &source, const Relay_log_info *rli, const Conv_param ¶m) const override { if (type_handler() == source.type_handler() || (source.type_handler() == &type_handler_string && source.type_handler()->max_display_length_for_field(source) == FbtImpl::binary_length())) return rpl_conv_type_from_same_data_type(source.metadata(), rli, param); return CONV_TYPE_IMPOSSIBLE; } /*** Optimizer routines ***/ bool test_if_equality_guarantees_uniqueness(const Item *const_item) const override { /* This condition: WHERE fbt_field=const should return a single distinct value only, as comparison is done according to FBT. */ return true; } bool can_be_substituted_to_equal_item(const Context &ctx, const Item_equal *item_equal) override { switch (ctx.subst_constraint()) { case ANY_SUBST: return ctx.compare_type_handler() == item_equal->compare_type_handler(); case IDENTITY_SUBST: return true; } return false; } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override { Fbt_null tmp(const_item); if (tmp.is_null()) return NULL; return new (thd->mem_root) Item_literal_fbt(thd, tmp); } Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const override { /* Mixing of two different non-traditional types is currently prevented. This may change in the future. */ DBUG_ASSERT(item->type_handler()->type_handler_base_or_self()-> is_traditional_scalar_type() || item->type_handler()->type_collection() == type_handler()->type_collection()); return Data_type_compatibility::OK; } /** Test if Field can use range optimizer for a standard comparison operation: <=, <, =, <=>, >, >= Note, this method does not cover spatial operations. */ Data_type_compatibility can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const override { // See the DBUG_ASSERT comment in can_optimize_keypart_ref() DBUG_ASSERT(item->type_handler()->type_handler_base_or_self()-> is_traditional_scalar_type() || item->type_handler()->type_collection() == type_handler()->type_collection()); return Data_type_compatibility::OK; } void hash_not_null(Hasher *hasher) override { FbtImpl::hash_record(ptr, hasher); } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) override { DBUG_ENTER("Field_fbt::get_mm_leaf"); if (can_optimize_scalar_range(prm, key_part, cond, op, value) != Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) DBUG_RETURN(&null_element); if (err > 0) { if (op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL) DBUG_RETURN(new (prm->mem_root) SEL_ARG_IMPOSSIBLE(this)); DBUG_RETURN(NULL); /* Cannot infer anything */ } DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); } Data_type_compatibility can_optimize_hash_join(const Item_bool_func *cond, const Item *item) const override { return can_optimize_keypart_ref(cond, item); } Data_type_compatibility can_optimize_group_min_max( const Item_bool_func *cond, const Item *const_item) const override { return Data_type_compatibility::OK; } uint row_pack_length() const override { return pack_length(); } Binlog_type_info binlog_type_info() const override { DBUG_ASSERT(type() == binlog_type()); return Binlog_type_info_fixed_string(Field_fbt::binlog_type(), FbtImpl::binary_length(), &my_charset_bin); } uchar *pack(uchar *to, const uchar *from, uint max_length) override { DBUG_PRINT("debug", ("Packing field '%s'", field_name.str)); return FbtImpl::pack(to, from, max_length); } const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override { return FbtImpl::unpack(to, from, from_end, param_data); } uint max_packed_col_length(uint max_length) override { return StringPack::max_packed_col_length(max_length); } uint packed_col_length(const uchar *fbt_ptr, uint length) override { return StringPack::packed_col_length(fbt_ptr, length); } uint size_of() const override { return sizeof(*this); } }; class cmp_item_fbt: public cmp_item_scalar { Fbt m_native; public: cmp_item_fbt() :cmp_item_scalar(), m_native(Fbt::zero()) { } void store_value(Item *item) override { m_native= Fbt(item, &m_null_value); } int cmp_not_null(const Value *val) override { DBUG_ASSERT(!val->is_null()); DBUG_ASSERT(val->is_string()); Fbt_null tmp(val->m_string); DBUG_ASSERT(!tmp.is_null()); return m_native.cmp(tmp); } int cmp(Item *arg) override { Fbt_null tmp(arg); return m_null_value || tmp.is_null() ? UNKNOWN : m_native.cmp(tmp) != 0; } int compare(const cmp_item *ci) const override { const cmp_item_fbt *tmp= static_cast<const cmp_item_fbt*>(ci); DBUG_ASSERT(!m_null_value); DBUG_ASSERT(!tmp->m_null_value); return m_native.cmp(tmp->m_native); } cmp_item *make_same(THD *thd) override { return new (thd->mem_root) cmp_item_fbt(); } }; class in_fbt :public in_vector { Fbt m_value; static int cmp_fbt(void *cmp_arg, const void *a, const void *b) { return static_cast<const Fbt*>(a)->cmp(*static_cast<const Fbt*>(b)); } public: in_fbt(THD *thd, uint elements) :in_vector(thd, elements, sizeof(Fbt), cmp_fbt, 0), m_value(Fbt::zero()) { } const Type_handler *type_handler() const override { return singleton(); } bool set(uint pos, Item *item) override { Fbt *buff= &((Fbt *) base)[pos]; Fbt_null value(item); if (value.is_null()) { *buff= Fbt::zero(); return true; } *buff= value; return false; } uchar *get_value(Item *item) override { Fbt_null value(item); if (value.is_null()) return 0; m_value= value; return (uchar *) &m_value; } Item* create_item(THD *thd) override { return new (thd->mem_root) Item_literal_fbt(thd); } void value_to_item(uint pos, Item *item) override { const Fbt &buff= (((Fbt*) base)[pos]); static_cast<Item_literal_fbt*>(item)->set_value(buff); } }; class Item_copy_fbt: public Item_copy { NativeBuffer<Fbt::binary_length()+1> m_value; public: Item_copy_fbt(THD *thd, Item *item_arg): Item_copy(thd, item_arg) {} bool val_native(THD *thd, Native *to) override { if (null_value) return true; return to->copy(m_value.ptr(), m_value.length()); } String *val_str(String *to) override { if (null_value) return NULL; Fbt_null tmp(m_value.ptr(), m_value.length()); return tmp.is_null() || tmp.to_string(to) ? NULL : to; } my_decimal *val_decimal(my_decimal *to) override { my_decimal_set_zero(to); return to; } double val_real() override { return 0; } longlong val_int() override { return 0; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return null_value; } void copy() override { null_value= item->val_native(current_thd, &m_value); DBUG_ASSERT(null_value == item->null_value); } int save_in_field(Field *field, bool no_conversions) override { return Item::save_in_field(field, no_conversions); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_copy_fbt>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_char_typecast_func_handler_fbt_to_binary: public Item_handled_func::Handler_str { public: const Type_handler *return_type_handler(const Item_handled_func *item) const override { if (item->max_length > MAX_FIELD_VARCHARLENGTH) return Type_handler::blob_type_handler(item->max_length); if (item->max_length > 255) return &type_handler_varchar; return &type_handler_string; } bool fix_length_and_dec(Item_handled_func *xitem) const override { return false; } String *val_str(Item_handled_func *item, String *to) const override { DBUG_ASSERT(dynamic_cast<const Item_char_typecast*>(item)); return static_cast<Item_char_typecast*>(item)-> val_str_binary_from_native(to); } }; class Item_typecast_fbt: public Item_func { public: Item_typecast_fbt(THD *thd, Item *a) :Item_func(thd, a) {} const Type_handler *type_handler() const override { return singleton(); } enum Functype functype() const override { return CHAR_TYPECAST_FUNC; } bool eq(const Item *item, const Eq_config &config) const override { if (this == item) return true; if (item->type() != FUNC_ITEM || functype() != ((Item_func*)item)->functype()) return false; if (type_handler() != item->type_handler()) return false; Item_typecast_fbt *cast= (Item_typecast_fbt*) item; return args[0]->eq(cast->args[0], config); } LEX_CSTRING func_name_cstring() const override { static Name name= singleton()->name(); size_t len= 9+name.length()+1; char *buf= (char*)current_thd->alloc(len); strmov(strmov(buf, "cast_as_"), name.ptr()); return { buf, len }; } void print(String *str, enum_query_type query_type) override { str->append(STRING_WITH_LEN("cast(")); args[0]->print(str, query_type); str->append(STRING_WITH_LEN(" as ")); str->append(singleton()->name().lex_cstring()); str->append(')'); } bool fix_length_and_dec(THD *thd) override { Type_std_attributes::operator=(Type_std_attributes_fbt()); if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(args[0])) set_maybe_null(); return false; } String *val_str(String *to) override { Fbt_null tmp(args[0]); return (null_value= tmp.is_null() || tmp.to_string(to)) ? NULL : to; } longlong val_int() override { return 0; } double val_real() override { return 0; } my_decimal *val_decimal(my_decimal *to) override { my_decimal_set_zero(to); return to; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return false; } bool val_native(THD *thd, Native *to) override { Fbt_null tmp(args[0]); return null_value= tmp.is_null() || tmp.to_native(to); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_typecast_fbt>(thd, this); } }; class Item_cache_fbt: public Item_cache { NativeBuffer<FbtImpl::binary_length()+1> m_value; public: Item_cache_fbt(THD *thd) :Item_cache(thd, singleton()) { } bool cache_value() override { if (!example) return false; value_cached= true; null_value_inside= null_value= example->val_native_with_conversion_result(current_thd, &m_value, type_handler()); return true; } String* val_str(String *to) override { if (!has_value()) return NULL; Fbt_null tmp(m_value.ptr(), m_value.length()); return tmp.is_null() || tmp.to_string(to) ? NULL : to; } my_decimal *val_decimal(my_decimal *to) override { if (!has_value()) return NULL; my_decimal_set_zero(to); return to; } longlong val_int() override { if (!has_value()) return 0; return 0; } double val_real() override { if (!has_value()) return 0; return 0; } longlong val_datetime_packed(THD *) override { DBUG_ASSERT(0); if (!has_value()) return 0; return 0; } longlong val_time_packed(THD *) override { DBUG_ASSERT(0); if (!has_value()) return 0; return 0; } bool get_date(THD *, MYSQL_TIME *ltime, date_mode_t) override { if (!has_value()) return true; set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return false; } bool val_native(THD *, Native *to) override { if (!has_value()) return true; return to->copy(m_value.ptr(), m_value.length()); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_fbt>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* =[ methods ]=============================================== */ private: bool character_or_binary_string_to_native(THD *thd, const String *str, Native *to) const { if (str->charset() == &my_charset_bin) { // Convert from a binary string if (str->length() != FbtImpl::binary_length() || to->copy(str->ptr(), str->length())) { thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, name().ptr(), ErrConvString(str).ptr()); return true; } return false; } // Convert from a character string Fbt_null tmp(*str); if (tmp.is_null()) thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, name().ptr(), ErrConvString(str).ptr()); return tmp.is_null() || tmp.to_native(to); } public: ~Type_handler_fbt() override {} const Type_collection *type_collection() const override { return TypeCollectionImpl::singleton(); } const Name &default_value() const override { return FbtImpl::default_value(); } ulong KEY_pack_flags(uint column_nr) const override { return FbtImpl::KEY_pack_flags(column_nr); } protocol_send_type_t protocol_send_type() const override { return PROTOCOL_SEND_STRING; } bool Item_append_extended_type_info(Send_field_extended_metadata *to, const Item *item) const override { return to->set_data_type_name(name().lex_cstring()); } enum_field_types field_type() const override { return MYSQL_TYPE_STRING; } Item_result result_type() const override { return STRING_RESULT; } Item_result cmp_type() const override { return STRING_RESULT; } enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const override { return DYN_COL_STRING; } uint32 max_display_length_for_field(const Conv_source &src) const override { return FbtImpl::max_char_length(); } const Type_handler *type_handler_for_implicit_upgrade() const override { return TypeCollectionImpl::singleton()-> type_handler_for_implicit_upgrade(this); } const Type_handler *type_handler_for_comparison() const override { return this; } int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override { DBUG_ASSERT(field->type_handler() == this); Fbt_null ni(item); // Convert Item to Fbt if (ni.is_null()) return 0; NativeBuffer<FbtImpl::binary_length()+1> tmp; if (field->val_native(&tmp)) { DBUG_ASSERT(0); return 0; } return -ni.cmp(tmp); } CHARSET_INFO *charset_for_protocol(const Item *item) const override { return item->collation.collation; } bool is_scalar_type() const override { return true; } bool is_val_native_ready() const override { return true; } bool can_return_int() const override { return false; } bool can_return_decimal() const override { return false; } bool can_return_real() const override { return false; } bool can_return_str() const override { return true; } bool can_return_text() const override { return true; } bool can_return_date() const override { return false; } bool can_return_time() const override { return false; } bool convert_to_binary_using_val_native() const override { return true; } decimal_digits_t Item_time_precision(THD *thd, Item *item) const override { return 0; } decimal_digits_t Item_datetime_precision(THD *thd, Item *item) const override { return 0; } decimal_digits_t Item_decimal_scale(const Item *item) const override { return 0; } decimal_digits_t Item_decimal_precision(const Item *item) const override { /* This will be needed if we ever allow cast from Fbt to DECIMAL. */ return (FbtImpl::binary_length()*8+7)/10*3; // = bytes to decimal digits } /* Returns how many digits a divisor adds into a division result. See Item::divisor_precision_increment() in item.h for more comments. */ decimal_digits_t Item_divisor_precision_increment(const Item *) const override { return 0; } /** Makes a temporary table Field to handle numeric aggregate functions, e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc. */ Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override { DBUG_ASSERT(0); return 0; } Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override { const Record_addr tmp(NULL, Bit_addr(true)); return new (table->in_use->mem_root) Field_fbt(&empty_clex_str, tmp); } // Fix attributes after the parser bool Column_definition_fix_attributes(Column_definition *c) const override { c->length= FbtImpl::max_char_length(); return false; } bool Column_definition_prepare_stage1(THD *, MEM_ROOT *, Column_definition *def, column_definition_type_t, const Column_derived_attributes *) const override { def->prepare_stage1_simple(&my_charset_numeric); return false; } bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file) const override { def->redefine_stage1_common(dup, file); def->set_compression_method(dup->compression_method()); def->create_length_to_internal_length_string(); return false; } bool Column_definition_prepare_stage2(Column_definition *def, handler *file, ulonglong table_flags) const override { def->pack_flag= FIELDFLAG_BINARY; return false; } bool partition_field_check(const LEX_CSTRING &field_name, Item *item_expr) const override { if (item_expr->cmp_type() != STRING_RESULT) { my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); return true; } return false; } bool partition_field_append_value(String *to, Item *item_expr, CHARSET_INFO *field_cs, partition_value_print_mode_t mode) const override { StringBuffer<FbtImpl::max_char_length()+64> fbtstr; Fbt_null fbt(item_expr); if (fbt.is_null()) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); return true; } return fbt.to_string(&fbtstr) || to->append('\'') || to->append(fbtstr) || to->append('\''); } Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, TABLE_SHARE *table) const override { return new (root) Field_fbt(name, addr); } Field * make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, const Record_addr &addr, const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const override { return new (mem_root) Field_fbt(name, addr); } void Column_definition_attributes_frm_pack(const Column_definition_attributes *def, uchar *buff) const override { def->frm_pack_basic(buff); def->frm_pack_charset(buff); } bool Column_definition_attributes_frm_unpack(Column_definition_attributes *def, TABLE_SHARE *share, const uchar *buffer, LEX_CUSTRING *gis_options) const override { def->frm_unpack_basic(buffer); return def->frm_unpack_charset(share, buffer); } void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *) const override { DBUG_ASSERT(item->type_handler() == this); NativeBuffer<FbtImpl::binary_length()+1> tmp; item->val_native_result(current_thd, &tmp); if (item->maybe_null()) { if (item->null_value) { memset(to, 0, FbtImpl::binary_length() + 1); return; } *to++= 1; } DBUG_ASSERT(!item->null_value); DBUG_ASSERT(FbtImpl::binary_length() == tmp.length()); DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length); FbtImpl::memory_to_record((char*) to, tmp.ptr()); } uint make_packed_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, String *) const override { DBUG_ASSERT(item->type_handler() == this); NativeBuffer<FbtImpl::binary_length()+1> tmp; item->val_native_result(current_thd, &tmp); if (item->maybe_null()) { if (item->null_value) { *to++=0; return 0; } *to++= 1; } DBUG_ASSERT(!item->null_value); DBUG_ASSERT(FbtImpl::binary_length() == tmp.length()); DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length); FbtImpl::memory_to_record((char*) to, tmp.ptr()); return tmp.length(); } void sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override { attr->original_length= attr->length= FbtImpl::binary_length(); attr->suffix_length= 0; } uint32 max_display_length(const Item *item) const override { return FbtImpl::max_char_length(); } uint32 calc_pack_length(uint32 length) const override { return FbtImpl::binary_length(); } void Item_update_null_value(Item *item) const override { NativeBuffer<FbtImpl::binary_length()+1> tmp; item->val_native(current_thd, &tmp); } bool Item_save_in_value(THD *thd, Item *item, st_value *value) const override { value->m_type= DYN_COL_STRING; String *str= item->val_str(&value->m_string); if (str != &value->m_string && !item->null_value) { // "item" returned a non-NULL value if (Fbt_null(*str).is_null()) { /* The value was not-null, but conversion to FBT failed: SELECT a, DECODE_ORACLE(fbtcol, 'garbage', '<NULL>', '::01', '01') FROM t1; */ thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, name().ptr(), ErrConvString(str).ptr()); value->m_type= DYN_COL_NULL; return true; } // "item" returned a non-NULL value, and it was a valid FBT value->m_string.set(str->ptr(), str->length(), str->charset()); } return check_null(item, value); } void Item_param_setup_conversion(THD *thd, Item_param *param) const override { param->setup_conversion_string(thd, thd->variables.character_set_client); } void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override { param->set_param_str(pos, len); } bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *val) const override { param->unsigned_flag= false; param->setup_conversion_string(thd, attr->collation.collation); /* Exact value of max_length is not known unless fbt is converted to charset of connection, so we have to set it later. */ return param->set_str(val->m_string.ptr(), val->m_string.length(), attr->collation.collation, attr->collation.collation); } bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const override { StringBuffer<FbtImpl::max_char_length()+1> buffer; String *str= item->val_str(&buffer); if (!str) return true; Fbt_null tmp(*str); return tmp.is_null() || tmp.to_native(to); } bool Item_send(Item *item, Protocol *p, st_value *buf) const override { return Item_send_str(item, p, buf); } int Item_save_in_field(Item *item, Field *field, bool no_conversions) const override { if (field->type_handler() == this) { NativeBuffer<MAX_FIELD_WIDTH> tmp; bool rc= item->val_native(current_thd, &tmp); if (rc || item->null_value) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); return field->store_native(tmp); } return item->save_str_in_field(field, no_conversions); } String *print_item_value(THD *thd, Item *item, String *str) const override { StringBuffer<FbtImpl::max_char_length()+64> buf; String *result= item->val_str(&buf); /* TODO: This should eventually use one of these notations: 1. CAST('xxx' AS Fbt) Problem: CAST is not supported as a NAME_CONST() argument. 2. Fbt'xxx' Problem: This syntax is not supported by the parser yet. */ return !result || str->realloc(result->length() + 2) || str->append(STRING_WITH_LEN("'")) || str->append(result->ptr(), result->length()) || str->append(STRING_WITH_LEN("'")) ? nullptr : str; } /** Check if WHERE expr=value AND expr=const can be rewritten as: WHERE const=value AND expr=const "this" is the comparison handler that is used by "target". @param target - the predicate expr=value, whose "expr" argument will be replaced to "const". @param target_expr - the target's "expr" which will be replaced to "const". @param target_value - the target's second argument, it will remain unchanged. @param source - the equality predicate expr=const (or expr<=>const) that can be used to rewrite the "target" part (under certain conditions, see the code). @param source_expr - the source's "expr". It should be exactly equal to the target's "expr" to make condition rewrite possible. @param source_const - the source's "const" argument, it will be inserted into "target" instead of "expr". */ bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const override { /* WHERE COALESCE(col)='xxx' AND COALESCE(col)=CONCAT(a); --> WHERE COALESCE(col)='xxx' AND 'xxx'=CONCAT(a); */ return target->compare_type_handler() == source->compare_type_handler(); } bool subquery_type_allows_materialization(const Item *inner, const Item *outer, bool) const override { /* Example: SELECT * FROM t1 WHERE a IN (SELECT col FROM t1 GROUP BY col); Allow materialization only if the outer column is also FBT. This can be changed for more relaxed rules in the future. */ DBUG_ASSERT(inner->type_handler() == this); return outer->type_handler() == this; } /** Make a simple constant replacement item for a constant "src", so the new item can futher be used for comparison with "cmp", e.g.: src = cmp -> replacement = cmp "this" is the type handler that is used to compare "src" and "cmp". @param thd - current thread, for mem_root @param src - The item that we want to replace. It's a const item, but it can be complex enough to calculate on every row. @param cmp - The src's comparand. @retval - a pointer to the created replacement Item @retval - NULL, if could not create a replacement (e.g. on EOM). NULL is also returned for ROWs, because instead of replacing a Item_row to a new Item_row, Type_handler_row just replaces its elements. */ Item *make_const_item_for_comparison(THD *thd, Item *src, const Item *cmp) const override { Fbt_null tmp(src); if (tmp.is_null()) return new (thd->mem_root) Item_null(thd, src->name.str); return new (thd->mem_root) Item_literal_fbt(thd, tmp); } Item_cache *Item_get_cache(THD *thd, const Item *item) const override { return new (thd->mem_root) Item_cache_fbt(thd); } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override { return new (thd->mem_root) Item_typecast_fbt(thd, item); } Item_copy *create_item_copy(THD *thd, Item *item) const override { return new (thd->mem_root) Item_copy_fbt(thd, item); } int cmp_native(const Native &a, const Native &b) const override { return FbtImpl::cmp(a.to_lex_cstring(), b.to_lex_cstring()); } bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override { return cmp->set_cmp_func_native(thd); } bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const override { return false; } bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const override { Fbt_null na(a), nb(b); return !na.is_null() && !nb.is_null() && !na.cmp(nb); } bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, Item_bool_rowready_func2 *func) const override { if (Type_handler::Item_bool_rowready_func2_fix_length_and_dec(thd, func)) return true; if (!func->maybe_null() && Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 2)) func->set_maybe_null(); return false; } bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *h, Type_all_attributes *attr, Item **items, uint nitems) const override { attr->Type_std_attributes::operator=(Type_std_attributes_fbt()); h->set_handler(this); /* If some of the arguments cannot be safely converted to "FBT NOT NULL", then mark the entire function nullability as NULL-able. Otherwise, keep the generic nullability calculated by earlier stages: - either by the most generic way in Item_func::fix_fields() - or by Item_func_xxx::fix_length_and_dec() before the call of Item_hybrid_func_fix_attributes() IFNULL and COALESCE are special- If the first non-null arg can be safely converted to result type, the result is guaranteed to be NOT NULL */ bool not_null_on_conversion= false; if (dynamic_cast<Item_func_ifnull*>(attr) || dynamic_cast<Item_func_coalesce*>(attr)) { for (uint i= 0; i< nitems; i++) { if (!items[i]->maybe_null() && !Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i])) { not_null_on_conversion= true; break; } } } else { not_null_on_conversion= true; for (uint i= 0; i < nitems; i++) { if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i])) { not_null_on_conversion= false; break; } } } if (not_null_on_conversion) attr->set_type_maybe_null(false); else attr->set_type_maybe_null(true); return false; } bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const override { return Item_hybrid_func_fix_attributes(thd, func->func_name_cstring(), func, func, items, nitems); } bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override { func->Type_std_attributes::operator=(Type_std_attributes_fbt()); func->set_handler(this); return false; } bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_val_native_with_conversion(THD *thd, Item *item, Native *to) const override { if (item->type_handler() == this) return item->val_native(thd, to); // No conversion needed StringBuffer<FbtImpl::max_char_length()+1> buffer; String *str= item->val_str(&buffer); return str ? character_or_binary_string_to_native(thd, str, to) : true; } bool Item_val_native_with_conversion_result(THD *thd, Item *item, Native *to) const override { if (item->type_handler() == this) return item->val_native_result(thd, to); // No conversion needed StringBuffer<FbtImpl::max_char_length()+1> buffer; String *str= item->str_result(&buffer); return str ? character_or_binary_string_to_native(thd, str, to) : true; } bool Item_val_bool(Item *item) const override { NativeBuffer<FbtImpl::binary_length()+1> tmp; if (item->val_native(current_thd, &tmp)) return false; return !Fbt::only_zero_bytes(tmp.ptr(), tmp.length()); } void Item_get_date(THD *thd, Item *item, Temporal::Warn *buff, MYSQL_TIME *ltime, date_mode_t fuzzydate) const override { set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); } longlong Item_val_int_signed_typecast(Item *item) const override { DBUG_ASSERT(0); return 0; } longlong Item_val_int_unsigned_typecast(Item *item) const override { DBUG_ASSERT(0); return 0; } String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const override { NativeBuffer<FbtImpl::binary_length()+1> tmp; if ((item->null_value= item->arguments()[0]->val_native(current_thd, &tmp))) return nullptr; DBUG_ASSERT(tmp.length() == FbtImpl::binary_length()); if (str->set_hex(tmp.ptr(), tmp.length())) { str->length(0); str->set_charset(item->collation.collation); } return str; } String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *item, String *str) const override { NativeBuffer<FbtImpl::binary_length()+1> native; if (item->val_native(current_thd, &native)) { DBUG_ASSERT(item->null_value); return nullptr; } DBUG_ASSERT(native.length() == FbtImpl::binary_length()); Fbt_null tmp(native.ptr(), native.length()); return tmp.is_null() || tmp.to_string(str) ? nullptr : str; } double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *) const override { return 0; } longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *) const override { return 0; } my_decimal * Item_func_hybrid_field_type_val_decimal(Item_func_hybrid_field_type *, my_decimal *to) const override { my_decimal_set_zero(to); return to; } void Item_func_hybrid_field_type_get_date(THD *, Item_func_hybrid_field_type *, Temporal::Warn *, MYSQL_TIME *to, date_mode_t fuzzydate) const override { set_zero_time(to, MYSQL_TIMESTAMP_TIME); } // WHERE is Item_func_min_max_val_native??? String *Item_func_min_max_val_str(Item_func_min_max *func, String *str) const override { Fbt_null tmp(func); return tmp.is_null() || tmp.to_string(str) ? nullptr : str; } double Item_func_min_max_val_real(Item_func_min_max *) const override { return 0; } longlong Item_func_min_max_val_int(Item_func_min_max *) const override { return 0; } my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *to) const override { my_decimal_set_zero(to); return to; } bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *to, date_mode_t fuzzydate) const override { set_zero_time(to, MYSQL_TIMESTAMP_TIME); return false; } bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override { if (!func->maybe_null() && Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 3)) func->set_maybe_null(); return false; } longlong Item_func_between_val_int(Item_func_between *func) const override { return func->val_int_cmp_native(); } cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override { return new (thd->mem_root) cmp_item_fbt; } in_vector *make_in_vector(THD *thd, const Item_func_in *func, uint nargs) const override { return new (thd->mem_root) in_fbt(thd, nargs); } bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *func) const override { if (!func->maybe_null() && Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), func->argument_count())) func->set_maybe_null(); if (func->compatible_types_scalar_bisection_possible()) { return func->value_list_convert_const_to_int(thd) || func->fix_for_scalar_comparison_using_bisection(thd); } return func->fix_for_scalar_comparison_using_cmp_items(thd, 1U << (uint) STRING_RESULT); } bool Item_func_round_fix_length_and_dec(Item_func_round *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_func_abs_fix_length_and_dec(Item_func_abs *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_func_neg_fix_length_and_dec(Item_func_neg *func) const override { return Item_func_or_sum_illegal_param(func); } bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const override { if (item->cast_charset() == &my_charset_bin) { static Item_char_typecast_func_handler_fbt_to_binary item_char_typecast_func_handler_fbt_to_binary; item->fix_length_and_dec_native_to_binary(FbtImpl::binary_length()); item->set_func_handler(&item_char_typecast_func_handler_fbt_to_binary); return false; } item->fix_length_and_dec_str(); return false; } bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_plus_fix_length_and_dec(Item_func_plus *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_minus_fix_length_and_dec(Item_func_minus *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_mul_fix_length_and_dec(Item_func_mul *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_div_fix_length_and_dec(Item_func_div *item) const override { return Item_func_or_sum_illegal_param(item); } bool Item_func_mod_fix_length_and_dec(Item_func_mod *item) const override { return Item_func_or_sum_illegal_param(item); } static Type_handler_fbt *singleton() { static Type_handler_fbt th; return &th; } }; template<class FbtImpl> class Type_collection_fbt: public Type_collection { const Type_handler *aggregate_common(const Type_handler *a, const Type_handler *b) const { if (a == b) return a; return NULL; } const Type_handler *aggregate_if_string(const Type_handler *a, const Type_handler *b) const { static const Type_aggregator::Pair agg[]= { {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_null, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_varchar, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_string, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_tiny_blob, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_blob, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_medium_blob, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_long_blob, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_hex_hybrid, Type_handler_fbt<FbtImpl>::singleton()}, {NULL,NULL,NULL} }; return Type_aggregator::find_handler_in_array(agg, a, b, true); } public: const Type_handler *aggregate_for_result(const Type_handler *a, const Type_handler *b) const override { const Type_handler *h; if ((h= aggregate_common(a, b)) || (h= aggregate_if_string(a, b))) return h; return NULL; } const Type_handler *aggregate_for_min_max(const Type_handler *a, const Type_handler *b) const override { return aggregate_for_result(a, b); } const Type_handler *aggregate_for_comparison(const Type_handler *a, const Type_handler *b) const override { if (const Type_handler *h= aggregate_common(a, b)) return h; static const Type_aggregator::Pair agg[]= { {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_null, Type_handler_fbt<FbtImpl>::singleton()}, {Type_handler_fbt<FbtImpl>::singleton(), &type_handler_long_blob, Type_handler_fbt<FbtImpl>::singleton()}, {NULL,NULL,NULL} }; return Type_aggregator::find_handler_in_array(agg, a, b, true); } const Type_handler *aggregate_for_num_op(const Type_handler *a, const Type_handler *b) const override { return NULL; } const Type_handler *type_handler_for_implicit_upgrade( const Type_handler *from) const { return from; } static Type_collection_fbt *singleton() { static Type_collection_fbt tc; return &tc; } }; #endif /* SQL_TYPE_FIXEDBIN_H */ wsrep_high_priority_service.h 0000644 00000011460 15156036154 0012545 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_HIGH_PRIORITY_SERVICE_H #define WSREP_HIGH_PRIORITY_SERVICE_H #include "wsrep/high_priority_service.hpp" #include "my_global.h" #include "sql_error.h" /* Diagnostics area */ #include "sql_class.h" /* rpl_group_info */ class THD; class Relay_log_info; class Wsrep_server_service; class Wsrep_high_priority_service : public wsrep::high_priority_service, public wsrep::high_priority_context { public: Wsrep_high_priority_service(THD*); ~Wsrep_high_priority_service(); int start_transaction(const wsrep::ws_handle&, const wsrep::ws_meta&) override; int next_fragment(const wsrep::ws_meta&) override; const wsrep::transaction& transaction() const override; int adopt_transaction(const wsrep::transaction&) override; int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&, wsrep::mutable_buffer&) override = 0; int append_fragment_and_commit(const wsrep::ws_handle&, const wsrep::ws_meta&, const wsrep::const_buffer&, const wsrep::xid&) override; int remove_fragments(const wsrep::ws_meta&) override; int commit(const wsrep::ws_handle&, const wsrep::ws_meta&) override; int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&) override; int apply_toi(const wsrep::ws_meta&, const wsrep::const_buffer&, wsrep::mutable_buffer&) override; void store_globals() override; void reset_globals() override; void switch_execution_context(wsrep::high_priority_service&) override; int log_dummy_write_set(const wsrep::ws_handle&, const wsrep::ws_meta&, wsrep::mutable_buffer&) override; void adopt_apply_error(wsrep::mutable_buffer&) override; virtual bool check_exit_status() const = 0; void debug_crash(const char*) override; protected: friend Wsrep_server_service; THD* m_thd; Relay_log_info* m_rli; rpl_group_info* m_rgi; struct shadow { ulonglong option_bits; uint server_status; struct st_vio* vio; ulong tx_isolation; char* db; size_t db_length; //struct timeval user_time; my_hrtime_t user_time; longlong row_count_func; bool wsrep_applier; } m_shadow; }; class Wsrep_applier_service : public Wsrep_high_priority_service { public: Wsrep_applier_service(THD*); ~Wsrep_applier_service(); int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&, wsrep::mutable_buffer&) override; int apply_nbo_begin(const wsrep::ws_meta&, const wsrep::const_buffer& data, wsrep::mutable_buffer& err) override; void after_apply() override; bool is_replaying() const override { return false; } bool check_exit_status() const override; }; class Wsrep_replayer_service : public Wsrep_high_priority_service { public: Wsrep_replayer_service(THD* replayer_thd, THD* orig_thd); ~Wsrep_replayer_service(); int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&, wsrep::mutable_buffer&) override; int apply_nbo_begin(const wsrep::ws_meta&, const wsrep::const_buffer& data, wsrep::mutable_buffer& err) override { DBUG_ASSERT(0); /* DDL should never cause replaying */ return 0; } void after_apply() override { } bool is_replaying() const override { return true; } void replay_status(enum wsrep::provider::status status) { m_replay_status = status; } enum wsrep::provider::status replay_status() const { return m_replay_status; } /* Replayer should never be forced to exit */ bool check_exit_status() const override { return false; } private: THD* m_orig_thd; struct da_shadow { enum Diagnostics_area::enum_diagnostics_status status; ulonglong affected_rows; ulonglong last_insert_id; char message[MYSQL_ERRMSG_SIZE]; da_shadow() : status() , affected_rows() , last_insert_id() , message() { } } m_da_shadow; enum wsrep::provider::status m_replay_status; }; #endif /* WSREP_HIGH_PRIORITY_SERVICE_H */ lock.h 0000644 00000004315 15156036155 0005657 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef LOCK_INCLUDED #define LOCK_INCLUDED #include "thr_lock.h" /* thr_lock_type */ #include "mdl.h" // Forward declarations struct TABLE; struct TABLE_LIST; class THD; typedef struct st_mysql_lock MYSQL_LOCK; MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags); bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags); int mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock); int mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); int mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); int mysql_unlock_some_tables(THD *thd, TABLE **table,uint count, uint flag); int mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); bool mysql_lock_abort_for_thread(THD *thd, TABLE *table); MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a, MYSQL_LOCK *b, THD *thd= NULL); /* Lock based on name */ bool lock_schema_name(THD *thd, const Lex_ident_db_normalized &db); /* Lock based on stored routine name */ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, const LEX_CSTRING &db, const LEX_CSTRING &name); /* flags for get_lock_data */ #define GET_LOCK_UNLOCK 0 #define GET_LOCK_STORE_LOCKS 1 #define GET_LOCK_ACTION_MASK 1 #define GET_LOCK_ON_THD (1 << 1) #define GET_LOCK_SKIP_SEQUENCES (1 << 2) MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags); void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock); #endif /* LOCK_INCLUDED */ sql_audit.h 0000644 00000033522 15156036155 0006716 0 ustar 00 #ifndef SQL_AUDIT_INCLUDED #define SQL_AUDIT_INCLUDED /* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <mysql/plugin_audit.h> #include "sql_class.h" extern unsigned long mysql_global_audit_mask[]; extern void mysql_audit_initialize(); extern void mysql_audit_finalize(); extern void mysql_audit_init_thd(THD *thd); extern void mysql_audit_free_thd(THD *thd); extern void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask); #ifndef EMBEDDED_LIBRARY extern void mysql_audit_notify(THD *thd, uint event_class, const void *event); static inline bool mysql_audit_general_enabled() { return mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK; } static inline bool mysql_audit_connection_enabled() { return mysql_global_audit_mask[0] & MYSQL_AUDIT_CONNECTION_CLASSMASK; } static inline bool mysql_audit_table_enabled() { return mysql_global_audit_mask[0] & MYSQL_AUDIT_TABLE_CLASSMASK; } #else static inline void mysql_audit_notify(THD *thd, uint event_class, const void *event) {} #define mysql_audit_general_enabled() 0 #define mysql_audit_connection_enabled() 0 #define mysql_audit_table_enabled() 0 #endif extern my_bool mysql_audit_release_required(THD *thd); extern void mysql_audit_release(THD *thd); static inline unsigned int strlen_uint(const char *s) { return (uint)strlen(s); } static inline unsigned int safe_strlen_uint(const char *s) { return (uint)safe_strlen(s); } #define MAX_USER_HOST_SIZE 512 static inline uint make_user_name(THD *thd, char *buf) { const Security_context *sctx= thd->security_ctx; char *end= strxnmov(buf, MAX_USER_HOST_SIZE, sctx->priv_user[0] ? sctx->priv_user : "", "[", sctx->user ? sctx->user : "", "] @ ", sctx->host ? sctx->host : "", " [", sctx->ip ? sctx->ip : "", "]", NullS); return (uint)(end-buf); } /** Call audit plugins of GENERAL audit class, MYSQL_AUDIT_GENERAL_LOG subtype. @param[in] thd @param[in] time time that event occurred @param[in] user User name @param[in] userlen User name length @param[in] cmd Command name @param[in] cmdlen Command name length @param[in] query Query string @param[in] querylen Query string length */ static inline void mysql_audit_general_log(THD *thd, time_t time, const char *user, uint userlen, const char *cmd, uint cmdlen, const char *query, uint querylen) { if (mysql_audit_general_enabled()) { mysql_event_general event; event.event_subclass= MYSQL_AUDIT_GENERAL_LOG; event.general_error_code= 0; event.general_time= time; event.general_user= user; event.general_user_length= userlen; event.general_command= cmd; event.general_command_length= cmdlen; event.general_query= query; event.general_query_length= querylen; event.general_rows= 0; if (thd) { event.general_thread_id= (unsigned long)thd->thread_id; event.general_charset= thd->variables.character_set_client; event.database= thd->db; event.query_id= thd->query_id; } else { event.general_thread_id= 0; event.general_charset= global_system_variables.character_set_client; event.database= null_clex_str; event.query_id= 0; } mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, &event); } } /** Call audit plugins of GENERAL audit class. event_subtype should be set to one of: MYSQL_AUDIT_GENERAL_ERROR MYSQL_AUDIT_GENERAL_RESULT MYSQL_AUDIT_GENERAL_STATUS @param[in] thd @param[in] event_subtype Type of general audit event. @param[in] error_code Error code @param[in] msg Message */ static inline void mysql_audit_general(THD *thd, uint event_subtype, int error_code, const char *msg) { DBUG_ENTER("mysql_audit_general"); if (mysql_audit_general_enabled()) { char user_buff[MAX_USER_HOST_SIZE+1]; mysql_event_general event; event.event_subclass= event_subtype; event.general_error_code= error_code; event.general_time= my_time(0); event.general_command= msg; event.general_command_length= safe_strlen_uint(msg); if (thd) { event.general_user= user_buff; event.general_user_length= make_user_name(thd, user_buff); event.general_thread_id= (unsigned long)thd->thread_id; event.general_query= thd->query_string.str(); event.general_query_length= (unsigned) thd->query_string.length(); event.general_charset= thd->query_string.charset(); event.general_rows= thd->get_stmt_da()->current_row_for_warning(); event.database= thd->db; event.query_id= thd->query_id; DBUG_PRINT("info", ("mysql_audit_general: query_id=%lld, query=%.*s, subtype=%d, error_code=%d, msg=%s", thd->query_id, thd->query_length(), thd->query(), event_subtype, error_code, msg)); } else { event.general_user= NULL; event.general_user_length= 0; event.general_thread_id= 0; event.general_query= NULL; event.general_query_length= 0; event.general_charset= &my_charset_bin; event.general_rows= 0; event.database= null_clex_str; event.query_id= 0; } mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, &event); } DBUG_VOID_RETURN; } static inline void mysql_audit_notify_connection_connect(THD *thd) { if (mysql_audit_connection_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_connection event; event.event_subclass= MYSQL_AUDIT_CONNECTION_CONNECT; event.status= thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.user_length= safe_strlen_uint(sctx->user); event.priv_user= sctx->priv_user; event.priv_user_length= strlen_uint(sctx->priv_user); event.external_user= sctx->external_user; event.external_user_length= safe_strlen_uint(sctx->external_user); event.proxy_user= sctx->proxy_user; event.proxy_user_length= strlen_uint(sctx->proxy_user); event.host= sctx->host; event.host_length= safe_strlen_uint(sctx->host); event.ip= sctx->ip; event.ip_length= safe_strlen_uint(sctx->ip); event.database= thd->db; mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } static inline void mysql_audit_notify_connection_disconnect(THD *thd, int errcode) { if (mysql_audit_connection_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_connection event; event.event_subclass= MYSQL_AUDIT_CONNECTION_DISCONNECT; event.status= errcode; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.user_length= safe_strlen_uint(sctx->user); event.priv_user= sctx->priv_user; event.priv_user_length= strlen_uint(sctx->priv_user); event.external_user= sctx->external_user; event.external_user_length= safe_strlen_uint(sctx->external_user); event.proxy_user= sctx->proxy_user; event.proxy_user_length= strlen_uint(sctx->proxy_user); event.host= sctx->host; event.host_length= safe_strlen_uint(sctx->host); event.ip= sctx->ip; event.ip_length= safe_strlen_uint(sctx->ip) ; event.database= thd->db; mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } static inline void mysql_audit_notify_connection_change_user(THD *thd, const Security_context *old_ctx) { if (mysql_audit_connection_enabled()) { mysql_event_connection event; event.event_subclass= MYSQL_AUDIT_CONNECTION_CHANGE_USER; event.status= thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0; event.thread_id= (unsigned long)thd->thread_id; event.user= old_ctx->user; event.user_length= safe_strlen_uint(old_ctx->user); event.priv_user= old_ctx->priv_user; event.priv_user_length= strlen_uint(old_ctx->priv_user); event.external_user= old_ctx->external_user; event.external_user_length= safe_strlen_uint(old_ctx->external_user); event.proxy_user= old_ctx->proxy_user; event.proxy_user_length= strlen_uint(old_ctx->proxy_user); event.host= old_ctx->host; event.host_length= safe_strlen_uint(old_ctx->host); event.ip= old_ctx->ip; event.ip_length= safe_strlen_uint(old_ctx->ip); event.database= thd->db; mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } static inline void mysql_audit_external_lock_ex(THD *thd, my_thread_id thread_id, const char *user, const char *host, const char *ip, query_id_t query_id, TABLE_SHARE *share, int lock) { if (lock != F_UNLCK && mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_table event; event.event_subclass= MYSQL_AUDIT_TABLE_LOCK; event.read_only= lock == F_RDLCK; event.thread_id= (unsigned long)thread_id; event.user= user; event.priv_user= sctx->priv_user; event.priv_host= sctx->priv_host; event.external_user= sctx->external_user; event.proxy_user= sctx->proxy_user; event.host= host; event.ip= ip; event.database= share->db; event.table= share->table_name; event.new_database= null_clex_str; event.new_table= null_clex_str; event.query_id= query_id; mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } static inline void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock) { mysql_audit_external_lock_ex(thd, thd->thread_id, thd->security_ctx->user, thd->security_ctx->host, thd->security_ctx->ip, thd->query_id, share, lock); } static inline void mysql_audit_create_table(TABLE *table) { if (mysql_audit_table_enabled()) { THD *thd= table->in_use; const TABLE_SHARE *share= table->s; const Security_context *sctx= thd->security_ctx; mysql_event_table event; event.event_subclass= MYSQL_AUDIT_TABLE_CREATE; event.read_only= 0; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.priv_user= sctx->priv_user; event.priv_host= sctx->priv_host; event.external_user= sctx->external_user; event.proxy_user= sctx->proxy_user; event.host= sctx->host; event.ip= sctx->ip; event.database= share->db; event.table= share->table_name; event.new_database= null_clex_str; event.new_table= null_clex_str; event.query_id= thd->query_id; mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } static inline void mysql_audit_drop_table(THD *thd, TABLE_LIST *table) { if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_table event; event.event_subclass= MYSQL_AUDIT_TABLE_DROP; event.read_only= 0; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.priv_user= sctx->priv_user; event.priv_host= sctx->priv_host; event.external_user= sctx->external_user; event.proxy_user= sctx->proxy_user; event.host= sctx->host; event.ip= sctx->ip; event.database= table->db; event.table= table->table_name; event.new_database= null_clex_str; event.new_table= null_clex_str; event.query_id= thd->query_id; mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } static inline void mysql_audit_rename_table(THD *thd, const LEX_CSTRING *old_db, const LEX_CSTRING *old_tb, const LEX_CSTRING *new_db, const LEX_CSTRING *new_tb) { if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_table event; event.event_subclass= MYSQL_AUDIT_TABLE_RENAME; event.read_only= 0; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.priv_user= sctx->priv_user; event.priv_host= sctx->priv_host; event.external_user= sctx->external_user; event.proxy_user= sctx->proxy_user; event.host= sctx->host; event.ip= sctx->ip; event.database= *old_db; event.table= *old_tb; event.new_database= *new_db; event.new_table= *new_tb; event.query_id= thd->query_id; mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } static inline void mysql_audit_alter_table(THD *thd, TABLE_LIST *table) { if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; mysql_event_table event; event.event_subclass= MYSQL_AUDIT_TABLE_ALTER; event.read_only= 0; event.thread_id= (unsigned long)thd->thread_id; event.user= sctx->user; event.priv_user= sctx->priv_user; event.priv_host= sctx->priv_host; event.external_user= sctx->external_user; event.proxy_user= sctx->proxy_user; event.host= sctx->host; event.ip= sctx->ip; event.database= table->db; event.table= table->table_name; event.new_database= null_clex_str; event.new_table= null_clex_str; event.query_id= thd->query_id; mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } #endif /* SQL_AUDIT_INCLUDED */ cset_narrowing.h 0000644 00000007600 15156036155 0007753 0 ustar 00 /* Copyright (c) 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef CSET_NARROWING_H_INCLUDED #define CSET_NARROWING_H_INCLUDED /* A singleton class to provide "utf8mb3_from_mb4.charset()". This is a variant of utf8mb3_general_ci that one can use when they have data in MB4 and want to make index lookup keys in MB3. */ extern class Charset_utf8narrow { struct my_charset_handler_st cset_handler; struct charset_info_st cset; public: Charset_utf8narrow() : cset_handler(*my_charset_utf8mb3_general_ci.cset), cset(my_charset_utf8mb3_general_ci) /* Copy the CHARSET_INFO structure */ { /* Insert our function wc_mb */ cset_handler.wc_mb= my_wc_mb_utf8mb4_bmp_only; cset.cset=&cset_handler; /* Charsets are compared by their name, so assign a different name */ LEX_CSTRING tmp= {STRING_WITH_LEN("utf8_mb4_to_mb3")}; cset.cs_name= tmp; } CHARSET_INFO *charset() { return &cset; } } utf8mb3_from_mb4; /* A class to temporary change a field that uses utf8mb3_general_ci to enable correct lookup key construction from string value in utf8mb4_general_ci Intended usage: // can do this in advance: bool do_narrowing= Utf8_narrow::should_do_narrowing(field, value_cset); ... // This sets the field to do narrowing if necessary: Utf8_narrow narrow(field, do_narrowing); // write to 'field' here // item->save_in_field(field) or something else // Stop doing narrowing narrow.stop(); */ class Utf8_narrow { Field *field; DTCollation save_collation; public: static bool should_do_narrowing(const THD *thd, CHARSET_INFO *field_cset, CHARSET_INFO *value_cset); static bool should_do_narrowing(const Field *field, CHARSET_INFO *value_cset) { CHARSET_INFO *field_cset= field->charset(); THD *thd= field->table->in_use; return should_do_narrowing(thd, field_cset, value_cset); } Utf8_narrow(Field *field_arg, bool is_applicable) { field= NULL; if (is_applicable) { DTCollation mb3_from_mb4= utf8mb3_from_mb4.charset(); field= field_arg; save_collation= field->dtcollation(); field->change_charset(mb3_from_mb4); } } void stop() { if (field) field->change_charset(save_collation); #ifndef NDEBUG field= NULL; #endif } ~Utf8_narrow() { DBUG_ASSERT(!field); } }; /* @brief Check if two fields can participate in a multiple equality using charset narrowing. @detail Normally, check_simple_equality() checks this by calling: left_field->eq_def(right_field) This function does the same but takes into account we might use charset narrowing: - collations are not the same but rather an utf8mb{3,4}_general_ci pair - for field lengths, should compare # characters, not #bytes. */ inline bool fields_equal_using_narrowing(const THD *thd, const Field *left, const Field *right) { return dynamic_cast<const Field_longstr*>(left) && dynamic_cast<const Field_longstr*>(right) && left->real_type() == right->real_type() && (Utf8_narrow::should_do_narrowing(left, right->charset()) || Utf8_narrow::should_do_narrowing(right, left->charset())) && left->char_length() == right->char_length(); }; #endif /* CSET_NARROWING_H_INCLUDED */ semisync.h 0000644 00000004357 15156036155 0006567 0 ustar 00 /* Copyright (C) 2007 Google Inc. Copyright (C) 2008 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SEMISYNC_H #define SEMISYNC_H #include "mysqld.h" #include "log_event.h" #include "replication.h" /** This class is used to trace function calls and other process information */ class Trace { public: static const unsigned long k_trace_function; static const unsigned long k_trace_general; static const unsigned long k_trace_detail; static const unsigned long k_trace_net_wait; unsigned long m_trace_level; /* the level for tracing */ Trace() :m_trace_level(0L) {} Trace(unsigned long trace_level) :m_trace_level(trace_level) {} }; /** Base class for semi-sync master and slave classes */ class Repl_semi_sync_base :public Trace { public: static const unsigned char k_sync_header[2]; /* three byte packet header */ /* Constants in network packet header. */ static const unsigned char k_packet_magic_num; static const unsigned char k_packet_flag_sync; }; /* The layout of a semisync slave reply packet: 1 byte for the magic num 8 bytes for the binlog positon n bytes for the binlog filename, terminated with a '\0' */ #define REPLY_MAGIC_NUM_LEN 1 #define REPLY_BINLOG_POS_LEN 8 #define REPLY_BINLOG_NAME_LEN (FN_REFLEN + 1) #define REPLY_MAGIC_NUM_OFFSET 0 #define REPLY_BINLOG_POS_OFFSET (REPLY_MAGIC_NUM_OFFSET + REPLY_MAGIC_NUM_LEN) #define REPLY_BINLOG_NAME_OFFSET (REPLY_BINLOG_POS_OFFSET + REPLY_BINLOG_POS_LEN) #define REPLY_MESSAGE_MAX_LENGTH \ (REPLY_MAGIC_NUM_LEN + REPLY_BINLOG_POS_LEN + REPLY_BINLOG_NAME_LEN) #endif /* SEMISYNC_H */ sql_handler.h 0000644 00000005536 15156036155 0007231 0 ustar 00 #ifndef SQL_HANDLER_INCLUDED #define SQL_HANDLER_INCLUDED /* Copyright (c) 2006, 2015, Oracle and/or its affiliates. Copyright (C) 2010, 2015, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_class.h" /* enum_ha_read_mode */ #include "my_base.h" /* ha_rkey_function, ha_rows */ #include "sql_list.h" /* List */ /* Open handlers are stored here */ class SQL_HANDLER { public: TABLE *table; List<Item> fields; /* Fields, set on open */ THD *thd; LEX_CSTRING handler_name; LEX_CSTRING db; LEX_CSTRING table_name; MEM_ROOT mem_root; MYSQL_LOCK *lock; MDL_request mdl_request; key_part_map keypart_map; int keyno; /* Used key */ uint key_len; enum enum_ha_read_modes mode; /* This is only used when deleting many handler objects */ SQL_HANDLER *next; Query_arena arena; char *base_data; SQL_HANDLER(THD *thd_arg) : thd(thd_arg), arena(&mem_root, Query_arena::STMT_INITIALIZED) { init(); clear_alloc_root(&mem_root); base_data= 0; } void init() { keyno= -1; table= 0; lock= 0; mdl_request.ticket= 0; } void reset(); ~SQL_HANDLER(); }; class THD; struct TABLE_LIST; bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes, const char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); void mysql_ha_flush(THD *thd); void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables); void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables); void mysql_ha_cleanup_no_free(THD *thd); void mysql_ha_cleanup(THD *thd); void mysql_ha_set_explicit_lock_duration(THD *thd); void mysql_ha_rm_temporary_tables(THD *thd); SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables, enum enum_ha_read_modes mode, const char *keyname, List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode, Item *cond); #endif my_libwrap.h 0000644 00000002237 15156036155 0007075 0 ustar 00 #ifndef MY_LIBWRAP_INCLUDED #define MY_LIBWRAP_INCLUDED /* Copyright (c) 2000, 2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef HAVE_LIBWRAP #include <tcpd.h> #include <syslog.h> #ifdef NEED_SYS_SYSLOG_H #include <sys/syslog.h> #endif /* NEED_SYS_SYSLOG_H */ extern void my_fromhost(struct request_info *req); extern int my_hosts_access(struct request_info *req); extern char *my_eval_client(struct request_info *req); #endif /* HAVE_LIBWRAP */ #endif /* MY_LIBWRAP_INCLUDED */ atomic/generic-msvc.h 0000644 00000007313 15156036155 0010566 0 ustar 00 #ifndef ATOMIC_MSC_INCLUDED #define ATOMIC_MSC_INCLUDED /* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <windows.h> static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) { int32 initial_cmp= *cmp; int32 initial_a= InterlockedCompareExchange((volatile LONG*)a, set, initial_cmp); int ret= (initial_a == initial_cmp); if (!ret) *cmp= initial_a; return ret; } static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) { int64 initial_cmp= *cmp; int64 initial_a= InterlockedCompareExchange64((volatile LONGLONG*)a, (LONGLONG)set, (LONGLONG)initial_cmp); int ret= (initial_a == initial_cmp); if (!ret) *cmp= initial_a; return ret; } static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set) { void *initial_cmp= *cmp; void *initial_a= InterlockedCompareExchangePointer(a, set, initial_cmp); int ret= (initial_a == initial_cmp); if (!ret) *cmp= initial_a; return ret; } static inline int32 my_atomic_add32(int32 volatile *a, int32 v) { return (int32)InterlockedExchangeAdd((volatile LONG*)a, v); } static inline int64 my_atomic_add64(int64 volatile *a, int64 v) { return (int64)InterlockedExchangeAdd64((volatile LONGLONG*)a, (LONGLONG)v); } /* According to MSDN: Simple reads and writes to properly-aligned 32-bit variables are atomic operations. ... Simple reads and writes to properly aligned 64-bit variables are atomic on 64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be atomic on 32-bit Windows. https://learn.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access */ static inline int32 my_atomic_load32(int32 volatile *a) { int32 value= *a; MemoryBarrier(); return value; } static inline int64 my_atomic_load64(int64 volatile *a) { #if defined(_M_X64) || defined(_M_ARM64) int64 value= *a; MemoryBarrier(); return value; #else return (int64) InterlockedCompareExchange64((volatile LONGLONG *) a, 0, 0); #endif } static inline void* my_atomic_loadptr(void * volatile *a) { void *value= *a; MemoryBarrier(); return value; } static inline int32 my_atomic_fas32(int32 volatile *a, int32 v) { return (int32)InterlockedExchange((volatile LONG*)a, v); } static inline int64 my_atomic_fas64(int64 volatile *a, int64 v) { return (int64)InterlockedExchange64((volatile LONGLONG*)a, v); } static inline void * my_atomic_fasptr(void * volatile *a, void * v) { return InterlockedExchangePointer(a, v); } static inline void my_atomic_store32(int32 volatile *a, int32 v) { MemoryBarrier(); *a= v; } static inline void my_atomic_store64(int64 volatile *a, int64 v) { #if defined(_M_X64) || defined(_M_ARM64) MemoryBarrier(); *a= v; #else (void) InterlockedExchange64((volatile LONGLONG *) a, v); #endif } static inline void my_atomic_storeptr(void * volatile *a, void *v) { MemoryBarrier(); *a= v; } #endif /* ATOMIC_MSC_INCLUDED */ atomic/solaris.h 0000644 00000006125 15156036155 0007660 0 ustar 00 #ifndef ATOMIC_SOLARIS_INCLUDED #define ATOMIC_SOLARIS_INCLUDED /* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <atomic.h> #if defined(__GNUC__) #define atomic_typeof(T,V) __typeof__(V) #else #define atomic_typeof(T,V) T #endif static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) { int ret; atomic_typeof(uint32_t, *cmp) sav; sav= atomic_cas_32((volatile uint32_t *)a, (uint32_t)*cmp, (uint32_t)set); ret= (sav == *cmp); if (!ret) *cmp= sav; return ret; } static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) { int ret; atomic_typeof(uint64_t, *cmp) sav; sav= atomic_cas_64((volatile uint64_t *)a, (uint64_t)*cmp, (uint64_t)set); ret= (sav == *cmp); if (!ret) *cmp= sav; return ret; } static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set) { int ret; atomic_typeof(void *, *cmp) sav; sav= atomic_cas_ptr((volatile void **)a, (void *)*cmp, (void *)set); ret= (sav == *cmp); if (!ret) *cmp= sav; return ret; } static inline int32 my_atomic_add32(int32 volatile *a, int32 v) { int32 nv= atomic_add_32_nv((volatile uint32_t *)a, v); return nv - v; } static inline int64 my_atomic_add64(int64 volatile *a, int64 v) { int64 nv= atomic_add_64_nv((volatile uint64_t *)a, v); return nv - v; } static inline int32 my_atomic_fas32(int32 volatile *a, int32 v) { return atomic_swap_32((volatile uint32_t *)a, (uint32_t)v); } static inline int64 my_atomic_fas64(int64 volatile *a, int64 v) { return atomic_swap_64((volatile uint64_t *)a, (uint64_t)v); } static inline void * my_atomic_fasptr(void * volatile *a, void * v) { return atomic_swap_ptr(a, v); } static inline int32 my_atomic_load32(int32 volatile *a) { return atomic_or_32_nv((volatile uint32_t *)a, 0); } static inline int64 my_atomic_load64(int64 volatile *a) { return atomic_or_64_nv((volatile uint64_t *)a, 0); } static inline void* my_atomic_loadptr(void * volatile *a) { return atomic_add_ptr_nv(a, 0); } static inline void my_atomic_store32(int32 volatile *a, int32 v) { (void) atomic_swap_32((volatile uint32_t *)a, (uint32_t)v); } static inline void my_atomic_store64(int64 volatile *a, int64 v) { (void) atomic_swap_64((volatile uint64_t *)a, (uint64_t)v); } static inline void my_atomic_storeptr(void * volatile *a, void *v) { (void) atomic_swap_ptr((volatile void **)a, (void *)v); } #endif /* ATOMIC_SOLARIS_INCLUDED */ atomic/gcc_builtins.h 0000644 00000007341 15156036155 0010652 0 ustar 00 #ifndef ATOMIC_GCC_BUILTINS_INCLUDED #define ATOMIC_GCC_BUILTINS_INCLUDED /* Copyright (c) 2017 MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #define MY_MEMORY_ORDER_RELAXED __ATOMIC_RELAXED #define MY_MEMORY_ORDER_CONSUME __ATOMIC_CONSUME #define MY_MEMORY_ORDER_ACQUIRE __ATOMIC_ACQUIRE #define MY_MEMORY_ORDER_RELEASE __ATOMIC_RELEASE #define MY_MEMORY_ORDER_ACQ_REL __ATOMIC_ACQ_REL #define MY_MEMORY_ORDER_SEQ_CST __ATOMIC_SEQ_CST #define my_atomic_store32_explicit(P, D, O) __atomic_store_n((P), (D), (O)) #define my_atomic_store64_explicit(P, D, O) __atomic_store_n((P), (D), (O)) #define my_atomic_storeptr_explicit(P, D, O) __atomic_store_n((P), (D), (O)) #define my_atomic_load32_explicit(P, O) __atomic_load_n((P), (O)) #define my_atomic_load64_explicit(P, O) __atomic_load_n((P), (O)) #define my_atomic_loadptr_explicit(P, O) __atomic_load_n((P), (O)) #define my_atomic_fas32_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) #define my_atomic_fas64_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) #define my_atomic_fasptr_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) #define my_atomic_add32_explicit(P, A, O) __atomic_fetch_add((P), (A), (O)) #define my_atomic_add64_explicit(P, A, O) __atomic_fetch_add((P), (A), (O)) #define my_atomic_cas32_weak_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) #define my_atomic_cas64_weak_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) #define my_atomic_casptr_weak_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) #define my_atomic_cas32_strong_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) #define my_atomic_cas64_strong_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) #define my_atomic_casptr_strong_explicit(P, E, D, S, F) \ __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) #define my_atomic_store32(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_store64(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_storeptr(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_load32(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) #define my_atomic_load64(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) #define my_atomic_loadptr(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) #define my_atomic_fas32(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_fas64(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_fasptr(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) #define my_atomic_add32(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST) #define my_atomic_add64(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST) #define my_atomic_cas32(P, E, D) \ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) #define my_atomic_cas64(P, E, D) \ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) #define my_atomic_casptr(P, E, D) \ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) #endif /* ATOMIC_GCC_BUILTINS_INCLUDED */ span.h 0000644 00000007533 15156036155 0005675 0 ustar 00 /***************************************************************************** Copyright (c) 2019, 2020 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *****************************************************************************/ #pragma once #include <cstddef> #include <iterator> namespace st_ { namespace detail { template <class T> struct remove_cv { typedef T type; }; template <class T> struct remove_cv<const T> { typedef T type; }; template <class T> struct remove_cv<volatile T> { typedef T type; }; template <class T> struct remove_cv<const volatile T> { typedef T type; }; } // namespace detail template <class ElementType> class span { public: typedef ElementType element_type; typedef typename detail::remove_cv<ElementType>::type value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef element_type *pointer; typedef const element_type *const_pointer; typedef element_type &reference; typedef const element_type &const_reference; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; span() : data_(NULL), size_(0) {} span(pointer ptr, size_type count) : data_(ptr), size_(count) {} span(pointer first, pointer last) : data_(first), size_(last - first) {} template <size_t N> span(element_type (&arr)[N]) : data_(arr), size_(N) {} template <class Container> span(Container &cont) : data_(cont.data()), size_(cont.size()) { } template <class Container> span(const Container &cont) : data_(cont.data()), size_(cont.size()) { } span(const span &other) : data_(other.data_), size_(other.size_) {} ~span() = default; span &operator=(const span &other) { data_= other.data(); size_= other.size(); return *this; } template <size_t Count> span<element_type> first() const { assert(!empty()); return span(data(), 1); } template <size_t Count> span<element_type> last() const { assert(!empty()); return span(data() + size() - 1, 1); } span<element_type> first(size_type count) const { assert(!empty()); return span(data(), 1); } span<element_type> last(size_type count) const { assert(!empty()); return span(data() + size() - 1, 1); } span<element_type> subspan(size_type offset, size_type count) const { assert(!empty()); assert(size() >= offset + count); return span(data() + offset, count); } size_type size() const { return size_; } size_type size_bytes() const { return size() * sizeof(ElementType); } bool empty() const __attribute__((warn_unused_result)) { return size() == 0; } reference operator[](size_type idx) const { assert(size() > idx); return data()[idx]; } reference front() const { assert(!empty()); return data()[0]; } reference back() const { assert(!empty()); return data()[size() - 1]; } pointer data() const { return data_; } iterator begin() const { return data_; } iterator end() const { return data_ + size_; } reverse_iterator rbegin() const { return std::reverse_iterator<iterator>(end()); } reverse_iterator rend() const { return std::reverse_iterator<iterator>(begin()); } private: pointer data_; size_type size_; }; } // namespace st_ rpl_filter.h 0000644 00000011246 15156036156 0007073 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_FILTER_H #define RPL_FILTER_H #include "mysql.h" #include "mysqld.h" #include "sql_list.h" /* I_List */ #include "hash.h" /* HASH */ class String; struct TABLE_LIST; typedef struct st_dynamic_array DYNAMIC_ARRAY; typedef struct st_table_rule_ent { char* db; char* tbl_name; uint key_len; } TABLE_RULE_ENT; /* Rpl_filter Inclusion and exclusion rules of tables and databases. Also handles rewrites of db. Used for replication and binlogging. */ class Rpl_filter { public: Rpl_filter(); ~Rpl_filter(); Rpl_filter(Rpl_filter const&); Rpl_filter& operator=(Rpl_filter const&); /* Checks - returns true if ok to replicate/log */ #ifndef MYSQL_CLIENT bool tables_ok(const char* db, TABLE_LIST *tables); #endif bool db_ok(const char* db); bool db_ok_with_wild_table(const char *db); bool is_on(); bool is_db_empty(); /* Setters - add filtering rules */ int add_do_table(const char* table_spec); int add_ignore_table(const char* table_spec); int set_do_table(const char* table_spec); int set_ignore_table(const char* table_spec); int add_wild_do_table(const char* table_spec); int add_wild_ignore_table(const char* table_spec); int set_wild_do_table(const char* table_spec); int set_wild_ignore_table(const char* table_spec); int add_rewrite_db(const char* table_spec); int add_do_db(const char* db_spec); int add_ignore_db(const char* db_spec); int set_rewrite_db(const char* db_spec); int set_do_db(const char* db_spec); int set_ignore_db(const char* db_spec); void set_parallel_mode(enum_slave_parallel_mode mode) { parallel_mode= mode; } /* Return given parallel mode or if one is not given, the default mode */ enum_slave_parallel_mode get_parallel_mode() { return parallel_mode; } /* Getters - to get information about current rules */ void get_do_table(String* str); void get_ignore_table(String* str); void get_wild_do_table(String* str); void get_wild_ignore_table(String* str); bool rewrite_db_is_empty(); I_List<i_string_pair>* get_rewrite_db(); void get_rewrite_db(String *str); const char* get_rewrite_db(const char* db, size_t *new_len); I_List<i_string>* get_do_db(); I_List<i_string>* get_ignore_db(); void get_do_db(String* str); void get_ignore_db(String* str); private: void init_table_rule_hash(HASH* h, bool* h_inited); void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited); int add_table_rule(HASH* h, const char* table_spec); int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec); typedef int (Rpl_filter::*Add_filter)(char const*); int parse_filter_rule(const char* spec, Add_filter func); void free_string_array(DYNAMIC_ARRAY *a); void free_string_list(I_List<i_string> *l); void free_string_pair_list(I_List<i_string_pair> *l); void table_rule_ent_hash_to_str(String* s, HASH* h, bool inited); void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a, bool inited); void db_rewrite_rule_ent_list_to_str(String*, I_List<i_string_pair>*); void db_rule_ent_list_to_str(String* s, I_List<i_string>* l); TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len); int add_string_list(I_List<i_string> *list, const char* spec); int add_string_pair_list(const char* my_spec); /* Those 4 structures below are uninitialized memory unless the corresponding *_inited variables are "true". */ HASH do_table; HASH ignore_table; DYNAMIC_ARRAY wild_do_table; DYNAMIC_ARRAY wild_ignore_table; enum_slave_parallel_mode parallel_mode; bool table_rules_on; bool do_table_inited; bool ignore_table_inited; bool wild_do_table_inited; bool wild_ignore_table_inited; I_List<i_string> do_db; I_List<i_string> ignore_db; I_List<i_string_pair> rewrite_db; }; extern Rpl_filter *global_rpl_filter; extern Rpl_filter *binlog_filter; #endif // RPL_FILTER_H wsrep_storage_service.h 0000644 00000003421 15156036156 0011331 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_STORAGE_SERVICE_H #define WSREP_STORAGE_SERVICE_H #include "wsrep/storage_service.hpp" #include "wsrep/client_state.hpp" class THD; class Wsrep_server_service; class Wsrep_storage_service : public wsrep::storage_service, public wsrep::high_priority_context { public: Wsrep_storage_service(THD*); ~Wsrep_storage_service(); int start_transaction(const wsrep::ws_handle&) override; void adopt_transaction(const wsrep::transaction&) override; int append_fragment(const wsrep::id&, wsrep::transaction_id, int flags, const wsrep::const_buffer&, const wsrep::xid&) override; int update_fragment_meta(const wsrep::ws_meta&) override; int remove_fragments() override; int commit(const wsrep::ws_handle&, const wsrep::ws_meta&) override; int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&) override; void store_globals() override; void reset_globals() override; private: friend class Wsrep_server_service; THD* m_thd; }; #endif /* WSREP_STORAGE_SERVICE_H */ pfs_memory_provider.h 0000644 00000003132 15156036156 0011016 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_MEMORY_PROVIDER_H #define PFS_MEMORY_PROVIDER_H /** @file include/pfs_memory_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_MEMORY_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_MEMORY_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_memory_v1 (const char *category, struct PSI_memory_info_v1 *info, int count); PSI_memory_key pfs_memory_alloc_v1 (PSI_memory_key key, size_t size, PSI_thread **owner); PSI_memory_key pfs_memory_realloc_v1 (PSI_memory_key key, size_t old_size, size_t new_size, PSI_thread **owner); void pfs_memory_free_v1 (PSI_memory_key key, size_t size, PSI_thread *owner); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_MEMORY_INTERFACE */ #endif wsrep_utils.h 0000644 00000023117 15156036156 0007311 0 ustar 00 /* Copyright (C) 2013-2015 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_UTILS_H #define WSREP_UTILS_H #include "wsrep_priv.h" #include "wsrep_mysqld.h" unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6); size_t wsrep_guess_ip (char* buf, size_t buf_len); namespace wsp { class node_status { public: node_status() : status(wsrep::server_state::s_disconnected) {} void set(enum wsrep::server_state::state new_status, const wsrep::view* view= 0) { if (status != new_status || 0 != view) { wsrep_notify_status(new_status, view); status= new_status; } } enum wsrep::server_state::state get() const { return status; } private: enum wsrep::server_state::state status; }; } /* namespace wsp */ extern wsp::node_status local_status; /* returns the length of the host part of the address string */ size_t wsrep_host_len(const char* addr, size_t addr_len); namespace wsp { class Address { public: Address() : m_address_len(0), m_family(UNSPEC), m_port(0), m_valid(false) { memset(m_address, 0, sizeof(m_address)); } Address(const char *addr_in) : m_address_len(0), m_family(UNSPEC), m_port(0), m_valid(false) { memset(m_address, 0, sizeof(m_address)); parse_addr(addr_in); } bool is_valid() { return m_valid; } bool is_ipv6() { return (m_family == INET6); } const char* get_address() { return m_address; } size_t get_address_len() { return m_address_len; } int get_port() { return m_port; } void set_port(int port) { m_port= port; } private: enum family { UNSPEC= 0, INET, /* IPv4 */ INET6, /* IPv6 */ }; char m_address[256]; size_t m_address_len; family m_family; int m_port; bool m_valid; void parse_addr(const char *addr_in) { const char *start; const char *end; const char *port; const char* open_bracket= strchr(const_cast<char *>(addr_in), '['); const char* close_bracket= strchr(const_cast<char *>(addr_in), ']'); const char* colon= strchr(const_cast<char *>(addr_in), ':'); const char* dot= strchr(const_cast<char *>(addr_in), '.'); int cc= colon_count(addr_in); if (open_bracket != NULL || dot == NULL || (colon != NULL && (dot == NULL || colon < dot))) { // This could be an IPv6 address or a hostname if (open_bracket != NULL) { /* Sanity check: Address with '[' must include ']' */ if (close_bracket == NULL && open_bracket < close_bracket) /* Error: malformed address */ { m_valid= false; return; } start= open_bracket + 1; end= close_bracket; /* Check for port */ port= strchr(close_bracket, ':'); if ((port != NULL) && parse_port(port + 1)) { return; /* Error: invalid port */ } m_family= INET6; } else { switch (cc) { case 0: /* Hostname with no port */ start= addr_in; end= addr_in + strlen(addr_in); break; case 1: /* Hostname with port (host:port) */ start= addr_in; end= colon; if (parse_port(colon + 1)) return; /* Error: invalid port */ break; default: /* IPv6 address */ start= addr_in; end= addr_in + strlen(addr_in); m_family= INET6; break; } } } else { /* IPv4 address or hostname */ start= addr_in; if (colon != NULL) { /* Port */ end= colon; if (parse_port(colon + 1)) return; /* Error: invalid port */ } else { end= addr_in + strlen(addr_in); } } size_t len= end - start; /* Safety */ if (len >= sizeof(m_address)) { // The supplied address is too large to fit into the internal buffer. m_valid= false; return; } memcpy(m_address, start, len); m_address[len]= '\0'; m_address_len= ++ len; m_valid= true; return; } int colon_count(const char *addr) { int count= 0, i= 0; while(addr[i] != '\0') { if (addr[i] == ':') ++count; ++ i; } return count; } bool parse_port(const char *port) { errno= 0; /* Reset the errno */ m_port= strtol(port, NULL, 10); if (errno == EINVAL || errno == ERANGE) { m_port= 0; /* Error: invalid port */ m_valid= false; return true; } return false; } }; class Config_state { public: Config_state() : view_(), status_(wsrep::server_state::s_disconnected) {} void set(const wsrep::view& view) { wsrep_notify_status(status_, &view); lock(); view_= view; unlock(); } void set(enum wsrep::server_state::state status) { if (status == wsrep::server_state::s_donor || status == wsrep::server_state::s_synced) wsrep_notify_status(status, &view_); else wsrep_notify_status(status); lock(); status_= status; unlock(); } const wsrep::view& get_view_info() const { return view_; } enum wsrep::server_state::state get_status() const { return status_; } int lock() { return mysql_mutex_lock(&LOCK_wsrep_config_state); } int unlock() { return mysql_mutex_unlock(&LOCK_wsrep_config_state); } private: wsrep::view view_; enum wsrep::server_state::state status_; }; } /* namespace wsp */ extern wsp::Config_state *wsrep_config_state; namespace wsp { /* a class to manage env vars array */ class env { private: size_t len_; char** env_; int errno_; bool ctor_common(char** e); void dtor(); env& operator =(env); public: explicit env(char** env); explicit env(const env&); ~env(); int append(const char* var); /* add a new env. var */ int error() const { return errno_; } char** operator()() { return env_; } }; /* A small class to run external programs. */ class process { private: const char* const str_; FILE* io_; int err_; pid_t pid_; public: /*! @arg type is a pointer to a null-terminated string which must contain either the letter 'r' for reading or the letter 'w' for writing. @arg env optional null-terminated vector of environment variables */ process (const char* cmd, const char* type, char** env); ~process (); FILE* pipe () { return io_; } int error() { return err_; } int wait (); const char* cmd() { return str_; } }; class thd { class thd_init { public: thd_init() { my_thread_init(); } ~thd_init() { my_thread_end(); } } init; thd (const thd&); thd& operator= (const thd&); public: thd(my_bool wsrep_on, bool system_thread=false); ~thd(); THD* const ptr; }; class string { public: string() : string_(0) {} explicit string(size_t s) : string_(static_cast<char*>(malloc(s))) {} char* operator()() { return string_; } void set(char* str) { if (string_) free (string_); string_= str; } ~string() { set (0); } private: char* string_; }; /* scope level lock */ class auto_lock { public: auto_lock(mysql_mutex_t* m) : m_(m) { mysql_mutex_lock(m_); } ~auto_lock() { mysql_mutex_unlock(m_); } private: mysql_mutex_t& operator =(mysql_mutex_t&); mysql_mutex_t* const m_; }; #ifdef REMOVED class lock { pthread_mutex_t* const mtx_; public: lock (pthread_mutex_t* mtx) : mtx_(mtx) { int err= pthread_mutex_lock (mtx_); if (err) { WSREP_ERROR("Mutex lock failed: %s", strerror(err)); abort(); } } virtual ~lock () { int err= pthread_mutex_unlock (mtx_); if (err) { WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); abort(); } } inline void wait (pthread_cond_t* cond) { pthread_cond_wait (cond, mtx_); } private: lock (const lock&); lock& operator=(const lock&); }; class monitor { int mutable refcnt; pthread_mutex_t mutable mtx; pthread_cond_t mutable cond; public: monitor() : refcnt(0) { pthread_mutex_init (&mtx, NULL); pthread_cond_init (&cond, NULL); } ~monitor() { pthread_mutex_destroy (&mtx); pthread_cond_destroy (&cond); } void enter() const { lock l(&mtx); while (refcnt) { l.wait(&cond); } refcnt++; } void leave() const { lock l(&mtx); refcnt--; if (refcnt == 0) { pthread_cond_signal (&cond); } } private: monitor (const monitor&); monitor& operator= (const monitor&); }; class critical { const monitor& mon; public: critical(const monitor& m) : mon(m) { mon.enter(); } ~critical() { mon.leave(); } private: critical (const critical&); critical& operator= (const critical&); }; #endif } // namespace wsrep #endif /* WSREP_UTILS_H */ deprecation.h 0000644 00000005362 15156036156 0007230 0 ustar 00 /* In the current release model, versions are released like the following (the table shows the year/quarter of the planned GA release): Q1 Q2 Q3 Q4 2022 10.7 10.8 10.9 10.10 2023 10.11-LTS 11.0 11.1 11.2 2024 11.3 11.4 11.5 11.6 2025 11.7-LTS 12.0 12.1 12.2 2026 12.3 12.4 12.5 12.6 2027 12.7-LTS 13.0 13.1 13.2 2028 13.3 13.4 13.5 13.6 2029 13.7-LTS 14.0 14.1 14.2 ... A deprecated feature can be removed only when all releases when it's not deprecated have reached EOL. For example, if something was deprecated in 11.3, then 10.11 (where it wasn't deprecated) will reach EOL in Q1 2028 (standard 5 years LTS life time). Meaning, the feature can be removed in 13.4. When the release model changes, the table above and templates below have to be updated. */ template<uint V> static inline void check_deprecated_version(void) { static_assert ( V <= 1004 ? MYSQL_VERSION_ID < 110500 : /* until 10.4 EOL */ V <= 1005 ? MYSQL_VERSION_ID < 120100 : /* until 10.5 EOL */ V <= 1010 ? MYSQL_VERSION_ID < 120500 : /* until 10.6 EOL */ V <= 1106 ? MYSQL_VERSION_ID < 130400 : /* until 10.11 EOL */ V == 999999, /* only for sys_var::do_deprecated_warning() */ "check_deprecated_version failed" ); } /* V is the 2-component 4-digit version where something was deprecated. For example, if deprecated in 11.2: warn_deprecated<1102>(thd, "something") */ template<uint V> static inline void warn_deprecated(THD *thd, const char *what, const char *to= NULL) { check_deprecated_version<V>(); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_DEPRECATED_SYNTAX, ER_THD(thd, to && *to ? ER_WARN_DEPRECATED_SYNTAX : ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT), what, to); } template<uint V> static inline void warn_deprecated(const char *what, const char *to= NULL) { check_deprecated_version<V>(); sql_print_warning(to && *to ? "'%s' is deprecated and will be removed in a future release. Please use %s instead" : "'%s' is deprecated and will be removed in a future release", what, to); } /* Prevent direct usage of the error that bypasses the template */ #undef ER_WARN_DEPRECATED_SYNTAX #undef ER_WARN_DEPRECATED_SYNTAX_WITH_VER #undef ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT mariadb.h 0000644 00000002375 15156036156 0006333 0 ustar 00 /* Copyright (c) 2010, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Include file that should always be included first in all file in the sql directory. Used to ensure that some files, like my_global.h and my_config.h are always included first. It can also be used to speed up compilation by using precompiled headers. This file should include a minum set of header files used by all files and header files that are very seldom changed. It can also include some defines that all files should be aware of. */ #ifndef MARIADB_INCLUDED #define MARIADB_INCLUDED #include <my_global.h> #endif /* MARIADB_INCLUDED */ parse_file.h 0000644 00000010443 15156036156 0007040 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _PARSE_FILE_H_ #define _PARSE_FILE_H_ #include "sql_string.h" // LEX_STRING #include "sql_alloc.h" // Sql_alloc class THD; typedef struct st_mem_root MEM_ROOT; #define PARSE_FILE_TIMESTAMPLENGTH 19 enum file_opt_type { FILE_OPTIONS_STRING, /**< String (LEX_STRING) */ FILE_OPTIONS_ESTRING, /**< Escaped string (LEX_STRING) */ FILE_OPTIONS_ULONGLONG, /**< ulonglong parameter (ulonglong) */ FILE_OPTIONS_VIEW_ALGO, /**< Similar to longlong, but needs conversion */ FILE_OPTIONS_TIMESTAMP, /**< timestamp (LEX_STRING have to be allocated with length 20 (19+1) */ FILE_OPTIONS_STRLIST, /**< list of escaped strings (List<LEX_STRING>) */ FILE_OPTIONS_ULLLIST /**< list of ulonglong values (List<ulonglong>) */ }; struct File_option { LEX_CSTRING name; /**< Name of the option */ my_ptrdiff_t offset; /**< offset to base address of value */ file_opt_type type; /**< Option type */ }; /** This hook used to catch no longer supported keys and process them for backward compatibility. */ class Unknown_key_hook { public: Unknown_key_hook() = default; /* Remove gcc warning */ virtual ~Unknown_key_hook() = default; /* Remove gcc warning */ virtual bool process_unknown_string(const char *&unknown_key, uchar* base, MEM_ROOT *mem_root, const char *end)= 0; }; /** Dummy hook for parsers which do not need hook for unknown keys. */ class File_parser_dummy_hook: public Unknown_key_hook { public: File_parser_dummy_hook() = default; /* Remove gcc warning */ bool process_unknown_string(const char *&unknown_key, uchar* base, MEM_ROOT *mem_root, const char *end) override; }; extern File_parser_dummy_hook file_parser_dummy_hook; bool get_file_options_ulllist(const char *&ptr, const char *end, const char *line, uchar* base, File_option *parameter, MEM_ROOT *mem_root); const char * parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root, LEX_CSTRING *str); class File_parser; File_parser *sql_parse_prepare(const LEX_CSTRING *file_name, MEM_ROOT *mem_root, bool bad_format_errors); my_bool sql_create_definition_file(const LEX_CSTRING *dir, const LEX_CSTRING *file_name, const LEX_CSTRING *type, uchar* base, File_option *parameters); my_bool rename_in_schema_file(THD *thd, const char *schema, const char *old_name, const char *new_db, const char *new_name); int sql_backup_definition_file(const LEX_CSTRING *org_name, LEX_CSTRING *new_name); int sql_restore_definition_file(const LEX_CSTRING *name); class File_parser: public Sql_alloc { char *start, *end; LEX_CSTRING file_type; bool content_ok; public: File_parser() :start(0), end(0), content_ok(0) { file_type.str= 0; file_type.length= 0; } bool ok() { return content_ok; } const LEX_CSTRING *type() const { return &file_type; } my_bool parse(uchar* base, MEM_ROOT *mem_root, struct File_option *parameters, uint required, Unknown_key_hook *hook) const; friend File_parser *sql_parse_prepare(const LEX_CSTRING *file_name, MEM_ROOT *mem_root, bool bad_format_errors); }; #endif /* _PARSE_FILE_H_ */ sql_lifo_buffer.h 0000644 00000022714 15156036156 0010074 0 ustar 00 /* Copyright (c) 2010, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @defgroup Bi-directional LIFO buffers used by DS-MRR implementation @{ */ class Forward_lifo_buffer; class Backward_lifo_buffer; /* A base class for in-memory buffer used by DS-MRR implementation. Common properties: - The buffer is last-in-first-out, i.e. elements that are written last are read first. - The buffer contains fixed-size elements. The elements are either atomic byte sequences or pairs of them. - The buffer resides in the memory provided by the user. It is possible to = dynamically (ie. between write operations) add ajacent memory space to the buffer = dynamically remove unused space from the buffer. The intent of this is to allow to have two buffers on adjacent memory space, one is being read from (and so its space shrinks), while the other is being written to (and so it needs more and more space). There are two concrete classes, Forward_lifo_buffer and Backward_lifo_buffer. */ class Lifo_buffer { protected: size_t size1; size_t size2; public: /** write() will put into buffer size1 bytes pointed by write_ptr1. If size2!=0, then they will be accompanied by size2 bytes pointed by write_ptr2. */ uchar *write_ptr1; uchar *write_ptr2; /** read() will do reading by storing pointers to read data into read_ptr1 or into (read_ptr1, read_ptr2), depending on whether the buffer was set to store single objects or pairs. */ uchar *read_ptr1; uchar *read_ptr2; protected: uchar *start; /**< points to start of buffer space */ uchar *end; /**< points to just beyond the end of buffer space */ public: enum enum_direction { BACKWARD=-1, /**< buffer is filled/read from bigger to smaller memory addresses */ FORWARD=1 /**< buffer is filled/read from smaller to bigger memory addresses */ }; virtual enum_direction type() = 0; /* Buffer space control functions */ /** Let the buffer store data in the given space. */ void set_buffer_space(uchar *start_arg, uchar *end_arg) { start= start_arg; end= end_arg; if (end != start) TRASH_ALLOC(start, size_t(end - start)); reset(); } /** Specify where write() should get the source data from, as well as source data size. */ void setup_writing(size_t len1, size_t len2) { size1= len1; size2= len2; } /** Specify where read() should store pointers to read data, as well as read data size. The sizes must match those passed to setup_writing(). */ void setup_reading(size_t len1, size_t len2) { DBUG_ASSERT(len1 == size1); DBUG_ASSERT(len2 == size2); } bool can_write() { return have_space_for(size1 + size2); } virtual void write() = 0; bool is_empty() { return used_size() == 0; } virtual bool read() = 0; void sort(qsort_cmp2 cmp_func, void *cmp_func_arg) { size_t elem_size= size1 + size2; size_t n_elements= used_size() / elem_size; my_qsort2(used_area(), n_elements, elem_size, cmp_func, cmp_func_arg); } virtual void reset() = 0; virtual uchar *end_of_space() = 0; protected: virtual size_t used_size() = 0; /* To be used only by iterator class: */ virtual uchar *get_pos()= 0; virtual bool read(uchar **position, uchar **ptr1, uchar **ptr2)= 0; friend class Lifo_buffer_iterator; public: virtual bool have_space_for(size_t bytes) = 0; virtual void remove_unused_space(uchar **unused_start, uchar **unused_end)=0; virtual uchar *used_area() = 0; virtual ~Lifo_buffer() = default; }; /** Forward LIFO buffer The buffer that is being written to from start to end and read in the reverse. 'pos' points to just beyond the end of used space. It is possible to grow/shink the buffer at the end bound used space unused space *==============*-----------------* ^ ^ ^ | | +--- end | +---- pos +--- start */ class Forward_lifo_buffer: public Lifo_buffer { uchar *pos; public: enum_direction type() override { return FORWARD; } size_t used_size() override { return (size_t)(pos - start); } void reset() override { pos= start; } uchar *end_of_space() override { return pos; } bool have_space_for(size_t bytes) override { return (pos + bytes < end); } void write() override { write_bytes(write_ptr1, size1); if (size2) write_bytes(write_ptr2, size2); } void write_bytes(const uchar *data, size_t bytes) { DBUG_ASSERT(have_space_for(bytes)); memcpy(pos, data, bytes); pos += bytes; } bool have_data(uchar *position, size_t bytes) { return ((position - start) >= (ptrdiff_t)bytes); } uchar *read_bytes(uchar **position, size_t bytes) { DBUG_ASSERT(have_data(*position, bytes)); *position= (*position) - bytes; return *position; } bool read() override { return read(&pos, &read_ptr1, &read_ptr2); } bool read(uchar **position, uchar **ptr1, uchar **ptr2) override { if (!have_data(*position, size1 + size2)) return TRUE; if (size2) *ptr2= read_bytes(position, size2); *ptr1= read_bytes(position, size1); return FALSE; } void remove_unused_space(uchar **unused_start, uchar **unused_end) override { DBUG_ASSERT(0); /* Don't need this yet */ } /** Add more space to the buffer. The caller is responsible that the space being added is adjacent to the end of the buffer. @param unused_start Start of space @param unused_end End of space */ void grow(uchar *unused_start, uchar *unused_end) { DBUG_ASSERT(unused_end >= unused_start); DBUG_ASSERT(end == unused_start); TRASH_ALLOC(unused_start, size_t(unused_end - unused_start)); end= unused_end; } /* Return pointer to start of the memory area that is occupied by the data */ uchar *used_area() override { return start; } friend class Lifo_buffer_iterator; uchar *get_pos() override { return pos; } }; /** Backward LIFO buffer The buffer that is being written to from start to end and read in the reverse. 'pos' points to the start of used space. It is possible to grow/shink the buffer at the start. unused space used space *--------------*=================* ^ ^ ^ | | +--- end | +---- pos +--- start */ class Backward_lifo_buffer: public Lifo_buffer { uchar *pos; public: enum_direction type() override { return BACKWARD; } size_t used_size() override { return (size_t)(end - pos); } void reset() override { pos= end; } uchar *end_of_space() override { return end; } bool have_space_for(size_t bytes) override { return (pos - bytes >= start); } void write() override { if (write_ptr2) write_bytes(write_ptr2, size2); write_bytes(write_ptr1, size1); } void write_bytes(const uchar *data, size_t bytes) { DBUG_ASSERT(have_space_for(bytes)); pos -= bytes; memcpy(pos, data, bytes); } bool read() override { return read(&pos, &read_ptr1, &read_ptr2); } bool read(uchar **position, uchar **ptr1, uchar **ptr2) override { if (!have_data(*position, size1 + size2)) return TRUE; *ptr1= read_bytes(position, size1); if (size2) *ptr2= read_bytes(position, size2); return FALSE; } bool have_data(uchar *position, size_t bytes) { return ((end - position) >= (ptrdiff_t)bytes); } uchar *read_bytes(uchar **position, size_t bytes) { DBUG_ASSERT(have_data(*position, bytes)); uchar *ret= *position; *position= *position + bytes; return ret; } /** Stop using/return the unused part of the space @param unused_start OUT Start of the unused space @param unused_end OUT End of the unused space */ void remove_unused_space(uchar **unused_start, uchar **unused_end) override { *unused_start= start; *unused_end= pos; start= pos; } void grow(uchar *unused_start, uchar *unused_end) { DBUG_ASSERT(0); /* Not used for backward buffers */ } /* Return pointer to start of the memory area that is occupied by the data */ uchar *used_area() override { return pos; } friend class Lifo_buffer_iterator; uchar *get_pos() override { return pos; } }; /** Iterator to walk over contents of the buffer without reading from it */ class Lifo_buffer_iterator { uchar *pos; Lifo_buffer *buf; public: /* The data is read to here */ uchar *read_ptr1; uchar *read_ptr2; void init(Lifo_buffer *buf_arg) { buf= buf_arg; pos= buf->get_pos(); } /* Read the next value. The calling convention is the same as buf->read() has. @retval FALSE - ok @retval TRUE - EOF, reached the end of the buffer */ bool read() { return buf->read(&pos, &read_ptr1, &read_ptr2); } }; winservice.h 0000644 00000013603 15156036156 0007106 0 ustar 00 /* Copyright (c) 2011, 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Extract properties of a windows service binary path */ #pragma once #ifdef __cplusplus extern "C" { #endif #include <windows.h> #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4995) #endif #include <winsvc.h> #ifdef _MSC_VER #pragma warning(pop) #endif typedef struct mysqld_service_properties_st { char mysqld_exe[MAX_PATH]; char inifile[MAX_PATH]; char datadir[MAX_PATH]; int version_major; int version_minor; int version_patch; } mysqld_service_properties; extern int get_mysql_service_properties(const wchar_t *bin_path, mysqld_service_properties *props); #if !defined(UNICODE) /* The following wrappers workaround Windows bugs with CreateService/OpenService with ANSI codepage UTF8. Apparently, these function in ANSI mode, for this codepage only do *not* behave as expected (as-if string parameters were converted to UTF16 and "wide" function were called) */ #include <malloc.h> static inline wchar_t* awstrdup(const char *str) { if (!str) return NULL; size_t len= strlen(str) + 1; wchar_t *wstr= (wchar_t *) malloc(sizeof(wchar_t)*len); if (MultiByteToWideChar(GetACP(), 0, str, (int)len, wstr, (int)len) == 0) { free(wstr); return NULL; } return wstr; } #define AWSTRDUP(dest, src) \ dest= awstrdup(src); \ if (src && !dest) \ { \ ok= FALSE; \ last_error = ERROR_OUTOFMEMORY; \ goto end; \ } static inline SC_HANDLE my_OpenService(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess) { wchar_t *w_ServiceName= NULL; BOOL ok=TRUE; DWORD last_error=0; SC_HANDLE sch=NULL; AWSTRDUP(w_ServiceName, lpServiceName); sch= OpenServiceW(hSCManager, w_ServiceName, dwDesiredAccess); if (!sch) { ok= FALSE; last_error= GetLastError(); } end: free(w_ServiceName); if (!ok) SetLastError(last_error); return sch; } static inline SC_HANDLE my_CreateService(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword) { wchar_t *w_ServiceName= NULL; wchar_t *w_DisplayName= NULL; wchar_t *w_BinaryPathName= NULL; wchar_t *w_LoadOrderGroup= NULL; wchar_t *w_Dependencies= NULL; wchar_t *w_ServiceStartName= NULL; wchar_t *w_Password= NULL; SC_HANDLE sch = NULL; DWORD last_error=0; BOOL ok= TRUE; AWSTRDUP(w_ServiceName,lpServiceName); AWSTRDUP(w_DisplayName,lpDisplayName); AWSTRDUP(w_BinaryPathName, lpBinaryPathName); AWSTRDUP(w_LoadOrderGroup, lpLoadOrderGroup); AWSTRDUP(w_Dependencies, lpDependencies); AWSTRDUP(w_ServiceStartName, lpServiceStartName); AWSTRDUP(w_Password, lpPassword); sch= CreateServiceW( hSCManager, w_ServiceName, w_DisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, w_BinaryPathName, w_LoadOrderGroup, lpdwTagId, w_Dependencies, w_ServiceStartName, w_Password); if(!sch) { ok= FALSE; last_error= GetLastError(); } end: free(w_ServiceName); free(w_DisplayName); free(w_BinaryPathName); free(w_LoadOrderGroup); free(w_Dependencies); free(w_ServiceStartName); free(w_Password); if (!ok) SetLastError(last_error); return sch; } static inline BOOL my_ChangeServiceConfig(SC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName) { wchar_t *w_DisplayName= NULL; wchar_t *w_BinaryPathName= NULL; wchar_t *w_LoadOrderGroup= NULL; wchar_t *w_Dependencies= NULL; wchar_t *w_ServiceStartName= NULL; wchar_t *w_Password= NULL; DWORD last_error=0; BOOL ok= TRUE; AWSTRDUP(w_DisplayName, lpDisplayName); AWSTRDUP(w_BinaryPathName, lpBinaryPathName); AWSTRDUP(w_LoadOrderGroup, lpLoadOrderGroup); AWSTRDUP(w_Dependencies, lpDependencies); AWSTRDUP(w_ServiceStartName, lpServiceStartName); AWSTRDUP(w_Password, lpPassword); ok= ChangeServiceConfigW( hService, dwServiceType, dwStartType, dwErrorControl, w_BinaryPathName, w_LoadOrderGroup, lpdwTagId, w_Dependencies, w_ServiceStartName, w_Password, w_DisplayName); if (!ok) { last_error= GetLastError(); } end: free(w_DisplayName); free(w_BinaryPathName); free(w_LoadOrderGroup); free(w_Dependencies); free(w_ServiceStartName); free(w_Password); if (last_error) SetLastError(last_error); return ok; } #undef AWSTRDUP #undef OpenService #define OpenService my_OpenService #undef ChangeServiceConfig #define ChangeServiceConfig my_ChangeServiceConfig #undef CreateService #define CreateService my_CreateService #endif #ifdef __cplusplus } #endif table.h 0000644 00000354771 15156036156 0006035 0 ustar 00 #ifndef TABLE_INCLUDED #define TABLE_INCLUDED /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_plist.h" #include "sql_list.h" /* Sql_alloc */ #include "mdl.h" #include "datadict.h" #include "sql_string.h" /* String */ #include "lex_string.h" #include "lex_ident.h" #ifndef MYSQL_CLIENT #include "my_cpu.h" /* LF_BACKOFF() */ #include "hash.h" /* HASH */ #include "handler.h" /* row_type, ha_choice, handler */ #include "mysql_com.h" /* enum_field_types */ #include "thr_lock.h" /* thr_lock_type */ #include "filesort_utils.h" #include "parse_file.h" #include "sql_i_s.h" #include "sql_type.h" /* vers_kind_t */ #include "privilege.h" /* privilege_t */ #include "my_bit.h" /* Buffer for unix timestamp in microseconds: 9,223,372,036,854,775,807 (signed int64 maximal value) 1 234 567 890 123 456 789 Note: we can use unsigned for calculation, but practically they are the same by probability to overflow them (signed int64 in microseconds is enough for almost 3e5 years) and signed allow to avoid increasing the buffer (the old buffer for human readable date was 19+1). */ #define MICROSECOND_TIMESTAMP_BUFFER_SIZE (19 + 1) /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ typedef Item (*Item_ptr); class Item_subselect; class Item_field; class Item_func_hash; class GRANT_TABLE; class st_select_lex_unit; class st_select_lex; class partition_info; class COND_EQUAL; class Security_context; struct TABLE_LIST; class ACL_internal_schema_access; class ACL_internal_table_access; class Field; class Copy_field; class Table_statistics; class With_element; struct TDC_element; class Virtual_column_info; class Table_triggers_list; class TMP_TABLE_PARAM; class SEQUENCE; class Range_rowid_filter_cost_info; class derived_handler; class Pushdown_derived; struct Name_resolution_context; class Table_function_json_table; class Open_table_context; class MYSQL_LOG; /* Used to identify NESTED_JOIN structures within a join (applicable only to structures that have not been simplified away and embed more the one element) */ typedef ulonglong nested_join_map; #define VIEW_MD5_LEN 32 #define tmp_file_prefix "#sql" /**< Prefix for tmp tables */ #define tmp_file_prefix_length 4 #define TMP_TABLE_KEY_EXTRA 8 #define ROCKSDB_DIRECTORY_NAME "#rocksdb" /** Enumerate possible types of a table from re-execution standpoint. TABLE_LIST class has a member of this type. At prepared statement prepare, this member is assigned a value as of the current state of the database. Before (re-)execution of a prepared statement, we check that the value recorded at prepare matches the type of the object we obtained from the table definition cache. @sa check_and_update_table_version() @sa Execute_observer @sa Prepared_statement::reprepare() */ enum enum_table_ref_type { /** Initial value set by the parser */ TABLE_REF_NULL= 0, TABLE_REF_VIEW, TABLE_REF_BASE_TABLE, TABLE_REF_I_S_TABLE, TABLE_REF_TMP_TABLE }; /*************************************************************************/ /** Object_creation_ctx -- interface for creation context of database objects (views, stored routines, events, triggers). Creation context -- is a set of attributes, that should be fixed at the creation time and then be used each time the object is parsed or executed. */ class Object_creation_ctx { public: Object_creation_ctx *set_n_backup(THD *thd); void restore_env(THD *thd, Object_creation_ctx *backup_ctx); protected: Object_creation_ctx() = default; virtual Object_creation_ctx *create_backup_ctx(THD *thd) const = 0; virtual void change_env(THD *thd) const = 0; public: virtual ~Object_creation_ctx() = default; }; /*************************************************************************/ /** Default_object_creation_ctx -- default implementation of Object_creation_ctx. */ class Default_object_creation_ctx : public Object_creation_ctx { public: CHARSET_INFO *get_client_cs() { return m_client_cs; } CHARSET_INFO *get_connection_cl() { return m_connection_cl; } protected: Default_object_creation_ctx(THD *thd); Default_object_creation_ctx(CHARSET_INFO *client_cs, CHARSET_INFO *connection_cl); protected: Object_creation_ctx *create_backup_ctx(THD *thd) const override; void change_env(THD *thd) const override; protected: /** client_cs stores the value of character_set_client session variable. The only character set attribute is used. Client character set is included into query context, because we save query in the original character set, which is client character set. So, in order to parse the query properly we have to switch client character set on parsing. */ CHARSET_INFO *m_client_cs; /** connection_cl stores the value of collation_connection session variable. Both character set and collation attributes are used. Connection collation is included into query context, becase it defines the character set and collation of text literals in internal representation of query (item-objects). */ CHARSET_INFO *m_connection_cl; }; class Query_arena; /*************************************************************************/ /** View_creation_ctx -- creation context of view objects. */ class View_creation_ctx : public Default_object_creation_ctx, public Sql_alloc { public: static View_creation_ctx *create(THD *thd); static View_creation_ctx *create(THD *thd, TABLE_LIST *view); private: View_creation_ctx(THD *thd) : Default_object_creation_ctx(thd) { } }; /*************************************************************************/ /* Order clause list element */ typedef int (*fast_field_copier)(Field *to, Field *from); typedef struct st_order { struct st_order *next; Item **item; /* Point at item in select fields */ Item *item_ptr; /* Storage for initial item */ /* Reference to the function we are trying to optimize copy to a temporary table */ fast_field_copier fast_field_copier_func; /* Field for which above optimizer function setup */ Field *fast_field_copier_setup; int counter; /* position in SELECT list, correct only if counter_used is true*/ enum enum_order { ORDER_NOT_RELEVANT, ORDER_ASC, ORDER_DESC }; enum_order direction; /* Requested direction of ordering */ bool in_field_list; /* true if in select field list */ bool counter_used; /* parameter was counter of columns */ Field *field; /* If tmp-table group */ char *buff; /* If tmp-table group */ table_map used; /* NOTE: the below is only set to 0 but is still used by eq_ref_table */ table_map depend_map; } ORDER; /** State information for internal tables grants. This structure is part of the TABLE_LIST, and is updated during the ACL check process. @sa GRANT_INFO */ struct st_grant_internal_info { /** True if the internal lookup by schema name was done. */ bool m_schema_lookup_done; /** Cached internal schema access. */ const ACL_internal_schema_access *m_schema_access; /** True if the internal lookup by table name was done. */ bool m_table_lookup_done; /** Cached internal table access. */ const ACL_internal_table_access *m_table_access; }; typedef struct st_grant_internal_info GRANT_INTERNAL_INFO; /** @brief The current state of the privilege checking process for the current user, SQL statement and SQL object. @details The privilege checking process is divided into phases depending on the level of the privilege to be checked and the type of object to be accessed. Due to the mentioned scattering of privilege checking functionality, it is necessary to keep track of the state of the process. This information is stored in privilege, want_privilege, and orig_want_privilege. A GRANT_INFO also serves as a cache of the privilege hash tables. Relevant members are grant_table and version. */ typedef struct st_grant_info { /** @brief A copy of the privilege information regarding the current host, database, object and user. @details The version of this copy is found in GRANT_INFO::version. */ GRANT_TABLE *grant_table_user; GRANT_TABLE *grant_table_role; GRANT_TABLE *grant_public; /** @brief Used for cache invalidation when caching privilege information. @details The privilege information is stored on disk, with dedicated caches residing in memory: table-level and column-level privileges, respectively, have their own dedicated caches. The GRANT_INFO works as a level 1 cache with this member updated to the current value of the global variable @c grant_version (@c static variable in sql_acl.cc). It is updated Whenever the GRANT_INFO is refreshed from the level 2 cache. The level 2 cache is the @c column_priv_hash structure (@c static variable in sql_acl.cc) @see grant_version */ uint version; /** @brief The set of privileges that the current user has fulfilled for a certain host, database, and object. @details This field is continually updated throughout the access checking process. In each step the "wanted privilege" is checked against the fulfilled privileges. When/if the intersection of these sets is empty, access is granted. The set is implemented as a bitmap, with the bits defined in sql_acl.h. */ privilege_t privilege; /** @brief the set of privileges that the current user needs to fulfil in order to carry out the requested operation. */ privilege_t want_privilege; /** Stores the requested access acl of top level tables list. Is used to check access rights to the underlying tables of a view. */ privilege_t orig_want_privilege; /** The grant state for internal tables. */ GRANT_INTERNAL_INFO m_internal; st_grant_info() :privilege(NO_ACL), want_privilege(NO_ACL), orig_want_privilege(NO_ACL) { } void read(const Security_context *sctx, const char *db, const char *table); inline void refresh(const Security_context *sctx, const char *db, const char *table); inline privilege_t aggregate_privs(); inline privilege_t aggregate_cols(); /* OR table and all column privileges */ privilege_t all_privilege(); } GRANT_INFO; enum tmp_table_type { NO_TMP_TABLE= 0, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE, INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE }; enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; enum vcol_init_mode { VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING= 1, VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR= 2 /* There may be new flags here. e.g. to automatically remove sql_mode dependency: GENERATED ALWAYS AS (char_col) -> GENERATED ALWAYS AS (RTRIM(char_col)) */ }; enum enum_vcol_update_mode { VCOL_UPDATE_FOR_READ= 0, VCOL_UPDATE_FOR_WRITE, VCOL_UPDATE_FOR_DELETE, VCOL_UPDATE_INDEXED, VCOL_UPDATE_INDEXED_FOR_UPDATE, VCOL_UPDATE_FOR_REPLACE }; /* Field visibility enums */ enum __attribute__((packed)) field_visibility_t { VISIBLE= 0, INVISIBLE_USER, /* automatically added by the server. Can be queried explicitly in SELECT, otherwise invisible from anything" */ INVISIBLE_SYSTEM, INVISIBLE_FULL }; #define INVISIBLE_MAX_BITS 3 #define HA_HASH_FIELD_LENGTH 8 #define HA_HASH_KEY_LENGTH_WITHOUT_NULL 8 #define HA_HASH_KEY_LENGTH_WITH_NULL 9 int fields_in_hash_keyinfo(KEY *keyinfo); void setup_keyinfo_hash(KEY *key_info); void re_setup_keyinfo_hash(KEY *key_info); /** Category of table found in the table share. */ enum enum_table_category { /** Unknown value. */ TABLE_UNKNOWN_CATEGORY=0, /** Temporary table. The table is visible only in the session. Therefore, - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON do not apply to this table. Note that LOCK TABLE t FOR READ/WRITE can be used on temporary tables. Temporary tables are not part of the table cache. */ TABLE_CATEGORY_TEMPORARY=1, /** User table. These tables do honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON User tables are cached in the table cache. */ TABLE_CATEGORY_USER=2, /** System table, maintained by the server. These tables do honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON Typically, writes to system tables are performed by the server implementation, not explicitly be a user. System tables are cached in the table cache. */ TABLE_CATEGORY_SYSTEM=3, /** Log tables. These tables are an interface provided by the system to inspect the system logs. These tables do *not* honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON as there is no point in locking explicitly a LOG table. An example of LOG tables are: - mysql.slow_log - mysql.general_log, which *are* updated even when there is either a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect. User queries do not write directly to these tables (there are exceptions for log tables). The server implementation perform writes. Log tables are cached in the table cache. */ TABLE_CATEGORY_LOG=4, /* Types below are read only tables, not affected by FLUSH TABLES or MDL locks. */ /** Information schema tables. These tables are an interface provided by the system to inspect the system metadata. These tables do *not* honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON as there is no point in locking explicitly an INFORMATION_SCHEMA table. Nothing is directly written to information schema tables. Note that this value is not used currently, since information schema tables are not shared, but implemented as session specific temporary tables. */ /* TODO: Fixing the performance issues of I_S will lead to I_S tables in the table cache, which should use this table type. */ TABLE_CATEGORY_INFORMATION=5, /** Performance schema tables. These tables are an interface provided by the system to inspect the system performance data. These tables do *not* honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON as there is no point in locking explicitly a PERFORMANCE_SCHEMA table. An example of PERFORMANCE_SCHEMA tables are: - performance_schema.* which *are* updated (but not using the handler interface) even when there is either a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect. User queries do not write directly to these tables (there are exceptions for SETUP_* tables). The server implementation perform writes. Performance tables are cached in the table cache. */ TABLE_CATEGORY_PERFORMANCE=6 }; typedef enum enum_table_category TABLE_CATEGORY; TABLE_CATEGORY get_table_category(const Lex_ident_db &db, const Lex_ident_table &name); typedef struct st_table_field_type { LEX_CSTRING name; LEX_CSTRING type; LEX_CSTRING cset; } TABLE_FIELD_TYPE; typedef struct st_table_field_def { uint count; const TABLE_FIELD_TYPE *field; uint primary_key_parts; const uint *primary_key_columns; } TABLE_FIELD_DEF; class Table_check_intact { protected: bool has_keys; virtual void report_error(uint code, const char *fmt, ...)= 0; public: Table_check_intact(bool keys= false) : has_keys(keys) {} virtual ~Table_check_intact() = default; /** Checks whether a table is intact. */ bool check(TABLE *table, const TABLE_FIELD_DEF *table_def); }; /* If the table isn't valid, report the error to the server log only. */ class Table_check_intact_log_error : public Table_check_intact { protected: void report_error(uint, const char *fmt, ...) override; public: Table_check_intact_log_error() : Table_check_intact(true) {} }; /** Class representing the fact that some thread waits for table share to be flushed. Is used to represent information about such waits in MDL deadlock detector. */ class Wait_for_flush : public MDL_wait_for_subgraph { MDL_context *m_ctx; TABLE_SHARE *m_share; uint m_deadlock_weight; public: Wait_for_flush(MDL_context *ctx_arg, TABLE_SHARE *share_arg, uint deadlock_weight_arg) : m_ctx(ctx_arg), m_share(share_arg), m_deadlock_weight(deadlock_weight_arg) {} MDL_context *get_ctx() const { return m_ctx; } bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor) override; uint get_deadlock_weight() const override; /** Pointers for participating in the list of waiters for table share. */ Wait_for_flush *next_in_share; Wait_for_flush **prev_in_share; }; typedef I_P_List <Wait_for_flush, I_P_List_adapter<Wait_for_flush, &Wait_for_flush::next_in_share, &Wait_for_flush::prev_in_share> > Wait_for_flush_list; enum open_frm_error { OPEN_FRM_OK = 0, OPEN_FRM_OPEN_ERROR, OPEN_FRM_READ_ERROR, OPEN_FRM_CORRUPTED, OPEN_FRM_DISCOVER, OPEN_FRM_ERROR_ALREADY_ISSUED, OPEN_FRM_NOT_A_VIEW, OPEN_FRM_NOT_A_TABLE, OPEN_FRM_NEEDS_REBUILD }; /** Control block to access table statistics loaded from persistent statistical tables */ #define TABLE_STAT_NO_STATS 0 #define TABLE_STAT_TABLE 1 #define TABLE_STAT_COLUMN 2 #define TABLE_STAT_INDEX 4 #define TABLE_STAT_HISTOGRAM 8 /* EITS statistics information for a table. This data is loaded from mysql.{table|index|column}_stats tables and then most of the time is owned by table's TABLE_SHARE object. Individual TABLE objects also have pointer to this object, and we do reference counting to know when to free it. See TABLE::update_engine_stats(), TABLE::free_engine_stats(), TABLE_SHARE::update_engine_stats(), TABLE_SHARE::destroy(). These implement a "shared pointer"-like functionality. When new statistics is loaded, we create new TABLE_STATISTICS_CB and make the TABLE_SHARE point to it. Some TABLE object may still be using older TABLE_STATISTICS_CB objects. Reference counting allows to free TABLE_STATISTICS_CB when it is no longer used. */ class TABLE_STATISTICS_CB { uint usage_count; // Instances of this stat public: TABLE_STATISTICS_CB(); ~TABLE_STATISTICS_CB(); MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */ Table_statistics *table_stats; /* Structure to access the statistical data */ uint stats_available; bool histograms_exists_on_disk; bool histograms_exists() const { return histograms_exists_on_disk; } bool unused() { return usage_count == 0; } /* Copy (latest) state from TABLE_SHARE to TABLE */ void update_stats_in_table(TABLE *table); friend struct TABLE; friend struct TABLE_SHARE; }; /** This structure is shared between different table objects. There is one instance of table share per one table in the database. */ struct TABLE_SHARE { TABLE_SHARE() = default; /* Remove gcc warning */ /** Category of this table. */ TABLE_CATEGORY table_category; /* hash of field names (contains pointers to elements of field array) */ HASH name_hash; /* hash of field names */ MEM_ROOT mem_root; TYPELIB keynames; /* Pointers to keynames */ TYPELIB fieldnames; /* Pointer to fieldnames */ TYPELIB *intervals; /* pointer to interval info */ mysql_mutex_t LOCK_ha_data; /* To protect access to ha_data */ mysql_mutex_t LOCK_share; /* To protect TABLE_SHARE */ mysql_mutex_t LOCK_statistics; /* To protect against concurrent load */ TDC_element *tdc; LEX_CUSTRING tabledef_version; engine_option_value *option_list; /* text options for table */ ha_table_option_struct *option_struct; /* structure with parsed options */ /* The following is copied to each TABLE on OPEN */ Field **field; Field **found_next_number_field; KEY *key_info; /* data of keys in database */ Virtual_column_info **check_constraints; uint *blob_field; /* Index to blobs in Field arrray*/ LEX_CUSTRING vcol_defs; /* definitions of generated columns */ /* EITS statistics data from the last time the table was opened or ANALYZE table was run. This is typically same as any related TABLE::stats_cb until ANALYZE table is run. This pointer is only to be de-referenced under LOCK_share as the pointer can change by another thread running ANALYZE TABLE. Without using a LOCK_share one can check if the statistics has been updated by checking if TABLE::stats_cb != TABLE_SHARE::stats_cb. */ TABLE_STATISTICS_CB *stats_cb; uchar *default_values; /* row with default values */ LEX_CSTRING comment; /* Comment about table */ CHARSET_INFO *table_charset; /* Default charset of string fields */ MY_BITMAP *check_set; /* Fields used by check constrant */ MY_BITMAP all_set; /* Key which is used for looking-up table in table cache and in the list of thread's temporary tables. Has the form of: "database_name\0table_name\0" + optional part for temporary tables. Note that all three 'table_cache_key', 'db' and 'table_name' members must be set (and be non-zero) for tables in table cache. They also should correspond to each other. To ensure this one can use set_table_cache() methods. */ LEX_CSTRING table_cache_key; LEX_CSTRING db; /* Pointer to db */ LEX_CSTRING table_name; /* Table name (for open) */ LEX_CSTRING path; /* Path to .frm file (from datadir) */ LEX_CSTRING normalized_path; /* unpack_filename(path) */ LEX_CSTRING connect_string; /* Set of keys in use, implemented as a Bitmap. Excludes keys disabled by ALTER TABLE ... DISABLE KEYS. */ key_map keys_in_use; /* The set of ignored indexes for a table. */ key_map ignored_indexes; key_map keys_for_keyread; ha_rows min_rows, max_rows; /* create information */ ulong avg_row_length; /* create information */ ulong mysql_version; /* 0 if .frm is created before 5.0 */ ulong reclength; /* Recordlength */ /* Stored record length. No generated-only virtual fields are included */ ulong stored_rec_length; plugin_ref db_plugin; /* storage engine plugin */ inline handlerton *db_type() const /* table_type for handler */ { return is_view ? view_pseudo_hton : db_plugin ? plugin_hton(db_plugin) : NULL; } OPTIMIZER_COSTS optimizer_costs; /* Copy of get_optimizer_costs() */ enum row_type row_type; /* How rows are stored */ enum Table_type table_type; enum tmp_table_type tmp_table; /** Transactional or not. */ enum ha_choice transactional; /** Per-page checksums or not. */ enum ha_choice page_checksum; uint key_block_size; /* create key_block_size, if used */ uint stats_sample_pages; /* number of pages to sample during stats estimation, if used, otherwise 0. */ enum_stats_auto_recalc stats_auto_recalc; /* Automatic recalc of stats. */ uint null_bytes, last_null_bit_pos; /* Same as null_bytes, except that if there is only a 'delete-marker' in the record then this value is 0. */ uint null_bytes_for_compare; uint fields; /* number of fields */ /* number of stored fields, purely virtual not included */ uint stored_fields; uint virtual_fields; /* number of purely virtual fields */ /* number of purely virtual not stored blobs */ uint virtual_not_stored_blob_fields; uint null_fields; /* number of null fields */ uint blob_fields; /* number of blob fields */ uint varchar_fields; /* number of varchar fields */ uint default_fields; /* number of default fields */ uint visible_fields; /* number of visible fields */ uint default_expressions; uint table_check_constraints, field_check_constraints; uint rec_buff_length; /* Size of table->record[] buffer */ uint keys, key_parts; uint ext_key_parts; /* Total number of key parts in extended keys */ uint max_key_length, max_unique_length; /* Older versions had TABLE_SHARE::uniques but now it is replaced with per-index HA_UNIQUE_HASH flag */ bool have_unique_constraint() const { for (uint i=0; i < keys; i++) if (key_info[i].flags & HA_UNIQUE_HASH) return true; return false; } uint db_create_options; /* Create options from database */ uint db_options_in_use; /* Options in use */ uint db_record_offset; /* if HA_REC_IN_SEQ */ uint rowid_field_offset; /* Field_nr +1 to rowid field */ /* Primary key index number, used in TABLE::key_info[] */ uint primary_key; uint next_number_index; /* autoincrement key number */ uint next_number_key_offset; /* autoinc keypart offset in a key */ uint next_number_keypart; /* autoinc keypart number in a key */ enum open_frm_error error; /* error from open_table_def() */ uint open_errno; /* error from open_table_def() */ uint column_bitmap_size; uchar frm_version; enum enum_v_keys { NOT_INITIALIZED=0, NO_V_KEYS, V_KEYS }; enum_v_keys check_set_initialized; bool use_ext_keys; /* Extended keys can be used */ bool null_field_first; bool system; /* Set if system table (one record) */ bool not_usable_by_query_cache; bool online_backup; /* Set if on-line backup supported */ /* This is used by log tables, for tables that have their own internal binary logging or for tables that doesn't support statement or row logging */ bool no_replicate; bool crashed; bool is_view; bool can_cmp_whole_record; /* This is set for temporary tables where CREATE was binary logged */ bool table_creation_was_logged; bool non_determinstic_insert; bool has_update_default_function; bool can_do_row_logging; /* 1 if table supports RBR */ bool long_unique_table; /* 1 if frm version cannot be updated as part of upgrade */ bool keep_original_mysql_version; bool optimizer_costs_inited; ulonglong table_map_id; /* for row-based replication */ /* Things that are incompatible between the stored version and the current version. This is a set of HA_CREATE... bits that can be used to modify create_info->used_fields for ALTER TABLE. */ ulong incompatible_version; /** For shares representing views File_parser object with view definition read from .FRM file. */ const File_parser *view_def; /* For sequence tables, the current sequence state */ SEQUENCE *sequence; #ifdef WITH_PARTITION_STORAGE_ENGINE /* filled in when reading from frm */ bool auto_partitioned; char *partition_info_str; uint partition_info_str_len; uint partition_info_buffer_size; plugin_ref default_part_plugin; #endif #ifdef HAVE_REPLICATION Cache_flip_event_log *online_alter_binlog; #endif /** System versioning and application-time periods support. */ struct period_info_t { field_index_t start_fieldno; field_index_t end_fieldno; Lex_ident name; Lex_ident constr_name; uint unique_keys; Field *start_field(TABLE_SHARE *s) const { return s->field[start_fieldno]; } Field *end_field(TABLE_SHARE *s) const { return s->field[end_fieldno]; } }; vers_kind_t versioned; period_info_t vers; period_info_t period; /* Protect multiple threads from repeating partition auto-create over single share. TODO: remove it when partitioning metadata will be in TABLE_SHARE. */ bool vers_skip_auto_create; bool init_period_from_extra2(period_info_t *period, const uchar *data, const uchar *end); Field *vers_start_field() { DBUG_ASSERT(versioned); return field[vers.start_fieldno]; } Field *vers_end_field() { DBUG_ASSERT(versioned); return field[vers.end_fieldno]; } Field *period_start_field() const { DBUG_ASSERT(period.name); return field[period.start_fieldno]; } Field *period_end_field() const { DBUG_ASSERT(period.name); return field[period.end_fieldno]; } /** Cache the checked structure of this table. The pointer data is used to describe the structure that a instance of the table must have. Each element of the array specifies a field that must exist on the table. The pointer is cached in order to perform the check only once -- when the table is loaded from the disk. */ const TABLE_FIELD_DEF *table_field_def_cache; /** Main handler's share */ Handler_share *ha_share; /** Instrumentation for this table share. */ PSI_table_share *m_psi; inline void reset() { bzero((void*)this, sizeof(*this)); } /* Set share's table cache key and update its db and table name appropriately. SYNOPSIS set_table_cache_key() key_buff Buffer with already built table cache key to be referenced from share. key_length Key length. NOTES Since 'key_buff' buffer will be referenced from share it should has same life-time as share itself. This method automatically ensures that TABLE_SHARE::table_name/db have appropriate values by using table cache key as their source. */ void set_table_cache_key(char *key_buff, uint key_length) { table_cache_key.str= key_buff; table_cache_key.length= key_length; /* Let us use the fact that the key is "db/0/table_name/0" + optional part for temporary tables. */ db.str= table_cache_key.str; db.length= strlen(db.str); table_name.str= db.str + db.length + 1; table_name.length= strlen(table_name.str); } /* Set share's table cache key and update its db and table name appropriately. SYNOPSIS set_table_cache_key() key_buff Buffer to be used as storage for table cache key (should be at least key_length bytes). key Value for table cache key. key_length Key length. NOTE Since 'key_buff' buffer will be used as storage for table cache key it should has same life-time as share itself. */ void set_table_cache_key(char *key_buff, const char *key, uint key_length) { memcpy(key_buff, key, key_length); set_table_cache_key(key_buff, key_length); } inline bool require_write_privileges() { return (table_category == TABLE_CATEGORY_LOG); } inline ulonglong get_table_def_version() { return table_map_id; } /** Convert unrelated members of TABLE_SHARE to one enum representing its type. @todo perhaps we need to have a member instead of a function. */ enum enum_table_ref_type get_table_ref_type() const { if (is_view) return TABLE_REF_VIEW; switch (tmp_table) { case NO_TMP_TABLE: return TABLE_REF_BASE_TABLE; case SYSTEM_TMP_TABLE: return TABLE_REF_I_S_TABLE; default: return TABLE_REF_TMP_TABLE; } } /** Return a table metadata version. * for base tables and views, we return table_map_id. It is assigned from a global counter incremented for each new table loaded into the table definition cache (TDC). * for temporary tables it's table_map_id again. But for temporary tables table_map_id is assigned from thd->query_id. The latter is assigned from a thread local counter incremented for every new SQL statement. Since temporary tables are thread-local, each temporary table gets a unique id. * for everything else (e.g. information schema tables), the version id is zero. This choice of version id is a large compromise to have a working prepared statement validation in 5.1. In future version ids will be persistent, as described in WL#4180. Let's try to explain why and how this limited solution allows to validate prepared statements. Firstly, sets (in mathematical sense) of version numbers never intersect for different table types. Therefore, version id of a temporary table is never compared with a version id of a view, and vice versa. Secondly, for base tables and views, we know that each DDL flushes the respective share from the TDC. This ensures that whenever a table is altered or dropped and recreated, it gets a new version id. Unfortunately, since elements of the TDC are also flushed on LRU basis, this choice of version ids leads to false positives. E.g. when the TDC size is too small, we may have a SELECT * FROM INFORMATION_SCHEMA.TABLES flush all its elements, which in turn will lead to a validation error and a subsequent reprepare of all prepared statements. This is considered acceptable, since as long as prepared statements are automatically reprepared, spurious invalidation is only a performance hit. Besides, no better simple solution exists. For temporary tables, using thd->query_id ensures that if a temporary table was altered or recreated, a new version id is assigned. This suits validation needs very well and will perhaps never change. Metadata of information schema tables never changes. Thus we can safely assume 0 for a good enough version id. Finally, by taking into account table type, we always track that a change has taken place when a view is replaced with a base table, a base table is replaced with a temporary table and so on. @sa TABLE_LIST::is_the_same_definition() */ ulonglong get_table_ref_version() const { return (tmp_table == SYSTEM_TMP_TABLE) ? 0 : table_map_id; } bool is_optimizer_tmp_table() { return tmp_table == INTERNAL_TMP_TABLE && !db.length && table_name.length; } bool visit_subgraph(Wait_for_flush *waiting_ticket, MDL_wait_for_graph_visitor *gvisitor); bool wait_for_old_version(THD *thd, struct timespec *abstime, uint deadlock_weight); /** Release resources and free memory occupied by the table share. */ void destroy(); void set_use_ext_keys_flag(bool fl) { use_ext_keys= fl; } uint actual_n_key_parts(THD *thd); LEX_CUSTRING *frm_image; ///< only during CREATE TABLE (@sa ha_create_table) /* populates TABLE_SHARE from the table description in the binary frm image. if 'write' is true, this frm image is also written into a corresponding frm file, that serves as a persistent metadata cache to avoid discovering the table over and over again */ int init_from_binary_frm_image(THD *thd, bool write, const uchar *frm_image, size_t frm_length, const uchar *par_image=0, size_t par_length=0); /* populates TABLE_SHARE from the table description, specified as the complete CREATE TABLE sql statement. if 'write' is true, this frm image is also written into a corresponding frm file, that serves as a persistent metadata cache to avoid discovering the table over and over again */ int init_from_sql_statement_string(THD *thd, bool write, const char *sql, size_t sql_length); /* writes the frm image to an frm file, corresponding to this table */ bool write_frm_image(const uchar *frm_image, size_t frm_length); bool write_par_image(const uchar *par_image, size_t par_length); /* Only used by S3 */ bool write_frm_image(void) { return frm_image ? write_frm_image(frm_image->str, frm_image->length) : 0; } /* returns an frm image for this table. the memory is allocated and must be freed later */ bool read_frm_image(const uchar **frm_image, size_t *frm_length); /* frees the memory allocated in read_frm_image */ void free_frm_image(const uchar *frm); void set_overlapped_keys(); void set_ignored_indexes(); key_map usable_indexes(THD *thd); bool old_long_hash_function() const { return mysql_version < 100428 || (mysql_version >= 100500 && mysql_version < 100519) || (mysql_version >= 100600 && mysql_version < 100612) || (mysql_version >= 100700 && mysql_version < 100708) || (mysql_version >= 100800 && mysql_version < 100807) || (mysql_version >= 100900 && mysql_version < 100905) || (mysql_version >= 101000 && mysql_version < 101003) || (mysql_version >= 101100 && mysql_version < 101102); } Item_func_hash *make_long_hash_func(THD *thd, MEM_ROOT *mem_root, List<Item> *field_list) const; void update_optimizer_costs(handlerton *hton); void update_engine_independent_stats(TABLE_STATISTICS_CB *stat); bool histograms_exists(); }; /* not NULL, but cannot be dereferenced */ #define UNUSABLE_TABLE_SHARE ((TABLE_SHARE*)1) /** Class is used as a BLOB field value storage for intermediate GROUP_CONCAT results. Used only for GROUP_CONCAT with DISTINCT or ORDER BY options. */ class Blob_mem_storage: public Sql_alloc { private: MEM_ROOT storage; /** Sign that some values were cut during saving into the storage. */ bool truncated_value; public: Blob_mem_storage() :truncated_value(false) { init_alloc_root(key_memory_blob_mem_storage, &storage, MAX_FIELD_VARCHARLENGTH, 0, MYF(0)); } ~ Blob_mem_storage() { free_root(&storage, MYF(0)); } void reset() { free_root(&storage, MYF(MY_MARK_BLOCKS_FREE)); truncated_value= false; } /** Fuction creates duplicate of 'from' string in 'storage' MEM_ROOT. @param from string to copy @param length string length @retval Pointer to the copied string. @retval 0 if an error occurred. */ char *store(const char *from, size_t length) { return (char*) memdup_root(&storage, from, length); } void set_truncated_value(bool is_truncated_value) { truncated_value= is_truncated_value; } bool is_truncated_value() { return truncated_value; } }; /* Information for one open table */ enum index_hint_type { INDEX_HINT_IGNORE, INDEX_HINT_USE, INDEX_HINT_FORCE }; struct st_cond_statistic; #define CHECK_ROW_FOR_NULLS_TO_REJECT (1 << 0) #define REJECT_ROW_DUE_TO_NULL_FIELDS (1 << 1) class SplM_opt_info; struct vers_select_conds_t; struct TABLE { TABLE() = default; /* Remove gcc warning */ TABLE_SHARE *s; handler *file; TABLE *next, *prev; private: /** Links for the list of all TABLE objects for this share. Declared as private to avoid direct manipulation with those objects. One should use methods of I_P_List template instead. */ TABLE *share_all_next, **share_all_prev; TABLE *global_free_next, **global_free_prev; friend struct All_share_tables; friend struct Table_cache_instance; public: THD *in_use; /* Which thread uses this */ uchar *record[3]; /* Pointer to records */ uchar *write_row_record; /* Used as optimisation in THD::write_row */ uchar *insert_values; /* used by INSERT ... UPDATE */ /* Map of keys that can be used to retrieve all data from this table needed by the query without reading the row. */ key_map covering_keys, intersect_keys; /* A set of keys that can be used in the query that references this table. All indexes disabled on the table's TABLE_SHARE (see TABLE::s) will be subtracted from this set upon instantiation. Thus for any TABLE t it holds that t.keys_in_use_for_query is a subset of t.s.keys_in_use. Generally we must not introduce any new keys here (see setup_tables). The set is implemented as a bitmap. */ key_map keys_in_use_for_query; /* Map of keys that can be used to calculate GROUP BY without sorting */ key_map keys_in_use_for_group_by; /* Map of keys that can be used to calculate ORDER BY without sorting */ key_map keys_in_use_for_order_by; /* Map of keys dependent on some constraint */ key_map constraint_dependent_keys; KEY *key_info; /* data of keys in database */ Field **field; /* Pointer to fields */ Field **vfield; /* Pointer to virtual fields*/ Field **default_field; /* Fields with non-constant DEFAULT */ Field *next_number_field; /* Set if next_number is activated */ Field *found_next_number_field; /* Set on open */ Virtual_column_info **check_constraints; /* Table's triggers, 0 if there are no of them */ Table_triggers_list *triggers; TABLE_LIST *pos_in_table_list;/* Element referring to this table */ /* Position in thd->locked_table_list under LOCK TABLES */ TABLE_LIST *pos_in_locked_tables; /* Tables used in DEFAULT and CHECK CONSTRAINT (normally sequence tables) */ TABLE_LIST *internal_tables; /* Not-null for temporary tables only. Non-null values means this table is used to compute GROUP BY, it has a unique of GROUP BY columns. (set by create_tmp_table) */ ORDER *group; String alias; /* alias or table name */ uchar *null_flags; MY_BITMAP def_read_set, def_write_set, tmp_set; MY_BITMAP def_rpl_write_set; MY_BITMAP eq_join_set; /* used to mark equi-joined fields */ MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/ /* Active column sets */ MY_BITMAP *read_set, *write_set, *rpl_write_set; /* On INSERT: fields that the user specified a value for */ MY_BITMAP has_value_set; /* The ID of the query that opened and is using this table. Has different meanings depending on the table type. Temporary tables: table->query_id is set to thd->query_id for the duration of a statement and is reset to 0 once it is closed by the same statement. A non-zero table->query_id means that a statement is using the table even if it's not the current statement (table is in use by some outer statement). Non-temporary tables: Under pre-locked or LOCK TABLES mode: query_id is set to thd->query_id for the duration of a statement and is reset to 0 once it is closed by the same statement. A non-zero query_id is used to control which tables in the list of pre-opened and locked tables are actually being used. */ query_id_t query_id; /* This structure is used for statistical data on the table that is collected by the function collect_statistics_for_table */ Table_statistics *collected_stats; /* The estimate of the number of records in the table used by optimizer */ ha_rows used_stat_records; key_map opt_range_keys; /* The following structure is filled for each key that has opt_range_keys.is_set(key) == TRUE */ struct OPT_RANGE { uint key_parts; uint ranges; ha_rows rows, max_index_blocks, max_row_blocks; Cost_estimate cost; /* Selectivity, in case of filters */ double selectivity; bool first_key_part_has_only_one_value; /* Cost of fetching keys with index only read and returning them to the sql level. */ double index_only_fetch_cost(TABLE *table); void get_costs(ALL_READ_COST *cost); } *opt_range; /* Bitmaps of key parts that =const for the duration of join execution. If we're in a subquery, then the constant may be different across subquery re-executions. */ key_part_map *const_key_parts; /* Estimate of number of records that satisfy SARGable part of the table condition, or table->file->records if no SARGable condition could be constructed. This value is used by join optimizer as an estimate of number of records that will pass the table condition (condition that depends on fields of this table and constants) */ ha_rows opt_range_condition_rows; double cond_selectivity; List<st_cond_statistic> *cond_selectivity_sampling_explain; table_map map; /* ID bit of table (1,2,4,8,16...) */ uint lock_position; /* Position in MYSQL_LOCK.table */ uint lock_data_start; /* Start pos. in MYSQL_LOCK.locks */ uint lock_count; /* Number of locks */ uint tablenr,used_fields; uint temp_pool_slot; /* Used by intern temp tables */ uint status; /* What's in record[0] */ uint db_stat; /* mode of file as in handler.h */ /* number of select if it is derived table */ uint derived_select_number; /* Possible values: - 0 by default - JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join operation - 1 if the SELECT has mixed_implicit_grouping=1. example: select max(col1), col2 from t1. In this case, the query produces one row with all columns having NULL values. Interpetation: If maybe_null!=0, all fields of the table are considered NULLable (and have NULL values when null_row=true) */ uint maybe_null; uint max_keys; /* Size of allocated key_info array. */ int current_lock; /* Type of lock on table */ /* Number of cost info elements for possible range filters */ uint range_rowid_filter_cost_info_elems; uint32 instance; /** Table cache instance this TABLE is belonging to */ /* variables of type bool */ bool copy_blobs; /* copy_blobs when storing */ /* Set if next_number_field is in the UPDATE fields of INSERT ... ON DUPLICATE KEY UPDATE. */ bool next_number_field_updated; /* If true, the current table row is considered to have all columns set to NULL, including columns declared as "not null" (see maybe_null). */ bool null_row; /* No rows that contain null values can be placed into this table. Currently this flag can be set to true only for a temporary table that used to store the result of materialization of a subquery. */ bool no_rows_with_nulls; /* This field can contain two bit flags: CHECK_ROW_FOR_NULLS_TO_REJECT REJECT_ROW_DUE_TO_NULL_FIELDS The first flag is set for the dynamic contexts where it is prohibited to write any null into the table. The second flag is set only if the first flag is set on. The informs the outer scope that there was an attept to write null into a field of the table in the context where it is prohibited. This flag should be set off as soon as the first flag is set on. Currently these flags are used only the tables tno_rows_with_nulls set to true. */ uint8 null_catch_flags; /* TODO: Each of the following flags take up 8 bits. They can just as easily be put into one single unsigned long and instead of taking up 18 bytes, it would take up 4. */ bool force_index; /* Flag set when the statement contains FORCE INDEX FOR JOIN */ bool force_index_join; /** Flag set when the statement contains FORCE INDEX FOR ORDER BY See TABLE_LIST::process_index_hints(). */ bool force_index_order; /** Flag set when the statement contains FORCE INDEX FOR GROUP BY See TABLE_LIST::process_index_hints(). */ bool force_index_group; /* TRUE<=> this table was created with create_tmp_table(... distinct=TRUE..) call */ bool distinct; bool const_table,no_rows, used_for_duplicate_elimination; /** Forces DYNAMIC Aria row format for internal temporary tables. */ bool keep_row_order; bool no_keyread; /** If set, indicate that the table is not replicated by the server. */ bool locked_by_logger; bool locked_by_name; bool fulltext_searched; bool no_cache; /* To signal that the table is associated with a HANDLER statement */ bool open_by_handler; /* To indicate that a non-null value of the auto_increment field was provided by the user or retrieved from the current record. Used only in the MODE_NO_AUTO_VALUE_ON_ZERO mode. */ bool auto_increment_field_not_null; /* NOTE: alias_name_used is only a hint! It works only in need_correct_ident() condition. On other cases it is FALSE even if table_name is alias. E.g. in update t1 as x set a = 1 */ bool alias_name_used; /* true if table_name is alias */ bool get_fields_in_item_tree; /* Signal to fix_field */ private: bool m_needs_reopen; bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: #ifdef HAVE_REPLICATION /* used in RBR Triggers */ bool master_had_triggers; #endif /* Temporary value used by binlog_write_table_maps(). Does not need init */ bool restore_row_logging; bool stats_is_read; /* Persistent statistics is read for the table */ bool histograms_are_read; #ifdef WITH_PARTITION_STORAGE_ENGINE /* If true, all partitions have been pruned away */ bool all_partitions_pruned_away; #endif bool vers_write; // For versioning List<Virtual_column_info> vcol_refix_list; REGINFO reginfo; /* field connections */ MEM_ROOT mem_root; /* this is for temporary tables created inside Item_func_group_concat */ union { bool group_concat; /* used during create_tmp_table() */ Blob_mem_storage *blob_storage; /* used after create_tmp_table() */ }; GRANT_INFO grant; /* The arena which the items for expressions from the table definition are associated with. Currently only the items of the expressions for virtual columns are associated with this arena. TODO: To attach the partitioning expressions to this arena. */ Query_arena *expr_arena; #ifdef WITH_PARTITION_STORAGE_ENGINE partition_info *part_info; /* Partition related information */ #endif MDL_ticket *mdl_ticket; /* This is used only for potentially splittable materialized tables and it points to the info used by the optimizer to apply splitting optimization */ SplM_opt_info *spl_opt_info; key_map keys_usable_for_splitting; /* Conjunction of the predicates of the form IS NOT NULL(f) where f refers to a column of this TABLE such that they can be inferred from the condition of the WHERE clause or from some ON expression of the processed select and can be useful for range optimizer. */ Item *notnull_cond; TABLE_STATISTICS_CB *stats_cb; online_alter_cache_data *online_alter_cache; inline void reset() { bzero((void*)this, sizeof(*this)); } void init(THD *thd, TABLE_LIST *tl); bool fill_item_list(List<Item> *item_list) const; void reset_item_list(List<Item> *item_list, uint skip) const; void clear_column_bitmaps(void); void prepare_for_position(void); MY_BITMAP *prepare_for_keyread(uint index, MY_BITMAP *map); MY_BITMAP *prepare_for_keyread(uint index) { return prepare_for_keyread(index, &tmp_set); } void mark_index_columns(uint index, MY_BITMAP *bitmap); void mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap); void mark_index_columns_for_read(uint index); void restore_column_maps_after_keyread(MY_BITMAP *backup); void mark_auto_increment_column(bool insert_fl); void mark_columns_needed_for_update(void); void mark_columns_needed_for_delete(void); void mark_columns_needed_for_insert(void); void mark_columns_per_binlog_row_image(void); inline bool mark_column_with_deps(Field *field); inline bool mark_virtual_column_with_deps(Field *field); inline void mark_virtual_column_deps(Field *field); bool mark_virtual_columns_for_write(bool insert_fl); bool check_virtual_columns_marked_for_read(); bool check_virtual_columns_marked_for_write(); void mark_default_fields_for_write(bool insert_fl); void mark_columns_used_by_virtual_fields(void); void mark_check_constraint_columns_for_read(void); int verify_constraints(bool ignore_failure); void free_engine_stats(); void update_engine_independent_stats(); inline void column_bitmaps_set(MY_BITMAP *read_set_arg) { read_set= read_set_arg; if (file) file->column_bitmaps_signal(); } inline void column_bitmaps_set(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg) { read_set= read_set_arg; write_set= write_set_arg; if (file) file->column_bitmaps_signal(); } inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg) { read_set= read_set_arg; write_set= write_set_arg; } inline void use_all_columns() { column_bitmaps_set(&s->all_set, &s->all_set); } inline void use_all_stored_columns(); inline void default_column_bitmaps() { read_set= &def_read_set; write_set= &def_write_set; rpl_write_set= 0; } /** Should this instance of the table be reopened? */ inline bool needs_reopen() { return !db_stat || m_needs_reopen; } /* Mark that all current connection instances of the table should be reopen at end of statement */ void mark_table_for_reopen(); /* Should only be called from Locked_tables_list::mark_table_for_reopen() */ void internal_set_needs_reopen(bool value) { m_needs_reopen= value; } bool init_expr_arena(MEM_ROOT *mem_root); bool alloc_keys(uint key_count); bool check_tmp_key(uint key, uint key_parts, uint (*next_field_no) (uchar *), uchar *arg); bool add_tmp_key(uint key, uint key_parts, uint (*next_field_no) (uchar *), uchar *arg, bool unique); void create_key_part_by_field(KEY_PART_INFO *key_part_info, Field *field, uint fieldnr); void use_index(int key_to_save, key_map *map_to_update); void set_table_map(table_map map_arg, uint tablenr_arg) { map= map_arg; tablenr= tablenr_arg; } /// Return true if table is instantiated, and false otherwise. bool is_created() const { DBUG_ASSERT(!created || file != 0); return created; } /** Set the table as "created", and enable flags in storage engine that could not be enabled without an instantiated table. */ void set_created() { if (created) return; if (file->keyread_enabled()) file->extra(HA_EXTRA_KEYREAD); created= true; } void reset_created() { created= 0; } /* Returns TRUE if the table is filled at execution phase (and so, the optimizer must not do anything that depends on the contents of the table, like range analysis or constant table detection) */ bool is_filled_at_execution(); bool update_const_key_parts(COND *conds); void update_keypart_vcol_info(); inline void initialize_opt_range_structures(); my_ptrdiff_t default_values_offset() const { return (my_ptrdiff_t) (s->default_values - record[0]); } void move_fields(Field **ptr, const uchar *to, const uchar *from); void remember_blob_values(String *blob_storage); void restore_blob_values(String *blob_storage); uint actual_n_key_parts(KEY *keyinfo); ulong actual_key_flags(KEY *keyinfo); int update_virtual_field(Field *vf, bool ignore_warnings); size_t key_storage_length(uint index); /* @brief Estimate how index tuple takes in storage, based solely on table's DDL @detail This is a conservative number that assumes the value is stored in KeyTupleFormat (or table->record format for clustered PK), without endspace compression, etc. On the other hand, it doesn't account that the storage engine may need to store transactionIds, etc. */ inline size_t key_storage_length_from_ddl(uint index) { if (is_clustering_key(index)) return s->stored_rec_length; return key_info[index].key_length + file->ref_length; } int update_virtual_fields(handler *h, enum_vcol_update_mode update_mode); int update_default_fields(bool ignore_errors); void evaluate_update_default_function(); void reset_default_fields(); inline ha_rows stat_records() { return used_stat_records; } void prepare_triggers_for_insert_stmt_or_event(); bool prepare_triggers_for_delete_stmt_or_event(); bool prepare_triggers_for_update_stmt_or_event(); Field **field_to_fill(); bool validate_default_values_of_unset_fields(THD *thd) const; // Check if the value list is assignable to the explicit field list static bool check_assignability_explicit_fields(List<Item> fields, List<Item> values, bool ignore); // Check if the value list is assignable to all visible fields bool check_assignability_all_visible_fields(List<Item> &values, bool ignore) const; /* Check if the value list is assignable to: - The explicit field list if fields.elements > 0, e.g. INSERT INTO t1 (a,b) VALUES (1,2); - All visible fields, if fields.elements==0, e.g. INSERT INTO t1 VALUES (1,2); */ bool check_assignability_opt_fields(List<Item> fields, List<Item> values, bool ignore) const { DBUG_ASSERT(values.elements); return fields.elements ? check_assignability_explicit_fields(fields, values, ignore) : check_assignability_all_visible_fields(values, ignore); } bool insert_all_rows_into_tmp_table(THD *thd, TABLE *tmp_table, TMP_TABLE_PARAM *tmp_table_param, bool with_cleanup); bool check_sequence_privileges(THD *thd); bool vcol_fix_expr(THD *thd); bool vcol_cleanup_expr(THD *thd); Field *find_field_by_name(const LEX_CSTRING *str) const; bool export_structure(THD *thd, class Row_definition_list *defs); bool is_splittable() { return spl_opt_info != NULL; } void set_spl_opt_info(SplM_opt_info *spl_info); void deny_splitting(); double get_materialization_cost(); // Now used only if is_splittable()==true void add_splitting_info_for_key_field(struct KEY_FIELD *key_field); key_map with_impossible_ranges; /* Pointer to the array of cost info elements for range filters */ Range_rowid_filter_cost_info *range_rowid_filter_cost_info; /* The array of pointers to cost info elements for range filters */ Range_rowid_filter_cost_info **range_rowid_filter_cost_info_ptr; void init_cost_info_for_usable_range_rowid_filters(THD *thd); void prune_range_rowid_filters(); void trace_range_rowid_filters(THD *thd) const; Range_rowid_filter_cost_info * best_range_rowid_filter(uint access_key_no, double records, double fetch_cost, double index_only_cost, double prev_records, double *records_out); /** System Versioning support */ bool versioned() const { return s->versioned; } bool versioned(vers_kind_t type) const { DBUG_ASSERT(type); return s->versioned == type; } bool versioned_write() const { DBUG_ASSERT(versioned() || !vers_write); return versioned() ? vers_write : false; } bool versioned_write(vers_kind_t type) const { DBUG_ASSERT(type); DBUG_ASSERT(versioned() || !vers_write); return versioned(type) ? vers_write : false; } Field *vers_start_field() const { DBUG_ASSERT(s->versioned); return field[s->vers.start_fieldno]; } Field *vers_end_field() const { DBUG_ASSERT(s->versioned); return field[s->vers.end_fieldno]; } Field *period_start_field() const { DBUG_ASSERT(s->period.name); return field[s->period.start_fieldno]; } Field *period_end_field() const { DBUG_ASSERT(s->period.name); return field[s->period.end_fieldno]; } inline void set_cond_selectivity(double selectivity) { DBUG_ASSERT(selectivity >= 0.0 && selectivity <= 1.0); cond_selectivity= selectivity; DBUG_PRINT("info", ("cond_selectivity: %g", cond_selectivity)); } inline void multiply_cond_selectivity(double selectivity) { DBUG_ASSERT(selectivity >= 0.0 && selectivity <= 1.0); cond_selectivity*= selectivity; DBUG_PRINT("info", ("cond_selectivity: %g", cond_selectivity)); } inline void set_opt_range_condition_rows(ha_rows rows) { if (opt_range_condition_rows > rows) opt_range_condition_rows= rows; } /* Return true if the key is a clustered key */ inline bool is_clustering_key(uint index) const { return key_info[index].index_flags & HA_CLUSTERED_INDEX; } /* Return true if we can use rowid filter with this index rowid filter can be used if - filter pushdown is supported by the engine for the index. If this is set then file->ha_table_flags() should not contain HA_NON_COMPARABLE_ROWID! - The index is not a clustered primary index */ inline bool can_use_rowid_filter(uint index) const { return ((key_info[index].index_flags & (HA_DO_RANGE_FILTER_PUSHDOWN | HA_CLUSTERED_INDEX)) == HA_DO_RANGE_FILTER_PUSHDOWN); } ulonglong vers_start_id(const uchar *ptr) const; ulonglong vers_end_id(const uchar *ptr) const; #ifdef WITH_PARTITION_STORAGE_ENGINE bool vers_switch_partition(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx); #endif int update_generated_fields(); void period_prepare_autoinc(); int period_make_insert(Item *src, Field *dst); int insert_portion_of_time(THD *thd, const vers_select_conds_t &period_conds, ha_rows *rows_inserted); bool vers_check_update(List<Item> &items); static bool check_period_overlaps(const KEY &key, const uchar *lhs, const uchar *rhs); inline int delete_row(){ return delete_row<false>(versioned(VERS_TIMESTAMP)); } template <bool replace> int delete_row(bool versioned); /* Used in majority of DML (called from fill_record()) */ bool vers_update_fields(); /* Used in DELETE, DUP REPLACE and insert history row */ void vers_update_end(); void find_constraint_correlated_indexes(); /** Number of additional fields used in versioned tables */ #define VERSIONING_FIELDS 2 }; /** Helper class which specifies which members of TABLE are used for participation in the list of used/unused TABLE objects for the share. */ struct TABLE_share { static inline TABLE **next_ptr(TABLE *l) { return &l->next; } static inline TABLE ***prev_ptr(TABLE *l) { return (TABLE ***) &l->prev; } }; struct All_share_tables { static inline TABLE **next_ptr(TABLE *l) { return &l->share_all_next; } static inline TABLE ***prev_ptr(TABLE *l) { return &l->share_all_prev; } }; typedef I_P_List <TABLE, All_share_tables> All_share_tables_list; enum enum_schema_table_state { NOT_PROCESSED= 0, PROCESSED_BY_CREATE_SORT_INDEX, PROCESSED_BY_JOIN_EXEC }; enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_NO_ACTION, FK_OPTION_CASCADE, FK_OPTION_SET_NULL, FK_OPTION_SET_DEFAULT }; typedef struct st_foreign_key_info { LEX_CSTRING *foreign_id; LEX_CSTRING *foreign_db; LEX_CSTRING *foreign_table; LEX_CSTRING *referenced_db; LEX_CSTRING *referenced_table; enum_fk_option update_method; enum_fk_option delete_method; LEX_CSTRING *referenced_key_name; List<LEX_CSTRING> foreign_fields; List<LEX_CSTRING> referenced_fields; private: unsigned char *fields_nullable= nullptr; /** Get the number of fields exist in foreign key relationship */ unsigned get_n_fields() const noexcept { unsigned n_fields= foreign_fields.elements; if (n_fields == 0) n_fields= referenced_fields.elements; return n_fields; } /** Assign nullable field for referenced and foreign fields based on number of fields. This nullable fields should be allocated by engine for passing the foreign key information @param thd thread to allocate the memory @param num_fields number of fields */ void assign_nullable(THD *thd, unsigned num_fields) noexcept { fields_nullable= (unsigned char *)thd_calloc(thd, my_bits_in_bytes(2 * num_fields)); } public: /** Set nullable bit for the field in the given field @param referenced set null bit for referenced column @param field field number @param n_fields number of fields */ void set_nullable(THD *thd, bool referenced, unsigned field, unsigned n_fields) noexcept { if (!fields_nullable) assign_nullable(thd, n_fields); DBUG_ASSERT(fields_nullable); DBUG_ASSERT(field < n_fields); size_t bit= size_t{field} + referenced * n_fields; #if defined __GNUC__ && !defined __clang__ && __GNUC__ < 8 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" #endif fields_nullable[bit / 8]|= static_cast<unsigned char>(1 << (bit % 8)); #if defined __GNUC__ && !defined __clang__ && __GNUC__ < 8 # pragma GCC diagnostic pop #endif } /** Check whether the given field_no in foreign key field or referenced key field @param referenced check referenced field nullable value @param field field number @return true if the field is nullable or false if it is not */ bool is_nullable(bool referenced, unsigned field) const noexcept { if (!fields_nullable) return false; unsigned n_field= get_n_fields(); DBUG_ASSERT(field < n_field); size_t bit= size_t{field} + referenced * n_field; return fields_nullable[bit / 8] & (1U << (bit % 8)); } } FOREIGN_KEY_INFO; LEX_CSTRING *fk_option_name(enum_fk_option opt); static inline bool fk_modifies_child(enum_fk_option opt) { return opt >= FK_OPTION_CASCADE; } class IS_table_read_plan; /* Types of derived tables. The ending part is a bitmap of phases that are applicable to a derived table of the type. */ #define DTYPE_ALGORITHM_UNDEFINED 0U #define DTYPE_VIEW 1U #define DTYPE_TABLE 2U #define DTYPE_MERGE 4U #define DTYPE_MATERIALIZE 8U #define DTYPE_MULTITABLE 16U #define DTYPE_IN_PREDICATE 32U #define DTYPE_MASK (DTYPE_VIEW|DTYPE_TABLE|DTYPE_MULTITABLE|DTYPE_IN_PREDICATE) /* Phases of derived tables/views handling, see sql_derived.cc Values are used as parts of a bitmap attached to derived table types. */ #define DT_INIT 1U #define DT_PREPARE 2U #define DT_OPTIMIZE 4U #define DT_MERGE 8U #define DT_MERGE_FOR_INSERT 16U #define DT_CREATE 32U #define DT_FILL 64U #define DT_REINIT 128U #define DT_OPTIMIZE_STAGE2 256U /* Number of bits used by all phases: */ #define DT_PHASES 9U /* Phases that are applicable to all derived tables. */ #define DT_COMMON (DT_INIT + DT_PREPARE + DT_REINIT + DT_OPTIMIZE + DT_OPTIMIZE_STAGE2) /* Phases that are applicable only to materialized derived tables. */ #define DT_MATERIALIZE (DT_CREATE + DT_FILL) #define DT_PHASES_MERGE (DT_COMMON | DT_MERGE | DT_MERGE_FOR_INSERT) #define DT_PHASES_MATERIALIZE (DT_COMMON | DT_MATERIALIZE) #define VIEW_ALGORITHM_UNDEFINED 0 /* Special value for ALTER VIEW: inherit original algorithm. */ #define VIEW_ALGORITHM_INHERIT DTYPE_VIEW #define VIEW_ALGORITHM_MERGE (DTYPE_VIEW | DTYPE_MERGE) #define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW | DTYPE_MATERIALIZE) /* View algorithm values as stored in the FRM. Values differ from in-memory representation for backward compatibility. */ #define VIEW_ALGORITHM_UNDEFINED_FRM 0U #define VIEW_ALGORITHM_MERGE_FRM 1U #define VIEW_ALGORITHM_TMPTABLE_FRM 2U #define JOIN_TYPE_LEFT 1U #define JOIN_TYPE_RIGHT 2U #define JOIN_TYPE_OUTER 4U /* Marker that this is an outer join */ /* view WITH CHECK OPTION parameter options */ #define VIEW_CHECK_NONE 0 #define VIEW_CHECK_LOCAL 1 #define VIEW_CHECK_CASCADED 2 /* result of view WITH CHECK OPTION parameter check */ #define VIEW_CHECK_OK 0 #define VIEW_CHECK_ERROR 1 #define VIEW_CHECK_SKIP 2 /** The threshold size a blob field buffer before it is freed */ #define MAX_TDC_BLOB_SIZE 65536 /** number of bytes used by field positional indexes in frm */ constexpr uint frm_fieldno_size= 2; /** number of bytes used by key position number in frm */ constexpr uint frm_keyno_size= 2; static inline field_index_t read_frm_fieldno(const uchar *data) { return uint2korr(data); } static inline void store_frm_fieldno(uchar *data, field_index_t fieldno) { int2store(data, fieldno); } static inline uint16 read_frm_keyno(const uchar *data) { return uint2korr(data); } static inline void store_frm_keyno(uchar *data, uint16 keyno) { int2store(data, keyno); } static inline size_t extra2_str_size(size_t len) { return (len > 255 ? 3 : 1) + len; } class select_unit; class TMP_TABLE_PARAM; Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, LEX_CSTRING *name); struct Field_translator { Item *item; LEX_CSTRING name; }; /* Column reference of a NATURAL/USING join. Since column references in joins can be both from views and stored tables, may point to either a Field (for tables), or a Field_translator (for views). */ class Natural_join_column: public Sql_alloc { public: Field_translator *view_field; /* Column reference of merge view. */ Item_field *table_field; /* Column reference of table or temp view. */ TABLE_LIST *table_ref; /* Original base table/view reference. */ /* True if a common join column of two NATURAL/USING join operands. Notice that when we have a hierarchy of nested NATURAL/USING joins, a column can be common at some level of nesting but it may not be common at higher levels of nesting. Thus this flag may change depending on at which level we are looking at some column. */ bool is_common; public: Natural_join_column(Field_translator *field_param, TABLE_LIST *tab); Natural_join_column(Item_field *field_param, TABLE_LIST *tab); LEX_CSTRING *name(); Item *create_item(THD *thd); Field *field(); const char *safe_table_name(); const char *safe_db_name(); GRANT_INFO *grant(); }; /** Type of table which can be open for an element of table list. */ enum enum_open_type { OT_TEMPORARY_OR_BASE= 0, OT_TEMPORARY_ONLY, OT_BASE_ONLY }; class SJ_MATERIALIZATION_INFO; class Index_hint; class Item_in_subselect; /* trivial class, for %union in sql_yacc.yy */ struct vers_history_point_t { vers_kind_t unit; Item *item; }; struct vers_select_conds_t; class Vers_history_point : public vers_history_point_t { void fix_item(); public: Vers_history_point() { empty(); } Vers_history_point(vers_kind_t unit_arg, Item *item_arg) { unit= unit_arg; item= item_arg; fix_item(); } Vers_history_point(vers_history_point_t p) { unit= p.unit; item= p.item; fix_item(); } void empty() { unit= VERS_TIMESTAMP; item= NULL; } void print(String *str, enum_query_type, const char *prefix, size_t plen) const; bool check_unit(THD *thd, vers_select_conds_t *vers_conds); bool has_param() const; bool eq(const vers_history_point_t &point) const; }; struct vers_select_conds_t { vers_system_time_t type; vers_system_time_t orig_type; bool used:1; bool delete_history:1; bool has_param:1; Vers_history_point start; Vers_history_point end; Lex_ident name; Item_field *field_start; Item_field *field_end; const TABLE_SHARE::period_info_t *period; void empty() { type= SYSTEM_TIME_UNSPECIFIED; orig_type= SYSTEM_TIME_UNSPECIFIED; used= false; delete_history= false; has_param= false; start.empty(); end.empty(); } void init(vers_system_time_t _type, Vers_history_point _start= Vers_history_point(), Vers_history_point _end= Vers_history_point(), Lex_ident _name= { STRING_WITH_LEN("SYSTEM_TIME") }) { type= _type; orig_type= _type; used= false; delete_history= (type == SYSTEM_TIME_HISTORY || type == SYSTEM_TIME_BEFORE); has_param= false; start= _start; end= _end; name= _name; } void set_all() { type= SYSTEM_TIME_ALL; name= { STRING_WITH_LEN("SYSTEM_TIME") }; } void print(String *str, enum_query_type query_type) const; bool init_from_sysvar(THD *thd); bool is_set() const { return type != SYSTEM_TIME_UNSPECIFIED; } bool check_units(THD *thd); bool was_set() const { return orig_type != SYSTEM_TIME_UNSPECIFIED; } bool need_setup() const { return type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL; } bool eq(const vers_select_conds_t &conds) const; }; /* Table reference in the FROM clause. These table references can be of several types that correspond to different SQL elements. Below we list all types of TABLE_LISTs with the necessary conditions to determine when a TABLE_LIST instance belongs to a certain type. 1) table (TABLE_LIST::view == NULL) - base table (TABLE_LIST::derived == NULL) - FROM-clause subquery - TABLE_LIST::table is a temp table (TABLE_LIST::derived != NULL) - information schema table (TABLE_LIST::schema_table != NULL) NOTICE: for schema tables TABLE_LIST::field_translation may be != NULL 2) view (TABLE_LIST::view != NULL) - merge (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_MERGE) also (TABLE_LIST::field_translation != NULL) - tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE) also (TABLE_LIST::field_translation == NULL) 2.5) TODO: Add derived tables description here 3) nested table reference (TABLE_LIST::nested_join != NULL) - table sequence - e.g. (t1, t2, t3) TODO: how to distinguish from a JOIN? - general JOIN TODO: how to distinguish from a table sequence? - NATURAL JOIN (TABLE_LIST::natural_join != NULL) - JOIN ... USING (TABLE_LIST::join_using_fields != NULL) - semi-join nest (sj_on_expr!= NULL && sj_subq_pred!=NULL) 4) jtbm semi-join (jtbm_subselect != NULL) */ /** last_leaf_for_name_resolutioning support. */ struct LEX; class Index_hint; /* @struct TABLE_CHAIN @brief Subchain of global chain of table references The structure contains a pointer to the address of the next_global pointer to the first TABLE_LIST objectof the subchain and the address of the next_global pointer to the element right after the last TABLE_LIST object of the subchain. For an empty subchain both pointers have the same value. */ struct TABLE_CHAIN { TABLE_CHAIN() = default; TABLE_LIST **start_pos; TABLE_LIST ** end_pos; void set_start_pos(TABLE_LIST **pos) { start_pos= pos; } void set_end_pos(TABLE_LIST **pos) { end_pos= pos; } }; class Table_ident; struct TABLE_LIST { TABLE_LIST(THD *thd, LEX_CSTRING db_str, bool fqtn, LEX_CSTRING alias_str, bool has_alias_ptr, Table_ident *table_ident, thr_lock_type lock_t, enum_mdl_type mdl_t, ulong table_opts, bool info_schema, st_select_lex *sel, List<Index_hint> *index_hints_ptr, LEX_STRING *option_ptr); TABLE_LIST() = default; /* Remove gcc warning */ enum prelocking_types { PRELOCK_NONE, PRELOCK_ROUTINE, PRELOCK_FK }; /** Prepare TABLE_LIST that consists of one table instance to use in open_and_lock_tables */ inline void reset() { bzero((void*)this, sizeof(*this)); } inline void init_one_table(const LEX_CSTRING *db_arg, const LEX_CSTRING *table_name_arg, const LEX_CSTRING *alias_arg, enum thr_lock_type lock_type_arg) { enum enum_mdl_type mdl_type; if (lock_type_arg >= TL_FIRST_WRITE) mdl_type= MDL_SHARED_WRITE; else if (lock_type_arg == TL_READ_NO_INSERT) mdl_type= MDL_SHARED_NO_WRITE; else mdl_type= MDL_SHARED_READ; reset(); DBUG_ASSERT(!db_arg->str || strlen(db_arg->str) == db_arg->length); DBUG_ASSERT(!table_name_arg->str || strlen(table_name_arg->str) == table_name_arg->length); DBUG_ASSERT(!alias_arg || strlen(alias_arg->str) == alias_arg->length); db= *db_arg; table_name= *table_name_arg; alias= (alias_arg ? *alias_arg : *table_name_arg); lock_type= lock_type_arg; updating= lock_type >= TL_FIRST_WRITE; MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, db.str, table_name.str, mdl_type, MDL_TRANSACTION); } TABLE_LIST(const LEX_CSTRING *db_arg, const LEX_CSTRING *table_name_arg, const LEX_CSTRING *alias_arg, enum thr_lock_type lock_type_arg) { init_one_table(db_arg, table_name_arg, alias_arg, lock_type_arg); } TABLE_LIST(TABLE *table_arg, thr_lock_type lock_type) : TABLE_LIST(&table_arg->s->db, &table_arg->s->table_name, NULL, lock_type) { DBUG_ASSERT(table_arg->s); table= table_arg; vers_conditions.name= table->s->vers.name; } inline void init_one_table_for_prelocking(const LEX_CSTRING *db_arg, const LEX_CSTRING *table_name_arg, const LEX_CSTRING *alias_arg, enum thr_lock_type lock_type_arg, prelocking_types prelocking_type, TABLE_LIST *belong_to_view_arg, uint8 trg_event_map_arg, TABLE_LIST ***last_ptr, my_bool insert_data) { init_one_table(db_arg, table_name_arg, alias_arg, lock_type_arg); cacheable_table= 1; prelocking_placeholder= prelocking_type; open_type= (prelocking_type == PRELOCK_ROUTINE ? OT_TEMPORARY_OR_BASE : OT_BASE_ONLY); belong_to_view= belong_to_view_arg; trg_event_map= trg_event_map_arg; /* MDL is enough for read-only FK checks, we don't need the table */ if (prelocking_type == PRELOCK_FK && lock_type < TL_FIRST_WRITE) open_strategy= OPEN_STUB; **last_ptr= this; prev_global= *last_ptr; *last_ptr= &next_global; for_insert_data= insert_data; } /* List of tables local to a subquery (used by SQL_I_List). Considers views as leaves (unlike 'next_leaf' below). Created at parse time in st_select_lex::add_table_to_list() -> table_list.link_in_list(). */ TABLE_LIST *next_local; /* link in a global list of all queries tables */ TABLE_LIST *next_global, **prev_global; TABLE_LIST *linked_table; // For sequence tables used in default LEX_CSTRING db; LEX_CSTRING table_name; LEX_CSTRING schema_table_name; LEX_CSTRING alias; const char *option; /* Used by cache index */ Item *on_expr; /* Used with outer join */ Name_resolution_context *on_context; /* For ON expressions */ Table_function_json_table *table_function; /* If it's the table function. */ Item *sj_on_expr; /* (Valid only for semi-join nests) Bitmap of tables that are within the semi-join (this is different from bitmap of all nest's children because tables that were pulled out of the semi-join nest remain listed as nest's children). */ table_map sj_inner_tables; /* Number of IN-compared expressions */ uint sj_in_exprs; /* If this is a non-jtbm semi-join nest: corresponding subselect predicate */ Item_in_subselect *sj_subq_pred; table_map original_subq_pred_used_tables; /* If this is a jtbm semi-join object: corresponding subselect predicate */ Item_in_subselect *jtbm_subselect; /* TODO: check if this can be joined with tablenr_exec */ uint jtbm_table_no; SJ_MATERIALIZATION_INFO *sj_mat_info; /* The structure of ON expression presented in the member above can be changed during certain optimizations. This member contains a snapshot of AND-OR structure of the ON expression made after permanent transformations of the parse tree, and is used to restore ON clause before every reexecution of a prepared statement or stored procedure. */ Item *prep_on_expr; COND_EQUAL *cond_equal; /* Used with outer join */ /* During parsing - left operand of NATURAL/USING join where 'this' is the right operand. After parsing (this->natural_join == this) iff 'this' represents a NATURAL or USING join operation. Thus after parsing 'this' is a NATURAL/USING join iff (natural_join != NULL). */ TABLE_LIST *natural_join; /* True if 'this' represents a nested join that is a NATURAL JOIN. For one of the operands of 'this', the member 'natural_join' points to the other operand of 'this'. */ bool is_natural_join; /* Field names in a USING clause for JOIN ... USING. */ List<String> *join_using_fields; /* Explicitly store the result columns of either a NATURAL/USING join or an operand of such a join. */ List<Natural_join_column> *join_columns; /* TRUE if join_columns contains all columns of this table reference. */ bool is_join_columns_complete; /* List of nodes in a nested join tree, that should be considered as leaves with respect to name resolution. The leaves are: views, top-most nodes representing NATURAL/USING joins, subqueries, and base tables. All of these TABLE_LIST instances contain a materialized list of columns. The list is local to a subquery. */ TABLE_LIST *next_name_resolution_table; /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */ List<Index_hint> *index_hints; TABLE *table; /* opened table */ ulonglong table_id; /* table id (from binlog) for opened table */ /* select_result for derived table to pass it from table creation to table filling procedure */ select_unit *derived_result; /* Stub used for materialized derived tables. */ bool delete_while_scanning; table_map map; /* ID bit of table (1,2,4,8,16...) */ table_map get_map() { return jtbm_subselect? table_map(1) << jtbm_table_no : table->map; } uint get_tablenr() { return jtbm_subselect? jtbm_table_no : table->tablenr; } void set_tablenr(uint new_tablenr) { if (jtbm_subselect) { jtbm_table_no= new_tablenr; } if (table) { table->tablenr= new_tablenr; table->map= table_map(1) << new_tablenr; } } /* Reference from aux_tables to local list entry of main select of multi-delete statement: delete t1 from t2,t1 where t1.a<'B' and t2.b=t1.b; here it will be reference of first occurrence of t1 to second (as you can see this lists can't be merged) */ TABLE_LIST *correspondent_table; /** @brief Normally, this field is non-null for anonymous derived tables only. @details This field is set to non-null for - Anonymous derived tables, In this case it points to the SELECT_LEX_UNIT representing the derived table. E.g. for a query @verbatim SELECT * FROM (SELECT a FROM t1) b @endverbatim For the @c TABLE_LIST representing the derived table @c b, @c derived points to the SELECT_LEX_UNIT representing the result of the query within parenteses. - Views. This is set for views with @verbatim ALGORITHM = TEMPTABLE @endverbatim by mysql_make_view(). @note Inside views, a subquery in the @c FROM clause is not allowed. @note Do not use this field to separate views/base tables/anonymous derived tables. Use TABLE_LIST::is_anonymous_derived_table(). */ st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ With_element *with; /* With element defining this table (if any) */ /* Bitmap of the defining with element */ table_map with_internal_reference_map; TABLE_LIST * next_with_rec_ref; bool is_derived_with_recursive_reference; bool block_handle_derived; /* The interface employed to materialize the table by a foreign engine */ derived_handler *dt_handler; /* The object used to organize execution of the query that specifies the derived table by a foreign engine */ Pushdown_derived *pushdown_derived; ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; /* True when the view field translation table is used to convert schema table fields for backwards compatibility with SHOW command. */ bool schema_table_reformed; TMP_TABLE_PARAM *schema_table_param; /* link to select_lex where this table was used */ st_select_lex *select_lex; LEX *view; /* link on VIEW lex for merging */ Field_translator *field_translation; /* array of VIEW fields */ /* pointer to element after last one in translation table above */ Field_translator *field_translation_end; bool field_translation_updated; /* List (based on next_local) of underlying tables of this view. I.e. it does not include the tables of subqueries used in the view. Is set only for merged views. */ TABLE_LIST *merge_underlying_list; /* - 0 for base tables - in case of the view it is the list of all (not only underlying tables but also used in subquery ones) tables of the view. */ List<TABLE_LIST> *view_tables; /* most upper view this table belongs to */ TABLE_LIST *belong_to_view; /* A merged derived table this table belongs to */ TABLE_LIST *belong_to_derived; /* The view directly referencing this table (non-zero only for merged underlying tables of a view). */ TABLE_LIST *referencing_view; table_map view_used_tables; table_map map_exec; /* TODO: check if this can be joined with jtbm_table_no */ uint tablenr_exec; uint maybe_null_exec; /* Ptr to parent MERGE table list item. See top comment in ha_myisammrg.cc */ TABLE_LIST *parent_l; /* Security context (non-zero only for tables which belong to view with SQL SECURITY DEFINER) */ Security_context *security_ctx; uchar tabledef_version_buf[MY_UUID_SIZE > MICROSECOND_TIMESTAMP_BUFFER_SIZE-1 ? MY_UUID_SIZE + 1 : MICROSECOND_TIMESTAMP_BUFFER_SIZE]; LEX_CUSTRING tabledef_version; /* This view security context (non-zero only for views with SQL SECURITY DEFINER) */ Security_context *view_sctx; bool allowed_show; Item *where; /* VIEW WHERE clause condition */ Item *check_option; /* WITH CHECK OPTION condition */ LEX_STRING select_stmt; /* text of (CREATE/SELECT) statement */ LEX_CSTRING md5; /* md5 of query text */ LEX_CSTRING source; /* source of CREATE VIEW */ LEX_CSTRING view_db; /* saved view database */ LEX_CSTRING view_name; /* saved view name */ LEX_STRING hr_timestamp; /* time stamp of last operation */ LEX_USER definer; /* definer of view */ ulonglong file_version; /* version of file's field set */ ulonglong mariadb_version; /* version of server on creation */ ulonglong updatable_view; /* VIEW can be updated */ /** @brief The declared algorithm, if this is a view. @details One of - VIEW_ALGORITHM_UNDEFINED - VIEW_ALGORITHM_TMPTABLE - VIEW_ALGORITHM_MERGE @to do Replace with an enum */ ulonglong algorithm; ulonglong view_suid; /* view is suid (TRUE dy default) */ ulonglong with_check; /* WITH CHECK OPTION */ /* effective value of WITH CHECK OPTION (differ for temporary table algorithm) */ uint8 effective_with_check; /** @brief The view algorithm that is actually used, if this is a view. @details One of - VIEW_ALGORITHM_UNDEFINED - VIEW_ALGORITHM_TMPTABLE - VIEW_ALGORITHM_MERGE @to do Replace with an enum */ uint8 derived_type; GRANT_INFO grant; /* data need by some engines in query cache*/ ulonglong engine_data; /* call back function for asking handler about caching in query cache */ qc_engine_callback callback_func; thr_lock_type lock_type; /* Two fields below are set during parsing this table reference in the cases when the table reference can be potentially a reference to a CTE table. In this cases the fact that the reference is a reference to a CTE or not will be ascertained at the very end of parsing of the query when referencies to CTE are resolved. For references to CTE and to derived tables no mdl requests are needed while for other table references they are. If a request is possibly postponed the info that allows to issue this request must be saved in 'mdl_type' and 'table_options'. */ enum_mdl_type mdl_type; ulong table_options; uint outer_join; /* Which join type */ uint shared; /* Used in multi-upd */ bool updatable; /* VIEW/TABLE can be updated now */ bool straight; /* optimize with prev table */ bool updating; /* for replicate-do/ignore table */ bool ignore_leaves; /* preload only non-leaf nodes */ bool crashed; /* Table was found crashed */ bool skip_locked; /* Skip locked in view defination */ table_map dep_tables; /* tables the table depends on */ table_map on_expr_dep_tables; /* tables on expression depends on */ struct st_nested_join *nested_join; /* if the element is a nested join */ TABLE_LIST *embedding; /* nested join containing the table */ List<TABLE_LIST> *join_list;/* join list the table belongs to */ bool lifted; /* set to true when the table is moved to the upper level at the parsing stage */ bool cacheable_table; /* stop PS caching */ /* used in multi-upd/views privilege check */ bool table_in_first_from_clause; /** Specifies which kind of table should be open for this element of table list. */ enum enum_open_type open_type; /* TRUE if this merged view contain auto_increment field */ bool contain_auto_increment; bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */ /* view where processed */ bool where_processed; /* TRUE <=> VIEW CHECK OPTION expression has been processed */ bool check_option_processed; /* TABLE_TYPE_UNKNOWN if any type is acceptable */ Table_type required_type; handlerton *db_type; /* table_type for handler */ char timestamp_buffer[MICROSECOND_TIMESTAMP_BUFFER_SIZE]; /* This TABLE_LIST object is just placeholder for prelocking, it will be used for implicit LOCK TABLES only and won't be used in real statement. */ prelocking_types prelocking_placeholder; /** Indicates that if TABLE_LIST object corresponds to the table/view which requires special handling. */ enum enum_open_strategy { /* Normal open. */ OPEN_NORMAL= 0, /* Associate a table share only if the table exists. */ OPEN_IF_EXISTS, /* Don't associate a table share. */ OPEN_STUB } open_strategy; /** TRUE if an alias for this table was specified in the SQL. */ bool is_alias; /** TRUE if the table is referred to in the statement using a fully qualified name (<db_name>.<table_name>). */ bool is_fqtn; /* TRUE <=> derived table should be filled right after optimization. */ bool fill_me; /* TRUE <=> view/DT is merged. */ /* TODO: replace with derived_type */ bool merged; bool merged_for_insert; bool sequence; /* Part of NEXTVAL/CURVAL/LASTVAL */ /* Protect single thread from repeating partition auto-create over multiple share instances (as the share is closed on backoff action). Skips auto-create only for one given query id. */ query_id_t vers_skip_create; /* Items created by create_view_field and collected to change them in case of materialization of the view/derived table */ List<Item> used_items; /* Sublist (tail) of persistent used_items */ List<Item> persistent_used_items; /* View creation context. */ View_creation_ctx *view_creation_ctx; /* Attributes to save/load view creation context in/from frm-file. Ther are required only to be able to use existing parser to load view-definition file. As soon as the parser parsed the file, view creation context is initialized and the attributes become redundant. These attributes MUST NOT be used for any purposes but the parsing. */ LEX_CSTRING view_client_cs_name; LEX_CSTRING view_connection_cl_name; /* View definition (SELECT-statement) in the UTF-form. */ LEX_CSTRING view_body_utf8; /* End of view definition context. */ /** Indicates what triggers we need to pre-load for this TABLE_LIST when opening an associated TABLE. This is filled after the parsed tree is created. slave_fk_event_map is filled on the slave side with bitmaps value representing row-based event operation to help find and prelock possible FK constrain-related child tables. */ uint8 trg_event_map, slave_fk_event_map; /* TRUE <=> this table is a const one and was optimized away. */ bool optimized_away; /** TRUE <=> already materialized. Valid only for materialized derived tables/views. */ bool materialized; /* I_S: Flags to open_table (e.g. OPEN_TABLE_ONLY or OPEN_VIEW_ONLY) */ uint i_s_requested_object; bool prohibit_cond_pushdown; /* I_S: how to read the tables (SKIP_OPEN_TABLE/OPEN_FRM_ONLY/OPEN_FULL_TABLE) */ uint table_open_method; /* I_S: where the schema table was filled (this is a hack. The code should be able to figure out whether reading from I_S should be done by create_sort_index() or by JOIN::exec.) */ enum enum_schema_table_state schema_table_state; /* Something like a "query plan" for reading INFORMATION_SCHEMA table */ IS_table_read_plan *is_table_read_plan; MDL_request mdl_request; #ifdef WITH_PARTITION_STORAGE_ENGINE /* List to carry partition names from PARTITION (...) clause in statement */ List<String> *partition_names; #endif /* WITH_PARTITION_STORAGE_ENGINE */ void calc_md5(char *buffer); int view_check_option(THD *thd, bool ignore_failure); bool create_field_translation(THD *thd); bool setup_underlying(THD *thd); void cleanup_items(); bool placeholder() { return derived || view || schema_table || !table || table_function; } void print(THD *thd, table_map eliminated_tables, String *str, enum_query_type query_type); void print_leaf_tables(THD *thd, String *str, enum_query_type query_type); bool check_single_table(TABLE_LIST **table, table_map map, TABLE_LIST *view); bool set_insert_values(MEM_ROOT *mem_root); void replace_view_error_with_generic(THD *thd); TABLE_LIST *find_underlying_table(TABLE *table); TABLE_LIST *first_leaf_for_name_resolution(); TABLE_LIST *last_leaf_for_name_resolution(); /* System Versioning */ vers_select_conds_t vers_conditions; vers_select_conds_t period_conditions; bool has_period() const { return period_conditions.is_set(); } my_bool for_insert_data; /** @brief Find the bottom in the chain of embedded table VIEWs. @detail This is used for single-table UPDATE/DELETE when they are modifying a single-table VIEW. */ TABLE_LIST *find_table_for_update() { TABLE_LIST *tbl= this; while(!tbl->is_multitable() && tbl->single_table_updatable() && tbl->merge_underlying_list) { tbl= tbl->merge_underlying_list; } return tbl; } TABLE *get_real_join_table(); bool is_leaf_for_name_resolution(); inline TABLE_LIST *top_table() { return belong_to_view ? belong_to_view : this; } inline bool prepare_check_option(THD *thd) { bool res= FALSE; if (effective_with_check) res= prep_check_option(thd, effective_with_check); return res; } inline bool prepare_where(THD *thd, Item **conds, bool no_where_clause) { if (!view || is_merged_derived()) return prep_where(thd, conds, no_where_clause); return FALSE; } void register_want_access(privilege_t want_access); bool prepare_security(THD *thd); #ifndef NO_EMBEDDED_ACCESS_CHECKS Security_context *find_view_security_context(THD *thd); bool prepare_view_security_context(THD *thd, bool upgrade_check); #endif /* Cleanup for re-execution in a prepared statement or a stored procedure. */ void reinit_before_use(THD *thd); Item_subselect *containing_subselect(); /* Compiles the tagged hints list and fills up TABLE::keys_in_use_for_query, TABLE::keys_in_use_for_group_by, TABLE::keys_in_use_for_order_by, TABLE::force_index and TABLE::covering_keys. */ bool process_index_hints(TABLE *table); bool is_the_same_definition(THD *thd, TABLE_SHARE *s); /** Record the value of metadata version of the corresponding table definition cache element in this parse tree node. @sa check_and_update_table_version() */ inline void set_table_ref_id(TABLE_SHARE *s) { set_table_ref_id(s->get_table_ref_type(), s->get_table_ref_version()); } inline void set_table_ref_id(enum_table_ref_type table_ref_type_arg, ulonglong table_ref_version_arg) { m_table_ref_type= table_ref_type_arg; m_table_ref_version= table_ref_version_arg; } void set_table_id(TABLE_SHARE *s) { set_table_ref_id(s); set_tabledef_version(s); } void set_tabledef_version(TABLE_SHARE *s) { if (!tabledef_version.length && s->tabledef_version.length) { DBUG_ASSERT(s->tabledef_version.length < sizeof(tabledef_version_buf)); tabledef_version.str= tabledef_version_buf; memcpy(tabledef_version_buf, s->tabledef_version.str, (tabledef_version.length= s->tabledef_version.length)); // safety tabledef_version_buf[tabledef_version.length]= 0; } } /* Set of functions returning/setting state of a derived table/view. */ bool is_non_derived() const { return (!derived_type); } bool is_view_or_derived() const { return derived_type; } bool is_view() const { return (derived_type & DTYPE_VIEW); } bool is_derived() const { return (derived_type & DTYPE_TABLE); } bool is_with_table(); bool is_recursive_with_table(); bool is_with_table_recursive_reference(); void register_as_derived_with_rec_ref(With_element *rec_elem); bool is_nonrecursive_derived_with_rec_ref(); bool fill_recursive(THD *thd); inline void set_view() { derived_type= DTYPE_VIEW; } inline void set_derived() { derived_type= DTYPE_TABLE; } bool is_merged_derived() const { return (derived_type & DTYPE_MERGE); } inline void set_merged_derived() { DBUG_ENTER("set_merged_derived"); DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (alias.str ? alias.str : "<NULL>"), get_unit())); derived_type= static_cast<uint8>((derived_type & DTYPE_MASK) | DTYPE_MERGE); set_check_merged(); DBUG_VOID_RETURN; } bool is_materialized_derived() const { return (derived_type & DTYPE_MATERIALIZE); } void set_materialized_derived() { DBUG_ENTER("set_materialized_derived"); DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (alias.str ? alias.str : "<NULL>"), get_unit())); derived_type= static_cast<uint8>((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) | DTYPE_MATERIALIZE); set_check_materialized(); DBUG_VOID_RETURN; } bool is_multitable() const { return (derived_type & DTYPE_MULTITABLE); } inline void set_multitable() { derived_type|= DTYPE_MULTITABLE; } bool set_as_with_table(THD *thd, With_element *with_elem); void reset_const_table(); bool handle_derived(LEX *lex, uint phases); /** @brief True if this TABLE_LIST represents an anonymous derived table, i.e. the result of a subquery. */ bool is_anonymous_derived_table() const { return derived && !view; } /** @brief Returns the name of the database that the referenced table belongs to. */ const LEX_CSTRING get_db_name() const { return view != NULL ? view_db : db; } /** @brief Returns the name of the table that this TABLE_LIST represents. @details The unqualified table name or view name for a table or view, respectively. */ const LEX_CSTRING get_table_name() const { return view != NULL ? view_name : table_name; } bool is_active_sjm(); bool is_sjm_scan_table(); bool is_jtbm() { return MY_TEST(jtbm_subselect != NULL); } bool is_pure_alias() const; st_select_lex_unit *get_unit(); st_select_lex *get_single_select(); void wrap_into_nested_join(List<TABLE_LIST> &join_list); bool init_derived(THD *thd, bool init_view); int fetch_number_of_rows(); bool change_refs_to_fields(); bool single_table_updatable(); bool is_inner_table_of_outer_join() { for (TABLE_LIST *tbl= this; tbl; tbl= tbl->embedding) { if (tbl->outer_join) return true; } return false; } void set_lock_type(THD* thd, enum thr_lock_type lock); derived_handler *find_derived_handler(THD *thd); TABLE_LIST *get_first_table(); void remove_join_columns() { if (join_columns) { join_columns->empty(); join_columns= NULL; is_join_columns_complete= FALSE; } } inline void set_view_def_version(LEX_STRING *version) { m_table_ref_type= TABLE_REF_VIEW; tabledef_version.str= (const uchar *) version->str; tabledef_version.length= version->length; } private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); void set_check_materialized(); #ifndef DBUG_OFF void set_check_merged(); #else inline void set_check_merged() {} #endif /** See comments for set_table_ref_id() */ enum enum_table_ref_type m_table_ref_type; /** See comments for set_table_ref_id() */ ulonglong m_table_ref_version; }; #define ERROR_TABLE ((TABLE_LIST*) 0x1) class Item; /* Iterator over the fields of a generic table reference. */ class Field_iterator: public Sql_alloc { public: Field_iterator() = default; /* Remove gcc warning */ virtual ~Field_iterator() = default; virtual void set(TABLE_LIST *)= 0; virtual void next()= 0; virtual bool end_of_fields()= 0; /* Return 1 at end of list */ virtual LEX_CSTRING *name()= 0; virtual Item *create_item(THD *)= 0; virtual Field *field()= 0; }; /* Iterator over the fields of a base table, view with temporary table, or subquery. */ class Field_iterator_table: public Field_iterator { Field **ptr; public: Field_iterator_table() :ptr(0) {} void set(TABLE_LIST *table) override { ptr= table->table->field; } void set_table(TABLE *table) { ptr= table->field; } void next() override { ptr++; } bool end_of_fields() override { return *ptr == 0; } LEX_CSTRING *name() override; Item *create_item(THD *thd) override; Field *field() override { return *ptr; } }; /* Iterator over the fields of a merge view. */ class Field_iterator_view: public Field_iterator { Field_translator *ptr, *array_end; TABLE_LIST *view; public: Field_iterator_view() :ptr(0), array_end(0) {} void set(TABLE_LIST *table) override; void next() override { ptr++; } bool end_of_fields() override { return ptr == array_end; } LEX_CSTRING *name() override; Item *create_item(THD *thd) override; Item **item_ptr() {return &ptr->item; } Field *field() override { return 0; } inline Item *item() { return ptr->item; } Field_translator *field_translator() { return ptr; } }; /* Field_iterator interface to the list of materialized fields of a NATURAL/USING join. */ class Field_iterator_natural_join: public Field_iterator { List_iterator_fast<Natural_join_column> column_ref_it; Natural_join_column *cur_column_ref; public: Field_iterator_natural_join() :cur_column_ref(NULL) {} ~Field_iterator_natural_join() = default; void set(TABLE_LIST *table) override; void next() override; bool end_of_fields() override { return !cur_column_ref; } LEX_CSTRING *name() override { return cur_column_ref->name(); } Item *create_item(THD *thd) override { return cur_column_ref->create_item(thd); } Field *field() override { return cur_column_ref->field(); } Natural_join_column *column_ref() { return cur_column_ref; } }; /* Generic iterator over the fields of an arbitrary table reference. DESCRIPTION This class unifies the various ways of iterating over the columns of a table reference depending on the type of SQL entity it represents. If such an entity represents a nested table reference, this iterator encapsulates the iteration over the columns of the members of the table reference. IMPLEMENTATION The implementation assumes that all underlying NATURAL/USING table references already contain their result columns and are linked into the list TABLE_LIST::next_name_resolution_table. */ class Field_iterator_table_ref: public Field_iterator { TABLE_LIST *table_ref, *first_leaf, *last_leaf; Field_iterator_table table_field_it; Field_iterator_view view_field_it; Field_iterator_natural_join natural_join_it; Field_iterator *field_it; void set_field_iterator(); public: Field_iterator_table_ref() :field_it(NULL) {} void set(TABLE_LIST *table) override; void next() override; bool end_of_fields() override { return (table_ref == last_leaf && field_it->end_of_fields()); } LEX_CSTRING *name() override { return field_it->name(); } const char *get_table_name(); const char *get_db_name(); GRANT_INFO *grant(); Item *create_item(THD *thd) override { return field_it->create_item(thd); } Field *field() override { return field_it->field(); } Natural_join_column *get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref); Natural_join_column *get_natural_column_ref(); }; #define JOIN_OP_NEST 1 #define REBALANCED_NEST 2 typedef struct st_nested_join { List<TABLE_LIST> join_list; /* list of elements in the nested join */ /* Currently the valid values for nest type are: JOIN_OP_NEST - for nest created for JOIN operation used as an operand in a join expression, contains 2 elements; JOIN_OP_NEST | REBALANCED_NEST - nest created after tree re-balancing in st_select_lex::add_cross_joined_table(), contains 1 element; 0 - for all other nests. Examples: 1. SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a; Here the nest created for LEFT JOIN at first has nest_type==JOIN_OP_NEST. After re-balancing in st_select_lex::add_cross_joined_table() this nest has nest_type==JOIN_OP_NEST | REBALANCED_NEST. The nest for JOIN created in st_select_lex::add_cross_joined_table() has nest_type== JOIN_OP_NEST. 2. SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) Here the nest created for LEFT JOIN has nest_type==0, because it's not an operand in a join expression. The nest created for JOIN has nest_type set to JOIN_OP_NEST. */ uint nest_type; /* Bitmap of tables within this nested join (including those embedded within its children), including tables removed by table elimination. */ table_map used_tables; table_map not_null_tables; /* tables that rejects nulls */ /** Used for pointing out the first table in the plan being covered by this join nest. It is used exclusively within make_outerjoin_info(). */ struct st_join_table *first_nested; /* Used to count tables in the nested join in 2 isolated places: 1. In make_outerjoin_info(). 2. check_interleaving_with_nj/restore_prev_nj_state (these are called by the join optimizer. Before each use the counters are zeroed by reset_nj_counters. */ uint counter; /* Number of elements in join_list that participate in the join plan choice: - Base tables that were not removed by table elimination - Join nests that were not removed by mark_join_nest_as_const */ uint n_tables; nested_join_map nj_map; /* Bit used to identify this nested join*/ /* (Valid only for semi-join nests) Bitmap of tables outside the semi-join that are used within the semi-join's ON condition. */ table_map sj_depends_on; /* Outer non-trivially correlated tables */ table_map sj_corr_tables; table_map direct_children_map; List<Item_ptr> sj_outer_expr_list; /** True if this join nest node is completely covered by the query execution plan. This means two things. 1. All tables on its @c join_list are covered by the plan. 2. All child join nest nodes are fully covered. */ bool is_fully_covered() const { return n_tables == counter; } } NESTED_JOIN; typedef struct st_changed_table_list { struct st_changed_table_list *next; char *key; size_t key_length; } CHANGED_TABLE_LIST; typedef struct st_open_table_list{ struct st_open_table_list *next; char *db,*table; uint32 in_use,locked; } OPEN_TABLE_LIST; static inline MY_BITMAP *tmp_use_all_columns(TABLE *table, MY_BITMAP **bitmap) { MY_BITMAP *old= *bitmap; *bitmap= &table->s->all_set; return old; } static inline void tmp_restore_column_map(MY_BITMAP **bitmap, MY_BITMAP *old) { *bitmap= old; } /* The following is only needed for debugging */ static inline MY_BITMAP *dbug_tmp_use_all_columns(TABLE *table, MY_BITMAP **bitmap) { #ifdef DBUG_ASSERT_EXISTS return tmp_use_all_columns(table, bitmap); #else return 0; #endif } static inline void dbug_tmp_restore_column_map(MY_BITMAP **bitmap, MY_BITMAP *old) { #ifdef DBUG_ASSERT_EXISTS tmp_restore_column_map(bitmap, old); #endif } /* Variant of the above : handle both read and write sets. Provide for the possiblity of the read set being the same as the write set */ static inline void dbug_tmp_use_all_columns(TABLE *table, MY_BITMAP **save, MY_BITMAP **read_set, MY_BITMAP **write_set) { #ifdef DBUG_ASSERT_EXISTS save[0]= *read_set; save[1]= *write_set; (void) tmp_use_all_columns(table, read_set); (void) tmp_use_all_columns(table, write_set); #endif } static inline void dbug_tmp_restore_column_maps(MY_BITMAP **read_set, MY_BITMAP **write_set, MY_BITMAP **old) { #ifdef DBUG_ASSERT_EXISTS tmp_restore_column_map(read_set, old[0]); tmp_restore_column_map(write_set, old[1]); #endif } enum get_table_share_flags { GTS_TABLE = 1, GTS_VIEW = 2, GTS_NOLOCK = 4, GTS_USE_DISCOVERY = 8, GTS_FORCE_DISCOVERY = 16 }; size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data); void init_mdl_requests(TABLE_LIST *table_list); enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, const LEX_CSTRING *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table, List<String> *partitions_to_open= NULL); bool copy_keys_from_share(TABLE *outparam, MEM_ROOT *root); bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, bool *error_reported, vcol_init_mode expr); TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, const char *key, uint key_length); void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, uint key_length, const char *table_name, const char *path); void free_table_share(TABLE_SHARE *share); enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags = GTS_TABLE); void open_table_error(TABLE_SHARE *share, enum open_frm_error error, int db_errno); void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); bool check_column_name(const Lex_ident &name); bool check_table_name(const char *name, size_t length, bool check_for_path_chars); int rename_file_ext(const char * from,const char * to,const char * ext); char *get_field(MEM_ROOT *mem, Field *field); bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, uint err_code, const char *name); int closefrm(TABLE *table); void free_blobs(TABLE *table); void free_field_buffers_larger_than(TABLE *table, uint32 size); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); void append_unescaped(String *res, const char *pos, size_t length); void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo, HA_CREATE_INFO *create_info, uint keys, KEY *key_info); const char *fn_frm_ext(const char *name); /* Check that the integer is in the internal */ static inline int set_zone(int nr,int min_zone,int max_zone) { if (nr <= min_zone) return min_zone; if (nr >= max_zone) return max_zone; return nr; } /* performance schema */ extern Lex_ident_db PERFORMANCE_SCHEMA_DB_NAME; extern Lex_ident_table GENERAL_LOG_NAME; extern Lex_ident_table SLOW_LOG_NAME; extern Lex_ident_table TRANSACTION_REG_NAME; /* information schema */ extern Lex_ident_db INFORMATION_SCHEMA_NAME; extern Lex_ident_db MYSQL_SCHEMA_NAME; /* table names */ extern Lex_ident_table MYSQL_PROC_NAME; inline bool is_infoschema_db(const LEX_CSTRING *name) { return lex_string_eq(&INFORMATION_SCHEMA_NAME, name); } inline bool is_perfschema_db(const LEX_CSTRING *name) { return lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, name); } inline void mark_as_null_row(TABLE *table) { table->null_row=1; table->status|=STATUS_NULL_ROW; if (table->s->null_bytes) bfill(table->null_flags,table->s->null_bytes,255); } /* Restore table to state before mark_as_null_row() call. This assumes that the caller has restored table->null_flags, as is done in unclear_tables(). */ inline void unmark_as_null_row(TABLE *table) { table->null_row= 0; table->status&= ~STATUS_NULL_ROW; } bool is_simple_order(ORDER *order); class Open_tables_backup; /** Transaction Registry Table (TRT) This table holds transaction IDs, their corresponding times and other transaction-related data which is used for transaction order resolution. When versioned table marks its records lifetime with transaction IDs, TRT is used to get their actual timestamps. */ class TR_table: public TABLE_LIST { THD *thd; Open_tables_backup *open_tables_backup; public: enum field_id_t { FLD_TRX_ID= 0, FLD_COMMIT_ID, FLD_BEGIN_TS, FLD_COMMIT_TS, FLD_ISO_LEVEL, FIELD_COUNT }; enum enabled {NO, MAYBE, YES}; static enum enabled use_transaction_registry; /** @param[in,out] Thread handle @param[in] Current transaction is read-write. */ TR_table(THD *_thd, bool rw= false); /** Opens a transaction_registry table. @retval true on error, false otherwise. */ bool open(); ~TR_table(); /** @retval current thd */ THD *get_thd() const { return thd; } /** Stores value to internal transaction_registry TABLE object. @param[in] field number in a TABLE @param[in] value to store */ void store(uint field_id, ulonglong val); /** Stores value to internal transaction_registry TABLE object. @param[in] field number in a TABLE @param[in] value to store */ void store(uint field_id, timeval ts); /** Update the transaction_registry right before commit. @param start_id transaction identifier at start @param end_id transaction identifier at commit @retval false on success @retval true on error (the transaction must be rolled back) */ bool update(ulonglong start_id, ulonglong end_id); // return true if found; false if not found or error bool query(ulonglong trx_id); /** Gets a row from transaction_registry with the closest commit_timestamp to first argument. We can search for a value which a lesser or greater than first argument. Also loads a row into an internal TABLE object. @param[in] timestamp @param[in] true if we search for a lesser timestamp, false if greater @retval true if exists, false it not exists or an error occurred */ bool query(MYSQL_TIME &commit_time, bool backwards); /** Checks whether transaction1 sees transaction0. @param[out] true if transaction1 sees transaction0, undefined on error and when transaction1=transaction0 and false otherwise @param[in] transaction_id of transaction1 @param[in] transaction_id of transaction0 @param[in] commit time of transaction1 or 0 if we want it to be queried @param[in] isolation level (from handler.h) of transaction1 @param[in] commit time of transaction0 or 0 if we want it to be queried @retval true on error, false otherwise */ bool query_sees(bool &result, ulonglong trx_id1, ulonglong trx_id0, ulonglong commit_id1= 0, enum_tx_isolation iso_level1= ISO_READ_UNCOMMITTED, ulonglong commit_id0= 0); /** @retval transaction isolation level of a row from internal TABLE object. */ enum_tx_isolation iso_level() const; /** Stores transactioin isolation level to internal TABLE object. */ void store_iso_level(enum_tx_isolation iso_level) { DBUG_ASSERT(iso_level <= ISO_SERIALIZABLE); store(FLD_ISO_LEVEL, iso_level + 1); } /** Writes a message to MariaDB log about incorrect transaction_registry schema. @param[in] a message explained what's incorrect in schema */ void warn_schema_incorrect(const char *reason); /** Checks whether transaction_registry table has a correct schema. @retval true if schema is incorrect and false otherwise */ bool check(bool error); TABLE * operator-> () const { return table; } Field * operator[] (uint field_id) const { DBUG_ASSERT(field_id < FIELD_COUNT); return table->field[field_id]; } operator bool () const { return table; } bool operator== (const TABLE_LIST &subj) const { return (!cmp(&db, &subj.db) && !cmp(&table_name, &subj.table_name)); } bool operator!= (const TABLE_LIST &subj) const { return !(*this == subj); } }; #endif /* MYSQL_CLIENT */ #endif /* TABLE_INCLUDED */ sql_derived.h 0000644 00000002411 15156036157 0007225 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DERIVED_INCLUDED #define SQL_DERIVED_INCLUDED struct TABLE_LIST; class THD; struct LEX; bool mysql_handle_derived(LEX *lex, uint phases); bool mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases); Item *transform_condition_or_part(THD *thd, Item *cond, Item_transformer transformer, uchar *arg); bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived); #endif /* SQL_DERIVED_INCLUDED */ my_md5.h 0000644 00000002716 15156036157 0006126 0 ustar 00 #ifndef MY_MD5_INCLUDED #define MY_MD5_INCLUDED /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2013 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "m_string.h" #define MD5_HASH_SIZE 16 /* Hash size in bytes */ /* Wrapper function for MD5 implementation. */ #ifdef __cplusplus extern "C" { #endif #define compute_md5_hash(A,B,C) my_md5(A,B,C) /* Convert an array of bytes to a hexadecimal representation. Used to generate a hexadecimal representation of a message digest. */ static inline void array_to_hex(char *to, const unsigned char *str, uint len) { const unsigned char *str_end= str + len; for (; str != str_end; ++str) { *to++= _dig_vec_lower[((uchar) *str) >> 4]; *to++= _dig_vec_lower[((uchar) *str) & 0x0F]; } } #ifdef __cplusplus } #endif #endif /* MY_MD5_INCLUDED */ my_bitmap.h 0000644 00000012576 15156036157 0006722 0 ustar 00 /* Copyright (c) 2001, 2011, Oracle and/or its affiliates. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_bitmap_h_ #define _my_bitmap_h_ #define MY_BIT_NONE (~(uint) 0) #include <m_string.h> #include <my_pthread.h> typedef ulonglong my_bitmap_map; typedef struct st_bitmap { my_bitmap_map *bitmap; my_bitmap_map *last_word_ptr; my_bitmap_map last_bit_mask; uint32 n_bits; /* number of bits occupied by the above */ my_bool bitmap_allocated; } MY_BITMAP; #ifdef __cplusplus extern "C" { #endif /* Reset memory. Faster then doing a full bzero */ #define my_bitmap_clear(A) ((A)->bitmap= 0) extern void create_last_bit_mask(MY_BITMAP *map); extern my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits); extern my_bool bitmap_is_clear_all(const MY_BITMAP *map); extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size); extern my_bool bitmap_is_set_all(const MY_BITMAP *map); extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2); extern my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2); extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2); extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array, uint bitmap_count, uint start_bit, uint end_bit); extern uint bitmap_set_next(MY_BITMAP *map); extern uint bitmap_get_first_clear(const MY_BITMAP *map); extern uint bitmap_get_first_set(const MY_BITMAP *map); extern uint bitmap_bits_set(const MY_BITMAP *map); extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit); extern void my_bitmap_free(MY_BITMAP *map); extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit); extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size); extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_invert(MY_BITMAP *map); extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); /* Functions to export/import bitmaps to an architecture independent format */ extern void bitmap_export(uchar *to, MY_BITMAP *map); extern void bitmap_import(MY_BITMAP *map, uchar *from); #define my_bitmap_map_bytes sizeof(my_bitmap_map) #define my_bitmap_map_bits (my_bitmap_map_bytes*8) /* Size in bytes to store 'bits' number of bits */ #define bitmap_buffer_size(bits) (MY_ALIGN((bits), my_bitmap_map_bits)/8) #define my_bitmap_buffer_size(map) bitmap_buffer_size((map)->n_bits) #define no_bytes_in_export_map(map) (((map)->n_bits + 7)/8) #define no_words_in_map(map) (((map)->n_bits + (my_bitmap_map_bits-1))/my_bitmap_map_bits) /* Fast, not thread safe, bitmap functions */ /* The following functions must be compatible with create_last_bit_mask()! */ static inline void bitmap_set_bit(MY_BITMAP *map,uint bit) { DBUG_ASSERT(bit < map->n_bits); map->bitmap[bit/my_bitmap_map_bits]|= (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_flip_bit(MY_BITMAP *map,uint bit) { DBUG_ASSERT(bit < map->n_bits); map->bitmap[bit/my_bitmap_map_bits]^= (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_clear_bit(MY_BITMAP *map,uint bit) { DBUG_ASSERT(bit < map->n_bits); map->bitmap[bit/my_bitmap_map_bits]&= ~(1ULL << (bit & (my_bitmap_map_bits-1))); } static inline uint bitmap_is_set(const MY_BITMAP *map,uint bit) { DBUG_ASSERT(bit < map->n_bits); return (!!(map->bitmap[bit/my_bitmap_map_bits] & (1ULL << (bit & (my_bitmap_map_bits-1))))); } /* Return true if bitmaps are equal */ static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) { DBUG_ASSERT(map1->n_bits == map2->n_bits); return (memcmp(map1->bitmap, map2->bitmap, my_bitmap_buffer_size(map1)) == 0); } #define bitmap_clear_all(MAP) \ { memset((MAP)->bitmap, 0, my_bitmap_buffer_size(MAP)); } static inline void bitmap_set_all(const MY_BITMAP *map) { if (map->n_bits) { memset(map->bitmap, 0xFF, my_bitmap_map_bytes * (no_words_in_map(map)-1)); DBUG_ASSERT(map->bitmap + no_words_in_map(map)-1 == map->last_word_ptr); *map->last_word_ptr= ~map->last_bit_mask; } } #ifdef __cplusplus } #endif #endif /* _my_bitmap_h_ */ create_options.h 0000644 00000010141 15156036157 0007741 0 ustar 00 /* Copyright (C) 2010, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file Engine defined options of tables/fields/keys in CREATE/ALTER TABLE. */ #ifndef SQL_CREATE_OPTIONS_INCLUDED #define SQL_CREATE_OPTIONS_INCLUDED #include "sql_class.h" enum { ENGINE_OPTION_MAX_LENGTH=32767 }; class engine_option_value: public Sql_alloc { public: LEX_CSTRING name; LEX_CSTRING value; engine_option_value *next; ///< parser puts them in a FIFO linked list bool parsed; ///< to detect unrecognized options bool quoted_value; ///< option=VAL vs. option='VAL' engine_option_value(engine_option_value *src) : name(src->name), value(src->value), next(NULL), parsed(src->parsed), quoted_value(src->quoted_value) { } engine_option_value(LEX_CSTRING &name_arg, LEX_CSTRING &value_arg, bool quoted) : name(name_arg), value(value_arg), next(NULL), parsed(false), quoted_value(quoted) { } engine_option_value(LEX_CSTRING &name_arg): name(name_arg), value(null_clex_str), next(NULL), parsed(false), quoted_value(false) { } engine_option_value(LEX_CSTRING &name_arg, ulonglong value_arg, MEM_ROOT *root) : name(name_arg), next(NULL), parsed(false), quoted_value(false) { char *str; if (likely((value.str= str= (char *)alloc_root(root, 22)))) { value.length= longlong10_to_str(value_arg, str, 10) - str; } } static uchar *frm_read(const uchar *buff, const uchar *buff_end, engine_option_value **start, engine_option_value **end, MEM_ROOT *root); void link(engine_option_value **start, engine_option_value **end); uint frm_length(); uchar *frm_image(uchar *buff); }; typedef struct st_key KEY; class Create_field; bool resolve_sysvar_table_options(handlerton *hton); void free_sysvar_table_options(handlerton *hton); bool parse_engine_table_options(THD *thd, handlerton *ht, TABLE_SHARE *share); #ifdef WITH_PARTITION_STORAGE_ENGINE bool parse_engine_part_options(THD *thd, TABLE *table); #endif bool parse_option_list(THD* thd, void *option_struct, engine_option_value **option_list, ha_create_table_option *rules, bool suppress_warning, MEM_ROOT *root); bool extend_option_list(THD* thd, handlerton *hton, bool create, engine_option_value **option_list, ha_create_table_option *rules); bool engine_table_options_frm_read(const uchar *buff, size_t length, TABLE_SHARE *share); bool merge_engine_options(engine_option_value *source, engine_option_value *changes, engine_option_value **out, MEM_ROOT *root); uint engine_table_options_frm_length(engine_option_value *table_option_list, List<Create_field> &create_fields, uint keys, KEY *key_info); uchar *engine_table_options_frm_image(uchar *buff, engine_option_value *table_option_list, List<Create_field> &create_fields, uint keys, KEY *key_info); bool engine_options_differ(void *old_struct, void *new_struct, ha_create_table_option *rules); bool is_engine_option_known(engine_option_value *opt, ha_create_table_option *rules); #endif filesort.h 0000644 00000016210 15156036157 0006555 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef FILESORT_INCLUDED #define FILESORT_INCLUDED #include "my_base.h" /* ha_rows */ #include "sql_alloc.h" #include "filesort_utils.h" class SQL_SELECT; class THD; struct TABLE; class Filesort_tracker; struct SORT_FIELD; struct SORT_FIELD_ATTR; typedef struct st_order ORDER; class JOIN; class Addon_fields; class Sort_keys; /** Sorting related info. To be extended by another WL to include complete filesort implementation. */ class Filesort: public Sql_alloc { public: /** List of expressions to order the table by */ ORDER *order; /** Number of records to return */ ha_rows limit; /** ORDER BY list with some precalculated info for filesort */ SORT_FIELD *sortorder; /* Used with ROWNUM. Contains the number of rows filesort has found so far */ ha_rows *accepted_rows; /** select to use for getting records */ SQL_SELECT *select; /** TRUE <=> free select on destruction */ bool own_select; /** TRUE means we are using Priority Queue for order by with limit. */ bool using_pq; /* TRUE means sort operation must produce table rowids. FALSE means that it also has an option of producing {sort_key, addon_fields} pairs. Usually initialized with value of join_tab->keep_current_rowid to allow for a call to table->file->position() using these table rowids. */ bool sort_positions; /* TRUE means all the fields of table of whose bitmap read_set is set need to be read while reading records in the sort buffer. FALSE otherwise */ bool set_all_read_bits; Filesort_tracker *tracker; Sort_keys *sort_keys; /* Unpack temp table columns to base table columns*/ void (*unpack)(TABLE *); Filesort(ORDER *order_arg, ha_rows limit_arg, bool sort_positions_arg, SQL_SELECT *select_arg): order(order_arg), limit(limit_arg), sortorder(NULL), accepted_rows(0), select(select_arg), own_select(false), using_pq(false), sort_positions(sort_positions_arg), set_all_read_bits(false), sort_keys(NULL), unpack(NULL) { DBUG_ASSERT(order); }; ~Filesort() { cleanup(); } /* Prepare ORDER BY list for sorting. */ Sort_keys* make_sortorder(THD *thd, JOIN *join, table_map first_table_bit); private: void cleanup(); }; class SORT_INFO { /// Buffer for sorting keys. Filesort_buffer filesort_buffer; public: SORT_INFO() :addon_fields(NULL), record_pointers(0), sort_keys(NULL), sorted_result_in_fsbuf(FALSE) { buffpek.str= 0; my_b_clear(&io_cache); } ~SORT_INFO(); void free_data() { close_cached_file(&io_cache); free_addon_buff(); my_free(record_pointers); my_free(buffpek.str); my_free(addon_fields); free_sort_buffer(); } void reset() { free_data(); record_pointers= 0; buffpek.str= 0; addon_fields= 0; sorted_result_in_fsbuf= false; } void free_addon_buff(); IO_CACHE io_cache; /* If sorted through filesort */ LEX_STRING buffpek; /* Buffer for buffpek structures */ Addon_fields *addon_fields; /* Addon field descriptors */ uchar *record_pointers; /* If sorted in memory */ Sort_keys *sort_keys; /* Sort key descriptors*/ /** If the entire result of filesort fits in memory, we skip the merge phase. We may leave the result in filesort_buffer (indicated by sorted_result_in_fsbuf), or we may strip away the sort keys, and copy the sorted result into a new buffer. @see save_index() */ bool sorted_result_in_fsbuf; /* How many rows in final result. Also how many rows in record_pointers, if used */ ha_rows return_rows; ha_rows m_examined_rows; /* How many rows read. Already in thd */ ha_rows found_rows; /* How many rows was accepted */ /** Sort filesort_buffer */ void sort_buffer(Sort_param *param, uint count) { filesort_buffer.sort_buffer(param, count); } uchar **get_sort_keys() { return filesort_buffer.get_sort_keys(); } uchar *get_sorted_record(uint ix) { return filesort_buffer.get_sorted_record(ix); } uchar *alloc_sort_buffer(uint num_records, uint record_length) { return filesort_buffer.alloc_sort_buffer(num_records, record_length); } void free_sort_buffer() { filesort_buffer.free_sort_buffer(); } bool isfull() const { return filesort_buffer.isfull(); } void init_record_pointers() { filesort_buffer.init_record_pointers(); } void init_next_record_pointer() { filesort_buffer.init_next_record_pointer(); } uchar *get_next_record_pointer() { return filesort_buffer.get_next_record_pointer(); } void adjust_next_record_pointer(uint val) { filesort_buffer.adjust_next_record_pointer(val); } Bounds_checked_array<uchar> get_raw_buf() { return filesort_buffer.get_raw_buf(); } size_t sort_buffer_size() const { return filesort_buffer.sort_buffer_size(); } bool is_allocated() const { return filesort_buffer.is_allocated(); } void set_sort_length(uint val) { filesort_buffer.set_sort_length(val); } uint get_sort_length() const { return filesort_buffer.get_sort_length(); } bool has_filesort_result_in_memory() const { return record_pointers || sorted_result_in_fsbuf; } /// Are we using "addon fields"? bool using_addon_fields() const { return addon_fields != NULL; } /// Are we using "packed addon fields"? bool using_packed_addons(); /** Copies (unpacks) values appended to sorted fields from a buffer back to their regular positions specified by the Field::ptr pointers. @param buff Buffer which to unpack the value from */ template<bool Packed_addon_fields> inline void unpack_addon_fields(uchar *buff); bool using_packed_sortkeys(); friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, Filesort_tracker* tracker, JOIN *join, table_map first_table_bit); }; SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, Filesort_tracker* tracker, JOIN *join=NULL, table_map first_table_bit=0); bool filesort_use_addons(TABLE *table, uint sortlength, uint *length, uint *fields, uint *null_fields, uint *m_packable_length); void change_double_for_sort(double nr,uchar *to); void store_length(uchar *to, uint length, uint pack_length); void reverse_key(uchar *to, const SORT_FIELD_ATTR *sort_field); #endif /* FILESORT_INCLUDED */ sql_cache.h 0000644 00000052541 15156036157 0006657 0 ustar 00 /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SQL_CACHE_H #define _SQL_CACHE_H #include "hash.h" #include "my_base.h" /* ha_rows */ class MY_LOCALE; struct TABLE_LIST; class Time_zone; struct LEX; struct TABLE; typedef struct st_changed_table_list CHANGED_TABLE_LIST; /* Query cache */ /* Can't create new free memory block if unused memory in block less then QUERY_CACHE_MIN_ALLOCATION_UNIT. if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automatically */ #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512 /* inittial size of hashes */ #define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024 #define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024 /* minimal result data size when data allocated */ #define QUERY_CACHE_MIN_RESULT_DATA_SIZE (1024*4) /* start estimation of first result block size only when number of queries bigger then: */ #define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3 /* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */ #define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4 #define QUERY_CACHE_MEM_BIN_STEP_PWR2 2 #define QUERY_CACHE_MEM_BIN_PARTS_INC 1 #define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2 #define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3 /* how many free blocks check when finding most suitable before other 'end' of list of free blocks */ #define QUERY_CACHE_MEM_BIN_TRY 5 /* packing parameters */ #define QUERY_CACHE_PACK_ITERATION 2 #define QUERY_CACHE_PACK_LIMIT (512*1024L) #define TABLE_COUNTER_TYPE uint struct Query_cache_block; struct Query_cache_block_table; struct Query_cache_table; struct Query_cache_query; struct Query_cache_result; class Query_cache; struct Query_cache_tls; struct LEX; class THD; typedef my_bool (*qc_engine_callback)(THD *thd, const char *table_key, uint key_length, ulonglong *engine_data); /** This class represents a node in the linked chain of queries belonging to one table. @note The root of this linked list is not a query-type block, but the table- type block which all queries has in common. */ struct Query_cache_block_table { Query_cache_block_table() = default; /* Remove gcc warning */ /** This node holds a position in a static table list belonging to the associated query (base 0). */ TABLE_COUNTER_TYPE n; /** Pointers to the next and previous node, linking all queries with a common table. */ Query_cache_block_table *next, *prev; /** A pointer to the table-type block which all linked queries has in common. */ Query_cache_table *parent; /** A method to calculate the address of the query cache block owning this node. The purpose of this calculation is to make it easier to move the query cache block without having to modify all the pointer addresses. */ inline Query_cache_block *block(); }; struct Query_cache_block { Query_cache_block() = default; /* Remove gcc warning */ enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG, RES_INCOMPLETE, TABLE, INCOMPLETE}; size_t length; // length of all block size_t used; // length of data /* Not used **pprev, **prev because really needed access to pervious block: *pprev to join free blocks *prev to access to opposite side of list in cyclic sorted list */ Query_cache_block *pnext,*pprev, // physical next/previous block *next,*prev; // logical next/previous block block_type type; TABLE_COUNTER_TYPE n_tables; // number of tables in query inline bool is_free(void) { return type == FREE; } void init(size_t length); void destroy(); uint headers_len() const; uchar* data(void) const; Query_cache_query *query(); Query_cache_table *table(); Query_cache_result *result(); Query_cache_block_table *table(TABLE_COUNTER_TYPE n); }; struct Query_cache_query { ulonglong limit_found_rows; mysql_rwlock_t lock; Query_cache_block *res; Query_cache_tls *wri; size_t len; unsigned int last_pkt_nr; uint8 tbls_type; uint8 ready; ulonglong hit_count; Query_cache_query() = default; /* Remove gcc warning */ inline void init_n_lock(); void unlock_n_destroy(); inline ulonglong found_rows() { return limit_found_rows; } inline void found_rows(ulonglong rows) { limit_found_rows= rows; } inline Query_cache_block *result() { return res; } inline void result(Query_cache_block *p) { res= p; } inline Query_cache_tls *writer() { return wri; } inline void writer(Query_cache_tls *p) { wri= p; } inline uint8 tables_type() { return tbls_type; } inline void tables_type(uint8 type) { tbls_type= type; } inline size_t length() { return len; } inline size_t add(size_t packet_len) { return(len+= packet_len); } inline void length(size_t length_arg) { len= length_arg; } inline uchar* query() { return (((uchar*)this) + ALIGN_SIZE(sizeof(Query_cache_query))); } /** following used to check if result ready in plugin without locking rw_lock of the query. */ inline void set_results_ready() { ready= 1; } inline bool is_results_ready() { return ready; } inline void increment_hits() { hit_count++; } inline ulonglong hits() { return hit_count; } void lock_writing(); void lock_reading(); bool try_lock_writing(); void unlock_writing(); void unlock_reading(); }; struct Query_cache_table { Query_cache_table() = default; /* Remove gcc warning */ char *tbl; uint32 key_len; uint8 suffix_len; /* For partitioned tables */ uint8 table_type; /* unique for every engine reference */ qc_engine_callback callback_func; /* data need by some engines */ ulonglong engine_data_buff; /** The number of queries depending of this table. */ int32 m_cached_query_count; /** If table included in the table hash to be found by other queries */ my_bool hashed; inline char *db() { return (char *) data(); } inline char *table() { return tbl; } inline void table(char *table_arg) { tbl= table_arg; } inline uint32 key_length() { return key_len; } inline void key_length(uint32 len) { key_len= len; } inline uint8 suffix_length() { return suffix_len; } inline void suffix_length(uint8 len) { suffix_len= len; } inline uint8 type() { return table_type; } inline void type(uint8 t) { table_type= t; } inline qc_engine_callback callback() { return callback_func; } inline void callback(qc_engine_callback fn){ callback_func= fn; } inline ulonglong engine_data() { return engine_data_buff; } inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; } inline my_bool is_hashed() { return hashed; } inline void set_hashed(my_bool hash) { hashed= hash; } inline uchar* data() { return (uchar*)(((uchar*)this)+ ALIGN_SIZE(sizeof(Query_cache_table))); } }; struct Query_cache_result { Query_cache_result() = default; /* Remove gcc warning */ Query_cache_block *query; inline uchar* data() { return (uchar*)(((uchar*) this)+ ALIGN_SIZE(sizeof(Query_cache_result))); } /* data_continue (if not whole packet contained by this block) */ inline Query_cache_block *parent() { return query; } inline void parent (Query_cache_block *p) { query=p; } }; extern "C" { const uchar *query_cache_query_get_key(const void *record, size_t *length, my_bool); const uchar *query_cache_table_get_key(const void *record, size_t *length, my_bool); } extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); struct Query_cache_memory_bin { Query_cache_memory_bin() = default; /* Remove gcc warning */ #ifndef DBUG_OFF size_t size; #endif uint number; Query_cache_block *free_blocks; inline void init(size_t size_arg) { #ifndef DBUG_OFF size = size_arg; #endif number = 0; free_blocks = 0; } }; struct Query_cache_memory_bin_step { Query_cache_memory_bin_step() = default; /* Remove gcc warning */ size_t size; size_t increment; size_t idx; inline void init(size_t size_arg, size_t idx_arg, size_t increment_arg) { size = size_arg; idx = idx_arg; increment = increment_arg; } }; class Query_cache { public: /* Info */ size_t query_cache_size, query_cache_limit; /* statistics */ size_t free_memory, queries_in_cache, hits, inserts, refused, free_memory_blocks, total_blocks, lowmem_prunes; private: #ifndef DBUG_OFF my_thread_id m_cache_lock_thread_id; #endif mysql_cond_t COND_cache_status_changed; uint m_requests_in_progress; enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED }; Cache_lock_status m_cache_lock_status; enum Cache_staus {OK, DISABLE_REQUEST, DISABLED}; Cache_staus m_cache_status; void free_query_internal(Query_cache_block *point); void invalidate_table_internal(uchar *key, size_t key_length); protected: /* The following mutex is locked when searching or changing global query, tables lists or hashes. When we are operating inside the query structure we locked an internal query block mutex. LOCK SEQUENCE (to prevent deadlocks): 1. structure_guard_mutex 2. query block (for operation inside query (query block/results)) Thread doing cache flush releases the mutex once it sets m_cache_lock_status flag, so other threads may bypass the cache as if it is disabled, not waiting for reset to finish. The exception is other threads that were going to do cache flush---they'll wait till the end of a flush operation. */ mysql_mutex_t structure_guard_mutex; size_t additional_data_size; uchar *cache; // cache memory Query_cache_block *first_block; // physical location block list Query_cache_block *queries_blocks; // query list (LIFO) Query_cache_block *tables_blocks; Query_cache_memory_bin *bins; // free block lists Query_cache_memory_bin_step *steps; // bins spacing info HASH queries, tables; /* options */ size_t min_allocation_unit, min_result_data_size; uint def_query_hash_size, def_table_hash_size; size_t mem_bin_num, mem_bin_steps; // See at init_cache & find_bin bool initialized; /* Exclude/include from cyclic double linked list */ static void double_linked_list_exclude(Query_cache_block *point, Query_cache_block **list_pointer); static void double_linked_list_simple_include(Query_cache_block *point, Query_cache_block ** list_pointer); static void double_linked_list_join(Query_cache_block *head_tail, Query_cache_block *tail_head); /* The following functions require that structure_guard_mutex is locked */ void flush_cache(); my_bool free_old_query(); void free_query(Query_cache_block *point); my_bool allocate_data_chain(Query_cache_block **result_block, size_t data_len, Query_cache_block *query_block, my_bool first_block); void invalidate_table(THD *thd, TABLE_LIST *table); void invalidate_table(THD *thd, TABLE *table); void invalidate_table(THD *thd, uchar *key, size_t key_length); void invalidate_table(THD *thd, Query_cache_block *table_block); void invalidate_query_block_list(Query_cache_block_table *list_root); TABLE_COUNTER_TYPE register_tables_from_list(THD *thd, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE counter, Query_cache_block_table **block_table); my_bool register_all_tables(THD *thd, Query_cache_block *block, TABLE_LIST *tables_used, TABLE_COUNTER_TYPE tables); void unlink_table(Query_cache_block_table *node); Query_cache_block *get_free_block (size_t len, my_bool not_less, size_t min); void free_memory_block(Query_cache_block *point); void split_block(Query_cache_block *block, size_t len); Query_cache_block *join_free_blocks(Query_cache_block *first_block, Query_cache_block *block_in_list); my_bool append_next_free_block(Query_cache_block *block, size_t add_size); void exclude_from_free_memory_list(Query_cache_block *free_block); void insert_into_free_memory_list(Query_cache_block *new_block); my_bool move_by_type(uchar **border, Query_cache_block **before, size_t *gap, Query_cache_block *i); uint find_bin(size_t size); void move_to_query_list_end(Query_cache_block *block); void insert_into_free_memory_sorted_list(Query_cache_block *new_block, Query_cache_block **list); void pack_cache(); void relink(Query_cache_block *oblock, Query_cache_block *nblock, Query_cache_block *next, Query_cache_block *prev, Query_cache_block *pnext, Query_cache_block *pprev); my_bool join_results(size_t join_limit); /* Following function control structure_guard_mutex by themself or don't need structure_guard_mutex */ size_t init_cache(); void make_disabled(); void free_cache(); Query_cache_block *write_block_data(size_t data_len, uchar* data, size_t header_len, Query_cache_block::block_type type, TABLE_COUNTER_TYPE ntab = 0); my_bool append_result_data(Query_cache_block **result, size_t data_len, uchar* data, Query_cache_block *parent); my_bool write_result_data(Query_cache_block **result, size_t data_len, uchar* data, Query_cache_block *parent, Query_cache_block::block_type type=Query_cache_block::RESULT); inline size_t get_min_first_result_data_size(); inline size_t get_min_append_result_data_size(); Query_cache_block *allocate_block(size_t len, my_bool not_less, size_t min); /* If query is cacheable return number tables in query (query without tables not cached) */ TABLE_COUNTER_TYPE is_cacheable(THD *thd, LEX *lex, TABLE_LIST *tables_used, uint8 *tables_type); TABLE_COUNTER_TYPE process_and_count_tables(THD *thd, TABLE_LIST *tables_used, uint8 *tables_type); static my_bool ask_handler_allowance(THD *thd, TABLE_LIST *tables_used); public: Query_cache(size_t query_cache_limit = ULONG_MAX, size_t min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT, size_t min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE, uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); inline bool is_disabled(void) { return m_cache_status != OK; } inline bool is_disable_in_progress(void) { return m_cache_status == DISABLE_REQUEST; } /* initialize cache (mutex) */ void init(); /* resize query cache (return real query size, 0 if disabled) */ size_t resize(size_t query_cache_size); /* set limit on result size */ inline void result_size_limit(size_t limit){query_cache_limit=limit;} /* set minimal result data allocation unit size */ size_t set_min_res_unit(size_t size); /* register query in cache */ void store_query(THD *thd, TABLE_LIST *used_tables); /* Check if the query is in the cache and if this is true send the data to client. */ int send_result_to_client(THD *thd, char *query, uint query_length); /* Remove all queries that uses any of the listed following tables */ void invalidate(THD *thd, TABLE_LIST *tables_used, my_bool using_transactions); void invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used); void invalidate_locked_for_write(THD *thd, TABLE_LIST *tables_used); void invalidate(THD *thd, TABLE *table, my_bool using_transactions); void invalidate(THD *thd, const char *key, size_t key_length, my_bool using_transactions); /* Remove all queries that uses any of the tables in following database */ void invalidate(THD *thd, const LEX_CSTRING &db); /* Remove all queries that uses any of the listed following table */ void invalidate_by_MyISAM_filename(const char *filename); void flush(); void pack(THD *thd, size_t join_limit = QUERY_CACHE_PACK_LIMIT, uint iteration_limit = QUERY_CACHE_PACK_ITERATION); void destroy(); void insert(THD *thd, Query_cache_tls *query_cache_tls, const char *packet, size_t length, unsigned pkt_nr); my_bool insert_table(THD *thd, size_t key_len, const char *key, Query_cache_block_table *node, size_t db_length, uint8 suffix_length_arg, uint8 cache_type, qc_engine_callback callback, ulonglong engine_data, my_bool hash); void end_of_result(THD *thd); void abort(THD *thd, Query_cache_tls *query_cache_tls); /* The following functions are only used when debugging We don't protect these with ifndef DBUG_OFF to not have to recompile everything if we want to add checks of the cache at some places. */ void wreck(uint line, const char *message); void bins_dump(); void cache_dump(); void queries_dump(); void tables_dump(); my_bool check_integrity(bool not_locked); my_bool in_list(Query_cache_block * root, Query_cache_block * point, const char *name); my_bool in_table_list(Query_cache_block_table * root, Query_cache_block_table * point, const char *name); my_bool in_blocks(Query_cache_block * point); /* Table key generation */ static uint filename_2_table_key (char *key, const char *filename, uint32 *db_langth); enum Cache_try_lock_mode {WAIT, TIMEOUT, TRY}; bool try_lock(THD *thd, Cache_try_lock_mode mode= WAIT); void lock(THD *thd); void lock_and_suspend(void); void unlock(void); void disable_query_cache(THD *thd); }; #ifdef HAVE_QUERY_CACHE struct Query_cache_query_flags { unsigned int client_long_flag:1; unsigned int client_protocol_41:1; unsigned int client_extended_metadata:1; unsigned int client_depr_eof:1; unsigned int protocol_type:2; unsigned int more_results_exists:1; unsigned int in_trans:1; unsigned int autocommit:1; unsigned int pkt_nr; uint character_set_client_num; uint character_set_results_num; uint collation_connection_num; uint group_concat_max_len; ha_rows limit; Time_zone *time_zone; sql_mode_t sql_mode; ulonglong max_sort_length; size_t default_week_format; size_t div_precision_increment; MY_LOCALE *lc_time_names; }; #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags) #define QUERY_CACHE_DB_LENGTH_SIZE 2 #include "sql_cache.h" #define query_cache_abort(A,B) query_cache.abort(A,B) #define query_cache_end_of_result(A) query_cache.end_of_result(A) #define query_cache_store_query(A, B) query_cache.store_query(A, B) #define query_cache_destroy() query_cache.destroy() #define query_cache_result_size_limit(A) query_cache.result_size_limit(A) #define query_cache_init() query_cache.init() #define query_cache_resize(A) query_cache.resize(A) #define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A) #define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C) #define query_cache_invalidate1(A, B) query_cache.invalidate(A, B) #define query_cache_send_result_to_client(A, B, C) \ query_cache.send_result_to_client(A, B, C) #define query_cache_invalidate_by_MyISAM_filename_ref \ &query_cache_invalidate_by_MyISAM_filename #define query_cache_invalidate_locked_for_write(A, B) \ query_cache.invalidate_locked_for_write(A, B) /* note the "maybe": it's a read without mutex */ #define query_cache_maybe_disabled(T) \ (T->variables.query_cache_type == 0 || query_cache.query_cache_size == 0) #define query_cache_is_cacheable_query(L) \ (((L)->sql_command == SQLCOM_SELECT) && (L)->safe_to_cache_query) #else #define QUERY_CACHE_FLAGS_SIZE 0 #define query_cache_store_query(A, B) do { } while(0) #define query_cache_destroy() do { } while(0) #define query_cache_result_size_limit(A) do { } while(0) #define query_cache_init() do { } while(0) #define query_cache_resize(A) do { } while(0) #define query_cache_set_min_res_unit(A) do { } while(0) #define query_cache_invalidate3(A, B, C) do { } while(0) #define query_cache_invalidate1(A,B) do { } while(0) #define query_cache_send_result_to_client(A, B, C) 0 #define query_cache_invalidate_by_MyISAM_filename_ref NULL #define query_cache_invalidate_locked_for_write(A, B) do { } while(0) #define query_cache_abort(A,B) do { } while(0) #define query_cache_end_of_result(A) do { } while(0) #define query_cache_maybe_disabled(T) 1 #define query_cache_is_cacheable_query(L) 0 #endif /*HAVE_QUERY_CACHE*/ extern MYSQL_PLUGIN_IMPORT Query_cache query_cache; #endif sql_reload.h 0000644 00000002014 15156036157 0007050 0 ustar 00 #ifndef SQL_RELOAD_INCLUDED #define SQL_RELOAD_INCLUDED /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ class THD; struct TABLE_LIST; bool reload_acl_and_cache(THD *thd, unsigned long long options, TABLE_LIST *tables, int *write_to_binlog); bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables); #endif log.h 0000644 00000146534 15156036160 0005516 0 ustar 00 /* Copyright (c) 2005, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef LOG_H #define LOG_H #include "handler.h" /* my_xid */ #include "rpl_constants.h" class Relay_log_info; class Gtid_index_writer; class Format_description_log_event; class Gtid_log_event; bool reopen_fstreams(const char *filename, FILE *outstream, FILE *errstream); void setup_log_handling(); bool trans_has_updated_trans_table(const THD* thd); bool stmt_has_updated_trans_table(const THD *thd); bool use_trans_cache(const THD* thd, bool is_transactional); bool ending_trans(THD* thd, const bool all); bool ending_single_stmt_trans(THD* thd, const bool all); bool trans_has_updated_non_trans_table(const THD* thd); bool stmt_has_updated_non_trans_table(const THD* thd); /* Transaction Coordinator log - a base abstract class for two different implementations */ class TC_LOG { public: int using_heuristic_recover(); TC_LOG() = default; virtual ~TC_LOG() = default; virtual int open(const char *opt_name)=0; virtual void close()=0; /* Transaction coordinator 2-phase commit. Must invoke the run_prepare_ordered and run_commit_ordered methods, as described below for these methods. In addition, must invoke THD::wait_for_prior_commit(), or equivalent wait, to ensure that one commit waits for another if registered to do so. */ virtual int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) = 0; virtual int unlog(ulong cookie, my_xid xid)=0; virtual int unlog_xa_prepare(THD *thd, bool all)= 0; virtual void commit_checkpoint_notify(void *cookie)= 0; protected: /* These methods are meant to be invoked from log_and_order() implementations to run any prepare_ordered() respectively commit_ordered() methods in participating handlers. They must be called using suitable thread syncronisation to ensure that they are each called in the correct commit order among all transactions. However, it is only necessary to call them if the corresponding flag passed to log_and_order is set (it is safe, but not required, to call them when the flag is false). The caller must be holding LOCK_prepare_ordered respectively LOCK_commit_ordered when calling these methods. */ void run_prepare_ordered(THD *thd, bool all); void run_commit_ordered(THD *thd, bool all); }; /* Locks used to ensure serialised execution of TC_LOG::run_prepare_ordered() and TC_LOG::run_commit_ordered(), or any other code that calls handler prepare_ordered() or commit_ordered() methods. */ extern mysql_mutex_t LOCK_prepare_ordered; extern mysql_cond_t COND_prepare_ordered; extern mysql_mutex_t LOCK_after_binlog_sync; extern mysql_mutex_t LOCK_commit_ordered; #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; extern PSI_mutex_key key_LOCK_after_binlog_sync; extern PSI_cond_key key_COND_prepare_ordered; #endif class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging { public: TC_LOG_DUMMY() = default; int open(const char *opt_name) override { return 0; } void close() override { } /* TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we only use internal XA during commit when >= 2 XA-capable engines participate. */ int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) override { DBUG_ASSERT(0); return 1; } int unlog(ulong cookie, my_xid xid) override { return 0; } int unlog_xa_prepare(THD *thd, bool all) override { return 0; } void commit_checkpoint_notify(void *cookie) override { DBUG_ASSERT(0); }; }; #define TC_LOG_PAGE_SIZE 8192 #ifdef HAVE_MMAP class TC_LOG_MMAP: public TC_LOG { public: // only to keep Sun Forte on sol9x86 happy typedef enum { PS_POOL, // page is in pool PS_ERROR, // last sync failed PS_DIRTY // new xids added since last sync } PAGE_STATE; struct pending_cookies { uint count; uint pending_count; ulong cookies[1]; }; private: typedef struct st_page { struct st_page *next; // page a linked in a fifo queue my_xid *start, *end; // usable area of a page my_xid *ptr; // next xid will be written here int size, free; // max and current number of free xid slots on the page int waiters; // number of waiters on condition PAGE_STATE state; // see above mysql_mutex_t lock; // to access page data or control structure mysql_cond_t cond; // to wait for a sync } PAGE; /* List of THDs for which to invoke commit_ordered(), in order. */ struct commit_entry { struct commit_entry *next; THD *thd; }; char logname[FN_REFLEN]; File fd; my_off_t file_length; uint npages, inited; uchar *data; struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr; /* note that, e.g. LOCK_active is only used to protect 'active' pointer, to protect the content of the active page one has to use active->lock. Same for LOCK_pool and LOCK_sync */ mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync, LOCK_pending_checkpoint; mysql_cond_t COND_pool, COND_active; /* Queue of threads that need to call commit_ordered(). Access to this queue must be protected by LOCK_prepare_ordered. */ commit_entry *commit_ordered_queue; /* This flag and condition is used to reserve the queue while threads in it each run the commit_ordered() methods one after the other. Only once the last commit_ordered() in the queue is done can we start on a new queue run. Since we start this process in the first thread in the queue and finish in the last (and possibly different) thread, we need a condition variable for this (we cannot unlock a mutex in a different thread than the one who locked it). The condition is used together with the LOCK_prepare_ordered mutex. */ mysql_cond_t COND_queue_busy; my_bool commit_ordered_queue_busy; pending_cookies* pending_checkpoint; public: TC_LOG_MMAP(): inited(0), pending_checkpoint(0) {} int open(const char *opt_name) override; void close() override; int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) override; int unlog(ulong cookie, my_xid xid) override; int unlog_xa_prepare(THD *thd, bool all) override { return 0; } void commit_checkpoint_notify(void *cookie) override; int recover(); private: int log_one_transaction(my_xid xid); void get_active_from_pool(); int sync(); int overflow(); int delete_entry(ulong cookie); }; #else #define TC_LOG_MMAP TC_LOG_DUMMY #endif extern TC_LOG *tc_log; extern TC_LOG_MMAP tc_log_mmap; extern TC_LOG_DUMMY tc_log_dummy; /* log info errors */ #define LOG_INFO_EOF -1 #define LOG_INFO_IO -2 #define LOG_INFO_INVALID -3 #define LOG_INFO_SEEK -4 #define LOG_INFO_MEM -6 #define LOG_INFO_FATAL -7 #define LOG_INFO_IN_USE -8 #define LOG_INFO_EMFILE -9 /* bitmap to SQL_LOG::close() */ #define LOG_CLOSE_INDEX 1 #define LOG_CLOSE_TO_BE_OPENED 2 #define LOG_CLOSE_STOP_EVENT 4 #define LOG_CLOSE_DELAYED_CLOSE 8 #define LOG_CLOSE_SYNC_GTID_INDEX 16 /* Maximum unique log filename extension. Note: setting to 0x7FFFFFFF due to atol windows overflow/truncate. */ #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF /* Number of warnings that will be printed to error log before extension number is exhausted. */ #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 class Relay_log_info; /* Note that we destroy the lock mutex in the desctructor here. This means that object instances cannot be destroyed/go out of scope, until we have reset thd->current_linfo to NULL; */ typedef struct st_log_info { char log_file_name[FN_REFLEN]; my_off_t index_file_offset, index_file_start_offset; my_off_t pos; bool fatal; // if the purge happens to give us a negative offset st_log_info() : index_file_offset(0), index_file_start_offset(0), pos(0), fatal(0) { DBUG_ENTER("LOG_INFO"); log_file_name[0] = '\0'; DBUG_VOID_RETURN; } } LOG_INFO; /* Currently we have only 3 kinds of logging functions: old-fashioned logs, stdout and csv logging routines. */ #define MAX_LOG_HANDLERS_NUM 3 /* log event handler flags */ #define LOG_NONE 1U #define LOG_FILE 2U #define LOG_TABLE 4U class Log_event; class Rows_log_event; enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN }; enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; /* Use larger buffers when reading from and to binary log We make it one step smaller than 64K to account for malloc overhead. */ #define LOG_BIN_IO_SIZE MY_ALIGN_DOWN(65536-1, IO_SIZE) /* TODO use mmap instead of IO_CACHE for binlog (mmap+fsync is two times faster than write+fsync) */ class MYSQL_LOG { public: MYSQL_LOG(); virtual ~MYSQL_LOG() = default; void init_pthread_objects(); void cleanup(); bool open( #ifdef HAVE_PSI_INTERFACE PSI_file_key log_file_key, #endif const char *log_name, enum_log_type log_type, const char *new_name, ulong next_file_number, enum cache_type io_cache_type_arg); void close(uint exiting); inline bool is_open() { return log_state != LOG_CLOSED; } const char *generate_name(const char *log_name, const char *suffix, bool strip_ext, char *buff); virtual int generate_new_name(char *new_name, const char *log_name, ulong next_log_number); inline mysql_mutex_t* get_log_lock() { return &LOCK_log; } protected: /* LOCK_log is inited by init_pthread_objects() */ mysql_mutex_t LOCK_log; char *name; char log_file_name[FN_REFLEN]; char time_buff[20], db[NAME_LEN + 1]; bool write_error, inited; IO_CACHE log_file; enum_log_type log_type; volatile enum_log_state log_state; enum cache_type io_cache_type; friend class Log_event; #ifdef HAVE_PSI_INTERFACE /** Instrumentation key to use for file io in @c log_file */ PSI_file_key m_log_file_key; #endif bool init_and_set_log_file_name(const char *log_name, const char *new_name, ulong next_log_number, enum_log_type log_type_arg, enum cache_type io_cache_type_arg); }; /** @struct Rows_event_factory Holds an event type code and a callback function to create it. Should be created by Rows_event_factory::get. */ struct Rows_event_factory { int type_code; Rows_log_event *(*create)(THD*, TABLE*, ulonglong, bool is_transactional); template<class RowsEventT> static Rows_event_factory get() { return { RowsEventT::TYPE_CODE, [](THD* thd, TABLE* table, ulonglong flags, bool is_transactional) -> Rows_log_event* { return new RowsEventT(thd, table, flags, is_transactional); } }; } }; class Event_log: public MYSQL_LOG { protected: /* binlog encryption data */ struct Binlog_crypt_data crypto; mysql_mutex_t LOCK_binlog_end_pos; /** The instrumentation key to use for LOCK_binlog_end_pos. */ PSI_mutex_key m_key_LOCK_binlog_end_pos; /** The instrumentation key to use for opening the log file. */ PSI_file_key m_key_file_log, m_key_file_log_cache; public: #if !defined(MYSQL_CLIENT) Rows_log_event* prepare_pending_rows_event(THD *thd, TABLE* table, binlog_cache_data *cache_data, uint32 serv_id, size_t needed, bool is_transactional, Rows_event_factory event_factory); #endif int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event, binlog_cache_data *cache_data, bool is_transactional); void set_write_error(THD *thd, bool is_transactional); static bool check_write_error(THD *thd); static bool check_cache_error(THD *thd, binlog_cache_data *cache_data); int write_cache(THD *thd, binlog_cache_data *cache_data); int write_cache_raw(THD *thd, IO_CACHE *cache); char* get_name() { return name; } void cleanup() { if (inited) mysql_mutex_destroy(&LOCK_binlog_end_pos); MYSQL_LOG::cleanup(); } void init_pthread_objects() { MYSQL_LOG::init_pthread_objects(); mysql_mutex_init(m_key_LOCK_binlog_end_pos, &LOCK_binlog_end_pos, MY_MUTEX_INIT_SLOW); } bool open(enum cache_type io_cache_type_arg); virtual IO_CACHE *get_log_file() { return &log_file; } longlong write_description_event(enum_binlog_checksum_alg checksum_alg, bool encrypt, bool dont_set_created, bool is_relay_log); bool write_event(Log_event *ev, binlog_cache_data *data, IO_CACHE *file); bool write_event(Log_event *ev, enum enum_binlog_checksum_alg checksum_alg, binlog_cache_data *data, IO_CACHE *file); }; /** A single-reader, single-writer non-blocking layer for Event_log. Provides IO_CACHE for writing and IO_CACHE for reading. Writers use an overrided get_log_file version for their writes, while readers should use flip() to initiate reading. flip() swaps pointers to allow non-blocking reads. Writers can block other writers and a reader with a mutex, but a reader only swaps two pointers under a lock, so it won't block writers. TODO should be unnecessary after MDEV-24676 is done */ class Cache_flip_event_log: public Event_log { IO_CACHE alt_buf; IO_CACHE *current, *alt; std::atomic<uint> ref_count; public: Cache_flip_event_log() : Event_log(), current(&log_file), alt(&alt_buf), ref_count(1) { bzero(&alt_buf, sizeof(alt_buf)); } bool open(enum cache_type io_cache_type_arg) { log_file.dir= mysql_tmpdir; alt_buf.dir= log_file.dir; bool res= Event_log::open(io_cache_type_arg); if (res) return res; name= my_strdup(key_memory_MYSQL_LOG_name, "online-alter-binlog", MYF(MY_WME)); if (!name) return false; res= init_io_cache(&alt_buf, -1, LOG_BIN_IO_SIZE, io_cache_type_arg, 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; return res; } /** Swaps current and alt_log. Can be called only from the reader thread. @return a new IO_CACHE pointer to read from. */ IO_CACHE *flip() { IO_CACHE *tmp= current; reinit_io_cache(alt, WRITE_CACHE, 0, 0, 0); mysql_mutex_lock(get_log_lock()); reinit_io_cache(current, READ_CACHE, 0, 0, 0); current= alt; mysql_mutex_unlock(get_log_lock()); alt= tmp; return alt; } IO_CACHE *get_log_file() override { mysql_mutex_assert_owner(get_log_lock()); return current; } void acquire() { IF_DBUG(auto prev= ,) ref_count.fetch_add(1); DBUG_ASSERT(prev != 0); } void release() { auto prev= ref_count.fetch_add(-1); if (prev == 1) { cleanup(); delete this; } } private: void cleanup() { close_cached_file(&log_file); close_cached_file(&alt_buf); Event_log::cleanup(); } }; /* Tell the io thread if we can delay the master info sync. */ #define SEMI_SYNC_SLAVE_DELAY_SYNC 1 /* Tell the io thread if the current event needs a ack. */ #define SEMI_SYNC_NEED_ACK 2 class MYSQL_QUERY_LOG: public MYSQL_LOG { public: MYSQL_QUERY_LOG() : last_time(0) {} void reopen_file(); bool write(time_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id, const char *command_type, size_t command_type_len, const char *sql_text, size_t sql_text_len); bool write(THD *thd, time_t current_time, const char *user_host, size_t user_host_len, ulonglong query_utime, ulonglong lock_utime, bool is_command, const char *sql_text, size_t sql_text_len); bool open_slow_log(const char *log_name) { char buf[FN_REFLEN]; return open( #ifdef HAVE_PSI_INTERFACE key_file_slow_log, #endif generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0, 0, WRITE_CACHE); } bool open_query_log(const char *log_name) { char buf[FN_REFLEN]; return open( #ifdef HAVE_PSI_INTERFACE key_file_query_log, #endif generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0, 0, WRITE_CACHE); } private: time_t last_time; }; /* We assign each binlog file an internal ID, used to identify them for unlog(). The IDs start from 0 and increment for each new binlog created. In unlog() we need to know the ID of the binlog file that the corresponding transaction was written into. We also need a special value for a corner case where there is no corresponding binlog id (since nothing was logged). And we need an error flag to mark that unlog() must return failure. We use the following macros to pack all of this information into the single ulong available with log_and_order() / unlog(). Note that we cannot use the value 0 for cookie, as that is reserved as error return value from log_and_order(). */ #define BINLOG_COOKIE_ERROR_RETURN 0 #define BINLOG_COOKIE_DUMMY_ID 1 #define BINLOG_COOKIE_BASE 2 #define BINLOG_COOKIE_DUMMY(error_flag) \ ( (BINLOG_COOKIE_DUMMY_ID<<1) | ((error_flag)&1) ) #define BINLOG_COOKIE_MAKE(id, error_flag) \ ( (((id)+BINLOG_COOKIE_BASE)<<1) | ((error_flag)&1) ) #define BINLOG_COOKIE_GET_ERROR_FLAG(c) ((c) & 1) #define BINLOG_COOKIE_GET_ID(c) ( ((ulong)(c)>>1) - BINLOG_COOKIE_BASE ) #define BINLOG_COOKIE_IS_DUMMY(c) \ ( ((ulong)(c)>>1) == BINLOG_COOKIE_DUMMY_ID ) class binlog_cache_mngr; class binlog_cache_data; struct rpl_gtid; struct wait_for_commit; class MYSQL_BIN_LOG: public TC_LOG, public Event_log { #ifdef HAVE_PSI_INTERFACE /** The instrumentation key to use for @ LOCK_index. */ PSI_mutex_key m_key_LOCK_index; /** The instrumentation key to use for @ COND_relay_log_updated */ PSI_cond_key m_key_relay_log_update; /** The instrumentation key to use for @ COND_bin_log_updated */ PSI_cond_key m_key_bin_log_update; /** The instrumentation key to use for opening the log index file. */ PSI_file_key m_key_file_log_index, m_key_file_log_index_cache; PSI_cond_key m_key_COND_queue_busy; #else static constexpr PSI_mutex_key m_key_LOCK_index= 0; static constexpr PSI_cond_key m_key_relay_log_update= 0; static constexpr PSI_cond_key m_key_bin_log_update= 0; static constexpr PSI_file_key m_key_file_log= 0, m_key_file_log_cache= 0; static constexpr PSI_file_key m_key_file_log_index= 0; static constexpr PSI_file_key m_key_file_log_index_cache= 0; static constexpr PSI_cond_key m_key_COND_queue_busy= 0; static constexpr PSI_mutex_key m_key_LOCK_binlog_end_pos= 0; #endif struct group_commit_entry { struct group_commit_entry *next; THD *thd; binlog_cache_mngr *cache_mngr; bool using_stmt_cache; bool using_trx_cache; /* Extra events (COMMIT/ROLLBACK/XID, and possibly INCIDENT) to be written during group commit. The incident_event is only valid if trx_data->has_incident() is true. */ Log_event *end_event; Log_event *incident_event; /* Set during group commit to record any per-thread error. */ int error; int commit_errno; IO_CACHE *error_cache; /* This is the `all' parameter for ha_commit_ordered(). */ bool all; /* True if we need to increment xid_count in trx_group_commit_leader() and decrement in unlog() (this is needed if there is a participating engine that does not implement the commit_checkpoint_request() handlerton method). */ bool need_unlog; /* Fields used to pass the necessary information to the last thread in a group commit, only used when opt_optimize_thread_scheduling is not set. */ bool check_purge; /* Flag used to optimise around wait_for_prior_commit. */ bool queued_by_other; ulong binlog_id; bool ro_1pc; // passes the binlog_cache_mngr::ro_1pc value to Gtid ctor }; /* When this is set, a RESET MASTER is in progress. Then we should not write any binlog checkpoints into the binlog (that could result in deadlock on LOCK_log, and we will delete all binlog files anyway). Instead we should signal COND_xid_list whenever a new binlog checkpoint arrives - when all have arrived, RESET MASTER will complete. */ uint reset_master_pending; ulong mark_xid_done_waiting; /* LOCK_log and LOCK_index are inited by init_pthread_objects() */ mysql_mutex_t LOCK_index; mysql_mutex_t LOCK_xid_list; mysql_cond_t COND_xid_list; mysql_cond_t COND_relay_log_updated, COND_bin_log_updated; ulonglong bytes_written; ulonglong binlog_space_total; IO_CACHE index_file; char index_file_name[FN_REFLEN]; /* purge_file is a temp file used in purge_logs so that the index file can be updated before deleting files from disk, yielding better crash recovery. It is created on demand the first time purge_logs is called and then reused for subsequent calls. It is cleaned up in cleanup(). */ IO_CACHE purge_index_file; char purge_index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary logs and relay logs). For a binlog, max_size should be max_binlog_size. max_size is set in init(), and dynamically changed (when one does SET GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) from sys_vars.cc */ ulong max_size; /* Number generated by last call of find_uniq_filename(). Corresponds closely with current_binlog_id */ ulong last_used_log_number; // current file sequence number for load data infile binary logging uint file_id; uint open_count; // For replication int readers_count; /* Queue of transactions queued up to participate in group commit. */ group_commit_entry *group_commit_queue; /* Condition variable to mark that the group commit queue is busy. Used when each thread does it's own commit_ordered() (when binlog_optimize_thread_scheduling=1). Used with the LOCK_commit_ordered mutex. */ my_bool group_commit_queue_busy; mysql_cond_t COND_queue_busy; /* Total number of committed transactions. */ ulonglong num_commits; /* Number of group commits done. */ ulonglong num_group_commits; /* The reason why the group commit was grouped */ ulonglong group_commit_trigger_count, group_commit_trigger_timeout; ulonglong group_commit_trigger_lock_wait; /* Binlog GTID index. */ Gtid_index_writer *gtid_index; /* pointer to the sync period variable, for binlog this will be sync_binlog_period, for relay log this will be sync_relay_log_period */ uint *sync_period_ptr; uint sync_counter; bool state_file_deleted; bool binlog_state_recover_done; Gtid_index_writer *recover_gtid_index_start(const char *base_name, my_off_t offset); void recover_gtid_index_process(Gtid_index_writer *gi, my_off_t offset, const rpl_gtid *gtid); void recover_gtid_index_end(Gtid_index_writer *gi); void recover_gtid_index_abort(Gtid_index_writer *gi); inline uint get_sync_period() { return *sync_period_ptr; } int write_to_file(IO_CACHE *cache); /* This is used to start writing to a new log file. The difference from new_file() is locking. new_file_without_locking() does not acquire LOCK_log. */ int new_file_impl(); void do_checkpoint_request(ulong binlog_id); int write_transaction_or_stmt(group_commit_entry *entry, uint64 commit_id); int queue_for_group_commit(group_commit_entry *entry); bool write_transaction_to_binlog_events(group_commit_entry *entry); void trx_group_commit_leader(group_commit_entry *leader); bool is_xidlist_idle_nolock(); void update_gtid_index(uint32 offset, rpl_gtid gtid); public: void purge(bool all); int new_file_without_locking(); /* A list of struct xid_count_per_binlog is used to keep track of how many XIDs are in prepared, but not committed, state in each binlog. And how many commit_checkpoint_request()'s are pending. When count drops to zero in a binlog after rotation, it means that there are no more XIDs in prepared state, so that binlog is no longer needed for XA crash recovery, and we can log a new binlog checkpoint event. The list is protected against simultaneous access from multiple threads by LOCK_xid_list. */ struct xid_count_per_binlog : public ilink { char *binlog_name; uint binlog_name_len; ulong binlog_id; /* Total prepared XIDs and pending checkpoint requests in this binlog. */ long xid_count; xid_count_per_binlog(char *log_file_name, uint log_file_name_len) :binlog_id(0), xid_count(0) { binlog_name_len= log_file_name_len; binlog_name= (char *) my_malloc(PSI_INSTRUMENT_ME, binlog_name_len, MYF(MY_ZEROFILL)); if (binlog_name) memcpy(binlog_name, log_file_name, binlog_name_len); } ~xid_count_per_binlog() { my_free(binlog_name); } }; I_List<xid_count_per_binlog> binlog_xid_count_list; mysql_mutex_t LOCK_binlog_background_thread; mysql_cond_t COND_binlog_background_thread; mysql_cond_t COND_binlog_background_thread_end; void stop_background_thread(); using MYSQL_LOG::generate_name; using MYSQL_LOG::is_open; /* This is relay log */ bool is_relay_log; ulong relay_signal_cnt; // update of the counter is checked by heartbeat enum enum_binlog_checksum_alg checksum_alg_reset; // to contain a new value when binlog is rotated /* Holds the last seen in Relay-Log FD's checksum alg value. The initial value comes from the slave's local FD that heads the very first Relay-Log file. In the following the value may change with each received master's FD_m. Besides to be used in verification events that IO thread receives (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd), the value specifies if/how to compute checksum for slave's local events and the first fake Rotate (R_f^1) coming from the master. R_f^1 needs logging checksum-compatibly with the RL's heading FD_s. Legends for the checksum related comments: FD - Format-Description event, R - Rotate event R_f - the fake Rotate event E - an arbirary event The underscore indexes for any event `_s' indicates the event is generated by Slave `_m' - by Master Two special underscore indexes of FD: FD_q - Format Description event for queuing (relay-logging) FD_e - Format Description event for executing (relay-logging) Upper indexes: E^n - n:th event is a sequence RL - Relay Log (A) - checksum algorithm descriptor value FD.(A) - the value of (A) in FD */ enum enum_binlog_checksum_alg relay_log_checksum_alg; /* These describe the log's format. This is used only for relay logs. _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's necessary to have 2 distinct objects, because the I/O thread may be reading events in a different format from what the SQL thread is reading (consider the case of a master which has been upgraded from 5.0 to 5.1 without doing RESET MASTER, or from 4.x to 5.0). */ Format_description_log_event *description_event_for_exec, *description_event_for_queue; /* Binlog position of last commit (or non-transactional write) to the binlog. Access to this is protected by LOCK_commit_ordered. */ char last_commit_pos_file[FN_REFLEN]; my_off_t last_commit_pos_offset; ulong current_binlog_id; /* Tracks the number of times that the master has been reset */ Atomic_counter<uint64> reset_master_count; MYSQL_BIN_LOG(uint *sync_period); /* note that there's no destructor ~MYSQL_BIN_LOG() ! The reason is that we don't want it to be automatically called on exit() - but only during the correct shutdown process */ #ifdef HAVE_PSI_INTERFACE void set_psi_keys(PSI_mutex_key key_LOCK_index, PSI_cond_key key_relay_log_update, PSI_cond_key key_bin_log_update, PSI_file_key key_file_log, PSI_file_key key_file_log_cache, PSI_file_key key_file_log_index, PSI_file_key key_file_log_index_cache, PSI_cond_key key_COND_queue_busy, PSI_mutex_key key_LOCK_binlog_end_pos) { m_key_LOCK_index= key_LOCK_index; m_key_relay_log_update= key_relay_log_update; m_key_bin_log_update= key_bin_log_update; m_key_file_log= key_file_log; m_key_file_log_cache= key_file_log_cache; m_key_file_log_index= key_file_log_index; m_key_file_log_index_cache= key_file_log_index_cache; m_key_COND_queue_busy= key_COND_queue_busy; m_key_LOCK_binlog_end_pos= key_LOCK_binlog_end_pos; } #endif Event_log *as_event_log() { return this; } int open(const char *opt_name) override; void close() override; int generate_new_name(char *new_name, const char *log_name, ulong next_log_number) override; int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) override; int unlog(ulong cookie, my_xid xid) override; int unlog_xa_prepare(THD *thd, bool all) override; void commit_checkpoint_notify(void *cookie) override; int recover(LOG_INFO *linfo, const char *last_log_name, IO_CACHE *first_log, Format_description_log_event *fdle, bool do_xa); int do_binlog_recovery(const char *opt_name, bool do_xa_recovery); #if !defined(MYSQL_CLIENT) static int remove_pending_rows_event(THD *thd, binlog_cache_data *cache_data); #endif /* !defined(MYSQL_CLIENT) */ void reset_bytes_written() { bytes_written = 0; } void harvest_bytes_written(Atomic_counter<uint64> *counter) { #ifdef DBUG_TRACE char buf1[22],buf2[22]; #endif DBUG_ENTER("harvest_bytes_written"); (*counter)+=bytes_written; DBUG_PRINT("info",("counter: %s bytes_written: %s", llstr(*counter,buf1), llstr(bytes_written,buf2))); bytes_written=0; DBUG_VOID_RETURN; } void set_max_size(ulong max_size_arg); /* Handle signaling that relay has been updated */ void signal_relay_log_update() { mysql_mutex_assert_owner(&LOCK_log); DBUG_ASSERT(is_relay_log); DBUG_ENTER("MYSQL_BIN_LOG::signal_relay_log_update"); relay_signal_cnt++; mysql_cond_broadcast(&COND_relay_log_updated); DBUG_VOID_RETURN; } void signal_bin_log_update() { mysql_mutex_assert_owner(&LOCK_binlog_end_pos); DBUG_ASSERT(!is_relay_log); DBUG_ENTER("MYSQL_BIN_LOG::signal_bin_log_update"); mysql_cond_broadcast(&COND_bin_log_updated); DBUG_VOID_RETURN; } void update_binlog_end_pos() { if (is_relay_log) signal_relay_log_update(); else { lock_binlog_end_pos(); binlog_end_pos= my_b_safe_tell(&log_file); signal_bin_log_update(); unlock_binlog_end_pos(); } } void update_binlog_end_pos(my_off_t pos) { mysql_mutex_assert_owner(&LOCK_log); mysql_mutex_assert_not_owner(&LOCK_binlog_end_pos); lock_binlog_end_pos(); /* Note: it would make more sense to assert(pos > binlog_end_pos) but there are two places triggered by mtr that has pos == binlog_end_pos i didn't investigate but accepted as it should do no harm */ DBUG_ASSERT(pos >= binlog_end_pos); binlog_end_pos= pos; signal_bin_log_update(); unlock_binlog_end_pos(); } void wait_for_sufficient_commits(); void binlog_trigger_immediate_group_commit(); void wait_for_update_relay_log(THD* thd); void init(ulong max_size); void init_pthread_objects(); void cleanup(); bool open(const char *log_name, const char *new_name, ulong next_log_number, enum cache_type io_cache_type_arg, ulong max_size, bool null_created, bool need_mutex); bool open_index_file(const char *index_file_name_arg, const char *log_name, bool need_mutex); /* Use this to start writing a new log file */ int new_file(); bool write(Log_event* event_info, my_bool *with_annotate= 0); // binary log write bool write_transaction_to_binlog(THD *thd, binlog_cache_mngr *cache_mngr, Log_event *end_ev, bool all, bool using_stmt_cache, bool using_trx_cache, bool is_ro_1pc); bool write_incident_already_locked(THD *thd); bool write_incident(THD *thd); void write_binlog_checkpoint_event_already_locked(const char *name, uint len); bool write_table_map(THD *thd, TABLE *table); void start_union_events(THD *thd, query_id_t query_id_param); void stop_union_events(THD *thd); bool is_query_in_union(THD *thd, query_id_t query_id_param); using Event_log::write_event; bool write_event(Log_event *ev, enum enum_binlog_checksum_alg checksum_alg) { return write_event(ev, checksum_alg, 0, &log_file); } bool write_event(Log_event *ev); bool write_event_buffer(uchar* buf,uint len); bool append(Log_event* ev, enum enum_binlog_checksum_alg checksum_alg); bool append_no_lock(Log_event* ev, enum enum_binlog_checksum_alg checksum_alg); void mark_xids_active(ulong cookie, uint xid_count); void mark_xid_done(ulong cookie, bool write_checkpoint); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); bool can_purge_log(const char *log_file_name, bool interactive); int update_log_index(LOG_INFO* linfo, bool need_update_threads); int rotate(bool force_rotate, bool* check_purge); void checkpoint_and_purge(ulong binlog_id); int rotate_and_purge(bool force_rotate, DYNAMIC_ARRAY* drop_gtid_domain= NULL); /** Flush binlog cache and synchronize to disk. This function flushes events in binlog cache to binary log file, it will do synchronizing according to the setting of system variable 'sync_binlog'. If file is synchronized, @c synced will be set to 1, otherwise 0. @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0 @retval 0 Success @retval other Failure */ bool flush_and_sync(bool *synced); int purge_logs(THD *thd, const char *to_log, bool included, bool need_mutex, bool need_update_threads, bool interactive, ulonglong *decrease_log_space); int purge_logs_before_date(THD *thd, time_t purge_time, bool interactive); int purge_first_log(Relay_log_info* rli, bool included); int count_binlog_space(); void count_binlog_space_with_mutex() { mysql_mutex_lock(&LOCK_index); count_binlog_space(); mysql_mutex_unlock(&LOCK_index); } ulonglong get_binlog_space_total(); int real_purge_logs_by_size(ulonglong binlog_pos); inline int purge_logs_by_size(ulonglong binlog_pos) { if (is_relay_log || ! binlog_space_limit || binlog_space_total + binlog_pos <= binlog_space_limit) return 0; return real_purge_logs_by_size(binlog_pos); } int set_purge_index_file_name(const char *base_file_name); int open_purge_index_file(bool destroy); bool truncate_and_remove_binlogs(const char *truncate_file, my_off_t truncate_pos, rpl_gtid *gtid); bool is_inited_purge_index_file(); int close_purge_index_file(); int clean_purge_index_file(); int sync_purge_index_file(); int register_purge_index_entry(const char* entry); int register_create_index_entry(const char* entry); int purge_index_entry(THD *thd, ulonglong *decrease_log_space, bool need_mutex); bool reset_logs(THD* thd, bool create_new_log, rpl_gtid *init_state, uint32 init_state_len, ulong next_log_number); void wait_for_last_checkpoint_event(); void close(uint exiting); void clear_inuse_flag_when_closing(File file); // iterating through the log index file int find_log_pos(LOG_INFO* linfo, const char* log_name, bool need_mutex); int find_next_log(LOG_INFO* linfo, bool need_mutex); int get_current_log(LOG_INFO* linfo); int raw_get_current_log(LOG_INFO* linfo); uint next_file_id(); inline char* get_index_fname() { return index_file_name;} inline char* get_log_fname() { return log_file_name; } using MYSQL_LOG::get_log_lock; inline mysql_cond_t* get_bin_log_cond() { return &COND_bin_log_updated; } inline IO_CACHE* get_log_file() override { return &log_file; } inline uint64 get_reset_master_count() { return reset_master_count; } inline void lock_index() { mysql_mutex_lock(&LOCK_index);} inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);} inline IO_CACHE *get_index_file() { return &index_file;} inline uint32 get_open_count() { return open_count; } void set_status_variables(THD *thd); bool is_xidlist_idle(); bool write_gtid_event(THD *thd, bool standalone, bool is_transactional, uint64 commit_id, bool has_xid= false, bool ro_1pc= false); int read_state_from_file(); int write_state_to_file(); int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); bool append_state_pos(String *str); bool append_state(String *str); bool is_empty_state(); bool find_in_binlog_state(uint32 domain_id, uint32 server_id, rpl_gtid *out_gtid); bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid); int bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no); bool check_strict_gtid_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no, bool no_error= false); /** * used when opening new file, and binlog_end_pos moves backwards */ void reset_binlog_end_pos(const char file_name[FN_REFLEN], my_off_t pos) { mysql_mutex_assert_owner(&LOCK_log); mysql_mutex_assert_not_owner(&LOCK_binlog_end_pos); lock_binlog_end_pos(); binlog_end_pos= pos; safe_strcpy(binlog_end_pos_file, sizeof(binlog_end_pos_file), file_name); signal_bin_log_update(); unlock_binlog_end_pos(); } /* It is called by the threads(e.g. dump thread) which want to read log without LOCK_log protection. */ my_off_t get_binlog_end_pos(char file_name_buf[FN_REFLEN]) const { mysql_mutex_assert_not_owner(&LOCK_log); mysql_mutex_assert_owner(&LOCK_binlog_end_pos); safe_strcpy(file_name_buf, FN_REFLEN, binlog_end_pos_file); return binlog_end_pos; } void lock_binlog_end_pos() { mysql_mutex_lock(&LOCK_binlog_end_pos); } void unlock_binlog_end_pos() { mysql_mutex_unlock(&LOCK_binlog_end_pos); } mysql_mutex_t* get_binlog_end_pos_lock() { return &LOCK_binlog_end_pos; } /* Ensures the log's state is either LOG_OPEN or LOG_CLOSED. If something failed along the desired path and left the log in invalid state, i.e. LOG_TO_BE_OPENED, forces the state to be LOG_CLOSED. */ void try_fix_log_state() { mysql_mutex_lock(get_log_lock()); /* Only change the log state if it is LOG_TO_BE_OPENED */ if (log_state == LOG_TO_BE_OPENED) log_state= LOG_CLOSED; mysql_mutex_unlock(get_log_lock()); } int wait_for_update_binlog_end_pos(THD* thd, struct timespec * timeout); /* Binlog position of end of the binlog. Access to this is protected by LOCK_binlog_end_pos The difference between this and last_commit_pos_{file,offset} is that the commit position is updated later. If semi-sync wait point is set to WAIT_AFTER_SYNC, the commit pos is update after semi-sync-ack has been received and the end point is updated after the write as it's needed for the dump threads to be able to semi-sync the event. */ my_off_t binlog_end_pos; char binlog_end_pos_file[FN_REFLEN]; }; class Log_event_handler { public: Log_event_handler() = default; virtual bool init()= 0; virtual void cleanup()= 0; virtual bool log_slow(THD *thd, my_hrtime_t current_time, const char *user_host, size_t user_host_len, ulonglong query_utime, ulonglong lock_utime, bool is_command, const char *sql_text, size_t sql_text_len)= 0; virtual bool log_error(enum loglevel level, const char *format, va_list args)= 0; virtual bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id, const char *command_type, size_t command_type_len, const char *sql_text, size_t sql_text_len, CHARSET_INFO *client_cs)= 0; virtual ~Log_event_handler() = default; }; int check_if_log_table(const TABLE_LIST *table); int check_if_log_table(const TABLE_LIST *table, bool check_if_opened, const char *errmsg); class Log_to_csv_event_handler: public Log_event_handler { friend class LOGGER; public: Log_to_csv_event_handler(); ~Log_to_csv_event_handler(); bool init() override; void cleanup() override; bool log_slow(THD *thd, my_hrtime_t current_time, const char *user_host, size_t user_host_len, ulonglong query_utime, ulonglong lock_utime, bool is_command, const char *sql_text, size_t sql_text_len) override; bool log_error(enum loglevel level, const char *format, va_list args) override; bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id, const char *command_type, size_t command_type_len, const char *sql_text, size_t sql_text_len, CHARSET_INFO *client_cs) override; int activate_log(THD *thd, uint log_type); }; /* type of the log table */ #define QUERY_LOG_SLOW 1 #define QUERY_LOG_GENERAL 2 class Log_to_file_event_handler: public Log_event_handler { MYSQL_QUERY_LOG mysql_log; MYSQL_QUERY_LOG mysql_slow_log; bool is_initialized; public: Log_to_file_event_handler(): is_initialized(FALSE) {} bool init() override; void cleanup() override; bool log_slow(THD *thd, my_hrtime_t current_time, const char *user_host, size_t user_host_len, ulonglong query_utime, ulonglong lock_utime, bool is_command, const char *sql_text, size_t sql_text_len) override; bool log_error(enum loglevel level, const char *format, va_list args) override; bool log_general(THD *thd, my_hrtime_t event_time, const char *user_host, size_t user_host_len, my_thread_id thread_id, const char *command_type, size_t command_type_len, const char *sql_text, size_t sql_text_len, CHARSET_INFO *client_cs) override; void flush(); void init_pthread_objects(); MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; } MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; } }; /* Class which manages slow, general and error log event handlers */ class LOGGER { mysql_rwlock_t LOCK_logger; /* flag to check whether logger mutex is initialized */ uint inited; /* available log handlers */ Log_to_csv_event_handler *table_log_handler; Log_to_file_event_handler *file_log_handler; /* NULL-terminated arrays of log handlers */ Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; public: bool is_log_tables_initialized; LOGGER() : inited(0), table_log_handler(NULL), file_log_handler(NULL), is_log_tables_initialized(FALSE) {} void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); } void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); } void unlock() { mysql_rwlock_unlock(&LOCK_logger); } bool is_log_table_enabled(uint log_table_type); bool log_command(THD *thd, enum enum_server_command command); /* We want to initialize all log mutexes as soon as possible, but we cannot do it in constructor, as safe_mutex relies on initialization, performed by MY_INIT(). This why this is done in this function. */ void init_base(); void init_log_tables(); bool flush_slow_log(); bool flush_general_log(); /* Perform basic logger cleanup. this will leave e.g. error log open. */ void cleanup_base(); /* Free memory. Nothing could be logged after this function is called */ void cleanup_end(); bool error_log_print(enum loglevel level, const char *format, va_list args); bool slow_log_print(THD *thd, const char *query, size_t query_length, ulonglong current_utime); bool general_log_print(THD *thd,enum enum_server_command command, const char *format, va_list args); bool general_log_write(THD *thd, enum enum_server_command command, const char *query, size_t query_length); /* we use this function to setup all enabled log event handlers */ int set_handlers(ulonglong slow_log_printer, ulonglong general_log_printer); void init_error_log(ulonglong error_log_printer); void init_slow_log(ulonglong slow_log_printer); void init_general_log(ulonglong general_log_printer); void deactivate_log_handler(THD* thd, uint log_type); bool activate_log_handler(THD* thd, uint log_type); MYSQL_QUERY_LOG *get_slow_log_file_handler() const { if (file_log_handler) return file_log_handler->get_mysql_slow_log(); return NULL; } MYSQL_QUERY_LOG *get_log_file_handler() const { if (file_log_handler) return file_log_handler->get_mysql_log(); return NULL; } }; enum enum_binlog_format { BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected BINLOG_FORMAT_STMT= 1, ///< statement-based BINLOG_FORMAT_ROW= 2, ///< row-based BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed }; int query_error_code(THD *thd, bool not_killed); uint purge_log_get_error_code(int res); int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); void sql_print_error(const char *format, ...); void sql_print_warning(const char *format, ...); void sql_print_information(const char *format, ...); void sql_print_information_v(const char *format, va_list ap); typedef void (*sql_print_message_func)(const char *format, ...); extern sql_print_message_func sql_print_message_handlers[]; int error_log_print(enum loglevel level, const char *format, va_list args); bool slow_log_print(THD *thd, const char *query, uint query_length, ulonglong current_utime); bool general_log_print(THD *thd, enum enum_server_command command, const char *format,...); bool general_log_write(THD *thd, enum enum_server_command command, const char *query, size_t query_length); void binlog_report_wait_for(THD *thd, THD *other_thd); void sql_perror(const char *message); bool flush_error_log(); File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg); void make_default_log_name(char **out, const char* log_ext, bool once); void binlog_reset_cache(THD *thd); void binlog_clear_incident(THD *thd); bool write_annotated_row(THD *thd); int binlog_flush_pending_rows_event(THD *thd, bool stmt_end, bool is_transactional, Event_log *bin_log, binlog_cache_data *cache_data); Rows_log_event* binlog_get_pending_rows_event(binlog_cache_mngr *cache_mngr, bool use_trans_cache); int online_alter_log_row(TABLE* table, const uchar *before_record, const uchar *after_record, Log_func *log_func); binlog_cache_data* binlog_get_cache_data(binlog_cache_mngr *cache_mngr, bool use_trans_cache); extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; extern handlerton *binlog_hton; extern LOGGER logger; extern const char *log_bin_index; extern const char *log_bin_basename; /** Turns a relative log binary log path into a full path, based on the opt_bin_logname or opt_relay_logname. @param from The log name we want to make into an absolute path. @param to The buffer where to put the results of the normalization. @param is_relay_log Switch that makes is used inside to choose which option (opt_bin_logname or opt_relay_logname) to use when calculating the base path. @returns true if a problem occurs, false otherwise. */ inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log) { DBUG_ENTER("normalize_binlog_name"); bool error= false; char buff[FN_REFLEN]; char *ptr= (char*) from; char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname; DBUG_ASSERT(from); /* opt_name is not null and not empty and from is a relative path */ if (opt_name && opt_name[0] && from && !test_if_hard_path(from)) { // take the path from "opt_name" // take the filename from "from" char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN]; size_t log_dirpart_len, log_dirname_len; dirname_part(log_dirpart, opt_name, &log_dirpart_len); dirname_part(log_dirname, from, &log_dirname_len); /* log may be empty => relay-log or log-bin did not hold paths, just filename pattern */ if (log_dirpart_len > 0) { /* create the new path name */ if(fn_format(buff, from+log_dirname_len, log_dirpart, "", MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL) { error= true; goto end; } ptr= buff; } } DBUG_ASSERT(ptr); if (ptr) strmake(to, ptr, strlen(ptr)); end: DBUG_RETURN(error); } static inline TC_LOG *get_tc_log_implementation() { if (total_ha_2pc <= 1) return &tc_log_dummy; if (opt_bin_log) return &mysql_bin_log; return &tc_log_mmap; } #ifdef WITH_WSREP IO_CACHE* wsrep_get_cache(THD *, bool); bool wsrep_is_binlog_cache_empty(THD *); void wsrep_thd_binlog_trx_reset(THD * thd); void wsrep_thd_binlog_stmt_rollback(THD * thd); #endif /* WITH_WSREP */ class Gtid_list_log_event; const char * get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list); int binlog_commit(THD *thd, bool all, bool is_ro_1pc= false); int binlog_rollback(handlerton *hton, THD *thd, bool all); int binlog_commit_by_xid(handlerton *hton, XID *xid); int binlog_rollback_by_xid(handlerton *hton, XID *xid); bool write_bin_log_start_alter(THD *thd, bool& partial_alter, uint64 start_alter_id, bool log_if_exists); #endif /* LOG_H */ transaction.h 0000644 00000002672 15156036160 0007254 0 ustar 00 /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef TRANSACTION_H #define TRANSACTION_H #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include <m_string.h> class THD; void trans_track_end_trx(THD *thd); bool trans_begin(THD *thd, uint flags= 0); bool trans_commit(THD *thd); bool trans_commit_implicit(THD *thd); bool trans_rollback(THD *thd); bool trans_rollback_implicit(THD *thd); bool trans_commit_stmt(THD *thd); bool trans_rollback_stmt(THD *thd); bool trans_savepoint(THD *thd, LEX_CSTRING name); bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name); bool trans_release_savepoint(THD *thd, LEX_CSTRING name); void trans_reset_one_shot_chistics(THD *thd); #endif /* TRANSACTION_H */ wsrep_binlog.h 0000644 00000006737 15156036160 0007427 0 ustar 00 /* Copyright (C) 2013 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_BINLOG_H #define WSREP_BINLOG_H #include "my_global.h" #include "sql_class.h" // THD, IO_CACHE #define HEAP_PAGE_SIZE 65536 /* 64K */ #define WSREP_MAX_WS_SIZE 2147483647 /* 2GB */ /* Write the contents of a cache to a memory buffer. This function quite the same as MYSQL_BIN_LOG::write_cache(), with the exception that here we write in buffer instead of log file. */ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len); /* Write the contents of a cache to wsrep provider. This function quite the same as MYSQL_BIN_LOG::write_cache(), with the exception that here we write in buffer instead of log file. @param log_position position to start writing the cache from @param len total amount of data written @return wsrep error status */ int wsrep_write_cache(THD* thd, IO_CACHE* cache, size_t log_position, size_t* len); /* Dump replication buffer to disk */ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); /* Dump replication buffer along with header to a file */ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, size_t buf_len); /** Write a skip event into binlog. @param thd Thread object pointer @return Zero in case of success, non-zero on failure. */ int wsrep_write_skip_event(THD* thd); /* Write dummy event into binlog in place of unused GTID. The binlog write is done in thd context. */ int wsrep_write_dummy_event_low(THD *thd, const char *msg); /* Write dummy event to binlog in place of unused GTID and commit. The binlog write and commit are done in temporary thd context, the original thd state is not altered. */ int wsrep_write_dummy_event(THD* thd, const char *msg); void wsrep_register_binlog_handler(THD *thd, bool trx); /** Return true if committing THD will write to binlog during commit. This is the case for: - Local THD, binlog is open - Replaying THD, binlog is open - Applier THD, log-slave-updates is enabled */ bool wsrep_commit_will_write_binlog(THD *thd); /** Register THD for group commit. The wsrep_trx must be in committing state, i.e. the call must be done after wsrep_before_commit() but before commit order is released. This call will release commit order critical section if it is determined that the commit will go through binlog group commit. */ void wsrep_register_for_group_commit(THD *thd); /** Deregister THD from group commit. The wsrep_trx must be in committing state, as for wsrep_register_for_group_commit() above. This call must be used only for THDs which will not go through binlog group commit. */ void wsrep_unregister_from_group_commit(THD *thd); #endif /* WSREP_BINLOG_H */ mysqld.h 0000644 00000122176 15156036160 0006242 0 ustar 00 /* Copyright (c) 2006, 2016, Oracle and/or its affiliates. Copyright (c) 2010, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MYSQLD_INCLUDED #define MYSQLD_INCLUDED #include "sql_basic_types.h" /* query_id_t */ #include "sql_mode.h" /* Sql_mode_dependency */ #include "sql_plugin.h" #include "sql_bitmap.h" /* Bitmap */ #include "my_decimal.h" /* my_decimal */ #include "mysql_com.h" /* SERVER_VERSION_LENGTH */ #include "my_counter.h" #include "mysql/psi/mysql_file.h" /* MYSQL_FILE */ #include "mysql/psi/mysql_socket.h" /* MYSQL_SOCKET */ #include "sql_list.h" /* I_List */ #include "sql_cmd.h" #include <my_rnd.h> #include "my_pthread.h" #include "my_rdtsc.h" class THD; class CONNECT; struct handlerton; class Time_zone; struct scheduler_functions; typedef struct st_mysql_show_var SHOW_VAR; /* Bits from testflag */ #define TEST_PRINT_CACHED_TABLES 1U #define TEST_NO_KEY_GROUP 2U #define TEST_MIT_THREAD 4U #define TEST_BLOCKING 8U #define TEST_KEEP_TMP_TABLES 16U #define TEST_READCHECK 64U /**< Force use of readcheck */ #define TEST_NO_EXTRA 128U #define TEST_CORE_ON_SIGNAL 256U /**< Give core if signal */ #define TEST_SIGINT 1024U /**< Allow sigint on threads */ #define TEST_SYNCHRONIZATION 2048U /**< get server to do sleep in some places */ /* Keep things compatible */ #define OPT_DEFAULT SHOW_OPT_DEFAULT #define OPT_SESSION SHOW_OPT_SESSION #define OPT_GLOBAL SHOW_OPT_GLOBAL extern MYSQL_PLUGIN_IMPORT MY_TIMER_INFO sys_timer_info; /* Values for --slave-parallel-mode Must match order in slave_parallel_mode_typelib in sys_vars.cc. */ enum enum_slave_parallel_mode { SLAVE_PARALLEL_NONE, SLAVE_PARALLEL_MINIMAL, SLAVE_PARALLEL_CONSERVATIVE, SLAVE_PARALLEL_OPTIMISTIC, SLAVE_PARALLEL_AGGRESSIVE }; /* Function prototypes */ void kill_mysql(THD *thd); void close_connection(THD *thd, uint sql_errno= 0); void handle_connection_in_main_thread(CONNECT *thd); void create_thread_to_handle_connection(CONNECT *connect); void unlink_thd(THD *thd); void refresh_status(THD *thd); bool is_secure_file_path(char *path); extern void init_net_server_extension(THD *thd); extern void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock); extern void create_new_thread(CONNECT *connect); extern void ssl_acceptor_stats_update(int sslaccept_ret); extern int reinit_ssl(); extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *national_charset_info; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset; /** Character set of the buildin error messages loaded from errmsg.sys. */ extern CHARSET_INFO *error_message_charset_info; extern CHARSET_INFO *character_set_filesystem; void temp_pool_clear_bit(uint bit); uint temp_pool_set_next(); extern bool opt_large_files; extern bool opt_update_log, opt_bin_log, opt_error_log, opt_bin_log_compress; extern uint opt_bin_log_compress_min_len; extern my_bool opt_log, opt_bootstrap; extern my_bool opt_backup_history_log; extern my_bool opt_backup_progress_log; extern my_bool opt_support_flashback; extern ulonglong log_output_options; extern ulong log_backup_output_options; extern bool opt_disable_networking, opt_skip_show_db; extern bool opt_skip_name_resolve; extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern my_bool debug_assert_on_not_freed_memory; extern MYSQL_PLUGIN_IMPORT bool volatile abort_loop; extern my_bool opt_safe_user_create; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern ulong slave_exec_mode_options, slave_ddl_exec_mode_options; extern ulong slave_retried_transactions; extern ulong transactions_multi_engine; extern ulong rpl_transactions_multi_engine; extern ulong transactions_gtid_foreign_engine; extern ulong slave_run_triggers_for_rbr; extern ulonglong slave_type_conversions_options; extern my_bool read_only, opt_readonly; extern MYSQL_PLUGIN_IMPORT my_bool lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern my_bool opt_require_secure_transport; extern const char *current_dbug_option; extern char* opt_secure_file_priv; extern char* opt_secure_backup_file_priv; extern size_t opt_secure_backup_file_priv_len; extern my_bool sp_automatic_privileges, opt_noacl; extern ulong use_stat_tables; extern my_bool opt_old_style_user_limits, trust_function_creators; extern uint opt_crash_binlog_innodb; extern const char *shared_memory_base_name; extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port; extern MYSQL_PLUGIN_IMPORT bool metadata_lock_info_plugin_loaded; extern my_bool opt_enable_shared_memory; extern ulong opt_replicate_events_marked_for_skip; extern char *default_tz_name; extern Time_zone *default_tz; extern char *my_bind_addr_str; extern char *default_storage_engine, *default_tmp_storage_engine; extern char *enforced_storage_engine; extern char *gtid_pos_auto_engines; extern plugin_ref *opt_gtid_pos_auto_plugins; extern bool opt_endinfo, using_udf_functions; extern my_bool locked_in_memory; extern bool opt_using_transactions; extern ulong current_pid; extern double expire_logs_days; extern ulong binlog_expire_logs_seconds; extern ulonglong binlog_space_limit; extern my_bool relay_log_recovery; #include <governor-mysql/lve-patch/main.h> extern uint sync_binlog_period, sync_relaylog_period, sync_relayloginfo_period, sync_masterinfo_period; extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size; extern ulong tc_log_page_waits; extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb; extern my_bool relay_log_recovery; extern uint select_errors,ha_open_options; extern ulonglong test_flags; extern uint protocol_version, dropping_tables; extern MYSQL_PLUGIN_IMPORT uint mysqld_port; extern ulong delay_key_write_options; extern char *opt_logname, *opt_slow_logname, *opt_bin_logname, *opt_relay_logname; extern char *opt_binlog_index_name; extern my_bool opt_binlog_legacy_event_pos; extern char *opt_backup_history_logname, *opt_backup_progress_logname, *opt_backup_settings_name; extern const char *log_output_str; extern const char *log_backup_output_str; /* System Versioning begin */ enum vers_system_time_t { SYSTEM_TIME_UNSPECIFIED = 0, SYSTEM_TIME_AS_OF, SYSTEM_TIME_FROM_TO, SYSTEM_TIME_BETWEEN, SYSTEM_TIME_BEFORE, // used for DELETE HISTORY ... BEFORE SYSTEM_TIME_HISTORY, // used for DELETE HISTORY SYSTEM_TIME_ALL }; struct vers_asof_timestamp_t { ulong type; my_time_t unix_time; ulong second_part; }; enum vers_alter_history_enum { VERS_ALTER_HISTORY_ERROR= 0, VERS_ALTER_HISTORY_KEEP }; /* System Versioning end */ extern char *mysql_home_ptr, *pidfile_name_ptr; extern MYSQL_PLUGIN_IMPORT char glob_hostname[FN_REFLEN]; extern char mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char default_logfile_name[FN_REFLEN]; extern char log_error_file[FN_REFLEN], *opt_tc_log_file, *opt_ddl_recovery_file; extern const double log_10[309]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; extern my_thread_id global_thread_id; extern ulong binlog_cache_use, binlog_cache_disk_use; extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use; extern ulong binlog_gtid_index_hit, binlog_gtid_index_miss; extern ulong aborted_threads, aborted_connects, aborted_connects_preauth; extern ulong delayed_insert_timeout; extern ulong delayed_insert_limit, delayed_queue_size; extern ulong delayed_insert_threads, delayed_insert_writes; extern ulong delayed_rows_in_use,delayed_insert_errors; extern Atomic_counter<uint32_t> slave_open_temp_tables; extern Atomic_counter<ulonglong> sending_new_binlog_file; extern uint slave_connections_needed_for_purge; extern ulonglong query_cache_size; extern ulong query_cache_limit; extern ulong query_cache_min_res_unit; extern ulong slow_launch_threads, slow_launch_time; extern MYSQL_PLUGIN_IMPORT ulong max_connections; extern uint max_digest_length; extern ulong max_connect_errors, connect_timeout; extern uint max_password_errors; extern my_bool slave_allow_batching; extern my_bool allow_slave_start; extern LEX_CSTRING reason_slave_blocked; extern ulong slave_trans_retries; extern ulong slave_trans_retry_interval; extern uint slave_net_timeout; extern int max_user_connections; extern ulong what_to_log,flush_time; extern uint max_prepared_stmt_count, prepared_stmt_count; extern MYSQL_PLUGIN_IMPORT ulong open_files_limit; extern ulonglong binlog_cache_size, binlog_stmt_cache_size, binlog_file_cache_size; extern ulonglong max_binlog_cache_size, max_binlog_stmt_cache_size; extern ulonglong internal_binlog_space_limit; extern uint internal_slave_connections_needed_for_purge; extern ulong max_binlog_size; extern ulong slave_max_allowed_packet; extern ulonglong slave_max_statement_time; extern double slave_max_statement_time_double; extern ulong opt_binlog_rows_event_max_size; extern ulong binlog_row_metadata; extern my_bool opt_binlog_gtid_index; extern uint opt_binlog_gtid_index_page_size; extern uint opt_binlog_gtid_index_span_min; extern ulong thread_cache_size; extern ulong stored_program_cache_size; extern ulong opt_slave_parallel_threads; extern ulong opt_slave_domain_parallel_threads; extern ulong opt_slave_parallel_max_queued; extern ulong opt_slave_parallel_mode; extern ulong opt_binlog_commit_wait_count; extern ulong opt_binlog_commit_wait_usec; extern my_bool opt_gtid_ignore_duplicates; extern uint opt_gtid_cleanup_batch_size; extern ulong back_log; extern ulong executed_events; extern char language[FN_REFLEN]; extern "C" MYSQL_PLUGIN_IMPORT ulong server_id; extern ulong concurrency; extern time_t server_start_time, flush_status_time; extern char *opt_mysql_tmpdir, mysql_charsets_dir[]; extern size_t mysql_unpacked_real_data_home_len; extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list; extern const char *first_keyword, *delayed_user, *slave_user, *wsrep_user; extern MYSQL_PLUGIN_IMPORT const char *my_localhost; extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */ extern const char *myisam_recover_options_str; extern const LEX_CSTRING in_left_expr_name, in_additional_cond, in_having_cond; extern const LEX_CSTRING NULL_clex_str; extern const LEX_CSTRING error_clex_str; extern SHOW_VAR status_vars[]; extern struct system_variables max_system_variables; extern struct system_status_var global_status_var; extern struct my_rnd_struct sql_rand; extern const char *opt_date_time_formats[]; extern handlerton *partition_hton; extern handlerton *myisam_hton; extern handlerton *heap_hton; extern const char *load_default_groups[]; extern struct my_option my_long_options[]; int handle_early_options(); extern int MYSQL_PLUGIN_IMPORT mysqld_server_started; extern int mysqld_server_initialized; extern "C" MYSQL_PLUGIN_IMPORT int orig_argc; extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv; extern pthread_attr_t connection_attrib; extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; extern char err_shared_dir[]; extern ulong connection_errors_select; extern ulong connection_errors_accept; extern ulong connection_errors_tcpwrap; extern ulong connection_errors_internal; extern ulong connection_errors_max_connection; extern ulong connection_errors_peer_addr; extern ulong log_warnings; extern my_bool encrypt_binlog; extern my_bool encrypt_tmp_disk_tables, encrypt_tmp_files; extern ulong encryption_algorithm; extern const char *encryption_algorithm_names[]; extern long opt_secure_timestamp; extern uint default_password_lifetime; extern my_bool disconnect_on_expired_password; enum secure_timestamp { SECTIME_NO, SECTIME_SUPER, SECTIME_REPL, SECTIME_YES }; bool is_set_timestamp_forbidden(THD *thd); #ifdef HAVE_MMAP extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool, key_LOCK_pending_checkpoint; #endif /* HAVE_MMAP */ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_BINLOG_LOCK_binlog_background_thread, key_LOCK_binlog_end_pos, key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi, key_LOCK_crypt, key_LOCK_delayed_create, key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log, key_LOCK_gdl, key_LOCK_global_system_variables, key_LOCK_logger, key_LOCK_manager, key_LOCK_prepared_stmt_count, key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, key_LOCK_optimizer_costs, key_LOCK_thd_data, key_LOCK_thd_kill, key_LOCK_user_conn, key_LOG_LOCK_log, key_gtid_index_lock, key_master_info_data_lock, key_master_info_run_lock, key_master_info_sleep_lock, key_master_info_start_stop_lock, key_master_info_start_alter_lock, key_master_info_start_alter_list_lock, key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_rpl_group_info_sleep_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_TABLE_SHARE_LOCK_statistics, key_LOCK_start_thread, key_LOCK_error_messages, key_PARTITION_LOCK_auto_inc; extern PSI_mutex_key key_RELAYLOG_LOCK_index; extern PSI_mutex_key key_LOCK_relaylog_end_pos; extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry; extern PSI_mutex_key key_TABLE_SHARE_LOCK_share, key_LOCK_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, key_LOCK_global_index_stats, key_LOCK_wakeup_ready, key_LOCK_wait_commit, key_TABLE_SHARE_LOCK_rotation; extern PSI_mutex_key key_LOCK_gtid_waiting; extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock, key_LOCK_SEQUENCE, key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial, key_rwlock_THD_list; #ifdef HAVE_MMAP extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool; #endif /* HAVE_MMAP */ extern PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_BINLOG_COND_binlog_background_thread, key_BINLOG_COND_binlog_background_thread_end, key_COND_cache_status_changed, key_COND_manager, key_COND_rpl_status, key_COND_server_started, key_delayed_insert_cond, key_delayed_insert_cond_client, key_item_func_sleep_cond, key_master_info_data_cond, key_master_info_start_cond, key_master_info_stop_cond, key_master_info_sleep_cond, key_relay_log_info_data_cond, key_relay_log_info_log_space_cond, key_relay_log_info_start_cond, key_relay_log_info_stop_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_start_thread; extern PSI_cond_key key_RELAYLOG_COND_relay_log_updated, key_RELAYLOG_COND_bin_log_updated, key_COND_wakeup_ready, key_COND_wait_commit; extern PSI_cond_key key_RELAYLOG_COND_queue_busy; extern PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy; extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_queue, key_COND_rpl_thread_stop, key_COND_rpl_thread_pool, key_COND_parallel_entry, key_COND_group_commit_orderer; extern PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates; extern PSI_cond_key key_TABLE_SHARE_COND_rotation; extern PSI_thread_key key_thread_delayed_insert, key_thread_handle_manager, key_thread_kill_server, key_thread_main, key_thread_one_connection, key_thread_signal_hand, key_thread_slave_background, key_rpl_parallel_thread; extern PSI_file_key key_file_binlog, key_file_binlog_cache, key_file_binlog_index, key_file_binlog_index_cache, key_file_casetest, key_file_dbopt, key_file_ERRMSG, key_select_to_file, key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load, key_file_loadfile, key_file_log_event_data, key_file_log_event_info, key_file_master_info, key_file_misc, key_file_partition_ddl_log, key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog, key_file_trg, key_file_trn, key_file_init, key_file_log_ddl; extern PSI_file_key key_file_query_log, key_file_slow_log; extern PSI_file_key key_file_relaylog, key_file_relaylog_index, key_file_relaylog_cache, key_file_relaylog_index_cache; extern PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection; extern PSI_file_key key_file_binlog_state, key_file_gtid_index; #ifdef HAVE_des extern char* des_key_file; extern PSI_file_key key_file_des_key_file; extern PSI_mutex_key key_LOCK_des_key_file; extern mysql_mutex_t LOCK_des_key_file; #endif #ifdef HAVE_PSI_INTERFACE void init_server_psi_keys(); #endif /* HAVE_PSI_INTERFACE */ extern PSI_memory_key key_memory_locked_table_list; extern PSI_memory_key key_memory_locked_thread_list; extern PSI_memory_key key_memory_thd_transactions; extern PSI_memory_key key_memory_delegate; extern PSI_memory_key key_memory_acl_mem; extern PSI_memory_key key_memory_acl_memex; extern PSI_memory_key key_memory_acl_cache; extern PSI_memory_key key_memory_thd_main_mem_root; extern PSI_memory_key key_memory_help; extern PSI_memory_key key_memory_frm; extern PSI_memory_key key_memory_table_share; extern PSI_memory_key key_memory_gdl; extern PSI_memory_key key_memory_table_triggers_list; extern PSI_memory_key key_memory_prepared_statement_map; extern PSI_memory_key key_memory_prepared_statement_main_mem_root; extern PSI_memory_key key_memory_protocol_rset_root; extern PSI_memory_key key_memory_warning_info_warn_root; extern PSI_memory_key key_memory_sp_cache; extern PSI_memory_key key_memory_sp_head_main_root; extern PSI_memory_key key_memory_sp_head_execute_root; extern PSI_memory_key key_memory_sp_head_call_root; extern PSI_memory_key key_memory_table_mapping_root; extern PSI_memory_key key_memory_quick_range_select_root; extern PSI_memory_key key_memory_quick_index_merge_root; extern PSI_memory_key key_memory_quick_ror_intersect_select_root; extern PSI_memory_key key_memory_quick_ror_union_select_root; extern PSI_memory_key key_memory_quick_group_min_max_select_root; extern PSI_memory_key key_memory_test_quick_select_exec; extern PSI_memory_key key_memory_prune_partitions_exec; extern PSI_memory_key key_memory_binlog_recover_exec; extern PSI_memory_key key_memory_blob_mem_storage; extern PSI_memory_key key_memory_Sys_var_charptr_value; extern PSI_memory_key key_memory_THD_db; extern PSI_memory_key key_memory_user_var_entry; extern PSI_memory_key key_memory_user_var_entry_value; extern PSI_memory_key key_memory_Slave_job_group_group_relay_log_name; extern PSI_memory_key key_memory_Relay_log_info_group_relay_log_name; extern PSI_memory_key key_memory_binlog_cache_mngr; extern PSI_memory_key key_memory_binlog_gtid_index; extern PSI_memory_key key_memory_Row_data_memory_memory; extern PSI_memory_key key_memory_errmsgs; extern PSI_memory_key key_memory_Event_queue_element_for_exec_names; extern PSI_memory_key key_memory_Event_scheduler_scheduler_param; extern PSI_memory_key key_memory_Gis_read_stream_err_msg; extern PSI_memory_key key_memory_Geometry_objects_data; extern PSI_memory_key key_memory_host_cache_hostname; extern PSI_memory_key key_memory_User_level_lock; extern PSI_memory_key key_memory_Filesort_info_record_pointers; extern PSI_memory_key key_memory_Sort_param_tmp_buffer; extern PSI_memory_key key_memory_Filesort_info_merge; extern PSI_memory_key key_memory_Filesort_buffer_sort_keys; extern PSI_memory_key key_memory_handler_errmsgs; extern PSI_memory_key key_memory_handlerton; extern PSI_memory_key key_memory_XID; extern PSI_memory_key key_memory_MYSQL_LOCK; extern PSI_memory_key key_memory_MYSQL_LOG_name; extern PSI_memory_key key_memory_TC_LOG_MMAP_pages; extern PSI_memory_key key_memory_my_str_malloc; extern PSI_memory_key key_memory_MYSQL_BIN_LOG_basename; extern PSI_memory_key key_memory_MYSQL_BIN_LOG_index; extern PSI_memory_key key_memory_MYSQL_RELAY_LOG_basename; extern PSI_memory_key key_memory_MYSQL_RELAY_LOG_index; extern PSI_memory_key key_memory_rpl_filter; extern PSI_memory_key key_memory_Security_context; extern PSI_memory_key key_memory_NET_buff; extern PSI_memory_key key_memory_NET_compress_packet; extern PSI_memory_key key_memory_my_bitmap_map; extern PSI_memory_key key_memory_QUICK_RANGE_SELECT_mrr_buf_desc; extern PSI_memory_key key_memory_TABLE_RULE_ENT; extern PSI_memory_key key_memory_Mutex_cond_array_Mutex_cond; extern PSI_memory_key key_memory_Owned_gtids_sidno_to_hash; extern PSI_memory_key key_memory_Sid_map_Node; extern PSI_memory_key key_memory_bison_stack; extern PSI_memory_key key_memory_TABLE_sort_io_cache; extern PSI_memory_key key_memory_DATE_TIME_FORMAT; extern PSI_memory_key key_memory_DDL_LOG_MEMORY_ENTRY; extern PSI_memory_key key_memory_ST_SCHEMA_TABLE; extern PSI_memory_key key_memory_ignored_db; extern PSI_memory_key key_memory_SLAVE_INFO; extern PSI_memory_key key_memory_log_event_old; extern PSI_memory_key key_memory_HASH_ROW_ENTRY; extern PSI_memory_key key_memory_table_def_memory; extern PSI_memory_key key_memory_MPVIO_EXT_auth_info; extern PSI_memory_key key_memory_LOG_POS_COORD; extern PSI_memory_key key_memory_XID_STATE; extern PSI_memory_key key_memory_Rpl_info_file_buffer; extern PSI_memory_key key_memory_Rpl_info_table; extern PSI_memory_key key_memory_binlog_pos; extern PSI_memory_key key_memory_db_worker_hash_entry; extern PSI_memory_key key_memory_rpl_slave_command_buffer; extern PSI_memory_key key_memory_binlog_ver_1_event; extern PSI_memory_key key_memory_rpl_slave_check_temp_dir; extern PSI_memory_key key_memory_TABLE; extern PSI_memory_key key_memory_binlog_statement_buffer; extern PSI_memory_key key_memory_user_conn; extern PSI_memory_key key_memory_dboptions_hash; extern PSI_memory_key key_memory_dbnames_cache; extern PSI_memory_key key_memory_hash_index_key_buffer; extern PSI_memory_key key_memory_THD_handler_tables_hash; extern PSI_memory_key key_memory_JOIN_CACHE; extern PSI_memory_key key_memory_READ_INFO; extern PSI_memory_key key_memory_partition_syntax_buffer; extern PSI_memory_key key_memory_global_system_variables; extern PSI_memory_key key_memory_THD_variables; extern PSI_memory_key key_memory_PROFILE; extern PSI_memory_key key_memory_LOG_name; extern PSI_memory_key key_memory_string_iterator; extern PSI_memory_key key_memory_frm_extra_segment_buff; extern PSI_memory_key key_memory_frm_form_pos; extern PSI_memory_key key_memory_frm_string; extern PSI_memory_key key_memory_Unique_sort_buffer; extern PSI_memory_key key_memory_Unique_merge_buffer; extern PSI_memory_key key_memory_shared_memory_name; extern PSI_memory_key key_memory_opt_bin_logname; extern PSI_memory_key key_memory_Query_cache; extern PSI_memory_key key_memory_READ_RECORD_cache; extern PSI_memory_key key_memory_Quick_ranges; extern PSI_memory_key key_memory_File_query_log_name; extern PSI_memory_key key_memory_Table_trigger_dispatcher; extern PSI_memory_key key_memory_show_slave_status_io_gtid_set; extern PSI_memory_key key_memory_write_set_extraction; extern PSI_memory_key key_memory_thd_timer; extern PSI_memory_key key_memory_THD_Session_tracker; extern PSI_memory_key key_memory_THD_Session_sysvar_resource_manager; extern PSI_memory_key key_memory_get_all_tables; extern PSI_memory_key key_memory_fill_schema_schemata; extern PSI_memory_key key_memory_native_functions; extern PSI_memory_key key_memory_JSON; extern PSI_memory_key key_memory_WSREP; /* MAINTAINER: Please keep this list in order, to limit merge collisions. Hint: grep PSI_stage_info | sort -u */ extern PSI_stage_info stage_apply_event; extern PSI_stage_info stage_after_create; extern PSI_stage_info stage_after_opening_tables; extern PSI_stage_info stage_after_table_lock; extern PSI_stage_info stage_allocating_local_table; extern PSI_stage_info stage_alter_inplace_prepare; extern PSI_stage_info stage_alter_inplace; extern PSI_stage_info stage_alter_inplace_commit; extern PSI_stage_info stage_after_apply_event; extern PSI_stage_info stage_changing_master; extern PSI_stage_info stage_checking_master_version; extern PSI_stage_info stage_checking_permissions; extern PSI_stage_info stage_checking_privileges_on_cached_query; extern PSI_stage_info stage_checking_query_cache_for_query; extern PSI_stage_info stage_cleaning_up; extern PSI_stage_info stage_closing_tables; extern PSI_stage_info stage_connecting_to_master; extern PSI_stage_info stage_converting_heap_to_myisam; extern PSI_stage_info stage_copying_to_group_table; extern PSI_stage_info stage_copying_to_tmp_table; extern PSI_stage_info stage_copy_to_tmp_table; extern PSI_stage_info stage_creating_delayed_handler; extern PSI_stage_info stage_creating_sort_index; extern PSI_stage_info stage_creating_table; extern PSI_stage_info stage_creating_tmp_table; extern PSI_stage_info stage_deleting_from_main_table; extern PSI_stage_info stage_deleting_from_reference_tables; extern PSI_stage_info stage_discard_or_import_tablespace; extern PSI_stage_info stage_end; extern PSI_stage_info stage_ending_io_thread; extern PSI_stage_info stage_enabling_keys; extern PSI_stage_info stage_executing; extern PSI_stage_info stage_execution_of_init_command; extern PSI_stage_info stage_explaining; extern PSI_stage_info stage_finding_key_cache; extern PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog; extern PSI_stage_info stage_flushing_relay_log_and_master_info_repository; extern PSI_stage_info stage_flushing_relay_log_info_file; extern PSI_stage_info stage_freeing_items; extern PSI_stage_info stage_fulltext_initialization; extern PSI_stage_info stage_got_handler_lock; extern PSI_stage_info stage_got_old_table; extern PSI_stage_info stage_init; extern PSI_stage_info stage_init_update; extern PSI_stage_info stage_insert; extern PSI_stage_info stage_invalidating_query_cache_entries_table; extern PSI_stage_info stage_invalidating_query_cache_entries_table_list; extern PSI_stage_info stage_killing_slave; extern PSI_stage_info stage_logging_slow_query; extern PSI_stage_info stage_making_temp_file_append_before_load_data; extern PSI_stage_info stage_making_temp_file_create_before_load_data; extern PSI_stage_info stage_manage_keys; extern PSI_stage_info stage_master_has_sent_all_binlog_to_slave; extern PSI_stage_info stage_opening_tables; extern PSI_stage_info stage_optimizing; extern PSI_stage_info stage_preparing; extern PSI_stage_info stage_purging_old_relay_logs; extern PSI_stage_info stage_query_end; extern PSI_stage_info stage_starting_cleanup; extern PSI_stage_info stage_slave_sql_cleanup; extern PSI_stage_info stage_rollback; extern PSI_stage_info stage_rollback_implicit; extern PSI_stage_info stage_commit; extern PSI_stage_info stage_commit_implicit; extern PSI_stage_info stage_queueing_master_event_to_the_relay_log; extern PSI_stage_info stage_reading_event_from_the_relay_log; extern PSI_stage_info stage_recreating_table; extern PSI_stage_info stage_registering_slave_on_master; extern PSI_stage_info stage_removing_duplicates; extern PSI_stage_info stage_removing_tmp_table; extern PSI_stage_info stage_rename; extern PSI_stage_info stage_rename_result_table; extern PSI_stage_info stage_requesting_binlog_dump; extern PSI_stage_info stage_reschedule; extern PSI_stage_info stage_searching_rows_for_update; extern PSI_stage_info stage_sending_binlog_event_to_slave; extern PSI_stage_info stage_sending_cached_result_to_client; extern PSI_stage_info stage_sending_data; extern PSI_stage_info stage_setup; extern PSI_stage_info stage_slave_has_read_all_relay_log; extern PSI_stage_info stage_show_explain; extern PSI_stage_info stage_sorting; extern PSI_stage_info stage_sorting_for_group; extern PSI_stage_info stage_sorting_for_order; extern PSI_stage_info stage_sorting_result; extern PSI_stage_info stage_sql_thd_waiting_until_delay; extern PSI_stage_info stage_statistics; extern PSI_stage_info stage_storing_result_in_query_cache; extern PSI_stage_info stage_storing_row_into_queue; extern PSI_stage_info stage_system_lock; extern PSI_stage_info stage_unlocking_tables; extern PSI_stage_info stage_table_lock; extern PSI_stage_info stage_filling_schema_table; extern PSI_stage_info stage_update; extern PSI_stage_info stage_updating; extern PSI_stage_info stage_updating_main_table; extern PSI_stage_info stage_updating_reference_tables; extern PSI_stage_info stage_upgrading_lock; extern PSI_stage_info stage_user_lock; extern PSI_stage_info stage_user_sleep; extern PSI_stage_info stage_verifying_table; extern PSI_stage_info stage_waiting_for_ddl; extern PSI_stage_info stage_waiting_for_delay_list; extern PSI_stage_info stage_waiting_for_disk_space; extern PSI_stage_info stage_waiting_for_flush; extern PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log; extern PSI_stage_info stage_waiting_for_handler_insert; extern PSI_stage_info stage_waiting_for_handler_lock; extern PSI_stage_info stage_waiting_for_handler_open; extern PSI_stage_info stage_waiting_for_insert; extern PSI_stage_info stage_waiting_for_master_to_send_event; extern PSI_stage_info stage_waiting_for_master_update; extern PSI_stage_info stage_waiting_for_relay_log_space; extern PSI_stage_info stage_waiting_for_slave_mutex_on_exit; extern PSI_stage_info stage_waiting_for_slave_thread_to_start; extern PSI_stage_info stage_waiting_for_query_cache_lock; extern PSI_stage_info stage_waiting_for_table_flush; extern PSI_stage_info stage_waiting_for_the_next_event_in_relay_log; extern PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position; extern PSI_stage_info stage_waiting_to_finalize_termination; extern PSI_stage_info stage_binlog_waiting_background_tasks; extern PSI_stage_info stage_binlog_write; extern PSI_stage_info stage_binlog_processing_checkpoint_notify; extern PSI_stage_info stage_binlog_stopping_background_thread; extern PSI_stage_info stage_waiting_for_work_from_sql_thread; extern PSI_stage_info stage_waiting_for_prior_transaction_to_commit; extern PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit; extern PSI_stage_info stage_waiting_for_room_in_worker_thread; extern PSI_stage_info stage_waiting_for_workers_idle; extern PSI_stage_info stage_waiting_for_ftwrl; extern PSI_stage_info stage_waiting_for_ftwrl_threads_to_pause; extern PSI_stage_info stage_waiting_for_rpl_thread_pool; extern PSI_stage_info stage_master_gtid_wait_primary; extern PSI_stage_info stage_master_gtid_wait; extern PSI_stage_info stage_gtid_wait_other_connection; extern PSI_stage_info stage_slave_background_process_request; extern PSI_stage_info stage_slave_background_wait_request; extern PSI_stage_info stage_waiting_for_deadlock_kill; extern PSI_stage_info stage_starting; #ifdef WITH_WSREP // Aditional Galera thread states extern PSI_stage_info stage_waiting_isolation; extern PSI_stage_info stage_waiting_certification; extern PSI_stage_info stage_waiting_ddl; extern PSI_stage_info stage_waiting_flow; #endif /* WITH_WSREP */ #ifdef HAVE_PSI_STATEMENT_INTERFACE /** Statement instrumentation keys (sql). The last entry, at [SQLCOM_END], is for parsing errors. */ extern PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1]; /** Statement instrumentation keys (com). The last entry, at [COM_END], is for packet errors. */ extern PSI_statement_info com_statement_info[(uint) COM_END + 1]; /** Statement instrumentation key for replication. */ extern PSI_statement_info stmt_info_rpl; void init_sql_statement_info(); void init_com_statement_info(); #endif /* HAVE_PSI_STATEMENT_INTERFACE */ #ifndef _WIN32 extern pthread_t signal_thread; #endif #ifdef HAVE_OPENSSL extern struct st_VioSSLFd * ssl_acceptor_fd; extern LEX_CUSTRING ssl_acceptor_fingerprint(); #endif /* HAVE_OPENSSL */ /* The following variables were under INNODB_COMPABILITY_HOOKS */ extern my_bool opt_large_pages; extern uint opt_large_page_size; extern MYSQL_PLUGIN_IMPORT char lc_messages_dir[FN_REFLEN]; extern char *lc_messages_dir_ptr, *log_error_file_ptr; extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN]; extern MYSQL_PLUGIN_IMPORT uint reg_ext_length; extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names; extern MYSQL_PLUGIN_IMPORT bool mysqld_embedded; extern ulong specialflag; extern uint mysql_data_home_len; extern uint mysql_real_data_home_len; extern const char *mysql_real_data_home_ptr; extern ulong thread_handling; extern "C" MYSQL_PLUGIN_IMPORT char server_version[SERVER_VERSION_LENGTH]; extern char *server_version_ptr; extern MYSQL_PLUGIN_IMPORT char mysql_real_data_home[]; extern char mysql_unpacked_real_data_home[]; extern MYSQL_PLUGIN_IMPORT struct system_variables global_system_variables; extern char default_logfile_name[FN_REFLEN]; extern char *my_proxy_protocol_networks; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty; extern MYSQL_PLUGIN_IMPORT key_map key_map_full; /* Should be threaded as const */ /* Server mutex locks and condition variables. */ extern mysql_mutex_t LOCK_item_func_sleep, LOCK_status, LOCK_error_log, LOCK_delayed_insert, LOCK_short_uuid_generator, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_active_mi, LOCK_manager, LOCK_user_conn, LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_backup_log, LOCK_optimizer_costs; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_global_system_variables; extern mysql_rwlock_t LOCK_all_status_vars; extern mysql_mutex_t LOCK_start_thread; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_server_started; extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern mysql_rwlock_t LOCK_ssl_refresh; extern mysql_prlock_t LOCK_system_variables_hash; extern mysql_cond_t COND_start_thread; extern mysql_cond_t COND_manager; extern my_bool opt_use_ssl; extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key, *opt_ssl_crl, *opt_ssl_crlpath; extern ulonglong tls_version; #ifdef MYSQL_SERVER /** only options that need special treatment in get_one_option() deserve to be listed below */ enum options_mysqld { OPT_to_set_the_start_number=256, OPT_BINLOG_DO_DB, OPT_BINLOG_FORMAT, OPT_BINLOG_IGNORE_DB, OPT_BIN_LOG, OPT_BOOTSTRAP, OPT_COSTS_DISK_READ_COST, OPT_COSTS_INDEX_BLOCK_COPY_COST, OPT_COSTS_KEY_CMP_COST, OPT_COSTS_KEY_COPY_COST, OPT_COSTS_KEY_LOOKUP_COST, OPT_COSTS_KEY_NEXT_FIND_COST, OPT_COSTS_DISK_READ_RATIO, OPT_COSTS_ROW_COPY_COST, OPT_COSTS_ROW_LOOKUP_COST, OPT_COSTS_ROW_NEXT_FIND_COST, OPT_COSTS_ROWID_CMP_COST, OPT_COSTS_ROWID_COPY_COST, OPT_EXPIRE_LOGS_DAYS, OPT_BINLOG_EXPIRE_LOGS_SECONDS, OPT_CONSOLE, OPT_DEBUG_SYNC_TIMEOUT, OPT_REMOVED_OPTION, OPT_IGNORE_DB_DIRECTORY, OPT_ISAM_LOG, OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_AGE_THRESHOLD, OPT_KEY_CACHE_BLOCK_SIZE, OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_PARTITIONS, OPT_KEY_CACHE_CHANGED_BLOCKS_HASH_SIZE, OPT_LOG_BASENAME, OPT_LOG_ERROR, OPT_LOG_SLOW_FILTER, OPT_LOWER_CASE_TABLE_NAMES, OPT_PLUGIN_LOAD, OPT_PLUGIN_LOAD_ADD, OPT_PFS_INSTRUMENT, OPT_REPLICATE_DO_DB, OPT_REPLICATE_DO_TABLE, OPT_REPLICATE_IGNORE_DB, OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_REWRITE_DB, OPT_REPLICATE_WILD_DO_TABLE, OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_SAFE, OPT_SERVER_ID, OPT_SILENT, OPT_SKIP_HOST_CACHE, OPT_SLAVE_PARALLEL_MODE, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CERT, OPT_SSL_CIPHER, OPT_SSL_CRL, OPT_SSL_CRLPATH, OPT_SSL_KEY, OPT_WANT_CORE, OPT_MYSQL_COMPATIBILITY, OPT_TLS_VERSION, OPT_SECURE_AUTH, OPT_MYSQL_TO_BE_IMPLEMENTED, OPT_SEQURE_FILE_PRIV, OPT_which_is_always_the_last }; #endif /** Query type constants (usable as bitmap flags). */ enum enum_query_type { /// Nothing specific, ordinary SQL query. QT_ORDINARY= 0, /// In utf8. QT_TO_SYSTEM_CHARSET= (1 << 0), /// Without character set introducers. QT_WITHOUT_INTRODUCERS= (1 << 1), /// view internal representation (like QT_ORDINARY except ORDER BY clause) QT_VIEW_INTERNAL= (1 << 2), /// If identifiers should not include database names, where unambiguous QT_ITEM_IDENT_SKIP_DB_NAMES= (1 << 3), /// If identifiers should not include table names, where unambiguous QT_ITEM_IDENT_SKIP_TABLE_NAMES= (1 << 4), /// If Item_cache_wrapper should not print <expr_cache> QT_ITEM_CACHE_WRAPPER_SKIP_DETAILS= (1 << 5), /// If Item_subselect should print as just "(subquery#1)" /// rather than display the subquery body QT_ITEM_SUBSELECT_ID_ONLY= (1 << 6), /// If NULLIF(a,b) should print itself as /// CASE WHEN a_for_comparison=b THEN NULL ELSE a_for_return_value END /// when "a" was replaced to two different items /// (e.g. by equal fields propagation in optimize_cond()) /// or always as NULLIF(a, b). /// The default behaviour is to use CASE syntax when /// a_for_return_value is not the same as a_for_comparison. /// SHOW CREATE {VIEW|PROCEDURE|FUNCTION} and other cases where the /// original representation is required, should set this flag. QT_ITEM_ORIGINAL_FUNC_NULLIF= (1 << 7), /// good for parsing QT_PARSABLE= (1 << 8), // If an expression is constant, print the expression, not the value // it evaluates to. Should be used for error messages, so that they // don't reveal values. QT_NO_DATA_EXPANSION= (1 << 9), /// This value means focus on readability, not on ability to parse back, etc. QT_EXPLAIN= QT_TO_SYSTEM_CHARSET | QT_ITEM_IDENT_SKIP_DB_NAMES | QT_ITEM_CACHE_WRAPPER_SKIP_DETAILS | QT_ITEM_SUBSELECT_ID_ONLY, QT_SHOW_SELECT_NUMBER= (1<<10), /// Do not print database name or table name in the identifiers (even if /// this means the printout will be ambigous). It is assumed that the caller /// passing this flag knows what they are doing. QT_ITEM_IDENT_DISABLE_DB_TABLE_NAMES= (1 <<11), /// This is used for EXPLAIN EXTENDED extra warnings / Be more detailed /// Be more detailed than QT_EXPLAIN. /// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE /// here, as it would give better readable results QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET| QT_SHOW_SELECT_NUMBER, // Remove wrappers added for TVC when creating or showing view QT_NO_WRAPPERS_FOR_TVC_IN_VIEW= (1 << 12), /// Print for FRM file. Focus on parse-back. /// e.g. VIEW expressions and virtual column expressions QT_FOR_FRM= (1 << 13), // Print only the SELECT part, even for INSERT...SELECT QT_SELECT_ONLY = (1 << 14) }; /* query_id */ extern Atomic_counter<query_id_t> global_query_id; /* increment query_id and return it. */ inline __attribute__((warn_unused_result)) query_id_t next_query_id() { return global_query_id++; } inline query_id_t get_query_id() { return global_query_id; } /* increment global_thread_id and return it. */ extern __attribute__((warn_unused_result)) my_thread_id next_thread_id(void); /* TODO: Replace this with an inline function. */ #ifndef EMBEDDED_LIBRARY extern "C" void unireg_abort(int exit_code) __attribute__((noreturn)); #else extern "C" void unireg_clear(int exit_code); #define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0) #endif inline void table_case_convert(char * name, uint length) { if (lower_case_table_names) files_charset_info->casedn(name, length, name, length); } extern char *set_server_version(char *buf, size_t size); #define current_thd _current_thd() void set_current_thd(THD *thd); /* @todo remove, make it static in ha_maria.cc currently it's needed for sql_select.cc */ extern handlerton *maria_hton; extern uint64 global_gtid_counter; extern my_bool opt_gtid_strict_mode; extern my_bool opt_userstat_running, debug_assert_if_crashed_table; extern uint mysqld_extra_port; extern ulong opt_progress_report_time; extern ulong extra_max_connections; extern ulonglong denied_connections; extern ulong thread_created; extern scheduler_functions *thread_scheduler, *extra_thread_scheduler; extern char *opt_log_basename; extern my_bool opt_master_verify_checksum; extern my_bool opt_stack_trace, disable_log_notes; extern my_bool opt_expect_abort; extern my_bool opt_slave_sql_verify_checksum; extern my_bool opt_mysql56_temporal_format, strict_password_validation; extern ulong binlog_checksum_options; extern bool max_user_connections_checking; extern ulong opt_binlog_dbug_fsync_sleep; static const int SERVER_UID_SIZE= 29; extern char server_uid[SERVER_UID_SIZE+1]; extern uint volatile global_disable_checkpoint; extern my_bool opt_help; extern int mysqld_main(int argc, char **argv); #ifdef _WIN32 extern HANDLE hEventShutdown; extern void mysqld_win_initiate_shutdown(); extern void mysqld_win_set_startup_complete(); extern void mysqld_win_extend_service_timeout(DWORD sec); extern void mysqld_set_service_status_callback(void (*)(DWORD, DWORD, DWORD)); extern void mysqld_win_set_service_name(const char *name); #endif #endif /* MYSQLD_INCLUDED */ sql_show.h 0000644 00000023352 15156036160 0006564 0 ustar 00 /* Copyright (c) 2005, 2010, Oracle and/or its affiliates. Copyright (c) 2012, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_SHOW_H #define SQL_SHOW_H #include "sql_list.h" /* List */ #include "handler.h" /* enum_schema_tables */ #include "table.h" /* enum_schema_table_state */ #include "my_apc.h" /* Forward declarations */ class JOIN; class String; class THD; class sp_name; struct TABLE_LIST; typedef class st_select_lex SELECT_LEX; struct LEX; typedef struct st_mysql_show_var SHOW_VAR; typedef struct st_schema_table ST_SCHEMA_TABLE; struct TABLE; typedef struct system_status_var STATUS_VAR; /* Used by handlers to store things in schema tables */ #define IS_FILES_FILE_ID 0 #define IS_FILES_FILE_NAME 1 #define IS_FILES_FILE_TYPE 2 #define IS_FILES_TABLESPACE_NAME 3 #define IS_FILES_TABLE_CATALOG 4 #define IS_FILES_TABLE_SCHEMA 5 #define IS_FILES_TABLE_NAME 6 #define IS_FILES_LOGFILE_GROUP_NAME 7 #define IS_FILES_LOGFILE_GROUP_NUMBER 8 #define IS_FILES_ENGINE 9 #define IS_FILES_FULLTEXT_KEYS 10 #define IS_FILES_DELETED_ROWS 11 #define IS_FILES_UPDATE_COUNT 12 #define IS_FILES_FREE_EXTENTS 13 #define IS_FILES_TOTAL_EXTENTS 14 #define IS_FILES_EXTENT_SIZE 15 #define IS_FILES_INITIAL_SIZE 16 #define IS_FILES_MAXIMUM_SIZE 17 #define IS_FILES_AUTOEXTEND_SIZE 18 #define IS_FILES_CREATION_TIME 19 #define IS_FILES_LAST_UPDATE_TIME 20 #define IS_FILES_LAST_ACCESS_TIME 21 #define IS_FILES_RECOVER_TIME 22 #define IS_FILES_TRANSACTION_COUNTER 23 #define IS_FILES_VERSION 24 #define IS_FILES_ROW_FORMAT 25 #define IS_FILES_TABLE_ROWS 26 #define IS_FILES_AVG_ROW_LENGTH 27 #define IS_FILES_DATA_LENGTH 28 #define IS_FILES_MAX_DATA_LENGTH 29 #define IS_FILES_INDEX_LENGTH 30 #define IS_FILES_DATA_FREE 31 #define IS_FILES_CREATE_TIME 32 #define IS_FILES_UPDATE_TIME 33 #define IS_FILES_CHECK_TIME 34 #define IS_FILES_CHECKSUM 35 #define IS_FILES_STATUS 36 #define IS_FILES_EXTRA 37 typedef enum { WITHOUT_DB_NAME, WITH_DB_NAME } enum_with_db_name; int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond); int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, Table_specification_st *create_info_arg, enum_with_db_name with_db_name); int show_create_table_ex(THD *thd, TABLE_LIST *table_list, const char * forced_db, const char *forced_name, String *packet, Table_specification_st *create_info_arg, enum_with_db_name with_db_name); int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table); bool append_identifier(THD *thd, String *packet, const char *name, size_t length); static inline bool append_identifier(THD *thd, String *packet, const LEX_CSTRING *name) { return append_identifier(thd, packet, name->str, name->length); } bool append_identifier_opt_casedn(THD *thd, String *to, const LEX_CSTRING &ident, bool casedn); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd); bool mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, List<Item> *field_list, String *buffer); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list); bool mysqld_show_create_db(THD *thd, LEX_CSTRING *db_name, LEX_CSTRING *orig_db_name, const DDL_options_st &options); void mysqld_list_processes(THD *thd,const char *user,bool verbose); int mysqld_show_status(THD *thd); int mysqld_show_variables(THD *thd,const char *wild); bool mysqld_show_storage_engines(THD *thd); bool mysqld_show_authors(THD *thd); bool mysqld_show_contributors(THD *thd); bool mysqld_show_privileges(THD *thd); char *make_backup_log_name(char *buff, const char *name, const char* log_ext); uint calc_sum_of_all_status(STATUS_VAR *to); bool append_definer(THD *thd, String *buffer, const LEX_CSTRING *definer_user, const LEX_CSTRING *definer_host); int add_status_vars(SHOW_VAR *list); void remove_status_vars(SHOW_VAR *list); ulonglong get_status_vars_version(void); void init_status_vars(); void free_status_vars(); void reset_status_vars(); bool show_create_trigger(THD *thd, const sp_name *trg_name); void view_store_options(THD *thd, TABLE_LIST *table, String *buff); void init_fill_schema_files_row(TABLE* table); void initialize_information_schema_acl(); ST_SCHEMA_TABLE *find_schema_table(THD *thd, const LEX_CSTRING *table_name, bool *in_plugin); static inline ST_SCHEMA_TABLE *find_schema_table(THD *thd, const LEX_CSTRING *table_name) { bool unused; return find_schema_table(thd, table_name, &unused); } ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx); int make_schema_select(THD *thd, SELECT_LEX *sel, ST_SCHEMA_TABLE *schema_table); int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list); bool get_schema_tables_result(JOIN *join, enum enum_schema_table_state executed_place); enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list); const char* get_one_variable(THD *thd, const SHOW_VAR *variable, enum_var_type value_type, SHOW_TYPE show_type, system_status_var *status_var, const CHARSET_INFO **charset, char *buff, size_t *length); /* These functions were under INNODB_COMPATIBILITY_HOOKS */ int get_quote_char_for_identifier(THD *thd, const char *name, size_t length); THD *find_thread_by_id(longlong id, bool query_id= false); class select_result_explain_buffer; /* SHOW EXPLAIN/SHOW ANALYZE request object. */ class Show_explain_request : public Apc_target::Apc_call { public: THD *target_thd; /* thd that we're running SHOW EXPLAIN/ANALYZE for */ THD *request_thd; /* thd that run SHOW EXPLAIN/ANALYZE command */ /* Set to TRUE if you need the result in JSON format, FALSE - in traditional tabular */ bool is_json_format= false; /* FALSE for SHOW EXPLAIN, TRUE - for SHOW ANALYZE*/ bool is_analyze; /* If true, there was some error when producing EXPLAIN output. */ bool failed_to_produce; /* SHOW EXPLAIN/ANALYZE will be stored here */ select_result_explain_buffer *explain_buf; /* Query that we've got SHOW EXPLAIN/ANALYZE for */ String query_str; void call_in_target_thread() override; }; /** Condition pushdown used for INFORMATION_SCHEMA / SHOW queries. This structure is to implement an optimization when accessing data dictionary data in the INFORMATION_SCHEMA or SHOW commands. When the query contain a TABLE_SCHEMA or TABLE_NAME clause, narrow the search for data based on the constraints given. */ typedef struct st_lookup_field_values { /** Value of a TABLE_SCHEMA clause. Note that this value length may exceed @c NAME_LEN. @sa wild_db_value */ LEX_CSTRING db_value; /** Value of a TABLE_NAME clause. Note that this value length may exceed @c NAME_LEN. @sa wild_table_value */ LEX_CSTRING table_value; /** True when @c db_value is a LIKE clause, false when @c db_value is an '=' clause. */ bool wild_db_value; /** True when @c table_value is a LIKE clause, false when @c table_value is an '=' clause. */ bool wild_table_value; } LOOKUP_FIELD_VALUES; /* INFORMATION_SCHEMA: Execution plan for get_all_tables() call */ class IS_table_read_plan : public Sql_alloc { public: IS_table_read_plan() : no_rows(false), trivial_show_command(FALSE) {} bool no_rows; /* For EXPLAIN only: For SHOW KEYS and SHOW COLUMNS, we know which db_name.table_name will be read, however for some reason we don't set the fields in this->lookup_field_vals. In order to not have JOIN::save_explain_data() walking over uninitialized data, we set trivial_show_command=true. */ bool trivial_show_command; LOOKUP_FIELD_VALUES lookup_field_vals; Item *partial_cond; bool has_db_lookup_value() { return (lookup_field_vals.db_value.length && !lookup_field_vals.wild_db_value); } bool has_table_lookup_value() { return (lookup_field_vals.table_value.length && !lookup_field_vals.wild_table_value); } }; bool optimize_schema_tables_reads(JOIN *join); bool optimize_schema_tables_memory_usage(List<TABLE_LIST> &tables); /* Handle the ignored database directories list for SHOW/I_S. */ bool ignore_db_dirs_init(); void ignore_db_dirs_free(); void ignore_db_dirs_reset(); bool ignore_db_dirs_process_additions(); bool push_ignored_db_dir(const char *path); extern char *opt_ignore_db_dirs; #endif /* SQL_SHOW_H */ sql_delete.h 0000644 00000007024 15156036160 0007044 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DELETE_INCLUDED #define SQL_DELETE_INCLUDED #include "my_base.h" /* ha_rows */ #include "sql_class.h" /* enum_duplicates */ #include "sql_cmd.h" // Sql_cmd_dml #include "sql_base.h" class THD; struct TABLE_LIST; class Item; class select_result; typedef class Item COND; template <typename T> class SQL_I_List; /** @class Sql_cmd_delete - class used for any DELETE statements This class is derived from Sql_cmd_dml and contains implementations for abstract virtual function of the latter such as precheck() and prepare_inner(). It also overrides the implementation of execute_inner() providing a special handling for single-table delete statements that are not converted to multi-table delete. The class provides an object of the DML_prelocking_strategy class for the virtual function get_dml_prelocking_strategy(). */ class Sql_cmd_delete final : public Sql_cmd_dml { public: ha_rows deleted{0}; Sql_cmd_delete(bool multitable_arg) : orig_multitable(multitable_arg), multitable(multitable_arg), save_protocol(NULL) {} enum_sql_command sql_command_code() const override { return orig_multitable ? SQLCOM_DELETE_MULTI : SQLCOM_DELETE; } DML_prelocking_strategy *get_dml_prelocking_strategy() override { return &dml_prelocking_strategy; } bool processing_as_multitable_delete_prohibited(THD *thd); bool is_multitable() const { return multitable; } void set_as_multitable() { multitable= true; } void remove_order_by_without_limit(THD *thd); void get_dml_stat (ha_rows &found, ha_rows &changed) override { found= 0; changed= deleted; } protected: /** @brief Perform precheck of table privileges for delete statements */ bool precheck(THD *thd) override; /** @brief Perform context analysis for delete statements */ bool prepare_inner(THD *thd) override; /** @brief Perform optimization and execution actions needed for deletes */ bool execute_inner(THD *thd) override; private: /** @biefSpecial handling of single-table deletes after prepare phase */ bool delete_from_single_table(THD *thd); /* Original value of the 'multitable' flag set by constructor */ const bool orig_multitable; /* True if the statement is a multitable delete or converted to such. For a single-table delete this flag is set to true if the statement is supposed to be converted to multi-table delete. */ bool multitable; /* The prelocking strategy used when opening the used tables */ DML_prelocking_strategy dml_prelocking_strategy; List<Item> empty_list; /**< auxiliary empty list used by prepare_inner() */ Protocol *save_protocol; /**< needed for ANALYZE .. DELETE .. RETURNING */ }; #endif /* SQL_DELETE_INCLUDED */ item_cmpfunc.h 0000644 00000411326 15156036160 0007400 0 ustar 00 #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* compare and test functions */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "item_func.h" /* Item_int_func, Item_bool_func */ #include "item.h" #include "opt_rewrite_date_cmp.h" extern Item_result item_cmp_type(Item_result a,Item_result b); inline Item_result item_cmp_type(const Item *a, const Item *b) { return item_cmp_type(a->cmp_type(), b->cmp_type()); } inline Item_result item_cmp_type(Item_result a, const Item *b) { return item_cmp_type(a, b->cmp_type()); } class Item_bool_func2; class Arg_comparator; typedef int (Arg_comparator::*arg_cmp_func)(); typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg); class Arg_comparator: public Sql_alloc { Item **a, **b; const Type_handler *m_compare_handler; CHARSET_INFO *m_compare_collation; arg_cmp_func func; Item_func_or_sum *owner; bool set_null; // TRUE <=> set owner->null_value Arg_comparator *comparators; // used only for compare_row() double precision; /* Fields used in DATE/DATETIME comparison. */ Item *a_cache, *b_cache; // Cached values of a and b items // when one of arguments is NULL. int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, const Type_handler *compare_handler, Item **a1, Item **a2); int compare_not_null_values(longlong val1, longlong val2) { if (set_null) owner->null_value= false; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } NativeBuffer<STRING_BUFFER_USUAL_SIZE> m_native1, m_native2; public: /* Allow owner function to use string buffers. */ String value1, value2; Arg_comparator(): m_compare_handler(&type_handler_null), m_compare_collation(&my_charset_bin), set_null(TRUE), comparators(0), a_cache(0), b_cache(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), m_compare_handler(&type_handler_null), m_compare_collation(&my_charset_bin), set_null(TRUE), comparators(0), a_cache(0), b_cache(0) {}; public: bool set_cmp_func_for_row_arguments(THD *thd); bool set_cmp_func_row(THD *thd); bool set_cmp_func_string(THD *thd); bool set_cmp_func_time(THD *thd); bool set_cmp_func_datetime(THD *thd); bool set_cmp_func_native(THD *thd); bool set_cmp_func_int(THD *thd); bool set_cmp_func_real(THD *thd); bool set_cmp_func_decimal(THD *thd); inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, const Type_handler *compare_handler, Item **a1, Item **a2, bool set_null_arg) { set_null= set_null_arg; return set_cmp_func(thd, owner_arg, compare_handler, a1, a2); } int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, Item **a1, Item **a2, bool set_null_arg) { Item *tmp_args[2]= { *a1, *a2 }; Type_handler_hybrid_field_type tmp; if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(), tmp_args, 2, false)) return 1; return set_cmp_func(thd, owner_arg, tmp.type_handler(), a1, a2, set_null_arg); } inline int compare() { return (this->*func)(); } int compare_string(); // compare args[0] & args[1] int compare_real(); // compare args[0] & args[1] int compare_decimal(); // compare args[0] & args[1] int compare_int_signed(); // compare args[0] & args[1] int compare_int_signed_unsigned(); int compare_int_unsigned_signed(); int compare_int_unsigned(); int compare_row(); // compare args[0] & args[1] int compare_e_string(); // compare args[0] & args[1] int compare_e_real(); // compare args[0] & args[1] int compare_e_decimal(); // compare args[0] & args[1] int compare_e_int(); // compare args[0] & args[1] int compare_e_int_diff_signedness(); int compare_e_row(); // compare args[0] & args[1] int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); int compare_e_datetime(); int compare_time(); int compare_e_time(); int compare_native(); int compare_e_native(); int compare_json_str_basic(Item *j, Item *s); int compare_json_str(); int compare_str_json(); int compare_e_json_str_basic(Item *j, Item *s); int compare_e_json_str(); int compare_e_str_json(); void min_max_update_field_native(THD *thd, Field *field, Item *item, int cmp_sign); Item** cache_converted_constant(THD *thd, Item **value, Item **cache, const Type_handler *type); inline bool is_owner_equal_func() { return (owner->type() == Item::FUNC_ITEM && ((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC); } const Type_handler *compare_type_handler() const { return m_compare_handler; } Item_result compare_type() const { return m_compare_handler->cmp_type(); } CHARSET_INFO *compare_collation() const { return m_compare_collation; } Arg_comparator *subcomparators() const { return comparators; } void cleanup() { delete [] comparators; comparators= 0; } friend class Item_func; friend class Item_bool_rowready_func2; }; class SEL_ARG; struct KEY_PART; class Item_bool_func :public Item_int_func, public Type_cmp_attributes { protected: /* Build a SEL_TREE for a simple predicate @param param PARAM from SQL_SELECT::test_quick_select @param field field in the predicate @param value constant in the predicate @return Pointer to the tree built tree */ virtual SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) { DBUG_ENTER("Item_bool_func::get_func_mm_tree"); DBUG_ASSERT(0); DBUG_RETURN(0); } /* Return the full select tree for "field_item" and "value": - a single SEL_TREE if the field is not in a multiple equality, or - a conjunction of all SEL_TREEs for all fields from the same multiple equality with "field_item". */ SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, Item_field *field_item, Item *value); /** Test if "item" and "value" are suitable for the range optimization and get their full select tree. "Suitable" means: - "item" is a field or a field reference - "value" is NULL (e.g. WHERE field IS NULL), or "value" is an unexpensive item (e.g. WHERE field OP value) @param item - the argument that is checked to be a field @param value - the other argument @returns - NULL if the arguments are not suitable for the range optimizer. @returns - the full select tree if the arguments are suitable. */ SEL_TREE *get_full_func_mm_tree_for_args(RANGE_OPT_PARAM *param, Item *item, Item *value) { DBUG_ENTER("Item_bool_func::get_full_func_mm_tree_for_args"); Item *field= item->real_item(); if (field->type() == Item::FIELD_ITEM && !field->const_item() && (!value || !value->is_expensive())) DBUG_RETURN(get_full_func_mm_tree(param, (Item_field *) field, value)); DBUG_RETURN(NULL); } SEL_TREE *get_mm_parts(RANGE_OPT_PARAM *param, Field *field, Item_func::Functype type, Item *value); SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *lt_value, Item *gt_value); virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value); void raise_note_if_key_become_unused(THD *thd, const Item_args &old_args); public: Item_bool_func(THD *thd): Item_int_func(thd) {} Item_bool_func(THD *thd, Item *a): Item_int_func(thd, a) {} Item_bool_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { } Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} const Type_handler *type_handler() const override { return &type_handler_bool; } const Type_handler *fixed_type_handler() const override { return &type_handler_bool; } CHARSET_INFO *compare_collation() const override { return NULL; } longlong val_int() override final { DBUG_ASSERT(!is_cond()); return val_bool(); } bool val_bool() override= 0; String *val_str(String *str) override final { DBUG_ASSERT(fixed()); bool res= val_bool(); if (null_value) return 0; str->set_int(res, false, collation.collation); return str; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=1; return FALSE; } decimal_digits_t decimal_precision() const override { return 1; } bool need_parentheses_in_default() override { return true; } }; /** Abstract Item class, to represent <code>X IS [NOT] (TRUE | FALSE)</code> boolean predicates. */ class Item_func_truth : public Item_bool_func { public: bool val_bool() override; bool fix_length_and_dec(THD *thd) override; void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return CMP_PRECEDENCE; } table_map not_null_tables() const override { return is_top_level_item() ? not_null_tables_cache : 0; } protected: Item_func_truth(THD *thd, Item *a, bool a_value, bool a_affirmative): Item_bool_func(thd, a), value(a_value), affirmative(a_affirmative) {} ~Item_func_truth() = default; private: /** True for <code>X IS [NOT] TRUE</code>, false for <code>X IS [NOT] FALSE</code> predicates. */ const bool value; /** True for <code>X IS Y</code>, false for <code>X IS NOT Y</code> predicates. */ const bool affirmative; }; /** This Item represents a <code>X IS TRUE</code> boolean predicate. */ class Item_func_istrue : public Item_func_truth { public: Item_func_istrue(THD *thd, Item *a): Item_func_truth(thd, a, true, true) {} ~Item_func_istrue() = default; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("istrue") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_istrue>(thd, this); } }; /** This Item represents a <code>X IS NOT TRUE</code> boolean predicate. */ class Item_func_isnottrue : public Item_func_truth { public: Item_func_isnottrue(THD *thd, Item *a): Item_func_truth(thd, a, true, false) {} ~Item_func_isnottrue() = default; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("isnottrue") }; return name; } bool find_not_null_fields(table_map allowed) override { return false; } bool eval_not_null_tables(void *) override { not_null_tables_cache= 0; return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isnottrue>(thd, this); } }; /** This Item represents a <code>X IS FALSE</code> boolean predicate. */ class Item_func_isfalse : public Item_func_truth { public: Item_func_isfalse(THD *thd, Item *a): Item_func_truth(thd, a, false, true) {} ~Item_func_isfalse() = default; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("isfalse") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isfalse>(thd, this); } }; /** This Item represents a <code>X IS NOT FALSE</code> boolean predicate. */ class Item_func_isnotfalse : public Item_func_truth { public: Item_func_isnotfalse(THD *thd, Item *a): Item_func_truth(thd, a, false, false) {} ~Item_func_isnotfalse() = default; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("isnotfalse") }; return name; } bool find_not_null_fields(table_map allowed) override { return false; } bool eval_not_null_tables(void *) override { not_null_tables_cache= 0; return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isnotfalse>(thd, this); } }; class Item_cache; #define UNKNOWN (-1) /* Item_in_optimizer(left_expr, Item_in_subselect(...)) Item_in_optimizer is used to wrap an instance of Item_in_subselect. This class does the following: - Evaluate the left expression and store it in Item_cache_* object (to avoid re-evaluating it many times during subquery execution) - Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we don't care if the result is NULL or FALSE. NOTE It is not quite clear why the above listed functionality should be placed into a separate class called 'Item_in_optimizer'. */ class Item_in_optimizer: public Item_bool_func { protected: Item_cache *cache; Item *expr_cache; /* Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries: UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated FALSE - result is FALSE TRUE - result is NULL */ int result_for_null_param; public: Item_in_optimizer(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b), cache(0), expr_cache(0), result_for_null_param(UNKNOWN) { with_flags|= item_with_t::SUBQUERY; } bool fix_fields(THD *, Item **) override; bool fix_left(THD *thd); table_map not_null_tables() const override { return 0; } bool is_null() override; bool val_bool() override; void cleanup() override; enum Functype functype() const override { return IN_OPTIMIZER_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<in_optimizer>") }; return name; } Item_cache **get_cache() { return &cache; } Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override; Item *expr_cache_insert_transformer(THD *thd, uchar *unused) override; bool is_expensive_processor(void *arg) override; bool is_expensive() override; void set_join_tab_idx(uint8 join_tab_idx_arg) override { args[1]->set_join_tab_idx(join_tab_idx_arg); } void get_cache_parameters(List<Item> ¶meters) override; bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; bool invisible_mode(); bool walk(Item_processor processor, bool walk_subquery, void *arg) override; void reset_cache() { cache= NULL; } void print(String *str, enum_query_type query_type) override; void restore_first_argument(); Item* get_wrapped_in_subselect_item() { return args[1]; } enum precedence precedence() const override { return args[1]->precedence(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_in_optimizer>(thd, this); } }; /* Functions and operators with two arguments that can use range optimizer. */ class Item_bool_func2 :public Item_bool_func { /* Bool with 2 string args */ protected: void add_key_fields_optimize_op(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables, bool equal_func); public: Item_bool_func2(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b) { } bool is_null() override { return MY_TEST(args[0]->is_null() || args[1]->is_null()); } COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level) override; bool count_sargable_conds(void *arg) override; /* Specifies which result type the function uses to compare its arguments. This method is used in equal field propagation. */ virtual const Type_handler *compare_type_handler() const { /* Have STRING_RESULT by default, which means the function compares val_str() results of the arguments. This is suitable for Item_func_like and for Item_func_spatial_rel. Note, Item_bool_rowready_func2 overrides this default behaviour. */ return &type_handler_varchar; } SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override { DBUG_ENTER("Item_bool_func2::get_mm_tree"); DBUG_ASSERT(arg_count == 2); SEL_TREE *ftree= get_full_func_mm_tree_for_args(param, args[0], args[1]); if (!ftree) ftree= Item_func::get_mm_tree(param, cond_ptr); DBUG_RETURN(ftree); } }; /** A class for functions and operators that can use the range optimizer and have a reverse function/operator that can also use the range optimizer, so this condition: WHERE value OP field can be optimized as equivalent to: WHERE field REV_OP value This class covers: - scalar comparison predicates: <, <=, =, <=>, >=, > - MBR and precise spatial relation predicates (e.g. SP_TOUCHES(x,y)) For example: WHERE 10 > field can be optimized as: WHERE field < 10 */ class Item_bool_func2_with_rev :public Item_bool_func2 { protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override { DBUG_ENTER("Item_bool_func2_with_rev::get_func_mm_tree"); Item_func::Functype func_type= (value != arguments()[0]) ? functype() : rev_functype(); DBUG_RETURN(get_mm_parts(param, field, func_type, value)); } public: Item_bool_func2_with_rev(THD *thd, Item *a, Item *b): Item_bool_func2(thd, a, b) { } virtual enum Functype rev_functype() const= 0; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override { DBUG_ENTER("Item_bool_func2_with_rev::get_mm_tree"); DBUG_ASSERT(arg_count == 2); SEL_TREE *ftree; /* Even if get_full_func_mm_tree_for_args(param, args[0], args[1]) will not return a range predicate it may still be possible to create one by reversing the order of the operands. Note that this only applies to predicates where both operands are fields. Example: A query of the form WHERE t1.a OP t2.b In this case, args[0] == t1.a and args[1] == t2.b. When creating range predicates for t2, get_full_func_mm_tree_for_args(param, args[0], args[1]) will return NULL because 'field' belongs to t1 and only predicates that applies to t2 are of interest. In this case a call to get_full_func_mm_tree_for_args() with reversed operands may succeed. */ if (!(ftree= get_full_func_mm_tree_for_args(param, args[0], args[1])) && !(ftree= get_full_func_mm_tree_for_args(param, args[1], args[0]))) ftree= Item_func::get_mm_tree(param, cond_ptr); DBUG_RETURN(ftree); } }; class Item_bool_rowready_func2 :public Item_bool_func2_with_rev { protected: Arg_comparator cmp; bool check_arguments() const override { return check_argument_types_like_args0(); } public: Item_bool_rowready_func2(THD *thd, Item *a, Item *b): Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1) { } Sql_mode_dependency value_depends_on_sql_mode() const override; void print(String *str, enum_query_type query_type) override { Item_func::print_op(str, query_type); } enum precedence precedence() const override { return CMP_PRECEDENCE; } Item *neg_transformer(THD *thd) override; virtual Item *negated_item(THD *thd); Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { Item_args::propagate_equal_fields(thd, Context(ANY_SUBST, cmp.compare_type_handler(), compare_collation()), cond); return this; } bool fix_length_and_dec(THD *thd) override; bool fix_length_and_dec_generic(THD *thd, const Type_handler *compare_handler) { DBUG_ASSERT(args == tmp_arg); return cmp.set_cmp_func(thd, this, compare_handler, tmp_arg, tmp_arg + 1, true/*set_null*/); } int set_cmp_func(THD *thd) { DBUG_ASSERT(args == tmp_arg); return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true/*set_null*/); } CHARSET_INFO *compare_collation() const override { return cmp.compare_collation(); } const Type_handler *compare_type_handler() const override { return cmp.compare_type_handler(); } Arg_comparator *get_comparator() { return &cmp; } void cleanup() override { Item_bool_func2::cleanup(); cmp.cleanup(); } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override { return add_key_fields_optimize_op(join, key_fields, and_level, usable_tables, sargables, false); } Item *deep_copy(THD *thd) const override { Item_bool_rowready_func2 *clone= (Item_bool_rowready_func2 *) Item_func::deep_copy(thd); if (clone) { clone->cmp.comparators= 0; } return clone; } }; /** XOR inherits from Item_bool_func because it is not optimized yet. Later, when XOR is optimized, it needs to inherit from Item_cond instead. See WL#5800. */ class Item_func_xor :public Item_bool_func { public: Item_func_xor(THD *thd, Item *i1, Item *i2): Item_bool_func(thd, i1, i2) {} enum Functype functype() const override { return XOR_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("xor") }; return name; } enum precedence precedence() const override { return XOR_PRECEDENCE; } void print(String *str, enum_query_type query_type) override { Item_func::print_op(str, query_type); } bool val_bool() override; bool find_not_null_fields(table_map allowed) override { return false; } Item *neg_transformer(THD *thd) override; Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { Item_args::propagate_equal_fields(thd, Context_boolean(), cond); return this; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_xor>(thd, this); } }; class Item_func_not :public Item_bool_func { public: Item_func_not(THD *thd, Item *a): Item_bool_func(thd, a) {} bool val_bool() override; enum Functype functype() const override { return NOT_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("not") }; return name; } bool find_not_null_fields(table_map allowed) override { return false; } enum precedence precedence() const override { return NEG_PRECEDENCE; } Item *neg_transformer(THD *thd) override; bool fix_fields(THD *, Item **) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_not>(thd, this); } }; class Item_maxmin_subselect; /* trigcond<param>(arg) ::= param? arg : TRUE The class Item_func_trig_cond is used for guarded predicates which are employed only for internal purposes. A guarded predicate is an object consisting of an a regular or a guarded predicate P and a pointer to a boolean guard variable g. A guarded predicate P/g is evaluated to true if the value of the guard g is false, otherwise it is evaluated to the same value that the predicate P: val(P/g)= g ? val(P):true. Guarded predicates allow us to include predicates into a conjunction conditionally. Currently they are utilized for pushed down predicates in queries with outer join operations. In the future, probably, it makes sense to extend this class to the objects consisting of three elements: a predicate P, a pointer to a variable g and a firing value s with following evaluation rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only one item for the objects of the form P/g1/g2... Objects of this class are built only for query execution after the execution plan has been already selected. That's why this class needs only val_int out of generic methods. Current uses of Item_func_trig_cond objects: - To wrap selection conditions when executing outer joins - To wrap condition that is pushed down into subquery */ class Item_func_trig_cond: public Item_bool_func { bool *trig_var; public: Item_func_trig_cond(THD *thd, Item *a, bool *f): Item_bool_func(thd, a) { trig_var= f; } bool val_bool() override { return *trig_var ? args[0]->val_bool() : true; } enum Functype functype() const override { return TRIG_COND_FUNC; }; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("trigcond") }; return name; } bool const_item() const override { return FALSE; } bool *get_trig_var() { return trig_var; } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trig_cond>(thd, this); } }; class Item_func_not_all :public Item_func_not { /* allow to check presence of values in max/min optimization */ Item_sum_min_max *test_sum_item; Item_maxmin_subselect *test_sub_item; public: bool show; Item_func_not_all(THD *thd, Item *a): Item_func_not(thd, a), test_sum_item(0), test_sub_item(0), show(0) {} table_map not_null_tables() const override { return 0; } bool val_bool() override; enum Functype functype() const override { return NOT_ALL_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<not>") }; return name; } enum precedence precedence() const override { return show ? Item_func::precedence() : args[0]->precedence(); } bool fix_fields(THD *thd, Item **ref) override { return Item_func::fix_fields(thd, ref);} void print(String *str, enum_query_type query_type) override; void set_sum_test(Item_sum_min_max *item) { test_sum_item= item; test_sub_item= 0; }; void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; test_sum_item= 0;}; bool empty_underlying_subquery(); Item *neg_transformer(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_not_all>(thd, this); } }; class Item_func_nop_all :public Item_func_not_all { public: Item_func_nop_all(THD *thd, Item *a): Item_func_not_all(thd, a) {} bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<nop>") }; return name; } Item *neg_transformer(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_nop_all>(thd, this); } }; class Item_func_eq :public Item_bool_rowready_func2 { public: Item_func_eq(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b), in_equality_no(UINT_MAX) {} bool val_bool() override; enum Functype functype() const override { return EQ_FUNC; } enum Functype rev_functype() const override { return EQ_FUNC; } cond_result eq_cmp_result() const override { return COND_TRUE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("=") }; return name; } Item *negated_item(THD *thd) override; COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override { return add_key_fields_optimize_op(join, key_fields, and_level, usable_tables, sargables, true); } bool check_equality(THD *thd, COND_EQUAL *cond, List<Item> *eq_list) override; /* - If this equality is created from the subquery's IN-equality: number of the item it was created from, e.g. for (a,b) IN (SELECT c,d ...) a=c will have in_equality_no=0, and b=d will have in_equality_no=1. - Otherwise, UINT_MAX */ uint in_equality_no; uint exists2in_reserved_items() override { return 1; }; friend class Arg_comparator; Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } Item* varchar_upper_cmp_transformer(THD *thd, uchar *arg) override; Item *deep_copy(THD *thd) const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_eq>(thd, this); } }; class Item_func_equal final :public Item_bool_rowready_func2 { public: Item_func_equal(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {} bool val_bool() override; bool fix_length_and_dec(THD *thd) override; table_map not_null_tables() const override { return 0; } bool find_not_null_fields(table_map allowed) override { return false; } enum Functype functype() const override { return EQUAL_FUNC; } enum Functype rev_functype() const override { return EQUAL_FUNC; } cond_result eq_cmp_result() const override { return COND_TRUE; } bool is_null() override { return false; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<=>") }; return name; } Item *neg_transformer(THD *thd) override { return 0; } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override { return add_key_fields_optimize_op(join, key_fields, and_level, usable_tables, sargables, true); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_equal>(thd, this); } }; class Item_func_ge :public Item_bool_rowready_func2 { public: Item_func_ge(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {}; bool val_bool() override; enum Functype functype() const override { return GE_FUNC; } enum Functype rev_functype() const override { return LE_FUNC; } cond_result eq_cmp_result() const override { return COND_TRUE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN(">=") }; return name; } Item *negated_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ge>(thd, this); } Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } }; class Item_func_gt :public Item_bool_rowready_func2 { public: Item_func_gt(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {}; bool val_bool() override; enum Functype functype() const override { return GT_FUNC; } enum Functype rev_functype() const override { return LT_FUNC; } cond_result eq_cmp_result() const override { return COND_FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN(">") }; return name; } Item *negated_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_gt>(thd, this); } Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } }; class Item_func_le :public Item_bool_rowready_func2 { public: Item_func_le(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {}; bool val_bool() override; enum Functype functype() const override { return LE_FUNC; } enum Functype rev_functype() const override { return GE_FUNC; } cond_result eq_cmp_result() const override { return COND_TRUE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<=") }; return name; } Item *negated_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_le>(thd, this); } Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } }; class Item_func_lt :public Item_bool_rowready_func2 { public: Item_func_lt(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {} bool val_bool() override; enum Functype functype() const override { return LT_FUNC; } enum Functype rev_functype() const override { return GT_FUNC; } cond_result eq_cmp_result() const override { return COND_FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<") }; return name; } Item *negated_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_lt>(thd, this); } Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } }; class Item_func_ne :public Item_bool_rowready_func2 { protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override; public: Item_func_ne(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {} bool val_bool() override; enum Functype functype() const override { return NE_FUNC; } enum Functype rev_functype() const override { return NE_FUNC; } cond_result eq_cmp_result() const override { return COND_FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<>") }; return name; } Item *negated_item(THD *thd) override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ne>(thd, this); } }; /* The class Item_func_opt_neg is defined to factor out the functionality common for the classes Item_func_between and Item_func_in. The objects of these classes can express predicates or there negations. The alternative approach would be to create pairs Item_func_between, Item_func_notbetween and Item_func_in, Item_func_notin. */ class Item_func_opt_neg :public Item_bool_func { protected: /* The data type handler that will be used for comparison. Data type handlers of all arguments are mixed to here. */ Type_handler_hybrid_field_type m_comparator; /* The collation that will be used for comparison in case when m_compare_type is STRING_RESULT. */ DTCollation cmp_collation; public: bool negated; /* <=> the item represents NOT <func> */ public: Item_func_opt_neg(THD *thd, Item *a, Item *b, Item *c): Item_bool_func(thd, a, b, c), negated(0) {} Item_func_opt_neg(THD *thd, List<Item> &list): Item_bool_func(thd, list), negated(0) {} public: Item *neg_transformer(THD *thd) override { negated= !negated; return this; } bool eq(const Item *item, const Eq_config &config) const override; CHARSET_INFO *compare_collation() const override { return cmp_collation.collation; } Item *propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override= 0; }; class Item_func_between :public Item_func_opt_neg { /* If the types of the arguments to BETWEEN permit, then: WHERE const1 BETWEEN expr2 AND field1 can be optimized as if it was just: WHERE const1 <= field1 as expr2 could be an arbitrary expression. More generally, this optimization is permitted if aggregation for comparison for three expressions (const1,const2,field1) and for two expressions (const1,field1) return the same type handler. @param [IN] field_item - This is a field from the right side of the BETWEEN operator. */ bool can_optimize_range_const(Item_field *field_item) const; protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override; bool val_int_cmp_int_finalize(longlong value, longlong a, longlong b); public: String value0,value1,value2; Item_func_between(THD *thd, Item *a, Item *b, Item *c): Item_func_opt_neg(thd, a, b, c) { } bool val_bool() override { DBUG_ASSERT(fixed()); return m_comparator.type_handler()->Item_func_between_val_int(this); } enum Functype functype() const override { return BETWEEN; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("between") }; return name; } enum precedence precedence() const override { return BETWEEN_PRECEDENCE; } bool fix_length_and_dec(THD *thd) override; bool fix_length_and_dec_string(THD *) { return agg_arg_charsets_for_comparison(cmp_collation, args, 3); } bool fix_length_and_dec_temporal(THD *); bool fix_length_and_dec_numeric(THD *); void print(String *str, enum_query_type query_type) override; bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; bool count_sargable_conds(void *arg) override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { Item_args::propagate_equal_fields(thd, Context(ANY_SUBST, m_comparator.type_handler(), compare_collation()), cond); return this; } longlong val_int_cmp_string(); longlong val_int_cmp_datetime(); longlong val_int_cmp_time(); longlong val_int_cmp_native(); longlong val_int_cmp_int(); longlong val_int_cmp_real(); longlong val_int_cmp_decimal(); protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_between>(thd, this); } }; class Item_func_strcmp :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_str(0, 2); } String value1, value2; DTCollation cmp_collation; public: Item_func_strcmp(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {} longlong val_int() override; decimal_digits_t decimal_precision() const override { return 1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("strcmp") }; return name; } bool fix_length_and_dec(THD *thd) override { if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) return TRUE; fix_char_length(2); // returns "1" or "0" or "-1" return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_strcmp>(thd, this); } }; struct interval_range { Item_result type; double dbl; my_decimal dec; }; class Item_func_interval :public Item_long_func { Item_row *row; bool use_decimal_comparison; interval_range *intervals; bool check_arguments() const override { return check_argument_types_like_args0(); } public: Item_func_interval(THD *thd, Item_row *a): Item_long_func(thd, a), row(a), intervals(0) { } longlong val_int() override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("interval") }; return name; } decimal_digits_t decimal_precision() const override { return 2; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); print_args(str, 0, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_interval>(thd, this); } }; class Item_func_coalesce :public Item_func_case_expression { public: Item_func_coalesce(THD *thd, Item *a, Item *b): Item_func_case_expression(thd, a, b) {} Item_func_coalesce(THD *thd, List<Item> &list): Item_func_case_expression(thd, list) {} double real_op() override; longlong int_op() override; String *str_op(String *) override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; bool native_op(THD *thd, Native *to) override; bool fix_length_and_dec(THD *thd) override { update_nullability_post_fix_fields(); if (aggregate_for_result(func_name_cstring(), args, arg_count, true)) return TRUE; fix_attributes(args, arg_count); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("coalesce") }; return name; } table_map not_null_tables() const override { return 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_coalesce>(thd, this); } }; /* Case abbreviations that aggregate its result field type by two arguments: IFNULL(arg1, arg2) IF(switch, arg1, arg2) NVL2(switch, arg1, arg2) */ class Item_func_case_abbreviation2 :public Item_func_case_expression { protected: bool fix_length_and_dec2(Item **items) { if (aggregate_for_result(func_name_cstring(), items, 2, true)) return TRUE; fix_attributes(items, 2); return FALSE; } void cache_type_info(const Item *source, bool maybe_null_arg) { Type_std_attributes::set(source); set_handler(source->type_handler()); set_maybe_null(maybe_null_arg); } bool fix_length_and_dec2_eliminate_null(Item **items) { // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr. if (items[0]->type() == NULL_ITEM) { cache_type_info(items[1], true); // If both arguments are NULL, make resulting type BINARY(0). if (items[1]->type() == NULL_ITEM) set_handler(&type_handler_string); } else if (items[1]->type() == NULL_ITEM) { cache_type_info(items[0], true); } else { if (fix_length_and_dec2(items)) return TRUE; } return FALSE; } public: Item_func_case_abbreviation2(THD *thd, Item *a, Item *b): Item_func_case_expression(thd, a, b) { } Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c): Item_func_case_expression(thd, a, b, c) { } }; class Item_func_ifnull :public Item_func_case_abbreviation2 { public: Item_func_ifnull(THD *thd, Item *a, Item *b): Item_func_case_abbreviation2(thd, a, b) {} double real_op() override; longlong int_op() override; String *str_op(String *str) override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; bool native_op(THD *thd, Native *to) override; bool fix_length_and_dec(THD *thd) override { update_nullability_post_fix_fields(); if (Item_func_case_abbreviation2::fix_length_and_dec2(args)) return TRUE; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ifnull") }; return name; } table_map not_null_tables() const override { return 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ifnull>(thd, this); } }; /** Case abbreviations that have a switch argument and two return arguments to choose from. Returns the value of either of the two return arguments depending on the switch argument value. IF(switch, arg1, arg2) NVL(switch, arg1, arg2) */ class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2 { protected: virtual Item *find_item() const= 0; public: Item_func_case_abbreviation2_switch(THD *thd, Item *a, Item *b, Item *c) :Item_func_case_abbreviation2(thd, a, b, c) { } bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { Datetime_truncation_not_needed dt(thd, find_item(), fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } bool time_op(THD *thd, MYSQL_TIME *ltime) override { return (null_value= Time(find_item()).copy_to_mysql_time(ltime)); } longlong int_op() override { return val_int_from_item(find_item()); } double real_op() override { return val_real_from_item(find_item()); } my_decimal *decimal_op(my_decimal *decimal_value) override { return val_decimal_from_item(find_item(), decimal_value); } String *str_op(String *str) override { return val_str_from_item(find_item(), str); } bool native_op(THD *thd, Native *to) override { return val_native_with_conversion_from_item(thd, find_item(), to, type_handler()); } }; class Item_func_if :public Item_func_case_abbreviation2_switch { protected: Item *find_item() const override { return args[0]->val_bool() ? args[1] : args[2]; } public: Item_func_if(THD *thd, Item *a, Item *b, Item *c): Item_func_case_abbreviation2_switch(thd, a, b, c) {} bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override { return fix_length_and_dec2_eliminate_null(args + 1); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("if") }; return name; } bool eval_not_null_tables(void *opt_arg) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_if>(thd, this); } private: void cache_type_info(Item *source); }; class Item_func_nvl2 :public Item_func_case_abbreviation2_switch { protected: Item *find_item() const override { return args[0]->is_null() ? args[2] : args[1]; } public: Item_func_nvl2(THD *thd, Item *a, Item *b, Item *c): Item_func_case_abbreviation2_switch(thd, a, b, c) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("nvl2") }; return name; } bool fix_length_and_dec(THD *thd) override { return fix_length_and_dec2_eliminate_null(args + 1); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_nvl2>(thd, this); } }; class Item_func_nullif :public Item_func_case_expression { Arg_comparator cmp; /* NULLIF(a,b) is a short for: CASE WHEN a=b THEN NULL ELSE a END The left "a" is for comparison purposes. The right "a" is for return value purposes. These are two different "a" and they can be replaced to different items. The left "a" is in a comparison and can be replaced by: - Item_func::convert_const_compared_to_int_field() - agg_item_set_converter() in set_cmp_func() - cache_converted_constant() in set_cmp_func() Both "a"s are subject to equal fields propagation and can be replaced by: - Item_field::propagate_equal_fields(ANY_SUBST) for the left "a" - Item_field::propagate_equal_fields(IDENTITY_SUBST) for the right "a" */ Item_cache *m_cache; int compare(); void reset_first_arg_if_needed() { if (arg_count == 3 && args[0] != args[2]) args[0]= args[2]; } Item *m_arg0; public: /* Here we pass three arguments to the parent constructor, as NULLIF is a three-argument function, it needs two copies of the first argument (see above). But fix_fields() will be confused if we try to prepare the same Item twice (if args[0]==args[2]), so we hide the third argument (decrementing arg_count) and copy args[2]=args[0] again after fix_fields(). See also Item_func_nullif::fix_length_and_dec(). */ Item_func_nullif(THD *thd, Item *a, Item *b): Item_func_case_expression(thd, a, b, a), m_cache(NULL), m_arg0(NULL) { arg_count--; } void cleanup() override { Item_func_hybrid_field_type::cleanup(); arg_count= 2; // See the comment to the constructor } bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; double real_op() override; longlong int_op() override; String *str_op(String *str) override; my_decimal *decimal_op(my_decimal *) override; bool native_op(THD *thd, Native *to) override; bool fix_length_and_dec(THD *thd) override; bool walk(Item_processor processor, bool walk_subquery, void *arg) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("nullif") }; return name; } void print(String *str, enum_query_type query_type) override; void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override; void update_used_tables() override; table_map not_null_tables() const override { return 0; } bool is_null() override; Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { Context cmpctx(ANY_SUBST, cmp.compare_type_handler(), cmp.compare_collation()); const Item *old0= args[0]; args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[0]); args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[1]); /* MDEV-9712 Performance degradation of nested NULLIF ANY_SUBST is more relaxed than IDENTITY_SUBST. If ANY_SUBST did not change args[0], then we can skip propagation for args[2]. */ if (old0 != args[0]) args[2]->propagate_equal_fields_and_change_item_tree(thd, Context_identity(), cond, &args[2]); return this; } Item *derived_field_transformer_for_having(THD *thd, uchar *arg) override { reset_first_arg_if_needed(); return this; } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) override { reset_first_arg_if_needed(); return this; } Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) override { reset_first_arg_if_needed(); return this; } Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) override { reset_first_arg_if_needed(); return this; } Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) override { reset_first_arg_if_needed(); return this; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_nullif>(thd, this); } }; /* Functions to handle the optimized IN */ /* A vector of values of some type */ class in_vector :public Sql_alloc { public: char *base; uint size; qsort_cmp2 compare; CHARSET_INFO *collation; uint count; uint used_count; in_vector() = default; in_vector(THD *thd, uint elements, uint element_length, qsort_cmp2 cmp_func, CHARSET_INFO *cmp_coll) :base((char*) thd_calloc(thd, elements * element_length)), size(element_length), compare(cmp_func), collation(cmp_coll), count(elements), used_count(elements) {} virtual ~in_vector() = default; /* Store an Item value at the given position. @returns false - the Item was not NULL, and the conversion from the Item data type to the cmp_item data type went without errors @returns true - the Item was NULL, or data type conversion returned NULL */ virtual bool set(uint pos, Item *item)=0; virtual uchar *get_value(Item *item)=0; void sort() { my_qsort2(base,used_count,size,compare,(void*)collation); } bool find(Item *item); /* Create an instance of Item_{type} (e.g. Item_decimal) constant object which type allows it to hold an element of this vector without any conversions. The purpose of this function is to be able to get elements of this vector in form of Item_xxx constants without creating Item_xxx object for every array element you get (i.e. this implements "FlyWeight" pattern) */ virtual Item* create_item(THD *thd) { return NULL; } /* Store the value at position #pos into provided item object SYNOPSIS value_to_item() pos Index of value to store item Constant item to store value into. The item must be of the same type that create_item() returns. */ virtual void value_to_item(uint pos, Item *item) { } /* Compare values number pos1 and pos2 for equality */ bool compare_elems(uint pos1, uint pos2) { return MY_TEST(compare(const_cast<charset_info_st *>(collation), base + pos1 * size, base + pos2 * size)); } virtual const Type_handler *type_handler() const= 0; }; class in_string :public in_vector { char buff[STRING_BUFFER_USUAL_SIZE]; String tmp; class Item_string_for_in_vector: public Item_string { public: Item_string_for_in_vector(THD *thd, CHARSET_INFO *cs): Item_string(thd, cs) { } void set_value(const String *str) { str_value= *str; collation.set(str->charset()); } }; public: in_string(THD *thd, uint elements, qsort_cmp2 cmp_func, CHARSET_INFO *cs); ~in_string(); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; Item* create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override { String *str=((String*) base)+pos; Item_string_for_in_vector *to= (Item_string_for_in_vector*) item; to->set_value(str); } const Type_handler *type_handler() const override { return &type_handler_varchar; } }; class in_longlong :public in_vector { protected: /* Here we declare a temporary variable (tmp) of the same type as the elements of this vector. tmp is used in finding if a given value is in the list. */ struct packed_longlong { longlong val; longlong unsigned_flag; // Use longlong, not bool, to preserve alignment } tmp; public: in_longlong(THD *thd, uint elements); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; Item* create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override { ((Item_int*) item)->value= ((packed_longlong*) base)[pos].val; ((Item_int*) item)->unsigned_flag= (bool) ((packed_longlong*) base)[pos].unsigned_flag; } const Type_handler *type_handler() const override { return &type_handler_slonglong; } friend int cmp_longlong(void *cmp_arg, const void *a, const void *b); }; class in_timestamp :public in_vector { Timestamp_or_zero_datetime tmp; public: in_timestamp(THD *thd, uint elements); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; Item* create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override; const Type_handler *type_handler() const override { return &type_handler_timestamp2; } }; /* Class to represent a vector of constant DATE/DATETIME values. */ class in_temporal :public in_longlong { public: /* Cache for the left item. */ in_temporal(THD *thd, uint elements) :in_longlong(thd, elements) {}; Item *create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override { packed_longlong *val= reinterpret_cast<packed_longlong*>(base)+pos; Item_datetime *dt= static_cast<Item_datetime*>(item); dt->set_from_packed(val->val, type_handler()->mysql_timestamp_type()); } friend int cmp_longlong(void *cmp_arg, const void *a, const void *b); }; class in_datetime :public in_temporal { public: in_datetime(THD *thd, uint elements) :in_temporal(thd, elements) {} bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; const Type_handler *type_handler() const override { return &type_handler_datetime2; } }; class in_time :public in_temporal { public: in_time(THD *thd, uint elements) :in_temporal(thd, elements) {} bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; const Type_handler *type_handler() const override { return &type_handler_time2; } }; class in_double :public in_vector { double tmp; public: in_double(THD *thd, uint elements); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; Item *create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override { ((Item_float*)item)->value= ((double*) base)[pos]; } const Type_handler *type_handler() const override { return &type_handler_double; } }; class in_decimal :public in_vector { my_decimal val; public: in_decimal(THD *thd, uint elements); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; Item *create_item(THD *thd) override; void value_to_item(uint pos, Item *item) override { my_decimal *dec= ((my_decimal *)base) + pos; Item_decimal *item_dec= (Item_decimal*)item; item_dec->set_decimal_value(dec); } const Type_handler *type_handler() const override { return &type_handler_newdecimal; } }; /* ** Classes for easy comparing of non const items */ class cmp_item :public Sql_alloc { public: CHARSET_INFO *cmp_charset; cmp_item() { cmp_charset= &my_charset_bin; } virtual ~cmp_item() = default; virtual void store_value(Item *item)= 0; /** @returns result (TRUE, FALSE or UNKNOWN) of "stored argument's value <> item's value" */ virtual int cmp(Item *item)= 0; virtual int cmp_not_null(const Value *value)= 0; // for optimized IN with row virtual int compare(const cmp_item *item) const= 0; virtual cmp_item *make_same(THD *thd)= 0; /* Store a scalar or a ROW value into "this". @returns false - the value (or every component in case of ROW) was not NULL and the data type conversion went without errors. @returns true - the value (or some of its components) was NULL, or the data type conversion of a not-NULL value returned NULL. */ virtual bool store_value_by_template(THD *thd, cmp_item *tmpl, Item *item)=0; }; /// cmp_item which stores a scalar (i.e. non-ROW). class cmp_item_scalar : public cmp_item { protected: bool m_null_value; ///< If stored value is NULL bool store_value_by_template(THD *thd, cmp_item *tmpl, Item *item) override { store_value(item); return m_null_value; } }; class cmp_item_string : public cmp_item_scalar { protected: String *value_res; public: cmp_item_string () = default; cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; } void set_charset(CHARSET_INFO *cs) { cmp_charset= cs; } friend class cmp_item_sort_string; friend class cmp_item_sort_string_in_static; }; class cmp_item_sort_string :public cmp_item_string { protected: char value_buff[STRING_BUFFER_USUAL_SIZE]; String value; public: cmp_item_sort_string(): cmp_item_string() {} cmp_item_sort_string(CHARSET_INFO *cs): cmp_item_string(cs), value(value_buff, sizeof(value_buff), cs) {} void store_value(Item *item) override { value_res= item->val_str(&value); m_null_value= item->null_value; // Make sure to cache the result String inside "value" if (value_res && value_res != &value) { if (value.copy(*value_res)) value.set("", 0, item->collation.collation); value_res= &value; } } int cmp_not_null(const Value *val) override { DBUG_ASSERT(!val->is_null()); DBUG_ASSERT(val->is_string()); return sortcmp(value_res, &val->m_string, cmp_charset) != 0; } int cmp(Item *arg) override { char buff[STRING_BUFFER_USUAL_SIZE]; String tmp(buff, sizeof(buff), cmp_charset), *res= arg->val_str(&tmp); if (m_null_value || arg->null_value) return UNKNOWN; if (value_res && res) return sortcmp(value_res, res, cmp_charset) != 0; else if (!value_res && !res) return FALSE; else return TRUE; } int compare(const cmp_item *ci) const override { cmp_item_string *l_cmp= (cmp_item_string *) ci; return sortcmp(value_res, l_cmp->value_res, cmp_charset); } cmp_item *make_same(THD *thd) override; void set_charset(CHARSET_INFO *cs) { cmp_charset= cs; value.set_buffer_if_not_allocated(value_buff, sizeof(value_buff), cs); } }; class cmp_item_int : public cmp_item_scalar { longlong value; public: cmp_item_int() = default; /* Remove gcc warning */ void store_value(Item *item) override { value= item->val_int(); m_null_value= item->null_value; } int cmp_not_null(const Value *val) override { DBUG_ASSERT(!val->is_null()); DBUG_ASSERT(val->is_longlong()); return value != val->value.m_longlong; } int cmp(Item *arg) override { const bool rc= value != arg->val_int(); return (m_null_value || arg->null_value) ? UNKNOWN : rc; } int compare(const cmp_item *ci) const override { cmp_item_int *l_cmp= (cmp_item_int *)ci; return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1); } cmp_item *make_same(THD *thd) override; }; /* Compare items in the DATETIME context. */ class cmp_item_temporal: public cmp_item_scalar { protected: longlong value; public: cmp_item_temporal() = default; int compare(const cmp_item *ci) const override; }; class cmp_item_datetime: public cmp_item_temporal { public: cmp_item_datetime() :cmp_item_temporal() { } void store_value(Item *item) override { value= item->val_datetime_packed(current_thd); m_null_value= item->null_value; } int cmp_not_null(const Value *val) override; int cmp(Item *arg) override; cmp_item *make_same(THD *thd) override; }; class cmp_item_time: public cmp_item_temporal { public: cmp_item_time() :cmp_item_temporal() { } void store_value(Item *item) override { value= item->val_time_packed(current_thd); m_null_value= item->null_value; } int cmp_not_null(const Value *val) override; int cmp(Item *arg) override; cmp_item *make_same(THD *thd) override; }; class cmp_item_timestamp: public cmp_item_scalar { Timestamp_or_zero_datetime_native m_native; public: cmp_item_timestamp() :cmp_item_scalar() { } void store_value(Item *item) override; int cmp_not_null(const Value *val) override; int cmp(Item *arg) override; int compare(const cmp_item *ci) const override; cmp_item *make_same(THD *thd) override; }; class cmp_item_real : public cmp_item_scalar { double value; public: cmp_item_real() = default; /* Remove gcc warning */ void store_value(Item *item) override { value= item->val_real(); m_null_value= item->null_value; } int cmp_not_null(const Value *val) override { DBUG_ASSERT(!val->is_null()); DBUG_ASSERT(val->is_double()); return value != val->value.m_double; } int cmp(Item *arg) override { const bool rc= value != arg->val_real(); return (m_null_value || arg->null_value) ? UNKNOWN : rc; } int compare(const cmp_item *ci) const override { cmp_item_real *l_cmp= (cmp_item_real *) ci; return (value < l_cmp->value)? -1 : ((value == l_cmp->value) ? 0 : 1); } cmp_item *make_same(THD *thd) override; }; class cmp_item_decimal : public cmp_item_scalar { my_decimal value; public: cmp_item_decimal() = default; /* Remove gcc warning */ void store_value(Item *item) override; int cmp(Item *arg) override; int cmp_not_null(const Value *val) override; int compare(const cmp_item *c) const override; cmp_item *make_same(THD *thd) override; }; /* cmp_item for optimized IN with row (right part string, which never be changed) */ class cmp_item_sort_string_in_static :public cmp_item_string { protected: String value; public: cmp_item_sort_string_in_static(CHARSET_INFO *cs): cmp_item_string(cs) {} void store_value(Item *item) override { value_res= item->val_str(&value); m_null_value= item->null_value; } int cmp_not_null(const Value *val) override { DBUG_ASSERT(false); return TRUE; } int cmp(Item *item) override { // Should never be called DBUG_ASSERT(false); return TRUE; } int compare(const cmp_item *ci) const override { cmp_item_string *l_cmp= (cmp_item_string *) ci; return sortcmp(value_res, l_cmp->value_res, cmp_charset); } cmp_item *make_same(THD *) override { return new cmp_item_sort_string_in_static(cmp_charset); } }; /** A helper class to handle situations when some item "pred" (the predicant) is consequently compared to a list of other items value0..valueN (the values). Currently used to handle: - <in predicate> pred IN (value0, value1, value2) - <simple case> CASE pred WHEN value0 .. WHEN value1 .. WHEN value2 .. END Every pair {pred,valueN} can be compared by its own Type_handler. Some pairs can use the same Type_handler. In cases when all pairs use exactly the same Type_handler, we say "all types are compatible". For example, for an expression 1 IN (1, 1e0, 1.0, 2) - pred is 1 - value0 is 1 - value1 is 1e0 - value2 is 1.1 - value3 is 2 Pairs (pred,valueN) are compared as follows: N expr1 Type - ----- ---- 0 1 INT 1 1e0 DOUBLE 2 1.0 DECIMAL 3 2 INT Types are not compatible in this example. During add_value() calls, each pair {pred,valueN} is analysed: - If valueN is an explicit NULL, it can be ignored in the caller asks to do so - If valueN is not an explicit NULL (or if the caller didn't ask to skip NULLs), then the value add an element in the array m_comparators[]. Every element m_comparators[] stores the following information: 1. m_arg_index - the position of the value expression in the original argument array, e.g. in Item_func_in::args[] or Item_func_case::args[]. 2. m_handler - the pointer to the data type handler that the owner will use to compare the pair {args[m_predicate_index],args[m_arg_index]}. 3. m_handler_index - the index of an m_comparators[] element corresponding to the leftmost pair that uses exactly the same Type_handler for comparison. m_handler_index helps to maintain unique data type handlers. - m_comparators[i].m_handler_index==i means that this is the leftmost pair that uses the Type_handler m_handler for comparision. - If m_comparators[i].m_handlex_index!=i, it means that some earlier element m_comparators[j<i] is already using this Type_handler pointed by m_handler. 4. m_cmp_item - the pointer to a cmp_item instance to handle comparison for this pair. Only unique type handlers have m_cmp_item!=NULL. Non-unique type handlers share the same cmp_item instance. For all m_comparators[] elements the following assersion it true: (m_handler_index==i) == (m_cmp_item!=NULL) */ class Predicant_to_list_comparator { // Allocate memory on thd memory root for "nvalues" values. bool alloc_comparators(THD *thd, uint nvalues); /** Look up m_comparators[] for a comparator using the given data type handler. @param [OUT] idx - the index of the found comparator is returned here @param [IN] handler - the data type handler to find @param [IN] count - search in the range [0,count) only @retval true - this type handler was not found (*idx is not defined in this case). @retval false - this type handler was found (the position of the found handler is returned in idx). */ bool find_handler(uint *idx, const Type_handler *handler, uint count) { DBUG_ASSERT(count < m_comparator_count); for (uint i= 0 ; i < count; i++) { if (m_comparators[i].m_handler == handler) { *idx= i; return false; } } return true; } /** Populate m_comparators[i].m_handler_index for all elements in m_comparators using the information in m_comparators[i].m_handlers, which was previously populated by a add_predicant() call and a number of add_value() calls. @param [OUT] compatible - If all comparator types are compatible, their data type handler is returned here. @param [OUT] unuque_cnt - The number of unique data type handlers found. If the value returned in *unique_cnt is 0, it means all values were explicit NULLs: expr0 IN (NULL,NULL,..,NULL) @param [OUT] found_type - The bit mask for all found cmp_type()'s. */ void detect_unique_handlers(Type_handler_hybrid_field_type *compatible, uint *unique_cnt, uint *found_types); /** Creates a cmp_item instances for all unique handlers and stores them into m_comparators[i].m_cmp_item, using the information previously populated by add_predicant(), add_value(), detect_unque_handlers(). */ /* Compare the predicant to the value pointed by m_comparators[i]. @param args - the same argument array which was previously used with add_predicant() and add_value(). @param i - which pair to check. @retval true - the predicant is not equal to the value. @retval false - the predicant is equal to the value. @retval UNKNOWN - the result is uncertain yet because the predicant and/or the value returned NULL, more pairs {pred,valueN} should be checked. */ int cmp_arg(Item_args *args, uint i) { Predicant_to_value_comparator *cmp= &m_comparators[m_comparators[i].m_handler_index]; cmp_item *in_item= cmp->m_cmp_item; DBUG_ASSERT(in_item); /* If this is the leftmost pair that uses the data type handler pointed by m_comparators[i].m_handler, then we need to cache the predicant value representation used by this handler. */ if (m_comparators[i].m_handler_index == i) in_item->store_value(args->arguments()[m_predicant_index]); /* If the predicant item has null_value==true then: - In case of scalar expression we can returns UNKNOWN immediately. No needs to check the result of the value item. - In case of ROW, null_value==true means that *some* row elements returned NULL, but *some* elements can still be non-NULL! We need to get the result of the value item and test if non-NULL elements in the predicant and the value produce TRUE (not equal), or UNKNOWN. */ if (args->arguments()[m_predicant_index]->null_value && m_comparators[i].m_handler != &type_handler_row) return UNKNOWN; return in_item->cmp(args->arguments()[m_comparators[i].m_arg_index]); } int cmp_args_nulls_equal(THD *thd, Item_args *args, uint i) { Predicant_to_value_comparator *cmp= &m_comparators[m_comparators[i].m_handler_index]; cmp_item *in_item= cmp->m_cmp_item; DBUG_ASSERT(in_item); Item *predicant= args->arguments()[m_predicant_index]; Item *arg= args->arguments()[m_comparators[i].m_arg_index]; ValueBuffer<MAX_FIELD_WIDTH> val; if (m_comparators[i].m_handler_index == i) in_item->store_value(predicant); m_comparators[i].m_handler->Item_save_in_value(thd, arg, &val); if (predicant->null_value && val.is_null()) return FALSE; // Two nulls are equal if (predicant->null_value || val.is_null()) return UNKNOWN; return in_item->cmp_not_null(&val); } /** Predicant_to_value_comparator - a comparator for one pair (pred,valueN). See comments above. */ struct Predicant_to_value_comparator { const Type_handler *m_handler; cmp_item *m_cmp_item; uint m_arg_index; uint m_handler_index; void cleanup() { if (m_cmp_item) delete m_cmp_item; memset(this, 0, sizeof(*this)); } }; Predicant_to_value_comparator *m_comparators; // The comparator array uint m_comparator_count;// The number of elements in m_comparators[] uint m_predicant_index; // The position of the predicant in its argument list, // e.g. for Item_func_in m_predicant_index is 0, // as predicant is stored in Item_func_in::args[0]. // For Item_func_case m_predicant_index is // set to Item_func_case::first_expr_num. public: Predicant_to_list_comparator(THD *thd, uint nvalues) :m_comparator_count(0), m_predicant_index(0) { alloc_comparators(thd, nvalues); } uint comparator_count() const { return m_comparator_count; } const Type_handler *get_comparator_type_handler(uint i) const { DBUG_ASSERT(i < m_comparator_count); return m_comparators[i].m_handler; } uint get_comparator_arg_index(uint i) const { DBUG_ASSERT(i < m_comparator_count); return m_comparators[i].m_arg_index; } cmp_item *get_comparator_cmp_item(uint i) const { DBUG_ASSERT(i < m_comparator_count); return m_comparators[i].m_cmp_item; } #ifndef DBUG_OFF void debug_print(THD *thd) { for (uint i= 0; i < m_comparator_count; i++) { DBUG_EXECUTE_IF("Predicant_to_list_comparator", push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, "DBUG: [%d] arg=%d handler=%d (%s)", i, m_comparators[i].m_arg_index, m_comparators[i].m_handler_index, m_comparators[m_comparators[i].m_handler_index]. m_handler->name().ptr());); } } #endif void add_predicant(Item_args *args, uint predicant_index) { DBUG_ASSERT(m_comparator_count == 0); // Set in constructor DBUG_ASSERT(m_predicant_index == 0); // Set in constructor DBUG_ASSERT(predicant_index < args->argument_count()); m_predicant_index= predicant_index; } /** Add a new element into m_comparators[], using a {pred,valueN} pair. @param funcname - the name of the operation, for error reporting @param args - the owner function's argument list @param value_index - the value position in args @retval true - could not add an element because of non-comparable arguments (e.g. ROWs with size) @retval false - a new element was successfully added. */ bool add_value(const LEX_CSTRING &funcname, Item_args *args, uint value_index); /** Add a new element into m_comparators[], ignoring explicit NULL values. If the value appeared to be an explicit NULL, nulls_found[0] is set to true. */ bool add_value_skip_null(const LEX_CSTRING &funcname, Item_args *args, uint value_index, bool *nulls_found); /** Signal "this" that there will be no new add_value*() calls, so it can prepare its internal structures for comparison. @param [OUT] compatible - If all comparators are compatible, their data type handler is returned here. @param [OUT] unuque_cnt - The number of unique data type handlers found. If the value returned in *unique_cnt is 0, it means all values were explicit NULLs: expr0 IN (NULL,NULL,..,NULL) @param [OUT] found_type - The bit mask for all found cmp_type()'s. */ void all_values_added(Type_handler_hybrid_field_type *compatible, uint *unique_cnt, uint *found_types) { detect_unique_handlers(compatible, unique_cnt, found_types); } /** Creates cmp_item instances for all unique handlers and stores them into m_comparators[].m_cmp_item, using the information previously populated by add_predicant(), add_value() and detect_unque_handlers(). */ bool make_unique_cmp_items(THD *thd, CHARSET_INFO *cs); void cleanup() { DBUG_ASSERT(m_comparators); for (uint i= 0; i < m_comparator_count; i++) m_comparators[i].cleanup(); memset(m_comparators, 0, sizeof(m_comparators[0]) * m_comparator_count); m_comparator_count= 0; m_predicant_index= 0; } bool init_clone(THD *thd, uint nvalues) { m_comparator_count= 0; m_predicant_index= 0; return alloc_comparators(thd, nvalues); } /** @param [IN] args - The argument list that was previously used with add_predicant() and add_value(). @param [OUT] idx - In case if a value that is equal to the predicant was found, the index of the matching value is returned here. Otherwise, *idx is not changed. @param [OUT] found_unknown_values - set to true if the result of at least one comparison was UNKNOWN @retval false - Found a value that is equal to the predicant @retval true - Didn't find an equal value */ bool cmp(Item_args *args, uint *idx, bool *found_unknown_values) { for (uint i= 0 ; i < m_comparator_count ; i++) { DBUG_ASSERT(m_comparators[i].m_handler != NULL); const int rc= cmp_arg(args, i); if (rc == FALSE) { *idx= m_comparators[i].m_arg_index; return false; // Found a matching value } if (rc == UNKNOWN) *found_unknown_values= true; } return true; // Not found } /* Same as above, but treats two NULLs as equal, e.g. as in DECODE_ORACLE(). */ bool cmp_nulls_equal(THD *thd, Item_args *args, uint *idx) { for (uint i= 0 ; i < m_comparator_count ; i++) { DBUG_ASSERT(m_comparators[i].m_handler != NULL); if (cmp_args_nulls_equal(thd, args, i) == FALSE) { *idx= m_comparators[i].m_arg_index; return false; // Found a matching value } } return true; // Not found } }; /* The class Item_func_case is the CASE ... WHEN ... THEN ... END function implementation. */ class Item_func_case :public Item_func_case_expression { protected: String tmp_value; DTCollation cmp_collation; bool aggregate_then_and_else_arguments(THD *thd, uint count); virtual Item **else_expr_addr() const= 0; virtual Item *find_item()= 0; inline void print_when_then_arguments(String *str, enum_query_type query_type, Item **items, uint count); inline void print_else_argument(String *str, enum_query_type query_type, Item *item); void reorder_args(uint start); public: Item_func_case(THD *thd, List<Item> &list) :Item_func_case_expression(thd, list) { } double real_op() override; longlong int_op() override; String *str_op(String *) override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; bool native_op(THD *thd, Native *to) override; bool fix_fields(THD *thd, Item **ref) override; table_map not_null_tables() const override { return 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("case") }; return name; } CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } bool need_parentheses_in_default() override { return true; } }; /* CASE WHEN cond THEN res [WHEN cond THEN res...] [ELSE res] END Searched CASE checks all WHEN expressions one after another. When some WHEN expression evaluated to TRUE then the value of the corresponding THEN expression is returned. */ class Item_func_case_searched: public Item_func_case { uint when_count() const { return arg_count / 2; } bool with_else() const { return arg_count % 2; } Item **else_expr_addr() const override { return with_else() ? &args[arg_count - 1] : 0; } public: Item_func_case_searched(THD *thd, List<Item> &list) :Item_func_case(thd, list) { DBUG_ASSERT(arg_count >= 2); reorder_args(0); } enum Functype functype() const override { return CASE_SEARCHED_FUNC; } void print(String *str, enum_query_type query_type) override; bool fix_length_and_dec(THD *thd) override; Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { // None of the arguments are in a comparison context Item_args::propagate_equal_fields(thd, Context_identity(), cond); return this; } Item *find_item() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_case_searched>(thd, this); } }; /* CASE pred WHEN value THEN res [WHEN value THEN res...] [ELSE res] END When the predicant expression is specified then it is compared to each WHEN expression individually. When an equal WHEN expression is found the corresponding THEN expression is returned. In order to do correct comparisons several comparators are used. One for each result type. Different result types that are used in particular CASE ... END expression are collected in the fix_length_and_dec() member function and only comparators for there result types are used. */ class Item_func_case_simple: public Item_func_case, public Predicant_to_list_comparator { protected: uint m_found_types; uint when_count() const { return (arg_count - 1) / 2; } bool with_else() const { return arg_count % 2 == 0; } Item **else_expr_addr() const override { return with_else() ? &args[arg_count - 1] : 0; } bool aggregate_switch_and_when_arguments(THD *thd, bool nulls_equal); bool prepare_predicant_and_values(THD *thd, uint *found_types, bool nulls_equal); public: Item_func_case_simple(THD *thd, List<Item> &list) :Item_func_case(thd, list), Predicant_to_list_comparator(thd, arg_count), m_found_types(0) { DBUG_ASSERT(arg_count >= 3); reorder_args(1); } void cleanup() override { DBUG_ENTER("Item_func_case_simple::cleanup"); Item_func::cleanup(); Predicant_to_list_comparator::cleanup(); DBUG_VOID_RETURN; } enum Functype functype() const override { return CASE_SIMPLE_FUNC; } void print(String *str, enum_query_type query_type) override; bool fix_length_and_dec(THD *thd) override; Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override; Item *find_item() override; protected: Item *deep_copy(THD *thd) const override { Item_func_case_simple *clone= (Item_func_case_simple *) Item_func_case::deep_copy(thd); uint ncases= when_count(); if (clone && clone->Predicant_to_list_comparator::init_clone(thd, ncases)) return NULL; return clone; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_case_simple>(thd, this); } }; class Item_func_decode_oracle: public Item_func_case_simple { public: Item_func_decode_oracle(THD *thd, List<Item> &list) :Item_func_case_simple(thd, list) { } const Schema *schema() const override { return &oracle_schema_ref; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("decode") }; return name; } void print(String *str, enum_query_type query_type) override; bool fix_length_and_dec(THD *thd) override; Item *find_item() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_decode_oracle>(thd, this); } }; /* The Item_func_in class implements in_expr IN (<in value list>) and in_expr NOT IN (<in value list>) The current implementation distinguishes 2 cases: 1) all items in <in value list> are constants and have the same result type. This case is handled by in_vector class, implementing fast bisection search. 2) otherwise Item_func_in employs several cmp_item objects to perform comparisons of in_expr and an item from <in value list>. One cmp_item object for each result type. Different result types are collected in the fix_length_and_dec() member function by means of collect_cmp_types() function. Bisection is possible when: 1. All types are similar 2. All expressions in <in value list> are const In the presence of NULLs, the correct result of evaluating this item must be UNKNOWN or FALSE. To achieve that: - If type is scalar, we can use bisection and the "have_null" boolean. - If type is ROW, we will need to scan all of <in value list> when searching, so bisection is impossible. Unless: 3. UNKNOWN and FALSE are equivalent results 4. Neither left expression nor <in value list> contain any NULL value */ class Item_func_in :public Item_func_opt_neg, public Predicant_to_list_comparator { /** Usable if <in value list> is made only of constants. Returns true if one of these constants contains a NULL. Example: IN ( (-5, (12,NULL)), ... ). */ bool list_contains_null(); bool all_items_are_consts(Item **items, uint nitems) const { for (uint i= 0; i < nitems; i++) { if (!items[i]->can_eval_in_optimize()) return false; } return true; } bool prepare_predicant_and_values(THD *thd, uint *found_types); bool check_arguments() const override { return check_argument_types_like_args0(); } protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override; bool transform_into_subq; bool transform_into_subq_checked; public: /// An array of values, created when the bisection lookup method is used in_vector *array; /** If there is some NULL among <in value list>, during a val_int() call; for example IN ( (1,(3,'col')), ... ), where 'col' is a column which evaluates to NULL. */ bool have_null; /** true when all arguments of the IN list are of compatible types and can be used safely as comparisons for key conditions */ bool arg_types_compatible; TABLE_LIST *emb_on_expr_nest; Item_func_in(THD *thd, List<Item> &list): Item_func_opt_neg(thd, list), Predicant_to_list_comparator(thd, arg_count - 1), transform_into_subq(false), transform_into_subq_checked(false), array(0), have_null(0), arg_types_compatible(FALSE), emb_on_expr_nest(0) { } bool val_bool() override; bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override; bool compatible_types_scalar_bisection_possible() { DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT); return all_items_are_consts(args + 1, arg_count - 1); // Bisection #2 } bool compatible_types_row_bisection_possible() { DBUG_ASSERT(m_comparator.cmp_type() == ROW_RESULT); return all_items_are_consts(args + 1, arg_count - 1) && // Bisection #2 ((is_top_level_item() && !negated) || // Bisection #3 (!list_contains_null() && !args[0]->maybe_null())); // Bisection #4 } bool agg_all_arg_charsets_for_comparison() { return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count); } void fix_in_vector(); bool value_list_convert_const_to_int(THD *thd); bool fix_for_scalar_comparison_using_bisection(THD *thd) { array= m_comparator.type_handler()->make_in_vector(thd, this, arg_count - 1); if (!array) // OOM return true; fix_in_vector(); return false; } bool fix_for_scalar_comparison_using_cmp_items(THD *thd, uint found_types); bool fix_for_row_comparison_using_cmp_items(THD *thd); bool fix_for_row_comparison_using_bisection(THD *thd); void cleanup() override { DBUG_ENTER("Item_func_in::cleanup"); Item_int_func::cleanup(); delete array; array= 0; Predicant_to_list_comparator::cleanup(); DBUG_VOID_RETURN; } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; SEL_TREE *get_func_row_mm_tree(RANGE_OPT_PARAM *param, Item_row *key_row); Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { /* Note, we pass ANY_SUBST, this makes sure that non of the args will be replaced to a zero-filled Item_string. Such a change would require rebuilding of cmp_items. */ if (arg_types_compatible) { Context cmpctx(ANY_SUBST, m_comparator.type_handler(), Item_func_in::compare_collation()); args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[0]); } for (uint i= 0; i < comparator_count(); i++) { Context cmpctx(ANY_SUBST, get_comparator_type_handler(i), Item_func_in::compare_collation()); uint idx= get_comparator_arg_index(i); args[idx]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[idx]); } return this; } void print(String *str, enum_query_type query_type) override; enum Functype functype() const override { return IN_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("in") }; return name; } enum precedence precedence() const override { return IN_PRECEDENCE; } bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; bool count_sargable_conds(void *arg) override; Item *deep_copy(THD *thd) const override { Item_func_in *clone= (Item_func_in *) Item_func::deep_copy(thd); if (clone) { clone->array= 0; if (clone->Predicant_to_list_comparator::init_clone(thd, arg_count - 1)) return NULL; } return clone; } void mark_as_condition_AND_part(TABLE_LIST *embedding) override; bool to_be_transformed_into_in_subq(THD *thd); bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values); Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) override; Item *in_predicate_to_equality_transformer(THD *thd, uchar *arg) override; uint32 max_length_of_left_expr(); Item* varchar_upper_cmp_transformer(THD *thd, uchar *arg) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_in>(thd, this); } }; class cmp_item_row :public cmp_item { cmp_item **comparators; uint n; bool alloc_comparators(THD *thd, uint n); bool aggregate_row_elements_for_comparison(THD *thd, Type_handler_hybrid_field_type *cmp, Item_args *tmp, const LEX_CSTRING &funcname, uint col, uint level); public: cmp_item_row(): comparators(0), n(0) {} ~cmp_item_row(); void store_value(Item *item) override; bool prepare_comparators(THD *, const LEX_CSTRING &funcname, const Item_args *args, uint level); int cmp(Item *arg) override; int cmp_not_null(const Value *) override { DBUG_ASSERT(false); return TRUE; } int compare(const cmp_item *arg) const override; cmp_item *make_same(THD *thd) override; bool store_value_by_template(THD *thd, cmp_item *tmpl, Item *) override; friend class Item_func_in; cmp_item *get_comparator(uint i) { return comparators[i]; } }; class in_row :public in_vector { cmp_item_row tmp; public: in_row(THD *thd, uint elements, Item *); ~in_row(); bool set(uint pos, Item *item) override; uchar *get_value(Item *item) override; friend class Item_func_in; const Type_handler *type_handler() const override { return &type_handler_row; } cmp_item *get_cmp_item() { return &tmp; } }; /* Functions used by where clause */ class Item_func_null_predicate :public Item_bool_func { protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override { DBUG_ENTER("Item_func_null_predicate::get_func_mm_tree"); DBUG_RETURN(get_mm_parts(param, field, functype(), value)); } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value) override; public: Item_func_null_predicate(THD *thd, Item *a): Item_bool_func(thd, a) { } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override { DBUG_ENTER("Item_func_null_predicate::get_mm_tree"); SEL_TREE *ftree= get_full_func_mm_tree_for_args(param, args[0], NULL); if (!ftree) ftree= Item_func::get_mm_tree(param, cond_ptr); DBUG_RETURN(ftree); } CHARSET_INFO *compare_collation() const override { return args[0]->collation.collation; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=1; base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; } bool count_sargable_conds(void *arg) override; }; class Item_func_isnull :public Item_func_null_predicate { public: Item_func_isnull(THD *thd, Item *a): Item_func_null_predicate(thd, a) {} bool val_bool() override; enum Functype functype() const override { return ISNULL_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("isnull") }; return name; } void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return CMP_PRECEDENCE; } bool arg_is_datetime_notnull_field() { Item **args= arguments(); if (args[0]->real_item()->type() == Item::FIELD_ITEM) { Field *field=((Item_field*) args[0]->real_item())->field; if ((field->flags & NOT_NULL_FLAG) && field->type_handler()->cond_notnull_field_isnull_to_field_eq_zero()) return true; } return false; } /* Optimize case of not_null_column IS NULL */ void update_used_tables() override { if (!args[0]->maybe_null() && !arg_is_datetime_notnull_field()) { used_tables_cache= 0; /* is always false */ const_item_cache= 1; } else { args[0]->update_used_tables(); used_tables_cache= args[0]->used_tables(); const_item_cache= args[0]->const_item(); } } COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level) override; table_map not_null_tables() const override { return 0; } bool find_not_null_fields(table_map allowed) override; Item *neg_transformer(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isnull>(thd, this); } }; /* Functions used by HAVING for rewriting IN subquery */ class Item_in_subselect; /* This is like IS NOT NULL but it also remembers if it ever has encountered a NULL. */ class Item_is_not_null_test :public Item_func_isnull { Item_in_subselect* owner; public: Item_is_not_null_test(THD *thd, Item_in_subselect* ow, Item *a): Item_func_isnull(thd, a), owner(ow) {} enum Functype functype() const override { return ISNOTNULLTEST_FUNC; } bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<is_not_null_test>") }; return name; } void update_used_tables() override; /* we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE */ table_map used_tables() const override { return used_tables_cache | RAND_TABLE_BIT; } bool const_item() const override { return FALSE; } }; class Item_func_isnotnull :public Item_func_null_predicate { public: Item_func_isnotnull(THD *thd, Item *a): Item_func_null_predicate(thd, a) {} bool val_bool() override; enum Functype functype() const override { return ISNOTNULL_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("isnotnull") }; return name; } enum precedence precedence() const override { return CMP_PRECEDENCE; } table_map not_null_tables() const override { return is_top_level_item() ? not_null_tables_cache : 0; } Item *neg_transformer(THD *thd) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_isnotnull>(thd, this); } }; class Item_func_like :public Item_bool_func2 { // Turbo Boyer-Moore data bool canDoTurboBM; // pattern is '%abcd%' case const char* pattern; int pattern_len; // TurboBM buffers, *this is owner int* bmGs; // good suffix shift table, size is pattern_len + 1 int* bmBc; // bad character shift table, size is alphabet_size void turboBM_compute_suffixes(int* suff); void turboBM_compute_good_suffix_shifts(int* suff); void turboBM_compute_bad_character_shifts(); bool turboBM_matches(const char* text, int text_len) const; enum { alphabet_size = 256 }; Item *escape_item; bool escape_used_in_parsing; bool use_sampling; DTCollation cmp_collation; String cmp_value1, cmp_value2; bool with_sargable_pattern() const; protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value) override { DBUG_ENTER("Item_func_like::get_func_mm_tree"); DBUG_RETURN(get_mm_parts(param, field, LIKE_FUNC, value)); } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value) override; public: int escape; bool negated; Item_func_like(THD *thd, Item *a, Item *b, Item *escape_arg, bool escape_used): Item_bool_func2(thd, a, b), canDoTurboBM(FALSE), pattern(0), pattern_len(0), bmGs(0), bmBc(0), escape_item(escape_arg), escape_used_in_parsing(escape_used), use_sampling(0), negated(0) {} bool get_negated() const { return negated; } // Used by ColumnStore Sql_mode_dependency value_depends_on_sql_mode() const override; bool val_bool() override; enum Functype functype() const override { return LIKE_FUNC; } void print(String *str, enum_query_type query_type) override; CHARSET_INFO *compare_collation() const override { return cmp_collation.collation; } cond_result eq_cmp_result() const override { /** We cannot always rewrite conditions as follows: from: WHERE expr1=const AND expr1 LIKE expr2 to: WHERE expr1=const AND const LIKE expr2 or from: WHERE expr1=const AND expr2 LIKE expr1 to: WHERE expr1=const AND expr2 LIKE const because LIKE works differently comparing to the regular "=" operator: 1. LIKE performs a stricter one-character-to-one-character comparison and does not recognize contractions and expansions. Replacing "expr1" to "const in LIKE would make the condition stricter in case of a complex collation. 2. LIKE does not ignore trailing spaces and thus works differently from the "=" operator in case of "PAD SPACE" collations (which are the majority in MariaDB). So, for "PAD SPACE" collations: - expr1=const - ignores trailing spaces - const LIKE expr2 - does not ignore trailing spaces - expr2 LIKE const - does not ignore trailing spaces Allow only "binary" for now. It neither ignores trailing spaces nor has contractions/expansions. TODO: We could still replace "expr1" to "const" in "expr1 LIKE expr2" in case of a "PAD SPACE" collation, but only if "expr2" has '%' at the end. */ if (compare_collation() == &my_charset_bin) { /* 'foo' NOT LIKE 'foo' is false, 'foo' LIKE 'foo' is true. */ return negated? COND_FALSE : COND_TRUE; } return COND_OK; } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { /* LIKE differs from the regular comparison operator ('=') in the following: - LIKE never ignores trailing spaces (even for PAD SPACE collations) Propagation of equal fields with a PAD SPACE collation into LIKE is not safe. Example: WHERE a='a ' AND a LIKE 'a' - returns true for 'a' cannot be rewritten to: WHERE a='a ' AND 'a ' LIKE 'a' - returns false for 'a' Note, binary collations in MySQL/MariaDB, e.g. latin1_bin, still have the PAD SPACE attribute and ignore trailing spaces! - LIKE does not take into account contractions, expansions, and ignorable characters. Propagation of equal fields with contractions/expansions/ignorables is also not safe. It's safe to propagate my_charset_bin (BINARY/VARBINARY/BLOB) values, because they do not ignore trailing spaces and have one-to-one mapping between a string and its weights. The below condition should be true only for my_charset_bin (as of version 10.1.7). */ uint flags= Item_func_like::compare_collation()->state; if ((flags & MY_CS_NOPAD) && !(flags & MY_CS_NON1TO1)) Item_args::propagate_equal_fields(thd, Context(ANY_SUBST, &type_handler_long_blob, compare_collation()), cond); return this; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("like") }; return name; } enum precedence precedence() const override { return IN_PRECEDENCE; } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override { max_length= 1; Item_args old_predicant(args[0]); if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) return true; raise_note_if_key_become_unused(current_thd, old_predicant); return false; } void cleanup() override; Item *neg_transformer(THD *thd) override { negated= !negated; return this; } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { return (walk_args(processor, walk_subquery, arg) || escape_item->walk(processor, walk_subquery, arg) || (this->*processor)(arg)); } bool find_selective_predicates_list_processor(void *arg) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_like>(thd, this); } }; typedef struct pcre2_real_code_8 pcre2_code; typedef struct pcre2_real_match_data_8 pcre2_match_data; #define PCRE2_SIZE size_t class Regexp_processor_pcre { pcre2_code *m_pcre; pcre2_match_data *m_pcre_match_data; bool m_conversion_is_needed; bool m_is_const; int m_library_flags; CHARSET_INFO *m_library_charset; String m_prev_pattern; int m_pcre_exec_rc; PCRE2_SIZE *m_SubStrVec; void pcre_exec_warn(int rc) const; int pcre_exec_with_warn(const pcre2_code *code, pcre2_match_data *data, const char *subject, int length, int startoffset, int options); public: String *convert_if_needed(String *src, String *converter); String subject_converter; String pattern_converter; String replace_converter; Regexp_processor_pcre() : m_pcre(NULL), m_pcre_match_data(NULL), m_conversion_is_needed(true), m_is_const(0), m_library_flags(0), m_library_charset(&my_charset_utf8mb4_general_ci) {} int default_regex_flags(); void init(CHARSET_INFO *data_charset, int extra_flags); bool fix_owner(Item_func *owner, Item *subject_arg, Item *pattern_arg); bool compile(String *pattern, bool send_error); bool compile(Item *item, bool send_error); bool recompile(Item *item) { return !m_is_const && compile(item, false); } bool exec(const char *str, size_t length, size_t offset); bool exec(String *str, int offset, uint n_result_offsets_to_convert); bool exec(Item *item, int offset, uint n_result_offsets_to_convert); bool match() const { return m_pcre_exec_rc < 0 ? 0 : 1; } int nsubpatterns() const { return m_pcre_exec_rc <= 0 ? 0 : m_pcre_exec_rc; } size_t subpattern_start(int n) const { return m_pcre_exec_rc <= 0 ? 0 : m_SubStrVec[n * 2]; } size_t subpattern_end(int n) const { return m_pcre_exec_rc <= 0 ? 0 : m_SubStrVec[n * 2 + 1]; } size_t subpattern_length(int n) const { return subpattern_end(n) - subpattern_start(n); } void reset() { m_pcre= NULL; m_pcre_match_data= NULL; m_prev_pattern.length(0); } void cleanup(); bool is_compiled() const { return m_pcre != NULL; } bool is_const() const { return m_is_const; } void set_const(bool arg) { m_is_const= arg; } CHARSET_INFO * library_charset() const { return m_library_charset; } void unset_flag(int flag) { m_library_flags&= ~flag; } }; class Item_func_regex :public Item_bool_func { Regexp_processor_pcre re; DTCollation cmp_collation; public: Item_func_regex(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b) {} void cleanup() override { DBUG_ENTER("Item_func_regex::cleanup"); Item_bool_func::cleanup(); re.cleanup(); DBUG_VOID_RETURN; } bool val_bool() override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("regexp") }; return name; } enum precedence precedence() const override { return IN_PRECEDENCE; } void print(String *str, enum_query_type query_type) override { print_op(str, query_type); } CHARSET_INFO *compare_collation() const override { return cmp_collation.collation; } protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; /* In the corner case REGEXP_INSTR could return (2^32 + 1), which would not fit into Item_long_func range. But string lengths are limited with max_allowed_packet, which cannot be bigger than 1024*1024*1024. */ class Item_func_regexp_instr :public Item_long_func { bool check_arguments() const override { return (args[0]->check_type_can_return_str(func_name_cstring()) || args[1]->check_type_can_return_text(func_name_cstring())); } Regexp_processor_pcre re; DTCollation cmp_collation; public: Item_func_regexp_instr(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {} void cleanup() override { DBUG_ENTER("Item_func_regexp_instr::cleanup"); Item_int_func::cleanup(); re.cleanup(); DBUG_VOID_RETURN; } longlong val_int() override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("regexp_instr") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; typedef class Item COND; class Item_cond :public Item_bool_func { protected: List<Item> list; table_map and_tables_cache; public: Item_cond(THD *thd): Item_bool_func(thd) { /* Item_cond() is only used to create top level items */ top_level_item(); const_item_cache=0; } Item_cond(THD *thd, Item *i1, Item *i2); Item_cond(THD *thd, Item_cond *item); Item_cond(THD *thd, List<Item> &nlist): Item_bool_func(thd), list(nlist) {} bool add(Item *item, MEM_ROOT *root) { DBUG_ASSERT(item); return list.push_back(item, root); } bool add_at_head(Item *item, MEM_ROOT *root) { DBUG_ASSERT(item); return list.push_front(item, root); } void add_at_head(List<Item> *nlist) { DBUG_ASSERT(nlist->elements); list.prepend(nlist); } void add_at_end(List<Item> *nlist) { DBUG_ASSERT(nlist->elements); list.append(nlist); } bool fix_fields(THD *, Item **ref) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; enum Type type() const override { return COND_ITEM; } List<Item>* argument_list() { return &list; } table_map used_tables() const override; void update_used_tables() override { used_tables_and_const_cache_init(); used_tables_and_const_cache_update_and_join(list); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override; COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level) override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; void print(String *str, enum_query_type query_type) override; void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override; friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds); void copy_andor_arguments(THD *thd, Item_cond *item); bool walk(Item_processor processor, bool walk_subquery, void *arg) override; Item *do_transform(THD *thd, Item_transformer transformer, uchar *arg, bool toplevel); Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override { return do_transform(thd, transformer, arg, 0); } Item *top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) override { return do_transform(thd, transformer, arg, 1); } void traverse_cond(Cond_traverser, void *arg, traverse_order order) override; void neg_arguments(THD *thd); Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override; Item *do_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t, bool toplevel); Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) override { return do_compile(thd, analyzer, arg_p, transformer, arg_t, 0); } Item* top_level_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) override { return do_compile(thd, analyzer, arg_p, transformer, arg_t, 1); } bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; Item *deep_copy(THD *thd) const override; bool excl_dep_on_table(table_map tab_map) override; bool excl_dep_on_grouping_fields(st_select_lex *sel) override; private: void merge_sub_condition(List_iterator<Item>& li); }; template <template<class> class LI, class T> class Item_equal_iterator; /* The class Item_equal is used to represent conjunctions of equality predicates of the form field1 = field2, and field=const in where conditions and on expressions. All equality predicates of the form field1=field2 contained in a conjunction are substituted for a sequence of items of this class. An item of this class Item_equal(f1,f2,...fk) represents a multiple equality f1=f2=...=fk.l If a conjunction contains predicates f1=f2 and f2=f3, a new item of this class is created Item_equal(f1,f2,f3) representing the multiple equality f1=f2=f3 that substitutes the above equality predicates in the conjunction. A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be substituted for the item representing the same multiple equality f1=f2=f3. An item Item_equal(f1,f2) can appear instead of a conjunction of f2=f1 and f1=f2, or instead of just the predicate f1=f2. An item of the class Item_equal inherits equalities from outer conjunctive levels. Suppose we have a where condition of the following form: WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)). In this case: f1=f2 will be substituted for Item_equal(f1,f2); f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5); f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5); An object of the class Item_equal can contain an optional constant item c. Then it represents a multiple equality of the form c=f1=...=fk. Objects of the class Item_equal are used for the following: 1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any pair of tables ti and tj as joined by an equi-condition. Thus it provide us with additional access paths from table to table. 2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new SARGable predicates: f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj). It also can give us additional index scans and can allow us to improve selectivity estimates. 3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the selected execution plan for the query: if table ti is accessed before the table tj then in any predicate P in the where condition the occurrence of tj.fj is substituted for ti.fi. This can allow an evaluation of the predicate at an earlier step. When feature 1 is supported they say that join transitive closure is employed. When feature 2 is supported they say that search argument transitive closure is employed. Both features are usually supported by preprocessing original query and adding additional predicates. We do not just add predicates, we rather dynamically replace some predicates that can not be used to access tables in the investigated plan for those, obtained by substitution of some fields for equal fields, that can be used. Prepared Statements/Stored Procedures note: instances of class Item_equal are created only at the time a PS/SP is executed and are deleted in the end of execution. All changes made to these objects need not be registered in the list of changes of the parse tree and do not harm PS/SP re-execution. Item equal objects are employed only at the optimize phase. Usually they are not supposed to be evaluated. Yet in some cases we call the method val_int() for them. We have to take care of restricting the predicate such an object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik. */ class Item_equal: public Item_bool_func { /* The list of equal items. Currently the list can contain: - Item_fields items for references to table columns - Item_direct_view_ref items for references to view columns - one const item If the list contains a constant item this item is always first in the list. The list contains at least two elements. Currently all Item_fields/Item_direct_view_ref items in the list should refer to table columns with equavalent type definitions. In particular if these are string columns they should have the same charset/collation. Use objects of the companion class Item_equal_fields_iterator to iterate over all items from the list of the Item_field/Item_direct_view_ref classes. */ List<Item> equal_items; /* TRUE <-> one of the items is a const item. Such item is always first in the equal_items list */ bool with_const; /* The field eval_item is used when this item is evaluated with the method val_int() */ cmp_item *eval_item; /* This initially is set to FALSE. It becomes TRUE when this item is evaluated as being always false. If the flag is TRUE the contents of the list the equal_items should be ignored. */ bool cond_false; /* This initially is set to FALSE. It becomes TRUE when this item is evaluated as being always true. If the flag is TRUE the contents of the list the equal_items should be ignored. */ bool cond_true; /* For Item_equal objects inside an OR clause: one of the fields that were used in the original equality. */ Item_field *context_field; bool link_equal_fields; const Type_handler *m_compare_handler; CHARSET_INFO *m_compare_collation; public: COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */ Item_equal(THD *thd, const Type_handler *handler, Item *f1, Item *f2, bool with_const_item); Item_equal(THD *thd, Item_equal *item_equal); /* Currently the const item is always the first in the list of equal items */ inline Item* get_const() { return with_const ? equal_items.head() : NULL; } void add_const(THD *thd, Item *c); /** Add a non-constant item to the multiple equality */ void add(Item *f, MEM_ROOT *root) { equal_items.push_back(f, root); } bool contains(Field *field); Item* get_first(struct st_join_table *context, Item *field); /** Get number of field items / references to field items in this object */ uint n_field_items() { return equal_items.elements - MY_TEST(with_const); } void merge(THD *thd, Item_equal *item); bool merge_with_check(THD *thd, Item_equal *equal_item, bool save_merged); void merge_into_list(THD *thd, List<Item_equal> *list, bool save_merged, bool only_intersected); void update_const(THD *thd); enum Functype functype() const override { return MULT_EQUAL_FUNC; } bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("multiple equal") }; return name; } void sort(Item_field_cmpfunc compare, void *arg); bool fix_length_and_dec(THD *thd) override; bool fix_fields(THD *thd, Item **ref) override; void cleanup() override { delete eval_item; eval_item= NULL; } void update_used_tables() override; bool find_not_null_fields(table_map allowed) override; COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; bool walk(Item_processor processor, bool walk_subquery, void *arg) override; Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override; void print(String *str, enum_query_type query_type) override; const Type_handler *compare_type_handler() const { return m_compare_handler; } CHARSET_INFO *compare_collation() const override { return m_compare_collation; } void set_context_field(Item_field *ctx_field) { context_field= ctx_field; } void set_link_equal_fields(bool flag) { link_equal_fields= flag; } protected: Item* shallow_copy(THD *thd) const override { return 0; } public: /* This does not comply with the specification of the virtual method, but Item_equal items are processed distinguishly anyway */ bool excl_dep_on_table(table_map tab_map) override { return used_tables() & tab_map; } bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override; bool excl_dep_on_grouping_fields(st_select_lex *sel) override; bool create_pushable_equalities(THD *thd, List<Item> *equalities, Pushdown_checker checker, uchar *arg, bool clone_const); /* Return the number of elements in this multiple equality */ uint elements_count() { return equal_items.elements; } friend class Item_equal_fields_iterator; bool count_sargable_conds(void *arg) override; Item *multiple_equality_transformer(THD *thd, uchar *arg) override; friend class Item_equal_iterator<List_iterator_fast,Item>; friend class Item_equal_iterator<List_iterator,Item>; friend Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, Item_equal *item_equal); friend bool setup_sj_materialization_part1(struct st_join_table *tab); friend bool setup_sj_materialization_part2(struct st_join_table *tab); }; class COND_EQUAL: public Sql_alloc { public: uint max_members; /* max number of members the current level list and all lower level lists */ COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */ List<Item_equal> current_level; /* list of multiple equalities of the current and level */ COND_EQUAL() { upper_levels= 0; } COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root) :upper_levels(0) { current_level.push_back(item, mem_root); } void copy(COND_EQUAL &cond_equal) { max_members= cond_equal.max_members; upper_levels= cond_equal.upper_levels; if (cond_equal.current_level.is_empty()) current_level.empty(); else current_level= cond_equal.current_level; } bool is_empty() { return (current_level.elements == 0); } }; /* The template Item_equal_iterator is used to define classes Item_equal_fields_iterator and Item_equal_fields_iterator_slow. These are helper classes for the class Item equal Both classes are used to iterate over references to table/view columns from the list of equal items that included in an Item_equal object. The second class supports the operation of removal of the current member from the list when performing an iteration. */ template <template<class> class LI, typename T> class Item_equal_iterator : public LI<T> { protected: Item_equal *item_equal; Item *curr_item= nullptr; public: Item_equal_iterator(Item_equal &item_eq) :LI<T> (item_eq.equal_items), item_equal(&item_eq) { if (item_eq.with_const) { LI<T> *list_it= this; curr_item= (*list_it)++; } } Item* operator++(int) { LI<T> *list_it= this; curr_item= (*list_it)++; return curr_item; } void rewind(void) { LI<T> *list_it= this; list_it->rewind(); if (item_equal->with_const) curr_item= (*list_it)++; } Field *get_curr_field() { Item_field *item= (Item_field *) (curr_item->real_item()); return item->field; } }; typedef Item_equal_iterator<List_iterator_fast,Item > Item_equal_iterator_fast; class Item_equal_fields_iterator :public Item_equal_iterator_fast { public: Item_equal_fields_iterator(Item_equal &item_eq) :Item_equal_iterator_fast(item_eq) { } Item ** ref() { return List_iterator_fast<Item>::ref(); } }; typedef Item_equal_iterator<List_iterator,Item > Item_equal_iterator_iterator_slow; class Item_equal_fields_iterator_slow :public Item_equal_iterator_iterator_slow { public: Item_equal_fields_iterator_slow(Item_equal &item_eq) :Item_equal_iterator_iterator_slow(item_eq) { } void remove() { List_iterator<Item>::remove(); } }; class Item_cond_and final :public Item_cond { public: COND_EQUAL m_cond_equal; /* contains list of Item_equal objects for the current and level and reference to multiple equalities of upper and levels */ Item_cond_and(THD *thd): Item_cond(thd) {} Item_cond_and(THD *thd, Item *i1,Item *i2): Item_cond(thd, i1, i2) {} Item_cond_and(THD *thd, Item_cond_and *item): Item_cond(thd, item) {} Item_cond_and(THD *thd, List<Item> &list_arg): Item_cond(thd, list_arg) {} enum Functype functype() const override { return COND_AND_FUNC; } bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("and") }; return name; } enum precedence precedence() const override { return AND_PRECEDENCE; } table_map not_null_tables() const override { return is_top_level_item() ? not_null_tables_cache: and_tables_cache; } Item *copy_andor_structure(THD *thd) override; Item *neg_transformer(THD *thd) override; void mark_as_condition_AND_part(TABLE_LIST *embedding) override; uint exists2in_reserved_items() override { return list.elements; }; COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override; bool set_format_by_check_constraint(Send_field_extended_metadata *to) const override; void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cond_and>(thd, this); } }; inline bool is_cond_and(Item *item) { Item_func *func_item= item->get_item_func(); return func_item && func_item->functype() == Item_func::COND_AND_FUNC; } class Item_cond_or final :public Item_cond { public: Item_cond_or(THD *thd): Item_cond(thd) {} Item_cond_or(THD *thd, Item *i1,Item *i2): Item_cond(thd, i1, i2) {} Item_cond_or(THD *thd, Item_cond_or *item): Item_cond(thd, item) {} Item_cond_or(THD *thd, List<Item> &list_arg): Item_cond(thd, list_arg) {} enum Functype functype() const override { return COND_OR_FUNC; } bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("or") }; return name; } enum precedence precedence() const override { return OR_PRECEDENCE; } table_map not_null_tables() const override { return and_tables_cache; } Item *copy_andor_structure(THD *thd) override; Item *neg_transformer(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cond_or>(thd, this); } }; class Item_func_dyncol_check :public Item_bool_func { public: Item_func_dyncol_check(THD *thd, Item *str): Item_bool_func(thd, str) {} bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_check") }; return name; } bool need_parentheses_in_default() override { return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_check>(thd, this); } }; class Item_func_dyncol_exists :public Item_bool_func { public: Item_func_dyncol_exists(THD *thd, Item *str, Item *num): Item_bool_func(thd, str, num) {} bool val_bool() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_exists") }; return name; } bool need_parentheses_in_default() override { return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_exists>(thd, this); } }; class Item_func_cursor_bool_attr: public Item_bool_func, public Cursor_ref { public: Item_func_cursor_bool_attr(THD *thd, const LEX_CSTRING *name, uint offset) :Item_bool_func(thd), Cursor_ref(name, offset) { } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC); } void print(String *str, enum_query_type query_type) override { Cursor_ref::print_func(str, func_name_cstring()); } }; class Item_func_cursor_isopen: public Item_func_cursor_bool_attr { public: Item_func_cursor_isopen(THD *thd, const LEX_CSTRING *name, uint offset) :Item_func_cursor_bool_attr(thd, name, offset) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("%ISOPEN") }; return name; } bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cursor_isopen>(thd, this); } }; class Item_func_cursor_found: public Item_func_cursor_bool_attr { public: Item_func_cursor_found(THD *thd, const LEX_CSTRING *name, uint offset) :Item_func_cursor_bool_attr(thd, name, offset) { set_maybe_null(); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("%FOUND") }; return name; } bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cursor_found>(thd, this); } }; class Item_func_cursor_notfound: public Item_func_cursor_bool_attr { public: Item_func_cursor_notfound(THD *thd, const LEX_CSTRING *name, uint offset) :Item_func_cursor_bool_attr(thd, name, offset) { set_maybe_null(); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("%NOTFOUND") }; return name; } bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cursor_notfound>(thd, this); } }; inline bool is_cond_or(Item *item) { Item_func *func_item= item->get_item_func(); return func_item && func_item->functype() == Item_func::COND_OR_FUNC; } Item *and_expressions(Item *a, Item *b, Item **org_item); class Comp_creator { public: Comp_creator() = default; /* Remove gcc warning */ virtual ~Comp_creator() = default; /* Remove gcc warning */ /** Create operation with given arguments. */ virtual Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const = 0; /** Create operation with given arguments in swap order. */ virtual Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const = 0; virtual const char* symbol(bool invert) const = 0; virtual bool eqne_op() const = 0; virtual bool l_op() const = 0; }; class Eq_creator :public Comp_creator { public: Eq_creator() = default; /* Remove gcc warning */ virtual ~Eq_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? "<>" : "="; } bool eqne_op() const override { return 1; } bool l_op() const override { return 0; } }; class Ne_creator :public Comp_creator { public: Ne_creator() = default; /* Remove gcc warning */ virtual ~Ne_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? "=" : "<>"; } bool eqne_op() const override { return 1; } bool l_op() const override { return 0; } }; class Gt_creator :public Comp_creator { public: Gt_creator() = default; /* Remove gcc warning */ virtual ~Gt_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? "<=" : ">"; } bool eqne_op() const override { return 0; } bool l_op() const override { return 0; } }; class Lt_creator :public Comp_creator { public: Lt_creator() = default; /* Remove gcc warning */ virtual ~Lt_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? ">=" : "<"; } bool eqne_op() const override { return 0; } bool l_op() const override { return 1; } }; class Ge_creator :public Comp_creator { public: Ge_creator() = default; /* Remove gcc warning */ virtual ~Ge_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? "<" : ">="; } bool eqne_op() const override { return 0; } bool l_op() const override { return 0; } }; class Le_creator :public Comp_creator { public: Le_creator() = default; /* Remove gcc warning */ virtual ~Le_creator() = default; /* Remove gcc warning */ Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const override; Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const override; const char* symbol(bool invert) const override { return invert? ">" : "<="; } bool eqne_op() const override { return 0; } bool l_op() const override { return 1; } }; /* These need definitions from this file but the variables are defined in mysqld.h. The variables really belong in this component, but for the time being we leave them in mysqld.cc to avoid merge problems. */ extern Eq_creator eq_creator; extern Ne_creator ne_creator; extern Gt_creator gt_creator; extern Lt_creator lt_creator; extern Ge_creator ge_creator; extern Le_creator le_creator; #endif /* ITEM_CMPFUNC_INCLUDED */ wsrep_xid.h 0000644 00000003015 15156036160 0006723 0 ustar 00 /* Copyright (C) 2015-2025 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_XID_H #define WSREP_XID_H #include <my_config.h> #ifdef WITH_WSREP #include "wsrep_mysqld.h" #include "wsrep/gtid.hpp" #include "handler.h" // XID typedef void wsrep_xid_init(xid_t*, const wsrep::gtid&, const wsrep_server_gtid_t&); const wsrep::id& wsrep_xid_uuid(const XID&); wsrep::seqno wsrep_xid_seqno(const XID&); template<typename T> T wsrep_get_SE_checkpoint(); bool wsrep_set_SE_checkpoint(const wsrep::gtid& gtid, const wsrep_server_gtid_t&); //void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */ //void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */ void wsrep_sort_xid_array(XID *array, int len); std::string wsrep_xid_print(const XID *xid); bool wsrep_is_xid_gtid_undefined(const XID *xid); #endif /* WITH_WSREP */ #endif /* WSREP_UTILS_H */ wsrep_status.h 0000644 00000003665 15156036161 0007476 0 ustar 00 /* Copyright 2021 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_STATUS_H #define WSREP_STATUS_H /* wsrep-lib */ #include "wsrep/reporter.hpp" /* implementation */ #include "wsrep_mutex.h" class Wsrep_status { public: static void init_once(const std::string& file_name); static void destroy(); static void report_state(enum wsrep::server_state::state const state) { if (!Wsrep_status::m_instance) return; Wsrep_status::m_instance->report_state(state); } static void report_progress(const std::string& progress) { if (!Wsrep_status::m_instance) return; Wsrep_status::m_instance->report_progress(progress); } static void report_event(const std::string& event) { if (!Wsrep_status::m_instance) return; Wsrep_status::m_instance->report_event(event); } static void report_log_msg(wsrep::reporter::log_level level, const char* tag, size_t tag_len, const char* buf, size_t buf_len, double const tstamp = wsrep::reporter::undefined); static bool is_instance_initialized() { return m_instance; } private: Wsrep_status(const std::string& file_name); static Wsrep_mutex* m_mutex; static wsrep::reporter* m_instance; }; #endif /* WSREP_STATUS_H */ rijndael.h 0000644 00000003257 15156036161 0006520 0 ustar 00 #ifndef RIJNDAEL_INCLUDED #define RIJNDAEL_INCLUDED /* Copyright (c) 2002, 2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* rijndael-alg-fst.h @version 3.0 (December 2000) Optimised ANSI C code for the Rijndael cipher (now AES) @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> @author Paulo Barreto <paulo.barreto@terra.com.br> This code is hereby placed in the public domain. Modified by Peter Zaitsev to fit MySQL coding style. */ #define AES_MAXKC (256/32) #define AES_MAXKB (256/8) #define AES_MAXNR 14 int rijndaelKeySetupEnc(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], int keyBits); int rijndaelKeySetupDec(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], int keyBits); void rijndaelEncrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, const uint8 pt[16], uint8 ct[16]); void rijndaelDecrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, const uint8 ct[16], uint8 pt[16]); #endif /* RIJNDAEL_INCLUDED */ sql_load.h 0000644 00000002374 15156036161 0006525 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_LOAD_INCLUDED #define SQL_LOAD_INCLUDED #include "sql_list.h" /* List */ class Item; #include "sql_class.h" /* enum_duplicates */ class sql_exchange; int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, List<Item> &fields_vars, List<Item> &set_fields, List<Item> &set_values_list, enum enum_duplicates handle_duplicates, bool ignore, bool local_file); #endif /* SQL_LOAD_INCLUDED */ sql_array.h 0000644 00000015741 15156036161 0006726 0 ustar 00 #ifndef SQL_ARRAY_INCLUDED #define SQL_ARRAY_INCLUDED /* Copyright (c) 2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <my_sys.h> /** A wrapper class which provides array bounds checking. We do *not* own the array, we simply have a pointer to the first element, and a length. @remark We want the compiler-generated versions of: - the copy CTOR (memberwise initialization) - the assignment operator (memberwise assignment) @param Element_type The type of the elements of the container. */ template <typename Element_type> class Bounds_checked_array { public: Bounds_checked_array()= default; Bounds_checked_array(Element_type *el, size_t size_arg) : m_array(el), m_size(size_arg) {} void reset() { m_array= NULL; m_size= 0; } void reset(Element_type *array_arg, size_t size_arg) { m_array= array_arg; m_size= size_arg; } /** Set a new bound on the array. Does not resize the underlying array, so the new size must be smaller than or equal to the current size. */ void resize(size_t new_size) { DBUG_ASSERT(new_size <= m_size); m_size= new_size; } Element_type &operator[](size_t n) { DBUG_ASSERT(n < m_size); return m_array[n]; } const Element_type &operator[](size_t n) const { DBUG_ASSERT(n < m_size); return m_array[n]; } size_t element_size() const { return sizeof(Element_type); } size_t size() const { return m_size; } bool is_null() const { return m_array == NULL; } void pop_front() { DBUG_ASSERT(m_size > 0); m_array+= 1; m_size-= 1; } Element_type *array() const { return m_array; } Element_type *begin() const { return array(); } Element_type *end() const { return array() + m_size; } bool operator==(const Bounds_checked_array<Element_type>&rhs) const { return m_array == rhs.m_array && m_size == rhs.m_size; } bool operator!=(const Bounds_checked_array<Element_type>&rhs) const { return m_array != rhs.m_array || m_size != rhs.m_size; } private: Element_type *m_array= nullptr; size_t m_size= 0; }; /* A typesafe wrapper around DYNAMIC_ARRAY TODO: Change creator to take a THREAD_SPECIFIC option. */ template <class Elem> class Dynamic_array { DYNAMIC_ARRAY array; public: Dynamic_array(PSI_memory_key psi_key, size_t prealloc=16, size_t increment=16) { init(psi_key, prealloc, increment); } Dynamic_array(MEM_ROOT *root, size_t prealloc=16, size_t increment=16) { void *init_buffer= alloc_root(root, sizeof(Elem) * prealloc); init_dynamic_array2(root->psi_key, &array, sizeof(Elem), init_buffer, prealloc, increment, MYF(0)); } void init(PSI_memory_key psi_key, size_t prealloc=16, size_t increment=16) { init_dynamic_array2(psi_key, &array, sizeof(Elem), 0, prealloc, increment, MYF(0)); } /** @note Though formally this could be declared "const" it would be misleading at it returns a non-const pointer to array's data. */ Elem& at(size_t idx) { DBUG_ASSERT(idx < array.elements); return *(((Elem*)array.buffer) + idx); } /// Const variant of at(), which cannot change data const Elem& at(size_t idx) const { return *(((Elem*)array.buffer) + idx); } Elem& operator[](size_t idx) { return at(idx); } /// Const variant of operator[] const Elem& operator[](size_t idx) const { return at(idx); } /// @returns pointer to first element Elem *front() { return (Elem*)array.buffer; } /// @returns pointer to first element const Elem *front() const { return (const Elem*)array.buffer; } /// @returns pointer to last element Elem *back() { return ((Elem*)array.buffer) + array.elements - 1; } /// @returns pointer to last element const Elem *back() const { return ((const Elem*)array.buffer) + array.elements - 1; } static const size_t NOT_FOUND= (size_t)-1; /// @returns index of the first element equal to el, or NOT_FOUND size_t find_first(const Elem &el) const { for (size_t i=0; i < size() ; i++) { if (el == at(i)) return i; } return NOT_FOUND; } size_t size() const { return array.elements; } const Elem *end() const { return back() + 1; } /// @returns pointer to n-th element Elem *get_pos(size_t idx) { return ((Elem*)array.buffer) + idx; } /// @returns pointer to n-th element const Elem *get_pos(size_t idx) const { return ((const Elem*)array.buffer) + idx; } /** @retval false ok @retval true OOM, @c my_error() has been called. */ bool append(const Elem &el) { return insert_dynamic(&array, &el); } bool append_val(Elem el) { return (insert_dynamic(&array, (uchar*)&el)); } bool push(Elem &el) { return append(el); } /// Pops the last element. Does nothing if array is empty. Elem& pop() { return *((Elem*)pop_dynamic(&array)); } void del(size_t idx) { DBUG_ASSERT(idx <= array.max_element); delete_dynamic_element(&array, idx); } size_t elements() const { return array.elements; } void elements(size_t num_elements) { DBUG_ASSERT(num_elements <= array.max_element); array.elements= num_elements; } void clear() { elements(0); } void set(size_t idx, const Elem &el) { set_dynamic(&array, &el, idx); } void freeze() { freeze_size(&array); } bool reserve(size_t new_size) { return allocate_dynamic(&array, new_size); } bool resize(size_t new_size, Elem default_val) { size_t old_size= elements(); if (reserve(new_size)) return true; if (new_size > old_size) { set_dynamic(&array, (uchar*)&default_val, new_size - 1); /*for (size_t i= old_size; i != new_size; i++) { at(i)= default_val; }*/ } return false; } ~Dynamic_array() { delete_dynamic(&array); } void free_memory() { delete_dynamic(&array); } void sort(int (*cmp_func)(const void *, const void *)) { my_qsort(array.buffer, array.elements, sizeof(Elem), cmp_func); } void sort(qsort_cmp2 cmp_func, void *data) { my_qsort2(array.buffer, array.elements, sizeof(Elem), cmp_func, data); } }; typedef Bounds_checked_array<Item*> Ref_ptr_array; #endif /* SQL_ARRAY_INCLUDED */ socketpair.h 0000644 00000001512 15156036161 0007064 0 ustar 00 /* Copyright (c) 2023, MariaDB Plc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef _WIN32 C_MODE_START int create_socketpair(SOCKET socks[2]); void close_socketpair(SOCKET socks[2]); C_MODE_END #endif /* _WIN32 */ item.h 0000644 00001053732 15156036161 0005672 0 ustar 00 #ifndef SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_priv.h" /* STRING_BUFFER_USUAL_SIZE */ #include "unireg.h" #include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */ #include "field.h" /* Derivation */ #include "sql_type.h" #include "sql_time.h" #include "sql_schema.h" #include "mem_root_array.h" #include <typeinfo> #include "cset_narrowing.h" C_MODE_START #include <ma_dyncol.h> /* A prototype for a C-compatible structure to store a value of any data type. Currently it has to stay in /sql, as it depends on String and my_decimal. We'll do the following changes: 1. add pure C "struct st_string" and "struct st_my_decimal" 2. change type of m_string to struct st_string and move inside the union 3. change type of m_decmal to struct st_my_decimal and move inside the union 4. move the definition to some file in /include */ class st_value { public: st_value() {} st_value(char *buffer, size_t buffer_size) : m_string(buffer, buffer_size, &my_charset_bin) {} enum enum_dynamic_column_type m_type; union { longlong m_longlong; double m_double; MYSQL_TIME m_time; } value; String m_string; my_decimal m_decimal; }; C_MODE_END class Value: public st_value { public: Value(char *buffer, size_t buffer_size) : st_value(buffer, buffer_size) {} Value() {} bool is_null() const { return m_type == DYN_COL_NULL; } bool is_longlong() const { return m_type == DYN_COL_UINT || m_type == DYN_COL_INT; } bool is_double() const { return m_type == DYN_COL_DOUBLE; } bool is_temporal() const { return m_type == DYN_COL_DATETIME; } bool is_string() const { return m_type == DYN_COL_STRING; } bool is_decimal() const { return m_type == DYN_COL_DECIMAL; } }; template<size_t buffer_size> class ValueBuffer: public Value { char buffer[buffer_size]; public: ValueBuffer(): Value(buffer, buffer_size) {} void reset_buffer() { m_string.set_buffer_if_not_allocated(buffer, buffer_size, &my_charset_bin); } }; #ifdef DBUG_OFF static inline const char *dbug_print_item(Item *item) { return NULL; } #else const char *dbug_print_item(Item *item); #endif class Virtual_tmp_table; class sp_head; class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ class Item_basic_value; class Item_result_field; class Item_field; class Item_ref; class Item_param; class user_var_entry; class JOIN; struct KEY_FIELD; struct SARGABLE_PARAM; class RANGE_OPT_PARAM; class SEL_TREE; enum precedence { LOWEST_PRECEDENCE, ASSIGN_PRECEDENCE, // := OR_PRECEDENCE, // OR, || (unless PIPES_AS_CONCAT) XOR_PRECEDENCE, // XOR AND_PRECEDENCE, // AND, && NOT_PRECEDENCE, // NOT (unless HIGH_NOT_PRECEDENCE) CMP_PRECEDENCE, // =, <=>, >=, >, <=, <, <>, !=, IS BETWEEN_PRECEDENCE, // BETWEEN IN_PRECEDENCE, // IN, LIKE, REGEXP BITOR_PRECEDENCE, // | BITAND_PRECEDENCE, // & SHIFT_PRECEDENCE, // <<, >> INTERVAL_PRECEDENCE, // first argument in +INTERVAL ADD_PRECEDENCE, // +, - MUL_PRECEDENCE, // *, /, DIV, %, MOD BITXOR_PRECEDENCE, // ^ PIPES_PRECEDENCE, // || (if PIPES_AS_CONCAT) NEG_PRECEDENCE, // unary -, ~, !, NOT (if HIGH_NOT_PRECEDENCE) COLLATE_PRECEDENCE, // BINARY, COLLATE DEFAULT_PRECEDENCE, HIGHEST_PRECEDENCE }; bool mark_unsupported_function(const char *where, void *store, uint result); /* convenience helper for mark_unsupported_function() above */ bool mark_unsupported_function(const char *w1, const char *w2, void *store, uint result); /* Bits for the split_sum_func() function */ #define SPLIT_SUM_SKIP_REGISTERED 1 /* Skip registered funcs */ #define SPLIT_SUM_SELECT 2 /* SELECT item; Split all parts */ /* Values for item->marker for cond items in the WHERE clause as used by the optimizer. Note that for Item_fields, the marker contains 'select->cur_pos_in_select_list */ /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define MARKER_UNDEF_POS -1 #define MARKER_UNUSED 0 #define MARKER_CHANGE_COND 1 #define MARKER_PROCESSED 2 #define MARKER_CHECK_ON_READ 3 #define MARKER_NULL_KEY 4 #define MARKER_FOUND_IN_ORDER 6 /* Used as bits in marker by Item::check_pushable_cond() */ #define MARKER_NO_EXTRACTION (1 << 6) #define MARKER_FULL_EXTRACTION (1 << 7) #define MARKER_DELETION (1 << 8) #define MARKER_IMMUTABLE (1 << 9) #define MARKER_SUBSTITUTION (1 << 10) /* Used as bits in marker by window functions */ #define MARKER_SORTORDER_CHANGE (1 << 11) #define MARKER_PARTITION_CHANGE (1 << 12) #define MARKER_FRAME_CHANGE (1 << 13) #define MARKER_EXTRACTION_MASK \ (MARKER_NO_EXTRACTION | MARKER_FULL_EXTRACTION | MARKER_DELETION | \ MARKER_IMMUTABLE) extern const char *item_empty_name; void dummy_error_processor(THD *thd, void *data); void view_error_processor(THD *thd, void *data); typedef List<TABLE_LIST>* ignored_tables_list_t; bool ignored_list_includes_table(ignored_tables_list_t list, TABLE_LIST *tbl); /* Instances of Name_resolution_context store the information necessary for name resolution of Items and other context analysis of a query made in fix_fields(). This structure is a part of SELECT_LEX, a pointer to this structure is assigned when an item is created (which happens mostly during parsing (sql_yacc.yy)), but the structure itself will be initialized after parsing is complete TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to separate SELECT_LEX which allow to remove tricks of changing this structure before and after INSERT/CREATE and its SELECT to make correct field name resolution. */ struct Name_resolution_context: Sql_alloc { /* The name resolution context to search in when an Item cannot be resolved in this context (the context of an outer select) */ Name_resolution_context *outer_context= nullptr; /* List of tables used to resolve the items of this context. Usually these are tables from the FROM clause of SELECT statement. The exceptions are INSERT ... SELECT and CREATE ... SELECT statements, where SELECT subquery is not moved to a separate SELECT_LEX. For these types of statements we have to change this member dynamically to ensure correct name resolution of different parts of the statement. */ TABLE_LIST *table_list= nullptr; /* In most cases the two table references below replace 'table_list' above for the purpose of name resolution. The first and last name resolution table references allow us to search only in a sub-tree of the nested join tree in a FROM clause. This is needed for NATURAL JOIN, JOIN ... USING and JOIN ... ON. */ TABLE_LIST *first_name_resolution_table= nullptr; /* Last table to search in the list of leaf table references that begins with first_name_resolution_table. */ TABLE_LIST *last_name_resolution_table= nullptr; /* Cache first_name_resolution_table in setup_natural_join_row_types */ TABLE_LIST *natural_join_first_table= nullptr; /* SELECT_LEX item belong to, in case of merged VIEW it can differ from SELECT_LEX where item was created, so we can't use table_list/field_list from there */ st_select_lex *select_lex= nullptr; /* Processor of errors caused during Item name resolving, now used only to hide underlying tables in errors about views (i.e. it substitute some errors for views) */ void (*error_processor)(THD *, void *)= &dummy_error_processor; void *error_processor_data= nullptr; /* When TRUE items are resolved in this context both against the SELECT list and this->table_list. If FALSE, items are resolved only against this->table_list. */ bool resolve_in_select_list= false; /* Bitmap of tables that should be ignored when doing name resolution. Normally it is {0}. Non-zero values are used by table functions. */ ignored_tables_list_t ignored_tables= nullptr; /* Security context of this name resolution context. It's used for views and is non-zero only if the view is defined with SQL SECURITY DEFINER. */ Security_context *security_ctx= nullptr; Name_resolution_context() = default; /** Name resolution context with resolution in only one table */ Name_resolution_context(TABLE_LIST *table) : first_name_resolution_table(table), last_name_resolution_table(table) {} void init() { resolve_in_select_list= FALSE; error_processor= &dummy_error_processor; ignored_tables= nullptr; first_name_resolution_table= nullptr; last_name_resolution_table= nullptr; } void resolve_in_table_list_only(TABLE_LIST *tables) { table_list= first_name_resolution_table= tables; resolve_in_select_list= FALSE; } void process_error(THD *thd) { (*error_processor)(thd, error_processor_data); } st_select_lex *outer_select() { return (outer_context ? outer_context->select_lex : NULL); } }; /* Store and restore the current state of a name resolution context. */ class Name_resolution_context_state { private: TABLE_LIST *save_table_list; TABLE_LIST *save_first_name_resolution_table; TABLE_LIST *save_next_name_resolution_table; bool save_resolve_in_select_list; TABLE_LIST *save_next_local; public: Name_resolution_context_state() = default; /* Remove gcc warning */ public: /* Save the state of a name resolution context. */ void save_state(Name_resolution_context *context, TABLE_LIST *table_list) { save_table_list= context->table_list; save_first_name_resolution_table= context->first_name_resolution_table; save_resolve_in_select_list= context->resolve_in_select_list; save_next_local= table_list->next_local; save_next_name_resolution_table= table_list->next_name_resolution_table; } /* Restore a name resolution context from saved state. */ void restore_state(Name_resolution_context *context, TABLE_LIST *table_list) { table_list->next_local= save_next_local; table_list->next_name_resolution_table= save_next_name_resolution_table; context->table_list= save_table_list; context->first_name_resolution_table= save_first_name_resolution_table; context->resolve_in_select_list= save_resolve_in_select_list; } TABLE_LIST *get_first_name_resolution_table() { return save_first_name_resolution_table; } }; class Name_resolution_context_backup { Name_resolution_context &ctx; TABLE_LIST &table_list; table_map save_map; Name_resolution_context_state ctx_state; public: Name_resolution_context_backup(Name_resolution_context &_ctx, TABLE_LIST &_table_list) : ctx(_ctx), table_list(_table_list), save_map(_table_list.map) { ctx_state.save_state(&ctx, &table_list); ctx.table_list= &table_list; ctx.first_name_resolution_table= &table_list; } ~Name_resolution_context_backup() { ctx_state.restore_state(&ctx, &table_list); table_list.map= save_map; } }; /* This enum is used to report information about monotonicity of function represented by Item* tree. Monotonicity is defined only for Item* trees that represent table partitioning expressions (i.e. have no subselects/user vars/PS parameters etc etc). An Item* tree is assumed to have the same monotonicity properties as its corresponding function F: [signed] longlong F(field1, field2, ...) { put values of field_i into table record buffer; return item->val_int(); } NOTE At the moment function monotonicity is not well defined (and so may be incorrect) for Item trees with parameters/return types that are different from INT_RESULT, may be NULL, or are unsigned. It will be possible to address this issue once the related partitioning bugs (BUG#16002, BUG#15447, BUG#13436) are fixed. The NOT_NULL enums are used in TO_DAYS, since TO_DAYS('2001-00-00') returns NULL which puts those rows into the NULL partition, but '2000-12-31' < '2001-00-00' < '2001-01-01'. So special handling is needed for this (see Bug#20577). */ typedef enum monotonicity_info { NON_MONOTONIC, /* none of the below holds */ MONOTONIC_INCREASING, /* F() is unary and (x < y) => (F(x) <= F(y)) */ MONOTONIC_INCREASING_NOT_NULL, /* But only for valid/real x and y */ MONOTONIC_STRICT_INCREASING,/* F() is unary and (x < y) => (F(x) < F(y)) */ MONOTONIC_STRICT_INCREASING_NOT_NULL /* But only for valid/real x and y */ } enum_monotonicity_info; /*************************************************************************/ class sp_rcontext; /** A helper class to collect different behavior of various kinds of SP variables: - local SP variables and SP parameters - PACKAGE BODY routine variables - (there will be more kinds in the future) */ class Sp_rcontext_handler { public: virtual ~Sp_rcontext_handler() = default; /** A prefix used for SP variable names in queries: - EXPLAIN EXTENDED - SHOW PROCEDURE CODE Local variables and SP parameters have empty prefixes. Package body variables are marked with a special prefix. This improves readability of the output of these queries, especially when a local variable or a parameter has the same name with a package body variable. */ virtual const LEX_CSTRING *get_name_prefix() const= 0; /** At execution time THD->spcont points to the run-time context (sp_rcontext) of the currently executed routine. Local variables store their data in the sp_rcontext pointed by thd->spcont. Package body variables store data in separate sp_rcontext that belongs to the package. This method provides access to the proper sp_rcontext structure, depending on the SP variable kind. */ virtual sp_rcontext *get_rcontext(sp_rcontext *ctx) const= 0; }; class Sp_rcontext_handler_local: public Sp_rcontext_handler { public: const LEX_CSTRING *get_name_prefix() const override; sp_rcontext *get_rcontext(sp_rcontext *ctx) const override; }; class Sp_rcontext_handler_package_body: public Sp_rcontext_handler { public: const LEX_CSTRING *get_name_prefix() const override; sp_rcontext *get_rcontext(sp_rcontext *ctx) const override; }; extern MYSQL_PLUGIN_IMPORT Sp_rcontext_handler_local sp_rcontext_handler_local; extern MYSQL_PLUGIN_IMPORT Sp_rcontext_handler_package_body sp_rcontext_handler_package_body; class Item_equal; struct st_join_table* const NO_PARTICULAR_TAB= (struct st_join_table*)0x1; typedef struct replace_equal_field_arg { Item_equal *item_equal; struct st_join_table *context_tab; } REPLACE_EQUAL_FIELD_ARG; 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. */ Settable_routine_parameter() = default; virtual ~Settable_routine_parameter() = default; 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 occurred. */ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0; virtual void set_out_param_info(Send_field *info) {} virtual const Send_field *get_out_param_info() const { return NULL; } virtual Item_param *get_item_param() { return 0; } }; /* A helper class to calculate offset and length of a query fragment - outside of SP - inside an SP - inside a compound block */ class Query_fragment { uint m_pos; uint m_length; void set(size_t pos, size_t length) { DBUG_ASSERT(pos < UINT_MAX32); DBUG_ASSERT(length < UINT_MAX32); m_pos= (uint) pos; m_length= (uint) length; } public: Query_fragment(THD *thd, sp_head *sphead, const char *start, const char *end); uint pos() const { return m_pos; } uint length() const { return m_length; } }; /** This is used for items in the query that needs to be rewritten before binlogging At the moment this applies to Item_param and Item_splocal */ class Rewritable_query_parameter { public: /* Offset inside the query text. Value of 0 means that this object doesn't have to be replaced (for example SP variables in control statements) */ my_ptrdiff_t pos_in_query; /* Byte length of parameter name in the statement. This is not Item::name.length because name.length contains byte length of UTF8-encoded name, but the query string is in the client charset. */ uint len_in_query; bool limit_clause_param; Rewritable_query_parameter(uint pos_in_q= 0, uint len_in_q= 0) : pos_in_query(pos_in_q), len_in_query(len_in_q), limit_clause_param(false) { } virtual ~Rewritable_query_parameter() = default; virtual bool append_for_log(THD *thd, String *str) = 0; }; class Copy_query_with_rewrite { THD *thd; const char *src; size_t src_len, from; String *dst; bool copy_up_to(size_t bytes) { DBUG_ASSERT(bytes >= from); return dst->append(src + from, uint32(bytes - from)); } public: Copy_query_with_rewrite(THD *t, const char *s, size_t l, String *d) :thd(t), src(s), src_len(l), from(0), dst(d) { } bool append(Rewritable_query_parameter *p) { if (copy_up_to(p->pos_in_query) || p->append_for_log(thd, dst)) return true; from= p->pos_in_query + p->len_in_query; return false; } bool finalize() { return copy_up_to(src_len); } }; struct st_dyncall_create_def { Item *key, *value; CHARSET_INFO *cs; uint len, frac; DYNAMIC_COLUMN_TYPE type; }; typedef struct st_dyncall_create_def DYNCALL_CREATE_DEF; typedef bool (Item::*Item_processor) (void *arg); /* Analyzer function SYNOPSIS argp in/out IN: Analysis parameter OUT: Parameter to be passed to the transformer RETURN TRUE Invoke the transformer FALSE Don't do it */ typedef bool (Item::*Item_analyzer) (uchar **argp); typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); typedef bool (Item::*Pushdown_checker) (uchar *arg); struct st_cond_statistic; struct find_selective_predicates_list_processor_data { TABLE *table; List<st_cond_statistic> list; }; class MY_LOCALE; class Item_equal; class COND_EQUAL; class st_select_lex_unit; class Item_func_not; class Item_splocal; /** String_copier that sends Item specific warnings. */ class String_copier_for_item: public String_copier { THD *m_thd; public: bool copy_with_warn(CHARSET_INFO *dstcs, String *dst, CHARSET_INFO *srccs, const char *src, uint32 src_length, uint32 nchars); String_copier_for_item(THD *thd): m_thd(thd) { } }; /** A helper class describing what kind of Item created a temporary field. - If m_field is set, then the temporary field was created from Field (e.g. when the Item was Item_field, or Item_ref pointing to Item_field) - If m_default_field is set, then there is a usable DEFAULT value. (e.g. when the Item is Item_field) - If m_item_result_field is set, then the temporary field was created from certain sub-types of Item_result_field (e.g. Item_func) See create_tmp_field() in sql_select.cc for details. */ class Tmp_field_src { Field *m_field; Field *m_default_field; Item_result_field *m_item_result_field; public: Tmp_field_src() :m_field(0), m_default_field(0), m_item_result_field(0) { } Field *field() const { return m_field; } Field *default_field() const { return m_default_field; } Item_result_field *item_result_field() const { return m_item_result_field; } void set_field(Field *field) { m_field= field; } void set_default_field(Field *field) { m_default_field= field; } void set_item_result_field(Item_result_field *item) { m_item_result_field= item; } }; /** Parameters for create_tmp_field_ex(). See create_tmp_field() in sql_select.cc for details. */ class Tmp_field_param { bool m_group; bool m_modify_item; bool m_table_cant_handle_bit_fields; bool m_make_copy_field; public: Tmp_field_param(bool group, bool modify_item, bool table_cant_handle_bit_fields, bool make_copy_field) :m_group(group), m_modify_item(modify_item), m_table_cant_handle_bit_fields(table_cant_handle_bit_fields), m_make_copy_field(make_copy_field) { } bool group() const { return m_group; } bool modify_item() const { return m_modify_item; } bool table_cant_handle_bit_fields() const { return m_table_cant_handle_bit_fields; } bool make_copy_field() const { return m_make_copy_field; } void set_modify_item(bool to) { m_modify_item= to; } }; class Item_const { public: virtual ~Item_const() = default; virtual const Type_all_attributes *get_type_all_attributes_from_const() const= 0; virtual bool const_is_null() const { return false; } virtual const longlong *const_ptr_longlong() const { return NULL; } virtual const double *const_ptr_double() const { return NULL; } virtual const my_decimal *const_ptr_my_decimal() const { return NULL; } virtual const MYSQL_TIME *const_ptr_mysql_time() const { return NULL; } virtual const String *const_ptr_string() const { return NULL; } }; struct subselect_table_finder_param { THD *thd; /* We're searching for different TABLE_LIST objects referring to the same table as this one */ const TABLE_LIST *find; /* NUL - not found, ERROR_TABLE - search error, or the found table reference */ TABLE_LIST *dup; }; /****************************************************************************/ #define STOP_PTR ((void *) 1) /* Base flags (including IN) for an item */ typedef uint8 item_flags_t; enum class item_base_t : item_flags_t { NONE= 0, #define ITEM_FLAGS_MAYBE_NULL_SHIFT 0 // Must match MAYBE_NULL MAYBE_NULL= (1<<0), // May be NULL. IN_ROLLUP= (1<<1), // Appears in GROUP BY list // of a query with ROLLUP. FIXED= (1<<2), // Was fixed with fix_fields(). IS_EXPLICIT_NAME= (1<<3), // The name of this Item was set by the user // (or was auto generated otherwise) IS_IN_WITH_CYCLE= (1<<4), // This item is in CYCLE clause of WITH. IS_COND= (1<<5), // The item is used as <search condition>. // Must be evaluated using val_bool(). // Note, not all items used as a search // condition set this flag yet. AT_TOP_LEVEL= (1<<6) // At top (AND) level of item tree }; /* Flags that tells us what kind of items the item contains */ enum class item_with_t : item_flags_t { NONE= 0, SP_VAR= (1<<0), // If Item contains a stored procedure variable WINDOW_FUNC= (1<<1), // If item contains a window func FIELD= (1<<2), // If any item except Item_sum contains a field. SUM_FUNC= (1<<3), // If item contains a sum func SUBQUERY= (1<<4), // If item containts a sub query ROWNUM_FUNC= (1<<5), // If ROWNUM function was used PARAM= (1<<6) // If user parameter was used }; /* Make operations in item_base_t and item_with_t work like 'int' */ static inline item_base_t operator&(const item_base_t a, const item_base_t b) { return (item_base_t) (((item_flags_t) a) & ((item_flags_t) b)); } static inline item_base_t & operator&=(item_base_t &a, item_base_t b) { a= (item_base_t) (((item_flags_t) a) & (item_flags_t) b); return a; } static inline item_base_t operator|(const item_base_t a, const item_base_t b) { return (item_base_t) (((item_flags_t) a) | ((item_flags_t) b)); } static inline item_base_t & operator|=(item_base_t &a, item_base_t b) { a= (item_base_t) (((item_flags_t) a) | (item_flags_t) b); return a; } static inline item_base_t operator~(const item_base_t a) { return (item_base_t) ~(item_flags_t) a; } static inline item_with_t operator&(const item_with_t a, const item_with_t b) { return (item_with_t) (((item_flags_t) a) & ((item_flags_t) b)); } static inline item_with_t & operator&=(item_with_t &a, item_with_t b) { a= (item_with_t) (((item_flags_t) a) & (item_flags_t) b); return a; } static inline item_with_t operator|(const item_with_t a, const item_with_t b) { return (item_with_t) (((item_flags_t) a) | ((item_flags_t) b)); } static inline item_with_t & operator|=(item_with_t &a, item_with_t b) { a= (item_with_t) (((item_flags_t) a) | (item_flags_t) b); return a; } static inline item_with_t operator~(const item_with_t a) { return (item_with_t) ~(item_flags_t) a; } class Item :public Value_source, public Type_all_attributes { static void *operator new(size_t size); public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, WINDOW_FUNC_ITEM, /* NOT NULL literal-alike constants, which do not change their value during an SQL statement execution, but can optionally change their value between statements: - Item_literal - real NOT NULL constants - Item_param - can change between statements - Item_splocal - can change between statements - Item_user_var_as_out_param - hack Note, Item_user_var_as_out_param actually abuses the type code. It should be moved out of the Item tree eventually. */ CONST_ITEM, NULL_ITEM, // Item_null or Item_param bound to NULL COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, CONTEXTUALLY_TYPED_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, PARAM_ITEM, TRIGGER_FIELD_ITEM, EXPR_CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum traverse_order { POSTFIX, PREFIX }; protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); /** Create a field based on the exact data type handler. */ Field *create_table_field_from_handler(MEM_ROOT *root, TABLE *table) { const Type_handler *h= type_handler(); return h->make_and_init_table_field(root, &name, Record_addr(maybe_null()), *this, table); } /** Create a field based on field_type of argument. This is used to create a field for - IFNULL(x,something) - time functions - prepared statement placeholders - SP variables with data type references: DECLARE a TYPE OF t1.a; @retval NULL error @retval !NULL on success */ Field *tmp_table_field_from_field_type(MEM_ROOT *root, TABLE *table) { DBUG_ASSERT(fixed()); const Type_handler *h= type_handler()->type_handler_for_tmp_table(this); return h->make_and_init_table_field(root, &name, Record_addr(maybe_null()), *this, table); } /** Create a temporary field for a simple Item, which does not need any special action after the field creation: - is not an Item_field descendant (and not a reference to Item_field) - is not an Item_result_field descendant - does not need to copy any DEFAULT value to the result Field - does not need to set Field::is_created_from_null_item for the result See create_tmp_field_ex() for details on parameters and return values. */ Field *create_tmp_field_ex_simple(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) { DBUG_ASSERT(!param->make_copy_field()); DBUG_ASSERT(!is_result_field()); DBUG_ASSERT(type() != NULL_ITEM); return tmp_table_field_from_field_type(root, table); } Field *create_tmp_field_int(MEM_ROOT *root, TABLE *table, uint convert_int_length); Field *tmp_table_field_from_field_type_maybe_null(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param, bool is_explicit_null); virtual void raise_error_not_evaluable(); void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_positive_complement(THD *thd); /* Helper methods, to get an Item value from another Item */ double val_real_from_item(Item *item) { DBUG_ASSERT(fixed()); double value= item->val_real(); null_value= item->null_value; return value; } longlong val_int_from_item(Item *item) { DBUG_ASSERT(fixed()); longlong value= item->val_int(); null_value= item->null_value; return value; } String *val_str_from_item(Item *item, String *str) { DBUG_ASSERT(fixed()); String *res= item->val_str(str); if (res) res->set_charset(collation.collation); if ((null_value= item->null_value)) res= NULL; return res; } bool val_native_from_item(THD *thd, Item *item, Native *to) { DBUG_ASSERT(fixed()); null_value= item->val_native(thd, to); DBUG_ASSERT(null_value == item->null_value); return null_value; } bool val_native_from_field(Field *field, Native *to) { if ((null_value= field->is_null())) return true; return (null_value= field->val_native(to)); } bool val_native_with_conversion_from_item(THD *thd, Item *item, Native *to, const Type_handler *handler) { DBUG_ASSERT(fixed()); return (null_value= item->val_native_with_conversion(thd, to, handler)); } my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value) { DBUG_ASSERT(fixed()); my_decimal *value= item->val_decimal(decimal_value); if ((null_value= item->null_value)) value= NULL; return value; } bool get_date_from_item(THD *thd, Item *item, MYSQL_TIME *ltime, date_mode_t fuzzydate) { bool rc= item->get_date(thd, ltime, fuzzydate); null_value= MY_TEST(rc || item->null_value); return rc; } public: /* Cache val_str() into the own buffer, e.g. to evaluate constant expressions with subqueries in the ORDER/GROUP clauses. */ String *val_str() { return val_str(&str_value); } String *val_str_null_to_empty(String *to) { String *res= val_str(to); if (res) return res; to->set_charset(collation.collation); to->length(0); return to; } String *val_str_null_to_empty(String *to, bool null_to_empty) { return null_to_empty ? val_str_null_to_empty(to) : val_str(to); } virtual Item_func *get_item_func() { return NULL; } const MY_LOCALE *locale_from_val_str(); /* All variables for the Item class */ /** Intrusive list pointer for free list. If not null, points to the next Item on some Query_arena's free list. For instance, stored procedures have their own Query_arena's. @see Query_arena::free_list */ Item *next; /* str_values's main purpose is to be used to cache the value in save_in_field. Calling full_name() for Item_field will also use str_value. */ String str_value; LEX_CSTRING name; /* Name of item */ /* Original item name (if it was renamed)*/ LEX_CSTRING orig_name; /* All common bool variables for an Item is stored here */ item_base_t base_flags; item_with_t with_flags; /* Marker is used in some functions to temporary mark an item */ int16 marker; /* Tells is the val() value of the item is/was null. This should not be part of the bit flags as it's changed a lot and also we use pointers to it */ bool null_value; /* Cache of the result of is_expensive(). */ int8 is_expensive_cache; /** The index in the JOIN::join_tab array of the JOIN_TAB this Item is attached to. Items are attached (or 'pushed') to JOIN_TABs during optimization by the make_cond_for_table procedure. During query execution, this item is evaluated when the join loop reaches the corresponding JOIN_TAB. If the value of join_tab_idx >= MAX_TABLES, this means that there is no corresponding JOIN_TAB. */ uint8 join_tab_idx; inline bool maybe_null() const { return (bool) (base_flags & item_base_t::MAYBE_NULL); } inline bool in_rollup() const { return (bool) (base_flags & item_base_t::IN_ROLLUP); } inline bool fixed() const { return (bool) (base_flags & item_base_t::FIXED); } inline bool is_explicit_name() const { return (bool) (base_flags & item_base_t::IS_EXPLICIT_NAME); } inline bool is_in_with_cycle() const { return (bool) (base_flags & item_base_t::IS_IN_WITH_CYCLE); } inline bool is_cond() const { return (bool) (base_flags & item_base_t::IS_COND); } inline bool with_sp_var() const { return (bool) (with_flags & item_with_t::SP_VAR); } inline bool with_window_func() const { return (bool) (with_flags & item_with_t::WINDOW_FUNC); } inline bool with_field() const { return (bool) (with_flags & item_with_t::FIELD); } inline bool with_sum_func() const { return (bool) (with_flags & item_with_t::SUM_FUNC); } inline bool with_subquery() const { return (bool) (with_flags & item_with_t::SUBQUERY); } inline bool with_rownum_func() const { return (bool) (with_flags & item_with_t::ROWNUM_FUNC); } inline bool with_param() const { return (bool) (with_flags & item_with_t::PARAM); } inline void copy_flags(const Item *org, item_base_t mask) { base_flags= (item_base_t) (((item_flags_t) base_flags & ~(item_flags_t) mask) | ((item_flags_t) org->base_flags & (item_flags_t) mask)); } inline void copy_flags(const Item *org, item_with_t mask) { with_flags= (item_with_t) (((item_flags_t) with_flags & ~(item_flags_t) mask) | ((item_flags_t) org->with_flags & (item_flags_t) mask)); } // alloc & destruct is done as start of select on THD::mem_root Item(THD *thd); /* Constructor used by Item_field, Item_ref & aggregate (sum) functions. Used for duplicating lists in processing queries with temporary tables Also it used for Item_cond_and/Item_cond_or for creating top AND/OR structure of WHERE clause to protect it of optimisation changes in prepared statements */ Item(THD *thd, Item *item); Item(); /* For const item */ virtual ~Item() { #ifdef EXTRA_DEBUG name.str= 0; name.length= 0; #endif } /*lint -e1509 */ void set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs); void set_name(THD *thd, String *str) { set_name(thd, str->ptr(), str->length(), str->charset()); } void set_name(THD *thd, const LEX_CSTRING &str, CHARSET_INFO *cs= system_charset_info) { set_name(thd, str.str, str.length, cs); } void set_name_no_truncate(THD *thd, const char *str, uint length, CHARSET_INFO *cs); void init_make_send_field(Send_field *tmp_field, const Type_handler *h); void share_name_with(const Item *item) { name= item->name; copy_flags(item, item_base_t::IS_EXPLICIT_NAME); } virtual void cleanup(); virtual void make_send_field(THD *thd, Send_field *field); bool fix_fields_if_needed(THD *thd, Item **ref) { return fixed() ? false : fix_fields(thd, ref); } /* fix_fields_if_needed_for_scalar() is used where we need to filter items that can't be scalars and want to return error for it. */ bool fix_fields_if_needed_for_scalar(THD *thd, Item **ref) { return fix_fields_if_needed(thd, ref) || check_cols(1); } bool fix_fields_if_needed_for_bool(THD *thd, Item **ref) { return fix_fields_if_needed_for_scalar(thd, ref); } bool fix_fields_if_needed_for_order_by(THD *thd, Item **ref) { return fix_fields_if_needed_for_scalar(thd, ref); } /* By default we assume that an Item is fixed by the constructor */ virtual bool fix_fields(THD *, Item **) { /* This should not normally be called, because usually before fix_fields() we check fixed() to be false. But historically we allow fix_fields() to be called for Items who return basic_const_item()==true. */ DBUG_ASSERT(fixed()); DBUG_ASSERT(basic_const_item()); return false; } virtual void unfix_fields() { DBUG_ASSERT(0); } /* Fix after some tables has been pulled out. Basically re-calculate all attributes that are dependent on the tables. */ virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) {}; /* This is for items that require a fixup after the JOIN::prepare() is done. */ virtual void fix_after_optimize(THD *thd) {} /* This method should be used in case where we are sure that we do not need complete fix_fields() procedure. Usually this method is used by the optimizer when it has to create a new item out of other already fixed items. For example, if the optimizer has to create a new Item_func for an inferred equality whose left and right parts are already fixed items. In some cases the optimizer cannot use directly fixed items as the arguments of the created functional item, but rather uses intermediate type conversion items. Then the method is supposed to be applied recursively. */ virtual void quick_fix_field() { DBUG_ASSERT(0); } bool save_in_value(THD *thd, st_value *value) { return type_handler()->Item_save_in_value(thd, this, value); } /* Function returns 1 on overflow and -1 on fatal errors */ int save_in_field_no_warnings(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions); virtual bool save_in_param(THD *thd, Item_param *param); virtual void save_org_in_field(Field *field, fast_field_copier data __attribute__ ((__unused__))) { (void) save_in_field(field, 1); } virtual fast_field_copier setup_fast_field_copier(Field *field) { return NULL; } virtual int save_safe_in_field(Field *field) { return save_in_field(field, 1); } virtual bool send(Protocol *protocol, st_value *buffer) { return type_handler()->Item_send(this, protocol, buffer); } struct Eq_config { bool binary_cmp; /**< Make binary comparison */ bool omit_table_names; /**< Skip table and db names comparison */ Eq_config(bool binary_cmp, bool omit_table_names= false) : binary_cmp(binary_cmp), omit_table_names(omit_table_names) {} }; virtual bool eq(const Item *, const Eq_config &config) const; enum_field_types field_type() const { return type_handler()->field_type(); } virtual const Type_handler *type_handler() const= 0; /** Detects if an Item has a fixed data type which is known even before fix_fields(). Currently it's important only to find Items with a fixed boolean data type. More item types can be marked in the future as having a fixed data type (e.g. all literals, all fixed type functions, etc). @retval NULL if the Item type is not known before fix_fields() @retval the pointer to the data type handler, if the data type is known before fix_fields(). */ virtual const Type_handler *fixed_type_handler() const { return NULL; } const Type_handler *type_handler_for_comparison() const { return type_handler()->type_handler_for_comparison(); } virtual const Type_handler *real_type_handler() const { return type_handler(); } const Type_handler *cast_to_int_type_handler() const { return real_type_handler()->cast_to_int_type_handler(); } /* result_type() of an item specifies how the value should be returned */ Item_result result_type() const { return type_handler()->result_type(); } /* ... while cmp_type() specifies how it should be compared */ Item_result cmp_type() const { return type_handler()->cmp_type(); } const Type_handler *string_type_handler() const { return Type_handler::string_type_handler(max_length); } /* Calculate the maximum length of an expression. This method is used in data type aggregation for UNION, e.g.: SELECT 'b' UNION SELECT COALESCE(double_10_3_field) FROM t1; The result is usually equal to max_length, except for some numeric types. In case of the INT, FLOAT, DOUBLE data types Item::max_length and Item::decimals are ignored, so the returned value depends only on the data type itself. E.g. for an expression of the DOUBLE(10,3) data type, the result is always 53 (length 10 and precision 3 do not matter). max_length is ignored for these numeric data types because the length limit means only "expected maximum length", it is not a hard limit, so it does not impose any data truncation. E.g. a column of the type INT(4) can normally store big values up to 2147483647 without truncation. When we're aggregating such column for UNION it's important to create a long enough result column, not to lose any data. For detailed behaviour of various data types see implementations of the corresponding Type_handler_xxx::max_display_length(). Note, Item_field::max_display_length() overrides this to get max_display_length() from the underlying field. */ virtual uint32 max_display_length() const { return type_handler()->max_display_length(this); } const TYPELIB *get_typelib() const override { return NULL; } /* optimized setting of maybe_null without jumps. Minimizes code size */ inline void set_maybe_null(bool maybe_null_arg) { base_flags= ((item_base_t) ((base_flags & ~item_base_t::MAYBE_NULL)) | (item_base_t) (maybe_null_arg << ITEM_FLAGS_MAYBE_NULL_SHIFT)); } /* This is used a lot, so make it simpler to use */ void set_maybe_null() { base_flags|= item_base_t::MAYBE_NULL; } /* This is used when calling Type_all_attributes::set_type_maybe_null() */ void set_type_maybe_null(bool maybe_null_arg) override { set_maybe_null(maybe_null_arg); } /* Mark the item that it is a top level item, or part of a top level AND item, for WHERE and ON clauses: Example: ... WHERE a=5 AND b=6; Both a=5 and b=6 are top level items This is used to indicate that there is no distinction between if the value of the item is FALSE or NULL.. This enables Item_cond_and and subquery related items to do special "top level" optimizations. */ virtual void top_level_item() { base_flags|= item_base_t::AT_TOP_LEVEL; } /* Return TRUE if this item of top WHERE level (AND/OR) */ bool is_top_level_item() const { return (bool) (base_flags & item_base_t::AT_TOP_LEVEL); } void set_typelib(const TYPELIB *typelib) override { // Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet. DBUG_ASSERT(0); } Item_cache* get_cache(THD *thd) const { return type_handler()->Item_get_cache(thd, this); } virtual enum Type type() const =0; bool is_of_type(Type t, Item_result cmp) const { return type() == t && cmp_type() == cmp; } /* real_type() is the type of base item. This is same as type() for most items, except Item_ref() and Item_cache_wrapper() where it shows the type for the underlying item. */ virtual enum Type real_type() const { return type(); } /* Return information about function monotonicity. See comment for enum_monotonicity_info for details. This function can only be called after fix_fields() call. */ virtual enum_monotonicity_info get_monotonicity_info() const { return NON_MONOTONIC; } /* Convert "func_arg $CMP$ const" half-interval into "FUNC(func_arg) $CMP2$ const2" SYNOPSIS val_int_endpoint() left_endp FALSE <=> The interval is "x < const" or "x <= const" TRUE <=> The interval is "x > const" or "x >= const" incl_endp IN FALSE <=> the comparison is '<' or '>' TRUE <=> the comparison is '<=' or '>=' OUT The same but for the "F(x) $CMP$ F(const)" comparison DESCRIPTION This function is defined only for unary monotonic functions. The caller supplies the source half-interval x $CMP$ const The value of const is supplied implicitly as the value this item's argument, the form of $CMP$ comparison is specified through the function's arguments. The calle returns the result interval F(x) $CMP2$ F(const) passing back F(const) as the return value, and the form of $CMP2$ through the out parameter. NULL values are assumed to be comparable and be less than any non-NULL values. RETURN The output range bound, which equal to the value of val_int() - If the value of the function is NULL then the bound is the smallest possible value of LONGLONG_MIN */ virtual longlong val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(0); return 0; } /* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */ /* Return double precision floating point representation of item. SYNOPSIS val_real() RETURN In case of NULL value return 0.0 and set null_value flag to TRUE. If value is not null null_value flag will be reset to FALSE. */ virtual double val_real()=0; Double_null to_double_null() { // val_real() must be caleed on a separate line. See to_longlong_null() double nr= val_real(); return Double_null(nr, null_value); } /* Return integer representation of item. SYNOPSIS val_int() RETURN In case of NULL value return 0 and set null_value flag to TRUE. If value is not null null_value flag will be reset to FALSE. */ virtual longlong val_int()=0; Longlong_hybrid to_longlong_hybrid() { return Longlong_hybrid(val_int(), unsigned_flag); } Longlong_null to_longlong_null() { longlong nr= val_int(); /* C++ does not guarantee the order of parameter evaluation, so to make sure "null_value" is passed to the constructor after the val_int() call, val_int() is caled on a separate line. */ return Longlong_null(nr, null_value); } Longlong_hybrid_null to_longlong_hybrid_null() { return Longlong_hybrid_null(to_longlong_null(), unsigned_flag); } /** Get a value for CAST(x AS SIGNED). Too large positive unsigned integer values are converted to negative complements. Values of non-integer data types are adjusted to the SIGNED range. */ virtual longlong val_int_signed_typecast() { return cast_to_int_type_handler()->Item_val_int_signed_typecast(this); } longlong val_int_signed_typecast_from_str(); /** Get a value for CAST(x AS UNSIGNED). Negative signed integer values are converted to positive complements. Values of non-integer data types are adjusted to the UNSIGNED range. */ virtual longlong val_int_unsigned_typecast() { return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this); } longlong val_int_unsigned_typecast_from_int(); longlong val_int_unsigned_typecast_from_str(); longlong val_int_unsigned_typecast_from_real(); /** Get a value for CAST(x AS UNSIGNED). Huge positive unsigned values are converted to negative complements. */ longlong val_int_signed_typecast_from_int(); longlong val_int_signed_typecast_from_real(); /* This is just a shortcut to avoid the cast. You should still use unsigned_flag to check the sign of the item. */ inline ulonglong val_uint() { return (ulonglong) val_int(); } virtual bool hash_not_null(Hasher *hasher) { DBUG_ASSERT(0); return true; } /* Return string representation of this item object. SYNOPSIS val_str() str an allocated buffer this or any nested Item object can use to store return value of this method. NOTE The caller can modify the returned String, if it's not marked "const" (with the String::mark_as_const() method). That means that if the item returns its own internal buffer (e.g. tmp_value), it *must* be marked "const" [1]. So normally it's preferable to return the result value in the String, that was passed as an argument. But, for example, SUBSTR() returns a String that simply points into the buffer of SUBSTR()'s args[0]->val_str(). Such a String is always "const", so it's ok to use tmp_value for that and avoid reallocating/copying of the argument String. [1] consider SELECT CONCAT(f, ":", f) FROM (SELECT func() AS f); here the return value of f() is used twice in the top-level select, and if they share the same tmp_value buffer, modifying the first one will implicitly modify the second too. RETURN In case of NULL value return 0 (NULL pointer) and set null_value flag to TRUE. If value is not null null_value flag will be reset to FALSE. */ virtual String *val_str(String *str)=0; bool val_native_with_conversion(THD *thd, Native *to, const Type_handler *th) { return th->Item_val_native_with_conversion(thd, this, to); } bool val_native_with_conversion_result(THD *thd, Native *to, const Type_handler *th) { return th->Item_val_native_with_conversion_result(thd, this, to); } virtual bool val_native(THD *thd, Native *to) { /* The default implementation for the Items that do not need native format: - Item_basic_value (default implementation) - Item_copy - Item_exists_subselect - Item_sum_field - Item_sum_or_func (default implementation) - Item_proc - Item_type_holder (as val_xxx() are never called for it); These hybrid Item types override val_native(): - Item_field - Item_param - Item_sp_variable - Item_ref - Item_cache_wrapper - Item_direct_ref - Item_direct_view_ref - Item_ref_null_helper - Item_name_const - Item_time_literal - Item_sum_or_func Note, these hybrid type Item_sum_or_func descendants override the default implementation: * Item_sum_hybrid * Item_func_hybrid_field_type * Item_func_min_max * Item_func_sp * Item_func_last_value * Item_func_rollup_const */ DBUG_ASSERT(0); return (null_value= 1); } virtual bool val_native_result(THD *thd, Native *to) { return val_native(thd, to); } /* Returns string representation of this item in ASCII format. SYNOPSIS val_str_ascii() str - similar to val_str(); NOTE This method is introduced for performance optimization purposes. 1. val_str() result of some Items in string context depends on @@character_set_results. @@character_set_results can be set to a "real multibyte" character set like UCS2, UTF16, UTF32. (We'll use only UTF32 in the examples below for convenience.) So the default string result of such functions in these circumstances is real multi-byte character set, like UTF32. For example, all numbers in string context return result in @@character_set_results: SELECT CONCAT(20010101); -> UTF32 We do sprintf() first (to get ASCII representation) and then convert to UTF32; So these kind "data sources" can use ASCII representation internally, but return multi-byte data only because @@character_set_results wants so. Therefore, conversion from ASCII to UTF32 is applied internally. 2. Some other functions need in fact ASCII input. For example, inet_aton(), GeometryFromText(), Convert_TZ(), GET_FORMAT(). Similar, fields of certain type, like DATE, TIME, when you insert string data into them, expect in fact ASCII input. If they get non-ASCII input, for example UTF32, they convert input from UTF32 to ASCII, and then use ASCII representation to do further processing. 3. Now imagine we pass result of a data source of the first type to a data destination of the second type. What happens: a. data source converts data from ASCII to UTF32, because @@character_set_results wants so and passes the result to data destination. b. data destination gets UTF32 string. c. data destination converts UTF32 string to ASCII, because it needs ASCII representation to be able to handle data correctly. As a result we get two steps of unnecessary conversion: From ASCII to UTF32, then from UTF32 to ASCII. A better way to handle these situations is to pass ASCII representation directly from the source to the destination. This is why val_str_ascii() introduced. RETURN Similar to val_str() */ virtual String *val_str_ascii(String *str); /* Returns the result of val_str_ascii(), translating NULLs back to empty strings (if MODE_EMPTY_STRING_IS_NULL is set). */ String *val_str_ascii_revert_empty_string_is_null(THD *thd, String *str); /* Returns the val_str() value converted to the given character set. */ String *val_str(String *str, String *converter, CHARSET_INFO *to); virtual String *val_json(String *str) { return val_str(str); } /* Return decimal representation of item with fixed point. SYNOPSIS val_decimal() decimal_buffer buffer which can be used by Item for returning value (but can be not) NOTE Returned value should not be changed if it is not the same which was passed via argument. RETURN Return pointer on my_decimal (it can be other then passed via argument) if value is not NULL (null_value flag will be reset to FALSE). In case of NULL value it return 0 pointer and set null_value flag to TRUE. */ virtual my_decimal *val_decimal(my_decimal *decimal_buffer)= 0; /* Return boolean value of item. RETURN FALSE value is false or NULL TRUE value is true (not equal to 0) */ virtual bool val_bool() { return type_handler()->Item_val_bool(this); } bool eval_const_cond() { DBUG_ASSERT(const_item()); DBUG_ASSERT(!is_expensive()); return val_bool(); } bool can_eval_in_optimize() { return const_item() && !is_expensive(); } /* save_val() is method of val_* family which stores value in the given field. */ virtual void save_val(Field *to) { save_org_in_field(to, NULL); } /* save_result() is method of val*result() family which stores value in the given field. */ virtual void save_result(Field *to) { save_val(to); } /* Helper functions, see item_sum.cc */ String *val_string_from_real(String *str); String *val_string_from_int(String *str); my_decimal *val_decimal_from_real(my_decimal *decimal_value); my_decimal *val_decimal_from_int(my_decimal *decimal_value); my_decimal *val_decimal_from_string(my_decimal *decimal_value); longlong val_int_from_real() { DBUG_ASSERT(fixed()); return Converter_double_to_longlong_with_warn(val_real(), false).result(); } longlong val_int_from_str(int *error); /* Returns true if this item can be calculated during value_depends_on_sql_mode() */ bool value_depends_on_sql_mode_const_item() { /* Currently we use value_depends_on_sql_mode() only for virtual column expressions. They should not contain any expensive items. If we ever get a crash on the assert below, it means check_vcol_func_processor() is badly implemented for this item. */ DBUG_ASSERT(!is_expensive()); /* It should return const_item() actually. But for some reasons Item_field::const_item() returns true at value_depends_on_sql_mode() call time. This should be checked and fixed. */ return basic_const_item(); } virtual Sql_mode_dependency value_depends_on_sql_mode() const { return Sql_mode_dependency(); } int save_time_in_field(Field *field, bool no_conversions); int save_date_in_field(Field *field, bool no_conversions); int save_str_in_field(Field *field, bool no_conversions); int save_real_in_field(Field *field, bool no_conversions); int save_int_in_field(Field *field, bool no_conversions); int save_bool_in_field(Field *field, bool no_conversions); int save_decimal_in_field(Field *field, bool no_conversions); int save_str_value_in_field(Field *field, String *result); virtual Field *get_tmp_table_field() { return 0; } virtual Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table); inline const char *full_name() const { return full_name_cstring().str; } virtual LEX_CSTRING full_name_cstring() const { if (name.str) return name; return { STRING_WITH_LEN("???") }; } const char *field_name_or_null() { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; } const TABLE_SHARE *field_table_or_null(); /* *result* family of methods is analog of *val* family (see above) but return value of result_field of item if it is present. If Item have not result field, it return val(). This methods set null_value flag in same way as *val* methods do it. */ virtual double val_result() { return val_real(); } virtual longlong val_int_result() { return val_int(); } virtual String *str_result(String* tmp) { return val_str(tmp); } virtual my_decimal *val_decimal_result(my_decimal *val) { return val_decimal(val); } virtual bool val_bool_result() { return val_bool(); } virtual bool is_null_result() { return is_null(); } /* Returns 1 if result type and collation for val_str() can change between calls */ virtual bool dynamic_result() { return 0; } /* Bitmap of tables used by item (note: if you need to check dependencies on individual columns, check out class Field_enumerator) */ virtual table_map used_tables() const { return (table_map) 0L; } virtual table_map all_used_tables() const { return used_tables(); } /* Return table map of tables that can't be NULL tables (tables that are used in a context where if they would contain a NULL row generated by a LEFT or RIGHT join, the item would not be true). This expression is used on WHERE item to determinate if a LEFT JOIN can be converted to a normal join. Generally this function should return used_tables() if the function would return null if any of the arguments are null As this is only used in the beginning of optimization, the value don't have to be updated in update_used_tables() */ virtual table_map not_null_tables() const { return used_tables(); } /* Returns true if this is a simple constant item like an integer, not a constant expression. Used in the optimizer to propagate basic constants. */ virtual bool basic_const_item() const { return 0; } /** Determines if the expression is allowed as a virtual column assignment source: INSERT INTO t1 (vcol) VALUES (10) -> error INSERT INTO t1 (vcol) VALUES (NULL) -> ok */ virtual bool vcol_assignment_allowed_value() const { return false; } /** Test if "this" is an ORDER position (rather than an expression). Notes: - can be called before fix_fields(). - local SP variables (even of integer types) are always expressions, not positions. (And they can't be used before fix_fields is called for them). */ virtual bool is_order_clause_position() const { return false; } /* Determines if the Item is an evaluable expression, that is it can return a value, so we can call methods val_xxx(), get_date(), etc. Most items are evaluable expressions. Examples of non-evaluable expressions: - Item_contextually_typed_value_specification (handling DEFAULT and IGNORE) - Item_type_param bound to DEFAULT and IGNORE We cannot call the mentioned methods for these Items, their method implementations typically have DBUG_ASSERT(0). */ virtual bool is_evaluable_expression() const { return true; } virtual bool check_assignability_to(const Field *to, bool ignore) const { /* "this" must be neither DEFAULT/IGNORE, nor Item_param bound to DEFAULT/IGNORE. */ DBUG_ASSERT(is_evaluable_expression()); return to->check_assignability_from(type_handler(), ignore); } /** * Check whether the item is a parameter ('?') of stored routine. * Default implementation returns false. Method is overridden in the class * Item_param where it returns true. */ virtual bool is_stored_routine_parameter() const { return false; } bool check_is_evaluable_expression_or_error() { if (is_evaluable_expression()) return false; // Ok raise_error_not_evaluable(); return true; // Error } /* Create a shallow copy of the item (usually invoking copy constructor). For deep copying see deep_copy_with_checks(). Return value: - pointer to a copy of the Item - nullptr if the item is not copyable */ Item *shallow_copy_with_checks(THD *thd) const { Item *copy= shallow_copy(thd); if (copy) { // Make sure the copy is of same type as this item DBUG_ASSERT(typeid(*copy) == typeid(*this)); } return copy; } /* Creates a clone of the item by deep copying. Return value: - pointer to a clone of the Item - nullptr if the item is not clonable */ Item* deep_copy_with_checks(THD *thd) const { Item *clone= deep_copy(thd); if (clone) { // Make sure the clone is of same type as this item DBUG_ASSERT(typeid(*clone) == typeid(*this)); } return clone; } /* Clones the constant item (not necessary returning the same item type) Return value: - pointer to a clone of the Item - nullptr if the item is not clonable Note: the clone may have item type different from this (i.e., instance of another basic constant class may be returned). For real clones look at deep_copy_with_checks()/shallow_copy_with_checks() methods */ virtual Item *clone_constant(THD *thd) const { return nullptr; } /* @detail The meaning of this function seems to be: Check what the item would return if it was provided with two identical non-NULL arguments. It is not clear why it is defined for generic class Item or what its other uses are. @return COND_TRUE Would return true COND_FALSE Would return false COND_OK May return either, depending on the argument type. */ virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals < FLOATING_POINT_DECIMALS ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} /* Returns total number of decimal digits */ decimal_digits_t decimal_precision() const override { return type_handler()->Item_decimal_precision(this); } /* Returns the number of integer part digits only */ inline decimal_digits_t decimal_int_part() const { return (decimal_digits_t) my_decimal_int_part(decimal_precision(), decimals); } /* Returns the number of fractional digits only. NOT_FIXED_DEC is replaced to the maximum possible number of fractional digits, taking into account the data type. */ decimal_digits_t decimal_scale() const { return type_handler()->Item_decimal_scale(this); } /* Returns how many digits a divisor adds into a division result. This is important when the integer part of the divisor can be 0. In this example: SELECT 1 / 0.000001; -> 1000000.0000 the divisor adds 5 digits into the result precision. Currently this method only replaces NOT_FIXED_DEC to TIME_SECOND_PART_DIGITS for temporal data types. This method can be made virtual, to create more efficient (smaller) data types for division results. For example, in SELECT 1/1.000001; the divisor could provide no additional precision into the result, so could any other items that are know to return a result with non-zero integer part. */ uint divisor_precision_increment() const { return type_handler()->Item_divisor_precision_increment(this); } /** TIME or DATETIME precision of the item: 0..6 */ decimal_digits_t time_precision(THD *thd) { return const_item() ? type_handler()->Item_time_precision(thd, this) : MY_MIN(decimals, TIME_SECOND_PART_DIGITS); } decimal_digits_t datetime_precision(THD *thd) { return const_item() ? type_handler()->Item_datetime_precision(thd, this) : MY_MIN(decimals, TIME_SECOND_PART_DIGITS); } virtual longlong val_int_min() const { return LONGLONG_MIN; } /* Returns true if this is constant (during query execution, i.e. its value will not change until next fix_fields) and its value is known. */ virtual bool const_item() const { return used_tables() == 0; } /* Returns true if this is constant but its value may be not known yet. (Can be used for parameters of prep. stmts or of stored procedures.) */ virtual bool const_during_execution() const { return (used_tables() & ~PARAM_TABLE_BIT) == 0; } /** This method is used for to: - to generate a view definition query (SELECT-statement); - to generate a SQL-query for EXPLAIN EXTENDED; - to generate a SQL-query to be shown in INFORMATION_SCHEMA; - debug. For more information about view definition query, INFORMATION_SCHEMA query and why they should be generated from the Item-tree, @see mysql_register_view(). */ virtual enum precedence precedence() const { return DEFAULT_PRECEDENCE; } enum precedence higher_precedence() const { return (enum precedence)(precedence() + 1); } void print_parenthesised(String *str, enum_query_type query_type, enum precedence parent_prec); /** This helper is used to print expressions as a part of a table definition, in particular for - generated columns - check constraints - default value expressions - partitioning expressions */ void print_for_table_def(String *str) { print_parenthesised(str, (enum_query_type)(QT_ITEM_ORIGINAL_FUNC_NULLIF | QT_ITEM_IDENT_SKIP_DB_NAMES | QT_ITEM_IDENT_SKIP_TABLE_NAMES | QT_NO_DATA_EXPANSION | QT_TO_SYSTEM_CHARSET | QT_FOR_FRM), LOWEST_PRECEDENCE); } virtual void print(String *str, enum_query_type query_type); class Print: public String { public: Print(Item *item, enum_query_type type) { item->print(this, type); } }; void print_item_w_name(String *str, enum_query_type query_type); void print_value(String *str); virtual void update_used_tables() {} virtual COND *build_equal_items(THD *thd, COND_EQUAL *inheited, bool link_item_fields, COND_EQUAL **cond_equal_ref) { update_used_tables(); DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); return this; } virtual COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level); virtual void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables) { return; } /* Make a select tree for all keys in a condition or a condition part @param param Context @param cond_ptr[OUT] Store a replacement item here if the condition can be simplified, e.g.: WHERE part1 OR part2 OR part3 with one of the partN evaluating to SEL_TREE::ALWAYS. */ virtual SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr); /* Checks whether the item is: - a simple equality (field=field_item or field=constant_item), or - a row equality and form multiple equality predicates. */ virtual bool check_equality(THD *thd, COND_EQUAL *cond, List<Item> *eq_list) { return false; } virtual void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) {} /* Called for items that really have to be split */ void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, Item **ref, uint flags); virtual bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)= 0; bool get_date_from_int(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_date_from_string(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_time(THD *thd, MYSQL_TIME *ltime) { return get_date(thd, ltime, Time::Options(thd)); } // Get a DATE or DATETIME value in numeric packed format for comparison virtual longlong val_datetime_packed(THD *thd) { return Datetime(thd, this, Datetime::Options_cmp(thd)).to_packed(); } // Get a TIME value in numeric packed format for comparison virtual longlong val_time_packed(THD *thd) { return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_datetime_packed_result(THD *thd); longlong val_time_packed_result(THD *thd); virtual bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { return get_date(thd, ltime,fuzzydate); } /* The method allows to determine nullness of a complex expression without fully evaluating it, instead of calling val/result*() then checking null_value. Used in Item_func_isnull/Item_func_isnotnull and Item_sum_count. Any new item which can be NULL must implement this method. */ virtual bool is_null() { return 0; } /* Make sure the null_value member has a correct value. */ virtual void update_null_value () { return type_handler()->Item_update_null_value(this); } /* return IN/ALL/ANY subquery or NULL */ virtual Item_in_subselect* get_IN_subquery() { return NULL; /* in is not IN/ALL/ANY */ } /* set field of temporary table for Item which can be switched on temporary table during query processing (grouping and so on) */ virtual bool is_result_field() { return 0; } virtual bool is_bool_literal() const { return false; } /* This is to handle printing of default values */ virtual bool need_parentheses_in_default() { return false; } virtual void save_in_result_field(bool no_conversions) {} /* Data type format implied by the CHECK CONSTRAINT, to be sent to the client in the result set metadata. */ virtual bool set_format_by_check_constraint(Send_field_extended_metadata *) const { return false; } /* set value of aggregate function in case of no rows for grouping were found */ virtual void no_rows_in_result() {} virtual void restore_to_before_no_rows_in_result() {} virtual Item *copy_or_same(THD *thd) { return this; } virtual Item *copy_andor_structure(THD *thd) { return this; } virtual Item *real_item() { return this; } const Item *real_item() const { return const_cast<Item*>(this)->real_item(); } virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr) { return this; } static CHARSET_INFO *default_charset(); CHARSET_INFO *charset_for_protocol(void) const { return type_handler()->charset_for_protocol(this); }; virtual bool walk(Item_processor processor, bool walk_subquery, void *arg) { return (this->*processor)(arg); } virtual Item* transform(THD *thd, Item_transformer transformer, uchar *arg); virtual Item* top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) { return transform(thd, transformer, arg); } /* This function performs a generic "compilation" of the Item tree. The process of compilation is assumed to go as follows: compile() { if (this->*some_analyzer(...)) { compile children if any; this->*some_transformer(...); } } i.e. analysis is performed top-down while transformation is done bottom-up. */ virtual Item* compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) { if ((this->*analyzer) (arg_p)) return ((this->*transformer) (thd, arg_t)); return 0; } virtual Item* top_level_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) { return compile(thd, analyzer, arg_p, transformer, arg_t); } virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { (*traverser)(this, arg); } /*========= Item processors, to be used with Item::walk() ========*/ virtual bool remove_dependence_processor(void *arg) { return 0; } virtual bool cleanup_processor(void *arg); virtual bool cleanup_excluding_fields_processor (void *arg) { return cleanup_processor(arg); } bool cleanup_excluding_immutables_processor (void *arg); virtual bool cleanup_excluding_const_fields_processor (void *arg) { return cleanup_processor(arg); } virtual bool collect_item_field_processor(void *arg) { return 0; } virtual bool unknown_splocal_processor(void *arg) { return 0; } virtual bool collect_outer_ref_processor(void *arg) {return 0; } virtual bool check_inner_refs_processor(void *arg) { return 0; } virtual bool find_item_in_field_list_processor(void *arg) { return 0; } virtual bool find_item_processor(void *arg); virtual bool change_context_processor(void *arg) { return 0; } virtual bool reset_query_id_processor(void *arg) { return 0; } virtual bool is_expensive_processor(void *arg) { return 0; } bool remove_immutable_flag_processor (void *arg); // FIXME reduce the number of "add field to bitmap" processors virtual bool add_field_to_set_processor(void *arg) { return 0; } virtual bool register_field_in_read_map(void *arg) { return 0; } virtual bool register_field_in_write_map(void *arg) { return 0; } virtual bool register_field_in_bitmap(void *arg) { return 0; } virtual bool update_table_bitmaps_processor(void *arg) { return 0; } virtual bool enumerate_field_refs_processor(void *arg) { return 0; } virtual bool mark_as_eliminated_processor(void *arg) { return 0; } virtual bool eliminate_subselect_processor(void *arg) { return 0; } virtual bool view_used_tables_processor(void *arg) { return 0; } virtual bool eval_not_null_tables(void *arg) { return 0; } virtual bool is_subquery_processor(void *arg) { return 0; } virtual bool count_sargable_conds(void *arg) { return 0; } virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; } virtual bool exists2in_processor(void *arg) { return 0; } virtual bool find_selective_predicates_list_processor(void *arg) { return 0; } virtual bool cleanup_is_expensive_cache_processor(void *arg) { is_expensive_cache= (int8)(-1); return 0; } virtual bool set_extraction_flag_processor(void *arg) { set_extraction_flag(*(int16*)arg); return 0; } virtual bool subselect_table_finder_processor(void *arg) { return 0; }; /* TRUE if the expression depends only on the table indicated by tab_map or can be converted to such an exression using equalities. Not to be used for AND/OR formulas. */ virtual bool excl_dep_on_table(table_map tab_map) { return false; } /* TRUE if the expression depends only on grouping fields of sel or can be converted to such an expression using equalities. It also checks if the expression doesn't contain stored procedures, subqueries or randomly generated elements. Not to be used for AND/OR formulas. */ virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; } /* TRUE if the expression depends only on fields from the left part of IN subquery or can be converted to such an expression using equalities. Not to be used for AND/OR formulas. */ virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) { return false; } virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; } virtual bool find_function_processor (void *arg) { return 0; } /* Check if a partition function is allowed SYNOPSIS check_partition_func_processor() int_arg Ignored RETURN VALUE TRUE Partition function not accepted FALSE Partition function accepted DESCRIPTION check_partition_func_processor is used to check if a partition function uses an allowed function. An allowed function will always ensure that X=Y guarantees that also part_function(X)=part_function(Y) where X is a set of partition fields and so is Y. The problems comes mainly from character sets where two equal strings can be quite unequal. E.g. the german character for double s is equal to 2 s. The default is that an item is not allowed in a partition function. Allowed functions can never depend on server version, they cannot depend on anything related to the environment. They can also only depend on a set of fields in the table itself. They cannot depend on other tables and cannot contain any queries and cannot contain udf's or similar. If a new Item class is defined and it inherits from a class that is allowed in a partition function then it is very important to consider whether this should be inherited to the new class. If not the function below should be defined in the new Item class. The general behaviour is that most integer functions are allowed. If the partition function contains any multi-byte collations then the function check_part_func_fields will report an error on the partition function independent of what functions are used. So the only character sets allowed are single character collation and even for those only a limited set of functions are allowed. The problem with multi-byte collations is that almost every string function has the ability to change things such that two strings that are equal will not be equal after manipulated by a string function. E.g. two strings one contains a double s, there is a special german character that is equal to two s. Now assume a string function removes one character at this place, then in one the double s will be removed and in the other there will still be one s remaining and the strings are no longer equal and thus the partition function will not sort equal strings into the same partitions. So the check if a partition function is valid is two steps. First check that the field types are valid, next check that the partition function is valid. The current set of partition functions valid assumes that there are no multi-byte collations amongst the partition fields. */ virtual bool check_partition_func_processor(void *arg) { return true; } virtual bool post_fix_fields_part_expr_processor(void *arg) { return 0; } virtual bool rename_fields_processor(void *arg) { return 0; } /* TRUE if the function is knowingly TRUE or FALSE. Not to be used for AND/OR formulas. */ virtual bool is_simplified_cond_processor(void *arg) { return false; } /** Processor used to check acceptability of an item in the defining expression for a virtual column @param arg always ignored @retval 0 the item is accepted in the definition of a virtual column @retval 1 otherwise */ struct vcol_func_processor_result { uint errors; /* Bits of possible errors */ const char *name; /* Not supported function */ Alter_info *alter_info; vcol_func_processor_result() : errors(0), name(NULL), alter_info(NULL) {} }; struct func_processor_rename { LEX_CSTRING db_name; LEX_CSTRING table_name; List<Create_field> fields; }; virtual bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(full_name(), arg, VCOL_IMPOSSIBLE); } virtual bool check_handler_func_processor(void *arg) { return 0; } virtual bool check_field_expression_processor(void *arg) { return 0; } virtual bool check_func_default_processor(void *arg) { return 0; } virtual bool update_func_default_processor(void *arg) { return 0; } /* Check if an expression value has allowed arguments, like DATE/DATETIME for date functions. Also used by partitioning code to reject timezone-dependent expressions in a (sub)partitioning function. */ virtual bool check_valid_arguments_processor(void *arg) { return 0; } virtual bool update_vcol_processor(void *arg) { return 0; } virtual bool set_fields_as_dependent_processor(void *arg) { return 0; } /* Find if some of the key parts of table keys (the reference on table is passed as an argument) participate in the expression. If there is some, sets a bit for this key in the proper key map. */ virtual bool check_index_dependence(void *arg) { return 0; } virtual bool check_sequence_privileges(void *arg) { return 0; } /*============== End of Item processor list ======================*/ /* Given a condition P from the WHERE clause or from an ON expression of the processed SELECT S and a set of join tables from S marked in the parameter 'allowed'={T} a call of P->find_not_null_fields({T}) has to find the set fields {F} of the tables from 'allowed' such that: - each field from {F} is declared as nullable - each record of table t from {T} that contains NULL as the value for at at least one field from {F} can be ignored when building the result set for S It is assumed here that the condition P is conjunctive and all its column references belong to T. Examples: CREATE TABLE t1 (a int, b int); CREATE TABLE t2 (a int, b int); SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b > 5; A call of find_not_null_fields() for the whole WHERE condition and {t1,t2} should find {t1.a,t1.b,t2.a} SELECT * FROM t1 LEFT JOIN ON (t1.a=t2.a and t2.a > t2.b); A call of find_not_null_fields() for the ON expression and {t2} should find {t2.a,t2.b} The function returns TRUE if it succeeds to prove that all records of a table from {T} can be ignored. Otherwise it always returns FALSE. Example: SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t2.a IS NULL; A call of find_not_null_fields() for the WHERE condition and {t1,t2} will return TRUE. It is assumed that the implementation of this virtual function saves the info on the found set of fields in the structures associates with tables from {T}. */ virtual bool find_not_null_fields(table_map allowed) { return false; } bool cache_const_expr_analyzer(uchar **arg); Item* cache_const_expr_transformer(THD *thd, uchar *arg); virtual Item* propagate_equal_fields(THD*, const Context &, COND_EQUAL *) { return this; }; Item* propagate_equal_fields_and_change_item_tree(THD *thd, const Context &ctx, COND_EQUAL *cond, Item **place); /* arg points to REPLACE_EQUAL_FIELD_ARG object */ virtual Item *replace_equal_field(THD *thd, uchar *arg) { return this; } struct Collect_deps_prm { List<Item> *parameters; /* unit from which we count nest_level */ st_select_lex_unit *nest_level_base; uint count; int nest_level; bool collect; }; /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. */ virtual Item *this_item() { return this; } virtual const Item *this_item() const { return this; } /* For SP local variable returns address of pointer to Item representing its current value and pointer passed via parameter otherwise. */ virtual Item **this_item_addr(THD *thd, Item **addr_arg) { return addr_arg; } // Row emulation virtual uint cols() const { return 1; } virtual Item* element_index(uint i) { return this; } virtual Item** addr(uint i) { return 0; } virtual bool check_cols(uint c); bool check_type_traditional_scalar(const LEX_CSTRING &opname) const; bool check_type_scalar(const LEX_CSTRING &opname) const; bool check_type_or_binary(const LEX_CSTRING &opname, const Type_handler *handler) const; bool check_type_general_purpose_string(const LEX_CSTRING &opname) const; bool check_type_can_return_int(const LEX_CSTRING &opname) const; bool check_type_can_return_decimal(const LEX_CSTRING &opname) const; bool check_type_can_return_real(const LEX_CSTRING &opname) const; bool check_type_can_return_str(const LEX_CSTRING &opname) const; bool check_type_can_return_text(const LEX_CSTRING &opname) const; bool check_type_can_return_date(const LEX_CSTRING &opname) const; bool check_type_can_return_time(const LEX_CSTRING &opname) const; // It is not row => null inside is impossible virtual bool null_inside() { return 0; } // used in row subselects to get value of elements virtual void bring_value() {} const Type_handler *type_handler_long_or_longlong() const { return Type_handler::type_handler_long_or_longlong(max_char_length(), unsigned_flag); } /** Create field for temporary table. @param table Temporary table @param [OUT] src Who created the fields @param param Create parameters @retval NULL (on error) @retval a pointer to a newly create Field (on success) */ virtual Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param)= 0; virtual Item_field *field_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } virtual Item *update_value_transformer(THD *thd, uchar *select_arg) { return this; } virtual Item *expr_cache_insert_transformer(THD *thd, uchar *unused) { return this; } virtual Item *derived_field_transformer_for_having(THD *thd, uchar *arg) { return this; } virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { return this; } virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) { return this; } /* Now is not used. */ virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) { return this; } virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { return this; } virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) { return this; } virtual Item *in_predicate_to_equality_transformer(THD *thd, uchar *arg) { return this; } virtual Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg) { return this; } virtual Item *multiple_equality_transformer(THD *thd, uchar *arg); virtual Item* varchar_upper_cmp_transformer(THD *thd, uchar *arg) { return this; } virtual Item* date_conds_transformer(THD *thd, uchar *arg) { return this; } virtual bool expr_cache_is_needed(THD *) { return FALSE; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const { /* This will return "true" if conversion happens: - between two non-binary different character sets - from "binary" to "unsafe" character set (those that can have non-well-formed string) - from "binary" to UCS2-alike character set with mbminlen>1, when prefix left-padding is needed for an incomplete character: binary 0xFF -> ucs2 0x00FF) */ if (!String::needs_conversion_on_storage(length, collation.collation, tocs)) return false; /* No needs to add converter if an "arg" is NUMERIC or DATETIME value (which is pure ASCII) and at the same time target DTCollation is ASCII-compatible. For example, no needs to rewrite: SELECT * FROM t1 WHERE datetime_field = '2010-01-01'; to SELECT * FROM t1 WHERE CONVERT(datetime_field USING cs) = '2010-01-01'; TODO: avoid conversion of any values with repertoire ASCII and 7bit-ASCII-compatible, not only numeric/datetime origin. */ if (collation.derivation == DERIVATION_NUMERIC && collation.repertoire == MY_REPERTOIRE_ASCII && !(collation.collation->state & MY_CS_NONASCII) && !(tocs->state & MY_CS_NONASCII)) return false; return true; } bool needs_charset_converter(CHARSET_INFO *tocs) { // Pass 1 as length to force conversion if tocs->mbminlen>1. return needs_charset_converter(1, tocs); } Item *const_charset_converter(THD *thd, CHARSET_INFO *tocs, bool lossless, const char *func_name); Item *const_charset_converter(THD *thd, CHARSET_INFO *tocs, bool lossless) { return const_charset_converter(thd, tocs, lossless, NULL); } void delete_self() { cleanup(); delete this; } virtual const Item_const *get_item_const() const { return NULL; } virtual Item_splocal *get_item_splocal() { return 0; } virtual Rewritable_query_parameter *get_rewritable_query_parameter() { return 0; } /* 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; } virtual Load_data_outvar *get_load_data_outvar() { return 0; } Load_data_outvar *get_load_data_outvar_or_error() { Load_data_outvar *dst= get_load_data_outvar(); if (dst) return dst; my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), name.str); return NULL; } /** Test whether an expression is expensive to compute. Used during optimization to avoid computing expensive expressions during this phase. Also used to force temp tables when sorting on expensive functions. @todo Normally we should have a method: cost Item::execution_cost(), where 'cost' is either 'double' or some structure of various cost parameters. @note This function is now used to prevent evaluation of expensive subquery predicates during the optimization phase. It also prevents evaluation of predicates that are not computable at this moment. */ virtual bool is_expensive() { if (is_expensive_cache < 0) is_expensive_cache= walk(&Item::is_expensive_processor, 0, NULL); return MY_TEST(is_expensive_cache); } String *check_well_formed_result(String *str, bool send_error= 0); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); bool too_big_for_varchar() const { return max_char_length() > CONVERT_IF_BIGGER_TO_BLOB; } void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs) { max_length= char_to_byte_length_safe(max_char_length_arg, cs->mbmaxlen); collation.collation= cs; } void fix_char_length(size_t max_char_length_arg) { max_length= char_to_byte_length_safe(max_char_length_arg, collation.collation->mbmaxlen); } /* Return TRUE if the item points to a column of an outer-joined table. */ virtual bool is_outer_field() const { DBUG_ASSERT(fixed()); return FALSE; } Item* set_expr_cache(THD *thd); virtual Item_equal *get_item_equal() { return NULL; } virtual void set_item_equal(Item_equal *item_eq) {}; virtual Item_equal *find_item_equal(COND_EQUAL *cond_equal) { return NULL; } /** Set the join tab index to the minimal (left-most) JOIN_TAB to which this Item is attached. The number is an index is depth_first_tab() traversal order. */ virtual void set_join_tab_idx(uint8 join_tab_idx_arg) { if (join_tab_idx_arg < join_tab_idx) join_tab_idx= join_tab_idx_arg; } uint get_join_tab_idx() const { return join_tab_idx; } table_map view_used_tables(TABLE_LIST *view) { view->view_used_tables= 0; walk(&Item::view_used_tables_processor, 0, view); return view->view_used_tables; } /** Collect and add to the list cache parameters for this Item. @note Now implemented only for subqueries and in_optimizer, if we need it for general function then this method should be defined for Item_func. */ virtual void get_cache_parameters(List<Item> ¶meters) { }; virtual void mark_as_condition_AND_part(TABLE_LIST *embedding) {}; /* how much position should be reserved for Exists2In transformation */ virtual uint exists2in_reserved_items() { return 0; }; virtual Item *neg(THD *thd); /** Inform the item that it is located under a NOT, which is a top-level item. */ virtual void under_not(Item_func_not * upper __attribute__((unused))) {}; void register_in(THD *thd); bool depends_only_on(table_map view_map) { return get_extraction_flag() & MARKER_FULL_EXTRACTION; } int get_extraction_flag() const { if (basic_const_item()) return MARKER_FULL_EXTRACTION; else return marker & MARKER_EXTRACTION_MASK; } void set_extraction_flag(int16 flags) { if (!basic_const_item()) { marker= marker & ~MARKER_EXTRACTION_MASK; marker|= flags; } } void clear_extraction_flag() { if (!basic_const_item()) marker= marker & ~MARKER_EXTRACTION_MASK; } void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg); bool pushable_cond_checker_for_derived(uchar *arg) { return excl_dep_on_table(*((table_map *)arg)); } bool pushable_cond_checker_for_subquery(uchar *arg) { DBUG_ASSERT(((Item*) arg)->get_IN_subquery()); return excl_dep_on_in_subq_left_part(((Item*)arg)->get_IN_subquery()); } Item *build_pushable_cond(THD *thd, Pushdown_checker checker, uchar *arg); /* Checks if this item depends only on the arg table */ bool pushable_equality_checker_for_derived(uchar *arg) { return (used_tables() == *((table_map *)arg)); } /* Checks if this item consists in the left part of arg IN subquery predicate */ bool pushable_equality_checker_for_subquery(uchar *arg); /** This method is to set relationship between a positional parameter represented by the '?' and an actual argument value passed to the call of PS/SP by the USING clause. The method is overridden in classes Item_param and Item_default_value. */ virtual bool associate_with_target_field(THD *, Item_field *) { DBUG_ASSERT(fixed()); return false; } protected: /* Service function for public method shallow_copy_with_checks(). See comments for shallow_copy_with_checks() above. Override this method in derived classes to create shallow copies of the item */ virtual Item *shallow_copy(THD *thd) const = 0; /* Service function for public method deep_copy_with_checks(). See comments for deep_copy_with_checks() above. Override this method in derived classes to create deep copies (clones) of the item where possible */ virtual Item *deep_copy(THD *thd) const = 0; }; MEM_ROOT *get_thd_memroot(THD *thd); template <class T> inline Item* get_item_copy (THD *thd, const T* item) { Item *copy= new (get_thd_memroot(thd)) T(*item); if (likely(copy)) copy->register_in(thd); return copy; } #ifndef DBUG_OFF /** A helper class to print the data type and the value for an Item in debug builds. */ class DbugStringItemTypeValue: public StringBuffer<128> { public: DbugStringItemTypeValue(THD *thd, const Item *item) { append('('); Name Item_name= item->type_handler()->name(); append(Item_name.ptr(), Item_name.length()); append(')'); const_cast<Item*>(item)->print(this, QT_EXPLAIN); /* Append end \0 to allow usage of c_ptr() */ append('\0'); str_length--; } }; #endif /* DBUG_OFF */ /** Compare two Items for List<Item>::add_unique() */ bool cmp_items(Item *a, Item *b); /** Array of items, e.g. function or aggerate function arguments. */ class Item_args { protected: Item **args, *tmp_arg[2]; uint arg_count; void set_arguments(THD *thd, List<Item> &list); bool walk_args(Item_processor processor, bool walk_subquery, void *arg) { for (uint i= 0; i < arg_count; i++) { if (args[i]->walk(processor, walk_subquery, arg)) return true; } return false; } bool transform_args(THD *thd, Item_transformer transformer, uchar *arg); void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *); bool excl_dep_on_table(table_map tab_map) { for (uint i= 0; i < arg_count; i++) { if (args[i]->const_item()) continue; if (!args[i]->excl_dep_on_table(tab_map)) return false; } return true; } bool excl_dep_on_grouping_fields(st_select_lex *sel); bool eq(const Item_args *other, const Item::Eq_config &config) const { for (uint i= 0; i < arg_count ; i++) { if (!args[i]->eq(other->args[i], config)) return false; } return true; } bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) { for (uint i= 0; i < arg_count; i++) { if (args[i]->const_item()) continue; if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred)) return false; } return true; } public: Item_args(void) :args(NULL), arg_count(0) { } Item_args(Item *a) :args(tmp_arg), arg_count(1) { args[0]= a; } Item_args(Item *a, Item *b) :args(tmp_arg), arg_count(2) { args[0]= a; args[1]= b; } Item_args(THD *thd, Item *a, Item *b, Item *c) { arg_count= 0; if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))) { arg_count= 3; args[0]= a; args[1]= b; args[2]= c; } } Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d) { arg_count= 0; if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))) { arg_count= 4; args[0]= a; args[1]= b; args[2]= c; args[3]= d; } } Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e) { arg_count= 5; if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))) { arg_count= 5; args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e; } } Item_args(THD *thd, List<Item> &list) { set_arguments(thd, list); } Item_args(THD *thd, const Item_args *other); bool alloc_arguments(THD *thd, uint count); void add_argument(Item *item) { args[arg_count++]= item; } /** Extract row elements from the given position. For example, for this input: (1,2),(3,4),(5,6) pos=0 will extract (1,3,5) pos=1 will extract (2,4,6) @param thd - current thread, to allocate memory on its mem_root @param rows - an array of compatible ROW-type items @param pos - the element position to extract */ bool alloc_and_extract_row_elements(THD *thd, const Item_args *rows, uint pos) { DBUG_ASSERT(rows->argument_count() > 0); DBUG_ASSERT(rows->arguments()[0]->cols() > pos); if (alloc_arguments(thd, rows->argument_count())) return true; for (uint i= 0; i < rows->argument_count(); i++) { DBUG_ASSERT(rows->arguments()[0]->cols() == rows->arguments()[i]->cols()); Item *arg= rows->arguments()[i]->element_index(pos); add_argument(arg); } DBUG_ASSERT(argument_count() == rows->argument_count()); return false; } inline Item **arguments() const { return args; } inline uint argument_count() const { return arg_count; } inline void remove_arguments() { arg_count=0; } Sql_mode_dependency value_depends_on_sql_mode_bit_or() const; }; /* Class to be used to enumerate all field references in an item tree. This includes references to outside but not fields of the tables within a subquery. Suggested usage: class My_enumerator : public Field_enumerator { virtual void visit_field() { ... your actions ...} } My_enumerator enumerator; item->walk(Item::enumerate_field_refs_processor, ...,&enumerator); This is similar to Visitor pattern. */ class Field_enumerator { public: virtual void visit_field(Item_field *field)= 0; virtual ~Field_enumerator() = default;; /* purecov: inspected */ Field_enumerator() = default; /* Remove gcc warning */ }; class Item_string; class Item_fixed_hybrid: public Item { public: Item_fixed_hybrid(THD *thd): Item(thd) { base_flags&= ~item_base_t::FIXED; } Item_fixed_hybrid(THD *thd, Item_fixed_hybrid *item) :Item(thd, item) { base_flags|= (item->base_flags & item_base_t::FIXED); } bool fix_fields(THD *thd, Item **ref) override { DBUG_ASSERT(!fixed()); base_flags|= item_base_t::FIXED; return false; } void cleanup() override { Item::cleanup(); base_flags&= ~item_base_t::FIXED; } void quick_fix_field() override { base_flags|= item_base_t::FIXED; } void unfix_fields() override { base_flags&= ~item_base_t::FIXED; } }; /** A common class for Item_basic_constant and Item_param */ class Item_basic_value :public Item, public Item_const { protected: // Value metadata, e.g. to make string processing easier class Metadata: private MY_STRING_METADATA { public: Metadata(const String *str) { my_string_metadata_get(this, str->charset(), str->ptr(), str->length()); } Metadata(const String *str, my_repertoire_t repertoire_arg) { MY_STRING_METADATA::repertoire= repertoire_arg; MY_STRING_METADATA::char_length= str->numchars(); } my_repertoire_t repertoire() const { return MY_STRING_METADATA::repertoire; } size_t char_length() const { return MY_STRING_METADATA::char_length; } }; void fix_charset_and_length(CHARSET_INFO *cs, Derivation dv, Metadata metadata) { /* We have to have a different max_length than 'length' here to ensure that we get the right length if we do use the item to create a new table. In this case max_length must be the maximum number of chars for a string of this type because we in Create_field:: divide the max_length with mbmaxlen). */ collation.set(cs, dv, metadata.repertoire()); fix_char_length(metadata.char_length()); decimals= NOT_FIXED_DEC; } void fix_charset_and_length_from_str_value(const String &str, Derivation dv) { fix_charset_and_length(str.charset(), dv, Metadata(&str)); } Item_basic_value(THD *thd): Item(thd) {} Item_basic_value(): Item() {} public: Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { /* create_tmp_field_ex() for this type of Items is called for: - CREATE TABLE ... SELECT - In ORDER BY: SELECT max(a) FROM t1 GROUP BY a ORDER BY 'const'; - In CURSORS: DECLARE c CURSOR FOR SELECT 'test'; OPEN c; */ return tmp_table_field_from_field_type_maybe_null(root, table, src, param, type() == Item::NULL_ITEM); } bool eq(const Item *item, const Eq_config &config) const override; const Type_all_attributes *get_type_all_attributes_from_const() const override { return this; } }; class Item_basic_constant :public Item_basic_value { public: Item_basic_constant(THD *thd): Item_basic_value(thd) {}; Item_basic_constant(): Item_basic_value() {}; bool check_vcol_func_processor(void *) override { return false; } const Item_const *get_item_const() const override { return this; } virtual Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *) { DBUG_ASSERT(0); return this; } bool val_bool() override = 0; }; /***************************************************************************** The class is a base class for representation of stored routine variables in the Item-hierarchy. There are the following kinds of SP-vars: - local variables (Item_splocal); - CASE expression (Item_case_expr); *****************************************************************************/ class Item_sp_variable :public Item_fixed_hybrid { protected: /* THD, which is stored in fix_fields() and is used in this_item() to avoid current_thd use. */ THD *m_thd; bool fix_fields_from_item(THD *thd, Item **, const Item *); public: LEX_CSTRING m_name; public: #ifdef DBUG_ASSERT_EXISTS /* Routine to which this Item_splocal belongs. Used for checking if correct runtime context is used for variable handling. */ const sp_head *m_sp; #endif public: Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name); public: bool fix_fields(THD *thd, Item **) override= 0; double val_real() override; longlong val_int() override; String *val_str(String *sp) override; my_decimal *val_decimal(my_decimal *decimal_value) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override; bool is_null() override; public: void make_send_field(THD *thd, Send_field *field) override; bool const_item() const override { return true; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return create_tmp_field_ex_simple(root, table, src, param); } inline int save_in_field(Field *field, bool no_conversions) override; inline bool send(Protocol *protocol, st_value *buffer) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(m_name.str, arg, VCOL_IMPOSSIBLE); } }; /***************************************************************************** Item_sp_variable inline implementation. *****************************************************************************/ inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions) { return this_item()->save_in_field(field, no_conversions); } inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer) { return this_item()->send(protocol, buffer); } /***************************************************************************** A reference to local SP variable (incl. reference to SP parameter), used in runtime. *****************************************************************************/ class Item_splocal :public Item_sp_variable, private Settable_routine_parameter, public Rewritable_query_parameter, public Type_handler_hybrid_field_type { protected: const Sp_rcontext_handler *m_rcontext_handler; uint m_var_idx; Type m_type; bool append_value_for_log(THD *thd, String *str); sp_rcontext *get_rcontext(sp_rcontext *local_ctx) const; Item_field *get_variable(sp_rcontext *ctx) const; public: Item_splocal(THD *thd, const Sp_rcontext_handler *rh, const LEX_CSTRING *sp_var_name, uint sp_var_idx, const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0); bool fix_fields(THD *, Item **) override; Item *this_item() override; const Item *this_item() const override; Item **this_item_addr(THD *thd, Item **) override; void print(String *str, enum_query_type query_type) override; public: inline const LEX_CSTRING *my_name() const; inline uint get_var_idx() const; Type type() const override { return m_type; } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } uint cols() const override { return this_item()->cols(); } Item* element_index(uint i) override { return this_item()->element_index(i); } Item** addr(uint i) override { return this_item()->addr(i); } bool check_cols(uint c) override; private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; public: Item_splocal *get_item_splocal() override { return this; } Rewritable_query_parameter *get_rewritable_query_parameter() override { return this; } Settable_routine_parameter *get_settable_routine_parameter() override { return this; } bool append_for_log(THD *thd, String *str) override; /* Override the inherited create_field_for_create_select(), because we want to preserve the exact data type for: DECLARE a1 INT; DECLARE a2 TYPE OF t1.a2; CREATE TABLE t1 AS SELECT a1, a2; The inherited implementation would create a column based on result_type(), which is less exact. */ Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return create_table_field_from_handler(root, table); } bool is_valid_limit_clause_variable_with_error() const { /* In case if the variable has an anchored data type, e.g.: DECLARE a TYPE OF t1.a; type_handler() is set to &type_handler_null and this function detects such variable as not valid in LIMIT. */ if (type_handler()->is_limit_clause_valid_type()) return true; my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)); return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_splocal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** An Item_splocal variant whose data type becomes known only at sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE". */ class Item_splocal_with_delayed_data_type: public Item_splocal { public: Item_splocal_with_delayed_data_type(THD *thd, const Sp_rcontext_handler *rh, const LEX_CSTRING *sp_var_name, uint sp_var_idx, uint pos_in_q, uint len_in_q) :Item_splocal(thd, rh, sp_var_name, sp_var_idx, &type_handler_null, pos_in_q, len_in_q) { } protected: Item *shallow_copy(THD *) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; /** SP variables that are fields of a ROW. DELCARE r ROW(a INT,b INT); SELECT r.a; -- This is handled by Item_splocal_row_field */ class Item_splocal_row_field :public Item_splocal { protected: LEX_CSTRING m_field_name; uint m_field_idx; bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; public: Item_splocal_row_field(THD *thd, const Sp_rcontext_handler *rh, const LEX_CSTRING *sp_var_name, const LEX_CSTRING *sp_field_name, uint sp_var_idx, uint sp_field_idx, const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0) :Item_splocal(thd, rh, sp_var_name, sp_var_idx, handler, pos_in_q, len_in_q), m_field_name(*sp_field_name), m_field_idx(sp_field_idx) { } bool fix_fields(THD *thd, Item **) override; Item *this_item() override; const Item *this_item() const override; Item **this_item_addr(THD *thd, Item **) override; bool append_for_log(THD *thd, String *str) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; class Item_splocal_row_field_by_name :public Item_splocal_row_field { bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; public: Item_splocal_row_field_by_name(THD *thd, const Sp_rcontext_handler *rh, const LEX_CSTRING *sp_var_name, const LEX_CSTRING *sp_field_name, uint sp_var_idx, const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0) :Item_splocal_row_field(thd, rh, sp_var_name, sp_field_name, sp_var_idx, 0 /* field index will be set later */, handler, pos_in_q, len_in_q) { } bool fix_fields(THD *thd, Item **it) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; /***************************************************************************** Item_splocal inline implementation. *****************************************************************************/ inline const LEX_CSTRING *Item_splocal::my_name() const { return &m_name; } inline uint Item_splocal::get_var_idx() const { return m_var_idx; } /***************************************************************************** A reference to case expression in SP, used in runtime. *****************************************************************************/ class Item_case_expr :public Item_sp_variable { public: Item_case_expr(THD *thd, uint case_expr_id); public: bool fix_fields(THD *thd, Item **) override; Item *this_item() override; const Item *this_item() const override; Item **this_item_addr(THD *thd, Item **) override; Type type() const override; const Type_handler *type_handler() const override { return this_item()->type_handler(); } public: /* NOTE: print() is intended to be used from views and for debug. Item_case_expr can not occur in views, so here it is only for debug purposes. */ void print(String *str, enum_query_type query_type) override; private: uint m_case_expr_id; protected: Item *shallow_copy(THD *) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; /***************************************************************************** Item_case_expr inline implementation. *****************************************************************************/ inline enum Item::Type Item_case_expr::type() const { return this_item()->type(); } /* NAME_CONST(given_name, const_value). This 'function' has all properties of the supplied const_value (which is assumed to be a literal constant), and the name given_name. This is used to replace references to SP variables when we write PROCEDURE statements into the binary log. TODO Together with Item_splocal and Item::this_item() we can actually extract common a base of this class and Item_splocal. Maybe it is possible to extract a common base with class Item_ref, too. */ class Item_name_const : public Item_fixed_hybrid { Item *value_item; Item *name_item; public: Item_name_const(THD *thd, Item *name_arg, Item *val); bool fix_fields(THD *, Item **) override; Type type() const override; double val_real() override; longlong val_int() override; String *val_str(String *sp) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override; bool is_null() override; void print(String *str, enum_query_type query_type) override; const Type_handler *type_handler() const override { return value_item->type_handler(); } bool const_item() const override { return true; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { /* We can get to here when using a CURSOR for a query with NAME_CONST(): DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1; OPEN c; */ return tmp_table_field_from_field_type_maybe_null(root, table, src, param, type() == Item::NULL_ITEM); } int save_in_field(Field *field, bool no_conversions) override { return value_item->save_in_field(field, no_conversions); } bool send(Protocol *protocol, st_value *buffer) override { return value_item->send(protocol, buffer); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("name_const()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_name_const>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_literal: public Item_basic_constant { public: Item_literal(THD *thd): Item_basic_constant(thd) { } Item_literal(): Item_basic_constant() {} Type type() const override { return CONST_ITEM; } bool check_partition_func_processor(void *int_arg) override { return false;} bool const_item() const override { return true; } bool basic_const_item() const override { return true; } bool is_expensive() override { return false; } bool cleanup_is_expensive_cache_processor(void *arg) override { return 0; } }; class Item_num: public Item_literal { public: Item_num(THD *thd): Item_literal(thd) { collation= DTCollation_numeric(); } Item_num(): Item_literal() { collation= DTCollation_numeric(); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; #define NO_CACHED_FIELD_INDEX ((field_index_t) ~0U) class st_select_lex; class Item_result_field :public Item_fixed_hybrid /* Item with result field */ { protected: Field *create_tmp_field_ex_from_handler(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param, const Type_handler *h); public: Field *result_field; /* Save result here */ Item_result_field(THD *thd): Item_fixed_hybrid(thd), result_field(0) {} // Constructor used for Item_sum/Item_cond_and/or (see Item comment) Item_result_field(THD *thd, Item_result_field *item): Item_fixed_hybrid(thd, item), result_field(item->result_field) {} ~Item_result_field() = default; Field *get_tmp_table_field() override { return result_field; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { DBUG_ASSERT(fixed()); const Type_handler *h= type_handler()->type_handler_for_tmp_table(this); return create_tmp_field_ex_from_handler(root, table, src, param, h); } void get_tmp_field_src(Tmp_field_src *src, const Tmp_field_param *param); /* This implementation of used_tables() used by Item_avg_field and Item_variance_field which work when only temporary table left, so theu return table map of the temporary table. */ table_map used_tables() const override { return 1; } bool is_result_field() override { return true; } void save_in_result_field(bool no_conversions) override { save_in_field(result_field, no_conversions); } void cleanup() override; bool check_vcol_func_processor(void *) override { return false; } }; class Item_ident :public Item_result_field { protected: /* We have to store initial values of db_name, table_name and field_name to be able to restore them during cleanup() because they can be updated during fix_fields() to values from Field object and life-time of those is shorter than life-time of Item_field. */ Lex_table_name orig_db_name; Lex_table_name orig_table_name; Lex_ident orig_field_name; void undeclared_spvar_error() const; public: Name_resolution_context *context; Lex_table_name db_name; Lex_table_name table_name; Lex_ident field_name; /* Cached pointer to table which contains this field, used for the same reason by prep. stmt. too in case then we have not-fully qualified field. 0 - means no cached value. */ TABLE_LIST *cached_table; st_select_lex *depended_from; /* Cached value of index for this field in table->field array, used by prepared stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX if index value is not known. */ field_index_t cached_field_index; /* Some Items resolved in another select should not be marked as dependency of the subquery where they are. During normal name resolution, we check this. Stored procedures and prepared statements first try to resolve an ident item using a cached table reference and field position from the previous query execution (cached_table/cached_field_index). If the tables were not changed, the ident matches the table/field, and we have faster resolution of the ident without looking through all tables and fields in the query. But in this case, we can not check all conditions about this ident item dependency, so we should cache the condition in this variable. */ bool can_be_depended; /* NOTE: came from TABLE::alias_name_used and this is only a hint! See comment for TABLE::alias_name_used. */ bool alias_name_used; /* true if item was resolved against alias */ Item_ident(THD *thd, Name_resolution_context *context_arg, const LEX_CSTRING &db_name_arg, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg); Item_ident(THD *thd, Item_ident *item); Item_ident(THD *thd, TABLE_LIST *view_arg, const LEX_CSTRING &field_name_arg); LEX_CSTRING full_name_cstring() const override; void cleanup() override; st_select_lex *get_depended_from() const; bool remove_dependence_processor(void * arg) override; void print(String *str, enum_query_type query_type) override; bool change_context_processor(void *cntx) override { context= (Name_resolution_context *)cntx; return FALSE; } /** Collect outer references */ bool collect_outer_ref_processor(void *arg) override; friend bool insert_fields(THD *thd, Name_resolution_context *context, const LEX_CSTRING &db_name, const LEX_CSTRING &table_name, List_iterator<Item> *it, bool any_privileges, bool returning_field); }; class Item_field :public Item_ident, public Load_data_outvar { protected: void set_field(Field *field); public: Field *field; Item_equal *item_equal; /* if any_privileges set to TRUE then here real effective privileges will be stored */ privilege_t have_privileges; /* field need any privileges (for VIEW creation) */ bool any_privileges; private: /* Indicates whether this Item_field refers to a regular or some kind of temporary table. This is needed for print() to work: it may be called even after the table referred by the Item_field has been dropped. See ExplainDataStructureLifetime in sql_explain.h for details. */ enum { NO_TEMP_TABLE= 0, REFERS_TO_DERIVED_TMP= 1, REFERS_TO_OTHER_TMP=2 } refers_to_temp_table = NO_TEMP_TABLE; public: Item_field(THD *thd, Name_resolution_context *context_arg, const LEX_CSTRING &db_arg, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg); Item_field(THD *thd, Name_resolution_context *context_arg, const LEX_CSTRING &field_name_arg) :Item_field(thd, context_arg, null_clex_str, null_clex_str, field_name_arg) { } Item_field(THD *thd, Name_resolution_context *context_arg) :Item_field(thd, context_arg, null_clex_str, null_clex_str, null_clex_str) { } /* Constructor needed to process subselect with temporary tables (see Item) */ Item_field(THD *thd, Item_field *item); /* Constructor used inside setup_wild(), ensures that field, table, and database names will live as long as Item_field (this is important in prepared statements). */ Item_field(THD *thd, Name_resolution_context *context_arg, Field *field); /* If this constructor is used, fix_fields() won't work, because db_name, table_name and column_name are unknown. It's necessary to call reset_field() before fix_fields() for all fields created this way. */ Item_field(THD *thd, Field *field); Type type() const override { return FIELD_ITEM; } bool eq(const Item *item, const Eq_config &config) const override; double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; String *val_str(String*) override; void save_result(Field *to) override; double val_result() override; longlong val_int_result() override; bool val_native(THD *thd, Native *to) override; bool val_native_result(THD *thd, Native *to) override; String *str_result(String* tmp) override; my_decimal *val_decimal_result(my_decimal *) override; bool val_bool_result() override; bool is_null_result() override; bool send(Protocol *protocol, st_value *buffer) override; Load_data_outvar *get_load_data_outvar() override { return this; } bool load_data_set_null(THD *thd, const Load_data_param *param) override { return field->load_data_set_null(thd); } bool load_data_set_value(THD *thd, const char *pos, uint length, const Load_data_param *param) override { field->load_data_set_value(pos, length, param->charset()); return false; } bool load_data_set_no_data(THD *thd, const Load_data_param *param) override; void load_data_print_for_log_event(THD *thd, String *to) const override; bool load_data_add_outvar(THD *thd, Load_data_param *param) const override { return param->add_outvar_field(thd, field); } uint load_data_fixed_length() const override { return field->field_length; } void reset_field(Field *f); bool fix_fields(THD *, Item **) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; void make_send_field(THD *thd, Send_field *tmp_field) override; int save_in_field(Field *field,bool no_conversions) override; void save_org_in_field(Field *field, fast_field_copier optimizer_data) override; fast_field_copier setup_fast_field_copier(Field *field) override; table_map used_tables() const override; table_map all_used_tables() const override; const Type_handler *type_handler() const override { const Type_handler *handler= field->type_handler(); return handler->type_handler_for_item_field(); } const Type_handler *real_type_handler() const override { if (field->is_created_from_null_item) return &type_handler_null; return field->type_handler(); } uint32 character_octet_length() const override { return field->character_octet_length(); } Field *create_tmp_field_from_item_field(MEM_ROOT *root, TABLE *new_table, Item_ref *orig_item, const Tmp_field_param *param); Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; const TYPELIB *get_typelib() const override { return field->get_typelib(); } enum_monotonicity_info get_monotonicity_info() const override { return MONOTONIC_STRICT_INCREASING; } Sql_mode_dependency value_depends_on_sql_mode() const override { return Sql_mode_dependency(0, field->value_depends_on_sql_mode()); } bool hash_not_null(Hasher *hasher) override { if (field->is_null()) return true; field->hash_not_null(hasher); return false; } longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool get_date_result(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate) override; longlong val_datetime_packed(THD *thd) override; longlong val_time_packed(THD *thd) override; bool is_null() override { return field->is_null(); } void update_null_value() override; void update_table_bitmaps() { if (field && field->table) { TABLE *tab= field->table; tab->covering_keys.intersect(field->part_of_key); if (tab->read_set) tab->mark_column_with_deps(field); } } void update_used_tables() override { update_table_bitmaps(); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override { /* normilize_cond() replaced all conditions of type WHERE/HAVING field to: WHERE/HAVING field<>0 By the time of a build_equal_items() call, all such conditions should already be replaced. No Item_field are possible. Note, some Item_field derivants are still possible. Item_insert_value: SELECT * FROM t1 WHERE VALUES(a); Item_default_value: SELECT * FROM t1 WHERE DEFAULT(a); */ DBUG_ASSERT(type() != FIELD_ITEM); return Item_ident::build_equal_items(thd, inherited, link_item_fields, cond_equal_ref); } bool is_result_field() override { return false; } void save_in_result_field(bool no_conversions) override; Item *get_tmp_table_item(THD *thd) override; bool find_not_null_fields(table_map allowed) override; bool collect_item_field_processor(void * arg) override; bool unknown_splocal_processor(void *arg) override; bool add_field_to_set_processor(void * arg) override; bool find_item_in_field_list_processor(void *arg) override; bool register_field_in_read_map(void *arg) override; bool register_field_in_write_map(void *arg) override; bool register_field_in_bitmap(void *arg) override; bool check_partition_func_processor(void *) override {return false;} bool post_fix_fields_part_expr_processor(void *bool_arg) override; bool check_valid_arguments_processor(void *bool_arg) override; bool check_field_expression_processor(void *arg) override; bool enumerate_field_refs_processor(void *arg) override; bool update_table_bitmaps_processor(void *arg) override; bool switch_to_nullable_fields_processor(void *arg) override; bool update_vcol_processor(void *arg) override; bool rename_fields_processor(void *arg) override; bool check_vcol_func_processor(void *arg) override; bool set_fields_as_dependent_processor(void *arg) override { if (!(used_tables() & OUTER_REF_TABLE_BIT)) { depended_from= (st_select_lex *) arg; item_equal= NULL; } return 0; } void cleanup() override; Item_equal *get_item_equal() override { return item_equal; } void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; } Item_equal *find_item_equal(COND_EQUAL *cond_equal) override; bool contains(Field *field); Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override; Item *replace_equal_field(THD *thd, uchar *arg) override; uint32 max_display_length() const override { return field->max_display_length(); } Item_field *field_for_view_update() override { return this; } int fix_outer_field(THD *thd, Field **field, Item **reference); Item *update_value_transformer(THD *thd, uchar *select_arg) override; Item *derived_field_transformer_for_having(THD *thd, uchar *arg) override; Item *derived_field_transformer_for_where(THD *thd, uchar *arg) override; Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) override; Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) override; Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) override; void print(String *str, enum_query_type query_type) override; bool excl_dep_on_table(table_map tab_map) override; bool excl_dep_on_grouping_fields(st_select_lex *sel) override; bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override; bool cleanup_excluding_fields_processor(void *arg) override { return field ? 0 : cleanup_processor(arg); } bool cleanup_excluding_const_fields_processor(void *arg) override { return field && const_item() ? 0 : cleanup_processor(arg); } bool is_outer_field() const override { DBUG_ASSERT(fixed()); return field->table->pos_in_table_list->outer_join; } bool check_index_dependence(void *arg) override; void set_refers_to_temp_table(); friend class Item_default_value; friend class Item_insert_value; friend class st_select_lex_unit; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_field>(thd, this); } Item* deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** Item_field for the ROW data type */ class Item_field_row: public Item_field, public Item_args { public: Item_field_row(THD *thd, Field *field) :Item_field(thd, field), Item_args() { } const Type_handler *type_handler() const override { return &type_handler_row; } uint cols() const override { return arg_count; } Item* element_index(uint i) override { return arg_count ? args[i] : this; } Item** addr(uint i) override { return arg_count ? args + i : NULL; } bool check_cols(uint c) override { if (cols() != c) { my_error(ER_OPERAND_COLUMNS, MYF(0), c); return true; } return false; } bool row_create_items(THD *thd, List<Spvar_definition> *list); protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_field_row>(thd, this); } }; class Item_null :public Item_basic_constant { public: Item_null(THD *thd, const char *name_par=0, CHARSET_INFO *cs= &my_charset_bin): Item_basic_constant(thd) { set_maybe_null(); null_value= TRUE; max_length= 0; name.str= name_par ? name_par : "NULL"; name.length= strlen(name.str); collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } Type type() const override { return NULL_ITEM; } bool vcol_assignment_allowed_value() const override { return true; } bool val_bool() override; double val_real() override; longlong val_int() override; String *val_str(String *str) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; longlong val_datetime_packed(THD *) override; longlong val_time_packed(THD *) override; int save_in_field(Field *field, bool no_conversions) override; int save_safe_in_field(Field *field) override; bool send(Protocol *protocol, st_value *buffer) override; const Type_handler *type_handler() const override { return &type_handler_null; } bool basic_const_item() const override { return true; } Item *clone_constant(THD *thd) const override; bool const_is_null() const override { return true; } bool is_null() override { return true; } void print(String *str, enum_query_type) override { str->append(NULL_clex_str); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; bool check_partition_func_processor(void *) override { return false; } Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_null>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_null_result :public Item_null { public: Field *result_field; Item_null_result(THD *thd): Item_null(thd), result_field(0) {} bool is_result_field() override { return result_field != 0; } const Type_handler *type_handler() const override { if (result_field) return result_field->type_handler(); return &type_handler_null; } Field *create_tmp_field_ex(MEM_ROOT *, TABLE *, Tmp_field_src *, const Tmp_field_param *) override { DBUG_ASSERT(0); return NULL; } void save_in_result_field(bool no_conversions) override { save_in_field(result_field, no_conversions); } bool check_partition_func_processor(void *int_arg) override { return true; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(full_name(), arg, VCOL_IMPOSSIBLE); } }; /* Item represents one placeholder ('?') of prepared statement Notes: Item_param::field_type() is used when this item is in a temporary table. This is NOT placeholder metadata sent to client, as this value is assigned after sending metadata (in setup_one_conversion_function). For example in case of 'SELECT ?' you'll get MYSQL_TYPE_STRING both in result set and placeholders metadata, no matter what type you will supply for this placeholder in mysql_stmt_execute. Item_param has two Type_handler pointers, which can point to different handlers: 1. In the Type_handler_hybrid_field_type member It's initialized in: - Item_param::setup_conversion(), for client-server PS protocol, according to the bind type. - Item_param::set_from_item(), for EXECUTE and EXECUTE IMMEDIATE, according to the actual parameter data type. 2. In the "value" member. It's initialized in: - Item_param::set_param_func(), for client-server PS protocol. - Item_param::set_from_item(), for EXECUTE and EXECUTE IMMEDIATE. */ class Item_param :public Item_basic_value, private Settable_routine_parameter, public Rewritable_query_parameter, private Type_handler_hybrid_field_type { /* NO_VALUE is a special value meaning that the parameter has not been assigned yet. Item_param::state is assigned to NO_VALUE in constructor and is used at prepare time. 1. At prepare time Item_param::fix_fields() sets "fixed" to true, but as Item_param::state is still NO_VALUE, Item_param::basic_const_item() returns false. This prevents various optimizations to happen at prepare time fix_fields(). For example, in this query: PREPARE stmt FROM 'SELECT FORMAT(10000,2,?)'; Item_param::basic_const_item() is tested from Item_func_format::fix_length_and_dec(). 2. At execute time: When Item_param gets a value (or a pseudo-value like DEFAULT_VALUE or IGNORE_VALUE): - Item_param::state changes from NO_VALUE to something else - Item_param::fixed is changed to true All Item_param::set_xxx() make sure to do so. In the state with an assigned value: - Item_param::basic_const_item() returns true - Item::type() returns NULL_ITEM or CONST_ITEM, depending on the value assigned. So in this state Item_param behaves in many cases like a literal. When Item_param::cleanup() is called: - Item_param::state does not change - Item_param::fixed changes to false Note, this puts Item_param into an inconsistent state: - Item_param::basic_const_item() still returns "true" - Item_param::type() still pretends to be a basic constant Item Both are not expected in combination with fixed==false. However, these methods are not really called in this state, see asserts in Item_param::basic_const_item() and Item_param::type(). When Item_param::reset() is called: - Item_param::state changes to NO_VALUE - Item_param::fixed changes to false */ enum enum_item_param_state { NO_VALUE, NULL_VALUE, SHORT_DATA_VALUE, LONG_DATA_VALUE, DEFAULT_VALUE, IGNORE_VALUE } state; void fix_temporal(uint32 max_length_arg, uint decimals_arg); struct CONVERSION_INFO { /* Character sets conversion info for string values. Character sets of client and connection defined at bind time are used for all conversions, even if one of them is later changed (i.e. between subsequent calls to mysql_stmt_execute). */ CHARSET_INFO *character_set_client; CHARSET_INFO *character_set_of_placeholder; /* This points at character set of connection if conversion to it is required (i. e. if placeholder typecode is not BLOB). Otherwise it's equal to character_set_client (to simplify check in convert_str_value()). */ CHARSET_INFO *final_character_set_of_str_value; private: bool needs_conversion() const { return final_character_set_of_str_value != character_set_of_placeholder; } bool convert(THD *thd, String *str); public: void set(THD *thd, CHARSET_INFO *cs); bool convert_if_needed(THD *thd, String *str) { /* Check is so simple because all charsets were set up properly in setup_one_conversion_function, where typecode of placeholder was also taken into account: the variables are different here only if conversion is really necessary. */ if (needs_conversion()) return convert(thd, str); str->set_charset(final_character_set_of_str_value); return false; } }; bool m_empty_string_is_null; class PValue_simple { public: union { longlong integer; double real; CONVERSION_INFO cs_info; MYSQL_TIME time; }; void swap(PValue_simple &other) { swap_variables(PValue_simple, *this, other); } }; class PValue: public Type_handler_hybrid_field_type, public PValue_simple, public Value_source { public: PValue(): Type_handler_hybrid_field_type(&type_handler_null) {} my_decimal m_decimal; String m_string; /* A buffer for string and long data values. Historically all allocated values returned from val_str() were treated as eligible to modification. I. e. in some cases Item_func_concat can append it's second argument to return value of the first one. Because of that we can't return the original buffer holding string data from val_str(), and have to have one buffer for data and another just pointing to the data. This is the latter one and it's returned from val_str(). Can not be declared inside the union as it's not a POD type. */ String m_string_ptr; void swap(PValue &other) { Type_handler_hybrid_field_type::swap(other); PValue_simple::swap(other); m_decimal.swap(other.m_decimal); m_string.swap(other.m_string); m_string_ptr.swap(other.m_string_ptr); } double val_real(const Type_std_attributes *attr) const; longlong val_int(const Type_std_attributes *attr) const; my_decimal *val_decimal(my_decimal *dec, const Type_std_attributes *attr); String *val_str(String *str, const Type_std_attributes *attr); }; PValue value; const String *value_query_val_str(THD *thd, String* str) const; Item *value_clone_item(THD *thd) const; bool is_evaluable_expression() const override; bool check_assignability_to(const Field *field, bool ignore) const override; bool can_return_value() const; public: /* Used for bulk protocol only. */ enum enum_indicator_type indicator; const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } bool vcol_assignment_allowed_value() const override { switch (state) { case NULL_VALUE: case DEFAULT_VALUE: case IGNORE_VALUE: return true; case NO_VALUE: case SHORT_DATA_VALUE: case LONG_DATA_VALUE: break; } return false; } Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); void cleanup() override { m_default_field= NULL; Item::cleanup(); } Type type() const override { // Don't pretend to be a constant unless value for this item is set. switch (state) { case NO_VALUE: return PARAM_ITEM; case NULL_VALUE: return NULL_ITEM; case SHORT_DATA_VALUE: return CONST_ITEM; case LONG_DATA_VALUE: return CONST_ITEM; case DEFAULT_VALUE: return PARAM_ITEM; case IGNORE_VALUE: return PARAM_ITEM; } DBUG_ASSERT(0); return PARAM_ITEM; } bool is_order_clause_position() const override { return state == SHORT_DATA_VALUE && type_handler()->is_order_clause_position_type(); } const Item_const *get_item_const() const override { switch (state) { case SHORT_DATA_VALUE: case LONG_DATA_VALUE: case NULL_VALUE: return this; case IGNORE_VALUE: case DEFAULT_VALUE: case NO_VALUE: break; } return NULL; } bool const_is_null() const override { return state == NULL_VALUE; } bool can_return_const_value(Item_result type) const { return can_return_value() && value.type_handler()->cmp_type() == type && type_handler()->cmp_type() == type; } const longlong *const_ptr_longlong() const override { return can_return_const_value(INT_RESULT) ? &value.integer : NULL; } const double *const_ptr_double() const override { return can_return_const_value(REAL_RESULT) ? &value.real : NULL; } const my_decimal *const_ptr_my_decimal() const override { return can_return_const_value(DECIMAL_RESULT) ? &value.m_decimal : NULL; } const MYSQL_TIME *const_ptr_mysql_time() const override { return can_return_const_value(TIME_RESULT) ? &value.time : NULL; } const String *const_ptr_string() const override { return can_return_const_value(STRING_RESULT) ? &value.m_string : NULL; } double val_real() override { return can_return_value() ? value.val_real(this) : 0e0; } longlong val_int() override { return can_return_value() ? value.val_int(this) : 0; } my_decimal *val_decimal(my_decimal *dec) override { return can_return_value() ? value.val_decimal(dec, this) : NULL; } String *val_str(String *str) override { return can_return_value() ? value.val_str(str, this) : NULL; } bool get_date(THD *thd, MYSQL_TIME *tm, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override { return Item_param::type_handler()->Item_param_val_native(thd, this, to); } int save_in_field(Field *field, bool no_conversions) override; void set_default(bool set_type_handler_null); void set_ignore(bool set_type_handler_null); void set_null(const DTCollation &c); void set_null_string(const DTCollation &c) { /* We need to distinguish explicit NULL (marked by DERIVATION_IGNORABLE) from other item types: - These statements should give an error, because the character set of the bound parameter is not known: EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING NULL; EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING CONCAT(NULL); - These statements should return a good result, because the character set of the bound parameter is known: EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING CONVERT(NULL USING utf8mb4); EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING CAST(NULL AS CHAR CHARACTER SET utf8mb4); */ set_null(DTCollation(c.collation, MY_MAX(c.derivation, DERIVATION_COERCIBLE))); } void set_null() { set_null(DTCollation(&my_charset_bin, DERIVATION_IGNORABLE)); } void set_int(longlong i, uint32 max_length_arg); void set_double(double i); void set_decimal(const char *str, ulong length); void set_decimal(const my_decimal *dv, bool unsigned_arg); bool set_str(const char *str, ulong length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); bool set_longdata(const char *str, ulong length); void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg); void set_time(const MYSQL_TIME *tm, uint32 max_length_arg, uint decimals_arg); bool set_from_item(THD *thd, Item *item); void reset(); void set_param_tiny(uchar **pos, ulong len); void set_param_short(uchar **pos, ulong len); void set_param_int32(uchar **pos, ulong len); void set_param_int64(uchar **pos, ulong len); void set_param_float(uchar **pos, ulong len); void set_param_double(uchar **pos, ulong len); void set_param_decimal(uchar **pos, ulong len); void set_param_time(uchar **pos, ulong len); void set_param_datetime(uchar **pos, ulong len); void set_param_date(uchar **pos, ulong len); void set_param_str(uchar **pos, ulong len); void setup_conversion(THD *thd, uchar param_type); void setup_conversion_blob(THD *thd); void setup_conversion_string(THD *thd, CHARSET_INFO *fromcs); /* Assign placeholder value from bind data. Note, that 'len' has different semantics in embedded library (as we don't need to check that packet is not broken there). See sql_prepare.cc for details. */ void set_param_func(uchar **pos, ulong len) { /* To avoid Item_param::set_xxx() asserting on data type mismatch, we set the value type handler here: - It can not be initialized yet after Item_param::setup_conversion(). - Also, for LIMIT clause parameters, the value type handler might have changed from the real type handler to type_handler_longlong. So here we'll restore it. */ const Type_handler *h= Item_param::type_handler(); value.set_handler(h); h->Item_param_set_param_func(this, pos, len); } bool set_value(THD *thd, const Type_all_attributes *attr, const st_value *val, const Type_handler *h) { value.set_handler(h); // See comments in set_param_func() return h->Item_param_set_from_value(thd, this, attr, val); } bool set_limit_clause_param(longlong nr) { value.set_handler(&type_handler_slonglong); set_int(nr, MY_INT64_NUM_DECIMAL_DIGITS); return !unsigned_flag && value.integer < 0; } const String *query_val_str(THD *thd, String *str) const; bool convert_str_value(THD *thd); /* If value for parameter was not set we treat it as non-const so no one will use parameters value in fix_fields still parameter is constant during execution. */ bool const_item() const override { return state != NO_VALUE; } table_map used_tables() const override { return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; } void print(String *str, enum_query_type query_type) override; bool is_null() override { DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; } bool basic_const_item() const override; bool has_no_value() const { return state == NO_VALUE; } bool has_long_data_value() const { return state == LONG_DATA_VALUE; } bool has_int_value() const { return state == SHORT_DATA_VALUE && value.type_handler()->cmp_type() == INT_RESULT; } bool is_stored_routine_parameter() const override { return true; } /* This method is used to make a copy of a basic constant item when propagating constants in the optimizer. The reason to create a new item and not use the existing one is not precisely known (2005/04/16). Probably we are trying to preserve tree structure of items, in other words, avoid pointing at one item from two different nodes of the tree. Return a new basic constant item if parameter value is a basic constant, assert otherwise. This method is called only if basic_const_item returned TRUE. */ Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; Item *clone_constant(THD *thd) const override; void set_param_type_and_swap_value(Item_param *from); Rewritable_query_parameter *get_rewritable_query_parameter() override { return this; } Settable_routine_parameter *get_settable_routine_parameter() override { return m_is_settable_routine_parameter ? this : nullptr; } bool append_for_log(THD *thd, String *str) override; bool check_vcol_func_processor(void *) override { return false; } bool add_as_clone(THD *thd); void sync_clones(); bool register_clone(Item_param *i) { return m_clones.push_back(i); } void raise_error_not_evaluable() override { invalid_default_param(); } private: void invalid_default_param() const; bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; void set_out_param_info(Send_field *info) override; public: const Send_field *get_out_param_info() const override; Item_param *get_item_param() override { return this; } void make_send_field(THD *thd, Send_field *field) override; /** See comments on @see Item::associate_with_target_field for method description */ bool associate_with_target_field(THD *, Item_field *field) override { m_associated_field= field; return false; } bool assign_default(Field *field); private: Send_field *m_out_param_info; bool m_is_settable_routine_parameter; /* Array of all references of this parameter marker used in a CTE to its clones created for copies of this marker used the CTE's copies. It's used to synchronize the actual value of the parameter with the values of the clones. */ Mem_root_array<Item_param *, true> m_clones; Item_field *m_associated_field; Field *m_default_field; protected: Item *shallow_copy(THD *thd) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; class Item_int :public Item_num { public: longlong value; Item_int(THD *thd, int32 i,size_t length= MY_INT32_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong) i) { max_length=(uint32)length; } Item_int(THD *thd, longlong i,size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value(i) { max_length=(uint32)length; } Item_int(THD *thd, ulonglong i, size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong)i) { max_length=(uint32)length; unsigned_flag= 1; } Item_int(THD *thd, const char *str_arg,longlong i,size_t length): Item_num(thd), value(i) { max_length=(uint32)length; name.str= str_arg; name.length= safe_strlen(name.str); } Item_int(THD *thd, const char *str_arg,longlong i,size_t length, bool flag): Item_num(thd), value(i) { max_length=(uint32)length; name.str= str_arg; name.length= safe_strlen(name.str); unsigned_flag= flag; } Item_int(const char *str_arg,longlong i,size_t length): Item_num(), value(i) { max_length=(uint32)length; name.str= str_arg; name.length= safe_strlen(name.str); unsigned_flag= 1; } Item_int(THD *thd, const char *str_arg, size_t length=64); const Type_handler *type_handler() const override { return type_handler_long_or_longlong(); } Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return tmp_table_field_from_field_type(root, table); } const longlong *const_ptr_longlong() const override { return &value; } bool val_bool() override { return value != 0; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return value; } longlong val_int_min() const override { return value; } double val_real() override { return (double) value; } my_decimal *val_decimal(my_decimal *) override; String *val_str(String*) override; int save_in_field(Field *field, bool no_conversions) override; bool is_order_clause_position() const override { return true; } Item *clone_constant(THD *thd) const override; void print(String *str, enum_query_type query_type) override; Item *neg(THD *thd) override; decimal_digits_t decimal_precision() const override { return (decimal_digits_t) (max_length - MY_TEST(value < 0)); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_int>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* We sometimes need to distinguish a number from a boolean: a[1] and a[true] are different things in XPath. Also in JSON boolean values should be treated differently. */ class Item_bool :public Item_int { public: Item_bool(THD *thd, const char *str_arg, longlong i): Item_int(thd, str_arg, i, 1) {} Item_bool(THD *thd, bool i) :Item_int(thd, (longlong) i, 1) { } Item_bool(const char *str_arg, longlong i): Item_int(str_arg, i, 1) {} bool is_bool_literal() const override { return true; } Item *neg_transformer(THD *thd) override; const Type_handler *type_handler() const override { return &type_handler_bool; } const Type_handler *fixed_type_handler() const override { return &type_handler_bool; } void quick_fix_field() override { /* We can get here when Item_bool is created instead of a constant predicate at various condition optimization stages in sql_select. */ } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_bool>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_bool_static :public Item_bool { public: Item_bool_static(const char *str_arg, longlong i): Item_bool(str_arg, i) {}; /* Don't mark static items as top level item */ virtual void top_level_item() override {} void set_join_tab_idx(uint8 join_tab_idx_arg) override { DBUG_ASSERT(0); } void cleanup() override {} protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_bool_static>(thd, this); } }; /* The following variablese are stored in a read only segment */ extern Item_bool_static *Item_false, *Item_true; class Item_uint :public Item_int { public: Item_uint(THD *thd, const char *str_arg, size_t length); Item_uint(THD *thd, ulonglong i): Item_int(thd, i, 10) {} Item_uint(THD *thd, const char *str_arg, longlong i, uint length); double val_real() override { return ulonglong2double((ulonglong)value); } Item *clone_constant(THD *thd) const override; Item *neg(THD *thd) override; decimal_digits_t decimal_precision() const override { return decimal_digits_t(max_length); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_uint>(thd, this); } }; class Item_datetime :public Item_int { protected: MYSQL_TIME ltime; public: Item_datetime(THD *thd): Item_int(thd, 0) { unsigned_flag=0; } Item_datetime(THD *thd, const Datetime &dt, decimal_digits_t dec) :Item_int(thd, 0), ltime(*dt.get_mysql_time()) { unsigned_flag= 0; decimals= dec; } int save_in_field(Field *field, bool no_conversions) override; longlong val_int() override; double val_real() override { return (double)val_int(); } void set(const MYSQL_TIME *datetime) { ltime= *datetime; } void set_from_packed(longlong packed, enum_mysql_timestamp_type ts_type); bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) override { *to= ltime; return false; } void print(String *str, enum_query_type query_type) override; }; /* decimal (fixed point) constant */ class Item_decimal :public Item_num { protected: my_decimal decimal_value; public: Item_decimal(THD *thd, const char *str_arg, size_t length, CHARSET_INFO *charset); Item_decimal(THD *thd, const char *str, const my_decimal *val_arg, uint decimal_par, uint length); Item_decimal(THD *thd, const my_decimal *value_par); Item_decimal(THD *thd, longlong val, bool unsig); Item_decimal(THD *thd, double val, int precision, int scale); Item_decimal(THD *thd, const uchar *bin, int precision, int scale); const Type_handler *type_handler() const override { return &type_handler_newdecimal; } bool val_bool() override { return decimal_value.to_bool(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return decimal_value.to_longlong(unsigned_flag); } double val_real() override { return decimal_value.to_double(); } String *val_str(String *to) override { return decimal_value.to_string(to); } my_decimal *val_decimal(my_decimal *val) override { return &decimal_value; } const my_decimal *const_ptr_my_decimal() const override { return &decimal_value; } int save_in_field(Field *field, bool no_conversions) override; Item *clone_constant(THD *thd) const override; void print(String *str, enum_query_type query_type) override { decimal_value.to_string(&str_value); str->append(str_value); } Item *neg(THD *thd) override; decimal_digits_t decimal_precision() const override { return decimal_value.precision(); } void set_decimal_value(my_decimal *value_par); protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_decimal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_float :public Item_num { const char *presentation; public: double value; Item_float(THD *thd, const char *str_arg, size_t length); Item_float(THD *thd, const char *str, double val_arg, uint decimal_par, uint length): Item_num(thd), value(val_arg) { presentation= name.str= str; name.length= safe_strlen(str); decimals=(uint8) decimal_par; max_length= length; } Item_float(THD *thd, double value_par, uint decimal_par): Item_num(thd), presentation(0), value(value_par) { decimals= (uint8) decimal_par; } int save_in_field(Field *field, bool no_conversions) override; const Type_handler *type_handler() const override { return &type_handler_double; } const double *const_ptr_double() const override { return &value; } bool val_bool() override { return value != 0.0; } double val_real() override { return value; } longlong val_int() override { DBUG_ASSERT(!is_cond()); if (value <= (double) LONGLONG_MIN) { return LONGLONG_MIN; } else if (value >= (double) (ulonglong) LONGLONG_MAX) { return LONGLONG_MAX; } return (longlong) rint(value); } String *val_str(String*) override; my_decimal *val_decimal(my_decimal *) override; Item *clone_constant(THD *thd) const override; Item *neg(THD *thd) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_float>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_static_float_func :public Item_float { const char *func_name; public: Item_static_float_func(THD *thd, const char *str, double val_arg, uint decimal_par, uint length): Item_float(thd, NullS, val_arg, decimal_par, length), func_name(str) {} void print(String *str, enum_query_type) override { str->append(func_name, strlen(func_name)); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { return const_charset_converter(thd, tocs, true, func_name); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_static_float_func>(thd, this); } }; class Item_string :public Item_literal { protected: void fix_from_value(Derivation dv, const Metadata metadata) { fix_charset_and_length(str_value.charset(), dv, metadata); } void fix_and_set_name_from_value(THD *thd, Derivation dv, const Metadata metadata) { fix_from_value(dv, metadata); set_name(thd, &str_value); } protected: /* Just create an item and do not fill string representation */ Item_string(THD *thd, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): Item_literal(thd) { collation.set(cs, dv); max_length= 0; set_name(thd, NULL, 0, system_charset_info); decimals= NOT_FIXED_DEC; } public: Item_string(THD *thd, CHARSET_INFO *csi, const char *str_arg, uint length_arg) :Item_literal(thd) { collation.set(csi, DERIVATION_COERCIBLE); set_name(thd, NULL, 0, system_charset_info); decimals= NOT_FIXED_DEC; str_value.copy(str_arg, length_arg, csi); max_length= str_value.numchars() * csi->mbmaxlen; } // Constructors with the item name set from its value Item_string(THD *thd, const char *str, uint length, CHARSET_INFO *cs, Derivation dv, my_repertoire_t repertoire) :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire)); } Item_string(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_and_set_name_from_value(thd, dv, Metadata(&str_value)); } Item_string(THD *thd, const String *str, CHARSET_INFO *tocs, uint *conv_errors, Derivation dv, my_repertoire_t repertoire) :Item_literal(thd) { if (str_value.copy(str, tocs, conv_errors)) str_value.set("", 0, tocs); // EOM ? str_value.mark_as_const(); fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire)); } // Constructors with an externally provided item name Item_string(THD *thd, const LEX_CSTRING &name_par, const LEX_CSTRING &str, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) :Item_literal(thd) { str_value.set_or_copy_aligned(str.str, str.length, cs); fix_from_value(dv, Metadata(&str_value)); set_name(thd, name_par); } Item_string(THD *thd, const LEX_CSTRING &name_par, const LEX_CSTRING &str, CHARSET_INFO *cs, Derivation dv, my_repertoire_t repertoire) :Item_literal(thd) { str_value.set_or_copy_aligned(str.str, str.length, cs); fix_from_value(dv, Metadata(&str_value, repertoire)); set_name(thd, name_par); } void print_value(String *to) const { str_value.print(to); } bool val_bool() override { return val_real() != 0.0; } double val_real() override; longlong val_int() override; const String *const_ptr_string() const override { return &str_value; } String *val_str(String*) override { return (String*) &str_value; } my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_string(thd, ltime, fuzzydate); } int save_in_field(Field *field, bool no_conversions) override; const Type_handler *type_handler() const override { return Type_handler::string_type_handler(max_length); } Item *clone_constant(THD *thd) const override; Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { return const_charset_converter(thd, tocs, true); } inline void append(const char *str, uint length) { str_value.append(str, length); max_length= str_value.numchars() * collation.collation->mbmaxlen; } void print(String *str, enum_query_type query_type) override; /** Return TRUE if character-set-introducer was explicitly specified in the original query for this item (text literal). This operation is to be called from Item_string::print(). The idea is that when a query is generated (re-constructed) from the Item-tree, character-set-introducers should appear only for those literals, where they were explicitly specified by the user. Otherwise, that may lead to loss collation information (character set introducers implies default collation for the literal). Basically, that makes sense only for views and hopefully will be gone one day when we start using original query as a view definition. @return This operation returns the value of m_cs_specified attribute. @retval TRUE if character set introducer was explicitly specified in the original query. @retval FALSE otherwise. */ virtual bool is_cs_specified() const { return false; } String *check_well_formed_result(bool send_error) { return Item::check_well_formed_result(&str_value, send_error); } Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *) override; Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_string>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_string_with_introducer :public Item_string { public: Item_string_with_introducer(THD *thd, const LEX_CSTRING &str, CHARSET_INFO *cs): Item_string(thd, str.str, str.length, cs) { } Item_string_with_introducer(THD *thd, const LEX_CSTRING &name_arg, const LEX_CSTRING &str, CHARSET_INFO *tocs): Item_string(thd, name_arg, str, tocs) { } bool is_cs_specified() const override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_string_with_introducer>(thd, this); } }; class Item_string_sys :public Item_string { public: Item_string_sys(THD *thd, const char *str, uint length): Item_string(thd, str, length, system_charset_info) { } Item_string_sys(THD *thd, const char *str): Item_string(thd, str, (uint) strlen(str), system_charset_info) { } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_string_sys>(thd, this); } }; class Item_string_ascii :public Item_string { public: Item_string_ascii(THD *thd, const char *str, uint length): Item_string(thd, str, length, &my_charset_latin1, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII) { } Item_string_ascii(THD *thd, const char *str): Item_string(thd, str, (uint) strlen(str), &my_charset_latin1, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII) { } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_string_ascii>(thd, this); } }; class Item_static_string_func :public Item_string { const LEX_CSTRING func_name; public: Item_static_string_func(THD *thd, const LEX_CSTRING &name_par, const LEX_CSTRING &str, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): Item_string(thd, LEX_CSTRING({NullS,0}), str, cs, dv), func_name(name_par) {} Item_static_string_func(THD *thd, const LEX_CSTRING &name_par, const String *str, CHARSET_INFO *tocs, uint *conv_errors, Derivation dv, my_repertoire_t repertoire): Item_string(thd, str, tocs, conv_errors, dv, repertoire), func_name(name_par) {} Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { return const_charset_converter(thd, tocs, true, func_name.str); } void print(String *str, enum_query_type) override { str->append(func_name); } bool check_partition_func_processor(void *) override { return true; } bool check_vcol_func_processor(void *arg) override { // VCOL_TIME_FUNC because the value is not constant, but does not // require fix_fields() to be re-run for every statement. return mark_unsupported_function(func_name.str, arg, VCOL_TIME_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_static_string_func>(thd, this); } }; /* for show tables */ class Item_partition_func_safe_string: public Item_string { public: Item_partition_func_safe_string(THD *thd, const LEX_CSTRING &name_arg, uint length, CHARSET_INFO *cs): Item_string(thd, name_arg, LEX_CSTRING({0,0}), cs) { max_length= length; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("safe_string", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_partition_func_safe_string>(thd, this); } }; /** Item_empty_string -- is a utility class to put an item into List<Item> which is then used in protocol.send_result_set_metadata() when sending SHOW output to the client. */ class Item_empty_string :public Item_partition_func_safe_string { public: Item_empty_string(THD *thd, const LEX_CSTRING &header, uint length, CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci) :Item_partition_func_safe_string(thd, header, length * cs->mbmaxlen, cs) { } Item_empty_string(THD *thd, const char *header, uint length, CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci) :Item_partition_func_safe_string(thd, LEX_CSTRING({header, strlen(header)}), length * cs->mbmaxlen, cs) { } void make_send_field(THD *thd, Send_field *field) override; }; class Item_return_int :public Item_int { enum_field_types int_field_type; public: Item_return_int(THD *thd, const char *name_arg, uint length, enum_field_types field_type_arg, longlong value_arg= 0): Item_int(thd, name_arg, value_arg, length), int_field_type(field_type_arg) { unsigned_flag=1; } const Type_handler *type_handler() const override { const Type_handler *h= Type_handler::get_handler_by_field_type(int_field_type); return unsigned_flag ? h->type_handler_unsigned() : h; } }; /** Item_hex_constant -- a common class for hex literals: X'HHHH' and 0xHHHH */ class Item_hex_constant: public Item_literal { private: void hex_string_init(THD *thd, const char *str, size_t str_length); public: Item_hex_constant(THD *thd): Item_literal(thd) { hex_string_init(thd, "", 0); } Item_hex_constant(THD *thd, const char *str, size_t str_length): Item_literal(thd) { hex_string_init(thd, str, str_length); } const Type_handler *type_handler() const override { return &type_handler_varchar; } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { return const_charset_converter(thd, tocs, true); } const String *const_ptr_string() const override { return &str_value; } String *val_str(String*) override { return &str_value; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; /** Item_hex_hybrid -- is a class implementing 0xHHHH literals, e.g.: SELECT 0x3132; They can behave as numbers and as strings depending on context. */ class Item_hex_hybrid: public Item_hex_constant { public: Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {} Item_hex_hybrid(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} const Type_handler *type_handler() const override { return &type_handler_hex_hybrid; } decimal_digits_t decimal_precision() const override; bool val_bool() override { return longlong_from_hex_hybrid(str_value.ptr(), str_value.length()) != 0; } double val_real() override { return (double) (ulonglong) Item_hex_hybrid::val_int(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return longlong_from_hex_hybrid(str_value.ptr(), str_value.length()); } my_decimal *val_decimal(my_decimal *decimal_value) override { longlong value= Item_hex_hybrid::val_int(); int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value); return decimal_value; } int save_in_field(Field *field, bool) override { field->set_notnull(); return field->store_hex_hybrid(str_value.ptr(), str_value.length()); } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_hex_hybrid>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** Item_hex_string -- is a class implementing X'HHHH' literals, e.g.: SELECT X'3132'; Unlike Item_hex_hybrid, X'HHHH' literals behave as strings in all contexts. X'HHHH' are also used in replication of string constants in case of "dangerous" charsets (sjis, cp932, big5, gbk) who can have backslash (0x5C) as the second byte of a multi-byte character, so using '\' escaping for these charsets is not desirable. */ class Item_hex_string: public Item_hex_constant { public: Item_hex_string(THD *thd): Item_hex_constant(thd) {} Item_hex_string(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} bool val_bool() override { return double_from_string_with_check(&str_value) != 0.0; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return longlong_from_string_with_check(&str_value); } double val_real() override { return double_from_string_with_check(&str_value); } my_decimal *val_decimal(my_decimal *decimal_value) override { return val_decimal_from_string(decimal_value); } int save_in_field(Field *field, bool) override { field->set_notnull(); return field->store(str_value.ptr(), str_value.length(), collation.collation); } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_hex_string>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_bin_string: public Item_hex_hybrid { public: Item_bin_string(THD *thd, const char *str, size_t str_length); void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_bin_string>(thd, this); } }; class Item_timestamp_literal: public Item_literal { Timestamp_or_zero_datetime m_value; public: Item_timestamp_literal(THD *thd) :Item_literal(thd) { collation= DTCollation_numeric(); } Item_timestamp_literal(THD *thd, const Timestamp_or_zero_datetime &value, decimal_digits_t dec) :Item_literal(thd), m_value(value) { DBUG_ASSERT(value.is_zero_datetime() || !value.to_timestamp().fraction_remainder(dec)); collation= DTCollation_numeric(); decimals= dec; } const Type_handler *type_handler() const override { return &type_handler_timestamp2; } void print(String *str, enum_query_type query_type) override; int save_in_field(Field *field, bool) override { Timestamp_or_zero_datetime_native native(m_value, decimals); return native.save_in_field(field, decimals); } bool val_bool() override { return m_value.to_bool(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return m_value.to_datetime(current_thd).to_longlong(); } double val_real() override { return m_value.to_datetime(current_thd).to_double(); } String *val_str(String *to) override { return m_value.to_datetime(current_thd).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return m_value.to_datetime(current_thd).to_decimal(to); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { bool res= m_value.to_TIME(thd, ltime, fuzzydate); DBUG_ASSERT(!res); return res; } bool val_native(THD *thd, Native *to) override { return m_value.to_native(to, decimals); } const Timestamp_or_zero_datetime &value() const { return m_value; } void set_value(const Timestamp_or_zero_datetime &value) { m_value= value; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_timestamp_literal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_temporal_literal :public Item_literal { public: Item_temporal_literal(THD *thd) :Item_literal(thd) { collation= DTCollation_numeric(); decimals= 0; } Item_temporal_literal(THD *thd, decimal_digits_t dec_arg): Item_literal(thd) { collation= DTCollation_numeric(); decimals= dec_arg; } int save_in_field(Field *field, bool no_conversions) override { return save_date_in_field(field, no_conversions); } }; /** DATE'2010-01-01' */ class Item_date_literal: public Item_temporal_literal { protected: Date cached_time; bool update_null() { return (maybe_null() && (null_value= cached_time.check_date_with_warn(current_thd))); } public: Item_date_literal(THD *thd, const Date *ltime) :Item_temporal_literal(thd), cached_time(*ltime) { DBUG_ASSERT(cached_time.is_valid_date()); max_length= MAX_DATE_WIDTH; /* If date has zero month or day, it can return NULL in case of NO_ZERO_DATE or NO_ZERO_IN_DATE. If date is `February 30`, it can return NULL in case if no ALLOW_INVALID_DATES is set. We can't set null_value using the current sql_mode here in constructor, because sql_mode can change in case of prepared statements between PREPARE and EXECUTE. Here we only set maybe_null to true if the value has such anomalies. Later (during execution time), if maybe_null is true, then the value will be checked per row, according to the execution time sql_mode. The check_date() below call should cover all cases mentioned. */ set_maybe_null(cached_time.check_date(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)); } const Type_handler *type_handler() const override { return &type_handler_newdate; } void print(String *str, enum_query_type query_type) override; const MYSQL_TIME *const_ptr_mysql_time() const override { return cached_time.get_mysql_time(); } Item *clone_constant(THD *thd) const override; bool val_bool() override { return update_null() ? false : cached_time.to_bool(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return update_null() ? 0 : cached_time.to_longlong(); } double val_real() override { return update_null() ? 0 : cached_time.to_double(); } String *val_str(String *to) override { return update_null() ? 0 : cached_time.to_string(to); } my_decimal *val_decimal(my_decimal *to) override { return update_null() ? 0 : cached_time.to_decimal(to); } longlong val_datetime_packed(THD *thd) override { return update_null() ? 0 : cached_time.valid_date_to_packed(); } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_date_literal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** TIME'10:10:10' */ class Item_time_literal final: public Item_temporal_literal { protected: Time cached_time; public: Item_time_literal(THD *thd, const Time *ltime, decimal_digits_t dec_arg): Item_temporal_literal(thd, dec_arg), cached_time(*ltime) { DBUG_ASSERT(cached_time.is_valid_time()); max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0); } const Type_handler *type_handler() const override { return &type_handler_time2; } void print(String *str, enum_query_type query_type) override; const MYSQL_TIME *const_ptr_mysql_time() const override { return cached_time.get_mysql_time(); } Item *clone_constant(THD *thd) const override; bool val_bool() override { return cached_time.to_bool(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return cached_time.to_longlong(); } double val_real() override { return cached_time.to_double(); } String *val_str(String *to) override { return cached_time.to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return cached_time.to_decimal(to); } longlong val_time_packed(THD *thd) override { return cached_time.valid_time_to_packed(); } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override { return Time(thd, this).to_native(to, decimals); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_time_literal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** TIMESTAMP'2001-01-01 10:20:30' */ class Item_datetime_literal: public Item_temporal_literal { protected: Datetime cached_time; bool update_null() { return (maybe_null() && (null_value= cached_time.check_date_with_warn(current_thd))); } public: Item_datetime_literal(THD *thd, const Datetime *ltime, decimal_digits_t dec_arg): Item_temporal_literal(thd, dec_arg), cached_time(*ltime) { DBUG_ASSERT(cached_time.is_valid_datetime()); max_length= MAX_DATETIME_WIDTH + (decimals ? decimals + 1 : 0); // See the comment on maybe_null in Item_date_literal set_maybe_null(cached_time.check_date(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)); } const Type_handler *type_handler() const override { return &type_handler_datetime2; } void print(String *str, enum_query_type query_type) override; const MYSQL_TIME *const_ptr_mysql_time() const override { return cached_time.get_mysql_time(); } Item *clone_constant(THD *thd) const override; bool val_bool() override { return update_null() ? false : cached_time.to_bool(); } longlong val_int() override { DBUG_ASSERT(!is_cond()); return update_null() ? 0 : cached_time.to_longlong(); } double val_real() override { return update_null() ? 0 : cached_time.to_double(); } String *val_str(String *to) override { return update_null() ? NULL : cached_time.to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return update_null() ? NULL : cached_time.to_decimal(to); } longlong val_datetime_packed(THD *thd) override { return update_null() ? 0 : cached_time.valid_datetime_to_packed(); } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_datetime_literal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** An error-safe counterpart for Item_date_literal */ class Item_date_literal_for_invalid_dates: public Item_date_literal { /** During equal field propagation we can replace non-temporal constants found in equalities to their native temporal equivalents: WHERE date_column='2001-01-01' ... -> WHERE date_column=DATE'2001-01-01' ... This is done to make the equal field propagation code handle mixtures of different temporal types in the same expressions easier (MDEV-8706), e.g. WHERE LENGTH(date_column)=10 AND date_column=TIME'00:00:00' Item_date_literal_for_invalid_dates::get_date() (unlike the regular Item_date_literal::get_date()) does not check the result for NO_ZERO_IN_DATE and NO_ZERO_DATE, always returns success (false), and does not produce error/warning messages. We need these _for_invalid_dates classes to be able to rewrite: SELECT * FROM t1 WHERE date_column='0000-00-00' ... to: SELECT * FROM t1 WHERE date_column=DATE'0000-00-00' ... to avoid returning NULL value instead of '0000-00-00' even in sql_mode=TRADITIONAL. */ public: Item_date_literal_for_invalid_dates(THD *thd, const Date *ltime) :Item_date_literal(thd, ltime) { base_flags&= ~item_base_t::MAYBE_NULL; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { cached_time.copy_to_mysql_time(ltime); return (null_value= false); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_date_literal_for_invalid_dates>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** An error-safe counterpart for Item_datetime_literal (see Item_date_literal_for_invalid_dates for comments) */ class Item_datetime_literal_for_invalid_dates final: public Item_datetime_literal { public: Item_datetime_literal_for_invalid_dates(THD *thd, const Datetime *ltime, decimal_digits_t dec_arg) :Item_datetime_literal(thd, ltime, dec_arg) { base_flags&= ~item_base_t::MAYBE_NULL; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { cached_time.copy_to_mysql_time(ltime); return (null_value= false); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_datetime_literal_for_invalid_dates>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Used_tables_and_const_cache { public: /* In some cases used_tables_cache is not what used_tables() return so the method should be used where one need used tables bit map (even internally in Item_func_* code). */ table_map used_tables_cache; bool const_item_cache; Used_tables_and_const_cache() :used_tables_cache(0), const_item_cache(true) { } Used_tables_and_const_cache(const Used_tables_and_const_cache *other) :used_tables_cache(other->used_tables_cache), const_item_cache(other->const_item_cache) { } inline void used_tables_and_const_cache_init() { used_tables_cache= 0; const_item_cache= true; } inline void used_tables_and_const_cache_join(const Item *item) { used_tables_cache|= item->used_tables(); const_item_cache&= item->const_item(); } inline void used_tables_and_const_cache_update_and_join(Item *item) { item->update_used_tables(); used_tables_and_const_cache_join(item); } /* Call update_used_tables() for all "argc" items in the array "argv" and join with the current cache. "this" must be initialized with a constructor or re-initialized with used_tables_and_const_cache_init(). */ void used_tables_and_const_cache_update_and_join(uint argc, Item **argv) { for (uint i=0 ; i < argc ; i++) used_tables_and_const_cache_update_and_join(argv[i]); } /* Call update_used_tables() for all items in the list and join with the current cache. "this" must be initialized with a constructor or re-initialized with used_tables_and_const_cache_init(). */ void used_tables_and_const_cache_update_and_join(List<Item> &list) { List_iterator_fast<Item> li(list); Item *item; while ((item=li++)) used_tables_and_const_cache_update_and_join(item); } }; /** An abstract class representing common features of regular functions and aggregate functions. */ class Item_func_or_sum: public Item_result_field, public Item_args, public Used_tables_and_const_cache { protected: bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, uint flags, int item_sep) { return Type_std_attributes::agg_arg_charsets(c, func_name_cstring(), items, nitems, flags, item_sep); } bool agg_arg_charsets_for_string_result(DTCollation &c, Item **items, uint nitems, int item_sep= 1) { return Type_std_attributes:: agg_arg_charsets_for_string_result(c, func_name_cstring(), items, nitems, item_sep); } bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c, Item **items, uint nitems, int item_sep= 1) { return Type_std_attributes:: agg_arg_charsets_for_string_result_with_comparison(c, func_name_cstring(), items, nitems, item_sep); } /* Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b - don't convert to @@character_set_connection if all arguments are numbers - don't allow DERIVATION_NONE */ bool agg_arg_charsets_for_comparison(DTCollation &c, Item **items, uint nitems, int item_sep= 1) { return Type_std_attributes:: agg_arg_charsets_for_comparison(c, func_name_cstring(), items, nitems, item_sep); } public: // This method is used by Arg_comparator bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b, bool allow_narrowing) { THD *thd= current_thd; DTCollation tmp; if (tmp.set((*a)->collation, (*b)->collation, MY_COLL_CMP_CONV) || tmp.derivation == DERIVATION_NONE) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), (*a)->collation.collation->coll_name.str, (*a)->collation.derivation_name(), (*b)->collation.collation->coll_name.str, (*b)->collation.derivation_name(), func_name()); return true; } if (allow_narrowing && (*a)->collation.derivation == (*b)->collation.derivation) { // allow_narrowing==true only for = and <=> comparisons. if (Utf8_narrow::should_do_narrowing(thd, (*a)->collation.collation, (*b)->collation.collation)) { // a is a subset, b is a superset (e.g. utf8mb3 vs utf8mb4) *cs= (*b)->collation.collation; // Compare using the wider cset return false; } else if (Utf8_narrow::should_do_narrowing(thd, (*b)->collation.collation, (*a)->collation.collation)) { // a is a superset, b is a subset (e.g. utf8mb4 vs utf8mb3) *cs= (*a)->collation.collation; // Compare using the wider cset return false; } } /* If necessary, convert both *a and *b to the collation in tmp: */ Single_coll_err error_for_a= {(*b)->collation, true}; Single_coll_err error_for_b= {(*a)->collation, false}; if (agg_item_set_converter(tmp, func_name_cstring(), a, 1, MY_COLL_CMP_CONV, 1, /*just for error message*/ &error_for_a) || agg_item_set_converter(tmp, func_name_cstring(), b, 1, MY_COLL_CMP_CONV, 1, /*just for error message*/ &error_for_b)) return true; *cs= tmp.collation; return false; } public: Item_func_or_sum(THD *thd): Item_result_field(thd), Item_args() {} Item_func_or_sum(THD *thd, Item *a): Item_result_field(thd), Item_args(a) { } Item_func_or_sum(THD *thd, Item *a, Item *b): Item_result_field(thd), Item_args(a, b) { } Item_func_or_sum(THD *thd, Item *a, Item *b, Item *c): Item_result_field(thd), Item_args(thd, a, b, c) { } Item_func_or_sum(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_result_field(thd), Item_args(thd, a, b, c, d) { } Item_func_or_sum(THD *thd, Item *a, Item *b, Item *c, Item *d, Item *e): Item_result_field(thd), Item_args(thd, a, b, c, d, e) { } Item_func_or_sum(THD *thd, Item_func_or_sum *item): Item_result_field(thd, item), Item_args(thd, item), Used_tables_and_const_cache(item) { } Item_func_or_sum(THD *thd, List<Item> &list): Item_result_field(thd), Item_args(thd, list) { } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { if (walk_args(processor, walk_subquery, arg)) return true; return (this->*processor)(arg); } /* Built-in schema, e.g. mariadb_schema, oracle_schema, maxdb_schema */ virtual const Schema *schema() const { // A function does not belong to a built-in schema by default return NULL; } /* This method is used for debug purposes to print the name of an item to the debug log. The second use of this method is as a helper function of print() and error messages, where it is applicable. To suit both goals it should return a meaningful, distinguishable and sintactically correct string. This method should not be used for runtime type identification, use enum {Sum}Functype and Item_func::functype()/Item_sum::sum_func() instead. Added here, to the parent class of both Item_func and Item_sum. NOTE: for Items inherited from Item_sum, func_name() and func_name_cstring() returns part of function name till first argument (including '(') to make difference in names for functions with 'distinct' clause and without 'distinct' and also to make printing of items inherited from Item_sum uniform. */ inline const char *func_name() const { return (char*) func_name_cstring().str; } virtual LEX_CSTRING func_name_cstring() const= 0; virtual bool fix_length_and_dec(THD *thd)= 0; bool const_item() const override { return const_item_cache; } table_map used_tables() const override { return used_tables_cache; } Item* deep_copy(THD *thd) const override; Sql_mode_dependency value_depends_on_sql_mode() const override { return Item_args::value_depends_on_sql_mode_bit_or().soft_to_hard(); } }; class sp_head; class sp_name; struct st_sp_security_context; class Item_sp { protected: // Can be NULL in some non-SELECT queries Name_resolution_context *context; public: sp_name *m_name; sp_head *m_sp; TABLE *dummy_table; uchar result_buf[64]; sp_rcontext *func_ctx; MEM_ROOT sp_mem_root; Query_arena *sp_query_arena; /* The result field of the stored function. */ Field *sp_result_field; Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg); Item_sp(THD *thd, Item_sp *item); virtual ~Item_sp() { delete sp_result_field; sp_result_field= NULL; } LEX_CSTRING func_name_cstring(THD *thd, bool is_package_function) const; void cleanup(); bool sp_check_access(THD *thd); bool execute(THD *thd, bool *null_value, Item **args, uint arg_count); bool execute_impl(THD *thd, Item **args, uint arg_count); bool init_result_field(THD *thd, uint max_length, uint maybe_null, bool *null_value, LEX_CSTRING *name); void process_error(THD *thd) { if (context) context->process_error(thd); } }; class Item_ref :public Item_ident { protected: void set_properties(); bool set_properties_only; // the item doesn't need full fix_fields public: enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF }; Item **ref; bool reference_trough_name; Item_ref(THD *thd, Name_resolution_context *context_arg, const LEX_CSTRING &db_arg, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg): Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg), set_properties_only(0), ref(0), reference_trough_name(1) {} Item_ref(THD *thd, Name_resolution_context *context_arg, const LEX_CSTRING &field_name_arg) :Item_ref(thd, context_arg, null_clex_str, null_clex_str, field_name_arg) { } /* This constructor is used in two scenarios: A) *item = NULL No initialization is performed, fix_fields() call will be necessary. B) *item points to an Item this Item_ref will refer to. This is used for GROUP BY. fix_fields() will not be called in this case, so we call set_properties to make this item "fixed". set_properties performs a subset of action Item_ref::fix_fields does, and this subset is enough for Item_ref's used in GROUP BY. TODO we probably fix a superset of problems like in BUG#6658. Check this with Bar, and if we have a more broader set of problems like this. */ Item_ref(THD *thd, Name_resolution_context *context_arg, Item **item, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg, bool alias_name_used_arg= FALSE); Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item, const LEX_CSTRING &field_name_arg, bool alias_name_used_arg= FALSE); /* Constructor need to process subselect with temporary tables (see Item) */ Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), set_properties_only(0), ref(item->ref) {} enum Type type() const override { return REF_ITEM; } enum Type real_type() const override { return ref ? (*ref)->type() : REF_ITEM; } bool eq(const Item *item, const Eq_config &config) const override { const Item *it= item->real_item(); return ref && (*ref)->eq(it, config); } void save_val(Field *to) override; void save_result(Field *to) override; double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; String *val_str(String* tmp) override; bool val_native(THD *thd, Native *to) override; bool is_null() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; longlong val_datetime_packed(THD *) override; longlong val_time_packed(THD *) override; double val_result() override; longlong val_int_result() override; String *str_result(String* tmp) override; bool val_native_result(THD *thd, Native *to) override; my_decimal *val_decimal_result(my_decimal *) override; bool val_bool_result() override; bool is_null_result() override; bool send(Protocol *prot, st_value *buffer) override; void make_send_field(THD *thd, Send_field *field) override; bool fix_fields(THD *, Item **) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; int save_in_field(Field *field, bool no_conversions) override; void save_org_in_field(Field *field, fast_field_copier optimizer_data) override; fast_field_copier setup_fast_field_copier(Field *field) override { return (*ref)->setup_fast_field_copier(field); } const Type_handler *type_handler() const override { return (*ref)->type_handler(); } const Type_handler *real_type_handler() const override { return (*ref)->real_type_handler(); } uint32 character_octet_length() const override { return Item_ref::real_item()->character_octet_length(); } Field *get_tmp_table_field() override { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd) override; Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override; table_map used_tables() const override; void update_used_tables() override; COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override { /* normilize_cond() replaced all conditions of type WHERE/HAVING field to: WHERE/HAVING field<>0 By the time of a build_equal_items() call, all such conditions should already be replaced. No Item_ref referencing to Item_field are possible. */ DBUG_ASSERT(real_type() != FIELD_ITEM); return Item_ident::build_equal_items(thd, inherited, link_item_fields, cond_equal_ref); } bool const_item() const override { return (*ref)->const_item(); } table_map not_null_tables() const override { return depended_from ? 0 : (*ref)->not_null_tables(); } bool find_not_null_fields(table_map allowed) override { return depended_from ? false : (*ref)->find_not_null_fields(allowed); } void save_in_result_field(bool no_conversions) override { (*ref)->save_in_field(result_field, no_conversions); } Item *real_item() override { return ref ? (*ref)->real_item() : this; } const Item *real_item() const { return const_cast<Item_ref*>(this)->Item_ref::real_item(); } const TYPELIB *get_typelib() const override { return ref ? (*ref)->get_typelib() : NULL; } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { if (ref && *ref) return (*ref)->walk(processor, walk_subquery, arg) || (this->*processor)(arg); else return FALSE; } Item* transform(THD *thd, Item_transformer, uchar *arg) override; Item* compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) override; bool enumerate_field_refs_processor(void *arg) override { return (*ref)->enumerate_field_refs_processor(arg); } void no_rows_in_result() override { (*ref)->no_rows_in_result(); } void restore_to_before_no_rows_in_result() override { (*ref)->restore_to_before_no_rows_in_result(); } void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return ref ? (*ref)->precedence() : DEFAULT_PRECEDENCE; } void cleanup() override; Item_field *field_for_view_update() override { return (*ref)->field_for_view_update(); } Load_data_outvar *get_load_data_outvar() override { return (*ref)->get_load_data_outvar(); } virtual Ref_Type ref_type() { return REF; } // Row emulation: forwarding of ROW-related calls to ref uint cols() const override { return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1; } Item* element_index(uint i) override { return ref && result_type() == ROW_RESULT ? (*ref)->element_index(i) : this; } Item** addr(uint i) override { return ref && result_type() == ROW_RESULT ? (*ref)->addr(i) : 0; } bool check_cols(uint c) override { return ref && result_type() == ROW_RESULT ? (*ref)->check_cols(c) : Item::check_cols(c); } bool null_inside() override { return ref && result_type() == ROW_RESULT ? (*ref)->null_inside() : 0; } void bring_value() override { if (ref && result_type() == ROW_RESULT) (*ref)->bring_value(); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("ref", arg, VCOL_IMPOSSIBLE); } bool basic_const_item() const override { return ref && (*ref)->basic_const_item(); } bool is_outer_field() const override { DBUG_ASSERT(fixed()); DBUG_ASSERT(ref); return (*ref)->is_outer_field(); } bool excl_dep_on_table(table_map tab_map) override { table_map used= used_tables(); if (used & OUTER_REF_TABLE_BIT) return false; return (used == tab_map) || (*ref)->excl_dep_on_table(tab_map); } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { return (*ref)->excl_dep_on_grouping_fields(sel); } bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override { return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); } bool cleanup_excluding_fields_processor(void *arg) override { Item *item= real_item(); if (item && item->type() == FIELD_ITEM && ((Item_field *)item)->field) return 0; return cleanup_processor(arg); } bool cleanup_excluding_const_fields_processor(void *arg) override { Item *item= real_item(); if (item && item->type() == FIELD_ITEM && ((Item_field *) item)->field && item->const_item()) return 0; return cleanup_processor(arg); } Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg) override { return (*ref)->field_transformer_for_having_pushdown(thd, arg); } protected: Item *deep_copy(THD *thd) const override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_ref>(thd, this); } }; /* The same as Item_ref, but get value from val_* family of method to get value of item on which it referred instead of result* family. */ class Item_direct_ref :public Item_ref { public: Item_direct_ref(THD *thd, Name_resolution_context *context_arg, Item **item, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg, bool alias_name_used_arg= FALSE): Item_ref(thd, context_arg, item, table_name_arg, field_name_arg, alias_name_used_arg) {} /* Constructor need to process subselect with temporary tables (see Item) */ Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {} Item_direct_ref(THD *thd, TABLE_LIST *view_arg, Item **item, const LEX_CSTRING &field_name_arg, bool alias_name_used_arg= FALSE): Item_ref(thd, view_arg, item, field_name_arg, alias_name_used_arg) {} bool fix_fields(THD *thd, Item **it) override { if ((*ref)->fix_fields_if_needed_for_scalar(thd, ref)) return TRUE; return Item_ref::fix_fields(thd, it); } void save_val(Field *to) override; /* Below we should have all val() methods as in Item_ref */ double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; String *val_str(String* tmp) override; bool val_native(THD *thd, Native *to) override; bool is_null() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; longlong val_datetime_packed(THD *) override; longlong val_time_packed(THD *) override; Ref_Type ref_type() override { return DIRECT_REF; } /* Should be called if ref is changed */ inline void ref_changed() { set_properties(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_direct_ref>(thd, this); } }; /** This class is the same as Item_direct_ref but created to wrap Item_ident before fix_fields() call */ class Item_direct_ref_to_ident :public Item_direct_ref { Item_ident *ident; public: Item_direct_ref_to_ident(THD *thd, Item_ident *item): Item_direct_ref(thd, item->context, (Item**)&item, item->table_name, item->field_name, FALSE) { ident= item; ref= (Item**)&ident; } bool fix_fields(THD *thd, Item **it) override { DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM); if (ident->fix_fields_if_needed_for_scalar(thd, ref)) return TRUE; set_properties(); return FALSE; } void print(String *str, enum_query_type query_type) override { ident->print(str, query_type); } }; class Item_cache; class Expression_cache; class Expression_cache_tracker; /** The objects of this class can store its values in an expression cache. */ class Item_cache_wrapper :public Item_result_field { private: /* Pointer on the cached expression */ Item *orig_item; Expression_cache *expr_cache; /* In order to put the expression into the expression cache and return value of val_*() method, we will need to get the expression value twice (probably in different types). In order to avoid making two (potentially costly) orig_item->val_*() calls, we store expression value in this Item_cache object. */ Item_cache *expr_value; List<Item> parameters; Item *check_cache(); void cache(); void init_on_demand(); public: Item_cache_wrapper(THD *thd, Item *item_arg); ~Item_cache_wrapper(); Type type() const override { return EXPR_CACHE_ITEM; } Type real_type() const override { return orig_item->type(); } bool set_cache(THD *thd); Expression_cache_tracker* init_tracker(MEM_ROOT *mem_root); bool fix_fields(THD *thd, Item **it) override; void cleanup() override; Item *get_orig_item() const { return orig_item; } /* Methods of getting value which should be cached in the cache */ void save_val(Field *to) override; double val_real() override; longlong val_int() override; String *val_str(String* tmp) override; bool val_native(THD *thd, Native *to) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; bool is_null() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool send(Protocol *protocol, st_value *buffer) override; void save_org_in_field(Field *field, fast_field_copier) override { save_val(field); } void save_in_result_field(bool) override { save_val(result_field); } Item* get_tmp_table_item(THD *thd_arg) override; /* Following methods make this item transparent as much as possible */ void print(String *str, enum_query_type query_type) override; LEX_CSTRING full_name_cstring() const override { return orig_item->full_name_cstring(); } void make_send_field(THD *thd, Send_field *field) override { orig_item->make_send_field(thd, field); } bool eq(const Item *item, const Eq_config &config) const override { const Item *it= item->real_item(); return orig_item->eq(it, config); } void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge) override { orig_item->fix_after_pullout(new_parent, &orig_item, merge); } int save_in_field(Field *to, bool no_conversions) override; const Type_handler *type_handler() const override { return orig_item->type_handler(); } table_map used_tables() const override { return orig_item->used_tables(); } void update_used_tables() override { orig_item->update_used_tables(); } bool const_item() const override { return orig_item->const_item(); } table_map not_null_tables() const override { return orig_item->not_null_tables(); } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { return orig_item->walk(processor, walk_subquery, arg) || (this->*processor)(arg); } bool enumerate_field_refs_processor(void *arg) override { return orig_item->enumerate_field_refs_processor(arg); } Item_field *field_for_view_update() override { return orig_item->field_for_view_update(); } /* Row emulation: forwarding of ROW-related calls to orig_item */ uint cols() const override { return result_type() == ROW_RESULT ? orig_item->cols() : 1; } Item* element_index(uint i) override { return result_type() == ROW_RESULT ? orig_item->element_index(i) : this; } Item** addr(uint i) override { return result_type() == ROW_RESULT ? orig_item->addr(i) : 0; } bool check_cols(uint c) override { return (result_type() == ROW_RESULT ? orig_item->check_cols(c) : Item::check_cols(c)); } bool null_inside() override { return result_type() == ROW_RESULT ? orig_item->null_inside() : 0; } void bring_value() override { if (result_type() == ROW_RESULT) orig_item->bring_value(); } bool is_expensive() override { return orig_item->is_expensive(); } bool is_expensive_processor(void *arg) override { return orig_item->is_expensive_processor(arg); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("cache", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_wrapper>(thd, this); } Item *deep_copy(THD *) const override { return nullptr; } }; /* Class for view fields, the same as Item_direct_ref, but call fix_fields of reference if it is not called yet */ class Item_direct_view_ref :public Item_direct_ref { Item_equal *item_equal; TABLE_LIST *view; TABLE *null_ref_table; #define NO_NULL_TABLE (reinterpret_cast<TABLE *>(0x1)) void set_null_ref_table() { if (!view->is_inner_table_of_outer_join() || !(null_ref_table= view->get_real_join_table())) null_ref_table= NO_NULL_TABLE; if (null_ref_table && null_ref_table != NO_NULL_TABLE) set_maybe_null(); } bool check_null_ref() { DBUG_ASSERT(null_ref_table); if (null_ref_table != NO_NULL_TABLE && null_ref_table->null_row) { null_value= 1; return TRUE; } return FALSE; } public: Item_direct_view_ref(THD *thd, Name_resolution_context *context_arg, Item **item, LEX_CSTRING &table_name_arg, LEX_CSTRING &field_name_arg, TABLE_LIST *view_arg): Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg), item_equal(0), view(view_arg), null_ref_table(NULL) { if (fixed()) set_null_ref_table(); } bool fix_fields(THD *, Item **) override; bool eq(const Item *item, const Eq_config &config) const override; Item *get_tmp_table_item(THD *thd) override { if (const_item()) return copy_or_same(thd); Item *item= Item_ref::get_tmp_table_item(thd); item->name= name; return item; } Ref_Type ref_type() override { return VIEW_REF; } Item_equal *get_item_equal() override { return item_equal; } void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; } Item_equal *find_item_equal(COND_EQUAL *cond_equal) override; Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override; Item *replace_equal_field(THD *thd, uchar *arg) override; table_map used_tables() const override; void update_used_tables() override; table_map not_null_tables() const override; bool const_item() const override { return (*ref)->const_item() && (null_ref_table == NO_NULL_TABLE); } TABLE *get_null_ref_table() const { return null_ref_table; } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { return (*ref)->walk(processor, walk_subquery, arg) || (this->*processor)(arg); } bool view_used_tables_processor(void *arg) override { TABLE_LIST *view_arg= (TABLE_LIST *) arg; if (view_arg == view) view_arg->view_used_tables|= (*ref)->used_tables(); return 0; } bool excl_dep_on_table(table_map tab_map) override; bool excl_dep_on_grouping_fields(st_select_lex *sel) override; bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override; Item *derived_field_transformer_for_having(THD *thd, uchar *arg) override; Item *derived_field_transformer_for_where(THD *thd, uchar *arg) override; Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) override; Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) override; Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) override; void save_val(Field *to) override { if (check_null_ref()) to->set_null(); else Item_direct_ref::save_val(to); } double val_real() override { if (check_null_ref()) return 0; else return Item_direct_ref::val_real(); } longlong val_int() override { if (check_null_ref()) return 0; else return Item_direct_ref::val_int(); } String *val_str(String* tmp) override { if (check_null_ref()) return NULL; else return Item_direct_ref::val_str(tmp); } bool val_native(THD *thd, Native *to) override { if (check_null_ref()) return true; return Item_direct_ref::val_native(thd, to); } my_decimal *val_decimal(my_decimal *tmp) override { if (check_null_ref()) return NULL; else return Item_direct_ref::val_decimal(tmp); } bool val_bool() override { if (check_null_ref()) return 0; else return Item_direct_ref::val_bool(); } bool is_null() override { if (check_null_ref()) return 1; else return Item_direct_ref::is_null(); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { if (check_null_ref()) { bzero((char*) ltime,sizeof(*ltime)); return 1; } return Item_direct_ref::get_date(thd, ltime, fuzzydate); } longlong val_time_packed(THD *thd) override { if (check_null_ref()) return 0; else return Item_direct_ref::val_time_packed(thd); } longlong val_datetime_packed(THD *thd) override { if (check_null_ref()) return 0; else return Item_direct_ref::val_datetime_packed(thd); } bool send(Protocol *protocol, st_value *buffer) override; void save_org_in_field(Field *field, fast_field_copier) override { if (check_null_ref()) field->set_null(); else Item_direct_ref::save_val(field); } void save_in_result_field(bool no_conversions) override { if (check_null_ref()) result_field->set_null(); else Item_direct_ref::save_in_result_field(no_conversions); } int save_in_field(Field *field, bool no_conversions) override { if (check_null_ref()) return set_field_to_null_with_conversions(field, no_conversions); return Item_direct_ref::save_in_field(field, no_conversions); } void cleanup() override { null_ref_table= NULL; item_equal= NULL; Item_direct_ref::cleanup(); } /* TODO move these val_*_result function to Item_direct_ref (maybe) */ double val_result() override; longlong val_int_result() override; String *str_result(String* tmp) override; my_decimal *val_decimal_result(my_decimal *val) override; bool val_bool_result() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_direct_view_ref>(thd, this); } public: Item *field_transformer_for_having_pushdown(THD *, uchar *) override { return this; } /* Do the same thing as Item_field: if we were referring to a local view, now we refer to somewhere outside of our SELECT. */ bool set_fields_as_dependent_processor(void *arg) override { if (!(used_tables() & OUTER_REF_TABLE_BIT)) { depended_from= (st_select_lex *) arg; item_equal= NULL; } return 0; } void print(String *str, enum_query_type query_type) override; }; /* Class for outer fields. An object of this class is created when the select where the outer field was resolved is a grouping one. After it has been fixed the ref field will point to either an Item_ref or an Item_direct_ref object which will be used to access the field. See also comments for the fix_inner_refs() and the Item_field::fix_outer_field() functions. */ class Item_sum; class Item_outer_ref :public Item_direct_ref { public: Item *outer_ref; /* The aggregate function under which this outer ref is used, if any. */ Item_sum *in_sum_func; /* TRUE <=> that the outer_ref is already present in the select list of the outer select. */ bool found_in_select_list; bool found_in_group_by; Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item_field *outer_field_arg): Item_direct_ref(thd, context_arg, 0, outer_field_arg->table_name, outer_field_arg->field_name), outer_ref(outer_field_arg), in_sum_func(0), found_in_select_list(0), found_in_group_by(0) { ref= &outer_ref; set_properties(); /* reset flag set in set_properties() */ base_flags&= ~item_base_t::FIXED; } Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item **item, const LEX_CSTRING &table_name_arg, LEX_CSTRING &field_name_arg, bool alias_name_used_arg): Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg, alias_name_used_arg), outer_ref(0), in_sum_func(0), found_in_select_list(1), found_in_group_by(0) {} void save_in_result_field(bool no_conversions) override { outer_ref->save_org_in_field(result_field, NULL); } bool fix_fields(THD *, Item **) override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; table_map used_tables() const override { return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT; } table_map not_null_tables() const override { return 0; } Ref_Type ref_type() override { return OUTER_REF; } bool check_inner_refs_processor(void * arg) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_outer_ref>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_in_subselect; /* An object of this class: - Converts val_XXX() calls to ref->val_XXX_result() calls, like Item_ref. - Sets owner->was_null=TRUE if it has returned a NULL value from any val_XXX() function. This allows to inject an Item_ref_null_helper object into subquery and then check if the subquery has produced a row with NULL value. */ class Item_ref_null_helper: public Item_ref { protected: Item_in_subselect* owner; public: Item_ref_null_helper(THD *thd, Name_resolution_context *context_arg, Item_in_subselect* master, Item **item, const LEX_CSTRING &table_name_arg, const LEX_CSTRING &field_name_arg): Item_ref(thd, context_arg, item, table_name_arg, field_name_arg), owner(master) {} void save_val(Field *to) override; double val_real() override; longlong val_int() override; String* val_str(String* s) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override; void print(String *str, enum_query_type query_type) override; table_map used_tables() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_ref_null_helper>(thd, this); } }; /* The following class is used to optimize comparing of date and bigint columns We need to save the original item ('ref') to be able to call ref->save_in_field(). This is used to create index search keys. An instance of Item_int_with_ref may have signed or unsigned integer value. */ class Item_int_with_ref :public Item_int { Item *ref; public: Item_int_with_ref(THD *thd, longlong i, Item *ref_arg, bool unsigned_arg): Item_int(thd, i), ref(ref_arg) { unsigned_flag= unsigned_arg; } int save_in_field(Field *field, bool no_conversions) override { return ref->save_in_field(field, no_conversions); } Item *clone_constant(THD *thd) const override; Item *real_item() override { return ref; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_int_with_ref>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; #ifdef MYSQL_SERVER #include "item_sum.h" #include "item_func.h" #include "item_row.h" #include "item_cmpfunc.h" #include "item_strfunc.h" #include "item_timefunc.h" #include "item_subselect.h" #include "item_xmlfunc.h" #include "item_jsonfunc.h" #include "item_create.h" #include "item_vers.h" #endif /** Base class to implement typed value caching Item classes Item_copy_ classes are very similar to the corresponding Item_ classes (e.g. Item_copy_string is similar to Item_string) but they add the following additional functionality to Item_ : 1. Nullability 2. Possibility to store the value not only on instantiation time, but also later. Item_copy_ classes are a functionality subset of Item_cache_ classes, as e.g. they don't support comparisons with the original Item as Item_cache_ classes do. Item_copy_ classes are used in GROUP BY calculation. TODO: Item_copy should be made an abstract interface and Item_copy_ classes should inherit both the respective Item_ class and the interface. Ideally we should drop Item_copy_ classes altogether and merge their functionality to Item_cache_ (and these should be made to inherit from Item_). */ class Item_copy :public Item, public Type_handler_hybrid_field_type { protected: /** Type_handler_hybrid_field_type is used to store the type of the resulting field that would be used to store the data in the cache. This is to avoid calls to the original item. */ /** The original item that is copied */ Item *item; /** Constructor of the Item_copy class stores metadata information about the original class as well as a pointer to it. */ Item_copy(THD *thd, Item *org): Item(thd) { DBUG_ASSERT(org->fixed()); item= org; null_value= item->maybe_null(); copy_flags(item, item_base_t::MAYBE_NULL); Type_std_attributes::set(item); name= item->name; set_handler(item->type_handler()); #ifndef DBUG_OFF copied_in= 0; #endif } #ifndef DBUG_OFF bool copied_in; #endif public: /** Update the cache with the value of the original item This is the method that updates the cached value. It must be explicitly called by the user of this class to store the value of the original item in the cache. */ virtual void copy() = 0; Item *get_item() { return item; } /** All of the subclasses should have the same type tag */ Type type() const override { return COPY_STR_ITEM; } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { DBUG_ASSERT(0); return NULL; } void make_send_field(THD *thd, Send_field *field) override { item->make_send_field(thd, field); } table_map used_tables() const override { return (table_map) 1L; } bool const_item() const override { return false; } bool is_null() override { return null_value; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("copy", arg, VCOL_IMPOSSIBLE); } /* Override the methods below as pure virtual to make sure all the sub-classes implement them. */ String *val_str(String*) override = 0; my_decimal *val_decimal(my_decimal *) override = 0; double val_real() override = 0; longlong val_int() override = 0; int save_in_field(Field *field, bool no_conversions) override = 0; bool walk(Item_processor processor, bool walk_subquery, void *args) override { return (item->walk(processor, walk_subquery, args)) || (this->*processor)(args); } }; /** Implementation of a string cache. Uses Item::str_value for storage */ class Item_copy_string : public Item_copy { public: Item_copy_string(THD *thd, Item *item_arg): Item_copy(thd, item_arg) {} String *val_str(String*) override; my_decimal *val_decimal(my_decimal *) override; double val_real() override; longlong val_int() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { DBUG_ASSERT(copied_in); return get_date_from_string(thd, ltime, fuzzydate); } void copy() override; int save_in_field(Field *field, bool no_conversions) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_copy_string>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** We need a separate class Item_copy_timestamp because TIMESTAMP->string->TIMESTAMP conversion is not round trip safe near the DST change, e.g. '2010-10-31 02:25:26' can mean: - my_time_t(1288477526) - summer time in Moscow - my_time_t(1288481126) - winter time in Moscow, one hour later */ class Item_copy_timestamp: public Item_copy { Timestamp_or_zero_datetime m_value; bool sane() const { return !null_value || m_value.is_zero_datetime(); } public: Item_copy_timestamp(THD *thd, Item *arg): Item_copy(thd, arg) { } const Type_handler *type_handler() const override { return &type_handler_timestamp2; } void copy() override { Timestamp_or_zero_datetime_native_null tmp(current_thd, item, false); null_value= tmp.is_null(); m_value= tmp.is_null() ? Timestamp_or_zero_datetime() : Timestamp_or_zero_datetime(tmp); #ifndef DBUG_OFF copied_in=1; #endif } int save_in_field(Field *field, bool) override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); if (null_value) return set_field_to_null(field); Timestamp_or_zero_datetime_native native(m_value, decimals); return native.save_in_field(field, decimals); } longlong val_int() override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); return null_value ? 0 : m_value.to_datetime(current_thd).to_longlong(); } double val_real() override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); return null_value ? 0e0 : m_value.to_datetime(current_thd).to_double(); } String *val_str(String *to) override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); return null_value ? NULL : m_value.to_datetime(current_thd).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); return null_value ? NULL : m_value.to_datetime(current_thd).to_decimal(to); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); bool res= m_value.to_TIME(thd, ltime, fuzzydate); DBUG_ASSERT(!res); return null_value || res; } bool val_native(THD *thd, Native *to) override { DBUG_ASSERT(copied_in); DBUG_ASSERT(sane()); return null_value || m_value.to_native(to, decimals); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_copy_timestamp>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* Cached_item_XXX objects are not exactly caches. They do the following: Each Cached_item_XXX object has - its source item - saved value of the source item - cmp() method that compares the saved value with the current value of the source item, and if they were not equal saves item's value into the saved value. TODO: add here: - a way to save the new value w/o comparison - a way to do less/equal/greater comparison */ class Cached_item :public Sql_alloc { public: bool null_value; Cached_item() :null_value(0) {} /* Compare the cached value with the source value. If not equal, copy the source value to the cache. @return true - Not equal false - Equal */ virtual bool cmp(void)=0; /* Compare the cached value with the source value, without copying */ virtual int cmp_read_only()=0; virtual ~Cached_item(); /*line -e1509 */ }; class Cached_item_item : public Cached_item { protected: Item *item; Cached_item_item(Item *arg) : item(arg) {} public: void fetch_value_from(Item *new_item) { Item *save= item; item= new_item; cmp(); item= save; } }; class Cached_item_str :public Cached_item_item { uint32 value_max_length; String value,tmp_value; public: Cached_item_str(THD *thd, Item *arg); bool cmp() override; int cmp_read_only() override; ~Cached_item_str(); // Deallocate String:s }; class Cached_item_real :public Cached_item_item { double value; public: Cached_item_real(Item *item_par) :Cached_item_item(item_par),value(0.0) {} bool cmp() override; int cmp_read_only() override; }; class Cached_item_int :public Cached_item_item { longlong value; public: Cached_item_int(Item *item_par) :Cached_item_item(item_par),value(0) {} bool cmp() override; int cmp_read_only() override; }; class Cached_item_decimal :public Cached_item_item { my_decimal value; public: Cached_item_decimal(Item *item_par); bool cmp() override; int cmp_read_only() override; }; class Cached_item_field :public Cached_item { uchar *buff; Field *field; uint length; public: Cached_item_field(THD *thd, Field *arg_field): field(arg_field) { field= arg_field; /* TODO: take the memory allocation below out of the constructor. */ buff= (uchar*) thd_calloc(thd, length= field->pack_length()); } bool cmp() override; int cmp_read_only() override; }; class Item_default_value : public Item_field { bool vcol_assignment_ok:1; bool m_associated:1; bool m_share_field:1; void calculate(); public: Item *arg= nullptr; Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a, bool vcol_assignment_arg) : Item_field(thd, context_arg), vcol_assignment_ok(vcol_assignment_arg), arg(a) { m_associated= false; m_share_field= false; } Type type() const override { return DEFAULT_VALUE_ITEM; } bool eq(const Item *item, const Eq_config &config) const override; bool fix_fields(THD *, Item **) override; void cleanup() override; void print(String *str, enum_query_type query_type) override; String *val_str(String *str) override; double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *decimal_value) override; bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *to) override; bool val_native_result(THD *thd, Native *to) override; longlong val_datetime_packed(THD *thd) override { return Item::val_datetime_packed(thd); } longlong val_time_packed(THD *thd) override { return Item::val_time_packed(thd); } /* Result variants */ double val_result() override; longlong val_int_result() override; String *str_result(String* tmp) override; my_decimal *val_decimal_result(my_decimal *val) override; bool val_bool_result() override; bool is_null_result() override; bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool send(Protocol *protocol, st_value *buffer) override; int save_in_field(Field *field_arg, bool no_conversions) override; void save_in_result_field(bool no_conversions) override; bool save_in_param(THD *, Item_param *param) override { // It should not be possible to have "EXECUTE .. USING DEFAULT(a)" DBUG_ASSERT(0); param->set_default(true); return false; } table_map used_tables() const override; void update_used_tables() override { if (field && field->default_value) field->default_value->expr->update_used_tables(); } bool vcol_assignment_allowed_value() const override { return vcol_assignment_ok; } Item *get_tmp_table_item(THD *) override { return this; } Item_field *field_for_view_update() override { return nullptr; } bool update_vcol_processor(void *) override { return false; } bool check_field_expression_processor(void *arg) override; bool check_func_default_processor(void *) override { return true; } bool update_func_default_processor(void *arg) override; bool register_field_in_read_map(void *arg) override; bool walk(Item_processor processor, bool walk_subquery, void *args) override { return (arg && arg->walk(processor, walk_subquery, args)) || (this->*processor)(args); } Item *transform(THD *thd, Item_transformer transformer, uchar *args) override; Item *derived_field_transformer_for_having(THD *thd, uchar *arg) override { return NULL; } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) override { return NULL; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; /** See comments on @see Item::associate_with_target_field for method description */ bool associate_with_target_field(THD *thd, Item_field *field) override; protected: Item *shallow_copy(THD *thd) const override { Item_default_value *new_item= (Item_default_value *) get_item_copy<Item_default_value>(thd, this); // This is a copy so do not manage the field and should not delete it new_item->m_share_field= 1; return new_item; } Item* deep_copy(THD *thd) const override { Item_default_value *copy= (Item_default_value *) shallow_copy_with_checks(thd); if (!copy || (arg && !(copy->arg= arg->deep_copy_with_checks(thd)))) return NULL; return copy; } private: bool tie_field(THD *thd); }; class Item_contextually_typed_value_specification: public Item { public: Item_contextually_typed_value_specification(THD *thd) :Item(thd) { } Type type() const override { return CONTEXTUALLY_TYPED_VALUE_ITEM; } bool vcol_assignment_allowed_value() const override { return true; } bool eq(const Item *item, const Eq_config &config) const override { return false; } bool is_evaluable_expression() const override { return false; } Field *create_tmp_field_ex(MEM_ROOT *, TABLE *, Tmp_field_src *, const Tmp_field_param *) override { DBUG_ASSERT(0); return NULL; } String *val_str(String *str) override { DBUG_ASSERT(0); // never should be called null_value= true; return 0; } double val_real() override { DBUG_ASSERT(0); // never should be called null_value= true; return 0.0; } longlong val_int() override { DBUG_ASSERT(0); // never should be called null_value= true; return 0; } my_decimal *val_decimal(my_decimal *) override { DBUG_ASSERT(0); // never should be called null_value= true; return 0; } bool get_date(THD *, MYSQL_TIME *, date_mode_t) override { DBUG_ASSERT(0); // never should be called return (null_value= true); } bool send(Protocol *, st_value *) override { DBUG_ASSERT(0); return true; } const Type_handler *type_handler() const override { DBUG_ASSERT(0); return &type_handler_null; } }; /* <default specification> ::= DEFAULT */ class Item_default_specification: public Item_contextually_typed_value_specification { public: Item_default_specification(THD *thd) :Item_contextually_typed_value_specification(thd) { } void print(String *str, enum_query_type) override { str->append(STRING_WITH_LEN("default")); } bool check_assignability_to(const Field *to, bool ignore) const override { return false; } int save_in_field(Field *field_arg, bool) override { return field_arg->save_in_field_default_value(false); } bool save_in_param(THD *, Item_param *param) override { param->set_default(true); return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_default_specification>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /** This class is used as bulk parameter INGNORE representation. It just do nothing when assigned to a field This is a non-standard MariaDB extension. */ class Item_ignore_specification: public Item_contextually_typed_value_specification { public: Item_ignore_specification(THD *thd) :Item_contextually_typed_value_specification(thd) { } void print(String *str, enum_query_type) override { str->append(STRING_WITH_LEN("ignore")); } bool check_assignability_to(const Field *to, bool ignore) const override { return false; } int save_in_field(Field *field_arg, bool) override { return field_arg->save_in_field_ignore_value(false); } bool save_in_param(THD *, Item_param *param) override { param->set_ignore(true); return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_ignore_specification>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* Item_insert_value -- an implementation of VALUES() function. You can use the VALUES(col_name) function in the UPDATE clause to refer to column values from the INSERT portion of the INSERT ... UPDATE statement. In other words, VALUES(col_name) in the UPDATE clause refers to the value of col_name that would be inserted, had no duplicate-key conflict occurred. In all other places this function returns NULL. */ class Item_insert_value : public Item_field { public: Item *arg; Item_insert_value(THD *thd, Name_resolution_context *context_arg, Item *a) :Item_field(thd, context_arg), arg(a) {} bool eq(const Item *item, const Eq_config &config) const override; bool fix_fields(THD *, Item **) override; void print(String *str, enum_query_type query_type) override; int save_in_field(Field *field_arg, bool no_conversions) override { return Item_field::save_in_field(field_arg, no_conversions); } Type type() const override { return INSERT_VALUE_ITEM; } /* We use RAND_TABLE_BIT to prevent Item_insert_value from being treated as a constant and precalculated before execution */ table_map used_tables() const override { return RAND_TABLE_BIT; } Item_field *field_for_view_update() override { return nullptr; } bool walk(Item_processor processor, bool walk_subquery, void *args) override { return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); } bool check_partition_func_processor(void *) override { return true; } bool update_vcol_processor(void *) override { return false; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("value()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_insert_value>(thd, this); } }; class Table_triggers_list; /* Represents NEW/OLD version of field of row which is changed/read in trigger. Note: For this item main part of actual binding to Field object happens not during fix_fields() call (like for Item_field) but right after parsing of trigger definition, when table is opened, with special setup_field() call. On fix_fields() stage we simply choose one of two Field instances representing either OLD or NEW version of this field. */ class Item_trigger_field : public Item_field, private Settable_routine_parameter { private: GRANT_INFO *table_grants; public: /* Next in list of all Item_trigger_field's in trigger */ Item_trigger_field *next_trg_field; /** Pointer to the next list of Item_trigger_field objects. This pointer is used to organize an intrusive list of lists of Item_trigger_field objects managed by sp_head. */ SQL_I_List<Item_trigger_field> *next_trig_field_list; /* Pointer to Table_trigger_list object for table of this trigger */ Table_triggers_list *triggers; /* Is this item represents row from NEW or OLD row ? */ enum __attribute__((packed)) row_version_type {OLD_ROW, NEW_ROW}; row_version_type row_version; /* Index of the field in the TABLE::field array */ field_index_t field_idx; private: /* Trigger field is read-only unless it belongs to the NEW row in a BEFORE INSERT of BEFORE UPDATE trigger. */ bool read_only; /* '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). */ privilege_t original_privilege; privilege_t want_privilege; public: Item_trigger_field(THD *thd, Name_resolution_context *context_arg, row_version_type row_ver_arg, const LEX_CSTRING &field_name_arg, privilege_t priv, const bool ro) :Item_field(thd, context_arg, field_name_arg), table_grants(nullptr), next_trg_field(nullptr), next_trig_field_list(nullptr), triggers(nullptr), row_version(row_ver_arg), field_idx(NO_CACHED_FIELD_INDEX), read_only (ro), original_privilege(priv), want_privilege(priv) { } void setup_field(THD *thd, TABLE *table, GRANT_INFO *table_grant_info); Type type() const override { return TRIGGER_FIELD_ITEM; } bool eq(const Item *item, const Eq_config &config) const override; bool fix_fields(THD *, Item **) override; void print(String *str, enum_query_type query_type) override; table_map used_tables() const override { return (table_map)0L; } Field *get_tmp_table_field() override { return nullptr; } Item *copy_or_same(THD *) override { return this; } Item *get_tmp_table_item(THD *thd) override { return copy_or_same(thd); } void cleanup() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_trigger_field>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } private: void set_required_privilege(bool rw) override; bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; public: Settable_routine_parameter *get_settable_routine_parameter() override { return read_only ? nullptr : this; } bool set_value(THD *thd, Item **it) { return set_value(thd, NULL, it); } public: bool unknown_splocal_processor(void *) override { return false; } bool check_vcol_func_processor(void *arg) override; }; /** @todo Implement the is_null() method for this class. Currently calling is_null() on any Item_cache object resolves to Item::is_null(), which returns FALSE for any value. */ class Item_cache: public Item_fixed_hybrid, public Type_handler_hybrid_field_type { protected: Item *example; /** Field that this object will get value from. This is used by index-based subquery engines to detect and remove the equality injected by IN->EXISTS transformation. */ Field *cached_field; /* TRUE <=> cache holds value of the last stored item (i.e actual value). store() stores item to be cached and sets this flag to FALSE. On the first call of val_xxx function if this flag is set to FALSE the cache_value() will be called to actually cache value of saved item. cache_value() will set this flag to TRUE. */ bool value_cached; table_map used_table_map; public: /* This is set if at least one of the values of a sub query is NULL Item_cache_row returns this with null_inside(). For not row items, it's set to the value of null_value It is set after cache_value() is called. */ bool null_value_inside; Item_cache(THD *thd): Item_fixed_hybrid(thd), Type_handler_hybrid_field_type(&type_handler_string), example(0), cached_field(0), value_cached(0), used_table_map(0) { set_maybe_null(); null_value= 1; null_value_inside= true; quick_fix_field(); } protected: Item_cache(THD *thd, const Type_handler *handler): Item_fixed_hybrid(thd), Type_handler_hybrid_field_type(handler), example(0), cached_field(0), value_cached(0), used_table_map(0) { set_maybe_null(); null_value= 1; null_value_inside= true; quick_fix_field(); } public: virtual bool allocate(THD *thd, uint i) { return 0; } virtual bool setup(THD *thd, Item *item) { example= item; Type_std_attributes::set(item); base_flags|= item->base_flags & item_base_t::IS_COND; if (item->type() == FIELD_ITEM) cached_field= ((Item_field *)item)->field; return 0; }; void set_used_tables(table_map map) { used_table_map= map; } table_map used_tables() const override { return used_table_map; } Type type() const override { return CACHE_ITEM; } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return create_tmp_field_ex_simple(root, table, src, param); } virtual void keep_array() {} #ifndef DBUG_OFF bool is_array_kept() { return TRUE; } #endif void print(String *str, enum_query_type query_type) override; bool eq_def(const Field *field) { return cached_field ? cached_field->eq_def (field) : FALSE; } bool eq(const Item *item, const Eq_config &config) const override { return this == item; } bool check_vcol_func_processor(void *arg) override { if (example) { Item::vcol_func_processor_result *res= (Item::vcol_func_processor_result*) arg; example->check_vcol_func_processor(arg); /* Item_cache of a non-deterministic function requires re-fixing even if the function itself doesn't (e.g. CURRENT_TIMESTAMP) */ if (res->errors & VCOL_NOT_STRICTLY_DETERMINISTIC) res->errors|= VCOL_SESSION_FUNC; return false; } return mark_unsupported_function("cache", arg, VCOL_IMPOSSIBLE); } bool fix_fields(THD *thd, Item **ref) override { quick_fix_field(); if (example && !example->fixed()) return example->fix_fields(thd, ref); return 0; } void cleanup() override { clear(); Item_fixed_hybrid::cleanup(); } /** Check if saved item has a non-NULL value. Will cache value of saved item if not already done. @return TRUE if cached value is non-NULL. */ bool has_value() { return (value_cached || cache_value()) && !null_value; } virtual void store(Item *item); virtual Item *get_item() { return example; } virtual bool cache_value()= 0; bool basic_const_item() const override { return example && example->basic_const_item(); } virtual void clear() { null_value= TRUE; value_cached= FALSE; } bool is_null() override { return !has_value(); } bool is_expensive() override { if (value_cached) return false; return example->is_expensive(); } bool is_expensive_processor(void *arg) override { DBUG_ASSERT(example); if (value_cached) return false; return example->is_expensive_processor(arg); } virtual void set_null(); bool walk(Item_processor processor, bool walk_subquery, void *arg) override { if (arg == STOP_PTR) return FALSE; if (example && example->walk(processor, walk_subquery, arg)) return TRUE; return (this->*processor)(arg); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; void split_sum_func2_example(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) { example->split_sum_func2(thd, ref_pointer_array, fields, &example, flags); } Item *get_example() const { return example; } virtual Item *convert_to_basic_const_item(THD *thd) { return 0; }; Item *derived_field_transformer_for_having(THD *thd, uchar *) override { return convert_to_basic_const_item(thd); } Item *derived_field_transformer_for_where(THD *thd, uchar *) override { return convert_to_basic_const_item(thd); } Item *grouping_field_transformer_for_where(THD *thd, uchar *) override { return convert_to_basic_const_item(thd); } Item *in_subq_field_transformer_for_where(THD *thd, uchar *) override { return convert_to_basic_const_item(thd); } Item *in_subq_field_transformer_for_having(THD *thd, uchar *) override { return convert_to_basic_const_item(thd); } }; class Item_cache_int: public Item_cache { protected: longlong value; public: Item_cache_int(THD *thd, const Type_handler *handler): Item_cache(thd, handler), value(0) {} double val_real() override; longlong val_int() override; String* val_str(String *str) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_int(thd, ltime, fuzzydate); } bool cache_value() override; int save_in_field(Field *field, bool no_conversions) override; Item *convert_to_basic_const_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_int>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_bool: public Item_cache_int { public: Item_cache_bool(THD *thd) :Item_cache_int(thd, &type_handler_bool) { } bool cache_value() override; bool val_bool() override { return !has_value() ? false : (bool) value; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return Item_cache_bool::val_bool(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_bool>(thd, this); } }; class Item_cache_year: public Item_cache_int { public: Item_cache_year(THD *thd, const Type_handler *handler) :Item_cache_int(thd, handler) { } bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) override { return type_handler_year.Item_get_date_with_warn(thd, this, to, mode); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_temporal: public Item_cache_int { protected: Item_cache_temporal(THD *thd, const Type_handler *handler); public: bool cache_value() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; int save_in_field(Field *field, bool no_conversions) override; bool setup(THD *thd, Item *item) override { if (Item_cache_int::setup(thd, item)) return true; set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); return false; } void store_packed(longlong val_arg, Item *example); /* Having a clone_constant method tells optimizer that this object is a constant and need not be optimized further. Important when storing packed datetime values. */ Item *clone_constant(THD *thd) const override; Item *convert_to_basic_const_item(THD *thd) override; virtual Item *make_literal(THD *) =0; }; class Item_cache_time: public Item_cache_temporal { public: Item_cache_time(THD *thd) :Item_cache_temporal(thd, &type_handler_time2) { } bool cache_value() override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_time>(thd, this); } Item *make_literal(THD *) override; longlong val_datetime_packed(THD *thd) override { Datetime::Options_cmp opt(thd); return has_value() ? Datetime(thd, this, opt).to_packed() : 0; } longlong val_time_packed(THD *) override { return has_value() ? value : 0; } longlong val_int() override { return has_value() ? Time(this).to_longlong() : 0; } double val_real() override { return has_value() ? Time(this).to_double() : 0; } String *val_str(String *to) override { return has_value() ? Time(this).to_string(to, decimals) : NULL; } my_decimal *val_decimal(my_decimal *to) override { return has_value() ? Time(this).to_decimal(to) : NULL; } bool val_native(THD *thd, Native *to) override { return has_value() ? Time(thd, this).to_native(to, decimals) : true; } }; class Item_cache_datetime: public Item_cache_temporal { public: Item_cache_datetime(THD *thd) :Item_cache_temporal(thd, &type_handler_datetime2) { } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_datetime>(thd, this); } public: Item *make_literal(THD *) override; longlong val_datetime_packed(THD *) override { return has_value() ? value : 0; } longlong val_time_packed(THD *thd) override { return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_int() override { return has_value() ? Datetime(this).to_longlong() : 0; } double val_real() override { return has_value() ? Datetime(this).to_double() : 0; } String *val_str(String *to) override { return has_value() ? Datetime(this).to_string(to, decimals) : NULL; } my_decimal *val_decimal(my_decimal *to) override { return has_value() ? Datetime(this).to_decimal(to) : NULL; } }; class Item_cache_date: public Item_cache_temporal { public: Item_cache_date(THD *thd) :Item_cache_temporal(thd, &type_handler_newdate) { } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_date>(thd, this); } public: Item *make_literal(THD *) override; longlong val_datetime_packed(THD *) override { return has_value() ? value : 0; } longlong val_time_packed(THD *thd) override { return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_int() override { return has_value() ? Date(this).to_longlong() : 0; } double val_real() override { return has_value() ? Date(this).to_double() : 0; } String *val_str(String *to) override { return has_value() ? Date(this).to_string(to) : NULL; } my_decimal *val_decimal(my_decimal *to) override { return has_value() ? Date(this).to_decimal(to) : NULL; } }; class Item_cache_timestamp: public Item_cache { Timestamp_or_zero_datetime_native m_native; Datetime to_datetime(THD *thd); public: Item_cache_timestamp(THD *thd) :Item_cache(thd, &type_handler_timestamp2) { } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_timestamp>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } public: bool cache_value() override; String* val_str(String *to) override { return to_datetime(current_thd).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return to_datetime(current_thd).to_decimal(to); } longlong val_int() override { return to_datetime(current_thd).to_longlong(); } double val_real() override { return to_datetime(current_thd).to_double(); } longlong val_datetime_packed(THD *thd) override { return to_datetime(thd).to_packed(); } longlong val_time_packed(THD *) override { DBUG_ASSERT(0); return 0; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; int save_in_field(Field *field, bool no_conversions) override; bool val_native(THD *thd, Native *to) override; }; class Item_cache_real: public Item_cache { protected: double value; public: Item_cache_real(THD *thd, const Type_handler *h) :Item_cache(thd, h), value(0) {} double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_real(thd, ltime, fuzzydate); } bool cache_value() override; Item *convert_to_basic_const_item(THD *thd) override; }; class Item_cache_double: public Item_cache_real { public: Item_cache_double(THD *thd) :Item_cache_real(thd, &type_handler_double) { } String *val_str(String *str) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_double>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_float: public Item_cache_real { public: Item_cache_float(THD *thd) :Item_cache_real(thd, &type_handler_float) { } String *val_str(String *str) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_float>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_decimal: public Item_cache { protected: my_decimal decimal_value; public: Item_cache_decimal(THD *thd): Item_cache(thd, &type_handler_newdecimal) {} double val_real() override; longlong val_int() override; String* val_str(String *str) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) override { return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, NULL, NULL); } bool cache_value() override; Item *convert_to_basic_const_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_decimal>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_str: public Item_cache { char buffer[STRING_BUFFER_USUAL_SIZE]; String *value, value_buff; bool is_varbinary; public: Item_cache_str(THD *thd, const Item *item): Item_cache(thd, item->type_handler()), value(0), is_varbinary(item->type() == FIELD_ITEM && Item_cache_str::field_type() == MYSQL_TYPE_VARCHAR && !((const Item_field *) item)->field->has_charset()) { collation.set(const_cast<DTCollation&>(item->collation)); } double val_real() override; longlong val_int() override; String* val_str(String *) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_string(thd, ltime, fuzzydate); } CHARSET_INFO *charset() const { return value->charset(); }; int save_in_field(Field *field, bool no_conversions) override; bool cache_value() override; Item *convert_to_basic_const_item(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_str>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_str_for_nullif: public Item_cache_str { public: Item_cache_str_for_nullif(THD *thd, const Item *item) :Item_cache_str(thd, item) { } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { /** Item_cache_str::safe_charset_converter() returns a new Item_cache with Item_func_conv_charset installed on "example". The original Item_cache is not referenced (neither directly nor recursively) from the result of Item_cache_str::safe_charset_converter(). For NULLIF() purposes we need a different behavior: we need a new instance of Item_func_conv_charset, with the original Item_cache referenced in args[0]. See MDEV-9181. */ return Item::safe_charset_converter(thd, tocs); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_str_for_nullif>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; class Item_cache_row: public Item_cache { Item_cache **values; uint item_count; bool save_array; public: Item_cache_row(THD *thd): Item_cache(thd, &type_handler_row), values(0), item_count(2), save_array(0) {} /* 'allocate' used only in row transformer, to preallocate space for row cache. */ bool allocate(THD *thd, uint num) override; /* 'setup' is needed only by row => it not called by simple row subselect (only by IN subselect (in subselect optimizer)) */ bool setup(THD *thd, Item *item) override; void store(Item *item) override; void illegal_method_call(const char *); void make_send_field(THD *, Send_field *) override { illegal_method_call("make_send_field"); }; double val_real() override { illegal_method_call("val"); return 0; }; longlong val_int() override { illegal_method_call("val_int"); return 0; }; String *val_str(String *) override { illegal_method_call("val_str"); return nullptr; }; my_decimal *val_decimal(my_decimal *) override { illegal_method_call("val_decimal"); return nullptr; }; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { illegal_method_call("val_decimal"); return true; } uint cols() const override { return item_count; } Item *element_index(uint i) override { return values[i]; } Item **addr(uint i) override { return (Item **) (values + i); } bool check_cols(uint c) override; bool null_inside() override; void bring_value() override; void keep_array() override { save_array= 1; } #ifndef DBUG_OFF bool is_array_kept() { return save_array; } #endif void cleanup() override { DBUG_ENTER("Item_cache_row::cleanup"); Item_cache::cleanup(); if (!save_array) values= 0; DBUG_VOID_RETURN; } bool cache_value() override; void set_null() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_cache_row>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* Item_type_holder used to store type. name, length of Item for UNIONS & derived tables. Item_type_holder do not need cleanup() because its time of live limited by single SP/PS execution. */ class Item_type_holder: public Item, public Type_handler_hybrid_field_type { protected: const TYPELIB *enum_set_typelib; public: Item_type_holder(THD *thd, Item *item, const Type_handler *handler, const Type_all_attributes *attr, bool maybe_null_arg) :Item(thd), Type_handler_hybrid_field_type(handler), enum_set_typelib(attr->get_typelib()) { name= item->name; Type_std_attributes::set(*attr); set_maybe_null(maybe_null_arg); copy_flags(item, item_base_t::IS_EXPLICIT_NAME | item_base_t::IS_IN_WITH_CYCLE); } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler()-> type_handler_for_item_field(); } const Type_handler *real_type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } Type type() const override { return TYPE_HOLDER; } const TYPELIB *get_typelib() const override { return enum_set_typelib; } /* When handling a query like this: VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin); Item_type_holder can be passed to Type_handler_xxx::Item_hybrid_func_fix_attributes() We don't want the latter to perform character set conversion of a Item_type_holder by calling its val_str(), which calls DBUG_ASSERT(0). Let's override const_item() and is_expensive() to avoid this. Note, Item_hybrid_func_fix_attributes() could probably have a new argument to distinguish what we need: - (a) aggregate data type attributes only - (b) install converters after attribute aggregation So st_select_lex_unit::join_union_type_attributes() could ask it to do (a) only, without (b). */ bool const_item() const override { return false; } bool is_expensive() override { return true; } double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal *) override; String *val_str(String*) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { return Item_type_holder::real_type_handler()-> make_and_init_table_field(root, &name, Record_addr(maybe_null()), *this, table); } protected: Item *shallow_copy(THD *) const override { return nullptr; } Item *deep_copy(THD *) const override { return nullptr; } }; class st_select_lex; void mark_select_range_as_dependent(THD *thd, st_select_lex *last_select, st_select_lex *current_sel, Field *found_field, Item *found_item, Item_ident *resolved_item, bool suppress_warning_output); extern Cached_item *new_Cached_item(THD *thd, Item *item, bool pass_through_ref); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item); extern const String my_null_string; /** Interface for Item iterator */ class Item_iterator { public: /** Shall set this iterator to the position before the first item @note This method also may perform some other initialization actions like allocation of certain resources. */ virtual void open()= 0; /** Shall return the next Item (or NULL if there is no next item) and move pointer to position after it. */ virtual Item *next()= 0; /** Shall force iterator to free resources (if it holds them) @note One should not use the iterator without open() call after close() */ virtual void close()= 0; virtual ~Item_iterator() = default; }; /** Item iterator over List_iterator_fast for Item references */ class Item_iterator_ref_list: public Item_iterator { List_iterator<Item*> list; public: Item_iterator_ref_list(List_iterator<Item*> &arg_list): list(arg_list) {} void open() override { list.rewind(); } Item *next() override { return *(list++); } void close() override {} }; /** Item iterator over List_iterator_fast for Items */ class Item_iterator_list: public Item_iterator { List_iterator<Item> list; public: Item_iterator_list(List_iterator<Item> &arg_list): list(arg_list) {} void open() override { list.rewind(); } Item *next() override { return (list++); } void close() override {} }; /** Item iterator over Item interface for rows */ class Item_iterator_row: public Item_iterator { Item *base_item; uint current; public: Item_iterator_row(Item *base) : base_item(base), current(0) {} void open() override { current= 0; } Item *next() override { if (current >= base_item->cols()) return NULL; return base_item->element_index(current++); } void close() override {} }; /* fix_escape_item() sets the out "escape" parameter to: - native code in case of an 8bit character set - Unicode code point in case of a multi-byte character set The value meaning a not-initialized ESCAPE character must not be equal to any valid value, so must be outside of these ranges: - -128..+127, not to conflict with a valid 8bit charcter - 0..0x10FFFF, not to conflict with a valid Unicode code point The exact value does not matter. */ #define ESCAPE_NOT_INITIALIZED -1000 /* It's used in ::fix_fields() methods of LIKE and JSON_SEARCH functions to handle the ESCAPE parameter. This parameter is quite non-standard so the specific function. */ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str, bool escape_used_in_parsing, CHARSET_INFO *cmp_cs, int *escape); inline bool Virtual_column_info::is_equal(const Virtual_column_info* vcol, bool omit_table_names) const { return type_handler() == vcol->type_handler() && is_stored() == vcol->is_stored() && expr->eq(vcol->expr, {true, omit_table_names}); } inline void Virtual_column_info::print(String* str) { expr->print_for_table_def(str); } class Item_direct_ref_to_item : public Item_direct_ref { Item *m_item; public: Item_direct_ref_to_item(THD *thd, Item *item); void change_item(THD *thd, Item *); bool fix_fields(THD *thd, Item **it) override; void print(String *str, enum_query_type query_type) override; Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; Item *get_tmp_table_item(THD *thd) override { return m_item->get_tmp_table_item(thd); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_direct_ref_to_item>(thd, this); } public: COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override { return m_item->build_equal_items(thd, inherited, link_item_fields, cond_equal_ref); } LEX_CSTRING full_name_cstring() const override { return m_item->full_name_cstring(); } void make_send_field(THD *thd, Send_field *field) override { m_item->make_send_field(thd, field); } bool eq(const Item *item, const Eq_config &config) const override { const Item *it= item->real_item(); return m_item->eq(it, config); } void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge) override { m_item->fix_after_pullout(new_parent, &m_item, merge); } void save_val(Field *to) override { return m_item->save_val(to); } void save_result(Field *to) override { return m_item->save_result(to); } int save_in_field(Field *to, bool no_conversions) override { return m_item->save_in_field(to, no_conversions); } const Type_handler *type_handler() const override { return m_item->type_handler(); } table_map used_tables() const override { return m_item->used_tables(); } void update_used_tables() override { m_item->update_used_tables(); } bool const_item() const override { return m_item->const_item(); } table_map not_null_tables() const override { return m_item->not_null_tables(); } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { return m_item->walk(processor, walk_subquery, arg) || (this->*processor)(arg); } bool enumerate_field_refs_processor(void *arg) override { return m_item->enumerate_field_refs_processor(arg); } Item_field *field_for_view_update() override { return m_item->field_for_view_update(); } /* Row emulation: forwarding of ROW-related calls to orig_item */ uint cols() const override { return m_item->cols(); } Item* element_index(uint i) override { return this; } Item** addr(uint i) override { return &m_item; } bool check_cols(uint c) override { return Item::check_cols(c); } bool null_inside() override { return m_item->null_inside(); } void bring_value() override {} Item_equal *get_item_equal() override { return m_item->get_item_equal(); } void set_item_equal(Item_equal *item_eq) override { m_item->set_item_equal(item_eq); } Item_equal *find_item_equal(COND_EQUAL *cond_equal) override { return m_item->find_item_equal(cond_equal); } Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { return m_item->propagate_equal_fields(thd, ctx, cond); } Item *replace_equal_field(THD *thd, uchar *arg) override { return m_item->replace_equal_field(thd, arg); } bool excl_dep_on_table(table_map tab_map) override { return m_item->excl_dep_on_table(tab_map); } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { return m_item->excl_dep_on_grouping_fields(sel); } bool is_expensive() override { return m_item->is_expensive(); } void set_item(Item *item) { m_item= item; } Item *deep_copy(THD *thd) const override { Item *clone_item= m_item->deep_copy_with_checks(thd); if (clone_item) { Item_direct_ref_to_item *copy= (Item_direct_ref_to_item *) shallow_copy_with_checks(thd); if (!copy) return 0; copy->set_item(clone_item); return copy; } return 0; } void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override { m_item->split_sum_func(thd, ref_pointer_array, fields, flags); } /* This processor states that this is safe for virtual columns (because this Item transparency) */ bool check_vcol_func_processor(void *arg) override { return FALSE;} }; inline bool TABLE::mark_column_with_deps(Field *field) { bool res; if (!(res= bitmap_fast_test_and_set(read_set, field->field_index))) { if (field->vcol_info) mark_virtual_column_deps(field); } return res; } inline bool TABLE::mark_virtual_column_with_deps(Field *field) { bool res; DBUG_ASSERT(field->vcol_info); if (!(res= bitmap_fast_test_and_set(read_set, field->field_index))) mark_virtual_column_deps(field); return res; } inline void TABLE::mark_virtual_column_deps(Field *field) { DBUG_ASSERT(field->vcol_info); DBUG_ASSERT(field->vcol_info->expr); field->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0); } inline void TABLE::use_all_stored_columns() { bitmap_set_all(read_set); if (Field **vf= vfield) for (; *vf; vf++) bitmap_clear_bit(read_set, (*vf)->field_index); } #endif /* SQL_ITEM_INCLUDED */ ft_global.h 0000644 00000006051 15156036161 0006654 0 ustar 00 /* Copyright (c) 2000-2005, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Written by Sergei A. Golubchik, who has a shared copyright to this code */ /* some definitions for full-text indices */ /* #include "myisam.h" */ #ifndef _ft_global_h #define _ft_global_h #ifdef __cplusplus extern "C" { #endif #include <my_compare.h> #define HA_FT_MAXBYTELEN 254 #define HA_FT_MAXCHARLEN (HA_FT_MAXBYTELEN/3) #define DEFAULT_FTB_SYNTAX "+ -><()~*:\"\"&|" typedef struct st_ft_info FT_INFO; struct _ft_vft { int (*read_next)(FT_INFO *, char *); float (*find_relevance)(FT_INFO *, uchar *, uint); void (*close_search)(FT_INFO *); float (*get_relevance)(FT_INFO *); void (*reinit_search)(FT_INFO *); }; typedef struct st_ft_info_ext FT_INFO_EXT; struct _ft_vft_ext { uint (*get_version)(); // Extended API version ulonglong (*get_flags)(); ulonglong (*get_docid)(FT_INFO_EXT *); ulonglong (*count_matches)(FT_INFO_EXT *); }; /* Flags for extended FT API */ #define FTS_ORDERED_RESULT (1LL << 1) #define FTS_DOCID_IN_RESULT (1LL << 2) #define FTS_DOC_ID_COL_NAME "FTS_DOC_ID" #ifndef FT_CORE struct st_ft_info { struct _ft_vft *please; /* INTERCAL style :-) */ }; struct st_ft_info_ext { struct _ft_vft *please; /* INTERCAL style :-) */ struct _ft_vft_ext *could_you; }; #endif extern const char *ft_stopword_file; extern const char *ft_precompiled_stopwords[]; extern ulong ft_min_word_len; extern ulong ft_max_word_len; extern ulong ft_query_expansion_limit; extern const char *ft_boolean_syntax; extern struct st_mysql_ftparser ft_default_parser; int ft_init_stopwords(void); void ft_free_stopwords(void); #define FT_NL 0 #define FT_BOOL 1 #define FT_SORTED 2 #define FT_EXPAND 4 /* query expansion */ FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t, CHARSET_INFO *, uchar *); my_bool ft_boolean_check_syntax_string(const uchar *, size_t length, CHARSET_INFO *cs); /* Internal symbols for fulltext between maria and MyISAM */ #define HA_FT_WTYPE HA_KEYTYPE_FLOAT #define HA_FT_WLEN 4 #define FT_SEGS 2 #define ft_sintXkorr(A) mi_sint4korr(A) #define ft_intXstore(T,A) mi_int4store(T,A) extern const HA_KEYSEG ft_keysegs[FT_SEGS]; typedef union {int32 i; float f;} FT_WEIGTH; #ifdef __cplusplus } #endif #endif bounded_queue.h 0000644 00000013715 15156036161 0007554 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef BOUNDED_QUEUE_INCLUDED #define BOUNDED_QUEUE_INCLUDED #include "my_base.h" #include <my_sys.h> #include "queues.h" #include <string.h> class Sort_param; /** A priority queue with a fixed, limited size. This is a wrapper on top of QUEUE and the queue_xxx() functions. It keeps the top-N elements which are inserted. Elements of type Element_type are pushed into the queue. For each element, we call a user-supplied keymaker_function, to generate a key of type Key_type for the element. Instances of Key_type are compared with the user-supplied compare_function. The underlying QUEUE implementation needs one extra element for replacing the lowest/highest element when pushing into a full queue. */ template<typename Element_type, typename Key_type> class Bounded_queue { public: Bounded_queue() { memset(&m_queue, 0, sizeof(m_queue)); } ~Bounded_queue() { delete_queue(&m_queue); } /** Function for making sort-key from input data. @param param Sort parameters. @param to Where to put the key. @param from The input data. */ typedef uint (*keymaker_function)(Sort_param *param, Key_type *to, Element_type *from, bool packing_keys); /** Initialize the queue. @param max_elements The size of the queue. @param max_at_top Set to true if you want biggest element on top. false: We keep the n largest elements. pop() will return the smallest key in the result set. true: We keep the n smallest elements. pop() will return the largest key in the result set. @param compare_length Length of the data (i.e. the keys) used for sorting. @param keymaker Function which generates keys for elements. @param sort_param Sort parameters. @param sort_keys Array of pointers to keys to sort. @retval 0 OK, 1 Could not allocate memory. We do *not* take ownership of any of the input pointer arguments. */ int init(ha_rows max_elements, bool max_at_top, size_t compare_length, keymaker_function keymaker, Sort_param *sort_param, Key_type **sort_keys); /** Pushes an element on the queue. If the queue is already full, we discard one element. Calls keymaker_function to generate a key for the element. @param element The element to be pushed. */ void push(Element_type *element); /** Removes the top element from the queue. @retval Pointer to the (key of the) removed element. @note This function is for unit testing, where we push elements into to the queue, and test that the appropriate keys are retained. Interleaving of push() and pop() operations has not been tested. */ Key_type **pop() { // Don't return the extra element to the client code. if (queue_is_full((&m_queue))) queue_remove(&m_queue, 0); DBUG_ASSERT(m_queue.elements > 0); if (m_queue.elements == 0) return NULL; return reinterpret_cast<Key_type**>(queue_remove(&m_queue, 0)); } /** The number of elements in the queue. */ uint num_elements() const { return m_queue.elements; } /** Is the queue initialized? */ bool is_initialized() const { return m_queue.max_elements > 0; } private: Key_type **m_sort_keys; size_t m_compare_length; keymaker_function m_keymaker; Sort_param *m_sort_param; st_queue m_queue; }; template<typename Element_type, typename Key_type> int Bounded_queue<Element_type, Key_type>::init(ha_rows max_elements, bool max_at_top, size_t compare_length, keymaker_function keymaker, Sort_param *sort_param, Key_type **sort_keys) { DBUG_ASSERT(sort_keys != NULL); m_sort_keys= sort_keys; m_compare_length= compare_length; m_keymaker= keymaker; m_sort_param= sort_param; // init_queue() takes an uint, and also does (max_elements + 1) if (max_elements >= (UINT_MAX - 1)) return 1; // We allocate space for one extra element, for replace when queue is full. return init_queue(&m_queue, (uint) max_elements + 1, 0, max_at_top, get_ptr_compare(compare_length), &m_compare_length, 0, 0); } template<typename Element_type, typename Key_type> void Bounded_queue<Element_type, Key_type>::push(Element_type *element) { DBUG_ASSERT(is_initialized()); if (queue_is_full((&m_queue))) { // Replace top element with new key, and re-order the queue. Key_type **pq_top= reinterpret_cast<Key_type **>(queue_top(&m_queue)); (void)(*m_keymaker)(m_sort_param, *pq_top, element, false); queue_replace_top(&m_queue); } else { // Insert new key into the queue. (*m_keymaker)(m_sort_param, m_sort_keys[m_queue.elements], element, false); queue_insert(&m_queue, reinterpret_cast<uchar*>(&m_sort_keys[m_queue.elements])); } } #endif // BOUNDED_QUEUE_INCLUDED pfs_transaction_provider.h 0000644 00000005436 15156036161 0012040 0 ustar 00 /* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_TRANSACTION_PROVIDER_H #define PFS_TRANSACTION_PROVIDER_H /** @file include/pfs_transaction_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_TRANSACTION_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_TRANSACTION_CALL(M) pfs_ ## M ## _v1 C_MODE_START PSI_transaction_locker* pfs_get_thread_transaction_locker_v1(PSI_transaction_locker_state *state, const void *xid, ulonglong trxid, int isolation_level, my_bool read_only, my_bool autocommit); void pfs_start_transaction_v1(PSI_transaction_locker *locker, const char *src_file, uint src_line); void pfs_set_transaction_xid_v1(PSI_transaction_locker *locker, const void *xid, int xa_state); void pfs_set_transaction_xa_state_v1(PSI_transaction_locker *locker, int xa_state); void pfs_set_transaction_gtid_v1(PSI_transaction_locker *locker, const void *sid, const void *gtid_spec); void pfs_set_transaction_trxid_v1(PSI_transaction_locker *locker, const ulonglong *trxid); void pfs_inc_transaction_savepoints_v1(PSI_transaction_locker *locker, ulong count); void pfs_inc_transaction_rollback_to_savepoint_v1(PSI_transaction_locker *locker, ulong count); void pfs_inc_transaction_release_savepoint_v1(PSI_transaction_locker *locker, ulong count); void pfs_end_transaction_v1(PSI_transaction_locker *locker, my_bool commit); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_TRANSACTION_INTERFACE */ #endif sql_manager.h 0000644 00000001700 15156036162 0007211 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_MANAGER_INCLUDED #define SQL_MANAGER_INCLUDED void start_handle_manager(); void stop_handle_manager(); bool mysql_manager_submit(void (*action)(void *), void *data); #endif /* SQL_MANAGER_INCLUDED */ client_settings.h 0000644 00000003570 15156036162 0010125 0 ustar 00 /* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef CLIENT_SETTINGS_INCLUDED #define CLIENT_SETTINGS_INCLUDED #else #error You have already included an client_settings.h and it should not be included twice #endif /* CLIENT_SETTINGS_INCLUDED */ #include <sql_common.h> /* Note: CLIENT_CAPABILITIES is also defined in libmysql/client_settings.h. When adding capabilities here, consider if they should be also added to the libmysql version. */ #define CLIENT_CAPABILITIES (CLIENT_MYSQL | \ CLIENT_LONG_FLAG | \ CLIENT_TRANSACTIONS | \ CLIENT_PROTOCOL_41 | \ CLIENT_SECURE_CONNECTION | \ CLIENT_PLUGIN_AUTH | \ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ CLIENT_CONNECT_ATTRS) #define read_user_name(A) A[0]= 0 #undef _CUSTOMCONFIG_ #define mysql_server_init(a,b,c) mysql_client_plugin_init() #define mysql_server_end() mysql_client_plugin_deinit() #ifdef HAVE_REPLICATION C_MODE_START void slave_io_thread_detach_vio(); C_MODE_END #else #define slave_io_thread_detach_vio() #endif item_strfunc.h 0000644 00000230656 15156036162 0007440 0 ustar 00 #ifndef ITEM_STRFUNC_INCLUDED #define ITEM_STRFUNC_INCLUDED /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file defines all string functions */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif extern size_t username_char_length; class Item_str_func :public Item_func { protected: /** Sets the result value of the function an empty string, using the current character set. No memory is allocated. @retval A pointer to the str_value member. */ virtual String *make_empty_result(String *str) { /* Reset string length to an empty string. We don't use str_value.set() as we don't want to free and potentially have to reallocate the buffer for each call. */ if (!str->is_alloced()) str->set("", 0, collation.collation); /* Avoid null ptrs */ else { str->length(0); /* Reuse allocated area */ str->set_charset(collation.collation); } return str; } public: Item_str_func(THD *thd): Item_func(thd) { decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, Item *a): Item_func(thd, a) {decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) { decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_func(thd, a, b, c, d) { decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e): Item_func(thd, a, b, c, d, e) { decimals=NOT_FIXED_DEC; } Item_str_func(THD *thd, List<Item> &list): Item_func(thd, list) { decimals=NOT_FIXED_DEC; } longlong val_int() override; double val_real() override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_string(thd, ltime, fuzzydate); } const Type_handler *type_handler() const override { return string_type_handler(); } void left_right_max_length(); bool fix_fields(THD *thd, Item **ref) override; }; /* Functions that return values with ASCII repertoire */ class Item_str_ascii_func :public Item_str_func { String ascii_buf; public: Item_str_ascii_func(THD *thd): Item_str_func(thd) {} Item_str_ascii_func(THD *thd, Item *a): Item_str_func(thd, a) {} Item_str_ascii_func(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_str_ascii_func(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} String *val_str(String *str) override { return val_str_from_val_str_ascii(str, &ascii_buf); } String *val_str_ascii(String *) override= 0; }; /** Functions that return a checksum or a hash of the argument, or somehow else encode or decode the argument, returning an ASCII-repertoire string. */ class Item_str_ascii_checksum_func: public Item_str_ascii_func { public: Item_str_ascii_checksum_func(THD *thd, Item *a) :Item_str_ascii_func(thd, a) { } Item_str_ascii_checksum_func(THD *thd, Item *a, Item *b) :Item_str_ascii_func(thd, a, b) { } bool eq(const Item *item, const Eq_config &config) const override { // Always use binary argument comparison: MD5('x') != MD5('X') Eq_config new_config= config; new_config.binary_cmp= true; return Item_func::eq(item, new_config); } }; /** Functions that return a checksum or a hash of the argument, or somehow else encode or decode the argument, returning a binary string. */ class Item_str_binary_checksum_func: public Item_str_func { public: Item_str_binary_checksum_func(THD *thd, Item *a) :Item_str_func(thd, a) { } Item_str_binary_checksum_func(THD *thd, Item *a, Item *b) :Item_str_func(thd, a, b) { } Item_str_binary_checksum_func(THD *thd, Item *a, Item *b, Item *c) :Item_str_func(thd, a, b, c) { } Item_str_binary_checksum_func(THD *thd, Item *a, Item *b, Item *c, Item *d) :Item_str_func(thd, a, b, c, d) { } Item_str_binary_checksum_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item *e) :Item_str_func(thd, a, b, c, d, e) { } bool eq(const Item *item, const Eq_config &config) const override { /* Always use binary argument comparison: FROM_BASE64('test') != FROM_BASE64('TEST') */ Eq_config new_config= config; new_config.binary_cmp= true; return Item_func::eq(item, new_config); } }; class Item_func_md5 :public Item_str_ascii_checksum_func { public: Item_func_md5(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override { fix_length_and_charset(32, default_charset()); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("md5") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_md5>(thd, this); } }; class Item_func_sha :public Item_str_ascii_checksum_func { public: Item_func_sha(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sha") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sha>(thd, this); } }; class Item_func_sha2 :public Item_str_ascii_checksum_func { public: Item_func_sha2(THD *thd, Item *a, Item *b) :Item_str_ascii_checksum_func(thd, a, b) {} String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sha2") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sha2>(thd, this); } }; class Item_func_to_base64 :public Item_str_ascii_checksum_func { String tmp_value; public: Item_func_to_base64(THD *thd, Item *a) :Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("to_base64") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_to_base64>(thd, this); } }; class Item_func_from_base64 :public Item_str_binary_checksum_func { String tmp_value; public: Item_func_from_base64(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) { } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("from_base64") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_from_base64>(thd, this); } }; #include <my_crypt.h> class Item_aes_crypt :public Item_str_binary_checksum_func { void create_key(String *user_key, uchar* key); int parse_mode(); String tmp_value; const int what; uint aes_key_length; enum my_aes_mode aes_mode; public: Item_aes_crypt(THD *thd, int what, Item *a, Item *b) : Item_str_binary_checksum_func(thd, a, b), what(what) {} Item_aes_crypt(THD *thd, int what, Item *a, Item *b, Item *c) : Item_str_binary_checksum_func(thd, a, b, c), what(what) {} Item_aes_crypt(THD *thd, int what, Item *a, Item *b, Item *c, Item *d) : Item_str_binary_checksum_func(thd, a, b, c, d), what(what) {} bool fix_fields(THD *thd, Item **ref) override; String *val_str(String *) override; bool check_vcol_func_processor(void *arg) override { if (arg_count > 3) return FALSE; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } }; class Item_func_aes_encrypt :public Item_aes_crypt { public: Item_func_aes_encrypt(THD *thd, Item *a, Item *b) :Item_aes_crypt(thd, ENCRYPTION_FLAG_ENCRYPT, a, b) {} Item_func_aes_encrypt(THD *thd, Item *a, Item *b, Item *c) :Item_aes_crypt(thd, ENCRYPTION_FLAG_ENCRYPT, a, b, c) {} Item_func_aes_encrypt(THD *thd, Item *a, Item *b, Item *c, Item *d) :Item_aes_crypt(thd, ENCRYPTION_FLAG_ENCRYPT, a, b, c, d) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("aes_encrypt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_aes_encrypt>(thd, this); } }; class Item_func_aes_decrypt :public Item_aes_crypt { public: Item_func_aes_decrypt(THD *thd, Item *a, Item *b): Item_aes_crypt(thd, ENCRYPTION_FLAG_DECRYPT, a, b) {} Item_func_aes_decrypt(THD *thd, Item *a, Item *b, Item *c): Item_aes_crypt(thd, ENCRYPTION_FLAG_DECRYPT, a, b, c) {} Item_func_aes_decrypt(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_aes_crypt(thd, ENCRYPTION_FLAG_DECRYPT, a, b, c, d) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("aes_decrypt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_aes_decrypt>(thd, this); } }; class Item_func_kdf :public Item_str_binary_checksum_func { uint key_length; public: Item_func_kdf(THD *thd, Item *a, Item *b) : Item_str_binary_checksum_func(thd, a, b) {} Item_func_kdf(THD *thd, Item *a, Item *b, Item *c) : Item_str_binary_checksum_func(thd, a, b, c) {} Item_func_kdf(THD *thd, Item *a, Item *b, Item *c, Item *d) : Item_str_binary_checksum_func(thd, a, b, c, d) {} Item_func_kdf(THD *thd, Item *a, Item *b, Item *c, Item *d, Item *e) : Item_str_binary_checksum_func(thd, a, b, c, d, e) {} bool fix_length_and_dec(THD *thd) override; String *val_str(String *) override; bool check_vcol_func_processor(void *arg) override { if (arg_count > 4) return FALSE; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("kdf") }; return name; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_kdf>(thd, this); } }; class Item_func_natural_sort_key : public Item_str_func { public: Item_func_natural_sort_key(THD *thd, Item *a) : Item_str_func(thd, a){}; String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("natural_sort_key")}; return name; } bool fix_length_and_dec(THD *thd) override; Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_natural_sort_key>(thd, this); } bool check_vcol_func_processor(void *arg) override; }; class Item_func_concat :public Item_str_func { protected: String tmp_value; /* Append a non-NULL value to the result. @param [IN] thd - The current thread. @param [IN/OUT] res - The current val_str() return value. @param [IN] app - The value to be appended. @retval - false on success, true on error */ bool append_value(THD *thd, String *res, const String *app); bool realloc_result(String *str, uint length) const; public: Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {} Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("concat") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_concat>(thd, this); } }; /* This class handles the || operator in sql_mode=ORACLE. Unlike the traditional MariaDB concat(), it treats NULL arguments as ''. */ class Item_func_concat_operator_oracle :public Item_func_concat { public: Item_func_concat_operator_oracle(THD *thd, List<Item> &list) :Item_func_concat(thd, list) { } Item_func_concat_operator_oracle(THD *thd, Item *a, Item *b) :Item_func_concat(thd, a, b) { } String *val_str(String *) override; const Schema *schema() const override { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) override { if (query_type & QT_FOR_FRM) { // 10.3 downgrade compatibility for FRM str->append(STRING_WITH_LEN("concat_operator_oracle")); } else print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_concat_operator_oracle>(thd, this); } }; class Item_func_decode_histogram :public Item_str_func { public: Item_func_decode_histogram(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { collation.set(system_charset_info); max_length= MAX_BLOB_WIDTH; set_maybe_null(); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("decode_histogram") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_decode_histogram>(thd, this); } }; class Item_func_concat_ws :public Item_str_func { String tmp_value; public: Item_func_concat_ws(THD *thd, List<Item> &list): Item_str_func(thd, list) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("concat_ws") }; return name; } table_map not_null_tables() const override { return 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_concat_ws>(thd, this); } }; class Item_func_random_bytes : public Item_str_func { public: Item_func_random_bytes(THD *thd, Item *arg1) : Item_str_func(thd, arg1) {} bool fix_length_and_dec(THD *thd) override; void update_used_tables() override; String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("random_bytes")}; return name; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_random_bytes>(thd, this); } static const int MAX_RANDOM_BYTES= 1024; }; class Item_func_reverse :public Item_str_func { String tmp_value; public: Item_func_reverse(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("reverse") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_reverse>(thd, this); } }; class Item_func_replace :public Item_str_func { String tmp_value,tmp_value2; protected: String *val_str_internal(String *str, bool null_to_empty); public: Item_func_replace(THD *thd, Item *org, Item *find, Item *replace): Item_str_func(thd, org, find, replace) {} String *val_str(String *to) override { return val_str_internal(to, false); }; bool fix_length_and_dec(THD *thd) override; const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("replace") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_replace>(thd, this); } }; class Item_func_replace_oracle :public Item_func_replace { String tmp_emtpystr; public: Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace): Item_func_replace(thd, org, find, replace) {} String *val_str(String *to) override { return val_str_internal(to, true); }; const Schema *schema() const override { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) override { if (query_type & QT_FOR_FRM) { // 10.3 downgrade compatibility for FRM str->append(STRING_WITH_LEN("replace_oracle")); } else print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_replace_oracle>(thd, this); } }; class Item_func_regexp_replace :public Item_str_func { Regexp_processor_pcre re; bool append_replacement(String *str, const LEX_CSTRING *source, const LEX_CSTRING *replace); protected: String *val_str_internal(String *str, bool null_to_empty); public: Item_func_regexp_replace(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } void cleanup() override { DBUG_ENTER("Item_func_regexp_replace::cleanup"); Item_str_func::cleanup(); re.cleanup(); DBUG_VOID_RETURN; } String *val_str(String *str) override { return val_str_internal(str, false); } bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("regexp_replace") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; class Item_func_regexp_replace_oracle: public Item_func_regexp_replace { public: Item_func_regexp_replace_oracle(THD *thd, Item *a, Item *b, Item *c) :Item_func_regexp_replace(thd, a, b, c) {} const Schema *schema() const override { return &oracle_schema_ref; } bool fix_length_and_dec(THD *thd) override { bool rc= Item_func_regexp_replace::fix_length_and_dec(thd); set_maybe_null(); // Empty result is converted to NULL return rc; } String *val_str(String *str) override { return val_str_internal(str, true); } protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; class Item_func_regexp_substr :public Item_str_func { Regexp_processor_pcre re; public: Item_func_regexp_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} void cleanup() override { DBUG_ENTER("Item_func_regexp_substr::cleanup"); Item_str_func::cleanup(); re.cleanup(); DBUG_VOID_RETURN; } String *val_str(String *str) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("regexp_substr") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return nullptr; } }; class Item_func_insert :public Item_str_func { String tmp_value; public: Item_func_insert(THD *thd, Item *org, Item *start, Item *length, Item *new_str): Item_str_func(thd, org, start, length, new_str) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("insert") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_insert>(thd, this); } }; class Item_str_conv :public Item_str_func { protected: uint multiply; my_charset_conv_case converter; String tmp_value; public: Item_str_conv(THD *thd, Item *item): Item_str_func(thd, item) {} String *val_str(String *) override; }; class Item_func_lcase :public Item_str_conv { public: Item_func_lcase(THD *thd, Item *item): Item_str_conv(thd, item) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("lcase") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_lcase>(thd, this); } }; class Item_func_ucase :public Item_str_conv { public: Item_func_ucase(THD *thd, Item *item): Item_str_conv(thd, item) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ucase") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ucase>(thd, this); } }; class Item_func_left :public Item_str_func { String tmp_value; public: Item_func_left(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} bool hash_not_null(Hasher *hasher) override; String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("left") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_left>(thd, this); } }; class Item_func_right :public Item_str_func { String tmp_value; public: Item_func_right(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("right") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_right>(thd, this); } }; class Item_func_substr :public Item_str_func { String tmp_value; protected: virtual longlong get_position() { return args[1]->val_int(); } public: Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} Item_func_substr(THD *thd, List<Item> &list) :Item_str_func(thd, list) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("substr") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_substr>(thd, this); } }; class Item_func_sformat :public Item_str_func { String *val_arg; public: Item_func_sformat(THD *thd, List<Item> &list); ~Item_func_sformat() { delete [] val_arg; } String *val_str(String*) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sformat") }; return name; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sformat>(thd, this); } }; class Item_func_substr_oracle :public Item_func_substr { protected: longlong get_position() override { longlong pos= args[1]->val_int(); return pos == 0 ? 1 : pos; } String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_substr_oracle(THD *thd, Item *a, Item *b): Item_func_substr(thd, a, b) {} Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c): Item_func_substr(thd, a, b, c) {} Item_func_substr_oracle(THD *thd, List<Item> &list) :Item_func_substr(thd, list) {} bool fix_length_and_dec(THD *thd) override { bool res= Item_func_substr::fix_length_and_dec(thd); set_maybe_null(); return res; } const Schema *schema() const override { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) override { if (query_type & QT_FOR_FRM) { // 10.3 downgrade compatibility for FRM str->append(STRING_WITH_LEN("substr_oracle")); } else print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_substr_oracle>(thd, this); } }; class Item_func_substr_index :public Item_str_func { String tmp_value; public: Item_func_substr_index(THD *thd, Item *a,Item *b,Item *c): Item_str_func(thd, a, b, c) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("substring_index") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_substr_index>(thd, this); } }; class Item_func_trim :public Item_str_func { protected: String tmp_value; String remove; String *trimmed_value(String *res, uint32 offset, uint32 length) { if (length == 0) return make_empty_result(&tmp_value); tmp_value.set(*res, offset, length); /* Make sure to return correct charset and collation: TRIM(0x000000 FROM _ucs2 0x0061) should set charset to "binary" rather than to "ucs2". */ tmp_value.set_charset(collation.collation); return &tmp_value; } String *non_trimmed_value(String *res) { return trimmed_value(res, 0, res->length()); } public: Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {} Sql_mode_dependency value_depends_on_sql_mode() const override; String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; const Schema *schema() const override { return &mariadb_schema; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("trim") }; return name; } void print(String *str, enum_query_type query_type) override; virtual LEX_CSTRING mode_name() const { return { "both", 4}; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trim>(thd, this); } }; class Item_func_trim_oracle :public Item_func_trim { protected: String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_trim_oracle(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {} Item_func_trim_oracle(THD *thd, Item *a): Item_func_trim(thd, a) {} const Schema *schema() const override { return &oracle_schema_ref; } bool fix_length_and_dec(THD *thd) override { bool res= Item_func_trim::fix_length_and_dec(thd); set_maybe_null(); return res; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trim_oracle>(thd, this); } }; class Item_func_ltrim :public Item_func_trim { public: Item_func_ltrim(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {} Item_func_ltrim(THD *thd, Item *a): Item_func_trim(thd, a) {} Sql_mode_dependency value_depends_on_sql_mode() const override { return Item_func::value_depends_on_sql_mode(); } String *val_str(String *) override; const Schema *schema() const override { return &mariadb_schema; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ltrim") }; return name; } LEX_CSTRING mode_name() const override { return { STRING_WITH_LEN("leading") }; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ltrim>(thd, this); } }; class Item_func_ltrim_oracle :public Item_func_ltrim { protected: String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_ltrim_oracle(THD *thd, Item *a, Item *b): Item_func_ltrim(thd, a, b) {} Item_func_ltrim_oracle(THD *thd, Item *a): Item_func_ltrim(thd, a) {} const Schema *schema() const override { return &oracle_schema_ref; } bool fix_length_and_dec(THD *thd) override { bool res= Item_func_ltrim::fix_length_and_dec(thd); set_maybe_null(); return res; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ltrim_oracle>(thd, this); } }; class Item_func_rtrim :public Item_func_trim { public: Item_func_rtrim(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {} Item_func_rtrim(THD *thd, Item *a): Item_func_trim(thd, a) {} String *val_str(String *) override; const Schema *schema() const override { return &mariadb_schema; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rtrim") }; return name; } LEX_CSTRING mode_name() const override { return { STRING_WITH_LEN("trailing") }; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rtrim>(thd, this); } }; class Item_func_rtrim_oracle :public Item_func_rtrim { protected: String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_rtrim_oracle(THD *thd, Item *a, Item *b): Item_func_rtrim(thd, a, b) {} Item_func_rtrim_oracle(THD *thd, Item *a): Item_func_rtrim(thd, a) {} const Schema *schema() const override { return &oracle_schema_ref; } bool fix_length_and_dec(THD *thd) override { bool res= Item_func_rtrim::fix_length_and_dec(thd); set_maybe_null(); return res; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rtrim_oracle>(thd, this); } }; /* Item_func_password -- new (4.1.1) PASSWORD() function implementation. Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new password format, sha1(sha1(password) is so-called hash_stage2 value. Length of returned string is always 41 byte. To find out how entire authentication procedure works, see comments in password.c. */ class Item_func_password :public Item_str_ascii_checksum_func { public: enum PW_Alg {OLD, NEW}; private: char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1]; enum PW_Alg alg; bool deflt; public: Item_func_password(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a), alg(NEW), deflt(1) {} Item_func_password(THD *thd, Item *a, PW_Alg al): Item_str_ascii_checksum_func(thd, a), alg(al), deflt(0) {} String *val_str_ascii(String *str) override; bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override { fix_length_and_charset((alg == 1 ? SCRAMBLED_PASSWORD_CHAR_LENGTH : SCRAMBLED_PASSWORD_CHAR_LENGTH_323), default_charset()); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING password_normal= {STRING_WITH_LEN("password") }; static LEX_CSTRING password_old= {STRING_WITH_LEN("old_password") }; return (deflt || alg == 1) ? password_normal : password_old; } static char *alloc(THD *thd, const char *password, size_t pass_len, enum PW_Alg al); protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_password>(thd, this); } }; class Item_func_des_encrypt :public Item_str_binary_checksum_func { String tmp_value,tmp_arg; public: Item_func_des_encrypt(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} Item_func_des_encrypt(THD *thd, Item *a, Item *b) :Item_str_binary_checksum_func(thd, a, b) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("des_encrypt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_des_encrypt>(thd, this); } }; class Item_func_des_decrypt :public Item_str_binary_checksum_func { String tmp_value; public: Item_func_des_decrypt(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} Item_func_des_decrypt(THD *thd, Item *a, Item *b) :Item_str_binary_checksum_func(thd, a, b) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("des_decrypt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_des_decrypt>(thd, this); } }; /** QQ: Item_func_encrypt should derive from Item_str_ascii_checksum_func. However, it should be fixed to handle UCS2, UTF16, UTF32 properly first, as the underlying crypt() call expects a null-terminated input string. */ class Item_func_encrypt :public Item_str_binary_checksum_func { String tmp_value; /* Encapsulate common constructor actions */ void constructor_helper() { collation.set(&my_charset_bin); } public: Item_func_encrypt(THD *thd, Item *a): Item_str_binary_checksum_func(thd, a) { constructor_helper(); } Item_func_encrypt(THD *thd, Item *a, Item *b) :Item_str_binary_checksum_func(thd, a, b) { constructor_helper(); } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { set_maybe_null(); max_length = 13; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("encrypt") }; return name; } bool check_vcol_func_processor(void *arg) override { return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_encrypt>(thd, this); } }; #include "sql_crypt.h" class Item_func_encode :public Item_str_binary_checksum_func { private: /** Whether the PRNG has already been seeded. */ bool seeded; protected: SQL_CRYPT sql_crypt; public: Item_func_encode(THD *thd, Item *a, Item *seed_arg): Item_str_binary_checksum_func(thd, a, seed_arg) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("encode") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_encode>(thd, this); } virtual void crypto_transform(String *); private: /** Provide a seed for the PRNG sequence. */ bool seed(); }; class Item_func_decode :public Item_func_encode { public: Item_func_decode(THD *thd, Item *a, Item *seed_arg): Item_func_encode(thd, a, seed_arg) {} const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("decode") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_decode>(thd, this); } void crypto_transform(String *) override; }; class Item_func_sysconst :public Item_str_func { public: Item_func_sysconst(THD *thd): Item_str_func(thd) { collation.set(system_charset_info,DERIVATION_SYSCONST); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; /* Used to create correct Item name in new converted item in safe_charset_converter, return string representation of this function call */ virtual const char *fully_qualified_func_name() const = 0; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(fully_qualified_func_name(), arg, VCOL_SESSION_FUNC); } bool const_item() const override; }; class Item_func_database :public Item_func_sysconst { public: Item_func_database(THD *thd): Item_func_sysconst(thd) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { max_length= NAME_CHAR_LEN * system_charset_info->mbmaxlen; set_maybe_null(); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("database") }; return name; } const char *fully_qualified_func_name() const override { return "database()"; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_database>(thd, this); } }; class Item_func_sqlerrm :public Item_func_sysconst { public: Item_func_sqlerrm(THD *thd): Item_func_sysconst(thd) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("SQLERRM") }; return name; } const char *fully_qualified_func_name() const override { return "SQLERRM"; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); } bool fix_length_and_dec(THD *thd) override { max_length= 512 * system_charset_info->mbmaxlen; null_value= false; base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sqlerrm>(thd, this); } }; class Item_func_user :public Item_func_sysconst { protected: bool init (const char *user, const char *host); public: Item_func_user(THD *thd): Item_func_sysconst(thd) { str_value.set("", 0, system_charset_info); } String *val_str(String *) override { DBUG_ASSERT(fixed()); return (null_value ? 0 : &str_value); } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override { max_length= (uint32) (username_char_length + HOSTNAME_LENGTH + 1) * SYSTEM_CHARSET_MBMAXLEN; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("user") }; return name; } const char *fully_qualified_func_name() const override { return "user()"; } int save_in_field(Field *field, bool no_conversions) override { return save_str_value_in_field(field, &str_value); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_user>(thd, this); } }; class Item_func_current_user :public Item_func_user { Name_resolution_context *context; public: Item_func_current_user(THD *thd, Name_resolution_context *context_arg): Item_func_user(thd), context(context_arg) {} bool fix_fields(THD *thd, Item **ref) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("current_user") }; return name; } const char *fully_qualified_func_name() const override { return "current_user()"; } bool check_vcol_func_processor(void *arg) override { context= 0; return mark_unsupported_function(fully_qualified_func_name(), arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_current_user>(thd, this); } }; class Item_func_current_role :public Item_func_sysconst { Name_resolution_context *context; public: Item_func_current_role(THD *thd, Name_resolution_context *context_arg): Item_func_sysconst(thd), context(context_arg) {} bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override { max_length= (uint32) username_char_length * SYSTEM_CHARSET_MBMAXLEN; return FALSE; } int save_in_field(Field *field, bool no_conversions) override { return save_str_value_in_field(field, &str_value); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("current_role") }; return name; } const char *fully_qualified_func_name() const override { return "current_role()"; } String *val_str(String *) override { DBUG_ASSERT(fixed()); return null_value ? NULL : &str_value; } bool check_vcol_func_processor(void *arg) override { context= 0; return mark_unsupported_function(fully_qualified_func_name(), arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_current_role>(thd, this); } }; class Item_func_soundex :public Item_str_func { String tmp_value; public: Item_func_soundex(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("soundex") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_soundex>(thd, this); } }; class Item_func_elt :public Item_str_func { public: Item_func_elt(THD *thd, List<Item> &list): Item_str_func(thd, list) {} double val_real() override; longlong val_int() override; String *val_str(String *str) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("elt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_elt>(thd, this); } }; class Item_func_make_set :public Item_str_func { String tmp_str; public: Item_func_make_set(THD *thd, List<Item> &list): Item_str_func(thd, list) {} String *val_str(String *str) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("make_set") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_make_set>(thd, this); } }; class Item_func_format :public Item_str_ascii_func { const MY_LOCALE *locale; public: Item_func_format(THD *thd, Item *org, Item *dec): Item_str_ascii_func(thd, org, dec) {} Item_func_format(THD *thd, Item *org, Item *dec, Item *lang): Item_str_ascii_func(thd, org, dec, lang) {} String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("format") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_format>(thd, this); } }; class Item_func_char :public Item_str_func { public: Item_func_char(THD *thd, List<Item> &list): Item_str_func(thd, list) { collation.set(&my_charset_bin); } Item_func_char(THD *thd, List<Item> &list, CHARSET_INFO *cs): Item_str_func(thd, list) { collation.set(cs); } Item_func_char(THD *thd, Item *arg1, CHARSET_INFO *cs): Item_str_func(thd, arg1) { collation.set(cs); } String *val_str(String *) override; void append_char(String * str, int32 num); bool fix_length_and_dec(THD *thd) override { max_length= arg_count * 4; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("char") }; return name; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_char>(thd, this); } } ; class Item_func_chr :public Item_func_char { public: Item_func_chr(THD *thd, Item *arg1, CHARSET_INFO *cs): Item_func_char(thd, arg1, cs) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { max_length= 4; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("chr") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_chr>(thd, this); } }; class Item_func_repeat :public Item_str_func { String tmp_value; public: Item_func_repeat(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("repeat") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_repeat>(thd, this); } }; class Item_func_space :public Item_str_func { public: Item_func_space(THD *thd, Item *arg1): Item_str_func(thd, arg1) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("space") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_space>(thd, this); } }; class Item_func_binlog_gtid_pos :public Item_str_func { public: Item_func_binlog_gtid_pos(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("binlog_gtid_pos") }; return name; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_binlog_gtid_pos>(thd, this); } }; class Item_func_pad: public Item_str_func { protected: String tmp_value, pad_str; public: Item_func_pad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_str_func(thd, arg1, arg2, arg3) {} Item_func_pad(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} Item_func_pad(THD *thd, List<Item> &list): Item_str_func(thd,list) {} bool fix_length_and_dec(THD *thd) override; }; class Item_func_rpad :public Item_func_pad { public: Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_func_pad(thd, arg1, arg2, arg3) {} Item_func_rpad(THD *thd, Item *arg1, Item *arg2): Item_func_pad(thd, arg1, arg2) {} Item_func_rpad(THD *thd, List<Item> &list): Item_func_pad(thd,list) {} String *val_str(String *) override; const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rpad") }; return name; } Sql_mode_dependency value_depends_on_sql_mode() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rpad>(thd, this); } }; class Item_func_rpad_oracle :public Item_func_rpad { String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_func_rpad(thd, arg1, arg2, arg3) {} Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2): Item_func_rpad(thd, arg1, arg2) {} Item_func_rpad_oracle(THD *thd, List<Item> &list): Item_func_rpad(thd,list) {} bool fix_length_and_dec(THD *thd) override { bool res= Item_func_rpad::fix_length_and_dec(thd); set_maybe_null(); return res; } const Schema *schema() const override { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) override { if (query_type & QT_FOR_FRM) { // 10.3 downgrade compatibility for FRM str->append(STRING_WITH_LEN("rpad_oracle")); } else print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rpad_oracle>(thd, this); } }; class Item_func_lpad :public Item_func_pad { public: Item_func_lpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_func_pad(thd, arg1, arg2, arg3) {} Item_func_lpad(THD *thd, Item *arg1, Item *arg2): Item_func_pad(thd, arg1, arg2) {} Item_func_lpad(THD *thd, List<Item> &list): Item_func_pad(thd,list) {} String *val_str(String *) override; const Schema *schema() const override { return &mariadb_schema; } void print(String *str, enum_query_type query_type) override { print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("lpad") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_lpad>(thd, this); } }; class Item_func_lpad_oracle :public Item_func_lpad { String *make_empty_result(String *str) override { null_value= 1; return NULL; } public: Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_func_lpad(thd, arg1, arg2, arg3) {} Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2): Item_func_lpad(thd, arg1, arg2) {} Item_func_lpad_oracle(THD *thd, List<Item> &list): Item_func_lpad(thd,list) {} bool fix_length_and_dec(THD *thd) override { bool res= Item_func_lpad::fix_length_and_dec(thd); set_maybe_null(); return res; } const Schema *schema() const override { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) override { if (query_type & QT_FOR_FRM) { // 10.3 downgrade compatibility for FRM str->append(STRING_WITH_LEN("lpad_oracle")); } else print_sql_mode_qualified_name(str, query_type); print_args_parenthesized(str, query_type); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_lpad_oracle>(thd, this); } }; class Item_func_conv :public Item_str_func { public: Item_func_conv(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("conv") }; return name; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { collation.set(default_charset()); fix_char_length(65); set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_conv>(thd, this); } }; class Item_func_hex :public Item_str_ascii_checksum_func { protected: String tmp_value; /* Calling arg[0]->type_handler() can be expensive on every row. It's a virtual method, and in case if args[0] is a complex Item, its type_handler() can call more virtual methods. So let's cache it during fix_length_and_dec(). */ const Type_handler *m_arg0_type_handler; public: Item_func_hex(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a), m_arg0_type_handler(NULL) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("hex") }; return name; } String *val_str_ascii_from_val_int(String *str); String *val_str_ascii_from_val_real(String *str); String *val_str_ascii_from_val_str(String *str); String *val_str_ascii(String *str) override { DBUG_ASSERT(fixed()); return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str); } bool fix_length_and_dec(THD *thd) override { m_arg0_type_handler= args[0]->type_handler(); collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); decimals=0; /* Reserve space for 16 characters for signed numeric data types: hex(-1) -> 'FFFFFFFFFFFFFFFF'. For unsigned numeric types, HEX() can create too large columns. This should be eventually fixed to create minimum possible columns. */ const Type_handler_numeric *tn= dynamic_cast<const Type_handler_numeric*>(m_arg0_type_handler); size_t char_length= (tn && !(tn->flags() & UNSIGNED_FLAG)) ? (size_t) 16 : (size_t) args[0]->max_length * 2; fix_char_length(char_length); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_hex>(thd, this); } }; class Item_func_unhex :public Item_str_func { String tmp_value; public: Item_func_unhex(THD *thd, Item *a): Item_str_func(thd, a) { /* there can be bad hex strings */ set_maybe_null(); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("unhex") }; return name; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { collation.set(&my_charset_bin); decimals=0; max_length=(1+args[0]->max_length)/2; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_unhex>(thd, this); } }; #ifndef DBUG_OFF class Item_func_like_range :public Item_str_func { protected: String min_str; String max_str; const bool is_min; public: Item_func_like_range(THD *thd, Item *a, Item *b, bool is_min_arg): Item_str_func(thd, a, b), is_min(is_min_arg) { set_maybe_null(); } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { collation.set(args[0]->collation); decimals=0; max_length= MAX_BLOB_WIDTH; return FALSE; } }; class Item_func_like_range_min :public Item_func_like_range { public: Item_func_like_range_min(THD *thd, Item *a, Item *b): Item_func_like_range(thd, a, b, true) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("like_range_min") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_like_range_min>(thd, this); } }; class Item_func_like_range_max :public Item_func_like_range { public: Item_func_like_range_max(THD *thd, Item *a, Item *b): Item_func_like_range(thd, a, b, false) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("like_range_max") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_like_range_max>(thd, this); } }; #endif class Item_func_binary :public Item_str_func { public: Item_func_binary(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *a) override { DBUG_ASSERT(fixed()); String *tmp=args[0]->val_str(a); null_value=args[0]->null_value; if (tmp) tmp->set_charset(&my_charset_bin); return tmp; } bool fix_length_and_dec(THD *thd) override { collation.set(&my_charset_bin); max_length=args[0]->max_length; return FALSE; } void print(String *str, enum_query_type query_type) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_binary") }; return name; } bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_binary>(thd, this); } }; class Item_load_file :public Item_str_func { String tmp_value; public: Item_load_file(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("load_file") }; return name; } bool fix_length_and_dec(THD *thd) override { collation.set(&my_charset_bin, DERIVATION_COERCIBLE); set_maybe_null(); max_length=MAX_BLOB_WIDTH; return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_load_file>(thd, this); } }; class Item_func_export_set: public Item_str_func { public: Item_func_export_set(THD *thd, Item *a, Item *b, Item* c): Item_str_func(thd, a, b, c) {} Item_func_export_set(THD *thd, Item *a, Item *b, Item* c, Item* d): Item_str_func(thd, a, b, c, d) {} Item_func_export_set(THD *thd, Item *a, Item *b, Item* c, Item* d, Item* e): Item_str_func(thd, a, b, c, d, e) {} String *val_str(String *str) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("export_set") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_export_set>(thd, this); } }; class Item_func_quote :public Item_str_func { String tmp_value; public: Item_func_quote(THD *thd, Item *a): Item_str_func(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("quote") }; return name; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { collation.set(args[0]->collation); ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 + 2 * collation.collation->mbmaxlen; // NULL argument is returned as a string "NULL" without quotes if (args[0]->maybe_null()) set_if_bigger(max_result_length, 4 * collation.collation->mbmaxlen); max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_quote>(thd, this); } }; class Item_func_conv_charset :public Item_str_func { bool use_cached_value; String tmp_value; public: bool safe; Item_func_conv_charset(THD *thd, Item *a, CHARSET_INFO *cs): Item_str_func(thd, a) { collation.set(cs, DERIVATION_IMPLICIT); use_cached_value= 0; safe= 0; } Item_func_conv_charset(THD *thd, Item *a, CHARSET_INFO *cs, bool cache_if_const): Item_str_func(thd, a) { collation.set(cs, DERIVATION_IMPLICIT); if (cache_if_const && args[0]->can_eval_in_optimize()) { uint errors= 0; String tmp, *str= args[0]->val_str(&tmp); if (!str || str_value.copy(str->ptr(), str->length(), str->charset(), cs, &errors)) null_value= 1; use_cached_value= 1; str_value.mark_as_const(); safe= (errors == 0); } else { use_cached_value= 0; /* Conversion from and to "binary" is safe. Conversion to Unicode is safe. Conversion from an expression with the ASCII repertoire to any character set that can store characters U+0000..U+007F is safe: - All supported multibyte character sets can store U+0000..U+007F - All supported 7bit character sets can store U+0000..U+007F except those marked with MY_CS_NONASCII (e.g. swe7). Other kind of conversions are potentially lossy. */ safe= (args[0]->collation.collation == &my_charset_bin || cs == &my_charset_bin || (cs->state & MY_CS_UNICODE) || (args[0]->collation.repertoire == MY_REPERTOIRE_ASCII && (cs->mbmaxlen > 1 || !(cs->state & MY_CS_NONASCII)))); } } String *val_str(String *) override; longlong val_int() override { if (args[0]->result_type() == STRING_RESULT) return Item_str_func::val_int(); longlong res= args[0]->val_int(); if ((null_value= args[0]->null_value)) return 0; return res; } double val_real() override { if (args[0]->result_type() == STRING_RESULT) return Item_str_func::val_real(); double res= args[0]->val_real(); if ((null_value= args[0]->null_value)) return 0; return res; } my_decimal *val_decimal(my_decimal *d) override { if (args[0]->result_type() == STRING_RESULT) return Item_str_func::val_decimal(d); my_decimal *res= args[0]->val_decimal(d); if ((null_value= args[0]->null_value)) return NULL; return res; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { if (args[0]->result_type() == STRING_RESULT) return Item_str_func::get_date(thd, ltime, fuzzydate); bool res= args[0]->get_date(thd, ltime, fuzzydate); if ((null_value= args[0]->null_value)) return 1; return res; } bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("convert") }; return name; } void print(String *str, enum_query_type query_type) override; int save_in_field(Field*, bool) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_conv_charset>(thd, this); } }; class Item_func_set_collation :public Item_str_func { Lex_extended_collation_st m_set_collation; public: Item_func_set_collation(THD *thd, Item *a, const Lex_extended_collation_st &set_collation): Item_str_func(thd, a), m_set_collation(set_collation) {} String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; bool eq(const Item *item, const Eq_config &config) const override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("collate") }; return name; } enum precedence precedence() const override { return COLLATE_PRECEDENCE; } enum Functype functype() const override { return COLLATE_FUNC; } void print(String *str, enum_query_type query_type) override; Item_field *field_for_view_update() override { /* this function is transparent for view updating */ return args[0]->field_for_view_update(); } bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_set_collation>(thd, this); } }; class Item_func_expr_str_metadata :public Item_str_func { public: Item_func_expr_str_metadata(THD *thd, Item *a): Item_str_func(thd, a) { } bool fix_length_and_dec(THD *thd) override { collation.set(system_charset_info); max_length= 64 * collation.collation->mbmaxlen; // should be enough base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; }; table_map not_null_tables() const override { return 0; } Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { return this; } bool const_item() const override { return true; } }; class Item_func_charset :public Item_func_expr_str_metadata { LEX_CSTRING m_cached_charset_info; public: Item_func_charset(THD *thd, Item *a) :Item_func_expr_str_metadata(thd, a) { } String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("charset") }; return name; } table_map used_tables() const override { return 0; } bool fix_length_and_dec(THD* thd) override { if (Item_func_expr_str_metadata::fix_length_and_dec(thd)) return true; /* Since this is a const item which doesn't use tables (see used_tables()), we don't want to access the function arguments during execution. That's why we store the charset here during the preparation phase and only return it later at the execution phase */ DBUG_ASSERT(args[0]->fixed()); m_cached_charset_info.str= args[0]->charset_for_protocol()->cs_name.str; m_cached_charset_info.length= args[0]->charset_for_protocol()->cs_name.length; return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_charset>(thd, this); } }; class Item_func_collation :public Item_func_expr_str_metadata { public: Item_func_collation(THD *thd, Item *a) :Item_func_expr_str_metadata(thd, a) {} String *val_str(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("collation") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_collation>(thd, this); } }; class Item_func_weight_string :public Item_str_func { String tmp_value; uint weigth_flags; uint nweights; uint result_length; public: Item_func_weight_string(THD *thd, Item *a, uint result_length_arg, uint nweights_arg, uint flags_arg): Item_str_func(thd, a) { nweights= nweights_arg; weigth_flags= flags_arg; result_length= result_length_arg; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("weight_string") }; return name; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; bool eq(const Item *item, const Eq_config &config) const override { if (!Item_str_func::eq(item, config)) return false; Item_func_weight_string *that= (Item_func_weight_string *)item; return this->weigth_flags == that->weigth_flags && this->nweights == that->nweights && this->result_length == that->result_length; } Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { return this; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_weight_string>(thd, this); } }; class Item_func_crc32 :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_str(func_name_cstring()) && (arg_count == 1 || args[1]->check_type_can_return_int(func_name_cstring())); } String value; uint32 (*const crc_func)(uint32, const void*, size_t); public: Item_func_crc32(THD *thd, bool Castagnoli, Item *a) : Item_long_func(thd, a), crc_func(Castagnoli ? my_crc32c : my_checksum) { unsigned_flag= 1; } Item_func_crc32(THD *thd, bool Castagnoli, Item *a, Item *b) : Item_long_func(thd, a, b), crc_func(Castagnoli ? my_crc32c : my_checksum) { unsigned_flag= 1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING crc32_name= {STRING_WITH_LEN("crc32") }; static LEX_CSTRING crc32c_name= {STRING_WITH_LEN("crc32c") }; return crc_func == my_crc32c ? crc32c_name : crc32_name; } bool fix_length_and_dec(THD *thd) override { max_length=10; return FALSE; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_crc32>(thd, this); } }; class Item_func_uncompressed_length : public Item_long_func_length { String value; public: Item_func_uncompressed_length(THD *thd, Item *a) :Item_long_func_length(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("uncompressed_length") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=10; set_maybe_null(); return FALSE; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_uncompressed_length>(thd, this); } }; #ifdef HAVE_COMPRESS #define ZLIB_DEPENDED_FUNCTION ; #else #define ZLIB_DEPENDED_FUNCTION { null_value=1; return 0; } #endif class Item_func_compress: public Item_str_binary_checksum_func { String tmp_value; public: Item_func_compress(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { max_length= (args[0]->max_length * 120) / 100 + 12; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("compress") }; return name; } String *val_str(String *) override ZLIB_DEPENDED_FUNCTION protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_compress>(thd, this); } }; class Item_func_uncompress: public Item_str_binary_checksum_func { String tmp_value; public: Item_func_uncompress(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { set_maybe_null(); max_length= MAX_BLOB_WIDTH; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("uncompress") }; return name; } String *val_str(String *) override ZLIB_DEPENDED_FUNCTION protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_uncompress>(thd, this); } }; class Item_func_dyncol_create: public Item_str_func { protected: DYNCALL_CREATE_DEF *defs; DYNAMIC_COLUMN_VALUE *vals; uint *keys_num; LEX_STRING *keys_str; bool names, force_names; bool prepare_arguments(THD *thd, bool force_names); void print_arguments(String *str, enum_query_type query_type); public: Item_func_dyncol_create(THD *thd, List<Item> &args, DYNCALL_CREATE_DEF *dfs); bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_create") }; return name; } String *val_str(String *) override; void print(String *str, enum_query_type query_type) override; enum Functype functype() const override { return DYNCOL_FUNC; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_create>(thd, this); } }; class Item_func_dyncol_add: public Item_func_dyncol_create { public: Item_func_dyncol_add(THD *thd, List<Item> &args_arg, DYNCALL_CREATE_DEF *dfs): Item_func_dyncol_create(thd, args_arg, dfs) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_add") }; return name; } String *val_str(String *) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_add>(thd, this); } }; class Item_func_dyncol_json: public Item_str_func { public: Item_func_dyncol_json(THD *thd, Item *str): Item_str_func(thd, str) {collation.set(DYNCOL_UTF);} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_json") }; return name; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override { max_length= MAX_BLOB_WIDTH; set_maybe_null(); decimals= 0; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_json>(thd, this); } }; /* The following functions is always called from an Item_cast function */ class Item_dyncol_get: public Item_str_func { public: Item_dyncol_get(THD *thd, Item *str, Item *num): Item_str_func(thd, str, num) {} bool fix_length_and_dec(THD *thd) override { set_maybe_null(); max_length= MAX_BLOB_WIDTH; return FALSE; } /* Mark that collation can change between calls */ bool dynamic_result() override { return 1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_get") }; return name; } String *val_str(String *) override; longlong val_int() override; longlong val_int_signed_typecast() override { unsigned_flag= false; // Mark that we want to have a signed value longlong value= val_int(); // val_int() can change unsigned_flag if (!null_value && unsigned_flag && value < 0) push_note_converted_to_negative_complement(current_thd); return value; } longlong val_int_unsigned_typecast() override { unsigned_flag= true; // Mark that we want to have an unsigned value longlong value= val_int(); // val_int() can change unsigned_flag if (!null_value && unsigned_flag == 0 && value < 0) push_note_converted_to_positive_complement(current_thd); return value; } double val_real() override; my_decimal *val_decimal(my_decimal *) override; bool get_dyn_value(THD *thd, DYNAMIC_COLUMN_VALUE *val, String *tmp); bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_dyncol_get>(thd, this); } }; class Item_func_dyncol_list: public Item_str_func { public: Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str) {collation.set(DYNCOL_UTF);} bool fix_length_and_dec(THD *thd) override { set_maybe_null(); max_length= MAX_BLOB_WIDTH; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("column_list") }; return name; } String *val_str(String *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dyncol_list>(thd, this); } }; /* this is used by JOIN_TAB::keep_current_rowid and stores handler::position(). It has nothing to do with _rowid pseudo-column, that the parser supports. */ class Item_temptable_rowid :public Item_str_func { public: TABLE *table; Item_temptable_rowid(TABLE *table_arg); const Type_handler *type_handler() const override { return &type_handler_string; } Field *create_tmp_field(MEM_ROOT *root, bool group, TABLE *table) { return create_table_field_from_handler(root, table); } String *val_str(String *str) override; enum Functype functype() const override { return TEMPTABLE_ROWID; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<rowid>") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_temptable_rowid>(thd, this); } }; class Item_func_format_pico_time : public Item_str_ascii_func { /* Format is 'AAAA.BB UUU' = 11 characters or 'AAA ps' = 6 characters. */ char m_value_buffer[12]; String m_value; public: Item_func_format_pico_time(THD *thd, Item *a): Item_str_ascii_func(thd, a) {} String *val_str_ascii(String *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("format_pico_time")}; return name; } bool fix_length_and_dec(THD *thd) override { m_value.set(m_value_buffer, sizeof(m_value_buffer), default_charset()); fix_length_and_charset(sizeof(m_value_buffer), default_charset()); return false; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_format_pico_time>(thd, this); } }; #ifdef WITH_WSREP #include "wsrep_api.h" class Item_func_wsrep_last_written_gtid: public Item_str_ascii_func { String gtid_str; public: Item_func_wsrep_last_written_gtid(THD *thd): Item_str_ascii_func(thd) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("wsrep_last_written_gtid") }; return name; } String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override { max_length= WSREP_GTID_STR_LEN; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_wsrep_last_written_gtid>(thd, this); } }; class Item_func_wsrep_last_seen_gtid: public Item_str_ascii_func { String gtid_str; public: Item_func_wsrep_last_seen_gtid(THD *thd): Item_str_ascii_func(thd) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("wsrep_last_seen_gtid") }; return name; } String *val_str_ascii(String *) override; bool fix_length_and_dec(THD *thd) override { max_length= WSREP_GTID_STR_LEN; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_wsrep_last_seen_gtid>(thd, this); } }; class Item_func_wsrep_sync_wait_upto: public Item_int_func { String value; public: Item_func_wsrep_sync_wait_upto(THD *thd, Item *a): Item_int_func(thd, a) {} Item_func_wsrep_sync_wait_upto(THD *thd, Item *a, Item* b): Item_int_func(thd, a, b) {} const Type_handler *type_handler() const override { return &type_handler_string; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("wsrep_sync_wait_upto_gtid") }; return name; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_wsrep_sync_wait_upto>(thd, this); } }; #endif /* WITH_WSREP */ #endif /* ITEM_STRFUNC_INCLUDED */ sql_view.h 0000644 00000004646 15156036162 0006565 0 ustar 00 #ifndef SQL_VIEW_INCLUDED #define SQL_VIEW_INCLUDED /* -*- C++ -*- */ /* Copyright (c) 2004, 2010, Oracle and/or its affiliates. Copyright (c) 2015, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_class.h" /* Required by sql_lex.h */ #include "sql_lex.h" /* enum_view_create_mode, enum_drop_mode */ /* Forward declarations */ class File_parser; /* Function declarations */ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, enum_view_create_mode mode); bool mysql_create_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode); bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, bool open_view_no_parse); bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode); bool check_key_in_view(THD *thd, TABLE_LIST * view); bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view); int view_checksum(THD *thd, TABLE_LIST *view); int view_check(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt); int view_repair(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt); extern TYPELIB updatable_views_with_limit_typelib; bool check_duplicate_names(THD *thd, List<Item>& item_list, bool gen_unique_view_names); bool mysql_rename_view(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *new_name, const LEX_CSTRING *old_db, const LEX_CSTRING *old_name); void make_valid_column_names(THD *thd, List<Item> &item_list); #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL) extern const LEX_CSTRING view_type; void make_valid_column_names(List<Item> &item_list); bool mariadb_view_version_get(TABLE_SHARE *share); #endif /* SQL_VIEW_INCLUDED */ password.h 0000644 00000002222 15156036162 0006562 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef PASSWORD_INCLUDED #define PASSWORD_INCLUDED C_MODE_START void my_make_scrambled_password_323(char *to, const char *password, size_t pass_len); void my_make_scrambled_password(char *to, const char *password, size_t pass_len); void hash_password(ulong *result, const char *password, uint password_len); C_MODE_END #endif /* PASSWORD_INCLUDED */ violite.h 0000644 00000023546 15156036162 0006407 0 ustar 00 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2012, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* * Vio Lite. * Purpose: include file for Vio that will work with C and C++ */ #ifndef vio_violite_h_ #define vio_violite_h_ #include "my_net.h" /* needed because of struct in_addr */ #include <mysql/psi/mysql_socket.h> /* Simple vio interface in C; The functions are implemented in violite.c */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifdef __cplusplus typedef struct st_vio Vio; #endif /* __cplusplus */ enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL /* see also vio_type_names[] */ }; enum enum_vio_state { VIO_STATE_NOT_INITIALIZED, VIO_STATE_ACTIVE, VIO_STATE_SHUTDOWN, VIO_STATE_CLOSED }; #define FIRST_VIO_TYPE VIO_CLOSED #define LAST_VIO_TYPE VIO_TYPE_SSL /** VIO I/O events. */ enum enum_vio_io_event { VIO_IO_EVENT_READ, VIO_IO_EVENT_WRITE, VIO_IO_EVENT_CONNECT }; struct vio_keepalive_opts { int interval; int idle; int probes; }; #define VIO_TLSv1_0 1 #define VIO_TLSv1_1 2 #define VIO_TLSv1_2 4 #define VIO_TLSv1_3 8 #define VIO_LOCALHOST 1U /* a localhost connection */ #define VIO_BUFFERED_READ 2U /* use buffered read */ #define VIO_READ_BUFFER_SIZE 16384U /* size of read buffer */ #define VIO_DESCRIPTION_SIZE 30 /* size of description */ Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags); Vio* mysql_socket_vio_new(MYSQL_SOCKET mysql_socket, enum enum_vio_type type, uint flags); #ifdef _WIN32 Vio* vio_new_win32pipe(HANDLE hPipe); #else #define HANDLE void * #endif /* _WIN32 */ void vio_delete(Vio* vio); int vio_close(Vio* vio); my_bool vio_reset(Vio* vio, enum enum_vio_type type, my_socket sd, void *ssl, uint flags); size_t vio_read(Vio *vio, uchar * buf, size_t size); size_t vio_read_buff(Vio *vio, uchar * buf, size_t size); size_t vio_write(Vio *vio, const uchar * buf, size_t size); int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode); my_bool vio_is_blocking(Vio *vio); /* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */ int vio_nodelay(Vio *vio, my_bool on); int vio_fastsend(Vio *vio); /* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */ int vio_keepalive(Vio *vio, my_bool onoff); int vio_set_keepalive_options(Vio * vio, const struct vio_keepalive_opts *opts); /* Whenever we should retry the last read/write operation. */ my_bool vio_should_retry(Vio *vio); /* Check that operation was timed out */ my_bool vio_was_timeout(Vio *vio); /* Short text description of the socket for those, who are curious.. */ const char* vio_description(Vio *vio); /* Return the type of the connection */ enum enum_vio_type vio_type(Vio* vio); /* Return last error number */ int vio_errno(Vio*vio); /* Get socket number */ my_socket vio_fd(Vio*vio); /* Remote peer's address and name in text form */ my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen); /* Wait for an I/O event notification. */ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout); my_bool vio_is_connected(Vio *vio); ssize_t vio_pending(Vio *vio); /* Set timeout for a network operation. */ extern int vio_timeout(Vio *vio, uint which, int timeout_sec); extern void vio_set_wait_callback(void (*before_wait)(void), void (*after_wait)(void)); /* Connect to a peer. */ my_bool vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, int timeout); void vio_get_normalized_ip(const struct sockaddr *src, size_t src_length, struct sockaddr *dst); my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, size_t addr_length, char *ip_string, size_t ip_string_size); my_bool vio_is_no_name_error(int err_code); int vio_getnameinfo(const struct sockaddr *sa, char *hostname, size_t hostname_size, char *port, size_t port_size, int flags); #ifdef HAVE_OPENSSL /* apple deprecated openssl in MacOSX Lion */ #ifdef __APPLE__ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif #define HEADER_DES_LOCL_H dummy_something #define YASSL_MYSQL_COMPATIBLE #ifndef YASSL_PREFIX #define YASSL_PREFIX #endif /* Set yaSSL to use same type as MySQL do for socket handles */ typedef my_socket YASSL_SOCKET_T; #define YASSL_SOCKET_T_DEFINED #define template _template /* bug in WolfSSL 4.4.0, see also my_crypt.cc */ #include <openssl/ssl.h> #undef template #include <openssl/err.h> #ifdef DEPRECATED #undef DEPRECATED #endif enum enum_ssl_init_error { SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY, SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS, SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_PROTOCOL, SSL_INITERR_LASTERR }; const char* sslGetErrString(enum enum_ssl_init_error err); struct st_VioSSLFd { SSL_CTX *ssl_context; }; int sslaccept(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); void vio_check_ssl_init(); struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, const char *cipher, enum enum_ssl_init_error *error, const char *crl_file, const char *crl_path); struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file,const char *ca_path, const char *cipher, enum enum_ssl_init_error *error, const char *crl_file, const char *crl_path, ulonglong tls_version); void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); #endif /* HAVE_OPENSSL */ void vio_end(void); const char *vio_type_name(enum enum_vio_type vio_type, size_t *len); #ifdef __cplusplus } #endif #if !defined(DONT_MAP_VIO) #define vio_delete(vio) (vio)->viodelete(vio) #define vio_errno(vio) (vio)->vioerrno(vio) #define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size) #define vio_write(vio, buf, size) ((vio)->write)(vio, buf, size) #define vio_blocking(vio, set_blocking_mode, old_mode)\ (vio)->vioblocking(vio, set_blocking_mode, old_mode) #define vio_is_blocking(vio) (vio)->is_blocking(vio) #define vio_fastsend(vio) (vio)->fastsend(vio) #define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) #define vio_should_retry(vio) (vio)->should_retry(vio) #define vio_was_timeout(vio) (vio)->was_timeout(vio) #define vio_close(vio) ((vio)->vioclose)(vio) #define vio_shutdown(vio,how) ((vio)->shutdown)(vio,how) #define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) #define vio_io_wait(vio, event, timeout) (vio)->io_wait(vio, event, timeout) #define vio_is_connected(vio) (vio)->is_connected(vio) #endif /* !defined(DONT_MAP_VIO) */ #ifdef _WIN32 /* shutdown(2) flags */ #ifndef SHUT_RD #define SHUT_RD SD_RECEIVE #endif #endif /* This enumerator is used in parser - should be always visible */ enum SSL_type { SSL_TYPE_NOT_SPECIFIED= -1, SSL_TYPE_NONE, SSL_TYPE_ANY, SSL_TYPE_X509, SSL_TYPE_SPECIFIED }; /* HFTODO - hide this if we don't want client in embedded server */ /* This structure is for every connection on both sides */ struct st_vio { MYSQL_SOCKET mysql_socket; /* Instrumented socket */ my_bool localhost; /* Are we from localhost? */ int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ struct sockaddr_storage local; /* Local internet address */ struct sockaddr_storage remote; /* Remote internet address */ enum enum_vio_type type; /* Type of connection */ enum enum_vio_state state; /* State of the connection */ const char *desc; /* String description */ char *read_buffer; /* buffer for vio_read_buff */ char *read_pos; /* start of unfetched data in the read buffer */ char *read_end; /* end of unfetched data */ int read_timeout; /* Timeout value (ms) for read ops. */ int write_timeout; /* Timeout value (ms) for write ops. */ /* function pointers. They are similar for socket/SSL/whatever */ void (*viodelete)(Vio*); int (*vioerrno)(Vio*); size_t (*read)(Vio*, uchar *, size_t); size_t (*write)(Vio*, const uchar *, size_t); int (*timeout)(Vio*, uint, my_bool); int (*vioblocking)(Vio*, my_bool, my_bool *); my_bool (*is_blocking)(Vio*); int (*viokeepalive)(Vio*, my_bool); int (*fastsend)(Vio*); my_bool (*peer_addr)(Vio*, char *, uint16*, size_t); void (*in_addr)(Vio*, struct sockaddr_storage*); my_bool (*should_retry)(Vio*); my_bool (*was_timeout)(Vio*); int (*vioclose)(Vio*); my_bool (*is_connected)(Vio*); int (*shutdown)(Vio *, int); my_bool (*has_data) (Vio*); int (*io_wait)(Vio*, enum enum_vio_io_event, int); my_bool (*connect)(Vio*, struct sockaddr *, socklen_t, int); #ifdef HAVE_OPENSSL void *ssl_arg; #endif #ifdef _WIN32 HANDLE hPipe; OVERLAPPED overlapped; int shutdown_flag; void *tp_ctx; /* threadpool context */ #endif }; #endif /* vio_violite_h_ */ sp.h 0000644 00000056165 15156036162 0005361 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_H_ #define _SP_H_ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_string.h" // LEX_STRING #include "sql_cmd.h" #include "mdl.h" class Field; class Open_tables_backup; class Open_tables_state; class Query_arena; class Query_tables_list; class Sroutine_hash_entry; class THD; class sp_cache; class sp_head; class sp_package; class sp_pcontext; class sp_name; class sp_expr_lex; class Database_qualified_name; struct st_sp_chistics; class Stored_program_creation_ctx; struct LEX; struct TABLE; struct TABLE_LIST; typedef struct st_hash HASH; template <typename T> class SQL_I_List; /* Values for the type enum. This reflects the order of the enum declaration in the CREATE TABLE command. See also storage/perfschema/my_thread.h */ enum enum_sp_type { SP_TYPE_FUNCTION=1, SP_TYPE_PROCEDURE=2, SP_TYPE_PACKAGE=3, SP_TYPE_PACKAGE_BODY=4, SP_TYPE_TRIGGER=5, SP_TYPE_EVENT=6, }; class Sp_handler { bool sp_resolve_package_routine_explicit(THD *thd, sp_head *caller, sp_name *name, const Sp_handler **pkg_routine_hndlr, Database_qualified_name *pkgname) const; bool sp_resolve_package_routine_implicit(THD *thd, sp_head *caller, sp_name *name, const Sp_handler **pkg_routine_hndlr, Database_qualified_name *pkgname) const; protected: int db_find_routine_aux(THD *thd, const Database_qualified_name *name, TABLE *table) const; int db_find_routine(THD *thd, const Database_qualified_name *name, sp_head **sphp) const; int db_find_and_cache_routine(THD *thd, const Database_qualified_name *name, sp_head **sp) const; int db_load_routine(THD *thd, const Database_qualified_name *name, sp_head **sphp, sql_mode_t sql_mode, const LEX_CSTRING ¶ms, const LEX_CSTRING &returns, const LEX_CSTRING &body, const st_sp_chistics &chistics, const AUTHID &definer, longlong created, longlong modified, sp_package *parent, Stored_program_creation_ctx *creation_ctx) const; int sp_drop_routine_internal(THD *thd, const Database_qualified_name *name, TABLE *table) const; sp_head *sp_clone_and_link_routine(THD *thd, const Database_qualified_name *name, sp_head *sp) const; int sp_cache_package_routine(THD *thd, const LEX_CSTRING &pkgname_cstr, const Database_qualified_name *name, sp_head **sp) const; int sp_cache_package_routine(THD *thd, const Database_qualified_name *name, sp_head **sp) const; sp_head *sp_find_package_routine(THD *thd, const LEX_CSTRING pkgname_str, const Database_qualified_name *name, bool cache_only) const; sp_head *sp_find_package_routine(THD *thd, const Database_qualified_name *name, bool cache_only) const; public: // TODO: make it private or protected virtual int sp_find_and_drop_routine(THD *thd, TABLE *table, const Database_qualified_name *name) const; public: virtual ~Sp_handler() = default; static const Sp_handler *handler(enum enum_sql_command cmd); static const Sp_handler *handler(enum_sp_type type); static const Sp_handler *handler(MDL_key::enum_mdl_namespace ns); /* Return a handler only those SP objects that store definitions in the mysql.proc system table */ static const Sp_handler *handler_mysql_proc(enum_sp_type type) { const Sp_handler *sph= handler(type); return sph ? sph->sp_handler_mysql_proc() : NULL; } static bool eq_routine_name(const LEX_CSTRING &name1, const LEX_CSTRING &name2) { return system_charset_info->strnncoll(name1.str, name1.length, name2.str, name2.length) == 0; } const char *type_str() const { return type_lex_cstring().str; } virtual const char *show_create_routine_col1_caption() const { DBUG_ASSERT(0); return ""; } virtual const char *show_create_routine_col3_caption() const { DBUG_ASSERT(0); return ""; } virtual const Sp_handler *package_routine_handler() const { return this; } virtual enum_sp_type type() const= 0; virtual LEX_CSTRING type_lex_cstring() const= 0; virtual enum_sql_command sqlcom_create() const= 0; virtual enum_sql_command sqlcom_drop() const= 0; virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const { static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("???")}; DBUG_ASSERT(0); return m_empty_body; } virtual MDL_key::enum_mdl_namespace get_mdl_type() const= 0; virtual const Sp_handler *sp_handler_mysql_proc() const { return this; } virtual sp_cache **get_cache(THD *) const { return NULL; } #ifndef NO_EMBEDDED_ACCESS_CHECKS virtual HASH *get_priv_hash() const { return NULL; } #endif virtual ulong recursion_depth(THD *thd) const { return 0; } /** Return appropriate error about recursion limit reaching @param thd Thread handle @param sp SP routine @remark For functions and triggers we return error about prohibited recursion. For stored procedures we return about reaching recursion limit. */ virtual void recursion_level_error(THD *thd, const sp_head *sp) const { my_error(ER_SP_NO_RECURSION, MYF(0)); } virtual bool add_instr_freturn(THD *thd, sp_head *sp, sp_pcontext *spcont, Item *item, sp_expr_lex *lex) const; virtual bool add_instr_preturn(THD *thd, sp_head *sp, sp_pcontext *spcont) const; void add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena, const Database_qualified_name *name) const; bool sp_resolve_package_routine(THD *thd, sp_head *caller, sp_name *name, const Sp_handler **pkg_routine_handler, Database_qualified_name *pkgname) const; virtual sp_head *sp_find_routine(THD *thd, const Database_qualified_name *name, bool cache_only) const; virtual int sp_cache_routine(THD *thd, const Database_qualified_name *name, sp_head **sp) const; int sp_cache_routine_reentrant(THD *thd, const Database_qualified_name *nm, sp_head **sp) const; bool sp_exist_routines(THD *thd, TABLE_LIST *procs) const; bool sp_show_create_routine(THD *thd, const Database_qualified_name *name) const; bool sp_create_routine(THD *thd, const sp_head *sp) const; int sp_update_routine(THD *thd, const Database_qualified_name *name, const st_sp_chistics *chistics) const; int sp_drop_routine(THD *thd, const Database_qualified_name *name) const; sp_head *sp_load_for_information_schema(THD *thd, TABLE *proc_table, const LEX_CSTRING &db, const LEX_CSTRING &name, const LEX_CSTRING ¶ms, const LEX_CSTRING &returns, sql_mode_t sql_mode, bool *free_sp_head) const; /* Make a SHOW CREATE statement. @retval true on error @retval false on success */ virtual bool show_create_sp(THD *thd, String *buf, const LEX_CSTRING &db, const LEX_CSTRING &name, const LEX_CSTRING ¶ms, const LEX_CSTRING &returns, const LEX_CSTRING &body, const st_sp_chistics &chistics, const AUTHID &definer, const DDL_options_st ddl_options, sql_mode_t sql_mode) const; }; class Sp_handler_procedure: public Sp_handler { public: enum_sp_type type() const override { return SP_TYPE_PROCEDURE; } LEX_CSTRING type_lex_cstring() const override { static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")}; return m_type_str; } enum_sql_command sqlcom_create() const override { return SQLCOM_CREATE_PROCEDURE; } enum_sql_command sqlcom_drop() const override { return SQLCOM_DROP_PROCEDURE; } LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const override; const char *show_create_routine_col1_caption() const override { return "Procedure"; } const char *show_create_routine_col3_caption() const override { return "Create Procedure"; } MDL_key::enum_mdl_namespace get_mdl_type() const override { return MDL_key::PROCEDURE; } const Sp_handler *package_routine_handler() const override; sp_cache **get_cache(THD *) const override; #ifndef NO_EMBEDDED_ACCESS_CHECKS HASH *get_priv_hash() const override; #endif ulong recursion_depth(THD *thd) const override; void recursion_level_error(THD *thd, const sp_head *sp) const override; bool add_instr_preturn(THD *thd, sp_head *sp, sp_pcontext *spcont) const override; }; class Sp_handler_package_procedure: public Sp_handler_procedure { public: int sp_cache_routine(THD *thd, const Database_qualified_name *name, sp_head **sp) const override { return sp_cache_package_routine(thd, name, sp); } sp_head *sp_find_routine(THD *thd, const Database_qualified_name *name, bool cache_only) const override { return sp_find_package_routine(thd, name, cache_only); } }; class Sp_handler_function: public Sp_handler { public: enum_sp_type type() const override { return SP_TYPE_FUNCTION; } LEX_CSTRING type_lex_cstring() const override { static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")}; return m_type_str; } enum_sql_command sqlcom_create() const override { return SQLCOM_CREATE_FUNCTION; } enum_sql_command sqlcom_drop() const override { return SQLCOM_DROP_FUNCTION; } LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const override; const char *show_create_routine_col1_caption() const override { return "Function"; } const char *show_create_routine_col3_caption() const override { return "Create Function"; } MDL_key::enum_mdl_namespace get_mdl_type() const override { return MDL_key::FUNCTION; } const Sp_handler *package_routine_handler() const override; sp_cache **get_cache(THD *) const override; #ifndef NO_EMBEDDED_ACCESS_CHECKS HASH *get_priv_hash() const override; #endif bool add_instr_freturn(THD *thd, sp_head *sp, sp_pcontext *spcont, Item *item, sp_expr_lex *lex) const override; }; class Sp_handler_package_function: public Sp_handler_function { public: int sp_cache_routine(THD *thd, const Database_qualified_name *name, sp_head **sp) const override { return sp_cache_package_routine(thd, name, sp); } sp_head *sp_find_routine(THD *thd, const Database_qualified_name *name, bool cache_only) const override { return sp_find_package_routine(thd, name, cache_only); } }; class Sp_handler_package: public Sp_handler { public: bool show_create_sp(THD *thd, String *buf, const LEX_CSTRING &db, const LEX_CSTRING &name, const LEX_CSTRING ¶ms, const LEX_CSTRING &returns, const LEX_CSTRING &body, const st_sp_chistics &chistics, const AUTHID &definer, const DDL_options_st ddl_options, sql_mode_t sql_mode) const override; }; class Sp_handler_package_spec: public Sp_handler_package { public: // TODO: make it private or protected int sp_find_and_drop_routine(THD *thd, TABLE *table, const Database_qualified_name *name) const override; public: enum_sp_type type() const override { return SP_TYPE_PACKAGE; } LEX_CSTRING type_lex_cstring() const override { static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")}; return m_type_str; } enum_sql_command sqlcom_create() const override { return SQLCOM_CREATE_PACKAGE; } enum_sql_command sqlcom_drop() const override { return SQLCOM_DROP_PACKAGE; } LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const override { static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("BEGIN END")}; return m_empty_body; } const char *show_create_routine_col1_caption() const override { return "Package"; } const char *show_create_routine_col3_caption() const override { return "Create Package"; } MDL_key::enum_mdl_namespace get_mdl_type() const override { return MDL_key::PACKAGE_BODY; } sp_cache **get_cache(THD *) const override; #ifndef NO_EMBEDDED_ACCESS_CHECKS HASH *get_priv_hash() const override; #endif }; class Sp_handler_package_body: public Sp_handler_package { public: enum_sp_type type() const override { return SP_TYPE_PACKAGE_BODY; } LEX_CSTRING type_lex_cstring() const override { static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")}; return m_type_str; } enum_sql_command sqlcom_create() const override { return SQLCOM_CREATE_PACKAGE_BODY; } enum_sql_command sqlcom_drop() const override { return SQLCOM_DROP_PACKAGE_BODY; } LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const override { static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("BEGIN END")}; return m_empty_body; } const char *show_create_routine_col1_caption() const override { return "Package body"; } const char *show_create_routine_col3_caption() const override { return "Create Package Body"; } MDL_key::enum_mdl_namespace get_mdl_type() const override { return MDL_key::PACKAGE_BODY; } sp_cache **get_cache(THD *) const override; #ifndef NO_EMBEDDED_ACCESS_CHECKS HASH *get_priv_hash() const override; #endif }; class Sp_handler_trigger: public Sp_handler { public: enum_sp_type type() const override { return SP_TYPE_TRIGGER; } LEX_CSTRING type_lex_cstring() const override { static LEX_CSTRING m_type_str= { STRING_WITH_LEN("TRIGGER")}; return m_type_str; } enum_sql_command sqlcom_create() const override { return SQLCOM_CREATE_TRIGGER; } enum_sql_command sqlcom_drop() const override { return SQLCOM_DROP_TRIGGER; } MDL_key::enum_mdl_namespace get_mdl_type() const override { DBUG_ASSERT(0); return MDL_key::TRIGGER; } const Sp_handler *sp_handler_mysql_proc() const override { return NULL; } }; extern MYSQL_PLUGIN_IMPORT Sp_handler_function sp_handler_function; extern MYSQL_PLUGIN_IMPORT Sp_handler_procedure sp_handler_procedure; extern MYSQL_PLUGIN_IMPORT Sp_handler_package_spec sp_handler_package_spec; extern MYSQL_PLUGIN_IMPORT Sp_handler_package_body sp_handler_package_body; extern MYSQL_PLUGIN_IMPORT Sp_handler_package_function sp_handler_package_function; extern MYSQL_PLUGIN_IMPORT Sp_handler_package_procedure sp_handler_package_procedure; extern MYSQL_PLUGIN_IMPORT Sp_handler_trigger sp_handler_trigger; inline const Sp_handler *Sp_handler::handler(enum_sql_command cmd) { switch (cmd) { case SQLCOM_CREATE_PROCEDURE: case SQLCOM_ALTER_PROCEDURE: case SQLCOM_DROP_PROCEDURE: case SQLCOM_SHOW_PROC_CODE: case SQLCOM_SHOW_CREATE_PROC: case SQLCOM_SHOW_STATUS_PROC: return &sp_handler_procedure; case SQLCOM_CREATE_SPFUNCTION: case SQLCOM_ALTER_FUNCTION: case SQLCOM_DROP_FUNCTION: case SQLCOM_SHOW_FUNC_CODE: case SQLCOM_SHOW_CREATE_FUNC: case SQLCOM_SHOW_STATUS_FUNC: return &sp_handler_function; case SQLCOM_CREATE_PACKAGE: case SQLCOM_DROP_PACKAGE: case SQLCOM_SHOW_CREATE_PACKAGE: case SQLCOM_SHOW_STATUS_PACKAGE: return &sp_handler_package_spec; case SQLCOM_CREATE_PACKAGE_BODY: case SQLCOM_DROP_PACKAGE_BODY: case SQLCOM_SHOW_CREATE_PACKAGE_BODY: case SQLCOM_SHOW_STATUS_PACKAGE_BODY: case SQLCOM_SHOW_PACKAGE_BODY_CODE: return &sp_handler_package_body; default: break; } return NULL; } inline const Sp_handler *Sp_handler::handler(enum_sp_type type) { switch (type) { case SP_TYPE_PROCEDURE: return &sp_handler_procedure; case SP_TYPE_FUNCTION: return &sp_handler_function; case SP_TYPE_PACKAGE: return &sp_handler_package_spec; case SP_TYPE_PACKAGE_BODY: return &sp_handler_package_body; case SP_TYPE_TRIGGER: return &sp_handler_trigger; case SP_TYPE_EVENT: break; } return NULL; } inline const Sp_handler *Sp_handler::handler(MDL_key::enum_mdl_namespace type) { switch (type) { case MDL_key::FUNCTION: return &sp_handler_function; case MDL_key::PROCEDURE: return &sp_handler_procedure; case MDL_key::PACKAGE_BODY: return &sp_handler_package_body; case MDL_key::BACKUP: case MDL_key::SCHEMA: case MDL_key::TABLE: case MDL_key::TRIGGER: case MDL_key::EVENT: case MDL_key::USER_LOCK: case MDL_key::NAMESPACE_END: break; } return NULL; } /* Tells what SP_DEFAULT_ACCESS should be mapped to */ #define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL // Return codes from sp_create_*, sp_drop_*, and sp_show_*: #define SP_OK 0 #define SP_KEY_NOT_FOUND -1 #define SP_OPEN_TABLE_FAILED -2 #define SP_WRITE_ROW_FAILED -3 #define SP_DELETE_ROW_FAILED -4 #define SP_GET_FIELD_FAILED -5 #define SP_PARSE_ERROR -6 #define SP_INTERNAL_ERROR -7 #define SP_NO_DB_ERROR -8 #define SP_BAD_IDENTIFIER -9 #define SP_BODY_TOO_LONG -10 #define SP_FLD_STORE_FAILED -11 /* DB storage of Stored PROCEDUREs and FUNCTIONs */ enum { MYSQL_PROC_FIELD_DB = 0, MYSQL_PROC_FIELD_NAME, MYSQL_PROC_MYSQL_TYPE, MYSQL_PROC_FIELD_SPECIFIC_NAME, MYSQL_PROC_FIELD_LANGUAGE, MYSQL_PROC_FIELD_ACCESS, MYSQL_PROC_FIELD_DETERMINISTIC, MYSQL_PROC_FIELD_SECURITY_TYPE, MYSQL_PROC_FIELD_PARAM_LIST, MYSQL_PROC_FIELD_RETURNS, MYSQL_PROC_FIELD_BODY, MYSQL_PROC_FIELD_DEFINER, MYSQL_PROC_FIELD_CREATED, MYSQL_PROC_FIELD_MODIFIED, MYSQL_PROC_FIELD_SQL_MODE, MYSQL_PROC_FIELD_COMMENT, MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT, MYSQL_PROC_FIELD_COLLATION_CONNECTION, MYSQL_PROC_FIELD_DB_COLLATION, MYSQL_PROC_FIELD_BODY_UTF8, MYSQL_PROC_FIELD_AGGREGATE, MYSQL_PROC_FIELD_COUNT }; /* Drop all routines in database 'db' */ int sp_drop_db_routines(THD *thd, const LEX_CSTRING &db); /** Acquires exclusive metadata lock on all stored routines in the given database. @param thd Thread handler @param db Database name @retval false Success @retval true Failure */ bool lock_db_routines(THD *thd, const Lex_ident_db_normalized &db); /** Structure that represents element in the set of stored routines used by statement or routine. */ class Sroutine_hash_entry { public: /** Metadata lock request for routine. MDL_key in this request is also used as a key for set. */ MDL_request mdl_request; /** Next element in list linking all routines in set. See also comments for LEX::sroutine/sroutine_list and sp_head::m_sroutines. */ Sroutine_hash_entry *next; /** Uppermost view which directly or indirectly uses this routine. 0 if routine is not used in view. Note that it also can be 0 if statement uses routine both via view and directly. */ TABLE_LIST *belong_to_view; /** This is for prepared statement validation purposes. A statement looks up and pre-loads all its stored functions at prepare. Later on, if a function is gone from the cache, execute may fail. Remember the version of sp_head at prepare to be able to invalidate the prepared statement at execute if it changes. */ ulong m_sp_cache_version; const Sp_handler *m_handler; int sp_cache_routine(THD *thd, sp_head **sp) const; }; bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena, const MDL_key *key, const Sp_handler *handler, TABLE_LIST *belong_to_view); void sp_remove_not_own_routines(Query_tables_list *prelocking_ctx); bool sp_update_sp_used_routines(HASH *dst, HASH *src); void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, HASH *src, TABLE_LIST *belong_to_view); void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, SQL_I_List<Sroutine_hash_entry> *src, TABLE_LIST *belong_to_view); extern "C" const uchar *sp_sroutine_key(const void *ptr, size_t *plen, my_bool); /* Routines which allow open/lock and close mysql.proc table even when we already have some tables open and locked. */ TABLE *open_proc_table_for_read(THD *thd); bool load_charset(THD *thd, MEM_ROOT *mem_root, Field *field, CHARSET_INFO *dflt_cs, CHARSET_INFO **cs); bool load_collation(THD *thd,MEM_ROOT *mem_root, Field *field, CHARSET_INFO *dflt_cl, CHARSET_INFO **cl); void sp_returns_type(THD *thd, String &result, const sp_head *sp); #endif /* _SP_H_ */ opt_subselect.h 0000644 00000035436 15156036162 0007610 0 ustar 00 /* Copyright (c) 2010, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Semi-join subquery optimization code definitions */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif int check_and_do_in_subquery_rewrites(JOIN *join); bool convert_join_subqueries_to_semijoins(JOIN *join); int pull_out_semijoin_tables(JOIN *join); bool optimize_semijoin_nests(JOIN *join, table_map all_table_map); bool setup_degenerate_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, List<Item> &eq_list); bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, List<Item> &eq_list); void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list); // used by Loose_scan_opt ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, table_map remaining_tables); /* This is a class for considering possible loose index scan optimizations. It's usage pattern is as follows: best_access_path() { Loose_scan_opt opt; opt.init() for each index we can do ref access with { opt.next_ref_key(); for each keyuse opt.add_keyuse(); opt.check_ref_access(); } if (some criteria for range scans) opt.check_range_access(); opt.get_best_option(); } */ class Loose_scan_opt { /* All methods must check this before doing anything else */ bool try_loosescan; /* If we consider (oe1, .. oeN) IN (SELECT ie1, .. ieN) then ieK=oeK is called sj-equality. If oeK depends only on preceding tables then such equality is called 'bound'. */ ulonglong bound_sj_equalities; /* Accumulated properties of ref access we're now considering: */ ulonglong handled_sj_equalities; key_part_map loose_scan_keyparts; uint max_loose_keypart; bool part1_conds_met; /* Use of quick select is a special case. Some of its properties: */ uint quick_uses_applicable_index; uint quick_max_loose_keypart; /* Best loose scan method so far */ uint best_loose_scan_key; double best_loose_scan_cost; double best_loose_scan_records; KEYUSE *best_loose_scan_start_key; uint best_max_loose_keypart; table_map best_ref_depend_map; public: Loose_scan_opt(): try_loosescan(false), bound_sj_equalities(0), quick_uses_applicable_index(0), quick_max_loose_keypart(0), best_loose_scan_key(0), best_loose_scan_cost(0), best_loose_scan_records(0), best_loose_scan_start_key(NULL), best_max_loose_keypart(0), best_ref_depend_map(0) { } void init(JOIN *join, JOIN_TAB *s, table_map remaining_tables) { /* Discover the bound equalities. We need to do this if 1. The next table is an SJ-inner table, and 2. It is the first table from that semijoin, and 3. We're not within a semi-join range (i.e. all semi-joins either have all or none of their tables in join_table_map), except s->emb_sj_nest (which we've just entered, see #2). 4. All non-IN-equality correlation references from this sj-nest are bound 5. But some of the IN-equalities aren't (so this can't be handled by FirstMatch strategy) */ best_loose_scan_cost= DBL_MAX; if (!join->emb_sjm_nest && s->emb_sj_nest && // (1) s->emb_sj_nest->sj_in_exprs < 64 && ((remaining_tables & s->emb_sj_nest->sj_inner_tables) == // (2) s->emb_sj_nest->sj_inner_tables) && // (2) join->cur_sj_inner_tables == 0 && // (3) !(remaining_tables & s->emb_sj_nest->nested_join->sj_corr_tables) && // (4) remaining_tables & s->emb_sj_nest->nested_join->sj_depends_on &&// (5) optimizer_flag(join->thd, OPTIMIZER_SWITCH_LOOSE_SCAN)) { /* This table is an LooseScan scan candidate */ bound_sj_equalities= get_bound_sj_equalities(s->emb_sj_nest, remaining_tables); try_loosescan= TRUE; DBUG_PRINT("info", ("Will try LooseScan scan, bound_map=%llx", (longlong)bound_sj_equalities)); } } void next_ref_key() { handled_sj_equalities=0; loose_scan_keyparts= 0; max_loose_keypart= 0; part1_conds_met= FALSE; } void add_keyuse(table_map remaining_tables, KEYUSE *keyuse) { if (try_loosescan && keyuse->sj_pred_no != UINT_MAX && (keyuse->table->file->index_flags(keyuse->key, 0, 1 ) & HA_READ_ORDER)) { if (!(remaining_tables & keyuse->used_tables)) { /* This allows to use equality propagation to infer that some sj-equalities are bound. */ bound_sj_equalities |= 1ULL << keyuse->sj_pred_no; } else { handled_sj_equalities |= 1ULL << keyuse->sj_pred_no; loose_scan_keyparts |= ((key_part_map)1) << keyuse->keypart; set_if_bigger(max_loose_keypart, keyuse->keypart); } } } bool have_a_case() { return MY_TEST(handled_sj_equalities); } void check_ref_access_part1(JOIN_TAB *s, uint key, KEYUSE *start_key, table_map found_part) { /* Check if we can use LooseScan semi-join strategy. We can if 1. This is the right table at right location 2. All IN-equalities are either - "bound", ie. the outer_expr part refers to the preceding tables - "handled", ie. covered by the index we're considering 3. Index order allows to enumerate subquery's duplicate groups in order. This happens when the index definition matches this pattern: (handled_col|bound_col)* (other_col|bound_col) */ if (try_loosescan && // (1) (handled_sj_equalities | bound_sj_equalities) == // (2) PREV_BITS(ulonglong, s->emb_sj_nest->sj_in_exprs) && // (2) (PREV_BITS(key_part_map, max_loose_keypart+1) & // (3) (found_part | loose_scan_keyparts)) == // (3) PREV_BITS(key_part_map, max_loose_keypart+1) && // (3) !key_uses_partial_cols(s->table->s, key)) { if (s->quick && s->quick->index == key && s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE) { quick_uses_applicable_index= TRUE; quick_max_loose_keypart= max_loose_keypart; } DBUG_PRINT("info", ("Can use LooseScan scan")); if (found_part & 1) { /* Can use LooseScan on ref access if the first key part is bound */ part1_conds_met= TRUE; } /* Check if this is a special case where there are no usable bound IN-equalities, i.e. we have outer_expr IN (SELECT innertbl.key FROM ...) and outer_expr cannot be evaluated yet, so it's actually full index scan and not a ref access. We can do full index scan if it uses index-only. */ if (!(found_part & 1 ) && /* no usable ref access for 1st key part */ s->table->covering_keys.is_set(key)) { double records, read_time; part1_conds_met= TRUE; handler *file= s->table->file; DBUG_PRINT("info", ("Can use full index scan for LooseScan")); /* Calculate the cost of complete loose index scan. */ records= rows2double(file->stats.records); /* The cost is entire index scan cost (divided by 2) */ read_time= file->cost(file->ha_keyread_and_copy_time(key, 1, (ha_rows) records, 0)); /* Now find out how many different keys we will get (for now we ignore the fact that we have "keypart_i=const" restriction for some key components, that may make us think that loose scan will produce more distinct records than it actually will) */ ulong rpc; if ((rpc= s->table->key_info[key].rec_per_key[max_loose_keypart])) records= records / rpc; // TODO: previous version also did /2 if (read_time < best_loose_scan_cost) { best_loose_scan_key= key; best_loose_scan_cost= read_time; best_loose_scan_records= records; best_max_loose_keypart= max_loose_keypart; best_loose_scan_start_key= start_key; best_ref_depend_map= 0; } } } } void check_ref_access_part2(uint key, KEYUSE *start_key, double records, double read_time, table_map ref_depend_map_arg) { if (part1_conds_met && read_time < best_loose_scan_cost) { /* TODO use rec-per-key-based fanout calculations */ best_loose_scan_key= key; best_loose_scan_cost= read_time; best_loose_scan_records= records; best_max_loose_keypart= max_loose_keypart; best_loose_scan_start_key= start_key; best_ref_depend_map= ref_depend_map_arg; } } void check_range_access(JOIN *join, uint idx, QUICK_SELECT_I *quick) { /* TODO: this the right part restriction: */ if (quick_uses_applicable_index && idx == join->const_tables && quick->read_time < best_loose_scan_cost) { best_loose_scan_key= quick->index; best_loose_scan_cost= quick->read_time; /* this is ok because idx == join->const_tables */ best_loose_scan_records= rows2double(quick->records); best_max_loose_keypart= quick_max_loose_keypart; best_loose_scan_start_key= NULL; best_ref_depend_map= 0; } } void save_to_position(JOIN_TAB *tab, double record_count, double records_out, POSITION *pos) { pos->read_time= best_loose_scan_cost; if (best_loose_scan_cost != DBL_MAX) { /* Make sure LooseScan plan doesn't produce more rows than the records_out of other table access method. */ set_if_smaller(best_loose_scan_records, records_out); pos->loops= record_count; pos->records_read= best_loose_scan_records; pos->records_init= pos->records_read; pos->records_out= best_loose_scan_records; pos->key= best_loose_scan_start_key; pos->cond_selectivity= 1.0; pos->loosescan_picker.loosescan_key= best_loose_scan_key; pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1; pos->use_join_buffer= FALSE; pos->firstmatch_with_join_buf= FALSE; pos->table= tab; pos->range_rowid_filter_info= tab->range_rowid_filter_info; pos->ref_depend_map= best_ref_depend_map; DBUG_PRINT("info", ("Produced a LooseScan plan, key %s, %s", tab->table->key_info[best_loose_scan_key].name.str, best_loose_scan_start_key? "(ref access)": "(range/index access)")); } } }; void optimize_semi_joins(JOIN *join, table_map remaining_tables, uint idx, double *current_record_count, double *current_read_time, POSITION *loose_scan_pos); void update_sj_state(JOIN *join, const JOIN_TAB *new_tab, uint idx, table_map remaining_tables); void restore_prev_sj_state(const table_map remaining_tables, const JOIN_TAB *tab, uint idx); void fix_semijoin_strategies_for_picked_join_order(JOIN *join); bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab); bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab); uint get_number_of_tables_at_top_level(JOIN *join); /* Temporary table used by semi-join DuplicateElimination strategy This consists of the temptable itself and data needed to put records into it. The table's DDL is as follows: CREATE TABLE tmptable (col VARCHAR(n) BINARY, PRIMARY KEY(col)); where the primary key can be replaced with unique constraint if n exceeds the limit (as it is always done for query execution-time temptables). The record value is a concatenation of rowids of tables from the join we're executing. If a join table is on the inner side of the outer join, we assume that its rowid can be NULL and provide means to store this rowid in the tuple. */ class SJ_TMP_TABLE : public Sql_alloc { public: /* Array of pointers to tables whose rowids compose the temporary table record. */ class TAB { public: JOIN_TAB *join_tab; uint rowid_offset; ushort null_byte; uchar null_bit; }; TAB *tabs; TAB *tabs_end; /* is_degenerate==TRUE means this is a special case where the temptable record has zero length (and presence of a unique key means that the temptable can have either 0 or 1 records). In this case we don't create the physical temptable but instead record its state in SJ_TMP_TABLE::have_degenerate_row. */ bool is_degenerate; /* When is_degenerate==TRUE: the contents of the table (whether it has the record or not). */ bool have_degenerate_row; /* table record parameters */ uint null_bits; uint null_bytes; uint rowid_len; /* The temporary table itself (NULL means not created yet) */ TABLE *tmp_table; /* These are the members we got from temptable creation code. We'll need them if we'll need to convert table from HEAP to MyISAM/Maria. */ TMP_ENGINE_COLUMNDEF *start_recinfo; TMP_ENGINE_COLUMNDEF *recinfo; SJ_TMP_TABLE *next_flush_table; int sj_weedout_delete_rows(); int sj_weedout_check_row(THD *thd); bool create_sj_weedout_tmp_table(THD *thd); }; int setup_semijoin_loosescan(JOIN *join); int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, uint no_jbuf_after); void destroy_sj_tmp_tables(JOIN *join); int clear_sj_tmp_tables(JOIN *join); int rewrite_to_index_subquery_engine(JOIN *join); void get_delayed_table_estimates(TABLE *table, ha_rows *out_rows, double *scan_time, double *startup_cost); enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab); sql_acl.h 0000644 00000033374 15156036163 0006353 0 ustar 00 #ifndef SQL_ACL_INCLUDED #define SQL_ACL_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "violite.h" /* SSL_type */ #include "sql_class.h" /* LEX_COLUMN */ #include "grant.h" #include "sql_cmd.h" /* Sql_cmd */ enum mysql_db_table_field { MYSQL_DB_FIELD_HOST = 0, MYSQL_DB_FIELD_DB, MYSQL_DB_FIELD_USER, MYSQL_DB_FIELD_SELECT_PRIV, MYSQL_DB_FIELD_INSERT_PRIV, MYSQL_DB_FIELD_UPDATE_PRIV, MYSQL_DB_FIELD_DELETE_PRIV, MYSQL_DB_FIELD_CREATE_PRIV, MYSQL_DB_FIELD_DROP_PRIV, MYSQL_DB_FIELD_GRANT_PRIV, MYSQL_DB_FIELD_REFERENCES_PRIV, MYSQL_DB_FIELD_INDEX_PRIV, MYSQL_DB_FIELD_ALTER_PRIV, MYSQL_DB_FIELD_CREATE_TMP_TABLE_PRIV, MYSQL_DB_FIELD_LOCK_TABLES_PRIV, MYSQL_DB_FIELD_CREATE_VIEW_PRIV, MYSQL_DB_FIELD_SHOW_VIEW_PRIV, MYSQL_DB_FIELD_CREATE_ROUTINE_PRIV, MYSQL_DB_FIELD_ALTER_ROUTINE_PRIV, MYSQL_DB_FIELD_EXECUTE_PRIV, MYSQL_DB_FIELD_EVENT_PRIV, MYSQL_DB_FIELD_TRIGGER_PRIV, MYSQL_DB_FIELD_DELETE_VERSIONING_ROWS_PRIV, MYSQL_DB_FIELD_COUNT }; extern const TABLE_FIELD_DEF mysql_db_table_def; extern bool mysql_user_table_is_in_short_password_format; extern LEX_CSTRING host_not_specified; extern LEX_CSTRING current_user; extern LEX_CSTRING current_role; extern LEX_CSTRING current_user_and_current_role; extern LEX_CSTRING none; extern LEX_CSTRING public_name; static inline int access_denied_error_code(int passwd_used) { #ifdef mysqld_error_find_printf_error_used return 0; #else return passwd_used == 2 ? ER_ACCESS_DENIED_NO_PASSWORD_ERROR : ER_ACCESS_DENIED_ERROR; #endif } /* prototypes */ bool hostname_requires_resolving(const char *hostname); bool acl_init(bool dont_read_acl_tables); bool acl_reload(THD *thd); void acl_free(bool end=0); privilege_t acl_get_all3(Security_context *sctx, const char *db, bool db_is_patern); bool acl_authenticate(THD *thd, uint com_change_user_pkt_len); bool acl_getroot(Security_context *sctx, const char *user, const char *host, const char *ip, const char *db); bool acl_check_host(const char *host, const char *ip); bool check_change_password(THD *thd, LEX_USER *user); bool change_password(THD *thd, LEX_USER *user); bool mysql_grant_role(THD *thd, List<LEX_USER> &user_list, bool revoke); int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list, List <LEX_COLUMN> &column_list, privilege_t rights, bool revoke); bool mysql_routine_grant(THD *thd, TABLE_LIST *table, const Sp_handler *sph, List <LEX_USER> &user_list, privilege_t rights, bool revoke, bool write_to_binlog); bool grant_init(); void grant_free(void); bool grant_reload(THD *thd); bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, bool any_combination_will_do, uint number, bool no_errors); bool check_grant_column (THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *name, size_t length, Security_context *sctx); bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, const char *name, size_t length, Field *fld); bool check_grant_all_columns(THD *thd, privilege_t want_access, Field_iterator_table_ref *fields); bool check_grant_routine(THD *thd, privilege_t want_access, TABLE_LIST *procs, const Sp_handler *sph, bool no_error); bool check_grant_db(THD *thd,const char *db); bool check_global_access(THD *thd, const privilege_t want_access, bool no_errors= false); bool check_access(THD *thd, privilege_t want_access, const char *db, privilege_t *save_priv, GRANT_INTERNAL_INFO *grant_internal_info, bool dont_check_global_grants, bool no_errors); privilege_t get_table_grant(THD *thd, TABLE_LIST *table); privilege_t get_column_grant(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *field_name); bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username, const char **hostname, const char **rolename); void mysql_show_grants_get_fields(THD *thd, List<Item> *fields, const char *name, size_t length); bool mysql_show_grants(THD *thd, LEX_USER *user); bool mysql_show_create_user(THD *thd, LEX_USER *user); int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond); void get_privilege_desc(char *to, uint max_length, privilege_t access); void get_mqh(const char *user, const char *host, USER_CONN *uc); bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); bool mysql_rename_user(THD *thd, List <LEX_USER> &list); int mysql_alter_user(THD *thd, List <LEX_USER> &list); bool mysql_revoke_all(THD *thd, List <LEX_USER> &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, const Sp_handler *sph); bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, const Sp_handler *sph); bool check_routine_level_acl(THD *thd, privilege_t acl, const char *db, const char *name, const Sp_handler *sph); bool is_acl_user(const char *host, const char *user); int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); /** Result of an access check for an internal schema or table. Internal ACL checks are always performed *before* using the grant tables. This mechanism enforces that the server implementation has full control on its internal tables. Depending on the internal check result, the server implementation can choose to: - always allow access, - always deny access, - delegate the decision to the database administrator, by using the grant tables. */ enum ACL_internal_access_result { /** Access granted for all the requested privileges, do not use the grant tables. */ ACL_INTERNAL_ACCESS_GRANTED, /** Access denied, do not use the grant tables. */ ACL_INTERNAL_ACCESS_DENIED, /** No decision yet, use the grant tables. */ ACL_INTERNAL_ACCESS_CHECK_GRANT }; /** Per internal table ACL access rules. This class is an interface. Per table(s) specific access rule should be implemented in a subclass. @sa ACL_internal_schema_access */ class ACL_internal_table_access { public: ACL_internal_table_access() = default; virtual ~ACL_internal_table_access() = default; /** Check access to an internal table. When a privilege is granted, this method add the requested privilege to save_priv. @param want_access the privileges requested @param [in, out] save_priv the privileges granted @return @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges are granted, and saved in save_priv. @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested privileges was denied. @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege was denied, and grant should be checked for at least one privilege. Requested privileges that are granted, if any, are saved in save_priv. */ virtual ACL_internal_access_result check(privilege_t want_access, privilege_t *save_priv, bool any_combination_will_do) const= 0; }; /** Per internal schema ACL access rules. This class is an interface. Each per schema specific access rule should be implemented in a different subclass, and registered. Per schema access rules can control: - every schema privileges on schema.* - every table privileges on schema.table @sa ACL_internal_schema_registry */ class ACL_internal_schema_access { public: ACL_internal_schema_access() = default; virtual ~ACL_internal_schema_access() = default; /** Check access to an internal schema. @param want_access the privileges requested @param [in, out] save_priv the privileges granted @return @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges are granted, and saved in save_priv. @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested privileges was denied. @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege was denied, and grant should be checked for at least one privilege. Requested privileges that are granted, if any, are saved in save_priv. */ virtual ACL_internal_access_result check(privilege_t want_access, privilege_t *save_priv) const= 0; /** Search for per table ACL access rules by table name. @param name the table name @return per table access rules, or NULL */ virtual const ACL_internal_table_access *lookup(const char *name) const= 0; }; /** A registry for per internal schema ACL. An 'internal schema' is a database schema maintained by the server implementation, such as 'performance_schema' and 'INFORMATION_SCHEMA'. */ class ACL_internal_schema_registry { public: static void register_schema(const LEX_CSTRING *name, const ACL_internal_schema_access *access); static const ACL_internal_schema_access *lookup(const char *name); }; const ACL_internal_schema_access * get_cached_schema_access(GRANT_INTERNAL_INFO *grant_internal_info, const char *schema_name); const ACL_internal_table_access * get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info, const char *schema_name, const char *table_name); bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user, bool with_grant); int acl_setrole(THD *thd, const char *rolename, privilege_t access); int acl_check_setrole(THD *thd, const char *rolename, privilege_t *access); int acl_check_set_default_role(THD *thd, const char *host, const char *user, const char *role); int acl_set_default_role(THD *thd, const char *host, const char *user, const char *rolename); extern SHOW_VAR acl_statistics[]; /* Check if a role is granted to a user/role. If hostname == NULL, search for a role as the starting grantee. */ bool check_role_is_granted(const char *username, const char *hostname, const char *rolename); #ifndef DBUG_OFF extern ulong role_global_merges, role_db_merges, role_table_merges, role_column_merges, role_routine_merges; #endif class Sql_cmd_grant: public Sql_cmd { protected: enum_sql_command m_command; #ifndef NO_EMBEDDED_ACCESS_CHECKS void warn_hostname_requires_resolving(THD *thd, List<LEX_USER> &list); bool user_list_reset_mqh(THD *thd, List<LEX_USER> &list); void grant_stage0(THD *thd); #endif public: Sql_cmd_grant(enum_sql_command command) :m_command(command) { } bool is_revoke() const { return m_command == SQLCOM_REVOKE; } enum_sql_command sql_command_code() const override { return m_command; } }; class Sql_cmd_grant_proxy: public Sql_cmd_grant { privilege_t m_grant_option; #ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access_proxy(THD *thd, List<LEX_USER> &list); #endif public: Sql_cmd_grant_proxy(enum_sql_command command, privilege_t grant_option) :Sql_cmd_grant(command), m_grant_option(grant_option) { } bool execute(THD *thd) override; }; class Sql_cmd_grant_object: public Sql_cmd_grant, public Grant_privilege { protected: #ifndef NO_EMBEDDED_ACCESS_CHECKS bool grant_stage0_exact_object(THD *thd, TABLE_LIST *table); #endif public: Sql_cmd_grant_object(enum_sql_command command, const Grant_privilege &grant) :Sql_cmd_grant(command), Grant_privilege(grant) { } }; class Sql_cmd_grant_table: public Sql_cmd_grant_object { #ifndef NO_EMBEDDED_ACCESS_CHECKS bool execute_table_mask(THD *thd); bool execute_exact_table(THD *thd, TABLE_LIST *table); #endif public: Sql_cmd_grant_table(enum_sql_command command, const Grant_privilege &grant) :Sql_cmd_grant_object(command, grant) { } bool execute(THD *thd) override; }; class Sql_cmd_grant_sp: public Sql_cmd_grant_object { const Sp_handler &m_sph; public: Sql_cmd_grant_sp(enum_sql_command command, const Grant_privilege &grant, const Sp_handler &sph) :Sql_cmd_grant_object(command, grant), m_sph(sph) { } bool execute(THD *thd) override; }; #endif /* SQL_ACL_INCLUDED */ probes_mysql_dtrace.h 0000644 00000100355 15156036163 0010770 0 ustar 00 /* Generated by the Systemtap dtrace wrapper */ #define _SDT_HAS_SEMAPHORES 1 #define STAP_HAS_SEMAPHORES 1 /* deprecated */ #include <sys/sdt.h> /* MYSQL_CONNECTION_START ( unsigned long conn_id, char * user, char * host ) */ #if defined STAP_SDT_V1 #define MYSQL_CONNECTION_START_ENABLED() __builtin_expect (connection__start_semaphore, 0) #define mysql_connection__start_semaphore connection__start_semaphore #else #define MYSQL_CONNECTION_START_ENABLED() __builtin_expect (mysql_connection__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_connection__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_CONNECTION_START(arg1, arg2, arg3) \ DTRACE_PROBE3 (mysql, connection__start, arg1, arg2, arg3) /* MYSQL_CONNECTION_DONE ( int status, unsigned long conn_id ) */ #if defined STAP_SDT_V1 #define MYSQL_CONNECTION_DONE_ENABLED() __builtin_expect (connection__done_semaphore, 0) #define mysql_connection__done_semaphore connection__done_semaphore #else #define MYSQL_CONNECTION_DONE_ENABLED() __builtin_expect (mysql_connection__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_connection__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_CONNECTION_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, connection__done, arg1, arg2) /* MYSQL_COMMAND_START ( unsigned long conn_id, int command, char * user, char * host ) */ #if defined STAP_SDT_V1 #define MYSQL_COMMAND_START_ENABLED() __builtin_expect (command__start_semaphore, 0) #define mysql_command__start_semaphore command__start_semaphore #else #define MYSQL_COMMAND_START_ENABLED() __builtin_expect (mysql_command__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_command__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_COMMAND_START(arg1, arg2, arg3, arg4) \ DTRACE_PROBE4 (mysql, command__start, arg1, arg2, arg3, arg4) /* MYSQL_COMMAND_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_COMMAND_DONE_ENABLED() __builtin_expect (command__done_semaphore, 0) #define mysql_command__done_semaphore command__done_semaphore #else #define MYSQL_COMMAND_DONE_ENABLED() __builtin_expect (mysql_command__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_command__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_COMMAND_DONE(arg1) \ DTRACE_PROBE1 (mysql, command__done, arg1) /* MYSQL_QUERY_START ( char * query, unsigned long conn_id, char * db_name, char * user, char * host ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_START_ENABLED() __builtin_expect (query__start_semaphore, 0) #define mysql_query__start_semaphore query__start_semaphore #else #define MYSQL_QUERY_START_ENABLED() __builtin_expect (mysql_query__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_START(arg1, arg2, arg3, arg4, arg5) \ DTRACE_PROBE5 (mysql, query__start, arg1, arg2, arg3, arg4, arg5) /* MYSQL_QUERY_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_DONE_ENABLED() __builtin_expect (query__done_semaphore, 0) #define mysql_query__done_semaphore query__done_semaphore #else #define MYSQL_QUERY_DONE_ENABLED() __builtin_expect (mysql_query__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_DONE(arg1) \ DTRACE_PROBE1 (mysql, query__done, arg1) /* MYSQL_QUERY_PARSE_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_PARSE_START_ENABLED() __builtin_expect (query__parse__start_semaphore, 0) #define mysql_query__parse__start_semaphore query__parse__start_semaphore #else #define MYSQL_QUERY_PARSE_START_ENABLED() __builtin_expect (mysql_query__parse__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__parse__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_PARSE_START(arg1) \ DTRACE_PROBE1 (mysql, query__parse__start, arg1) /* MYSQL_QUERY_PARSE_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_PARSE_DONE_ENABLED() __builtin_expect (query__parse__done_semaphore, 0) #define mysql_query__parse__done_semaphore query__parse__done_semaphore #else #define MYSQL_QUERY_PARSE_DONE_ENABLED() __builtin_expect (mysql_query__parse__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__parse__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_PARSE_DONE(arg1) \ DTRACE_PROBE1 (mysql, query__parse__done, arg1) /* MYSQL_QUERY_CACHE_HIT ( char * query, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_CACHE_HIT_ENABLED() __builtin_expect (query__cache__hit_semaphore, 0) #define mysql_query__cache__hit_semaphore query__cache__hit_semaphore #else #define MYSQL_QUERY_CACHE_HIT_ENABLED() __builtin_expect (mysql_query__cache__hit_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__cache__hit_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_CACHE_HIT(arg1, arg2) \ DTRACE_PROBE2 (mysql, query__cache__hit, arg1, arg2) /* MYSQL_QUERY_CACHE_MISS ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_CACHE_MISS_ENABLED() __builtin_expect (query__cache__miss_semaphore, 0) #define mysql_query__cache__miss_semaphore query__cache__miss_semaphore #else #define MYSQL_QUERY_CACHE_MISS_ENABLED() __builtin_expect (mysql_query__cache__miss_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__cache__miss_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_CACHE_MISS(arg1) \ DTRACE_PROBE1 (mysql, query__cache__miss, arg1) /* MYSQL_QUERY_EXEC_START ( char * query, unsigned long connid, char * db_name, char * user, char * host, int exec_type ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_EXEC_START_ENABLED() __builtin_expect (query__exec__start_semaphore, 0) #define mysql_query__exec__start_semaphore query__exec__start_semaphore #else #define MYSQL_QUERY_EXEC_START_ENABLED() __builtin_expect (mysql_query__exec__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__exec__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_EXEC_START(arg1, arg2, arg3, arg4, arg5, arg6) \ DTRACE_PROBE6 (mysql, query__exec__start, arg1, arg2, arg3, arg4, arg5, arg6) /* MYSQL_QUERY_EXEC_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_QUERY_EXEC_DONE_ENABLED() __builtin_expect (query__exec__done_semaphore, 0) #define mysql_query__exec__done_semaphore query__exec__done_semaphore #else #define MYSQL_QUERY_EXEC_DONE_ENABLED() __builtin_expect (mysql_query__exec__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_query__exec__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_QUERY_EXEC_DONE(arg1) \ DTRACE_PROBE1 (mysql, query__exec__done, arg1) /* MYSQL_INSERT_ROW_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_ROW_START_ENABLED() __builtin_expect (insert__row__start_semaphore, 0) #define mysql_insert__row__start_semaphore insert__row__start_semaphore #else #define MYSQL_INSERT_ROW_START_ENABLED() __builtin_expect (mysql_insert__row__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__row__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_ROW_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, insert__row__start, arg1, arg2) /* MYSQL_INSERT_ROW_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_ROW_DONE_ENABLED() __builtin_expect (insert__row__done_semaphore, 0) #define mysql_insert__row__done_semaphore insert__row__done_semaphore #else #define MYSQL_INSERT_ROW_DONE_ENABLED() __builtin_expect (mysql_insert__row__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__row__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_ROW_DONE(arg1) \ DTRACE_PROBE1 (mysql, insert__row__done, arg1) /* MYSQL_UPDATE_ROW_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_UPDATE_ROW_START_ENABLED() __builtin_expect (update__row__start_semaphore, 0) #define mysql_update__row__start_semaphore update__row__start_semaphore #else #define MYSQL_UPDATE_ROW_START_ENABLED() __builtin_expect (mysql_update__row__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_update__row__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_UPDATE_ROW_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, update__row__start, arg1, arg2) /* MYSQL_UPDATE_ROW_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_UPDATE_ROW_DONE_ENABLED() __builtin_expect (update__row__done_semaphore, 0) #define mysql_update__row__done_semaphore update__row__done_semaphore #else #define MYSQL_UPDATE_ROW_DONE_ENABLED() __builtin_expect (mysql_update__row__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_update__row__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_UPDATE_ROW_DONE(arg1) \ DTRACE_PROBE1 (mysql, update__row__done, arg1) /* MYSQL_DELETE_ROW_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_DELETE_ROW_START_ENABLED() __builtin_expect (delete__row__start_semaphore, 0) #define mysql_delete__row__start_semaphore delete__row__start_semaphore #else #define MYSQL_DELETE_ROW_START_ENABLED() __builtin_expect (mysql_delete__row__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_delete__row__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_DELETE_ROW_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, delete__row__start, arg1, arg2) /* MYSQL_DELETE_ROW_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_DELETE_ROW_DONE_ENABLED() __builtin_expect (delete__row__done_semaphore, 0) #define mysql_delete__row__done_semaphore delete__row__done_semaphore #else #define MYSQL_DELETE_ROW_DONE_ENABLED() __builtin_expect (mysql_delete__row__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_delete__row__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_DELETE_ROW_DONE(arg1) \ DTRACE_PROBE1 (mysql, delete__row__done, arg1) /* MYSQL_READ_ROW_START ( char * db, char * table, int scan_flag ) */ #if defined STAP_SDT_V1 #define MYSQL_READ_ROW_START_ENABLED() __builtin_expect (read__row__start_semaphore, 0) #define mysql_read__row__start_semaphore read__row__start_semaphore #else #define MYSQL_READ_ROW_START_ENABLED() __builtin_expect (mysql_read__row__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_read__row__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_READ_ROW_START(arg1, arg2, arg3) \ DTRACE_PROBE3 (mysql, read__row__start, arg1, arg2, arg3) /* MYSQL_READ_ROW_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_READ_ROW_DONE_ENABLED() __builtin_expect (read__row__done_semaphore, 0) #define mysql_read__row__done_semaphore read__row__done_semaphore #else #define MYSQL_READ_ROW_DONE_ENABLED() __builtin_expect (mysql_read__row__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_read__row__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_READ_ROW_DONE(arg1) \ DTRACE_PROBE1 (mysql, read__row__done, arg1) /* MYSQL_INDEX_READ_ROW_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_INDEX_READ_ROW_START_ENABLED() __builtin_expect (index__read__row__start_semaphore, 0) #define mysql_index__read__row__start_semaphore index__read__row__start_semaphore #else #define MYSQL_INDEX_READ_ROW_START_ENABLED() __builtin_expect (mysql_index__read__row__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_index__read__row__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INDEX_READ_ROW_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, index__read__row__start, arg1, arg2) /* MYSQL_INDEX_READ_ROW_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_INDEX_READ_ROW_DONE_ENABLED() __builtin_expect (index__read__row__done_semaphore, 0) #define mysql_index__read__row__done_semaphore index__read__row__done_semaphore #else #define MYSQL_INDEX_READ_ROW_DONE_ENABLED() __builtin_expect (mysql_index__read__row__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_index__read__row__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INDEX_READ_ROW_DONE(arg1) \ DTRACE_PROBE1 (mysql, index__read__row__done, arg1) /* MYSQL_HANDLER_RDLOCK_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_RDLOCK_START_ENABLED() __builtin_expect (handler__rdlock__start_semaphore, 0) #define mysql_handler__rdlock__start_semaphore handler__rdlock__start_semaphore #else #define MYSQL_HANDLER_RDLOCK_START_ENABLED() __builtin_expect (mysql_handler__rdlock__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__rdlock__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_RDLOCK_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, handler__rdlock__start, arg1, arg2) /* MYSQL_HANDLER_WRLOCK_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_WRLOCK_START_ENABLED() __builtin_expect (handler__wrlock__start_semaphore, 0) #define mysql_handler__wrlock__start_semaphore handler__wrlock__start_semaphore #else #define MYSQL_HANDLER_WRLOCK_START_ENABLED() __builtin_expect (mysql_handler__wrlock__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__wrlock__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_WRLOCK_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, handler__wrlock__start, arg1, arg2) /* MYSQL_HANDLER_UNLOCK_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_UNLOCK_START_ENABLED() __builtin_expect (handler__unlock__start_semaphore, 0) #define mysql_handler__unlock__start_semaphore handler__unlock__start_semaphore #else #define MYSQL_HANDLER_UNLOCK_START_ENABLED() __builtin_expect (mysql_handler__unlock__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__unlock__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_UNLOCK_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, handler__unlock__start, arg1, arg2) /* MYSQL_HANDLER_RDLOCK_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() __builtin_expect (handler__rdlock__done_semaphore, 0) #define mysql_handler__rdlock__done_semaphore handler__rdlock__done_semaphore #else #define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() __builtin_expect (mysql_handler__rdlock__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__rdlock__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_RDLOCK_DONE(arg1) \ DTRACE_PROBE1 (mysql, handler__rdlock__done, arg1) /* MYSQL_HANDLER_WRLOCK_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() __builtin_expect (handler__wrlock__done_semaphore, 0) #define mysql_handler__wrlock__done_semaphore handler__wrlock__done_semaphore #else #define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() __builtin_expect (mysql_handler__wrlock__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__wrlock__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_WRLOCK_DONE(arg1) \ DTRACE_PROBE1 (mysql, handler__wrlock__done, arg1) /* MYSQL_HANDLER_UNLOCK_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() __builtin_expect (handler__unlock__done_semaphore, 0) #define mysql_handler__unlock__done_semaphore handler__unlock__done_semaphore #else #define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() __builtin_expect (mysql_handler__unlock__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_handler__unlock__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_HANDLER_UNLOCK_DONE(arg1) \ DTRACE_PROBE1 (mysql, handler__unlock__done, arg1) /* MYSQL_FILESORT_START ( char * db, char * table ) */ #if defined STAP_SDT_V1 #define MYSQL_FILESORT_START_ENABLED() __builtin_expect (filesort__start_semaphore, 0) #define mysql_filesort__start_semaphore filesort__start_semaphore #else #define MYSQL_FILESORT_START_ENABLED() __builtin_expect (mysql_filesort__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_filesort__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_FILESORT_START(arg1, arg2) \ DTRACE_PROBE2 (mysql, filesort__start, arg1, arg2) /* MYSQL_FILESORT_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_FILESORT_DONE_ENABLED() __builtin_expect (filesort__done_semaphore, 0) #define mysql_filesort__done_semaphore filesort__done_semaphore #else #define MYSQL_FILESORT_DONE_ENABLED() __builtin_expect (mysql_filesort__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_filesort__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_FILESORT_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, filesort__done, arg1, arg2) /* MYSQL_SELECT_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_SELECT_START_ENABLED() __builtin_expect (select__start_semaphore, 0) #define mysql_select__start_semaphore select__start_semaphore #else #define MYSQL_SELECT_START_ENABLED() __builtin_expect (mysql_select__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_select__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_SELECT_START(arg1) \ DTRACE_PROBE1 (mysql, select__start, arg1) /* MYSQL_SELECT_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_SELECT_DONE_ENABLED() __builtin_expect (select__done_semaphore, 0) #define mysql_select__done_semaphore select__done_semaphore #else #define MYSQL_SELECT_DONE_ENABLED() __builtin_expect (mysql_select__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_select__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_SELECT_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, select__done, arg1, arg2) /* MYSQL_INSERT_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_START_ENABLED() __builtin_expect (insert__start_semaphore, 0) #define mysql_insert__start_semaphore insert__start_semaphore #else #define MYSQL_INSERT_START_ENABLED() __builtin_expect (mysql_insert__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_START(arg1) \ DTRACE_PROBE1 (mysql, insert__start, arg1) /* MYSQL_INSERT_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_DONE_ENABLED() __builtin_expect (insert__done_semaphore, 0) #define mysql_insert__done_semaphore insert__done_semaphore #else #define MYSQL_INSERT_DONE_ENABLED() __builtin_expect (mysql_insert__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, insert__done, arg1, arg2) /* MYSQL_INSERT_SELECT_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_SELECT_START_ENABLED() __builtin_expect (insert__select__start_semaphore, 0) #define mysql_insert__select__start_semaphore insert__select__start_semaphore #else #define MYSQL_INSERT_SELECT_START_ENABLED() __builtin_expect (mysql_insert__select__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__select__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_SELECT_START(arg1) \ DTRACE_PROBE1 (mysql, insert__select__start, arg1) /* MYSQL_INSERT_SELECT_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_INSERT_SELECT_DONE_ENABLED() __builtin_expect (insert__select__done_semaphore, 0) #define mysql_insert__select__done_semaphore insert__select__done_semaphore #else #define MYSQL_INSERT_SELECT_DONE_ENABLED() __builtin_expect (mysql_insert__select__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_insert__select__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_INSERT_SELECT_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, insert__select__done, arg1, arg2) /* MYSQL_UPDATE_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_UPDATE_START_ENABLED() __builtin_expect (update__start_semaphore, 0) #define mysql_update__start_semaphore update__start_semaphore #else #define MYSQL_UPDATE_START_ENABLED() __builtin_expect (mysql_update__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_update__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_UPDATE_START(arg1) \ DTRACE_PROBE1 (mysql, update__start, arg1) /* MYSQL_UPDATE_DONE ( int status, unsigned long rowsmatches, unsigned long rowschanged ) */ #if defined STAP_SDT_V1 #define MYSQL_UPDATE_DONE_ENABLED() __builtin_expect (update__done_semaphore, 0) #define mysql_update__done_semaphore update__done_semaphore #else #define MYSQL_UPDATE_DONE_ENABLED() __builtin_expect (mysql_update__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_update__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_UPDATE_DONE(arg1, arg2, arg3) \ DTRACE_PROBE3 (mysql, update__done, arg1, arg2, arg3) /* MYSQL_MULTI_UPDATE_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_MULTI_UPDATE_START_ENABLED() __builtin_expect (multi__update__start_semaphore, 0) #define mysql_multi__update__start_semaphore multi__update__start_semaphore #else #define MYSQL_MULTI_UPDATE_START_ENABLED() __builtin_expect (mysql_multi__update__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_multi__update__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_MULTI_UPDATE_START(arg1) \ DTRACE_PROBE1 (mysql, multi__update__start, arg1) /* MYSQL_MULTI_UPDATE_DONE ( int status, unsigned long rowsmatches, unsigned long rowschanged ) */ #if defined STAP_SDT_V1 #define MYSQL_MULTI_UPDATE_DONE_ENABLED() __builtin_expect (multi__update__done_semaphore, 0) #define mysql_multi__update__done_semaphore multi__update__done_semaphore #else #define MYSQL_MULTI_UPDATE_DONE_ENABLED() __builtin_expect (mysql_multi__update__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_multi__update__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_MULTI_UPDATE_DONE(arg1, arg2, arg3) \ DTRACE_PROBE3 (mysql, multi__update__done, arg1, arg2, arg3) /* MYSQL_DELETE_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_DELETE_START_ENABLED() __builtin_expect (delete__start_semaphore, 0) #define mysql_delete__start_semaphore delete__start_semaphore #else #define MYSQL_DELETE_START_ENABLED() __builtin_expect (mysql_delete__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_delete__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_DELETE_START(arg1) \ DTRACE_PROBE1 (mysql, delete__start, arg1) /* MYSQL_DELETE_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_DELETE_DONE_ENABLED() __builtin_expect (delete__done_semaphore, 0) #define mysql_delete__done_semaphore delete__done_semaphore #else #define MYSQL_DELETE_DONE_ENABLED() __builtin_expect (mysql_delete__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_delete__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_DELETE_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, delete__done, arg1, arg2) /* MYSQL_MULTI_DELETE_START ( char * query ) */ #if defined STAP_SDT_V1 #define MYSQL_MULTI_DELETE_START_ENABLED() __builtin_expect (multi__delete__start_semaphore, 0) #define mysql_multi__delete__start_semaphore multi__delete__start_semaphore #else #define MYSQL_MULTI_DELETE_START_ENABLED() __builtin_expect (mysql_multi__delete__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_multi__delete__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_MULTI_DELETE_START(arg1) \ DTRACE_PROBE1 (mysql, multi__delete__start, arg1) /* MYSQL_MULTI_DELETE_DONE ( int status, unsigned long rows ) */ #if defined STAP_SDT_V1 #define MYSQL_MULTI_DELETE_DONE_ENABLED() __builtin_expect (multi__delete__done_semaphore, 0) #define mysql_multi__delete__done_semaphore multi__delete__done_semaphore #else #define MYSQL_MULTI_DELETE_DONE_ENABLED() __builtin_expect (mysql_multi__delete__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_multi__delete__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_MULTI_DELETE_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, multi__delete__done, arg1, arg2) /* MYSQL_NET_READ_START ( ) */ #if defined STAP_SDT_V1 #define MYSQL_NET_READ_START_ENABLED() __builtin_expect (net__read__start_semaphore, 0) #define mysql_net__read__start_semaphore net__read__start_semaphore #else #define MYSQL_NET_READ_START_ENABLED() __builtin_expect (mysql_net__read__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_net__read__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_NET_READ_START() \ DTRACE_PROBE (mysql, net__read__start) /* MYSQL_NET_READ_DONE ( int status, unsigned long bytes ) */ #if defined STAP_SDT_V1 #define MYSQL_NET_READ_DONE_ENABLED() __builtin_expect (net__read__done_semaphore, 0) #define mysql_net__read__done_semaphore net__read__done_semaphore #else #define MYSQL_NET_READ_DONE_ENABLED() __builtin_expect (mysql_net__read__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_net__read__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_NET_READ_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, net__read__done, arg1, arg2) /* MYSQL_NET_WRITE_START ( unsigned long bytes ) */ #if defined STAP_SDT_V1 #define MYSQL_NET_WRITE_START_ENABLED() __builtin_expect (net__write__start_semaphore, 0) #define mysql_net__write__start_semaphore net__write__start_semaphore #else #define MYSQL_NET_WRITE_START_ENABLED() __builtin_expect (mysql_net__write__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_net__write__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_NET_WRITE_START(arg1) \ DTRACE_PROBE1 (mysql, net__write__start, arg1) /* MYSQL_NET_WRITE_DONE ( int status ) */ #if defined STAP_SDT_V1 #define MYSQL_NET_WRITE_DONE_ENABLED() __builtin_expect (net__write__done_semaphore, 0) #define mysql_net__write__done_semaphore net__write__done_semaphore #else #define MYSQL_NET_WRITE_DONE_ENABLED() __builtin_expect (mysql_net__write__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_net__write__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_NET_WRITE_DONE(arg1) \ DTRACE_PROBE1 (mysql, net__write__done, arg1) /* MYSQL_KEYCACHE_READ_START ( char * filepath, unsigned long bytes, unsigned long mem_used, unsigned long mem_free ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_READ_START_ENABLED() __builtin_expect (keycache__read__start_semaphore, 0) #define mysql_keycache__read__start_semaphore keycache__read__start_semaphore #else #define MYSQL_KEYCACHE_READ_START_ENABLED() __builtin_expect (mysql_keycache__read__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__read__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_READ_START(arg1, arg2, arg3, arg4) \ DTRACE_PROBE4 (mysql, keycache__read__start, arg1, arg2, arg3, arg4) /* MYSQL_KEYCACHE_READ_BLOCK ( unsigned long bytes ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() __builtin_expect (keycache__read__block_semaphore, 0) #define mysql_keycache__read__block_semaphore keycache__read__block_semaphore #else #define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() __builtin_expect (mysql_keycache__read__block_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__read__block_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_READ_BLOCK(arg1) \ DTRACE_PROBE1 (mysql, keycache__read__block, arg1) /* MYSQL_KEYCACHE_READ_HIT ( ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_READ_HIT_ENABLED() __builtin_expect (keycache__read__hit_semaphore, 0) #define mysql_keycache__read__hit_semaphore keycache__read__hit_semaphore #else #define MYSQL_KEYCACHE_READ_HIT_ENABLED() __builtin_expect (mysql_keycache__read__hit_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__read__hit_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_READ_HIT() \ DTRACE_PROBE (mysql, keycache__read__hit) /* MYSQL_KEYCACHE_READ_MISS ( ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_READ_MISS_ENABLED() __builtin_expect (keycache__read__miss_semaphore, 0) #define mysql_keycache__read__miss_semaphore keycache__read__miss_semaphore #else #define MYSQL_KEYCACHE_READ_MISS_ENABLED() __builtin_expect (mysql_keycache__read__miss_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__read__miss_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_READ_MISS() \ DTRACE_PROBE (mysql, keycache__read__miss) /* MYSQL_KEYCACHE_READ_DONE ( unsigned long mem_used, unsigned long mem_free ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_READ_DONE_ENABLED() __builtin_expect (keycache__read__done_semaphore, 0) #define mysql_keycache__read__done_semaphore keycache__read__done_semaphore #else #define MYSQL_KEYCACHE_READ_DONE_ENABLED() __builtin_expect (mysql_keycache__read__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__read__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_READ_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, keycache__read__done, arg1, arg2) /* MYSQL_KEYCACHE_WRITE_START ( char * filepath, unsigned long bytes, unsigned long mem_used, unsigned long mem_free ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_WRITE_START_ENABLED() __builtin_expect (keycache__write__start_semaphore, 0) #define mysql_keycache__write__start_semaphore keycache__write__start_semaphore #else #define MYSQL_KEYCACHE_WRITE_START_ENABLED() __builtin_expect (mysql_keycache__write__start_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__write__start_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_WRITE_START(arg1, arg2, arg3, arg4) \ DTRACE_PROBE4 (mysql, keycache__write__start, arg1, arg2, arg3, arg4) /* MYSQL_KEYCACHE_WRITE_BLOCK ( unsigned long bytes ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() __builtin_expect (keycache__write__block_semaphore, 0) #define mysql_keycache__write__block_semaphore keycache__write__block_semaphore #else #define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() __builtin_expect (mysql_keycache__write__block_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__write__block_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_WRITE_BLOCK(arg1) \ DTRACE_PROBE1 (mysql, keycache__write__block, arg1) /* MYSQL_KEYCACHE_WRITE_DONE ( unsigned long mem_used, unsigned long mem_free ) */ #if defined STAP_SDT_V1 #define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() __builtin_expect (keycache__write__done_semaphore, 0) #define mysql_keycache__write__done_semaphore keycache__write__done_semaphore #else #define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() __builtin_expect (mysql_keycache__write__done_semaphore, 0) #endif __extension__ extern unsigned short mysql_keycache__write__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); #define MYSQL_KEYCACHE_WRITE_DONE(arg1, arg2) \ DTRACE_PROBE2 (mysql, keycache__write__done, arg1, arg2) slave.h 0000644 00000027763 15156036163 0006054 0 ustar 00 /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SLAVE_H #define SLAVE_H /** MASTER_DELAY can be at most (1 << 31) - 1. */ #define MASTER_DELAY_MAX (0x7FFFFFFF) #if INT_MAX < 0x7FFFFFFF #error "don't support platforms where INT_MAX < 0x7FFFFFFF" #endif /** @defgroup Replication Replication @{ @file */ /** Some of defines are need in parser even though replication is not compiled in (embedded). */ /** The maximum is defined as (ULONG_MAX/1000) with 4 bytes ulong */ #define SLAVE_MAX_HEARTBEAT_PERIOD 4294967 #ifdef HAVE_REPLICATION #include "log.h" #include "my_list.h" #include "rpl_filter.h" #include "rpl_tblmap.h" #include "rpl_gtid.h" #include "log_event.h" #define SLAVE_NET_TIMEOUT 60 #define MAX_SLAVE_ERROR ER_ERROR_LAST+1 #define MAX_REPLICATION_THREAD 64 // Forward declarations class Relay_log_info; class Master_info; class Master_info_index; struct rpl_group_info; struct rpl_parallel_thread; int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val); int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val); int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); /***************************************************************************** MySQL Replication Replication is implemented via two types of threads: I/O Thread - One of these threads is started for each master server. They maintain a connection to their master server, read log events from the master as they arrive, and queues them into a single, shared relay log file. A Master_info represents each of these threads. SQL Thread - One of these threads is started and reads from the relay log file, executing each event. A Relay_log_info represents this thread. Buffering in the relay log file makes it unnecessary to reread events from a master server across a slave restart. It also decouples the slave from the master where long-running updates and event logging are concerned--ie it can continue to log new events while a slow query executes on the slave. *****************************************************************************/ /* MUTEXES in replication: LOCK_active_mi: [note: this was originally meant for multimaster, to switch from a master to another, to protect active_mi] It is used to SERIALIZE ALL administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not need it it's called early]. Any of these commands holds the mutex from the start till the end. This thus protects us against a handful of deadlocks (consider start_slave_thread() which, when starting the I/O thread, releases mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock). Currently active_mi never moves (it's created at startup and deleted at shutdown, and not changed: it always points to the same Master_info struct), because we don't have multimaster. So for the moment, mi does not move, and mi->rli does not either. In Master_info: run_lock, data_lock run_lock protects all information about the run state: slave_running, thd and the existence of the I/O thread (to stop/start it, you need this mutex). data_lock protects some moving members of the struct: counters (log name, position) and relay log (MYSQL_BIN_LOG object). In Relay_log_info: run_lock, data_lock see Master_info However, note that run_lock does not protect Relay_log_info.run_state; that is protected by data_lock. Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you must acquire LOCK_active_mi first. In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog (so that you have to update the .index file). */ extern ulong master_retry_count; extern MY_BITMAP slave_error_mask; extern char slave_skip_error_names[]; extern bool use_slave_mask; extern char slave_transaction_retry_error_names[]; extern uint *slave_transaction_retry_errors; extern uint slave_transaction_retry_error_length; extern char *slave_load_tmpdir; extern char *master_info_file; extern MYSQL_PLUGIN_IMPORT char *relay_log_info_file; extern char *opt_relay_logname, *opt_relaylog_index_name; extern my_bool opt_skip_slave_start, opt_reckless_slave; extern my_bool opt_log_slave_updates; extern char *opt_slave_skip_errors; extern char *opt_slave_transaction_retry_errors; extern my_bool opt_replicate_annotate_row_events; extern ulonglong relay_log_space_limit; extern ulonglong opt_read_binlog_speed_limit; extern ulonglong slave_skipped_errors; extern const char *relay_log_index; extern const char *relay_log_basename; /* 4 possible values for Master_info::slave_running and Relay_log_info::slave_running. The values 0,1,2,3 are very important: to keep the diff small, I didn't substitute places where we use 0/1 with the newly defined symbols. So don't change these values. The same way, code is assuming that in Relay_log_info we use only values 0/1. I started with using an enum, but enum_variable=1; is not legal so would have required many line changes. */ #define MYSQL_SLAVE_NOT_RUN 0 #define MYSQL_SLAVE_RUN_NOT_CONNECT 1 #define MYSQL_SLAVE_RUN_CONNECT 2 #define MYSQL_SLAVE_RUN_READING 3 #define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\ "FIRST") #define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\ "FIRST") /* If the following is set, if first gives an error, second will be tried. Otherwise, if first fails, we fail. */ #define SLAVE_FORCE_ALL 4 /* Values for the option --replicate-events-marked-for-skip. Must match the names in replicate_events_marked_for_skip_names in sys_vars.cc */ #define RPL_SKIP_REPLICATE 0 #define RPL_SKIP_FILTER_ON_SLAVE 1 #define RPL_SKIP_FILTER_ON_MASTER 2 int init_slave(); int init_recovery(Master_info* mi, const char** errmsg); bool init_slave_skip_errors(const char* arg); bool init_slave_transaction_retry_errors(const char* arg); int register_slave_on_master(MYSQL* mysql); int terminate_slave_threads(Master_info* mi, int thread_mask, bool skip_lock = 0); int start_slave_threads(THD *thd, bool need_slave_mutex, bool wait_for_start, Master_info* mi, const char* master_info_fname, const char* slave_info_fname, int thread_mask); /* cond_lock is usually same as start_lock. It is needed for the case when start_lock is 0 which happens if start_slave_thread() is called already inside the start_lock section, but at the same time we want a mysql_cond_wait() on start_cond, start_lock */ int start_slave_thread( #ifdef HAVE_PSI_INTERFACE PSI_thread_key thread_key, #endif pthread_handler h_func, mysql_mutex_t *start_lock, mysql_mutex_t *cond_lock, mysql_cond_t *start_cond, volatile uint *slave_running, volatile ulong *slave_run_id, Master_info *mi); /* If fd is -1, dump to NET */ int mysql_table_dump(THD* thd, const char* db, const char* tbl_name, int fd = -1); /* retrieve table from master and copy to slave*/ int fetch_master_table(THD* thd, const char* db_name, const char* table_name, Master_info* mi, MYSQL* mysql, bool overwrite); void show_master_info_get_fields(THD *thd, List<Item> *field_list, bool full, size_t gtid_pos_length); bool show_master_info(THD* thd, Master_info* mi, bool full); bool show_all_master_info(THD* thd); void show_binlog_info_get_fields(THD *thd, List<Item> *field_list); bool show_binlog_info(THD* thd); bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, bool (*pred)(const void *), const void *param, bool maria_master= false); bool rpl_master_erroneous_autoinc(THD* thd); const char *print_slave_db_safe(const char *db); void skip_load_data_infile(NET* net); void slave_prepare_for_shutdown(); void end_slave(); /* release slave threads */ void close_active_mi(); /* clean up slave threads data */ void clear_until_condition(Relay_log_info* rli); void clear_slave_error(Relay_log_info* rli); void end_relay_log_info(Relay_log_info* rli); void init_thread_mask(int* mask,Master_info* mi,bool inverse); Format_description_log_event * read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos, const char **errmsg); int init_relay_log_pos(Relay_log_info* rli,const char* log,ulonglong pos, bool need_data_lock, const char** errmsg, bool look_for_description_event); int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); void set_slave_thread_default_charset(THD *thd, rpl_group_info *rgi); int rotate_relay_log(Master_info* mi); int has_temporary_error(THD *thd); int sql_delay_event(Log_event *ev, THD *thd, rpl_group_info *rgi); int apply_event_and_update_pos(Log_event* ev, THD* thd, struct rpl_group_info *rgi); int apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd, struct rpl_group_info *rgi); int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val); int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val); int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); pthread_handler_t handle_slave_io(void *arg); void slave_output_error_info(rpl_group_info *rgi, THD *thd); pthread_handler_t handle_slave_sql(void *arg); bool net_request_file(NET* net, const char* fname); void slave_background_kill_request(THD *to_kill); void slave_background_gtid_pos_create_request (rpl_slave_state::gtid_pos_table *table_entry); void slave_background_gtid_pending_delete_request(void); extern Master_info *active_mi; /* active_mi for multi-master */ extern Master_info *default_master_info; /* To replace active_mi */ extern Master_info_index *master_info_index; extern LEX_CSTRING default_master_connection_name; extern my_bool replicate_same_server_id; extern int disconnect_slave_event_count, abort_slave_event_count ; /* the master variables are defaults read from my.cnf or command line */ extern uint report_port; extern char *master_info_file, *report_user; extern char *report_host, *report_password; extern I_List<THD> threads; /* Check that a binlog event (read from the relay log) is valid to update last_master_timestamp. That is, a valid event is one with a consistent timestamp which originated from a primary server. */ static inline bool event_can_update_last_master_timestamp(Log_event *ev) { return ev && !(ev->is_artificial_event() || ev->is_relay_log_event() || (ev->when == 0)); } #else #define close_active_mi() /* no-op */ #endif /* HAVE_REPLICATION */ /* masks for start/stop operations on io and sql slave threads */ #define SLAVE_IO 1 #define SLAVE_SQL 2 /** @} (end of group Replication) */ #endif sql_cmd.h 0000644 00000027343 15156036163 0006356 0 ustar 00 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file Representation of an SQL command. */ #ifndef SQL_CMD_INCLUDED #define SQL_CMD_INCLUDED #include <my_base.h> #include "sql_command.h" class Storage_engine_name { protected: LEX_CSTRING m_storage_engine_name; public: Storage_engine_name() { m_storage_engine_name.str= NULL; m_storage_engine_name.length= 0; } Storage_engine_name(const LEX_CSTRING &name) :m_storage_engine_name(name) { } bool resolve_storage_engine_with_error(THD *thd, handlerton **ha, bool tmp_table); bool is_set() { return m_storage_engine_name.str != NULL; } const LEX_CSTRING *name() const { return &m_storage_engine_name; } }; class Prepared_statement; /** @class Sql_cmd - Representation of an SQL command. This class is an interface between the parser and the runtime. The parser builds the appropriate derived classes of Sql_cmd to represent a SQL statement in the parsed tree. The execute() method in the derived classes of Sql_cmd contain the runtime implementation. Note that this interface is used for SQL statements recently implemented, the code for older statements tend to load the LEX structure with more attributes instead. Implement new statements by sub-classing Sql_cmd, as this improves code modularity (see the 'big switch' in dispatch_command()), and decreases the total size of the LEX structure (therefore saving memory in stored programs). The recommended name of a derived class of Sql_cmd is Sql_cmd_<derived>. Notice that the Sql_cmd class should not be confused with the Statement class. Statement is a class that is used to manage an SQL command or a set of SQL commands. When the SQL statement text is analyzed, the parser will create one or more Sql_cmd objects to represent the actual SQL commands. */ class Sql_cmd : public Sql_alloc { private: Sql_cmd(const Sql_cmd &); // No copy constructor wanted void operator=(Sql_cmd &); // No assignment operator wanted public: /** @brief Return the command code for this statement */ virtual enum_sql_command sql_command_code() const = 0; /** @brief Check whether the statement has been prepared @returns true if this statement is prepared, false otherwise */ bool is_prepared() const { return m_prepared; } /** @brief Prepare this SQL statement @param thd global context the processed statement @returns false if success, true if error */ virtual bool prepare(THD *thd) { /* Default behavior for a statement is to have no preparation code. */ DBUG_ASSERT(!is_prepared()); set_prepared(); return false; } /** @brief Execute this SQL statement @param thd global context the processed statement @returns false if success, true if error */ virtual bool execute(THD *thd) = 0; virtual Storage_engine_name *option_storage_engine_name() { return NULL; } /** @brief Set the owning prepared statement */ void set_owner(Prepared_statement *stmt) { m_owner = stmt; } /** @breaf Get the owning prepared statement */ Prepared_statement *get_owner() { return m_owner; } /** @brief Check whether this command is a DML statement @return true if SQL command is a DML statement, false otherwise */ virtual bool is_dml() const { return false; } virtual void get_dml_stat (ha_rows &found, ha_rows &changed) { found= changed= 0; } /** @brief Unprepare prepared statement for the command @param thd global context of the processed statement @notes Temporary function used to "unprepare" a prepared statement after preparation, so that a subsequent execute statement will reprepare it. This is done because UNIT::cleanup() will un-resolve all resolved QBs. */ virtual void unprepare(THD *thd) { DBUG_ASSERT(is_prepared()); m_prepared = false; } protected: Sql_cmd() : m_prepared(false), m_owner(nullptr) {} virtual ~Sql_cmd() { /* Sql_cmd objects are allocated in thd->mem_root. In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is simply destroyed instead. Do not rely on the destructor for any cleanup. */ DBUG_ASSERT(false); } /** @brief Set this statement as prepared */ void set_prepared() { m_prepared = true; } private: /* True when statement has been prepared */ bool m_prepared; /* Owning prepared statement, nullptr if not prepared */ Prepared_statement *m_owner; }; struct LEX; class select_result; class Prelocking_strategy; class DML_prelocking_strategy; class Protocol; /** @class Sql_cmd_dml - derivative abstract class used for DML statements This class is a class derived from Sql_cmd used when processing such data manipulation commands as SELECT, INSERT, UPDATE, DELETE and others that operate over some tables. After the parser phase all these commands are supposed to be processed by the same schema: - precheck of the access rights is performed for the used tables - the used tables are opened - context analysis phase is performed for the statement - the used tables are locked - the statement is optimized and executed - clean-up is performed for the statement. This schema is reflected in the function Sql_cmd_dml::execute() that uses Sql_cmd_dml::prepare is the statement has not been prepared yet. Precheck of the access right, context analysis are specific for statements of a certain type. That's why the methods implementing this operations are declared as abstract in this class. @note Currently this class is used only for UPDATE and DELETE commands. */ class Sql_cmd_dml : public Sql_cmd { public: /** @brief Check whether the statement changes the contents of used tables @return true if this is data change statement, false otherwise */ virtual bool is_data_change_stmt() const { return true; } /** @brief Perform context analysis of the statement @param thd global context the processed statement @returns false on success, true on error */ bool prepare(THD *thd) override; /** Execute the processed statement once @param thd global context the processed statement @returns false on success, true on error */ bool execute(THD *thd) override; bool is_dml() const override { return true; } select_result *get_result() { return result; } protected: Sql_cmd_dml() : Sql_cmd(), lex(nullptr), result(nullptr), m_empty_query(false) {} /** @brief Check whether query is guaranteed to return no data @return true if query is guaranteed to return no data, false otherwise @todo Also check this for the following cases: - Empty source for multi-table UPDATE and DELETE. - Check empty query expression for INSERT */ bool is_empty_query() const { DBUG_ASSERT(is_prepared()); return m_empty_query; } /** @brief Set statement as returning no data */ void set_empty_query() { m_empty_query = true; } /** @brief Perform precheck of table privileges for the specific command @param thd global context the processed statement @returns false if success, true if false @details Check that user has some relevant privileges for all tables involved in the statement, e.g. SELECT privileges for tables selected from, INSERT privileges for tables inserted into, etc. This function will also populate TABLE_LIST::grant with all privileges the user has for each table, which is later used during checking of column privileges. Note that at preparation time, views are not expanded yet. Privilege checking is thus rudimentary and must be complemented with later calls to SELECT_LEX::check_view_privileges(). The reason to call this function at such an early stage is to be able to quickly reject statements for which the user obviously has insufficient privileges. */ virtual bool precheck(THD *thd) = 0; /** @brief Perform the command-specific actions of the context analysis @param thd global context the processed statement @returns false if success, true if error @note This function is called from prepare() */ virtual bool prepare_inner(THD *thd) = 0; /** @brief Perform the command-specific actions of optimization and excution @param thd global context the processed statement @returns false on success, true on error */ virtual bool execute_inner(THD *thd); virtual DML_prelocking_strategy *get_dml_prelocking_strategy() = 0; uint table_count; protected: LEX *lex; /**< Pointer to LEX for this statement */ select_result *result; /**< Pointer to object for handling of the result */ bool m_empty_query; /**< True if query will produce no rows */ }; class Sql_cmd_show_slave_status: public Sql_cmd { protected: bool show_all_slaves_status; public: Sql_cmd_show_slave_status() :show_all_slaves_status(false) {} Sql_cmd_show_slave_status(bool status_all) :show_all_slaves_status(status_all) {} enum_sql_command sql_command_code() const override { return SQLCOM_SHOW_SLAVE_STAT; } bool execute(THD *thd) override; bool is_show_all_slaves_stat() { return show_all_slaves_status; } }; class Sql_cmd_create_table_like: public Sql_cmd, public Storage_engine_name { public: Storage_engine_name *option_storage_engine_name() override { return this; } bool execute(THD *thd) override; }; class Sql_cmd_create_table: public Sql_cmd_create_table_like { public: enum_sql_command sql_command_code() const override { return SQLCOM_CREATE_TABLE; } }; class Sql_cmd_create_sequence: public Sql_cmd_create_table_like { public: enum_sql_command sql_command_code() const override { return SQLCOM_CREATE_SEQUENCE; } }; /** Sql_cmd_call represents the CALL statement. */ class Sql_cmd_call : public Sql_cmd { public: class sp_name *m_name; const class Sp_handler *m_handler; Sql_cmd_call(class sp_name *name, const class Sp_handler *handler) :m_name(name), m_handler(handler) {} virtual ~Sql_cmd_call() = default; /** Execute a CALL statement at runtime. @param thd the current thread. @return false on success. */ bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_CALL; } }; #ifndef DBUG_OFF /** Sql_cmd_call represents the SHOW CODE statement: - SHOW PROCEDURE CODE - SHOW FUNCTION CODE - SHOW PACKAGE BODY CODE */ class Sql_cmd_show_routine_code : public Sql_cmd { public: class sp_name *m_name; const class Sp_handler *m_handler; enum_sql_command m_sql_command; Sql_cmd_show_routine_code(class sp_name *name, const class Sp_handler *handler, enum_sql_command sql_command) :m_name(name), m_handler(handler), m_sql_command(sql_command) {} virtual ~Sql_cmd_show_routine_code() = default; bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return m_sql_command; } }; #endif // DBUG_OFF #endif // SQL_CMD_INCLUDED debug.h 0000644 00000002411 15156036163 0006007 0 ustar 00 #ifndef DEBUG_INCLUDED #define DEBUG_INCLUDED /* Copyright (c) 2021, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file Declarations for debug_crash_here and other future mariadb server debug functionality. */ /* debug_crash_here() functionallity. See mysql_test/suite/atomic/create_table.test for an example of how it can be used */ #ifndef DBUG_OFF void debug_crash_here(const char *keyword); bool debug_simulate_error(const char *keyword, uint error); bool debug_decrement_counter(const LEX_CSTRING *name); #else #define debug_crash_here(A) do { } while(0) #define debug_simulate_error(A, B) 0 #endif #endif /* DEBUG_INCLUDED */ item_timefunc.h 0000644 00000200746 15156036163 0007564 0 ustar 00 #ifndef ITEM_TIMEFUNC_INCLUDED #define ITEM_TIMEFUNC_INCLUDED /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. Copyright (c) 2009-2011, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Function items used by mysql */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif class MY_LOCALE; bool get_interval_value(THD *thd, Item *args, interval_type int_type, INTERVAL *interval); class Item_long_func_date_field: public Item_long_ge0_func { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()); } public: Item_long_func_date_field(THD *thd, Item *a) :Item_long_ge0_func(thd, a) { } }; class Item_long_func_time_field: public Item_long_ge0_func { bool check_arguments() const override { return args[0]->check_type_can_return_time(func_name_cstring()); } public: Item_long_func_time_field(THD *thd, Item *a) :Item_long_ge0_func(thd, a) { } }; class Item_func_period_add :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_int(0, 2); } public: Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("period_add") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_period_add>(thd, this); } }; class Item_func_period_diff :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_int(0, 2); } public: Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("period_diff") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_period_diff>(thd, this); } }; class Item_func_to_days :public Item_long_func_date_field { public: Item_func_to_days(THD *thd, Item *a): Item_long_func_date_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("to_days") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } enum_monotonicity_info get_monotonicity_info() const override; longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_to_days>(thd, this); } }; class Item_func_to_seconds :public Item_longlong_func { bool check_arguments() const override { return check_argument_types_can_return_date(0, arg_count); } public: Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("to_seconds") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; fix_char_length(12); set_maybe_null(); return FALSE; } enum_monotonicity_info get_monotonicity_info() const override; longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool check_partition_func_processor(void *bool_arg) override { return FALSE;} /* Only meaningful with date part and optional time part */ bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_to_seconds>(thd, this); } }; class Item_func_dayofmonth :public Item_long_func_date_field { public: Item_func_dayofmonth(THD *thd, Item *a): Item_long_func_date_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("dayofmonth") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dayofmonth>(thd, this); } }; class Item_func_month :public Item_long_ge0_func { public: Item_func_month(THD *thd, Item *a): Item_long_ge0_func(thd, a) { } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("month") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals= 0; fix_char_length(2); set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_month>(thd, this); } }; class Item_func_monthname :public Item_str_func { MY_LOCALE *locale; public: Item_func_monthname(THD *thd, Item *a): Item_str_func(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("monthname") }; return name; } String *val_str(String *str) override; bool fix_length_and_dec(THD *thd) override; bool check_partition_func_processor(void *int_arg) override {return TRUE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_monthname>(thd, this); } }; class Item_func_dayofyear :public Item_long_func_date_field { public: Item_func_dayofyear(THD *thd, Item *a): Item_long_func_date_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("dayofyear") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals= 0; fix_char_length(3); set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dayofyear>(thd, this); } }; class Item_func_hour :public Item_long_func_time_field { public: Item_func_hour(THD *thd, Item *a): Item_long_func_time_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("hour") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_time_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_hour>(thd, this); } }; class Item_func_minute :public Item_long_func_time_field { public: Item_func_minute(THD *thd, Item *a): Item_long_func_time_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("minute") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_time_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_minute>(thd, this); } }; class Item_func_quarter :public Item_long_func_date_field { public: Item_func_quarter(THD *thd, Item *a): Item_long_func_date_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("quarter") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=1*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_quarter>(thd, this); } }; class Item_func_second :public Item_long_func_time_field { public: Item_func_second(THD *thd, Item *a): Item_long_func_time_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("second") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_time_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_second>(thd, this); } }; class Item_func_week :public Item_long_ge0_func { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()) || (arg_count > 1 && args[1]->check_type_can_return_int(func_name_cstring())); } public: Item_func_week(THD *thd, Item *a): Item_long_ge0_func(thd, a) {} Item_func_week(THD *thd, Item *a, Item *b): Item_long_ge0_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("week") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_vcol_func_processor(void *arg) override { if (arg_count == 2) return FALSE; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } bool check_valid_arguments_processor(void *int_arg) override { return arg_count == 2; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_week>(thd, this); } }; class Item_func_yearweek :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()) || args[1]->check_type_can_return_int(func_name_cstring()); } public: Item_func_yearweek(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("yearweek") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_yearweek>(thd, this); } }; class Item_func_year :public Item_long_func_date_field { public: Item_func_year(THD *thd, Item *a): Item_long_func_date_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("year") }; return name; } enum Functype functype() const override { return YEAR_FUNC; } enum_monotonicity_info get_monotonicity_info() const override; longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=4*MY_CHARSET_BIN_MB_MAXLEN; set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_year>(thd, this); } }; class Item_func_weekday :public Item_long_func { bool odbc_type; public: Item_func_weekday(THD *thd, Item *a, bool type_arg): Item_long_func(thd, a), odbc_type(type_arg) { } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING dayofweek= {STRING_WITH_LEN("dayofweek") }; static LEX_CSTRING weekday= {STRING_WITH_LEN("weekday") }; return (odbc_type ? dayofweek : weekday); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } bool fix_length_and_dec(THD *thd) override { decimals= 0; fix_char_length(1); set_maybe_null(); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_weekday>(thd, this); } }; class Item_func_dayname :public Item_str_func { MY_LOCALE *locale; public: Item_func_dayname(THD *thd, Item *a): Item_str_func(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("dayname") }; return name; } String *val_str(String *str) override; const Type_handler *type_handler() const override { return &type_handler_varchar; } bool fix_length_and_dec(THD *thd) override; bool check_partition_func_processor(void *int_arg) override {return TRUE;} bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } bool check_valid_arguments_processor(void *int_arg) override { return !has_date_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_dayname>(thd, this); } }; class Item_func_seconds_hybrid: public Item_func_numhybrid { public: Item_func_seconds_hybrid(THD *thd): Item_func_numhybrid(thd) {} Item_func_seconds_hybrid(THD *thd, Item *a): Item_func_numhybrid(thd, a) {} void fix_length_and_dec_generic(decimal_digits_t dec) { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); decimals= dec; max_length=17 + (decimals ? decimals + 1 : 0); set_maybe_null(); if (decimals) set_handler(&type_handler_newdecimal); else set_handler(type_handler_long_or_longlong()); } double real_op() override { DBUG_ASSERT(0); return 0; } String *str_op(String *str) override { DBUG_ASSERT(0); return 0; } bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { DBUG_ASSERT(0); return true; } }; class Item_func_unix_timestamp :public Item_func_seconds_hybrid { bool get_timestamp_value(my_time_t *seconds, ulong *second_part); public: Item_func_unix_timestamp(THD *thd): Item_func_seconds_hybrid(thd) {} Item_func_unix_timestamp(THD *thd, Item *a): Item_func_seconds_hybrid(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("unix_timestamp") }; return name; } enum_monotonicity_info get_monotonicity_info() const override; longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} /* UNIX_TIMESTAMP() depends on the current timezone (and thus may not be used as a partitioning function) when its argument is NOT of the TIMESTAMP type. */ bool check_valid_arguments_processor(void *int_arg) override { return !has_timestamp_args(); } bool check_vcol_func_processor(void *arg) override { if (arg_count) return FALSE; return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC); } bool fix_length_and_dec(THD *thd) override { fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision(thd) : 0); return FALSE; } longlong int_op() override; my_decimal *decimal_op(my_decimal* buf) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_unix_timestamp>(thd, this); } }; class Item_func_time_to_sec :public Item_func_seconds_hybrid { public: Item_func_time_to_sec(THD *thd, Item *item): Item_func_seconds_hybrid(thd, item) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("time_to_sec") }; return name; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_time_args(); } bool fix_length_and_dec(THD *thd) override { fix_length_and_dec_generic(args[0]->time_precision(thd)); return FALSE; } longlong int_op() override; my_decimal *decimal_op(my_decimal* buf) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_time_to_sec>(thd, this); } }; class Item_datefunc :public Item_func { public: Item_datefunc(THD *thd): Item_func(thd) { } Item_datefunc(THD *thd, Item *a): Item_func(thd, a) { } Item_datefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { } const Type_handler *type_handler() const override { return &type_handler_newdate; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return Date(this).to_longlong(); } double val_real() override { return Date(this).to_double(); } String *val_str(String *to) override { return Date(this).to_string(to); } my_decimal *val_decimal(my_decimal *to) override { return Date(this).to_decimal(to); } bool fix_length_and_dec(THD *thd) override { fix_attributes_date(); set_maybe_null(arg_count > 0); return FALSE; } }; class Item_timefunc :public Item_func { public: Item_timefunc(THD *thd): Item_func(thd) {} Item_timefunc(THD *thd, Item *a): Item_func(thd, a) {} Item_timefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} Item_timefunc(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const override { return &type_handler_time2; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return Time(this).to_longlong(); } double val_real() override { return Time(this).to_double(); } String *val_str(String *to) override { return Time(this).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return Time(this).to_decimal(to); } bool val_native(THD *thd, Native *to) override { return Time(thd, this).to_native(to, decimals); } }; class Item_datetimefunc :public Item_func { public: Item_datetimefunc(THD *thd): Item_func(thd) {} Item_datetimefunc(THD *thd, Item *a): Item_func(thd, a) {} Item_datetimefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} Item_datetimefunc(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const override { return &type_handler_datetime2; } longlong val_int() override { DBUG_ASSERT(!is_cond()); return Datetime(this).to_longlong(); } double val_real() override { return Datetime(this).to_double(); } String *val_str(String *to) override { return Datetime(this).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) override { return Datetime(this).to_decimal(to); } }; /* Abstract CURTIME function. Children should define what time zone is used */ class Item_func_curtime :public Item_timefunc { MYSQL_TIME ltime; query_id_t last_query_id; public: Item_func_curtime(THD *thd, decimal_digits_t dec): Item_timefunc(thd), last_query_id(0) { decimals= dec; } bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override { fix_attributes_time(decimals); return FALSE; } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; /* Abstract method that defines which time zone is used for conversion. Converts time current time in my_time_t representation to broken-down MYSQL_TIME representation using UTC-SYSTEM or per-thread time zone. */ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC); } void print(String *str, enum_query_type query_type) override; }; class Item_func_curtime_local :public Item_func_curtime { public: Item_func_curtime_local(THD *thd, decimal_digits_t dec): Item_func_curtime(thd, dec) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("curtime") }; return name; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_curtime_local>(thd, this); } }; class Item_func_curtime_utc :public Item_func_curtime { public: Item_func_curtime_utc(THD *thd, decimal_digits_t dec): Item_func_curtime(thd, dec) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("utc_time") }; return name; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_curtime_utc>(thd, this); } }; /* Abstract CURDATE function. See also Item_func_curtime. */ class Item_func_curdate :public Item_datefunc { query_id_t last_query_id; MYSQL_TIME ltime; public: Item_func_curdate(THD *thd): Item_datefunc(thd), last_query_id(0) {} bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC); } }; class Item_func_curdate_local :public Item_func_curdate { public: Item_func_curdate_local(THD *thd): Item_func_curdate(thd) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("curdate") }; return name; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_curdate_local>(thd, this); } }; class Item_func_curdate_utc :public Item_func_curdate { public: Item_func_curdate_utc(THD *thd): Item_func_curdate(thd) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("utc_date") }; return name; } void store_now_in_TIME(THD* thd, MYSQL_TIME *now_time) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_curdate_utc>(thd, this); } }; /* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */ class Item_func_now :public Item_datetimefunc { MYSQL_TIME ltime; query_id_t last_query_id; public: Item_func_now(THD *thd, decimal_digits_t dec): Item_datetimefunc(thd), last_query_id(0) { decimals= dec; } bool fix_fields(THD *, Item **) override; bool fix_length_and_dec(THD *thd) override { fix_attributes_datetime(decimals); return FALSE;} bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0; bool check_vcol_func_processor(void *arg) override { /* NOW is safe for replication as slaves will run with same time as master */ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC); } void print(String *str, enum_query_type query_type) override; }; class Item_func_now_local :public Item_func_now { public: Item_func_now_local(THD *thd, decimal_digits_t dec): Item_func_now(thd, dec) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("current_timestamp") }; return name; } int save_in_field(Field *field, bool no_conversions) override; void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; enum Functype functype() const override { return NOW_FUNC; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_now_local>(thd, this); } }; class Item_func_now_utc :public Item_func_now { public: Item_func_now_utc(THD *thd, decimal_digits_t dec): Item_func_now(thd, dec) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("utc_timestamp") }; return name; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; enum Functype functype() const override { return NOW_UTC_FUNC; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC | VCOL_NON_DETERMINISTIC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_now_utc>(thd, this); } }; /* This is like NOW(), but always uses the real current time, not the query_start(). This matches the Oracle behavior. */ class Item_func_sysdate_local :public Item_func_now { public: Item_func_sysdate_local(THD *thd, decimal_digits_t dec): Item_func_now(thd, dec) {} bool const_item() const override { return 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sysdate") }; return name; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; table_map used_tables() const override { return RAND_TABLE_BIT; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC | VCOL_NON_DETERMINISTIC); } enum Functype functype() const override { return SYSDATE_FUNC; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sysdate_local>(thd, this); } }; class Item_func_from_days :public Item_datefunc { bool check_arguments() const override { return args[0]->check_type_can_return_int(func_name_cstring()); } public: Item_func_from_days(THD *thd, Item *a): Item_datefunc(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("from_days") }; return name; } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return has_date_args() || has_time_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_from_days>(thd, this); } }; class Item_func_date_format :public Item_str_func { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()) || check_argument_types_can_return_text(1, arg_count); } const MY_LOCALE *locale; int fixed_length; String value; protected: bool is_time_format; public: Item_func_date_format(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b), locale(0), is_time_format(false) {} Item_func_date_format(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c), locale(0), is_time_format(false) {} String *val_str(String *str) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("date_format") }; return name; } bool fix_length_and_dec(THD *thd) override; uint format_length(const String *format); bool eq(const Item *item, const Eq_config &config) const override; bool check_vcol_func_processor(void *arg) override { if (arg_count > 2) return false; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_date_format>(thd, this); } }; class Item_func_time_format: public Item_func_date_format { public: Item_func_time_format(THD *thd, Item *a, Item *b): Item_func_date_format(thd, a, b) { is_time_format= true; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("time_format") }; return name; } bool check_vcol_func_processor(void *arg) override { return false; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_time_format>(thd, this); } }; /* the max length of datetime format models string in Oracle is 144 */ #define MAX_DATETIME_FORMAT_MODEL_LEN 144 class Item_func_tochar :public Item_str_func { const MY_LOCALE *locale; THD *thd; String warning_message; bool fixed_length; /* When datetime format models is parsed, use uint16 integers to represent the format models and store in fmt_array. */ uint16 fmt_array[MAX_DATETIME_FORMAT_MODEL_LEN+1]; bool check_arguments() const override { return (args[0]->check_type_can_return_date(func_name_cstring()) && args[0]->check_type_can_return_time(func_name_cstring())) || check_argument_types_can_return_text(1, arg_count); } public: Item_func_tochar(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b), locale(0) { /* NOTE: max length of warning message is 64 */ warning_message.alloc(64); warning_message.length(0); } ~Item_func_tochar() { warning_message.free(); } String *val_str(String *str) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("to_char") }; return name; } bool fix_length_and_dec(THD *thd) override; bool parse_format_string(const String *format, uint *fmt_len); bool check_vcol_func_processor(void *arg) override { if (arg_count > 2) return false; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_tochar>(thd, this); } }; class Item_func_from_unixtime :public Item_datetimefunc { bool check_arguments() const override { return args[0]->check_type_can_return_decimal(func_name_cstring()); } Time_zone *tz; public: Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("from_unixtime") }; return name; } bool fix_length_and_dec(THD *thd) override; bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_from_unixtime>(thd, this); } }; /* We need Time_zone class declaration for storing pointers in Item_func_convert_tz. */ class Time_zone; /* This class represents CONVERT_TZ() function. The important fact about this function that it is handled in special way. When such function is met in expression time_zone system tables are added to global list of tables to open, so later those already opened and locked tables can be used during this function calculation for loading time zone descriptions. */ class Item_func_convert_tz :public Item_datetimefunc { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()) || check_argument_types_can_return_text(1, arg_count); } /* If time zone parameters are constants we are caching objects that represent them (we use separate from_tz_cached/to_tz_cached members to indicate this fact, since NULL is legal value for from_tz/to_tz members. */ bool from_tz_cached, to_tz_cached; Time_zone *from_tz, *to_tz; public: Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c): Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("convert_tz") }; return name; } bool fix_length_and_dec(THD *thd) override { fix_attributes_datetime(args[0]->datetime_precision(thd)); set_maybe_null(); return FALSE; } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; void cleanup() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_convert_tz>(thd, this); } }; class Item_func_sec_to_time :public Item_timefunc { bool check_arguments() const override { return args[0]->check_type_can_return_decimal(func_name_cstring()); } public: Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {} bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { fix_attributes_time(args[0]->decimals); set_maybe_null(); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sec_to_time") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sec_to_time>(thd, this); } }; class Item_date_add_interval :public Item_handled_func { public: const interval_type int_type; // keep it public const bool date_sub_interval; // keep it public Item_date_add_interval(THD *thd, Item *a, Item *b, interval_type type_arg, bool neg_arg): Item_handled_func(thd, a, b), int_type(type_arg), date_sub_interval(neg_arg) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("date_add_interval") }; return name; } bool fix_length_and_dec(THD *thd) override; bool eq(const Item *item, const Eq_config &config) const override; void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return INTERVAL_PRECEDENCE; } bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_date_add_interval>(thd, this); } }; class Item_extract :public Item_int_func, public Type_handler_hybrid_field_type { date_mode_t m_date_mode; const Type_handler_int_result *handler_by_length(uint32 length, uint32 threashold) { if (length >= threashold) return &type_handler_slonglong; return &type_handler_slong; } void set_date_length(uint32 length) { /* DATE components (e.g. YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK) return non-negative values but historically EXTRACT for date components always returned the signed int data type. So do equivalent functions YEAR(), QUARTER(), MONTH(), WEEK(). Let's set the data type to "signed int, but not negative", so "this" produces better data types in VARCHAR and DECIMAL context by using the fact that all of the max_length characters are spent for digits (non of them are spent for the sign). */ set_handler(&type_handler_slong_ge0); fix_char_length(length); m_date_mode= date_mode_t(0); } void set_day_length(uint32 length) { /* Units starting with DAY can be negative: EXTRACT(DAY FROM '-24:00:00') -> -1 */ set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); m_date_mode= Temporal::Options(TIME_INTERVAL_DAY, current_thd); } void set_time_length(uint32 length) { set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); m_date_mode= Temporal::Options(TIME_INTERVAL_hhmmssff, current_thd); } public: const interval_type int_type; // keep it public Item_extract(THD *thd, interval_type type_arg, Item *a): Item_int_func(thd, a), Type_handler_hybrid_field_type(&type_handler_slonglong), m_date_mode(date_mode_t(0)), int_type(type_arg) { } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } longlong val_int() override; enum Functype functype() const override { return EXTRACT_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("extract") }; return name; } bool check_arguments() const override; bool fix_length_and_dec(THD *thd) override; bool eq(const Item *item, const Eq_config &config) const override; void print(String *str, enum_query_type query_type) override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { if (int_type != INTERVAL_WEEK) return FALSE; return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } bool check_valid_arguments_processor(void *int_arg) override { switch (int_type) { case INTERVAL_YEAR: case INTERVAL_YEAR_MONTH: case INTERVAL_QUARTER: case INTERVAL_MONTH: /* case INTERVAL_WEEK: Not allowed as partitioning function, bug#57071 */ case INTERVAL_DAY: return !has_date_args(); case INTERVAL_DAY_HOUR: case INTERVAL_DAY_MINUTE: case INTERVAL_DAY_SECOND: case INTERVAL_DAY_MICROSECOND: return !has_datetime_args(); case INTERVAL_HOUR: case INTERVAL_HOUR_MINUTE: case INTERVAL_HOUR_SECOND: case INTERVAL_MINUTE: case INTERVAL_MINUTE_SECOND: case INTERVAL_SECOND: case INTERVAL_MICROSECOND: case INTERVAL_HOUR_MICROSECOND: case INTERVAL_MINUTE_MICROSECOND: case INTERVAL_SECOND_MICROSECOND: return !has_time_args(); default: /* INTERVAL_LAST is only an end marker, INTERVAL_WEEK depends on default_week_format which is a session variable and cannot be used for partitioning. See bug#57071. */ break; } return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_extract>(thd, this); } }; class Item_char_typecast :public Item_handled_func { uint cast_length; CHARSET_INFO *cast_cs, *from_cs; bool charset_conversion; String tmp_value; bool m_suppress_warning_to_error_escalation; public: bool has_explicit_length() const { return cast_length != ~0U; } private: String *reuse(String *src, size_t length); String *copy(String *src, CHARSET_INFO *cs); uint adjusted_length_with_warn(uint length); void check_truncation_with_warn(String *src, size_t dstlen); void fix_length_and_dec_internal(CHARSET_INFO *fromcs); public: // Methods used by ColumnStore uint get_cast_length() const { return cast_length; } public: Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg): Item_handled_func(thd, a), cast_length(length_arg), cast_cs(cs_arg), m_suppress_warning_to_error_escalation(false) {} enum Functype functype() const override { return CHAR_TYPECAST_FUNC; } bool eq(const Item *item, const Eq_config &config) const override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_char") }; return name; } CHARSET_INFO *cast_charset() const { return cast_cs; } String *val_str_generic(String *a); String *val_str_binary_from_native(String *a); void fix_length_and_dec_generic(); void fix_length_and_dec_numeric(); void fix_length_and_dec_str(); void fix_length_and_dec_native_to_binary(uint32 octet_length); bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this); } void print(String *str, enum_query_type query_type) override; bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_char_typecast>(thd, this); } }; class Item_interval_DDhhmmssff_typecast :public Item_char_typecast { uint m_fsp; public: Item_interval_DDhhmmssff_typecast(THD *thd, Item *a, uint fsp) :Item_char_typecast(thd, a,Interval_DDhhmmssff::max_char_length(fsp), &my_charset_latin1), m_fsp(fsp) { } String *val_str(String *to) override { Interval_DDhhmmssff it(current_thd, args[0], m_fsp); null_value= !it.is_valid_interval_DDhhmmssff(); return it.to_string(to, m_fsp); } }; class Item_date_typecast :public Item_datefunc { public: Item_date_typecast(THD *thd, Item *a): Item_datefunc(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_date") }; return name; } void print(String *str, enum_query_type query_type) override { print_cast_temporal(str, query_type); } enum Functype functype() const override { return DATE_FUNC; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_date_typecast>(thd, this); } }; class Item_time_typecast :public Item_timefunc { public: Item_time_typecast(THD *thd, Item *a, decimal_digits_t dec_arg): Item_timefunc(thd, a) { decimals= dec_arg; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_time") }; return name; } void print(String *str, enum_query_type query_type) override { print_cast_temporal(str, query_type); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()-> Item_time_typecast_fix_length_and_dec(this); } Sql_mode_dependency value_depends_on_sql_mode() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_time_typecast>(thd, this); } }; class Item_datetime_typecast :public Item_datetimefunc { public: Item_datetime_typecast(THD *thd, Item *a, decimal_digits_t dec_arg): Item_datetimefunc(thd, a) { decimals= dec_arg; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_datetime") }; return name; } void print(String *str, enum_query_type query_type) override { print_cast_temporal(str, query_type); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()-> Item_datetime_typecast_fix_length_and_dec(this); } Sql_mode_dependency value_depends_on_sql_mode() const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_datetime_typecast>(thd, this); } }; class Item_func_makedate :public Item_datefunc { bool check_arguments() const override { return check_argument_types_can_return_int(0, arg_count); } public: Item_func_makedate(THD *thd, Item *a, Item *b): Item_datefunc(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("makedate") }; return name; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_makedate>(thd, this); } }; class Item_func_timestamp :public Item_datetimefunc { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()) || args[1]->check_type_can_return_time(func_name_cstring()); } public: Item_func_timestamp(THD *thd, Item *a, Item *b) :Item_datetimefunc(thd, a, b) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("timestamp") }; return name; } bool fix_length_and_dec(THD *thd) override { decimal_digits_t dec0= args[0]->datetime_precision(thd); decimal_digits_t dec1= Interval_DDhhmmssff::fsp(thd, args[1]); fix_attributes_datetime(MY_MAX(dec0, dec1)); set_maybe_null(); return false; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { Datetime dt(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); if (!dt.is_valid_datetime()) return (null_value= 1); Interval_DDhhmmssff it(thd, args[1]); if (!it.is_valid_interval_DDhhmmssff()) return (null_value= true); return (null_value= Sec6_add(dt.get_mysql_time(), it.get_mysql_time(), 1). to_datetime(ltime)); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_timestamp>(thd, this); } }; /** ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value t: time_or_datetime_expression a: time_expression Result: Time value or datetime value */ class Item_func_add_time :public Item_handled_func { int sign; public: // Methods used by ColumnStore int get_sign() const { return sign; } public: Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg) :Item_handled_func(thd, a, b), sign(neg_arg ? -1 : 1) { } bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING addtime= { STRING_WITH_LEN("addtime") }; static LEX_CSTRING subtime= { STRING_WITH_LEN("subtime") }; return sign > 0 ? addtime : subtime; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_add_time>(thd, this); } }; class Item_func_timediff :public Item_timefunc { bool check_arguments() const override { return check_argument_types_can_return_time(0, arg_count); } public: Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("timediff") }; return name; } bool fix_length_and_dec(THD *thd) override { decimal_digits_t dec= MY_MAX(args[0]->time_precision(thd), args[1]->time_precision(thd)); fix_attributes_time(dec); set_maybe_null(); return FALSE; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_timediff>(thd, this); } }; class Item_func_maketime :public Item_timefunc { bool check_arguments() const override { return check_argument_types_can_return_int(0, 2) || args[2]->check_type_can_return_decimal(func_name_cstring()); } public: Item_func_maketime(THD *thd, Item *a, Item *b, Item *c): Item_timefunc(thd, a, b, c) {} bool fix_length_and_dec(THD *thd) override { fix_attributes_time(args[2]->decimals); set_maybe_null(); return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("maketime") }; return name; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_maketime>(thd, this); } }; class Item_func_microsecond :public Item_long_func_time_field { public: Item_func_microsecond(THD *thd, Item *a): Item_long_func_time_field(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("microsecond") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; set_maybe_null(); fix_char_length(6); return FALSE; } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool check_valid_arguments_processor(void *int_arg) override { return !has_time_args(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_microsecond>(thd, this); } }; class Item_func_timestamp_diff :public Item_longlong_func { bool check_arguments() const override { return check_argument_types_can_return_date(0, arg_count); } const interval_type int_type; public: // Methods used by ColumnStore interval_type get_int_type() const { return int_type; }; public: Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg): Item_longlong_func(thd, a, b), int_type(type_arg) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("timestampdiff") }; return name; } longlong val_int() override; bool fix_length_and_dec(THD *thd) override { decimals=0; set_maybe_null(); return FALSE; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_timestamp_diff>(thd, this); } }; enum date_time_format { USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT }; class Item_func_get_format :public Item_str_ascii_func { public: const timestamp_type type; // keep it public Item_func_get_format(THD *thd, timestamp_type type_arg, Item *a): Item_str_ascii_func(thd, a), type(type_arg) {} String *val_str_ascii(String *str) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("get_format") }; return name; } bool fix_length_and_dec(THD *thd) override { set_maybe_null(); decimals=0; fix_length_and_charset(17, default_charset()); return FALSE; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_get_format>(thd, this); } }; class Item_func_str_to_date :public Item_handled_func { bool const_item; String subject_converter; String format_converter; CHARSET_INFO *internal_charset; public: Item_func_str_to_date(THD *thd, Item *a, Item *b): Item_handled_func(thd, a, b), const_item(false), internal_charset(NULL) {} bool get_date_common(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate, timestamp_type); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("str_to_date") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_str_to_date>(thd, this); } }; class Item_func_last_day :public Item_datefunc { bool check_arguments() const override { return args[0]->check_type_can_return_date(func_name_cstring()); } public: Item_func_last_day(THD *thd, Item *a): Item_datefunc(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("last_day") }; return name; } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_last_day>(thd, this); } }; /*****************************************************************************/ class Func_handler_date_add_interval { protected: static decimal_digits_t interval_dec(const Item *item, interval_type int_type) { if (int_type == INTERVAL_MICROSECOND || (int_type >= INTERVAL_DAY_MICROSECOND && int_type <= INTERVAL_SECOND_MICROSECOND)) return TIME_SECOND_PART_DIGITS; if (int_type == INTERVAL_SECOND && item->decimals > 0) return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); return 0; } interval_type int_type(const Item_handled_func *item) const { return static_cast<const Item_date_add_interval*>(item)->int_type; } bool sub(const Item_handled_func *item) const { return static_cast<const Item_date_add_interval*>(item)->date_sub_interval; } bool add(THD *thd, Item *item, interval_type type, bool sub, MYSQL_TIME *to) const { INTERVAL interval; if (get_interval_value(thd, item, type, &interval)) return true; if (sub) interval.neg = !interval.neg; return date_add_interval(thd, to, type, interval); } }; class Func_handler_date_add_interval_datetime: public Item_handled_func::Handler_datetime, public Func_handler_date_add_interval { public: bool fix_length_and_dec(Item_handled_func *item) const override { decimal_digits_t dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd), interval_dec(item->arguments()[1], int_type(item))); item->fix_attributes_datetime(dec); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { Datetime::Options opt(TIME_CONV_NONE, thd); Datetime dt(thd, item->arguments()[0], opt); if (!dt.is_valid_datetime() || dt.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) return (item->null_value= true); dt.copy_to_mysql_time(to); return (item->null_value= add(thd, item->arguments()[1], int_type(item), sub(item), to)); } }; class Func_handler_date_add_interval_datetime_arg0_time: public Func_handler_date_add_interval_datetime { public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override; }; class Func_handler_date_add_interval_date: public Item_handled_func::Handler_date, public Func_handler_date_add_interval { public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { /* The first argument is known to be of the DATE data type (not DATETIME). We don't need rounding here. */ Date d(thd, item->arguments()[0], TIME_CONV_NONE); if (!d.is_valid_date() || d.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) return (item->null_value= true); d.copy_to_mysql_time(to); return (item->null_value= add(thd, item->arguments()[1], int_type(item), sub(item), to)); } }; class Func_handler_date_add_interval_time: public Item_handled_func::Handler_time, public Func_handler_date_add_interval { public: bool fix_length_and_dec(Item_handled_func *item) const override { decimal_digits_t dec= MY_MAX(item->arguments()[0]->time_precision(current_thd), interval_dec(item->arguments()[1], int_type(item))); item->fix_attributes_time(dec); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { Time t(thd, item->arguments()[0]); if (!t.is_valid_time()) return (item->null_value= true); t.copy_to_mysql_time(to); return (item->null_value= add(thd, item->arguments()[1], int_type(item), sub(item), to)); } }; class Func_handler_date_add_interval_string: public Item_handled_func::Handler_temporal_string, public Func_handler_date_add_interval { public: bool fix_length_and_dec(Item_handled_func *item) const override { decimal_digits_t dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd), interval_dec(item->arguments()[1], int_type(item))); item->Type_std_attributes::set( Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false), DTCollation(item->default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII)); item->fix_char_length(item->max_length); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { if (item->arguments()[0]-> get_date(thd, to, Datetime::Options(TIME_CONV_NONE, thd)) || (to->time_type != MYSQL_TIMESTAMP_TIME && check_date_with_warn(thd, to, TIME_NO_ZEROS, MYSQL_TIMESTAMP_ERROR))) return (item->null_value= true); return (item->null_value= add(thd, item->arguments()[1], int_type(item), sub(item), to)); } }; class Func_handler_sign { protected: int m_sign; Func_handler_sign(int sign) :m_sign(sign) { } }; class Func_handler_add_time_datetime: public Item_handled_func::Handler_datetime, public Func_handler_sign { public: Func_handler_add_time_datetime(int sign) :Func_handler_sign(sign) { } bool fix_length_and_dec(Item_handled_func *item) const override { THD *thd= current_thd; decimal_digits_t dec0= item->arguments()[0]->datetime_precision(thd); decimal_digits_t dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]); item->fix_attributes_datetime(MY_MAX(dec0, dec1)); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { DBUG_ASSERT(item->fixed()); Datetime::Options opt(TIME_CONV_NONE, thd); Datetime dt(thd, item->arguments()[0], opt); if (!dt.is_valid_datetime()) return (item->null_value= true); Interval_DDhhmmssff it(thd, item->arguments()[1]); if (!it.is_valid_interval_DDhhmmssff()) return (item->null_value= true); return (item->null_value= (Sec6_add(dt.get_mysql_time(), it.get_mysql_time(), m_sign). to_datetime(to))); } }; class Func_handler_add_time_time: public Item_handled_func::Handler_time, public Func_handler_sign { public: Func_handler_add_time_time(int sign) :Func_handler_sign(sign) { } bool fix_length_and_dec(Item_handled_func *item) const override { THD *thd= current_thd; decimal_digits_t dec0= item->arguments()[0]->time_precision(thd); decimal_digits_t dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]); item->fix_attributes_time(MY_MAX(dec0, dec1)); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { DBUG_ASSERT(item->fixed()); Time t(thd, item->arguments()[0]); if (!t.is_valid_time()) return (item->null_value= true); Interval_DDhhmmssff i(thd, item->arguments()[1]); if (!i.is_valid_interval_DDhhmmssff()) return (item->null_value= true); return (item->null_value= (Sec6_add(t.get_mysql_time(), i.get_mysql_time(), m_sign). to_time(thd, to, item->decimals))); } }; class Func_handler_add_time_string: public Item_handled_func::Handler_temporal_string, public Func_handler_sign { public: Func_handler_add_time_string(int sign) :Func_handler_sign(sign) { } bool fix_length_and_dec(Item_handled_func *item) const override { decimal_digits_t dec0= item->arguments()[0]->decimals; decimal_digits_t dec1= Interval_DDhhmmssff::fsp(current_thd, item->arguments()[1]); decimal_digits_t dec= MY_MAX(dec0, dec1); item->Type_std_attributes::set( Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false), DTCollation(item->default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII)); item->fix_char_length(item->max_length); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { DBUG_ASSERT(item->fixed()); // Detect a proper timestamp type based on the argument values Temporal_hybrid l_time1(thd, item->arguments()[0], Temporal::Options(TIME_TIME_ONLY, thd)); if (!l_time1.is_valid_temporal()) return (item->null_value= true); Interval_DDhhmmssff l_time2(thd, item->arguments()[1]); if (!l_time2.is_valid_interval_DDhhmmssff()) return (item->null_value= true); Sec6_add add(l_time1.get_mysql_time(), l_time2.get_mysql_time(), m_sign); return (item->null_value= (l_time1.get_mysql_time()->time_type == MYSQL_TIMESTAMP_TIME ? add.to_time(thd, to, item->decimals) : add.to_datetime(to))); } }; class Func_handler_str_to_date_datetime_sec: public Item_handled_func::Handler_datetime { public: bool fix_length_and_dec(Item_handled_func *item) const override { item->fix_attributes_datetime(0); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { return static_cast<Item_func_str_to_date*>(item)-> get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME); } }; class Func_handler_str_to_date_datetime_usec: public Item_handled_func::Handler_datetime { public: bool fix_length_and_dec(Item_handled_func *item) const override { item->fix_attributes_datetime(TIME_SECOND_PART_DIGITS); return false; } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { return static_cast<Item_func_str_to_date*>(item)-> get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME); } }; class Func_handler_str_to_date_date: public Item_handled_func::Handler_date { public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { return static_cast<Item_func_str_to_date*>(item)-> get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATE); } }; class Func_handler_str_to_date_time: public Item_handled_func::Handler_time { public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const override { if (static_cast<Item_func_str_to_date*>(item)-> get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_TIME)) return true; if (to->day) { /* Day part for time type can be nonzero value and so we should add hours from day part to hour part to keep valid time value. */ to->hour+= to->day * 24; to->day= 0; } return false; } }; class Func_handler_str_to_date_time_sec: public Func_handler_str_to_date_time { public: bool fix_length_and_dec(Item_handled_func *item) const override { item->fix_attributes_time(0); return false; } }; class Func_handler_str_to_date_time_usec: public Func_handler_str_to_date_time { public: bool fix_length_and_dec(Item_handled_func *item) const override { item->fix_attributes_time(TIME_SECOND_PART_DIGITS); return false; } }; #endif /* ITEM_TIMEFUNC_INCLUDED */ rpl_utility.h 0000644 00000025670 15156036163 0007315 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_UTILITY_H #define RPL_UTILITY_H #ifndef __cplusplus #error "Don't include this C++ header file from a non-C++ file!" #endif #include "sql_priv.h" #include "m_string.h" /* bzero, memcpy */ #ifdef MYSQL_SERVER #include "table.h" /* TABLE_LIST */ #endif #include "mysql_com.h" class Relay_log_info; class Log_event; struct rpl_group_info; /** A table definition from the master. The responsibilities of this class is: - Extract and decode table definition data from the table map event - Check if table definition in table map is compatible with table definition on slave */ class table_def { table_def(const table_def&) = default; public: /** Constructor. @param types Array of types, each stored as a byte @param size Number of elements in array 'types' @param field_metadata Array of extra information about fields @param metadata_size Size of the field_metadata array @param null_bitmap The bitmap of fields that can be null */ table_def(unsigned char *types, ulong size, uchar *field_metadata, int metadata_size, uchar *null_bitmap, uint16 flags); /** Move constructor Since it deallocates a memory during destruction, we can't safely copy it. We should instead move it to zero m_memory in an old object */ table_def(table_def &&tabledef) : table_def(tabledef) { tabledef.m_memory= NULL; } ~table_def(); /** Return the number of fields there is type data for. @return The number of fields that there is type data for. */ uint size() const { return m_size; } /** Returns internal binlog type code for one field, without translation to real types. */ enum_field_types binlog_type(ulong index) const { return static_cast<enum_field_types>(m_type[index]); } /* Return a representation of the type data for one field. @param index Field index to return data for @return Will return a representation of the type data for field <code>index</code>. Currently, only the type identifier is returned. */ enum_field_types type(ulong index) const { DBUG_ASSERT(index < m_size); /* If the source type is MYSQL_TYPE_STRING, it can in reality be either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so we might need to modify the type to get the real type. */ enum_field_types source_type= binlog_type(index); uint16 source_metadata= m_field_metadata[index]; switch (source_type) { case MYSQL_TYPE_STRING: { int real_type= source_metadata >> 8; if (real_type == MYSQL_TYPE_ENUM || real_type == MYSQL_TYPE_SET) source_type= static_cast<enum_field_types>(real_type); break; } /* This type has not been used since before row-based replication, so we can safely assume that it really is MYSQL_TYPE_NEWDATE. */ case MYSQL_TYPE_DATE: source_type= MYSQL_TYPE_NEWDATE; break; default: /* Do nothing */ break; } return source_type; } #ifdef MYSQL_SERVER const Type_handler *field_type_handler(uint index) const; #endif /* This function allows callers to get the extra field data from the table map for a given field. If there is no metadata for that field or there is no extra metadata at all, the function returns 0. The function returns the value for the field metadata for column at position indicated by index. As mentioned, if the field was a type that stores field metadata, that value is returned else zero (0) is returned. This method is used in the unpack() methods of the corresponding fields to properly extract the data from the binary log in the event that the master's field is smaller than the slave. */ uint16 field_metadata(uint index) const { DBUG_ASSERT(index < m_size); if (m_field_metadata_size) return m_field_metadata[index]; else return 0; } /* This function returns whether the field on the master can be null. This value is derived from field->maybe_null(). */ my_bool maybe_null(uint index) const { DBUG_ASSERT(index < m_size); return ((m_null_bits[(index / 8)] & (1 << (index % 8))) == (1 << (index %8))); } /* This function returns the field size in raw bytes based on the type and the encoded field data from the master's raw data. This method can be used for situations where the slave needs to skip a column (e.g., WL#3915) or needs to advance the pointer for the fields in the raw data from the master to a specific column. */ uint32 calc_field_size(uint col, uchar *master_data) const; /** Decide if the table definition is compatible with a table. Compare the definition with a table to see if it is compatible with it. A table definition is compatible with a table if: - The columns types of the table definition is a (not necessarily proper) prefix of the column type of the table. - The other way around. - Each column on the master that also exists on the slave can be converted according to the current settings of @c SLAVE_TYPE_CONVERSIONS. @param thd @param rli Pointer to relay log info @param table Pointer to table to compare with. @param[out] tmp_table_var Pointer to temporary table for holding conversion table. @retval 1 if the table definition is not compatible with @c table @retval 0 if the table definition is compatible with @c table */ #ifndef MYSQL_CLIENT bool compatible_with(THD *thd, rpl_group_info *rgi, TABLE *table, TABLE **conv_table_var) const; /** Create a virtual in-memory temporary table structure. The table structure has records and field array so that a row can be unpacked into the record for further processing. In the virtual table, each field that requires conversion will have a non-NULL value, while fields that do not require conversion will have a NULL value. Some information that is missing in the events, such as the character set for string types, are taken from the table that the field is going to be pushed into, so the target table that the data eventually need to be pushed into need to be supplied. @param thd Thread to allocate memory from. @param rli Relay log info structure, for error reporting. @param target_table Target table for fields. @return A pointer to a temporary table with memory allocated in the thread's memroot, NULL if the table could not be created */ TABLE *create_conversion_table(THD *thd, rpl_group_info *rgi, TABLE *target_table) const; #endif private: unsigned char *m_type; // Array of type descriptors uint m_size; // Number of elements in the types array uint m_field_metadata_size; uint16 *m_field_metadata; uint16 m_flags; // Table flags uchar *m_null_bits; uchar *m_memory; }; #ifndef MYSQL_CLIENT /** Extend the normal table list with a few new fields needed by the slave thread, but nowhere else. */ struct RPL_TABLE_LIST : public TABLE_LIST { table_def m_tabledef; TABLE *m_conv_table; const Copy_field *m_online_alter_copy_fields; const Copy_field *m_online_alter_copy_fields_end; uint cached_key_nr; // [0..MAX_KEY] if set, ~0U if unset uint cached_usable_key_parts; bool m_tabledef_valid; bool master_had_triggers; RPL_TABLE_LIST(const LEX_CSTRING *db_arg, const LEX_CSTRING *table_name_arg, thr_lock_type thr_lock_type, table_def &&tabledef, bool master_had_trigers) : TABLE_LIST(db_arg, table_name_arg, NULL, thr_lock_type), m_tabledef(std::move(tabledef)), m_conv_table(NULL), m_online_alter_copy_fields(NULL), m_online_alter_copy_fields_end(NULL), cached_key_nr(~0U), m_tabledef_valid(true), master_had_triggers(master_had_trigers) {} RPL_TABLE_LIST(TABLE *table, thr_lock_type lock_type, TABLE *conv_table, table_def &&tabledef, const Copy_field online_alter_copy_fields[], const Copy_field *online_alter_copy_fields_end) : TABLE_LIST(table, lock_type), m_tabledef(std::move(tabledef)), m_conv_table(conv_table), m_online_alter_copy_fields(online_alter_copy_fields), m_online_alter_copy_fields_end(online_alter_copy_fields_end), cached_key_nr(~0U), m_tabledef_valid(true), master_had_triggers(false) {} }; /* Anonymous namespace for template functions/classes */ CPP_UNNAMED_NS_START /* Smart pointer that will automatically call my_afree (a macro) when the pointer goes out of scope. This is used so that I do not have to remember to call my_afree() before each return. There is no overhead associated with this, since all functions are inline. I (Matz) would prefer to use the free function as a template parameter, but that is not possible when the "function" is a macro. */ template <class Obj> class auto_afree_ptr { Obj* m_ptr; public: auto_afree_ptr(Obj* ptr) : m_ptr(ptr) { } ~auto_afree_ptr() { if (m_ptr) my_afree(m_ptr); } void assign(Obj* ptr) { /* Only to be called if it hasn't been given a value before. */ DBUG_ASSERT(m_ptr == NULL); m_ptr= ptr; } Obj* get() { return m_ptr; } }; CPP_UNNAMED_NS_END class Deferred_log_events { private: DYNAMIC_ARRAY array; Log_event *last_added; public: Deferred_log_events(Relay_log_info *rli); ~Deferred_log_events(); /* queue for exection at Query-log-event time prior the Query */ int add(Log_event *ev); bool is_empty(); bool execute(struct rpl_group_info *rgi); void rewind(); bool is_last(Log_event *ev) { return ev == last_added; }; }; #endif // NB. number of printed bit values is limited to sizeof(buf) - 1 #define DBUG_PRINT_BITSET(N,FRM,BS) \ do { \ char buf[256]; \ uint i; \ for (i = 0 ; i < MY_MIN(sizeof(buf) - 1, (BS)->n_bits) ; i++) \ buf[i] = bitmap_is_set((BS), i) ? '1' : '0'; \ buf[i] = '\0'; \ DBUG_PRINT((N), ((FRM), buf)); \ } while (0) #endif /* RPL_UTILITY_H */ rpl_rli.h 0000644 00000106025 15156036163 0006372 0 ustar 00 /* Copyright (c) 2005, 2017, Oracle and/or its affiliates. Copyright (c) 2009, 2017, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef RPL_RLI_H #define RPL_RLI_H #include "rpl_tblmap.h" #include "rpl_reporting.h" #include "rpl_utility.h" #include "log.h" /* LOG_INFO, MYSQL_BIN_LOG */ #include "sql_class.h" /* THD */ #include "log_event.h" #include "rpl_parallel.h" struct RPL_TABLE_LIST; class Master_info; class Rpl_filter; /**************************************************************************** Replication SQL Thread Relay_log_info contains: - the current relay log - the current relay log offset - master log name - master log sequence corresponding to the last update - misc information specific to the SQL thread Relay_log_info is initialized from the slave.info file if such exists. Otherwise, data members are intialized with defaults. The initialization is done with Relay_log_info::init() call. The format of slave.info file: relay_log_name relay_log_pos master_log_name master_log_pos To clean up, call end_relay_log_info() *****************************************************************************/ struct rpl_group_info; struct inuse_relaylog; class Relay_log_info : public Slave_reporting_capability { public: /** Flags for the state of reading the relay log. Note that these are bit masks. */ enum enum_state_flag { /** We are inside a group of events forming a statement */ IN_STMT=1, /** We have inside a transaction */ IN_TRANSACTION=2 }; /* The SQL thread owns one Relay_log_info, and each client that has executed a BINLOG statement owns one Relay_log_info. This function returns zero for the Relay_log_info object that belongs to the SQL thread and nonzero for Relay_log_info objects that belong to clients. */ inline bool belongs_to_client() { DBUG_ASSERT(sql_driver_thd); return !sql_driver_thd->slave_thread; } /* If true, events with the same server id should be replicated. This field is set on creation of a relay log info structure by copying the value of ::replicate_same_server_id and can be overridden if necessary. For example of when this is done, check sql_binlog.cc, where the BINLOG statement can be used to execute "raw" events. */ bool replicate_same_server_id; /*** The following variables can only be read when protect by data lock ****/ /* info_fd - file descriptor of the info file. set only during initialization or clean up - safe to read anytime cur_log_fd - file descriptor of the current read relay log */ File info_fd,cur_log_fd; /* Protected with internal locks. Must get data_lock when resetting the logs. */ MYSQL_BIN_LOG relay_log; LOG_INFO linfo; /* cur_log Pointer that either points at relay_log.get_log_file() or &rli->cache_buf, depending on whether the log is hot or there was the need to open a cold relay_log. cache_buf IO_CACHE used when opening cold relay logs. */ IO_CACHE cache_buf,*cur_log; /* Keeps track of the number of transactions that commits before fsyncing. The option --sync-relay-log-info determines how many transactions should commit before fsyncing. */ uint sync_counter; /* Identifies when the recovery process is going on. See sql/slave.cc:init_recovery for further details. */ bool is_relay_log_recovery; /* The following variables are safe to read any time */ /* IO_CACHE of the info file - set only during init or end */ IO_CACHE info_file; /* List of temporary tables used by this connection. This is updated when a temporary table is created or dropped by a replication thread. Not reset when replication ends, to allow one to access the tables when replication restarts. Protected by data_lock. */ All_tmp_tables_list *save_temporary_tables; /* standard lock acquisition order to avoid deadlocks: run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index */ mysql_mutex_t data_lock, run_lock; /* start_cond is broadcast when SQL thread is started stop_cond - when stopped data_cond - when data protected by data_lock changes */ mysql_cond_t start_cond, stop_cond, data_cond; /* parent Master_info structure */ Master_info *mi; /* List of active relay log files. (This can be more than one in case of parallel replication). */ inuse_relaylog *inuse_relaylog_list; inuse_relaylog *last_inuse_relaylog; /* Needed to deal properly with cur_log getting closed and re-opened with a different log under our feet */ uint32 cur_log_old_open_count; /* If on init_info() call error_on_rli_init_info is true that means that previous call to init_info() terminated with an error, RESET SLAVE must be executed and the problem fixed manually. */ bool error_on_rli_init_info; /* Let's call a group (of events) : - a transaction or - an autocommiting query + its associated events (INSERT_ID, TIMESTAMP...) We need these rli coordinates : - relay log name and position of the beginning of the group we currently are executing. Needed to know where we have to restart when replication has stopped in the middle of a group (which has been rolled back by the slave). - relay log name and position just after the event we have just executed. This event is part of the current group. Formerly we only had the immediately above coordinates, plus a 'pending' variable, but this dealt wrong with the case of a transaction starting on a relay log and finishing (commiting) on another relay log. Case which can happen when, for example, the relay log gets rotated because of max_binlog_size. Note: group_relay_log_name, group_relay_log_pos must only be written from the thread owning the Relay_log_info (SQL thread if !belongs_to_client(); client thread executing BINLOG statement if belongs_to_client()). */ char group_relay_log_name[FN_REFLEN]; ulonglong group_relay_log_pos; char event_relay_log_name[FN_REFLEN]; ulonglong event_relay_log_pos; ulonglong future_event_relay_log_pos; /* The master log name for current event. Only used in parallel replication. */ char future_event_master_log_name[FN_REFLEN]; /* Original log name and position of the group we're currently executing (whose coordinates are group_relay_log_name/pos in the relay log) in the master's binlog. These concern the *group*, because in the master's binlog the log_pos that comes with each event is the position of the beginning of the group. Note: group_master_log_name, group_master_log_pos must only be written from the thread owning the Relay_log_info (SQL thread if !belongs_to_client(); client thread executing BINLOG statement if belongs_to_client()). */ char group_master_log_name[FN_REFLEN]; volatile my_off_t group_master_log_pos; /* Handling of the relay_log_space_limit optional constraint. ignore_log_space_limit is used to resolve a deadlock between I/O and SQL threads, the SQL thread sets it to unblock the I/O thread and make it temporarily forget about the constraint. */ ulonglong log_space_limit; Atomic_counter<uint64> log_space_total; bool ignore_log_space_limit; /* Used by the SQL thread to instructs the IO thread to rotate the logs when the SQL thread needs to purge to release some disk space. */ bool sql_force_rotate_relay; time_t last_master_timestamp; /* The SQL driver thread sets this true while it is waiting at the end of the relay log for more events to arrive. SHOW SLAVE STATUS uses this to report Seconds_Behind_Master as zero while the SQL thread is so waiting. */ bool sql_thread_caught_up; /** Simple setter for @ref worker_threads_caught_up; sets it `false` to indicate new user events in queue @pre @ref data_lock held to prevent race with is_threads_caught_up() */ inline void unset_worker_threads_caught_up() { mysql_mutex_assert_owner(&data_lock); worker_threads_caught_up= false; } /** @return `true` if both @ref sql_thread_caught_up and (refresh according to @ref last_inuse_relaylog as needed) @ref worker_threads_caught_up @pre Only meaningful if `mi->using_parallel()` @pre @ref data_lock held to prevent race condition @note Parallel replication requires the idleness of the main SQL thread as well, because after the thread sets its state to "busy" with `data_lock` held, it enqueues events *without this lock*. Not to mention any event the main thread processes itself without distribution, e.g., ignored ones. */ bool are_sql_threads_caught_up(); void clear_until_condition(); /** Reset the delay. This is used by RESET SLAVE to clear the delay. */ void clear_sql_delay() { sql_delay= 0; } /* Needed for problems when slave stops and we want to restart it skipping one or more events in the master log that have caused errors, and have been manually applied by DBA already. Must be ulong as it's referred to from set_var.cc */ volatile ulonglong slave_skip_counter; ulonglong max_relay_log_size; volatile ulong abort_pos_wait; /* Incremented on change master */ volatile ulong slave_run_id; /* Incremented on slave start */ mysql_mutex_t log_space_lock; mysql_cond_t log_space_cond; /* THD for the main sql thread, the one that starts threads to process slave requests. If there is only one thread, then this THD is also used for SQL processing. A kill sent to this THD will kill the replication. */ THD *sql_driver_thd; #ifndef DBUG_OFF int events_till_abort; #endif enum_gtid_skip_type gtid_skip_flag; /* inited changes its value within LOCK_active_mi-guarded critical sections at times of start_slave_threads() (0->1) and end_slave() (1->0). Readers may not acquire the mutex while they realize potential concurrency issue. If not set, the value of other members of the structure are undefined. */ volatile bool inited; volatile bool abort_slave; volatile bool stop_for_until; volatile uint slave_running; /* Condition and its parameters from START SLAVE UNTIL clause. UNTIL condition is tested with is_until_satisfied() method that is called by exec_relay_log_event(). is_until_satisfied() caches the result of the comparison of log names because log names don't change very often; this cache is invalidated by parts of code which change log names with notify_*_log_name_updated() methods. (They need to be called only if SQL thread is running). */ enum { UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS, UNTIL_GTID } until_condition; char until_log_name[FN_REFLEN]; ulonglong until_log_pos; /* extension extracted from log_name and converted to int */ ulong until_log_name_extension; /* Cached result of comparison of until_log_name and current log name -2 means unitialised, -1,0,1 are comarison results */ enum { UNTIL_LOG_NAMES_CMP_UNKNOWN= -2, UNTIL_LOG_NAMES_CMP_LESS= -1, UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1 } until_log_names_cmp_result; /* Condition for UNTIL master_gtid_pos. */ slave_connection_state until_gtid_pos; bool is_until_before_gtids; /* retried_trans is a cumulative counter: how many times the slave has retried a transaction (any) since slave started. Protected by data_lock. */ ulong retried_trans; /* Number of executed events for SLAVE STATUS. Protected by slave_executed_entries_lock */ Atomic_counter<uint32_t> executed_entries; /* If the end of the hot relay log is made of master's events ignored by the slave I/O thread, these two keep track of the coords (in the master's binlog) of the last of these events seen by the slave I/O thread. If not, ign_master_log_name_end[0] == 0. As they are like a Rotate event read/written from/to the relay log, they are both protected by rli->relay_log.LOCK_log. */ char ign_master_log_name_end[FN_REFLEN]; ulonglong ign_master_log_pos_end; /* Similar for ignored GTID events. */ slave_connection_state ign_gtids; /* Indentifies where the SQL Thread should create temporary files for the LOAD DATA INFILE. This is used for security reasons. */ char slave_patternload_file[FN_REFLEN]; size_t slave_patternload_file_size; rpl_parallel parallel; /* The relay_log_state keeps track of the current binlog state of the execution of the relay log. This is used to know where to resume current GTID position if the slave thread is stopped and restarted. It is only accessed from the SQL thread, so it does not need any locking. */ rpl_binlog_state relay_log_state; /* The restart_gtid_state is used when the SQL thread restarts on a relay log in GTID mode. In multi-domain parallel replication, each domain may have a separat position, so some events in more progressed domains may need to be skipped. This keeps track of the domains that have not yet reached their starting event. */ slave_connection_state restart_gtid_pos; Relay_log_info(bool is_slave_recovery, const char* thread_name= "SQL"); ~Relay_log_info(); /* Invalidate cached until_log_name and group_relay_log_name comparison result. Should be called after any update of group_realy_log_name if there chances that sql_thread is running. */ inline void notify_group_relay_log_name_update() { if (until_condition==UNTIL_RELAY_POS) until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; } /* The same as previous but for group_master_log_name. */ inline void notify_group_master_log_name_update() { if (until_condition==UNTIL_MASTER_POS) until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; } void inc_group_relay_log_pos(ulonglong log_pos, rpl_group_info *rgi, bool skip_lock=0); int wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout); void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ bool is_until_satisfied(Log_event *ev); inline ulonglong until_pos() { DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || until_condition == UNTIL_RELAY_POS); return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : group_relay_log_pos); } inline char *until_name() { DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || until_condition == UNTIL_RELAY_POS); return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_name : group_relay_log_name); } /** Helper function to do after statement completion. This function is called from an event to complete the group by either stepping the group position, if the "statement" is not inside a transaction; or increase the event position, if the "statement" is inside a transaction. @param event_log_pos Master log position of the event. The position is recorded in the relay log info and used to produce information for <code>SHOW SLAVE STATUS</code>. */ bool stmt_done(my_off_t event_log_pos, THD *thd, rpl_group_info *rgi); int alloc_inuse_relaylog(const char *name); void free_inuse_relaylog(inuse_relaylog *ir); void reset_inuse_relaylog(); int update_relay_log_state(rpl_gtid *gtid_list, uint32 count); /** Is the replication inside a group? The reader of the relay log is inside a group if either: - The IN_TRANSACTION flag is set, meaning we're inside a transaction - The IN_STMT flag is set, meaning we have read at least one row from a multi-event entry. This flag reflects the state of the log 'just now', ie after the last read event would be executed. This allow us to test if we can stop replication before reading the next entry. @retval true Replication thread is currently inside a group @retval false Replication thread is currently not inside a group */ bool is_in_group() const { return (m_flags & (IN_STMT | IN_TRANSACTION)); } /** Set the value of a replication state flag. @param flag Flag to set */ void set_flag(enum_state_flag flag) { m_flags|= flag; } /** Get the value of a replication state flag. @param flag Flag to get value of @return @c true if the flag was set, @c false otherwise. */ bool get_flag(enum_state_flag flag) { return m_flags & flag; } /** Clear the value of a replication state flag. @param flag Flag to clear */ void clear_flag(enum_state_flag flag) { m_flags&= ~flag; } bool flush(); /** Reads the relay_log.info file. */ int init(const char* info_filename); /** Indicate that a delay starts. This does not actually sleep; it only sets the state of this Relay_log_info object to delaying so that the correct state can be reported by SHOW SLAVE STATUS and SHOW PROCESSLIST. Requires rli->data_lock. @param delay_end The time when the delay shall end. */ void start_sql_delay(time_t delay_end) { mysql_mutex_assert_owner(&data_lock); sql_delay_end= delay_end; THD_STAGE_INFO(sql_driver_thd, stage_sql_thd_waiting_until_delay); } int32 get_sql_delay() { return sql_delay; } void set_sql_delay(int32 _sql_delay) { sql_delay= _sql_delay; } time_t get_sql_delay_end() { return sql_delay_end; } rpl_gtid last_seen_gtid; ulong last_trans_retry_count; private: /** Delay slave SQL thread by this amount, compared to master (in seconds). This is set with CHANGE MASTER TO MASTER_DELAY=X. Guarded by data_lock. Initialized by the client thread executing START SLAVE. Written by client threads executing CHANGE MASTER TO MASTER_DELAY=X. Read by SQL thread and by client threads executing SHOW SLAVE STATUS. Note: must not be written while the slave SQL thread is running, since the SQL thread reads it without a lock when executing Relay_log_info::flush(). */ int sql_delay; /** During a delay, specifies the point in time when the delay ends. This is used for the SQL_Remaining_Delay column in SHOW SLAVE STATUS. Guarded by data_lock. Written by the sql thread. Read by client threads executing SHOW SLAVE STATUS. This is calculated as: clock_time_for_event_on_master + clock_difference_between_master_and_slave + SQL_DELAY. */ time_t sql_delay_end; /* Before the MASTER_DELAY parameter was added (WL#344), relay_log.info had 4 lines. Now it has 5 lines. */ static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5; /* Hint for when to stop event distribution by sql driver thread. The flag is set ON by a non-group event when this event is in the middle of a group (e.g a transaction group) so it's too early to refresh the current-relay-log vs until-log cached comparison result. And it is checked and to decide whether it's a right time to do so when the being processed group has been fully scheduled. */ bool until_relay_log_names_defer; /* Holds the state of the data in the relay log. We need this to ensure that we are not in the middle of a statement or inside BEGIN ... COMMIT when should rotate the relay log. */ uint32 m_flags; /** When `true`, this worker threads' copy of @ref sql_thread_caught_up represents that __every__ worker thread is waiting for new events. * The SQL driver thread sets this to `false` through unset_worker_threads_caught_up() as it prepares an event (either to enqueue a worker or, e.g., ignored events, process itself) * For the main driver or any worker thread to refresh this state immediately when it finishes, the procedure would have to be a critical section. To avoid depending on a mutex, this state instead only returns to `true` as part of its reader, are_worker_threads_caught_up(). `Seconds_Behind_Master` of SHOW SLAVE STATUS uses this method (which also reads `sql_thread_caught_up`) to know when all SQL threads are waiting. @pre Only meaningful if `mi->using_parallel()` */ bool worker_threads_caught_up= true; }; /* In parallel replication, if we need to re-try a transaction due to a deadlock or other temporary error, we may need to go back and re-read events out of an earlier relay log. This structure keeps track of the relaylogs that are potentially in use. Each rpl_group_info has a pointer to one of those, corresponding to the first GTID event. A pair of reference count keeps track of how long a relay log is potentially in use. When the `completed' flag is set, all events have been read out of the relay log, but the log might still be needed for retry in worker threads. As worker threads complete an event group, they increment atomically the `dequeued_count' with number of events queued. Thus, when completed is set and dequeued_count equals queued_count, the relay log file is finally done with and can be purged. By separating the queued and dequeued count, only the dequeued_count needs multi-thread synchronisation; the completed flag and queued_count fields are only accessed by the SQL driver thread and need no synchronisation. */ struct inuse_relaylog { inuse_relaylog *next; Relay_log_info *rli; /* relay_log_state holds the binlog state corresponding to the start of this relay log file. It is an array with relay_log_state_count elements. */ rpl_gtid *relay_log_state; uint32 relay_log_state_count; /* Number of events in this relay log queued for worker threads. */ Atomic_counter<int64> queued_count; /* Number of events completed by worker threads. */ Atomic_counter<int64> dequeued_count; /* Set when all events have been read from a relaylog. */ bool completed; char name[FN_REFLEN]; inuse_relaylog(Relay_log_info *rli_arg, rpl_gtid *relay_log_state_arg, uint32 relay_log_state_count_arg, const char *name_arg): next(0), rli(rli_arg), relay_log_state(relay_log_state_arg), relay_log_state_count(relay_log_state_count_arg), queued_count(0), dequeued_count(0), completed(false) { strmake_buf(name, name_arg); } }; enum start_alter_state { INVALID= 0, REGISTERED, // Start Alter exist, Default state COMMIT_ALTER, // COMMIT the alter ROLLBACK_ALTER, // Rollback the alter COMPLETED // COMMIT/ROLLBACK Alter written in binlog }; struct start_alter_info { /* ALTER id is defined as a pair of GTID's seq_no and domain_id. */ decltype(rpl_gtid::seq_no) sa_seq_no; // key for searching (SA's id) uint32 domain_id; bool direct_commit_alter; // when true CA thread executes the whole query /* 0 prepared and not error from commit and rollback >0 error expected in commit/rollback Rollback can be logged with 0 error if master is killed */ uint error; enum start_alter_state state; /* We are not using mysql_cond_t because we do not need PSI */ mysql_cond_t start_alter_cond; }; struct Rpl_table_data { const table_def *tabledef; TABLE *conv_table; const Copy_field *copy_fields; const Copy_field *copy_fields_end; Rpl_table_data(const RPL_TABLE_LIST &rpl_table_list) { tabledef= &rpl_table_list.m_tabledef; conv_table= rpl_table_list.m_conv_table; copy_fields= rpl_table_list.m_online_alter_copy_fields; copy_fields_end= rpl_table_list.m_online_alter_copy_fields_end; } bool is_online_alter() const { return copy_fields != NULL; } }; /* This is data for various state needed to be kept for the processing of one event group (transaction) during replication. In single-threaded replication, there will be one global rpl_group_info and one global Relay_log_info per master connection. They will be linked together. In parallel replication, there will be one rpl_group_info object for each running sql thread, each having their own thd. All rpl_group_info will share the same Relay_log_info. */ struct rpl_group_info { rpl_group_info *next; /* For free list in rpl_parallel_thread */ Relay_log_info *rli; THD *thd; /* Current GTID being processed. The sub_id gives the binlog order within one domain_id. A zero sub_id means that there is no active GTID. */ uint64 gtid_sub_id; rpl_gtid current_gtid; /* Currently applied event or NULL */ Log_event *current_event; uint64 commit_id; /* This is used to keep transaction commit order. We will signal this when we commit, and can register it to wait for the commit_orderer of the previous commit to signal us. */ wait_for_commit commit_orderer; /* If non-zero, the sub_id of a prior event group whose commit we have to wait for before committing ourselves. Then wait_commit_group_info points to the event group to wait for. Before using this, rpl_parallel_entry::last_committed_sub_id should be compared against wait_commit_sub_id. Only if last_committed_sub_id is smaller than wait_commit_sub_id must the wait be done (otherwise the waited-for transaction is already committed, so we would otherwise wait for the wrong commit). */ uint64 wait_commit_sub_id; rpl_group_info *wait_commit_group_info; /* This holds a pointer to a struct that keeps track of the need to wait for the previous batch of event groups to reach the commit stage, before this batch can start to execute. (When we execute in parallel the transactions that group committed together on the master, we still need to wait for any prior transactions to have reached the commit stage). The pointed-to gco is only valid for as long as gtid_sub_id < parallel_entry->last_committed_sub_id. After that, it can be freed by another thread. */ group_commit_orderer *gco; struct rpl_parallel_entry *parallel_entry; /* A container to hold on Intvar-, Rand-, Uservar- log-events in case the slave is configured with table filtering rules. The withhold events are executed when their parent Query destiny is determined for execution as well. */ Deferred_log_events *deferred_events; /* State of the container: true stands for IRU events gathering, false does for execution, either deferred or direct. */ bool deferred_events_collecting; Annotate_rows_log_event *m_annotate_event; RPL_TABLE_LIST *tables_to_lock; /* RBR: Tables to lock */ uint tables_to_lock_count; /* RBR: Count of tables to lock */ table_mapping m_table_map; /* RBR: Mapping table-id to table */ mysql_mutex_t sleep_lock; mysql_cond_t sleep_cond; /* trans_retries varies between 0 to slave_transaction_retries and counts how many times the slave has retried the present transaction; gets reset to 0 when the transaction finally succeeds. */ ulong trans_retries; /* Used to defer stopping the SQL thread to give it a chance to finish up the current group of events. The timestamp is set and reset in @c sql_slave_killed(). */ time_t last_event_start_time; char *event_relay_log_name; char event_relay_log_name_buf[FN_REFLEN]; ulonglong event_relay_log_pos; ulonglong future_event_relay_log_pos; /* The master log name for current event. Only used in parallel replication. */ char future_event_master_log_name[FN_REFLEN]; bool is_parallel_exec; /* When gtid_pending is true, we have not yet done record_gtid(). */ bool gtid_pending; int worker_error; /* Set true when we signalled that we reach the commit phase. Used to avoid counting one event group twice. */ bool did_mark_start_commit; /* Copy of flags2 from GTID event. */ uchar gtid_ev_flags2; /* Copy of flags3 from GTID event. */ uint16 gtid_ev_flags_extra; uint64 gtid_ev_sa_seq_no; enum { GTID_DUPLICATE_NULL=0, GTID_DUPLICATE_IGNORE=1, GTID_DUPLICATE_OWNER=2 }; /* When --gtid-ignore-duplicates, this is set to one of the above three values: GTID_DUPLICATE_NULL - Not using --gtid-ignore-duplicates. GTID_DUPLICATE_IGNORE - This gtid already applied, skip the event group. GTID_DUPLICATE_OWNER - We are the current owner of the domain, and must apply the event group and then release the domain. */ uint8 gtid_ignore_duplicate_state; /* Runtime state for printing a note when slave is taking too long while processing a row event. */ longlong row_stmt_start_timestamp; bool long_find_row_note_printed; /* Needs room for "Gtid D-S-N\x00". */ mutable char gtid_info_buf[5+10+1+10+1+20+1]; /* The timestamp, from the master, of the commit event. Used to do delayed update of rli->last_master_timestamp, for getting reasonable values out of Seconds_Behind_Master in SHOW SLAVE STATUS. */ time_t last_master_timestamp; /* Information to be able to re-try an event group in case of a deadlock or other temporary error. */ inuse_relaylog *relay_log; uint64 retry_start_offset; uint64 retry_event_count; /* If `speculation' is != SPECULATE_NO, then we are optimistically running this transaction in parallel, even though it might not be safe (there may be a conflict with a prior event group). In this case, a conflict can cause other errors than deadlocks (like duplicate key for example). So in case of _any_ error, we need to roll back and retry the event group. */ enum enum_speculation { /* This transaction was group-committed together on the master with the other transactions with which it is replicated in parallel. */ SPECULATE_NO, /* We will optimistically try to run this transaction in parallel with other transactions, even though it is not known to be conflict free. If we get a conflict, we will detect it as a deadlock, roll back and retry. */ SPECULATE_OPTIMISTIC, /* This transaction got a conflict during speculative parallel apply, or it was marked on the master as likely to cause a conflict or unsafe to speculate. So it will wait for the prior transaction to commit before starting to replicate. */ SPECULATE_WAIT } speculation; enum enum_retry_killed { RETRY_KILL_NONE = 0, RETRY_KILL_PENDING, RETRY_KILL_KILLED }; uchar killed_for_retry; bool reserved_start_alter_thread; bool finish_event_group_called; /* Used for two phase alter table */ rpl_parallel_thread *rpt; Query_log_event *start_alter_ev; bool direct_commit_alter; start_alter_info *sa_info; rpl_group_info(Relay_log_info *rli_); ~rpl_group_info(); void reinit(Relay_log_info *rli); /* Returns true if the argument event resides in the containter; more specifically, the checking is done against the last added event. */ bool is_deferred_event(Log_event * ev) { return deferred_events_collecting ? deferred_events->is_last(ev) : false; }; /* The general cleanup that slave applier may need at the end of query. */ inline void cleanup_after_query() { if (deferred_events) deferred_events->rewind(); }; /* The general cleanup that slave applier may need at the end of session. */ void cleanup_after_session() { if (deferred_events) { delete deferred_events; deferred_events= NULL; } }; /** Save pointer to Annotate_rows event and switch on the binlog_annotate_row_events for this sql thread. To be called when sql thread receives an Annotate_rows event. */ inline void set_annotate_event(Annotate_rows_log_event *event) { DBUG_ASSERT(m_annotate_event == NULL); m_annotate_event= event; this->thd->variables.binlog_annotate_row_events= 1; } /** Returns pointer to the saved Annotate_rows event or NULL if there is no saved event. */ inline Annotate_rows_log_event* get_annotate_event() { return m_annotate_event; } /** Delete saved Annotate_rows event (if any) and switch off the binlog_annotate_row_events for this sql thread. To be called when sql thread has applied the last (i.e. with STMT_END_F flag) rbr event. */ inline void free_annotate_event() { if (m_annotate_event) { this->thd->variables.binlog_annotate_row_events= 0; delete m_annotate_event; m_annotate_event= 0; } } void clear_tables_to_lock(); void cleanup_context(THD *, bool, bool keep_domain_owner= false); void slave_close_thread_tables(THD *); void mark_start_commit_no_lock(); void mark_start_commit(); char *gtid_info() const; void unmark_start_commit(); longlong get_row_stmt_start_timestamp() { return row_stmt_start_timestamp; } void set_row_stmt_start_timestamp() { if (row_stmt_start_timestamp == 0) row_stmt_start_timestamp= microsecond_interval_timer(); } void reset_row_stmt_start_timestamp() { row_stmt_start_timestamp= 0; } void set_long_find_row_note_printed() { long_find_row_note_printed= true; } void unset_long_find_row_note_printed() { long_find_row_note_printed= false; } bool is_long_find_row_note_printed() { return long_find_row_note_printed; } inline void inc_event_relay_log_pos() { if (!is_parallel_exec) rli->event_relay_log_pos= future_event_relay_log_pos; } void finish_start_alter_event_group(); bool get_finish_event_group_called() { return finish_event_group_called; } void set_finish_event_group_called(bool value) { finish_event_group_called= value; } }; /* The class rpl_sql_thread_info is the THD::system_thread_info for an SQL thread; this is either the driver SQL thread or a worker thread for parallel replication. */ class rpl_sql_thread_info { public: char cached_charset[6]; Rpl_filter* rpl_filter; rpl_sql_thread_info(Rpl_filter *filter); /* Last charset (6 bytes) seen by slave SQL thread is cached here; it helps the thread save 3 get_charset() per Query_log_event if the charset is not changing from event to event (common situation). When the 6 bytes are equal to 0 is used to mean "cache is invalidated". */ void cached_charset_invalidate(); bool cached_charset_compare(char *charset) const; }; extern struct rpl_slave_state *rpl_global_gtid_slave_state; extern gtid_waiting rpl_global_gtid_waiting; int rpl_load_gtid_slave_state(THD *thd); int find_gtid_slave_pos_tables(THD *thd); int event_group_new_gtid(rpl_group_info *rgi, Gtid_log_event *gev); void delete_or_keep_event_post_apply(rpl_group_info *rgi, Log_event_type typ, Log_event *ev); #endif /* RPL_RLI_H */ custom_conf.h 0000644 00000002072 15156036163 0007243 0 ustar 00 /* Copyright (c) 2000, 2006 MySQL AB Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef __MYSQL_CUSTOM_BUILD_CONFIG__ #define __MYSQL_CUSTOM_BUILD_CONFIG__ #define MYSQL_PORT 5002 #ifdef _WIN32 #define MYSQL_NAMEDPIPE "SwSqlServer" #define MYSQL_SERVICENAME "SwSqlServer" #define KEY_SERVICE_PARAMETERS "SYSTEM\\CurrentControlSet\\Services\\SwSqlServer\\Parameters" #endif #endif /* __MYSQL_CUSTOM_BUILD_CONFIG__ */ sql_plugin_compat.h 0000644 00000004275 15156036164 0010454 0 ustar 00 /* Copyright (C) 2013 Sergei Golubchik and Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* old plugin api structures, used for backward compatibility */ #define upgrade_var(X) latest->X= X #define upgrade_str(X) strmake_buf(latest->X, X) #define downgrade_var(X) X= latest->X #define downgrade_str(X) strmake_buf(X, latest->X) /**************************************************************/ /* Authentication API, version 0x0100 *************************/ #define MIN_AUTHENTICATION_INTERFACE_VERSION 0x0100 struct MYSQL_SERVER_AUTH_INFO_0x0100 { const char *user_name; unsigned int user_name_length; const char *auth_string; unsigned long auth_string_length; char authenticated_as[49]; char external_user[512]; int password_used; const char *host_or_ip; unsigned int host_or_ip_length; void upgrade(MYSQL_SERVER_AUTH_INFO *latest) { upgrade_var(user_name); upgrade_var(user_name_length); upgrade_var(auth_string); upgrade_var(auth_string_length); upgrade_str(authenticated_as); upgrade_str(external_user); upgrade_var(password_used); upgrade_var(host_or_ip); upgrade_var(host_or_ip_length); } void downgrade(MYSQL_SERVER_AUTH_INFO *latest) { downgrade_var(user_name); downgrade_var(user_name_length); downgrade_var(auth_string); downgrade_var(auth_string_length); downgrade_str(authenticated_as); downgrade_str(external_user); downgrade_var(password_used); downgrade_var(host_or_ip); downgrade_var(host_or_ip_length); } }; /**************************************************************/ aria_backup.h 0000644 00000003373 15156036164 0007173 0 ustar 00 /* Copyright (C) 2018,2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ /* Interfaces for doing backups of Aria tables */ #ifndef ARIA_BACKUP_INCLUDED C_MODE_START typedef struct st_aria_table_capabilities { my_off_t header_size; MARIA_CRYPT_DATA *crypt_data; uint crypt_page_header_space; ulong bitmap_pages_covered; uint block_size; uint keypage_header; enum data_file_type data_file_type; my_bool checksum; my_bool transactional; my_bool encrypted; /* This is true if the table can be copied without any locks */ my_bool online_backup_safe; /* s3 capabilities */ ulong s3_block_size; uint8 compression; char filename[FN_REFLEN]; } ARIA_TABLE_CAPABILITIES; int aria_get_capabilities(File kfile, const char *table_name, ARIA_TABLE_CAPABILITIES *cap); void aria_free_capabilities(ARIA_TABLE_CAPABILITIES *cap); int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, uchar *buffer); int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, uchar *buffer, size_t *bytes_read); C_MODE_END #endif /* ARIA_BACKUP_INCLUDED */ t_ctype.h 0000644 00000013007 15156036164 0006374 0 ustar 00 /* Copyright (C) 2000 MySQL AB Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved. Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved. Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies. Smaphan Raruenrom and Pruet Boonma makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /* LC_COLLATE category + Level information */ #ifndef _t_ctype_h #define _t_ctype_h #define TOT_LEVELS 5 #define LAST_LEVEL 4 /* TOT_LEVELS - 1 */ #define IGNORE 0 /* level 1 symbols & order */ enum l1_symbols { L1_08 = TOT_LEVELS, L1_18, L1_28, L1_38, L1_48, L1_58, L1_68, L1_78, L1_88, L1_98, L1_A8, L1_B8, L1_C8, L1_D8, L1_E8, L1_F8, L1_G8, L1_H8, L1_I8, L1_J8, L1_K8, L1_L8, L1_M8, L1_N8, L1_O8, L1_P8, L1_Q8, L1_R8, L1_S8, L1_T8, L1_U8, L1_V8, L1_W8, L1_X8, L1_Y8, L1_Z8, L1_KO_KAI, L1_KHO_KHAI, L1_KHO_KHUAT, L1_KHO_KHWAI, L1_KHO_KHON, L1_KHO_RAKHANG, L1_NGO_NGU, L1_CHO_CHAN, L1_CHO_CHING, L1_CHO_CHANG, L1_SO_SO, L1_CHO_CHOE, L1_YO_YING, L1_DO_CHADA, L1_TO_PATAK, L1_THO_THAN, L1_THO_NANGMONTHO, L1_THO_PHUTHAO, L1_NO_NEN, L1_DO_DEK, L1_TO_TAO, L1_THO_THUNG, L1_THO_THAHAN, L1_THO_THONG, L1_NO_NU, L1_BO_BAIMAI, L1_PO_PLA, L1_PHO_PHUNG, L1_FO_FA, L1_PHO_PHAN, L1_FO_FAN, L1_PHO_SAMPHAO, L1_MO_MA, L1_YO_YAK, L1_RO_RUA, L1_RU, L1_LO_LING, L1_LU, L1_WO_WAEN, L1_SO_SALA, L1_SO_RUSI, L1_SO_SUA, L1_HO_HIP, L1_LO_CHULA, L1_O_ANG, L1_HO_NOKHUK, L1_NKHIT, L1_SARA_A, L1_MAI_HAN_AKAT, L1_SARA_AA, L1_SARA_AM, L1_SARA_I, L1_SARA_II, L1_SARA_UE, L1_SARA_UEE, L1_SARA_U, L1_SARA_UU, L1_SARA_E, L1_SARA_AE, L1_SARA_O, L1_SARA_AI_MAIMUAN, L1_SARA_AI_MAIMALAI }; /* level 2 symbols & order */ enum l2_symbols { L2_BLANK = TOT_LEVELS, L2_THAII, L2_YAMAK, L2_PINTHU, L2_GARAN, L2_TYKHU, L2_TONE1, L2_TONE2, L2_TONE3, L2_TONE4 }; /* level 3 symbols & order */ enum l3_symbols { L3_BLANK = TOT_LEVELS, L3_SPACE, L3_NB_SACE, L3_LOW_LINE, L3_HYPHEN, L3_COMMA, L3_SEMICOLON, L3_COLON, L3_EXCLAMATION, L3_QUESTION, L3_SOLIDUS, L3_FULL_STOP, L3_PAIYAN_NOI, L3_MAI_YAMOK, L3_GRAVE, L3_CIRCUMFLEX, L3_TILDE, L3_APOSTROPHE, L3_QUOTATION, L3_L_PARANTHESIS, L3_L_BRACKET, L3_L_BRACE, L3_R_BRACE, L3_R_BRACKET, L3_R_PARENTHESIS, L3_AT, L3_BAHT, L3_DOLLAR, L3_FONGMAN, L3_ANGKHANKHU, L3_KHOMUT, L3_ASTERISK, L3_BK_SOLIDUS, L3_AMPERSAND, L3_NUMBER, L3_PERCENT, L3_PLUS, L3_LESS_THAN, L3_EQUAL, L3_GREATER_THAN, L3_V_LINE }; /* level 4 symbols & order */ enum l4_symbols { L4_BLANK = TOT_LEVELS, L4_MIN, L4_CAP, L4_EXT }; enum level_symbols { L_UPRUPR = TOT_LEVELS, L_UPPER, L_MIDDLE, L_LOWER }; #define _is(c) (t_ctype[(c)][LAST_LEVEL]) #define _level 8 #define _consnt 16 #define _ldvowel 32 #define _fllwvowel 64 #define _uprvowel 128 #define _lwrvowel 256 #define _tone 512 #define _diacrt1 1024 #define _diacrt2 2048 #define _combine 4096 #define _stone 8192 #define _tdig 16384 #define _rearvowel (_fllwvowel | _uprvowel | _lwrvowel) #define _diacrt (_diacrt1 | _diacrt2) #define levelof(c) ( _is(c) & _level ) #define isthai(c) ( (c) >= 128 ) #define istalpha(c) ( _is(c) & (_consnt|_ldvowel|_rearvowel|\ _tone|_diacrt1|_diacrt2) ) #define isconsnt(c) ( _is(c) & _consnt ) #define isldvowel(c) ( _is(c) & _ldvowel ) #define isfllwvowel(c) ( _is(c) & _fllwvowel ) #define ismidvowel(c) ( _is(c) & (_ldvowel|_fllwvowel) ) #define isuprvowel(c) ( _is(c) & _uprvowel ) #define islwrvowel(c) ( _is(c) & _lwrvowel ) #define isuprlwrvowel(c) ( _is(c) & (_lwrvowel | _uprvowel)) #define isrearvowel(c) ( _is(c) & _rearvowel ) #define isvowel(c) ( _is(c) & (_ldvowel|_rearvowel) ) #define istone(c) ( _is(c) & _tone ) #define isunldable(c) ( _is(c) & (_rearvowel|_tone|_diacrt1|_diacrt2) ) #define iscombinable(c) ( _is(c) & _combine ) #define istdigit(c) ( _is(c) & _tdig ) #define isstone(c) ( _is(c) & _stone ) #define isdiacrt1(c) ( _is(c) & _diacrt1) #define isdiacrt2(c) ( _is(c) & _diacrt2) #define isdiacrt(c) ( _is(c) & _diacrt) /* Function prototype called by sql/field.cc */ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length); #endif my_minidump.h 0000644 00000001520 15156036164 0007251 0 ustar 00 /* Copyright (c) 2021, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include <windows.h> #ifdef __cplusplus extern "C" { #endif BOOL my_create_minidump(DWORD pid, BOOL verbose); #ifdef __cplusplus } #endif item_subselect.h 0000644 00000163224 15156036164 0007743 0 ustar 00 #ifndef ITEM_SUBSELECT_INCLUDED #define ITEM_SUBSELECT_INCLUDED /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* subselect Item */ #include "item.h" #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include <queues.h> class st_select_lex; class st_select_lex_unit; class JOIN; class select_result_interceptor; class subselect_engine; class subselect_hash_sj_engine; class Item_bool_func2; class Comp_creator; class With_element; class Field_pair; typedef class st_select_lex SELECT_LEX; /** Convenience typedef used in this file, and further used by any files including this file. */ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); class Cached_item; class Subq_materialization_tracker; class Explain_subq_materialization; /* base class for subselects */ class Item_subselect :public Item_result_field, protected Used_tables_and_const_cache { /* Set to TRUE if the value is assigned for the subselect FALSE: subquery not executed or the subquery returns an empty result */ bool value_assigned; bool own_engine; /* the engine was not taken from other Item_subselect */ protected: /* thread handler, will be assigned in fix_fields only */ THD *thd; /* old engine if engine was changed */ subselect_engine *old_engine; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; /* where subquery is placed */ enum_parsing_place parsing_place; /* work with 'substitution' */ bool have_to_be_excluded; bool inside_first_fix_fields; bool done_first_fix_fields; Item *expr_cache; /* Set to TRUE if at optimization or execution time we determine that this item's value is a constant. We need this member because it is not possible to substitute 'this' with a constant item. */ bool forced_const; /* Set to the result of the last call of is_expensive() */ bool expensive_fl; #ifndef DBUG_OFF /* Count the number of times this subquery predicate has been executed. */ uint exec_counter; #endif public: /* Used inside Item_subselect::fix_fields() according to this scenario: > Item_subselect::fix_fields > engine->prepare > child_join->prepare (Here we realize we need to do the rewrite and set substitution= some new Item, eg. Item_in_optimizer ) < child_join->prepare < engine->prepare *ref= substitution; substitution= NULL; < Item_subselect::fix_fields */ /* TODO make this protected member again. */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ /* TODO make this protected member again. */ subselect_engine *engine; /* unit of subquery */ st_select_lex_unit *unit; /* Cached buffers used when calling filesort in sub queries */ Filesort_buffer filesort_buffer; LEX_STRING sortbuffer; /* A reference from inside subquery predicate to somewhere outside of it */ class Ref_to_outside : public Sql_alloc { public: st_select_lex *select; /* Select where the reference is pointing to */ /* What is being referred. This may be NULL when we're referring to an aggregate function. */ Item *item; }; /* References from within this subquery to somewhere outside of it (i.e. to parent select, grandparent select, etc) */ List<Ref_to_outside> upper_refs; st_select_lex *parent_select; /* TRUE<=>Table Elimination has made it redundant to evaluate this select (and so it is not part of QEP, etc) */ bool eliminated; /* subquery is transformed */ bool changed; /* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */ bool is_correlated; /* TRUE <=> the subquery contains a recursive reference in the FROM list of one of its selects. In this case some of subquery optimization strategies cannot be applied for the subquery; */ bool with_recursive_reference; /* To link Item_subselects containing references to the same recursive CTE */ Item_subselect *next_with_rec_ref; enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS, EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS}; Item_subselect(THD *thd); virtual subs_type substype() { return UNKNOWN_SUBS; } bool is_exists_predicate() { return substype() == Item_subselect::EXISTS_SUBS; } bool is_in_predicate() { return get_IN_subquery() != NULL; } /* We need this method, because some compilers do not allow 'this' pointer in constructor initialization list, but we need to pass a pointer to subselect Item class to select_result_interceptor's constructor. */ virtual void init (st_select_lex *select_lex, select_result_interceptor *result); ~Item_subselect(); void cleanup() override; virtual void reset() { eliminated= FALSE; null_value= 1; } /** Set the subquery result to a default value consistent with the semantics of the result row produced for queries with implicit grouping. */ void no_rows_in_result() override= 0; virtual bool select_transformer(JOIN *join); bool assigned() { return value_assigned; } void assigned(bool a) { value_assigned= a; } enum Type type() const override; bool is_null() override { update_null_value(); return null_value; } bool fix_fields(THD *thd, Item **ref) override; bool mark_as_dependent(THD *thd, st_select_lex *select, Item *item); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; void recalc_used_tables(st_select_lex *new_parent, bool after_pullout); virtual bool exec(); /* If subquery optimization or execution determines that the subquery has an empty result, mark the subquery predicate as a constant value. */ void make_const() { used_tables_cache= 0; const_item_cache= 0; forced_const= TRUE; } virtual bool fix_length_and_dec(); table_map used_tables() const override; table_map not_null_tables() const override { return 0; } bool const_item() const override; inline table_map get_used_tables_cache() { return used_tables_cache; } Item *get_tmp_table_item(THD *thd) override; void update_used_tables() override; void print(String *str, enum_query_type query_type) override; virtual bool have_guarded_conds() { return FALSE; } bool change_engine(subselect_engine *eng) { old_engine= engine; engine= eng; return eng == 0; } bool engine_changed(subselect_engine *eng) { return engine != eng; } /* True if this subquery has been already evaluated. Implemented only for single select and union subqueries only. */ bool is_evaluated() const; bool is_uncacheable() const; bool is_expensive() override; /* Used by max/min subquery to initialize value presence registration mechanism. Engine call this method before rexecution query. */ virtual void reset_value_registration() {} enum_parsing_place place() { return parsing_place; } bool walk(Item_processor processor, bool walk_subquery, void *arg) override; bool unknown_splocal_processor(void *arg) override; bool mark_as_eliminated_processor(void *arg) override; bool eliminate_subselect_processor(void *arg) override; bool enumerate_field_refs_processor(void *arg) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("select ...", arg, VCOL_IMPOSSIBLE); } /** Callback to test if an IN predicate is expensive. @notes The return value affects the behavior of make_cond_for_table(). @retval TRUE if the predicate is expensive @retval FALSE otherwise */ bool is_expensive_processor(void *arg) override { return is_expensive(); } bool update_table_bitmaps_processor(void *arg) override; /** Get the SELECT_LEX structure associated with this Item. @return the SELECT_LEX structure associated with this Item */ st_select_lex* get_select_lex(); bool expr_cache_is_needed(THD *) override; void get_cache_parameters(List<Item> ¶meters) override; bool is_subquery_processor (void *opt_arg) override { return 1; } bool exists2in_processor(void *opt_arg) override { return 0; } bool limit_index_condition_pushdown_processor(void *opt_arg) override { return TRUE; } bool subselect_table_finder_processor(void *arg) override; void register_as_with_rec_ref(With_element *with_elem); void init_expr_cache_tracker(THD *thd); st_select_lex *wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl); protected: Item* deep_copy(THD *thd) const override { return nullptr; } Item *shallow_copy(THD *thd) const override { return nullptr; } friend class select_result_interceptor; friend class Item_in_optimizer; friend bool Item_field::fix_fields(THD *, Item **); friend int Item_field::fix_outer_field(THD *, Field **, Item **); friend bool Item_ref::fix_fields(THD *, Item **); friend void mark_select_range_as_dependent(THD*, st_select_lex*, st_select_lex*, Field*, Item*, Item_ident*, bool); friend bool convert_join_subqueries_to_semijoins(JOIN *join); }; /* single value subselect */ class Item_cache; class Item_singlerow_subselect :public Item_subselect { protected: Item_cache *value, **row; public: Item_singlerow_subselect(THD *thd_arg, st_select_lex *select_lex); Item_singlerow_subselect(THD *thd_arg): Item_subselect(thd_arg), value(0), row (0) {} void cleanup() override; subs_type substype() override { return SINGLEROW_SUBS; } void reset() override; void no_rows_in_result() override; bool select_transformer(JOIN *join) override; void store(uint i, Item* item); double val_real() override; longlong val_int() override; String *val_str(String *) override; bool val_native(THD *thd, Native *) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; const Type_handler *type_handler() const override; bool fix_length_and_dec() override; uint cols() const override; Item* element_index(uint i) override { return reinterpret_cast<Item*>(row[i]); } Item** addr(uint i) override { return (Item**)row + i; } bool check_cols(uint c) override; bool null_inside() override; void bring_value() override; /** This method is used to implement a special case of semantic tree rewriting, mandated by a SQL:2003 exception in the specification. The only caller of this method is handle_sql2003_note184_exception(), see the code there for more details. Note that this method breaks the object internal integrity, by removing it's association with the corresponding SELECT_LEX, making this object orphan from the parse tree. No other method, beside the destructor, should be called on this object, as it is now invalid. @return the SELECT_LEX structure that was given in the constructor. */ st_select_lex* invalidate_and_restore_select_lex(); Item* expr_cache_insert_transformer(THD *thd, uchar *unused) override; friend class select_singlerow_subselect; }; /* used in static ALL/ANY optimization */ class select_max_min_finder_subselect; class Item_maxmin_subselect :public Item_singlerow_subselect { protected: bool max; bool was_values; // Set if we have found at least one row public: Item_maxmin_subselect(THD *thd, Item_subselect *parent, st_select_lex *select_lex, bool max); void print(String *str, enum_query_type query_type) override; void cleanup() override; bool any_value() { return was_values; } void register_value() { was_values= TRUE; } void reset_value_registration() override { was_values= FALSE; } void no_rows_in_result() override; }; /* exists subselect */ class Item_exists_subselect :public Item_subselect { protected: Item_func_not *upper_not; bool value; /* value of this item (boolean: exists/not-exists) */ void init_length_and_dec(); bool select_prepare_to_be_in(); public: /* Used by subquery optimizations to keep track about in which clause this subquery predicate is located: NO_JOIN_NEST - the predicate is an AND-part of the WHERE join nest pointer - the predicate is an AND-part of ON expression of a join nest NULL - for all other locations */ TABLE_LIST *emb_on_expr_nest; /** Reference on the Item_in_optimizer wrapper of this subquery */ Item_in_optimizer *optimizer; /* true if we got this from EXISTS or to IN */ bool exists_transformed; Item_exists_subselect(THD *thd_arg, st_select_lex *select_lex); Item_exists_subselect(THD *thd_arg): Item_subselect(thd_arg), upper_not(NULL), emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0) {} subs_type substype() override { return EXISTS_SUBS; } void reset() override { eliminated= FALSE; value= 0; } void no_rows_in_result() override; const Type_handler *type_handler() const override { return &type_handler_bool; } longlong val_int() override; double val_real() override; String *val_str(String*) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_int(thd, ltime, fuzzydate); } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec() override; void print(String *str, enum_query_type query_type) override; bool select_transformer(JOIN *join) override; bool exists2in_processor(void *opt_arg) override; Item* expr_cache_insert_transformer(THD *thd, uchar *unused) override; void mark_as_condition_AND_part(TABLE_LIST *embedding) override { emb_on_expr_nest= embedding; } void under_not(Item_func_not *upper) override { upper_not= upper; }; void set_exists_transformed() { exists_transformed= TRUE; } friend class select_exists_subselect; friend class subselect_uniquesubquery_engine; friend class subselect_indexsubquery_engine; }; TABLE_LIST * const NO_JOIN_NEST=(TABLE_LIST*)0x1; /* Possible methods to execute an IN predicate. These are set by the optimizer based on user-set optimizer switches, semantic analysis and cost comparison. */ #define SUBS_NOT_TRANSFORMED 0 /* No execution method was chosen for this IN. */ /* The Final decision about the strategy is made. */ #define SUBS_STRATEGY_CHOSEN 1 #define SUBS_SEMI_JOIN 2 /* IN was converted to semi-join. */ #define SUBS_IN_TO_EXISTS 4 /* IN was converted to correlated EXISTS. */ #define SUBS_MATERIALIZATION 8 /* Execute IN via subquery materialization. */ /* Partial matching substrategies of MATERIALIZATION. */ #define SUBS_PARTIAL_MATCH_ROWID_MERGE 16 #define SUBS_PARTIAL_MATCH_TABLE_SCAN 32 /* ALL/ANY will be transformed with max/min optimization */ /* The subquery has not aggregates, transform it into a MAX/MIN query. */ #define SUBS_MAXMIN_INJECTED 64 /* The subquery has aggregates, use a special max/min subselect engine. */ #define SUBS_MAXMIN_ENGINE 128 /** Representation of IN subquery predicates of the form "left_expr IN (SELECT ...)". @details This class has: - A "subquery execution engine" (as a subclass of Item_subselect) that allows it to evaluate subqueries. (and this class participates in execution by having was_null variable where part of execution result is stored. - Transformation methods (todo: more on this). This class is not used directly, it is "wrapped" into Item_in_optimizer which provides some small bits of subquery evaluation. */ class Item_in_subselect :public Item_exists_subselect { protected: /* Cache of the left operand of the subquery predicate. Allocated in the runtime memory root, for each execution, thus need not be freed. */ List<Cached_item> *left_expr_cache; bool first_execution; /* expr & optimizer used in subselect rewriting to store Item for all JOIN in UNION */ Item *expr; bool was_null; /* A bitmap of possible execution strategies for an IN predicate. */ uchar in_strategy; /* Tracker collecting execution parameters of a materialized subquery */ Subq_materialization_tracker *materialization_tracker; protected: /* Used to trigger on/off conditions that were pushed down to subselect */ bool *pushed_cond_guards; Comp_creator *func; protected: bool init_cond_guards(); bool select_in_like_transformer(JOIN *join); bool single_value_transformer(JOIN *join); bool row_value_transformer(JOIN * join); bool fix_having(Item *having, st_select_lex *select_lex); bool create_single_in_to_exists_cond(JOIN * join, Item **where_item, Item **having_item); bool create_row_in_to_exists_cond(JOIN * join, Item **where_item, Item **having_item); Item *left_expr; /* Important for PS/SP: left_expr_orig is the item that left_expr originally pointed at. That item is allocated on the statement arena, while left_expr could later be changed to something on the execution arena. */ Item *left_expr_orig; public: /* Priority of this predicate in the convert-to-semi-join-nest process. */ int sj_convert_priority; /* May be TRUE only for the candidates to semi-join conversion */ bool do_not_convert_to_sj; /* Types of left_expr and subquery's select list allow to perform subquery materialization. Currently, we set this to FALSE when it as well could be TRUE. This is to be properly addressed with fix for BUG#36752. */ bool types_allow_materialization; /* Same as above, but they also allow to scan the materialized table. */ bool sjm_scan_allowed; /* JoinTaB Materialization (JTBM) members */ /* TRUE <=> This subselect has been converted into non-mergeable semi-join table. */ bool is_jtbm_merged; /* (Applicable if is_jtbm_merged==TRUE) Time required to run the materialized join */ double jtbm_read_time; /* (Applicable if is_jtbm_merged==TRUE) Number of output rows in materialized join */ double jtbm_record_count; /* (Applicable if is_jtbm_merged==TRUE) TRUE <=> The materialized subselect is a degenerate subselect which produces 0 or 1 rows, which we know at optimization phase. Examples: 1. subquery has "Impossible WHERE": SELECT * FROM ot WHERE ot.column IN (SELECT it.col FROM it WHERE 2 > 3) 2. Subquery produces one row which opt_sum.cc is able to get with one lookup: SELECT * FROM ot WHERE ot.column IN (SELECT MAX(it.key_col) FROM it) */ bool is_jtbm_const_tab; /* (Applicable if is_jtbm_const_tab==TRUE) Whether the subquery has produced the row (or not) */ bool jtbm_const_row_found; /* TRUE<=>this is a flattenable semi-join, false otherwise. */ bool is_flattenable_semijoin; /* TRUE<=>registered in the list of semijoins in outer select */ bool is_registered_semijoin; List<Field_pair> corresponding_fields; /* Used to determine how this subselect item is represented in the item tree, in case there is a need to locate it there and replace with something else. Two options are possible: 1. This item is there 'as-is'. 1. This item is wrapped within Item_in_optimizer. */ Item *original_item() { return (is_flattenable_semijoin && !exists_transformed ? (Item*)this : (Item*)optimizer); } bool *get_cond_guard(int i) { return pushed_cond_guards ? pushed_cond_guards + i : NULL; } void set_cond_guard_var(int i, bool v) { if ( pushed_cond_guards) pushed_cond_guards[i]= v; } bool have_guarded_conds() override { return MY_TEST(pushed_cond_guards); } Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery /* SET to TRUE if IN subquery is converted from an IN predicate */ bool converted_from_in_predicate; Item_in_subselect(THD *thd_arg, Item * left_expr, st_select_lex *select_lex); Item_in_subselect(THD *thd_arg): Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), materialization_tracker(NULL), pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0), converted_from_in_predicate(FALSE) {} void cleanup() override; subs_type substype() override { return IN_SUBS; } void reset() override { eliminated= FALSE; value= 0; null_value= 0; was_null= 0; is_jtbm_const_tab= 0; } bool select_transformer(JOIN *join) override; bool create_in_to_exists_cond(JOIN *join_arg); bool inject_in_to_exists_cond(JOIN *join_arg); bool exec() override; longlong val_int() override; double val_real() override; String *val_str(String*) override; my_decimal *val_decimal(my_decimal *) override; bool val_bool() override; bool test_limit(st_select_lex_unit *unit); void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return IN_PRECEDENCE; } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec() override; void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; bool const_item() const override { return Item_subselect::const_item() && left_expr->const_item(); } void update_used_tables() override; bool setup_mat_engine(); bool init_left_expr_cache(); /* Inform 'this' that it was computed, and contains a valid result. */ void set_first_execution() { if (first_execution) first_execution= FALSE; } bool expr_cache_is_needed(THD *thd) override; inline bool left_expr_has_null(); void disable_cond_guard_for_const_null_left_expr(int i) { if (left_expr->can_eval_in_optimize()) { if (left_expr->element_index(i)->is_null()) set_cond_guard_var(i,FALSE); } } int optimize(double *out_rows, double *cost); /* Return the identifier that we could use to identify the subquery for the user. */ int get_identifier(); void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; } bool test_strategy(uchar strategy) { return MY_TEST(in_strategy & strategy); } /** Test that the IN strategy was chosen for execution. This is so when the CHOSEN flag is ON, and there is no other strategy. */ bool test_set_strategy(uchar strategy) { DBUG_ASSERT(strategy == SUBS_SEMI_JOIN || strategy == SUBS_IN_TO_EXISTS || strategy == SUBS_MATERIALIZATION || strategy == SUBS_PARTIAL_MATCH_ROWID_MERGE || strategy == SUBS_PARTIAL_MATCH_TABLE_SCAN || strategy == SUBS_MAXMIN_INJECTED || strategy == SUBS_MAXMIN_ENGINE); return ((in_strategy & SUBS_STRATEGY_CHOSEN) && (in_strategy & ~SUBS_STRATEGY_CHOSEN) == strategy); } bool is_set_strategy() { return MY_TEST(in_strategy & SUBS_STRATEGY_CHOSEN); } bool has_strategy() { return in_strategy != SUBS_NOT_TRANSFORMED; } void add_strategy (uchar strategy) { DBUG_ENTER("Item_in_subselect::add_strategy"); DBUG_PRINT("enter", ("current: %u add: %u", (uint) in_strategy, (uint) strategy)); DBUG_ASSERT(strategy != SUBS_NOT_TRANSFORMED); DBUG_ASSERT(!(strategy & SUBS_STRATEGY_CHOSEN)); /* TODO: PS re-execution breaks this condition, because check_and_do_in_subquery_rewrites() is called for each reexecution and re-adds the same strategies. DBUG_ASSERT(!(in_strategy & SUBS_STRATEGY_CHOSEN)); */ in_strategy|= strategy; DBUG_VOID_RETURN; } void reset_strategy(uchar strategy) { DBUG_ENTER("Item_in_subselect::reset_strategy"); DBUG_PRINT("enter", ("current: %u new: %u", (uint) in_strategy, (uint) strategy)); DBUG_ASSERT(strategy != SUBS_NOT_TRANSFORMED); in_strategy= strategy; DBUG_VOID_RETURN; } void set_strategy(uchar strategy) { DBUG_ENTER("Item_in_subselect::set_strategy"); DBUG_PRINT("enter", ("current: %u set: %u", (uint) in_strategy, (uint) (SUBS_STRATEGY_CHOSEN | strategy))); /* Check that only one strategy is set for execution. */ DBUG_ASSERT(strategy == SUBS_SEMI_JOIN || strategy == SUBS_IN_TO_EXISTS || strategy == SUBS_MATERIALIZATION || strategy == SUBS_PARTIAL_MATCH_ROWID_MERGE || strategy == SUBS_PARTIAL_MATCH_TABLE_SCAN || strategy == SUBS_MAXMIN_INJECTED || strategy == SUBS_MAXMIN_ENGINE); in_strategy= (SUBS_STRATEGY_CHOSEN | strategy); DBUG_VOID_RETURN; } bool walk(Item_processor processor, bool walk_subquery, void *arg) override { return left_expr->walk(processor, walk_subquery, arg) || Item_subselect::walk(processor, walk_subquery, arg); } bool exists2in_processor(void *opt_arg __attribute__((unused))) override { return 0; }; bool pushdown_cond_for_in_subquery(THD *thd, Item *cond); Item_in_subselect *get_IN_subquery() override { return this; } inline Item** left_exp_ptr() { return &left_expr; } inline Item* left_exp() const { return left_expr; } inline Item* left_exp_orig() const { return left_expr_orig; } void init_subq_materialization_tracker(THD *thd); Subq_materialization_tracker *get_materialization_tracker() const { return materialization_tracker; } friend class Item_ref_null_helper; friend class Item_is_not_null_test; friend class Item_in_optimizer; friend class subselect_indexsubquery_engine; friend class subselect_hash_sj_engine; friend class subselect_partial_match_engine; friend class Item_exists_subselect; }; /* ALL/ANY/SOME subselect */ class Item_allany_subselect :public Item_in_subselect { public: chooser_compare_func_creator func_creator; bool all; Item_allany_subselect(THD *thd_arg, Item * left_expr, chooser_compare_func_creator fc, st_select_lex *select_lex, bool all); void cleanup() override; // only ALL subquery has upper not subs_type substype() override { return all?ALL_SUBS:ANY_SUBS; } bool select_transformer(JOIN *join) override; void create_comp_func(bool invert) { func= func_creator(invert); } void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return CMP_PRECEDENCE; } bool is_maxmin_applicable(JOIN *join); bool transform_into_max_min(JOIN *join); void no_rows_in_result() override; }; class subselect_engine: public Sql_alloc, public Type_handler_hybrid_field_type { protected: select_result_interceptor *result; /* results storage class */ THD *thd; /* pointer to current THD */ Item_subselect *item; /* item, that use this engine */ bool maybe_null; /* may be null (first item in select) */ public: enum enum_engine_type {ABSTRACT_ENGINE, SINGLE_SELECT_ENGINE, UNION_ENGINE, UNIQUESUBQUERY_ENGINE, INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE, ROWID_MERGE_ENGINE, TABLE_SCAN_ENGINE, SINGLE_COLUMN_ENGINE}; subselect_engine(Item_subselect *si, select_result_interceptor *res): Type_handler_hybrid_field_type(&type_handler_varchar), thd(NULL) { result= res; item= si; maybe_null= 0; } virtual ~subselect_engine() = default;; // to satisfy compiler virtual void cleanup()= 0; /* Also sets "thd" for subselect_engine::result. Should be called before prepare(). */ void set_thd(THD *thd_arg); THD * get_thd() { return thd ? thd : current_thd; } virtual int prepare(THD *)= 0; virtual bool fix_length_and_dec(Item_cache** row)= 0; /* Execute the engine SYNOPSIS exec() DESCRIPTION Execute the engine. The result of execution is subquery value that is either captured by previously set up select_result-based 'sink' or stored somewhere by the exec() method itself. A required side effect: If at least one pushed-down predicate is disabled, subselect_engine->no_rows() must return correct result after the exec() call. RETURN 0 - OK 1 - Either an execution error, or the engine was "changed", and the caller should call exec() again for the new engine. */ virtual int exec()= 0; virtual uint cols() const= 0; /* return number of columns in select */ virtual uint8 uncacheable()= 0; /* query is uncacheable */ virtual void exclude()= 0; virtual bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; static table_map calc_const_tables(TABLE_LIST *); static table_map calc_const_tables(List<TABLE_LIST> &list); virtual void print(String *str, enum_query_type query_type)= 0; virtual bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE)= 0; virtual bool no_tables() const = 0; /* Return true we can guarantee that the subquery will always return one row. */ virtual bool always_returns_one_row() const { return false; } virtual bool is_executed() const { return FALSE; } /* Check if subquery produced any rows during last query execution */ virtual bool no_rows() = 0; virtual enum_engine_type engine_type() { return ABSTRACT_ENGINE; } virtual int get_identifier() { DBUG_ASSERT(0); return 0; } virtual void force_reexecution() {} protected: bool set_row(List<Item> &item_list, Item_cache **row); }; class subselect_single_select_engine: public subselect_engine { bool prepared; /* simple subselect is prepared */ bool executed; /* simple subselect is executed */ st_select_lex *select_lex; /* corresponding select_lex */ JOIN * join; /* corresponding JOIN structure */ public: subselect_single_select_engine(st_select_lex *select, select_result_interceptor *result, Item_subselect *item); void cleanup() override; int prepare(THD *thd) override; bool fix_length_and_dec(Item_cache** row) override; int exec() override; uint cols() const override; uint8 uncacheable() override; void exclude() override; table_map upper_select_const_tables() override; void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp) override; bool no_tables() const override; bool always_returns_one_row() const override; bool may_be_null() override; bool is_executed() const override { return executed; } bool no_rows() override; enum_engine_type engine_type() override { return SINGLE_SELECT_ENGINE; } int get_identifier() override; void force_reexecution() override; void change_select(st_select_lex *new_select) { select_lex= new_select; } friend class subselect_hash_sj_engine; friend class Item_in_subselect; friend bool execute_degenerate_jtbm_semi_join(THD *thd, TABLE_LIST *tbl, Item_in_subselect *subq_pred, List<Item> &eq_list); }; class subselect_union_engine: public subselect_engine { st_select_lex_unit *unit; /* corresponding unit structure */ public: subselect_union_engine(st_select_lex_unit *u, select_result_interceptor *result, Item_subselect *item); void cleanup() override; int prepare(THD *) override; bool fix_length_and_dec(Item_cache** row) override; int exec() override; uint cols() const override; uint8 uncacheable() override; void exclude() override; table_map upper_select_const_tables() override; void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE) override; bool no_tables() const override; bool is_executed() const override; void force_reexecution() override; bool no_rows() override; enum_engine_type engine_type() override { return UNION_ENGINE; } }; struct st_join_table; /* A subquery execution engine that evaluates the subquery by doing one index lookup in a unique index. This engine is used to resolve subqueries in forms outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where) or, tuple-based: (oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK FROM tbl WHERE subqwhere) i.e. the subquery is a single table SELECT without GROUP BY, aggregate functions, etc. */ class subselect_uniquesubquery_engine: public subselect_engine { protected: st_join_table *tab; Item *cond; /* The WHERE condition of subselect */ /* TRUE<=> last execution produced empty set. Valid only when left expression is NULL. */ bool empty_result_set; public: // constructor can assign THD because it will be called after JOIN::prepare subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg, Item_in_subselect *subs, Item *where) :subselect_engine(subs, 0), tab(tab_arg), cond(where) { thd= thd_arg; DBUG_ASSERT(subs); } ~subselect_uniquesubquery_engine(); void cleanup() override; int prepare(THD *) override; bool fix_length_and_dec(Item_cache** row) override; int exec() override; uint cols() const override { return 1; } uint8 uncacheable() override { return UNCACHEABLE_DEPENDENT_INJECTED; } void exclude() override; table_map upper_select_const_tables() override { return 0; } void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE) override; bool no_tables() const override; int index_lookup(); /* TIMOUR: this method needs refactoring. */ int scan_table(); bool copy_ref_key(bool skip_constants); bool no_rows() override { return empty_result_set; } enum_engine_type engine_type() override { return UNIQUESUBQUERY_ENGINE; } }; class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine { /* FALSE for 'ref', TRUE for 'ref-or-null'. */ bool check_null; /* The "having" clause. This clause (further referred to as "artificial having") was inserted by subquery transformation code. It contains Item(s) that have a side-effect: they record whether the subquery has produced a row with NULL certain components. We need to use it for cases like (oe1, oe2) IN (SELECT t.key, t.no_key FROM t1) where we do index lookup on t.key=oe1 but need also to check if there was a row such that t.no_key IS NULL. NOTE: This is currently here and not in the uniquesubquery_engine. Ideally it should have been in uniquesubquery_engine in order to allow execution of subqueries like (oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl) We could use uniquesubquery_engine for the first component and let Item_is_not_null_test( non_key_maybe_null_field) to handle the second. However, subqueries like the above are currently not handled by index lookup-based subquery engines, the engine applicability check misses them: it doesn't switch the engine for case of artificial having and [eq_]ref access (only for artificial having + ref_or_null or no having). The above example subquery is handled as a full-blown SELECT with eq_ref access to one table. Due to this limitation, the "artificial having" currently needs to be checked by only in indexsubquery_engine. */ Item *having; public: // constructor can assign THD because it will be called after JOIN::prepare subselect_indexsubquery_engine(THD *thd_arg, st_join_table *tab_arg, Item_in_subselect *subs, Item *where, Item *having_arg, bool chk_null) :subselect_uniquesubquery_engine(thd_arg, tab_arg, subs, where), check_null(chk_null), having(having_arg) { DBUG_ASSERT(subs); } int exec() override; void print (String *str, enum_query_type query_type) override; enum_engine_type engine_type() override { return INDEXSUBQUERY_ENGINE; } }; /* This function is actually defined in sql_parse.cc, but it depends on chooser_compare_func_creator defined in this file. */ Item * all_any_subquery_creator(THD *thd, Item *left_expr, chooser_compare_func_creator cmp, bool all, SELECT_LEX *select_lex); inline bool Item_subselect::is_evaluated() const { return engine->is_executed(); } inline bool Item_subselect::is_uncacheable() const { return engine->uncacheable(); } /** Compute an IN predicate via a hash semi-join. This class is responsible for the materialization of the subquery, and the selection of the correct and optimal execution method (e.g. direct index lookup, or partial matching) for the IN predicate. */ class subselect_hash_sj_engine : public subselect_engine { public: /* The table into which the subquery is materialized. */ TABLE *tmp_table; /* TRUE if the subquery was materialized into a temp table. */ bool is_materialized; /* The old engine already chosen at parse time and stored in permanent memory. Through this member we can re-create and re-prepare materialize_join for each execution of a prepared statement. We also reuse the functionality of subselect_single_select_engine::[prepare | cols]. */ subselect_single_select_engine *materialize_engine; /* QEP to execute the subquery and materialize its result into a temporary table. Created during the first call to exec(). */ JOIN *materialize_join; /* A conjunction of all the equality conditions between all pairs of expressions that are arguments of an IN predicate. We need these to post-filter some IN results because index lookups sometimes match values that are actually not equal to the search key in SQL terms. */ Item_cond_and *semi_join_conds; Name_resolution_context *semi_join_conds_context; subselect_hash_sj_engine(THD *thd_arg, Item_in_subselect *in_predicate, subselect_single_select_engine *old_engine) : subselect_engine(in_predicate, NULL), tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine), materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL), count_partial_match_columns(0), count_null_only_columns(0), count_columns_with_nulls(0), strategy(UNDEFINED) { DBUG_ASSERT(in_predicate); } ~subselect_hash_sj_engine(); bool init(List<Item> *tmp_columns, uint subquery_id); void cleanup() override; int prepare(THD *) override; int exec() override; void print(String *str, enum_query_type query_type) override; uint cols() const override { return materialize_engine->cols(); } uint8 uncacheable() override { return materialize_engine->uncacheable(); } table_map upper_select_const_tables() override { return 0; } bool no_rows() override { return !tmp_table->file->stats.records; } enum_engine_type engine_type() override { return HASH_SJ_ENGINE; } /* TODO: factor out all these methods in a base subselect_index_engine class because all of them have dummy implementations and should never be called. */ bool fix_length_and_dec(Item_cache** row) override;//=>base class void exclude() override; //=>base class //=>base class bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE) override; bool no_tables() const override;//=>base class /* Possible execution strategies that can be used to compute hash semi-join.*/ enum exec_strategy { UNDEFINED= 0, COMPLETE_MATCH, /* Use regular index lookups. */ PARTIAL_MATCH, /* Use some partial matching strategy. */ PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */ PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */ SINGLE_COLUMN_MATCH, /* Use simplified matching when there is only one field involved. */ CONST_RETURN_NULL, /* The result of IN predicate is constant NULL */ IMPOSSIBLE /* Subquery materialization is not applicable. */ }; protected: /* The engine used to compute the IN predicate. */ subselect_engine *lookup_engine; /* Keyparts of the only non-NULL composite index in a rowid merge. */ MY_BITMAP non_null_key_parts; /* Keyparts of the single column indexes with NULL, one keypart per index. */ MY_BITMAP partial_match_key_parts; uint count_partial_match_columns; uint count_null_only_columns; uint count_columns_with_nulls; /* The chosen execution strategy. Computed after materialization. */ exec_strategy strategy; exec_strategy get_strategy_using_schema(); exec_strategy get_strategy_using_data(); ulonglong rowid_merge_buff_size(bool has_non_null_key, bool has_covering_null_row, MY_BITMAP *partial_match_key_parts); void choose_partial_match_strategy(uint field_count, bool has_non_null_key, bool has_covering_null_row, MY_BITMAP *partial_match_key_parts); bool make_semi_join_conds(); subselect_uniquesubquery_engine* make_unique_engine(); }; /* Distinguish the type of (0-based) row numbers from the type of the index into an array of row numbers. */ typedef ha_rows rownum_t; /* An Ordered_key is an in-memory table index that allows O(log(N)) time lookups of a multi-part key. If the index is over a single column, then this column may contain NULLs, and the NULLs are stored and tested separately for NULL in O(1) via is_null(). Multi-part indexes assume that the indexed columns do not contain NULLs. TODO: = Due to the unnatural assymetry between single and multi-part indexes, it makes sense to somehow refactor or extend the class. = This class can be refactored into a base abstract interface, and two subclasses: - one to represent single-column indexes, and - another to represent multi-column indexes. Such separation would allow slightly more efficient implementation of the single-column indexes. = The current design requires such indexes to be fully recreated for each PS (re)execution, however most of the comprising objects can be reused. */ class Ordered_key : public Sql_alloc { protected: /* Index of the key in an array of keys. This index allows to construct (sub)sets of keys represented by bitmaps. */ uint keyid; /* The table being indexed. */ TABLE *tbl; /* The columns being indexed. */ Item_field **key_columns; /* Number of elements in 'key_columns' (number of key parts). */ uint key_column_count; /* An expression, or sequence of expressions that forms the search key. The search key is a sequence when it is Item_row. Each element of the sequence is accessible via Item::element_index(int i). */ Item *search_key; /* Value index related members. */ /* The actual value index, consists of a sorted sequence of row numbers. */ rownum_t *key_buff; /* Number of elements in key_buff. */ ha_rows key_buff_elements; /* Current element in 'key_buff'. */ ha_rows cur_key_idx; /* Mapping from row numbers to row ids. The element row_num_to_rowid[i] contains a buffer with the rowid for the row numbered 'i'. The memory for this member is not maintanined by this class because all Ordered_key indexes of the same table share the same mapping. */ uchar *row_num_to_rowid; /* A sequence of predicates to compare the search key with the corresponding columns of a table row from the index. */ Item_func_lt **compare_pred; /* Null index related members. */ MY_BITMAP null_key; /* Count of NULLs per column. */ ha_rows null_count; /* The row number that contains the first NULL in a column. */ rownum_t min_null_row; /* The row number that contains the last NULL in a column. */ rownum_t max_null_row; protected: bool alloc_keys_buffers(); /* Quick sort comparison function that compares two rows of the same table indentfied with their row numbers. */ int cmp_keys_by_row_data(const rownum_t a, const rownum_t b) const; static int cmp_keys_by_row_data_and_rownum(void *key, const void *a, const void *b); int cmp_key_with_search_key(rownum_t row_num); public: Ordered_key(uint keyid_arg, TABLE *tbl_arg, Item *search_key_arg, ha_rows null_count_arg, ha_rows min_null_row_arg, ha_rows max_null_row_arg, uchar *row_num_to_rowid_arg); ~Ordered_key(); void cleanup(); /* Initialize a multi-column index. */ bool init(MY_BITMAP *columns_to_index); /* Initialize a single-column index. */ bool init(int col_idx); uint get_column_count() const { return key_column_count; } uint get_keyid() const { return keyid; } Field *get_field(uint i) const { DBUG_ASSERT(i < key_column_count); return key_columns[i]->field; } rownum_t get_min_null_row() const { return min_null_row; } rownum_t get_max_null_row() const { return max_null_row; } MY_BITMAP * get_null_key() { return &null_key; } ha_rows get_null_count() const { return null_count; } ha_rows get_key_buff_elements() const { return key_buff_elements; } /* Get the search key element that corresponds to the i-th key part of this index. */ Item *get_search_key(uint i) const { return search_key->element_index(key_columns[i]->field->field_index); } void add_key(rownum_t row_num) { /* The caller must know how many elements to add. */ DBUG_ASSERT(key_buff_elements && cur_key_idx < key_buff_elements); key_buff[cur_key_idx]= row_num; ++cur_key_idx; } bool sort_keys(); inline double null_selectivity() const; /* Position the current element at the first row that matches the key. The key itself is propagated by evaluating the current value(s) of this->search_key. */ bool lookup(); /* Move the current index cursor to the first key. */ void first() { DBUG_ASSERT(key_buff_elements); cur_key_idx= 0; } /* TODO */ bool next_same(); /* Move the current index cursor to the next key. */ bool next() { DBUG_ASSERT(key_buff_elements); if (cur_key_idx < key_buff_elements - 1) { ++cur_key_idx; return TRUE; } return FALSE; }; /* Return the current index element. */ rownum_t current() const { DBUG_ASSERT(key_buff_elements && cur_key_idx < key_buff_elements); return key_buff[cur_key_idx]; } void set_null(rownum_t row_num) { bitmap_set_bit(&null_key, (uint)row_num); } bool is_null(rownum_t row_num) const { /* Indexes consisting of only NULLs do not have a bitmap buffer at all. Their only initialized member is 'n_bits', which is equal to the number of temp table rows. */ if (null_count == tbl->file->stats.records) { DBUG_ASSERT(tbl->file->stats.records == null_key.n_bits); return TRUE; } if (row_num > max_null_row || row_num < min_null_row) return FALSE; return bitmap_is_set(&null_key, (uint)row_num); } void print(String *str) const; }; class subselect_partial_match_engine : public subselect_engine { protected: /* The temporary table that contains a materialized subquery. */ TABLE *tmp_table; /* The engine used to check whether an IN predicate is TRUE or not. If not TRUE, then subselect_rowid_merge_engine further distinguishes between FALSE and UNKNOWN. */ subselect_uniquesubquery_engine *lookup_engine; /* A list of equalities between each pair of IN operands. */ List<Item> *equi_join_conds; /* True if there is an all NULL row in tmp_table. If so, then if there is no complete match, there is a guaranteed partial match. */ bool has_covering_null_row; /* True if all nullable columns of tmp_table consist of only NULL values. If so, then if there is a match in the non-null columns, there is a guaranteed partial match. */ bool has_covering_null_columns; uint count_columns_with_nulls; protected: virtual bool partial_match()= 0; public: subselect_partial_match_engine(THD *thd, subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, List<Item> *equi_join_conds_arg, bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg); int prepare(THD *thd_arg) override { set_thd(thd_arg); return 0; } int exec() override; bool fix_length_and_dec(Item_cache**) override { return FALSE; } uint cols() const override { /* TODO: what is the correct value? */ return 1; } uint8 uncacheable() override { return UNCACHEABLE_DEPENDENT; } void exclude() override {} table_map upper_select_const_tables() override { return 0; } bool change_result(Item_subselect*, select_result_interceptor*, bool temp= FALSE) override { DBUG_ASSERT(FALSE); return false; } bool no_tables() const override { return false; } bool no_rows() override { /* TODO: It is completely unclear what is the semantics of this method. The current result is computed so that the call to no_rows() from Item_in_optimizer::val_int() sets Item_in_optimizer::null_value correctly. */ return !(item->get_IN_subquery()->null_value); } void print(String*, enum_query_type) override; friend void subselect_hash_sj_engine::cleanup(); }; class subselect_rowid_merge_engine: public subselect_partial_match_engine { protected: /* Mapping from row numbers to row ids. The rowids are stored sequentially in the array - rowid[i] is located in row_num_to_rowid + i * rowid_length. */ uchar *row_num_to_rowid; /* A subset of all the keys for which there is a match for the same row. Used during execution. Computed for each outer reference */ MY_BITMAP matching_keys; /* The columns of the outer reference that are NULL. Computed for each outer reference. */ MY_BITMAP matching_outer_cols; /* Indexes of row numbers, sorted by <column_value, row_number>. If an index may contain NULLs, the NULLs are stored efficiently in a bitmap. The indexes are sorted by the selectivity of their NULL sub-indexes, the one with the fewer NULLs is first. Thus, if there is any index on non-NULL columns, it is contained in keys[0]. */ Ordered_key **merge_keys; /* The number of elements in merge_keys. */ uint merge_keys_count; /* The NULL bitmaps of merge keys.*/ MY_BITMAP **null_bitmaps; /* An index on all non-NULL columns of 'tmp_table'. The index has the logical form: <[v_i1 | ... | v_ik], rownum>. It allows to find the row number where the columns c_i1,...,c1_k contain the values v_i1,...,v_ik. If such an index exists, it is always the first element of 'merge_keys'. */ Ordered_key *non_null_key; /* Priority queue of Ordered_key indexes, one per NULLable column. This queue is used by the partial match algorithm in method exec(). */ QUEUE pq; protected: /* Comparison function to compare keys in order of decreasing bitmap selectivity. */ static int cmp_keys_by_null_selectivity(const void *k1, const void *k2); /* Comparison function used by the priority queue pq, the 'smaller' key is the one with the smaller current row number. */ static int cmp_keys_by_cur_rownum(void *, const void *k1, const void *k2); bool test_null_row(rownum_t row_num); bool exists_complementing_null_row(MY_BITMAP *keys_to_complement); bool partial_match() override; public: subselect_rowid_merge_engine(THD *thd, subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, uint merge_keys_count_arg, bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, List<Item> *equi_join_conds_arg) :subselect_partial_match_engine(thd, engine_arg, tmp_table_arg, item_arg, result_arg, equi_join_conds_arg, has_covering_null_row_arg, has_covering_null_columns_arg, count_columns_with_nulls_arg), merge_keys_count(merge_keys_count_arg), non_null_key(NULL) {} ~subselect_rowid_merge_engine(); bool init(MY_BITMAP *non_null_key_parts, MY_BITMAP *partial_match_key_parts); void cleanup() override; enum_engine_type engine_type() override { return ROWID_MERGE_ENGINE; } }; class subselect_table_scan_engine: public subselect_partial_match_engine { protected: bool partial_match() override; public: subselect_table_scan_engine(THD *thd, subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, List<Item> *equi_join_conds_arg, bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg); void cleanup() override; enum_engine_type engine_type() override { return TABLE_SCAN_ENGINE; } }; /* An engine to handle NULL-aware Materialization for subqueries that compare one column: col1 IN (SELECT t2.col2 FROM t2 ...) When only one column is used, we need to handle NULL values of col1 and col2 but don't need to perform "partial" matches when only a subset of compared columns is NULL. This allows to save on some data structures. */ class subselect_single_column_match_engine: public subselect_partial_match_engine { protected: bool partial_match() override; public: subselect_single_column_match_engine(THD *thd, subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, List<Item> *equi_join_conds_arg, bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg); void cleanup() override {} enum_engine_type engine_type() override { return SINGLE_COLUMN_ENGINE; } }; /** @brief Subquery materialization tracker @details Used to track various parameters of the materialized subquery execution, such as the execution strategy, sizes of buffers employed, etc */ class Subq_materialization_tracker { public: using Strategy = subselect_hash_sj_engine::exec_strategy; Subq_materialization_tracker(MEM_ROOT *mem_root) : exec_strategy(Strategy::UNDEFINED), partial_match_buffer_size(0), partial_match_array_sizes(mem_root), loops_count(0), index_lookups_count(0), partial_matches_count(0) {} void report_partial_merge_keys(Ordered_key **merge_keys, uint merge_keys_count); void report_exec_strategy(Strategy es) { exec_strategy= es; } void report_partial_match_buffer_size(longlong sz) { partial_match_buffer_size= sz; } void increment_loops_count() { loops_count++; } void increment_index_lookups() { index_lookups_count++; } void increment_partial_matches() { partial_matches_count++; } void print_json_members(Json_writer *writer) const; private: Strategy exec_strategy; ulonglong partial_match_buffer_size; Dynamic_array<ha_rows> partial_match_array_sizes; /* Number of times subquery predicate was evaluated */ ulonglong loops_count; /* Number of times we made a lookup in the materialized temptable (we do this when all parts of left_expr are not NULLs) */ ulonglong index_lookups_count; /* Number of times we had to check for a partial match (either by scanning the materialized subquery or by doing a merge) */ ulonglong partial_matches_count; const char *get_exec_strategy() const { switch (exec_strategy) { case Strategy::UNDEFINED: return "undefined"; case Strategy::COMPLETE_MATCH: return "index_lookup"; case Strategy::PARTIAL_MATCH_MERGE: return "index_lookup;array merge for partial match"; case Strategy::PARTIAL_MATCH_SCAN: return "index_lookup;full scan for partial match"; case Strategy::SINGLE_COLUMN_MATCH: return "null-aware index_lookup"; case Strategy::CONST_RETURN_NULL: return "return NULL"; default: return "unsupported"; } } }; #endif /* ITEM_SUBSELECT_INCLUDED */ wsrep_mutex.h 0000644 00000002327 15156036164 0007312 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_MUTEX_H #define WSREP_MUTEX_H /* wsrep-lib */ #include "wsrep/mutex.hpp" /* implementation */ #include "my_global.h" #include "my_pthread.h" class Wsrep_mutex : public wsrep::mutex { public: Wsrep_mutex(mysql_mutex_t* mutex) : m_mutex(mutex) { } void lock() override { mysql_mutex_lock(m_mutex); } void unlock() override { mysql_mutex_unlock(m_mutex); } void* native() override { return m_mutex; } private: mysql_mutex_t* m_mutex; }; #endif /* WSREP_MUTEX_H */ sql_plugin.h 0000644 00000016631 15156036164 0007110 0 ustar 00 /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. Copyright (c) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _sql_plugin_h #define _sql_plugin_h /* the following #define adds server-only members to enum_mysql_show_type, that is defined in plugin.h */ #define SHOW_always_last SHOW_KEY_CACHE_LONG, \ SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \ SHOW_LONG_NOFLUSH, SHOW_LEX_STRING, SHOW_ATOMIC_COUNTER_UINT32_T, \ /* SHOW_*_STATUS must be at the end, SHOW_LONG_STATUS being first */ \ SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_LONGLONG_STATUS, \ SHOW_UINT32_STATUS, SHOW_MICROSECOND_STATUS, #include "mariadb.h" #undef SHOW_always_last #include "m_string.h" /* LEX_STRING */ #include "my_alloc.h" /* MEM_ROOT */ class sys_var; enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; enum enum_plugin_load_option { PLUGIN_OFF, PLUGIN_ON, PLUGIN_FORCE, PLUGIN_FORCE_PLUS_PERMANENT }; extern const char *global_plugin_typelib_names[]; extern volatile int global_plugin_version; extern ulong dlopen_count; #include <my_sys.h> #include "sql_list.h" #ifdef DBUG_OFF #define plugin_ref_to_int(A) A #define plugin_int_to_ref(A) A #else #define plugin_ref_to_int(A) (A ? A[0] : NULL) #define plugin_int_to_ref(A) &(A) #endif /* the following flags are valid for plugin_init() */ #define PLUGIN_INIT_SKIP_PLUGIN_TABLE 1U #define PLUGIN_INIT_SKIP_INITIALIZATION 2U #define INITIAL_LEX_PLUGIN_LIST_SIZE 16 typedef enum enum_mysql_show_type SHOW_TYPE; typedef struct st_mysql_show_var SHOW_VAR; #define MYSQL_ANY_PLUGIN -1 /* different values of st_plugin_int::state though they look like a bitmap, plugin may only be in one of those eigenstates, not in a superposition of them :) It's a bitmap, because it makes it easier to test "whether the state is one of those..." */ #define PLUGIN_IS_FREED 1U #define PLUGIN_IS_DELETED 2U #define PLUGIN_IS_UNINITIALIZED 4U #define PLUGIN_IS_READY 8U #define PLUGIN_IS_DYING 16U #define PLUGIN_IS_DISABLED 32U struct st_ptr_backup { void **ptr; void *value; void save(void **p) { ptr= p; value= *p; } void save(const char **p) { save((void**)p); } void restore() { *ptr= value; } }; /* A handle for the dynamic library containing a plugin or plugins. */ struct st_plugin_dl { LEX_CSTRING dl; void *handle; struct st_maria_plugin *plugins; st_ptr_backup *ptr_backup; uint nbackups; uint ref_count; /* number of plugins loaded from the library */ int mysqlversion; int mariaversion; bool allocated; }; /* A handle of a plugin */ struct st_plugin_int { LEX_CSTRING name; struct st_maria_plugin *plugin; struct st_plugin_dl *plugin_dl; st_ptr_backup *ptr_backup; uint nbackups; uint state; uint ref_count; /* number of threads using the plugin */ uint locks_total; /* how many times the plugin was locked */ void *data; /* plugin type specific, e.g. handlerton */ MEM_ROOT mem_root; /* memory for dynamic plugin structures */ sys_var *system_vars; /* server variables for this plugin */ enum enum_plugin_load_option load_option; /* OFF, ON, FORCE, F+PERMANENT */ }; extern mysql_mutex_t LOCK_plugin; /* See intern_plugin_lock() for the explanation for the conditionally defined plugin_ref type */ #ifdef DBUG_OFF typedef struct st_plugin_int *plugin_ref; #define plugin_ref_to_int(A) A #define plugin_int_to_ref(A) A #define plugin_decl(pi) ((pi)->plugin) #define plugin_dlib(pi) ((pi)->plugin_dl) #define plugin_data(pi,cast) ((cast)((pi)->data)) #define plugin_name(pi) (&((pi)->name)) #define plugin_state(pi) ((pi)->state) #define plugin_load_option(pi) ((pi)->load_option) #define plugin_equals(p1,p2) ((p1) == (p2)) #else typedef struct st_plugin_int **plugin_ref; #define plugin_ref_to_int(A) (A ? A[0] : NULL) #define plugin_int_to_ref(A) &(A) #define plugin_decl(pi) ((pi)[0]->plugin) #define plugin_dlib(pi) ((pi)[0]->plugin_dl) #define plugin_data(pi,cast) ((cast)((pi)[0]->data)) #define plugin_name(pi) (&((pi)[0]->name)) #define plugin_state(pi) ((pi)[0]->state) #define plugin_load_option(pi) ((pi)[0]->load_option) #define plugin_equals(p1,p2) ((p1) && (p2) && (p1)[0] == (p2)[0]) #endif typedef int (*plugin_type_init)(void *); extern I_List<i_string> *opt_plugin_load_list_ptr; extern char *opt_plugin_dir_ptr; extern MYSQL_PLUGIN_IMPORT char opt_plugin_dir[FN_REFLEN]; extern const LEX_CSTRING plugin_type_names[]; extern ulong plugin_maturity; extern TYPELIB plugin_maturity_values; extern const char *plugin_maturity_names[]; extern int plugin_init(int *argc, char **argv, int init_flags); extern void plugin_shutdown(void); void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root); extern bool plugin_is_ready(const LEX_CSTRING *name, int type); #define my_plugin_lock_by_name(A,B,C) plugin_lock_by_name(A,B,C) #define my_plugin_lock(A,B) plugin_lock(A,B) extern plugin_ref plugin_lock(THD *thd, plugin_ref ptr); extern plugin_ref plugin_lock_by_name(THD *thd, const LEX_CSTRING *name, int type); extern void plugin_unlock(THD *thd, plugin_ref plugin); extern void plugin_unlock_list(THD *thd, plugin_ref *list, size_t count); extern bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, const LEX_CSTRING *dl); extern bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, const LEX_CSTRING *dl); extern bool plugin_register_builtin(struct st_mysql_plugin *plugin); extern void plugin_thdvar_init(THD *thd); extern void plugin_thdvar_cleanup(THD *thd); sys_var *find_plugin_sysvar(st_plugin_int *plugin, st_mysql_sys_var *var); void plugin_opt_set_limits(struct my_option *, const struct st_mysql_sys_var *); extern SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type); extern bool check_valid_path(const char *path, size_t length); extern void plugin_mutex_init(); typedef my_bool (plugin_foreach_func)(THD *thd, plugin_ref plugin, void *arg); #define plugin_foreach(A,B,C,D) plugin_foreach_with_mask(A,B,C,PLUGIN_IS_READY,D) extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg); extern void sync_dynamic_session_variables(THD* thd, bool global_lock); extern bool plugin_dl_foreach(THD *thd, const LEX_CSTRING *dl, plugin_foreach_func *func, void *arg); extern void sync_dynamic_session_variables(THD* thd, bool global_lock); #endif #ifdef WITH_WSREP extern void wsrep_plugins_pre_init(); extern void wsrep_plugins_post_init(); #endif /* WITH_WSREP */ assume_aligned.h 0000644 00000004456 15156036164 0007715 0 ustar 00 /* Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #include <cassert> #include <cstring> #ifdef _MSC_VER template <std::size_t Alignment, class T> static inline T my_assume_aligned(T ptr) { assert(reinterpret_cast<size_t>(ptr) % Alignment == 0); __assume(reinterpret_cast<size_t>(ptr) % Alignment == 0); return ptr; } #else template <std::size_t Alignment, class T> static inline T my_assume_aligned(T ptr) { assert(reinterpret_cast<size_t>(ptr) % Alignment == 0); return static_cast<T>(__builtin_assume_aligned(ptr, Alignment)); } #endif template <std::size_t Alignment> inline void *memcpy_aligned(void *dest, const void *src, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); return std::memcpy(my_assume_aligned<Alignment>(dest), my_assume_aligned<Alignment>(src), n); } template <std::size_t Alignment> inline void *memmove_aligned(void *dest, const void *src, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); return std::memmove(my_assume_aligned<Alignment>(dest), my_assume_aligned<Alignment>(src), n); } template <std::size_t Alignment> inline int memcmp_aligned(const void *s1, const void *s2, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); return std::memcmp(my_assume_aligned<Alignment>(s1), my_assume_aligned<Alignment>(s2), n); } template <std::size_t Alignment> inline void *memset_aligned(void *s, int c, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); return std::memset(my_assume_aligned<Alignment>(s), c, n); } hash.h 0000644 00000010544 15156036164 0005653 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. Copyright (c) 2011, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Dynamic hashing of record with different key-length */ #ifndef _hash_h #define _hash_h #include "my_sys.h" /* DYNAMIC_ARRAY */ /* This forward declaration is used from C files where the real definition is included before. Since C does not allow repeated typedef declarations, even when identical, the definition may not be repeated. */ #ifdef __cplusplus extern "C" { #endif /* Overhead to store an element in hash Can be used to approximate memory consumption for a hash */ #define HASH_OVERHEAD (sizeof(char*)*2) /* flags for hash_init */ #define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ #define HASH_THREAD_SPECIFIC 2 /* Mark allocated memory THREAD_SPECIFIC */ typedef uint32 my_hash_value_type; typedef const uchar *(*my_hash_get_key)(const void *, size_t *, my_bool); typedef my_hash_value_type (*my_hash_function)(CHARSET_INFO *, const uchar *, size_t); typedef void (*my_hash_free_key)(void *); typedef my_bool (*my_hash_walk_action)(void *,void *); typedef struct st_hash { size_t key_offset,key_length; /* Length of key if const length */ size_t blength; ulong records; uint flags; DYNAMIC_ARRAY array; /* Place for hash_keys */ my_hash_get_key get_key; my_hash_function hash_function; void (*free)(void *); CHARSET_INFO *charset; } HASH; /* A search iterator state */ typedef uint HASH_SEARCH_STATE; #define my_hash_init(A,B,C,D,E,F,G,H,I) my_hash_init2(A,B,0,C,D,E,F,G,0,H,I) my_bool my_hash_init2(PSI_memory_key psi_key, HASH *hash, size_t growth_size, CHARSET_INFO *charset, size_t default_array_elements, size_t key_offset, size_t key_length, my_hash_get_key get_key, my_hash_function hash_function, void (*free_element)(void*), uint flags); void my_hash_free(HASH *tree); void my_hash_reset(HASH *hash); uchar *my_hash_element(HASH *hash, size_t idx); uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); uchar *my_hash_search_using_hash_value(const HASH *info, my_hash_value_type hash_value, const uchar *key, size_t length); my_hash_value_type my_hash_sort(CHARSET_INFO *cs, const uchar *key, size_t length); #define my_calc_hash(A, B, C) my_hash_sort((A)->charset, B, C) uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); uchar *my_hash_first_from_hash_value(const HASH *info, my_hash_value_type hash_value, const uchar *key, size_t length, HASH_SEARCH_STATE *state); uchar *my_hash_next(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info, const uchar *data); my_bool my_hash_delete(HASH *hash, uchar *record); my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, size_t old_key_length); void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row); my_bool my_hash_check(HASH *hash); /* Only in debug library */ my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument); #define my_hash_clear(H) bzero((char*) (H), sizeof(*(H))) #define my_hash_inited(H) ((H)->blength != 0) #define my_hash_init_opt(A,B,C,D,E,F,G,H,I) \ (!my_hash_inited(B) && my_hash_init(A,B,C,D,E,F,G,H,I)) #ifdef __cplusplus } #endif #endif repl_failsafe.h 0000644 00000003061 15156036164 0007520 0 ustar 00 #ifndef REPL_FAILSAFE_INCLUDED #define REPL_FAILSAFE_INCLUDED /* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef HAVE_REPLICATION #include "mysql.h" #include <my_sys.h> #include "slave.h" extern Atomic_counter<uint32_t> binlog_dump_thread_count; typedef enum {RPL_AUTH_MASTER=0,RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE, RPL_LOST_SOLDIER,RPL_TROOP_SOLDIER, RPL_RECOVERY_CAPTAIN,RPL_NULL /* inactive */, RPL_ANY /* wild card used by change_rpl_status */ } RPL_STATUS; extern ulong rpl_status; extern mysql_mutex_t LOCK_rpl_status; extern mysql_cond_t COND_rpl_status; extern TYPELIB rpl_role_typelib; extern const char* rpl_role_type[], *rpl_status_type[]; void change_rpl_status(ulong from_status, ulong to_status); int find_recovery_captain(THD* thd, MYSQL* mysql); bool show_slave_hosts(THD* thd); #endif /* HAVE_REPLICATION */ #endif /* REPL_FAILSAFE_INCLUDED */ sql_limit.h 0000644 00000006163 15156036165 0006730 0 ustar 00 /* Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef INCLUDES_MARIADB_SQL_LIMIT_H #define INCLUDES_MARIADB_SQL_LIMIT_H /** LIMIT/OFFSET parameters for execution. */ class Select_limit_counters { ha_rows select_limit_cnt, offset_limit_cnt; bool with_ties; public: Select_limit_counters(): select_limit_cnt(0), offset_limit_cnt(0), with_ties(false) {}; Select_limit_counters(const Select_limit_counters &orig): select_limit_cnt(orig.select_limit_cnt), offset_limit_cnt(orig.offset_limit_cnt), with_ties(orig.with_ties) {}; void set_limit(ha_rows limit, ha_rows offset, bool with_ties_arg) { if (limit == 0) offset= 0; offset_limit_cnt= offset; select_limit_cnt= limit; with_ties= with_ties_arg; /* Guard against an overflow condition, where limit + offset exceede ha_rows value range. This case covers unreasonably large parameter values that do not have any practical use so assuming in this case that the query does not have a limit is fine. */ if (select_limit_cnt + offset_limit_cnt >= select_limit_cnt) select_limit_cnt+= offset_limit_cnt; else select_limit_cnt= HA_POS_ERROR; } void set_single_row() { offset_limit_cnt= 0; select_limit_cnt= 1; with_ties= false; } /* Send the first row, still honoring offset_limit_cnt */ void send_first_row() { /* Guard against overflow */ if ((select_limit_cnt= offset_limit_cnt +1 ) == 0) select_limit_cnt= offset_limit_cnt; // with_ties= false; Remove // on merge to 10.6 } bool is_unlimited() const { return select_limit_cnt == HA_POS_ERROR; } /* Set the limit to allow returning an unlimited number of rows. Useful for cases when we want to continue execution indefinitely after the limit is reached (for example for SQL_CALC_ROWS extension). */ void set_unlimited() { select_limit_cnt= HA_POS_ERROR; } /* Reset the limit entirely. */ void clear() { select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; with_ties= false;} bool check_offset(ha_rows sent) const { return sent < offset_limit_cnt; } void remove_offset() { offset_limit_cnt= 0; } ha_rows get_select_limit() const { return select_limit_cnt; } ha_rows get_offset_limit() const { return offset_limit_cnt; } bool is_with_ties() const { return with_ties; } }; #endif // INCLUDES_MARIADB_SQL_LIMIT_H ha_sequence.h 0000644 00000014145 15156036165 0007212 0 ustar 00 #ifndef HA_SEQUENCE_INCLUDED #define HA_SEQUENCE_INCLUDED /* Copyright (c) 2017 Aliyun and/or its affiliates. Copyright (c) 2017 MariaDB corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "sql_sequence.h" #include "table.h" #include "handler.h" extern handlerton *sql_sequence_hton; /* Sequence engine handler. The sequence engine is a logic engine. It doesn't store any data. All the sequence data stored into the base table which must support non rollback writes (HA_CAN_TABLES_WITHOUT_ROLLBACK) The sequence data (SEQUENCE class) is stored in TABLE_SHARE->sequence TABLE RULES: 1. When table is created, one row is automaticlly inserted into the table. The table will always have one and only one row. 2. Any inserts or updates to the table will be validated. 3. Inserts will overwrite the original row. 4. DELETE and TRUNCATE will not affect the table. Instead a warning will be given. 5. Cache will be reset for any updates. CACHE RULES: SEQUENCE class is used to cache values that sequence defined. 1. If hit cache, we can query back the sequence nextval directly instead of reading the underlying table. 2. When run out of values, the sequence engine will reserve new values in update the base table. 3. The cache is invalidated if any update on based table. */ class ha_sequence :public handler { private: handler *file; SEQUENCE *sequence; /* From table_share->sequence */ public: /* Set when handler is write locked */ bool write_locked; ha_sequence(handlerton *hton, TABLE_SHARE *share); ~ha_sequence(); virtual handlerton *storage_ht() const override { return file->ht; } /* virtual function that are re-implemented for sequence */ int open(const char *name, int mode, uint test_if_locked) override; int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info) override; handler *clone(const char *name, MEM_ROOT *mem_root) override; int write_row(const uchar *buf) override; Table_flags table_flags() const override; /* One can't update or delete from sequence engine */ int update_row(const uchar *old_data, const uchar *new_data) override { return HA_ERR_WRONG_COMMAND; } int delete_row(const uchar *buf) override { return HA_ERR_WRONG_COMMAND; } /* One can't delete from sequence engine */ int truncate() override { return HA_ERR_WRONG_COMMAND; } /* Can't use query cache */ uint8 table_cache_type() override { return HA_CACHE_TBL_NOCACHE; } void print_error(int error, myf errflag) override; int info(uint) override; LEX_CSTRING *engine_name() override { return hton_name(file->ht); } int external_lock(THD *thd, int lock_type) override; int extra(enum ha_extra_function operation) override; /* For ALTER ONLINE TABLE */ bool check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) override; enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ai) override; void write_lock() { write_locked= 1;} void unlock() { write_locked= 0; } bool is_locked() { return write_locked; } /* Functions that are directly mapped to the underlying handler */ int rnd_init(bool scan) override { return file->rnd_init(scan); } /* We need to have a lock here to protect engines like MyISAM from simultaneous read and write. For sequence's this is not critical as this function is used extremely seldom. */ int rnd_next(uchar *buf) override { int error; table->s->sequence->read_lock(table); error= file->rnd_next(buf); table->s->sequence->read_unlock(table); return error; } int rnd_end() override { return file->rnd_end(); } int rnd_pos(uchar *buf, uchar *pos) override { int error; table->s->sequence->read_lock(table); error= file->rnd_pos(buf, pos); table->s->sequence->read_unlock(table); return error; } void position(const uchar *record) override { return file->position(record); } const char *table_type() const override { return file->table_type(); } ulong index_flags(uint inx, uint part, bool all_parts) const override { return file->index_flags(inx, part, all_parts); } THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) override { return file->store_lock(thd, to, lock_type); } int close(void) override { return file->close(); } const char **bas_ext() const { return file->bas_ext(); } int delete_table(const char*name) override { return file->delete_table(name); } int rename_table(const char *from, const char *to) override { return file->rename_table(from, to); } void unbind_psi() override { file->unbind_psi(); } void rebind_psi() override { file->rebind_psi(); } int discard_or_import_tablespace(my_bool discard) override; bool auto_repair(int error) const override { return file->auto_repair(error); } int repair(THD* thd, HA_CHECK_OPT* check_opt) override { return file->repair(thd, check_opt); } bool check_and_repair(THD *thd) override { return file->check_and_repair(thd); } bool is_crashed() const override { return file->is_crashed(); } void column_bitmaps_signal() override { return file->column_bitmaps_signal(); } /* New methods */ void register_original_handler(handler *file_arg) { file= file_arg; init(); /* Update cached_table_flags */ } }; #endif my_time.h 0000644 00000024256 15156036165 0006401 0 ustar 00 /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. Copyright (c) 2017, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This is a private header of sql-common library, containing declarations for my_time.c */ #ifndef _my_time_h_ #define _my_time_h_ #include "mysql_time.h" #include "my_decimal_limits.h" C_MODE_START extern MYSQL_PLUGIN_IMPORT ulonglong log_10_int[20]; extern uchar days_in_month[]; #define MY_TIME_T_MAX LONG_MAX #define MY_TIME_T_MIN LONG_MIN /* Time handling defaults */ #define TIMESTAMP_MAX_YEAR 2038 #define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) #define TIMESTAMP_MAX_VALUE INT_MAX32 #define TIMESTAMP_MIN_VALUE 0 /* two-digit years < this are 20..; >= this are 19.. */ #define YY_PART_YEAR 70 /* check for valid times only if the range of time_t is greater than the range of my_time_t */ #if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED) # define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ ((x) <= TIMESTAMP_MAX_VALUE && \ (x) >= TIMESTAMP_MIN_VALUE) #else # define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ ((x) >= TIMESTAMP_MIN_VALUE) #endif /* Flags to str_to_datetime */ #define C_TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ #define C_TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ #define C_TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ #define MYSQL_TIME_WARN_TRUNCATED 1U #define MYSQL_TIME_WARN_OUT_OF_RANGE 2U #define MYSQL_TIME_WARN_EDOM 4U #define MYSQL_TIME_WARN_ZERO_DATE 8U #define MYSQL_TIME_NOTE_TRUNCATED 16U #define MYSQL_TIME_WARN_WARNINGS (MYSQL_TIME_WARN_TRUNCATED|\ MYSQL_TIME_WARN_OUT_OF_RANGE|\ MYSQL_TIME_WARN_EDOM|\ MYSQL_TIME_WARN_ZERO_DATE) #define MYSQL_TIME_WARN_NOTES (MYSQL_TIME_NOTE_TRUNCATED) #define MYSQL_TIME_WARN_HAVE_WARNINGS(x) MY_TEST((x) & MYSQL_TIME_WARN_WARNINGS) #define MYSQL_TIME_WARN_HAVE_NOTES(x) MY_TEST((x) & MYSQL_TIME_WARN_NOTES) /* Useful constants */ #define SECONDS_IN_24H 86400L /* Limits for the INTERVAL data type */ /* Number of hours between '0001-01-01 00h' and '9999-12-31 23h' */ #define TIME_MAX_INTERVAL_HOUR 87649415 #define TIME_MAX_INTERVAL_HOUR_CHAR_LENGTH 8 /* Number of full days between '0001-01-01' and '9999-12-31'*/ #define TIME_MAX_INTERVAL_DAY 3652058 /*87649415/24*/ #define TIME_MAX_INTERVAL_DAY_CHAR_LENGTH 7 /* Limits for the TIME data type */ #define TIME_MAX_HOUR 838 #define TIME_MAX_MINUTE 59 #define TIME_MAX_SECOND 59 #define TIME_MAX_SECOND_PART 999999 #define TIME_SECOND_PART_FACTOR (TIME_MAX_SECOND_PART+1) #define TIME_SECOND_PART_DIGITS 6 #define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND) #define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \ TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND) /* Structure to return status from str_to_datetime(), str_to_time(). */ typedef struct st_mysql_time_status { int warnings; uint precision; uint nanoseconds; } MYSQL_TIME_STATUS; static inline void my_time_status_init(MYSQL_TIME_STATUS *status) { status->warnings= 0; status->precision= 0; status->nanoseconds= 0; } my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, ulonglong flags, int *was_cut); my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time, ulong max_hour, MYSQL_TIME_STATUS *status); my_bool str_to_datetime_or_date_or_time(const char *str, size_t length, MYSQL_TIME *to, ulonglong flag, MYSQL_TIME_STATUS *status, ulong time_max_hour, ulong time_err_hour); my_bool str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length, MYSQL_TIME *to, ulonglong flag, MYSQL_TIME_STATUS *status, ulong time_max_hour, ulong time_err_hour); my_bool str_to_datetime_or_date_or_interval_day(const char *str, size_t length, MYSQL_TIME *to, ulonglong flag, MYSQL_TIME_STATUS *status, ulong time_max_hour, ulong time_err_hour); my_bool str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *to, ulonglong flags, MYSQL_TIME_STATUS *status); longlong number_to_datetime_or_date(longlong nr, ulong sec_part, MYSQL_TIME *time_res, ulonglong flags, int *was_cut); int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part, ulong max_hour, MYSQL_TIME *to, int *was_cut); ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *); ulonglong TIME_to_ulonglong(const MYSQL_TIME *); double TIME_to_double(const MYSQL_TIME *my_time); int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning); my_bool check_datetime_range(const MYSQL_TIME *ltime); long calc_daynr(uint year,uint month,uint day); uint calc_days_in_year(uint year); uint year_2000_handling(uint year); void my_init_time(void); /* Function to check sanity of a TIMESTAMP value DESCRIPTION Check if a given MYSQL_TIME value fits in TIMESTAMP range. This function doesn't make precise check, but rather a rough estimate. RETURN VALUES TRUE The value seems sane FALSE The MYSQL_TIME value is definitely out of range */ static inline my_bool validate_timestamp_range(const MYSQL_TIME *t) { if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) return FALSE; return TRUE; } /* Can't include mysqld_error.h, it needs mysys to build, thus hardcode 2 error values here. */ #ifndef ER_WARN_DATA_OUT_OF_RANGE #define ER_WARN_DATA_OUT_OF_RANGE 1264 #define ER_WARN_INVALID_TIMESTAMP 1299 #endif my_time_t my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, uint *error_code); void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type); /* Required buffer length for my_time_to_str, my_date_to_str, my_datetime_to_str and TIME_to_string functions. Note, that the caller is still responsible to check that given TIME structure has values in valid ranges, otherwise size of the buffer could be not enough. We also rely on the fact that even wrong values sent using binary protocol fit in this buffer. */ #define MAX_DATE_STRING_REP_LENGTH 30 #define AUTO_SEC_PART_DIGITS DECIMAL_NOT_SPECIFIED int my_interval_DDhhmmssff_to_str(const MYSQL_TIME *, char *to, uint digits); int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits); int my_date_to_str(const MYSQL_TIME *l_time, char *to); int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits); int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits); int my_timeval_to_str(const struct timeval *tm, char *to, uint dec); static inline longlong sec_part_shift(longlong second_part, uint digits) { return second_part / (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits]; } static inline longlong sec_part_unshift(longlong second_part, uint digits) { return second_part * (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits]; } /* Date/time rounding and truncation functions */ static inline long my_time_fraction_remainder(long nr, uint decimals) { return nr % (long) log_10_int[TIME_SECOND_PART_DIGITS - decimals]; } static inline void my_datetime_trunc(MYSQL_TIME *ltime, uint decimals) { ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); } static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals) { ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); if (!ltime->second_part && ltime->neg && !ltime->hour && !ltime->minute && !ltime->second) ltime->neg= FALSE; } #ifdef _WIN32 #define suseconds_t long #endif static inline void my_timeval_trunc(struct timeval *tv, uint decimals) { tv->tv_usec-= (suseconds_t) my_time_fraction_remainder(tv->tv_usec, decimals); } #define hrtime_to_my_time(X) ((my_time_t)hrtime_to_time(X)) /* Available interval types used in any statement. 'interval_type' must be sorted so that simple intervals comes first, ie year, quarter, month, week, day, hour, etc. The order based on interval size is also important and the intervals should be kept in a large to smaller order. (get_interval_value() depends on this) Note: If you change the order of elements in this enum you should fix order of elements in 'interval_type_to_name' and 'interval_names' arrays See also interval_type_to_name, get_interval_value, interval_names, append_interval */ enum interval_type { INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST }; C_MODE_END #endif /* _my_time_h_ */ wsrep_mysqld.h 0000644 00000052024 15156036165 0007461 0 ustar 00 /* Copyright 2008-2025 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef WSREP_MYSQLD_H #define WSREP_MYSQLD_H #include <wsrep.h> #ifdef WITH_WSREP #include <mysql/plugin.h> #include "mysql/service_wsrep.h" #include <my_global.h> #include <my_pthread.h> #include "log.h" #include "mysqld.h" typedef struct st_mysql_show_var SHOW_VAR; #include <sql_priv.h> #include "mdl.h" #include "sql_table.h" #include "wsrep_mysqld_c.h" #include "wsrep/provider.hpp" #include "wsrep/streaming_context.hpp" #include "wsrep_api.h" #include <map> #define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX class THD; // Global wsrep parameters // MySQL wsrep options extern const char* wsrep_provider; extern const char* wsrep_provider_options; extern const char* wsrep_cluster_name; extern const char* wsrep_cluster_address; extern const char* wsrep_node_name; extern const char* wsrep_node_address; extern const char* wsrep_node_incoming_address; extern const char* wsrep_data_home_dir; extern const char* wsrep_dbug_option; extern long wsrep_slave_threads; extern int wsrep_slave_count_change; extern ulong wsrep_debug; extern my_bool wsrep_convert_LOCK_to_trx; extern ulong wsrep_retry_autocommit; extern my_bool wsrep_auto_increment_control; extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_incremental_data_collection; extern const char* wsrep_start_position; extern ulong wsrep_max_ws_size; extern ulong wsrep_max_ws_rows; extern const char* wsrep_notify_cmd; extern const char* wsrep_status_file; extern const char* wsrep_allowlist; extern my_bool wsrep_certify_nonPK; extern long int wsrep_protocol_version; extern my_bool wsrep_desync; extern ulong wsrep_reject_queries; extern my_bool wsrep_recovery; extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; extern my_bool wsrep_load_data_splitting; extern my_bool wsrep_restart_slave; extern my_bool wsrep_restart_slave_activated; extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; extern ulong wsrep_trx_fragment_unit; extern ulong wsrep_SR_store_type; extern uint wsrep_ignore_apply_errors; extern ulong wsrep_running_threads; extern ulong wsrep_running_applier_threads; extern ulong wsrep_running_rollbacker_threads; extern bool wsrep_new_cluster; extern bool wsrep_gtid_mode; extern uint32 wsrep_gtid_domain_id; extern std::atomic <bool > wsrep_thread_create_failed; extern ulonglong wsrep_mode; enum enum_wsrep_reject_types { WSREP_REJECT_NONE, /* nothing rejected */ WSREP_REJECT_ALL, /* reject all queries, with UNKNOWN_COMMAND error */ WSREP_REJECT_ALL_KILL /* kill existing connections and reject all queries*/ }; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU, WSREP_OSU_NONE, }; enum enum_wsrep_sync_wait { WSREP_SYNC_WAIT_NONE= 0x0, // select, begin WSREP_SYNC_WAIT_BEFORE_READ= 0x1, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE= 0x2, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE= 0x4, WSREP_SYNC_WAIT_BEFORE_SHOW= 0x8, WSREP_SYNC_WAIT_MAX= 0xF }; enum enum_wsrep_ignore_apply_error { WSREP_IGNORE_ERRORS_NONE= 0x0, WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL= 0x1, WSREP_IGNORE_ERRORS_ON_RECONCILING_DML= 0x2, WSREP_IGNORE_ERRORS_ON_DDL= 0x4, WSREP_IGNORE_ERRORS_MAX= 0x7 }; /* wsrep_mode features */ enum enum_wsrep_mode { WSREP_MODE_STRICT_REPLICATION= (1ULL << 0), WSREP_MODE_BINLOG_ROW_FORMAT_ONLY= (1ULL << 1), WSREP_MODE_REQUIRED_PRIMARY_KEY= (1ULL << 2), WSREP_MODE_REPLICATE_MYISAM= (1ULL << 3), WSREP_MODE_REPLICATE_ARIA= (1ULL << 4), WSREP_MODE_DISALLOW_LOCAL_GTID= (1ULL << 5), WSREP_MODE_BF_MARIABACKUP= (1ULL << 6) }; // Streaming Replication #define WSREP_FRAG_BYTES 0 #define WSREP_FRAG_ROWS 1 #define WSREP_FRAG_STATEMENTS 2 #define WSREP_SR_STORE_NONE 0 #define WSREP_SR_STORE_TABLE 1 extern const char *wsrep_fragment_units[]; extern const char *wsrep_SR_store_types[]; // MySQL status variables extern my_bool wsrep_connected; extern const char* wsrep_cluster_state_uuid; extern long long wsrep_cluster_conf_id; extern const char* wsrep_cluster_status; extern long wsrep_cluster_size; extern long wsrep_local_index; extern long long wsrep_local_bf_aborts; extern const char* wsrep_provider_name; extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; extern char* wsrep_provider_capabilities; extern char* wsrep_cluster_capabilities; int wsrep_show_status(THD *thd, SHOW_VAR *var, void *buff, system_status_var *status_var, enum_var_type scope); int wsrep_show_ready(THD *thd, SHOW_VAR *var, void *buff, system_status_var *, enum_var_type); void wsrep_free_status(THD *thd); void wsrep_update_cluster_state_uuid(const char* str); /* Filters out --wsrep-new-cluster oprtion from argv[] * should be called in the very beginning of main() */ void wsrep_filter_new_cluster (int* argc, char* argv[]); int wsrep_init(); void wsrep_deinit(bool free_options); /* Initialize wsrep thread LOCKs and CONDs */ void wsrep_thr_init(); /* Destroy wsrep thread LOCKs and CONDs */ void wsrep_thr_deinit(); void wsrep_recover(); bool wsrep_before_SE(); // initialize wsrep before storage // engines (true) or after (false) /* wsrep initialization sequence at startup * @param before wsrep_before_SE() value */ void wsrep_init_startup(bool before); /* Recover streaming transactions from fragment storage */ void wsrep_recover_sr_from_storage(THD *); // Other wsrep global variables extern my_bool wsrep_inited; // whether wsrep is initialized ? extern bool wsrep_service_started; extern "C" void wsrep_fire_rollbacker(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); extern "C" time_t wsrep_thd_query_start(THD *thd); extern void wsrep_close_client_connections(my_bool wait_to_end, THD *except_caller_thd= NULL); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); extern int wsrep_wait_committing_connections_close(int wait_time); extern void wsrep_close_applier(THD *thd); extern void wsrep_wait_appliers_close(THD *thd); extern void wsrep_close_applier_threads(int count); /* new defines */ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(const char *wsrep_cluster_address); extern void wsrep_shutdown_replication(); extern bool wsrep_check_mode (enum_wsrep_mode mask); extern bool wsrep_check_mode_after_open_table (THD *thd, const handlerton *hton, TABLE_LIST *tables); extern bool wsrep_check_mode_before_cmd_execute (THD *thd); extern bool wsrep_must_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait (THD* thd, enum enum_sql_command command); extern enum wsrep::provider::status wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout); extern int wsrep_check_opts(); extern void wsrep_prepend_PATH (const char* path); extern bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys); extern bool wsrep_reload_ssl(); extern bool wsrep_split_allowlist(std::vector<std::string>& allowlist); /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; /* A wrapper function for MySQL log functions. The call will prefix the log message with WSREP and forward the result buffer to fun. */ void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...); #define WSREP_SYNC_WAIT(thd_, before_) \ { if (WSREP_CLIENT(thd_) && \ wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } #define WSREP_MYSQL_DB (char *)"mysql" #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \ goto wsrep_error_label; #define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \ if (WSREP_ON && WSREP(thd) && \ wsrep_to_isolation_begin(thd, db_, table_, \ table_list_, nullptr, nullptr, create_info_))\ goto wsrep_error_label; #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_, create_info_) \ if (WSREP(thd) && wsrep_thd_is_local(thd) && \ wsrep_to_isolation_begin(thd, db_, table_, \ table_list_, alter_info_, fk_tables_, create_info_)) #define WSREP_TO_ISOLATION_END \ if ((WSREP(thd) && wsrep_thd_is_local_toi(thd)) || \ wsrep_thd_is_in_rsu(thd)) \ wsrep_to_isolation_end(thd); /* Checks if lex->no_write_to_binlog is set for statements that use LOCAL or NO_WRITE_TO_BINLOG. */ #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) \ if (WSREP(thd) && !thd->lex->no_write_to_binlog \ && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \ goto wsrep_error_label; #define WSREP_PROVIDER_EXISTS (WSREP_PROVIDER_EXISTS_) static inline bool wsrep_cluster_address_exists() { if (mysqld_server_started) mysql_mutex_assert_owner(&LOCK_global_system_variables); return wsrep_cluster_address && wsrep_cluster_address[0]; } extern my_bool wsrep_ready_get(); extern void wsrep_ready_wait(); extern mysql_mutex_t LOCK_wsrep_ready; extern mysql_cond_t COND_wsrep_ready; extern mysql_mutex_t LOCK_wsrep_sst; extern mysql_cond_t COND_wsrep_sst; extern mysql_mutex_t LOCK_wsrep_sst_init; extern mysql_cond_t COND_wsrep_sst_init; extern int wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_replaying; extern mysql_cond_t COND_wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_slave_threads; extern mysql_cond_t COND_wsrep_slave_threads; extern mysql_mutex_t LOCK_wsrep_gtid_wait_upto; extern mysql_mutex_t LOCK_wsrep_cluster_config; extern mysql_mutex_t LOCK_wsrep_desync; extern mysql_mutex_t LOCK_wsrep_SR_pool; extern mysql_mutex_t LOCK_wsrep_SR_store; extern mysql_mutex_t LOCK_wsrep_config_state; extern mysql_mutex_t LOCK_wsrep_group_commit; extern mysql_mutex_t LOCK_wsrep_joiner_monitor; extern mysql_mutex_t LOCK_wsrep_donor_monitor; extern mysql_cond_t COND_wsrep_joiner_monitor; extern mysql_cond_t COND_wsrep_donor_monitor; extern int wsrep_to_isolation; #ifdef GTID_SUPPORT extern rpl_sidno wsrep_sidno; #endif /* GTID_SUPPORT */ extern my_bool wsrep_preordered_opt; #ifdef HAVE_PSI_INTERFACE extern PSI_cond_key key_COND_wsrep_thd; extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready; extern PSI_mutex_key key_LOCK_wsrep_sst; extern PSI_cond_key key_COND_wsrep_sst; extern PSI_mutex_key key_LOCK_wsrep_sst_init; extern PSI_cond_key key_COND_wsrep_sst_init; extern PSI_mutex_key key_LOCK_wsrep_sst_thread; extern PSI_cond_key key_COND_wsrep_sst_thread; extern PSI_mutex_key key_LOCK_wsrep_replaying; extern PSI_cond_key key_COND_wsrep_replaying; extern PSI_mutex_key key_LOCK_wsrep_slave_threads; extern PSI_cond_key key_COND_wsrep_slave_threads; extern PSI_mutex_key key_LOCK_wsrep_gtid_wait_upto; extern PSI_cond_key key_COND_wsrep_gtid_wait_upto; extern PSI_mutex_key key_LOCK_wsrep_cluster_config; extern PSI_mutex_key key_LOCK_wsrep_desync; extern PSI_mutex_key key_LOCK_wsrep_SR_pool; extern PSI_mutex_key key_LOCK_wsrep_SR_store; extern PSI_mutex_key key_LOCK_wsrep_global_seqno; extern PSI_mutex_key key_LOCK_wsrep_thd_queue; extern PSI_cond_key key_COND_wsrep_thd_queue; extern PSI_mutex_key key_LOCK_wsrep_joiner_monitor; extern PSI_mutex_key key_LOCK_wsrep_donor_monitor; extern PSI_file_key key_file_wsrep_gra_log; extern PSI_thread_key key_wsrep_sst_joiner; extern PSI_thread_key key_wsrep_sst_donor; extern PSI_thread_key key_wsrep_rollbacker; extern PSI_thread_key key_wsrep_applier; extern PSI_thread_key key_wsrep_sst_joiner_monitor; extern PSI_thread_key key_wsrep_sst_donor_monitor; #endif /* HAVE_PSI_INTERFACE */ struct TABLE_LIST; class Alter_info; int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list, const Alter_info* alter_info= nullptr, const wsrep::key_array *fk_tables= nullptr, const HA_CREATE_INFO* create_info= nullptr); bool wsrep_should_replicate_ddl(THD* thd, const handlerton *hton); bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list); void wsrep_to_isolation_end(THD *thd); bool wsrep_append_SR_keys(THD *thd); int wsrep_to_buf_helper( THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len); int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len); void wsrep_init_sidno(const wsrep_uuid_t&); bool wsrep_node_is_donor(); bool wsrep_node_is_synced(); void wsrep_init_SR(); void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno); int wsrep_replay_from_SR_store(THD*, const wsrep_trx_meta_t&); class Log_event; int wsrep_ignored_error_code(Log_event* ev, int error); int wsrep_must_ignore_error(THD* thd); struct wsrep_server_gtid_t { uint32 domain_id; uint32 server_id; uint64 seqno; }; class Wsrep_gtid_server { public: uint32 domain_id; uint32 server_id; Wsrep_gtid_server() : m_force_signal(false) , m_seqno(0) , m_committed_seqno(0) { } void gtid(const wsrep_server_gtid_t& gtid) { domain_id= gtid.domain_id; server_id= gtid.server_id; m_seqno= gtid.seqno; } wsrep_server_gtid_t gtid() { wsrep_server_gtid_t gtid; gtid.domain_id= domain_id; gtid.server_id= server_id; gtid.seqno= m_seqno; return gtid; } void seqno(const uint64 seqno) { m_seqno= seqno; } uint64 seqno() const { return m_seqno; } uint64 seqno_committed() const { return m_committed_seqno; } uint64 seqno_inc() { m_seqno++; return m_seqno; } const wsrep_server_gtid_t& undefined() { return m_undefined; } int wait_gtid_upto(const uint64_t seqno, uint timeout) { int wait_result= 0; struct timespec wait_time; int ret= 0; mysql_cond_t wait_cond; mysql_cond_init(key_COND_wsrep_gtid_wait_upto, &wait_cond, NULL); set_timespec(wait_time, timeout); mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto); std::multimap<uint64, mysql_cond_t*>::iterator it; if (seqno > m_seqno) { try { it= m_wait_map.insert(std::make_pair(seqno, &wait_cond)); } catch (std::bad_alloc& e) { ret= ENOMEM; } while (!ret && (m_committed_seqno < seqno) && !m_force_signal) { wait_result= mysql_cond_timedwait(&wait_cond, &LOCK_wsrep_gtid_wait_upto, &wait_time); if (wait_result == ETIMEDOUT || wait_result == ETIME) { ret= wait_result; break; } } if (ret != ENOMEM) { m_wait_map.erase(it); } } mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto); mysql_cond_destroy(&wait_cond); return ret; } void signal_waiters(uint64 seqno, bool signal_all) { mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto); if (!signal_all && (m_committed_seqno >= seqno)) { mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto); return; } m_force_signal= true; std::multimap<uint64, mysql_cond_t*>::iterator it_end; std::multimap<uint64, mysql_cond_t*>::iterator it_begin; if (signal_all) { it_end= m_wait_map.end(); } else { it_end= m_wait_map.upper_bound(seqno); } if (m_committed_seqno < seqno) { m_committed_seqno= seqno; } for (it_begin = m_wait_map.begin(); it_begin != it_end; ++it_begin) { mysql_cond_signal(it_begin->second); } m_force_signal= false; mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto); } private: const wsrep_server_gtid_t m_undefined= {0,0,0}; std::multimap<uint64, mysql_cond_t*> m_wait_map; bool m_force_signal; Atomic_counter<uint64_t> m_seqno; Atomic_counter<uint64_t> m_committed_seqno; }; extern Wsrep_gtid_server wsrep_gtid_server; void wsrep_init_gtid(); bool wsrep_check_gtid_seqno(const uint32&, const uint32&, uint64&); bool wsrep_get_binlog_gtid_seqno(wsrep_server_gtid_t&); int wsrep_append_table_keys(THD* thd, TABLE_LIST* first_table, TABLE_LIST* table_list, Wsrep_service_key_type key_type); extern void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, const MDL_ticket *ticket, const MDL_key *key); enum wsrep_thread_type { WSREP_APPLIER_THREAD=1, WSREP_ROLLBACKER_THREAD=2 }; typedef void (*wsrep_thd_processor_fun)(THD*, void *); class Wsrep_thd_args { public: Wsrep_thd_args(wsrep_thd_processor_fun fun, wsrep_thread_type thread_type, pthread_t thread_id) : fun_ (fun), thread_type_ (thread_type), thread_id_ (thread_id) { } wsrep_thd_processor_fun fun() { return fun_; } pthread_t* thread_id() {return &thread_id_; } enum wsrep_thread_type thread_type() {return thread_type_;} private: Wsrep_thd_args(const Wsrep_thd_args&); Wsrep_thd_args& operator=(const Wsrep_thd_args&); wsrep_thd_processor_fun fun_; enum wsrep_thread_type thread_type_; pthread_t thread_id_; }; void* start_wsrep_THD(void*); void wsrep_close_threads(THD *thd); bool wsrep_is_show_query(enum enum_sql_command command); void wsrep_replay_transaction(THD *thd); bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, HA_CREATE_INFO *create_info); bool wsrep_node_is_donor(); bool wsrep_node_is_synced(); /** * Check if the wsrep provider (ie the Galera library) is capable of * doing streaming replication. * @return true if SR capable */ bool wsrep_provider_is_SR_capable(); /** * Initialize WSREP server instance. * * @return Zero on success, non-zero on error. */ int wsrep_init_server(); /** * Initialize WSREP globals. This should be done after server initialization * is complete and the server has joined to the cluster. * */ void wsrep_init_globals(); /** * Deinit and release WSREP resources. */ void wsrep_deinit_server(); /** * Convert streaming fragment unit (WSREP_FRAG_BYTES, WSREP_FRAG_ROWS...) * to corresponding wsrep-lib fragment_unit */ enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit); wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table, enum wsrep::key::type type); void wsrep_wait_ready(THD *thd); void wsrep_ready_set(bool ready_value); /** * Returns true if the given list of tables contains at least one * non-temporary table. */ bool wsrep_table_list_has_non_temp_tables(THD *thd, TABLE_LIST *tables); /** * Append foreign key to wsrep. * * @param thd Thread object * @param fk Foreign Key Info * * @return true if error, otherwise false. */ bool wsrep_foreign_key_append(THD *thd, FOREIGN_KEY_INFO *fk); void wsrep_report_query_interrupted(const THD *thd, const char* file, const int line); #else /* !WITH_WSREP */ /* These macros are needed to compile MariaDB without WSREP support * (e.g. embedded) */ #define WSREP_PROVIDER_EXISTS (0) #define wsrep_emulate_bin_log (0) #define wsrep_to_isolation (0) #define wsrep_before_SE() (0) #define wsrep_init_startup(X) #define wsrep_check_opts() (0) #define wsrep_thr_init() do {} while(0) #define wsrep_thr_deinit() do {} while(0) #define wsrep_init_globals() do {} while(0) #define wsrep_create_appliers(X) do {} while(0) #define wsrep_cluster_address_exists() (false) #define WSREP_MYSQL_DB (0) #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0) #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_) #define WSREP_TO_ISOLATION_END #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) #define WSREP_SYNC_WAIT(thd_, before_) #endif /* WITH_WSREP */ #endif /* WSREP_MYSQLD_H */ my_user.h 0000644 00000002146 15156036165 0006413 0 ustar 00 /* Copyright (c) 2005-2007 MySQL AB Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* This is a header for libraries containing functions used in both server and only some of clients (but not in libmysql)... */ #ifndef _my_user_h_ #define _my_user_h_ C_MODE_START int parse_user(const char *user_id_str, size_t user_id_len, char *user_name_str, size_t *user_name_len, char *host_name_str, size_t *host_name_len); C_MODE_END #endif /* _my_user_h_ */ my_decimal.h 0000644 00000034231 15156036165 0007033 0 ustar 00 /* Copyright (c) 2005, 2013, Oracle and/or its affiliates. Copyright (c) 2011, 2014, SkySQL Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file It is interface module to fixed precision decimals library. Most functions use 'uint mask' as parameter, if during operation error which fit in this mask is detected then it will be processed automatically here. (errors are E_DEC_* constants, see include/decimal.h) Most function are just inline wrappers around library calls */ #ifndef my_decimal_h #define my_decimal_h #include "sql_basic_types.h" #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) #include "sql_string.h" /* String */ #endif C_MODE_START #include <decimal.h> #include <my_decimal_limits.h> C_MODE_END class String; class Field; typedef struct st_mysql_time MYSQL_TIME; /** maximum size of packet length. */ #define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION inline uint my_decimal_size(decimal_digits_t precision, decimal_digits_t scale) { /* Always allocate more space to allow library to put decimal point where it want */ return decimal_size(precision, scale) + 1; } inline decimal_digits_t my_decimal_int_part(decimal_digits_t precision, decimal_digits_t decimals) { return (decimal_digits_t) (precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals)); } #ifndef MYSQL_CLIENT int decimal_operation_results(int result, const char *value, const char *type); #else inline int decimal_operation_results(int result, const char *value, const char *type) { return result; } #endif /*MYSQL_CLIENT*/ inline int check_result(uint mask, int result) { if (result & mask) decimal_operation_results(result, "", "DECIMAL"); return result; } /** my_decimal class limits 'decimal_t' type to what we need in MySQL. It contains internally all necessary space needed by the instance so no extra memory is needed. One should call fix_buffer_pointer() function when he moves my_decimal objects in memory. */ class my_decimal :public decimal_t { /* Several of the routines in strings/decimal.c have had buffer overrun/underrun problems. These are *not* caught by valgrind. To catch them, we allocate dummy fields around the buffer, and test that their values do not change. */ #if !defined(DBUG_OFF) int foo1; #endif decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; #if !defined(DBUG_OFF) int foo2; static const int test_value= 123; #endif public: my_decimal(const my_decimal &rhs) : decimal_t(rhs) { init(); for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) buffer[i]= rhs.buffer[i]; } my_decimal& operator=(const my_decimal &rhs) { if (this == &rhs) return *this; decimal_t::operator=(rhs); for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) buffer[i]= rhs.buffer[i]; fix_buffer_pointer(); return *this; } void init() { #if !defined(DBUG_OFF) foo1= test_value; foo2= test_value; #endif len= DECIMAL_BUFF_LENGTH; buf= buffer; TRASH_ALLOC(buffer, sizeof(buffer)); } my_decimal() { init(); } my_decimal(const uchar *bin, decimal_digits_t prec, decimal_digits_t scale) { init(); check_result(E_DEC_FATAL_ERROR, bin2decimal(bin, this, prec, scale)); } my_decimal(Field *field); ~my_decimal() { sanity_check(); } void sanity_check() { DBUG_SLOW_ASSERT(foo1 == test_value); DBUG_SLOW_ASSERT(foo2 == test_value); } void fix_buffer_pointer() { buf= buffer; } bool sign() const { return decimal_t::sign; } void sign(bool s) { decimal_t::sign= s; } decimal_digits_t precision() const { return (decimal_digits_t) (intg + frac); } void set_zero() { /* We need the up-cast here, since my_decimal has sign() member functions, which conflicts with decimal_t::sign (and decimal_make_zero is a macro, rather than a funcion). */ decimal_make_zero(static_cast<decimal_t*>(this)); } int cmp(const my_decimal *other) const { return decimal_cmp(this, other); } #ifndef MYSQL_CLIENT bool to_bool() const { return !decimal_is_zero(this); } double to_double() const { double res; decimal2double(this, &res); return res; } longlong to_longlong(bool unsigned_flag) const; /* Return the value as a signed or unsigned longlong, depending on the sign. - Positive values are returned as unsigned. - Negative values are returned as signed. This is used by bit SQL operators: | & ^ ~ as well as by the SQL function BIT_COUNT(). */ longlong to_xlonglong() const { return to_longlong(!sign()); } // Convert to string returning decimal2string() error code int to_string_native(String *to, uint prec, uint dec, char filler, uint mask= E_DEC_FATAL_ERROR) const; // Convert to string returning the String pointer String *to_string(String *to, uint prec, uint dec, char filler) const { return to_string_native(to, prec, dec, filler) ? NULL : to; } String *to_string(String *to) const { return to_string(to, 0, 0, 0); } String *to_string_round(String *to, decimal_digits_t scale, my_decimal *round_buff) const { (void) round_to(round_buff, scale, HALF_UP); // QQ: check result? return round_buff->to_string(to); } /* Scale can be negative here when called from truncate() */ int round_to(my_decimal *to, int scale, decimal_round_mode mode, int mask= E_DEC_FATAL_ERROR) const { return check_result(mask, decimal_round(this, to, scale, mode)); } int to_binary(uchar *bin, int prec, decimal_digits_t scale, uint mask= E_DEC_FATAL_ERROR) const; #endif /** Swap two my_decimal values */ void swap(my_decimal &rhs) { swap_variables(my_decimal, *this, rhs); } }; #ifndef DBUG_OFF void print_decimal(const my_decimal *dec); void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length); const char *dbug_decimal_as_string(char *buff, const my_decimal *val); #else #define dbug_decimal_as_string(A) NULL #endif bool str_set_decimal(uint mask, const my_decimal *val, uint fixed_prec, uint fixed_dec, char filler, String *str, CHARSET_INFO *cs); extern my_decimal decimal_zero; inline void max_my_decimal(my_decimal *to, decimal_digits_t precision, decimal_digits_t frac) { DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&& (frac <= DECIMAL_MAX_SCALE)); max_decimal(precision, frac, to); } inline void max_internal_decimal(my_decimal *to) { max_my_decimal(to, DECIMAL_MAX_PRECISION, 0); } inline int check_result_and_overflow(uint mask, int result, my_decimal *val) { if (check_result(mask, result) & E_DEC_OVERFLOW) { bool sign= val->sign(); val->fix_buffer_pointer(); max_internal_decimal(val); val->sign(sign); } return result; } inline decimal_digits_t my_decimal_length_to_precision(decimal_digits_t length, decimal_digits_t scale, bool unsigned_flag) { /* Precision can't be negative thus ignore unsigned_flag when length is 0. */ DBUG_ASSERT(length || !scale); return (decimal_digits_t) (length - (scale>0 ? 1:0) - (unsigned_flag || !length ? 0:1)); } inline decimal_digits_t my_decimal_precision_to_length_no_truncation(decimal_digits_t precision, decimal_digits_t scale, bool unsigned_flag) { /* When precision is 0 it means that original length was also 0. Thus unsigned_flag is ignored in this case. */ DBUG_ASSERT(precision || !scale); return (decimal_digits_t)(precision + (scale > 0 ? 1 : 0) + (unsigned_flag || !precision ? 0 : 1)); } inline decimal_digits_t my_decimal_precision_to_length(decimal_digits_t precision, decimal_digits_t scale, bool unsigned_flag) { /* When precision is 0 it means that original length was also 0. Thus unsigned_flag is ignored in this case. */ DBUG_ASSERT(precision || !scale); set_if_smaller(precision, DECIMAL_MAX_PRECISION); return my_decimal_precision_to_length_no_truncation(precision, scale, unsigned_flag); } inline uint my_decimal_string_length(const my_decimal *d) { /* length of string representation including terminating '\0' */ return decimal_string_size(d); } inline uint my_decimal_max_length(const my_decimal *d) { /* -1 because we do not count \0 */ return decimal_string_size(d) - 1; } inline uint my_decimal_get_binary_size(decimal_digits_t precision, decimal_digits_t scale) { return decimal_bin_size(precision, scale); } inline void my_decimal2decimal(const my_decimal *from, my_decimal *to) { *to= *from; } inline int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, decimal_digits_t prec, decimal_digits_t scale) { return check_result(mask, bin2decimal(bin, d, prec, scale)); } inline int my_decimal_set_zero(my_decimal *d) { d->set_zero(); return 0; } inline bool my_decimal_is_zero(const my_decimal *decimal_value) { return decimal_is_zero(decimal_value); } inline bool str_set_decimal(const my_decimal *val, String *str, CHARSET_INFO *cs) { return str_set_decimal(E_DEC_FATAL_ERROR, val, 0, 0, 0, str, cs); } bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec, ulong *nanosec); my_decimal *seconds2my_decimal(bool sign, ulonglong sec, ulong microsec, my_decimal *d); #define TIME_to_my_decimal(TIME, DECIMAL) \ seconds2my_decimal((TIME)->neg, TIME_to_ulonglong(TIME), \ (TIME)->second_part, (DECIMAL)) int my_decimal2int(uint mask, const decimal_t *d, bool unsigned_flag, longlong *l, decimal_round_mode round_type= HALF_UP); inline int my_decimal2double(uint, const decimal_t *d, double *result) { /* No need to call check_result as this will always succeed */ return decimal2double(d, result); } inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { return check_result_and_overflow(mask, string2decimal(str, d, end), d); } int str2my_decimal(uint mask, const char *from, size_t length, CHARSET_INFO *charset, my_decimal *decimal_value, const char **end); inline int str2my_decimal(uint mask, const char *from, size_t length, CHARSET_INFO *charset, my_decimal *decimal_value) { const char *end; return str2my_decimal(mask, from, length, charset, decimal_value, &end); } #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) inline int string2my_decimal(uint mask, const String *str, my_decimal *d) { const char *end; return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d, &end); } my_decimal *date2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec); #endif /*defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) */ inline int double2my_decimal(uint mask, double val, my_decimal *d) { return check_result_and_overflow(mask, double2decimal(val, d), d); } inline int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d) { return check_result(mask, (unsigned_flag ? ulonglong2decimal((ulonglong)i, d) : longlong2decimal(i, d))); } inline void decimal2my_decimal(decimal_t *from, my_decimal *to) { DBUG_ASSERT(to->len >= from->len); to->intg= from->intg; to->frac= from->frac; to->sign(from->sign); memcpy(to->buf, from->buf, to->len*sizeof(decimal_digit_t)); } inline void my_decimal_neg(decimal_t *arg) { if (decimal_is_zero(arg)) { arg->sign= 0; return; } decimal_neg(arg); } inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { return check_result_and_overflow(mask, decimal_add(a, b, res), res); } inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { return check_result_and_overflow(mask, decimal_sub(a, b, res), res); } inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { return check_result_and_overflow(mask, decimal_mul(a, b, res), res); } inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { return check_result_and_overflow(mask, decimal_div(a, b, res, div_scale_inc), res); } inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { return check_result_and_overflow(mask, decimal_mod(a, b, res), res); } /** @return -1 if a<b, 1 if a>b and 0 if a==b */ inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) { return decimal_cmp(a, b); } inline int my_decimal_intg(const my_decimal *a) { return decimal_intg(a); } void my_decimal_trim(ulonglong *precision, decimal_digits_t *scale); #endif /*my_decimal_h*/ set_var.h 0000644 00000040613 15156036165 0006374 0 ustar 00 #ifndef SET_VAR_INCLUDED #define SET_VAR_INCLUDED /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file "public" interface to sys_var - server configuration variables. */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include <my_getopt.h> #include <my_attribute.h> class sys_var; class set_var; class sys_var_pluginvar; class PolyLock; class Item_func_set_user_var; // This include needs to be here since item.h requires enum_var_type :-P #include "item.h" /* Item */ #include "sql_class.h" /* THD */ extern TYPELIB bool_typelib; struct sys_var_chain { sys_var *first; sys_var *last; }; int mysql_add_sys_var_chain(sys_var *chain); int mysql_del_sys_var_chain(sys_var *chain); /** A class representing one system variable - that is something that can be accessed as @@global.variable_name or @@session.variable_name, visible in SHOW xxx VARIABLES and in INFORMATION_SCHEMA.xxx_VARIABLES, optionally it can be assigned to, optionally it can have a command-line counterpart with the same name. */ class sys_var: protected Value_source // for double_from_string_with_check { public: sys_var *next; LEX_CSTRING name; bool *test_load; enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023, READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096, NO_SET_STATEMENT=8192, AUTO_SET=16384}; enum { NO_GETOPT=-1, GETOPT_ONLY_HELP=-2 }; enum where { CONFIG, COMMAND_LINE, AUTO, SQL, COMPILE_TIME, ENV }; /** Enumeration type to indicate for a system variable whether it will be written to the binlog or not. */ enum binlog_status_enum { VARIABLE_NOT_IN_BINLOG, SESSION_VARIABLE_IN_BINLOG } binlog_status; my_option option; ///< min, max, default values are stored here enum where value_origin; const char *origin_filename; protected: typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var); typedef bool (*on_update_function)(sys_var *self, THD *thd, enum_var_type type); int flags; ///< or'ed flag_enum values SHOW_TYPE show_val_type; ///< what value_ptr() returns for sql_show.cc PolyLock *guard; ///< *second* lock that protects the variable ptrdiff_t offset; ///< offset to the value from global_system_variables on_check_function on_check; on_update_function on_update; const char *const deprecation_substitute; public: sys_var(sys_var_chain *chain, const char *name_arg, const char *comment, int flag_args, ptrdiff_t off, int getopt_id, enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg, longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, on_check_function on_check_func, on_update_function on_update_func, const char *substitute); virtual ~sys_var() = default; /** All the cleanup procedures should be performed here */ virtual void cleanup() {} /** downcast for sys_var_pluginvar. Returns this if it's an instance of sys_var_pluginvar, and 0 otherwise. */ virtual sys_var_pluginvar *cast_pluginvar() { return 0; } bool check(THD *thd, set_var *var); const uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const; /** Update the system variable with the default value from either session or global scope. The default value is stored in the 'var' argument. Return false when successful. */ bool set_default(THD *thd, set_var *var); bool update(THD *thd, set_var *var); String *val_str_nolock(String *str, THD *thd, const uchar *value); longlong val_int(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base); String *val_str(String *str, THD *thd, enum_var_type type, const LEX_CSTRING *base); double val_real(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base); SHOW_TYPE show_type() const { return show_val_type; } int scope() const { return flags & SCOPE_MASK; } virtual CHARSET_INFO *charset(THD *thd) const { return system_charset_info; } bool is_readonly() const { return flags & READONLY; } void update_flags(int new_flags) { flags = new_flags; } int get_flags() const { return flags; } /** the following is only true for keycache variables, that support the syntax @@keycache_name.variable_name */ bool is_struct() { return option.var_type & GET_ASK_ADDR; } bool is_set_stmt_ok() const { return !(flags & NO_SET_STATEMENT); } bool is_written_to_binlog(enum_var_type type) { return type != OPT_GLOBAL && binlog_status == SESSION_VARIABLE_IN_BINLOG; } bool check_update_type(const Item *item) { Item_result type= item->result_type(); switch (option.var_type & GET_TYPE_MASK) { case GET_INT: case GET_UINT: case GET_LONG: case GET_ULONG: case GET_LL: case GET_ULL: return type != INT_RESULT && (type != DECIMAL_RESULT || item->decimals != 0); case GET_STR: case GET_STR_ALLOC: return type != STRING_RESULT; case GET_ENUM: case GET_BOOL: case GET_SET: case GET_FLAGSET: case GET_BIT: return type != STRING_RESULT && type != INT_RESULT; case GET_DOUBLE: return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT; default: return true; } } bool check_type(enum_var_type type) { switch (scope()) { case GLOBAL: return type != OPT_GLOBAL; case SESSION: return false; // always ok case ONLY_SESSION: return type == OPT_GLOBAL; } return true; // keep gcc happy } bool register_option(DYNAMIC_ARRAY *array, int parse_flags) { DBUG_ASSERT(parse_flags == GETOPT_ONLY_HELP || parse_flags == PARSE_EARLY || parse_flags == 0); if (option.id == NO_GETOPT) return 0; if (parse_flags == GETOPT_ONLY_HELP) { if (option.id != GETOPT_ONLY_HELP) return 0; } else { if (option.id == GETOPT_ONLY_HELP) return 0; if ((flags & PARSE_EARLY) != parse_flags) return 0; } return insert_dynamic(array, (uchar*)&option); } void do_deprecated_warning(THD *thd); /** whether session value of a sysvar is a default one. in this simple implementation we don't distinguish between default and non-default values. for most variables it's ok, they don't treat default values specially. this method is overwritten in descendant classes as necessary. */ virtual bool session_is_default(THD *thd) { return false; } virtual const uchar *default_value_ptr(THD *thd) const { return (uchar*)&option.def_value; } virtual bool on_check_access_global(THD *thd) const; virtual bool on_check_access_session(THD *thd) const { return false; } private: virtual bool do_check(THD *thd, set_var *var) = 0; /** save the session default value of the variable in var */ virtual void session_save_default(THD *thd, set_var *var) = 0; /** save the global default value of the variable in var */ virtual void global_save_default(THD *thd, set_var *var) = 0; virtual bool session_update(THD *thd, set_var *var) = 0; virtual bool global_update(THD *thd, set_var *var) = 0; protected: /** A pointer to a value of the variable for SHOW. It must be of show_val_type type (my_bool for SHOW_MY_BOOL, int for SHOW_INT, longlong for SHOW_LONGLONG, etc). */ virtual const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const; virtual const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; /** A pointer to a storage area of the variable, to the raw data. Typically it's the same as session_value_ptr(), but it's different, for example, for ENUM, that is printed as a string, but stored as a number. */ ATTRIBUTE_NO_UBSAN uchar *session_var_ptr(THD *thd) const { return ((uchar*)&(thd->variables)) + offset; } ATTRIBUTE_NO_UBSAN uchar *global_var_ptr() const { return ((uchar*)&global_system_variables) + offset; } void *max_var_ptr() { return scope() == SESSION ? (((uchar*)&max_system_variables) + offset) : 0; } friend class Session_sysvars_tracker; friend class Session_tracker; }; #include "sql_plugin.h" /* SHOW_HA_ROWS, SHOW_MY_BOOL */ /**************************************************************************** Classes for parsing of the SET command ****************************************************************************/ /** A base class for everything that can be set with SET command. It's similar to Items, an instance of this is created by the parser for every assigmnent in SET (or elsewhere, e.g. in SELECT). */ class set_var_base :public Sql_alloc { public: set_var_base() = default; virtual ~set_var_base() = default; virtual int check(THD *thd)=0; /* To check privileges etc. */ virtual int update(THD *thd)=0; /* To set the value */ virtual int light_check(THD *thd) { return check(thd); } /* for PS */ virtual bool is_system() { return FALSE; } /** @returns whether this variable is @@@@optimizer_trace. */ virtual bool is_var_optimizer_trace() const { return false; } }; /** Structure for holding unix timestamp and high precision second part. */ typedef struct my_time_t_hires { my_time_t unix_time; ulong second_part; } my_time_t_hires; /** set_var_base descendant for assignments to the system variables. */ class set_var :public set_var_base { public: sys_var *var; ///< system variable to be updated Item *value; ///< the expression that provides the new value of the variable enum_var_type type; union ///< temp storage to hold a value between sys_var::check and ::update { ulonglong ulonglong_value; ///< for unsigned integer, set, enum sysvars longlong longlong_value; ///< for signed integer double double_value; ///< for Sys_var_double plugin_ref plugin; ///< for Sys_var_plugin plugin_ref *plugins; ///< for Sys_var_pluginlist Time_zone *time_zone; ///< for Sys_var_tz LEX_STRING string_value; ///< for Sys_var_charptr and others my_time_t_hires timestamp; ///< for Sys_var_vers_asof const void *ptr; ///< for Sys_var_struct } save_result; LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */ set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg, const LEX_CSTRING *base_name_arg, Item *value_arg); bool is_system() override { return 1; } int check(THD *thd) override; int update(THD *thd) override; int light_check(THD *thd) override; bool is_var_optimizer_trace() const override { extern sys_var *Sys_optimizer_trace_ptr; return var == Sys_optimizer_trace_ptr; } }; /* User variables like @my_own_variable */ class set_var_user: public set_var_base { Item_func_set_user_var *user_var_item; public: set_var_user(Item_func_set_user_var *item) :user_var_item(item) {} int check(THD *thd) override; int update(THD *thd) override; int light_check(THD *thd) override; }; /* For SET PASSWORD */ class set_var_password: public set_var_base { LEX_USER *user; public: set_var_password(LEX_USER *user_arg) :user(user_arg) {} int check(THD *thd) override; int update(THD *thd) override; }; /* For SET ROLE */ class set_var_role: public set_var_base { LEX_CSTRING role; privilege_t access; public: set_var_role(LEX_CSTRING role_arg) : role(role_arg), access(NO_ACL) {} int check(THD *thd) override; int update(THD *thd) override; }; /* For SET DEFAULT ROLE */ class set_var_default_role: public set_var_base { LEX_USER *user, *real_user; LEX_CSTRING role; const char *real_role; public: set_var_default_role(LEX_USER *user_arg, LEX_CSTRING role_arg) : user(user_arg), role(role_arg) {} int check(THD *thd) override; int update(THD *thd) override; }; /* For SET NAMES and SET CHARACTER SET */ class set_var_collation_client: public set_var_base { CHARSET_INFO *character_set_client; CHARSET_INFO *character_set_results; CHARSET_INFO *collation_connection; public: set_var_collation_client(CHARSET_INFO *client_coll_arg, CHARSET_INFO *connection_coll_arg, CHARSET_INFO *result_coll_arg) :character_set_client(client_coll_arg), character_set_results(result_coll_arg), collation_connection(connection_coll_arg) {} int check(THD *thd) override; int update(THD *thd) override; }; /* optional things, have_* variables */ extern SHOW_COMP_OPTION have_csv, have_innodb; extern SHOW_COMP_OPTION have_ndbcluster, have_partitioning; extern SHOW_COMP_OPTION have_profiling; extern SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen; extern SHOW_COMP_OPTION have_query_cache; extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; extern SHOW_COMP_OPTION have_crypt; extern SHOW_COMP_OPTION have_compress; extern SHOW_COMP_OPTION have_openssl; /* Prototypes for helper functions */ ulong get_system_variable_hash_records(void); ulonglong get_system_variable_hash_version(void); SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type); int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond); sys_var *find_sys_var(THD *thd, const char *str, size_t length= 0, bool throw_error= false); int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free); #define SYSVAR_AUTOSIZE(VAR,VAL) \ do { \ VAR= (VAL); \ set_sys_var_value_origin(&VAR, sys_var::AUTO); \ } while(0) #define SYSVAR_AUTOSIZE_IF_CHANGED(VAR,VAL,TYPE) \ do { \ TYPE tmp= (VAL); \ if (VAR != tmp) \ { \ VAR= (VAL); \ set_sys_var_value_origin(&VAR, sys_var::AUTO); \ } \ } while(0) void set_sys_var_value_origin(void *ptr, enum sys_var::where here, const char *filename= NULL); enum sys_var::where get_sys_var_value_origin(void *ptr); inline bool IS_SYSVAR_AUTOSIZE(void *ptr) { enum sys_var::where res= get_sys_var_value_origin(ptr); return (res == sys_var::AUTO || res == sys_var::COMPILE_TIME); } bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type); sql_mode_t expand_sql_mode(sql_mode_t sql_mode); #ifndef EMBEDDED_LIBRARY bool validate_redirect_url(char *str, size_t len); #endif const char *sql_mode_string_representation(uint bit_number); bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode, LEX_CSTRING *ls); int default_regex_flags_pcre(THD *thd); extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr, *Sys_character_set_client_ptr, *Sys_character_set_connection_ptr, *Sys_character_set_results_ptr; CHARSET_INFO *get_old_charset_by_name(const char *old_name); int sys_var_init(); uint sys_var_elements(); int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags); void sys_var_end(void); bool check_has_super(sys_var *self, THD *thd, set_var *var); plugin_ref *resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len, bool error_on_unknown_engine, bool temp_copy); void free_engine_list(plugin_ref *list); plugin_ref *copy_engine_list(plugin_ref *list); plugin_ref *temp_copy_engine_list(THD *thd, plugin_ref *list); char *pretty_print_engine_list(THD *thd, plugin_ref *list); void check_new_mode_value(THD *thd, ulonglong *v); #endif aligned.h 0000644 00000002160 15156036166 0006330 0 ustar 00 /* Copyright (c) 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #if defined __linux__ # include <malloc.h> #endif inline void *aligned_malloc(size_t size, size_t alignment) { #ifdef _WIN32 return _aligned_malloc(size, alignment); #elif defined __linux__ return memalign(alignment, size); #else void *result; if (posix_memalign(&result, alignment, size)) result= NULL; return result; #endif } inline void aligned_free(void *ptr) { IF_WIN(_aligned_free,free)(ptr); } wsrep_var.h 0000644 00000010476 15156036166 0006746 0 ustar 00 /* Copyright (C) 2013-2025 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_VAR_H #define WSREP_VAR_H #include <my_config.h> #ifdef WITH_WSREP #define WSREP_CLUSTER_NAME "my_wsrep_cluster" #define WSREP_NODE_INCOMING_AUTO "AUTO" #define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" #define WSREP_START_POSITION_ZERO_GTID "00000000-0000-0000-0000-000000000000:-1,0-0-0" // MySQL variables funcs #include "sql_priv.h" #include <sql_plugin.h> #include <mysql/plugin.h> class sys_var; class set_var; class THD; int wsrep_init_vars(); void wsrep_set_wsrep_on(THD *thd); void wsrep_free_status_vars(); bool wsrep_refresh_provider_options(); #define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) #define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) #define DEFAULT_ARGS (THD* thd, enum_var_type var_type) #define INIT_ARGS (const char* opt) extern bool wsrep_on_check CHECK_ARGS; extern bool wsrep_on_update UPDATE_ARGS; extern bool wsrep_start_position_check CHECK_ARGS; extern bool wsrep_start_position_update UPDATE_ARGS; extern bool wsrep_start_position_init INIT_ARGS; extern bool wsrep_provider_check CHECK_ARGS; extern bool wsrep_provider_update UPDATE_ARGS; extern void wsrep_provider_init INIT_ARGS; extern bool wsrep_provider_options_check CHECK_ARGS; extern bool wsrep_provider_options_update UPDATE_ARGS; extern void wsrep_provider_options_init INIT_ARGS; extern bool wsrep_cluster_address_check CHECK_ARGS; extern bool wsrep_cluster_address_update UPDATE_ARGS; extern void wsrep_cluster_address_init INIT_ARGS; extern bool wsrep_cluster_name_check CHECK_ARGS; extern bool wsrep_cluster_name_update UPDATE_ARGS; extern bool wsrep_node_name_check CHECK_ARGS; extern bool wsrep_node_name_update UPDATE_ARGS; extern bool wsrep_node_address_check CHECK_ARGS; extern bool wsrep_node_address_update UPDATE_ARGS; extern void wsrep_node_address_init INIT_ARGS; extern bool wsrep_sst_method_check CHECK_ARGS; extern bool wsrep_sst_method_update UPDATE_ARGS; extern void wsrep_sst_method_init INIT_ARGS; extern bool wsrep_sst_receive_address_check CHECK_ARGS; extern bool wsrep_sst_receive_address_update UPDATE_ARGS; extern bool wsrep_sst_auth_check CHECK_ARGS; extern bool wsrep_sst_auth_update UPDATE_ARGS; extern bool wsrep_sst_donor_check CHECK_ARGS; extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_slave_threads_check CHECK_ARGS; extern bool wsrep_slave_threads_update UPDATE_ARGS; extern bool wsrep_desync_check CHECK_ARGS; extern bool wsrep_desync_update UPDATE_ARGS; extern bool wsrep_trx_fragment_size_check CHECK_ARGS; extern bool wsrep_trx_fragment_size_update UPDATE_ARGS; extern bool wsrep_trx_fragment_unit_check CHECK_ARGS; extern bool wsrep_trx_fragment_unit_update UPDATE_ARGS; extern bool wsrep_max_ws_size_check CHECK_ARGS; extern bool wsrep_max_ws_size_update UPDATE_ARGS; extern bool wsrep_reject_queries_update UPDATE_ARGS; extern bool wsrep_debug_update UPDATE_ARGS; extern bool wsrep_gtid_seq_no_check CHECK_ARGS; extern bool wsrep_gtid_domain_id_update UPDATE_ARGS; extern bool wsrep_mode_check CHECK_ARGS; extern bool wsrep_forced_binlog_format_check CHECK_ARGS; #else /* WITH_WSREP */ #define wsrep_provider_init(X) #define wsrep_init_vars() (0) #define wsrep_start_position_init(X) #endif /* WITH_WSREP */ #endif /* WSREP_VAR_H */ my_handler_errors.h 0000644 00000011422 15156036166 0010444 0 ustar 00 #ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED #define MYSYS_MY_HANDLER_ERRORS_INCLUDED /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. Copyright (c) 2011, 2013, SkySQL Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Errors a handler can give you */ static const char *handler_error_messages[]= { /* 120 */ "Didn't find the key on read or update", "Duplicate key on write or update", "Internal (unspecified) error in handler", "Someone has changed the row since it was read (even though the table was locked to prevent it)", "Wrong index given to a function", "Undefined handler error 125", "Index is corrupted", "Table file is corrupted", "Out of memory in engine", "Undefined handler error 129", /* 130 */ "Incorrect file format", "Command not supported by the engine", "Old database file", "No record read before update", "Record was already deleted (or record file crashed)", "No more room in record file", "No more room in index file", "No more records (read after end of file)", "Unsupported extension used for table", "Too big row", /* 140 */ "Wrong create options", "Duplicate unique key on write or update", "Unknown character set used in table", "Conflicting table definitions in sub-tables of MERGE table", "Table is crashed and last repair failed", "Table was marked as crashed and should be repaired", "Lock timed out; Retry transaction", "Lock table is full; Restart program with a larger lock table", "Updates are not allowed under a read only transactions", "Lock deadlock; Retry transaction", /* 150 */ "Foreign key constraint is incorrectly formed", "Cannot add a child row", "Cannot delete a parent row", "No savepoint with that name", "Non unique key block size", "The table does not exist in the storage engine", "The table already existed in the storage engine", "Could not connect to the storage engine", "Unexpected null pointer found when using spatial index", "The table changed in the storage engine", /* 160 */ "There's no partition in the table for the given value", "Row-based binary logging of row failed", "Index needed in foreign key constraint", "Upholding foreign key constraints would lead to a duplicate key error in some other table", "Table needs to be upgraded before it can be used", "Table is read only", "Failed to get next auto increment value", "Failed to set row auto increment value", "Unknown (generic) error from engine", "Record was not updated. New values were the same as original values", /* 170 */ "It is not possible to log this statement", "The event was corrupt, leading to illegal data being read", "The table is of a new format not supported by this version", "The event could not be processed. No other handler error happened", "Fatal error during initialization of handler", "File too short; Expected more data in file", "Read page with wrong checksum", "Too many active concurrent transactions", "Record not matching the given partition set", "Index column length exceeds limit", /* 180 */ "Index corrupted", "Undo record too big", "Invalid InnoDB FTS Doc ID", "Table is being used in foreign key check", "Tablespace already exists", "Too many columns", "Row in wrong partition", "Row is not visible by the current transaction", "Operation was interrupted by end user (probably kill command?)", "Disk full", /* 190 */ "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry or dump and restore the table to fix this", "Too many words in a FTS phrase or proximity search", "Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.", "Foreign key cascade delete/update exceeds max depth", "Tablespace is missing for a table", "Sequence has been run out", "Sequence values are conflicting", "Error during commit", "Cannot select partitions", "Cannot initialize encryption. Check that all encryption parameters have been set", "Transaction was aborted", }; #endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ item_vers.h 0000644 00000010475 15156036166 0006732 0 ustar 00 #ifndef ITEM_VERS_INCLUDED #define ITEM_VERS_INCLUDED /* Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /* System Versioning items */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif class Item_func_history: public Item_bool_func { public: /* @param a Item_field for row_end system field */ Item_func_history(THD *thd, Item *a): Item_bool_func(thd, a) { DBUG_ASSERT(a->type() == Item::FIELD_ITEM); } bool val_bool() override; bool fix_length_and_dec(THD *thd) override { set_maybe_null(); null_value= 0; decimals= 0; max_length= 1; return FALSE; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("is_history") }; return name; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_history>(thd, this); } }; class Item_func_trt_ts: public Item_datetimefunc { TR_table::field_id_t trt_field; public: Item_func_trt_ts(THD *thd, Item* a, TR_table::field_id_t _trt_field); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING begin_name= {STRING_WITH_LEN("trt_begin_ts") }; static LEX_CSTRING commit_name= {STRING_WITH_LEN("trt_commit_ts") }; return (trt_field == TR_table::FLD_BEGIN_TS) ? begin_name : commit_name; } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { fix_attributes_datetime(decimals); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trt_ts>(thd, this); } }; class Item_func_trt_id : public Item_longlong_func { TR_table::field_id_t trt_field; bool backwards; longlong get_by_trx_id(ulonglong trx_id); longlong get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards); public: Item_func_trt_id(THD *thd, Item* a, TR_table::field_id_t _trt_field, bool _backwards= false); Item_func_trt_id(THD *thd, Item* a, Item* b, TR_table::field_id_t _trt_field); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING trx_name= {STRING_WITH_LEN("trt_trx_id") }; static LEX_CSTRING commit_name= {STRING_WITH_LEN("trt_commit_id") }; static LEX_CSTRING iso_name= {STRING_WITH_LEN("trt_iso_level") }; switch (trt_field) { case TR_table::FLD_TRX_ID: return trx_name; case TR_table::FLD_COMMIT_ID: return commit_name; case TR_table::FLD_ISO_LEVEL: return iso_name; default: DBUG_ASSERT(0); } return NULL_clex_str; } bool fix_length_and_dec(THD *thd) override { bool res= Item_int_func::fix_length_and_dec(thd); max_length= 20; return res; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trt_id>(thd, this); } }; class Item_func_trt_trx_sees : public Item_bool_func { protected: bool accept_eq; public: Item_func_trt_trx_sees(THD *thd, Item* a, Item* b); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("trt_trx_sees") }; return name; } bool val_bool() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_trt_trx_sees>(thd, this); } }; class Item_func_trt_trx_sees_eq : public Item_func_trt_trx_sees { public: Item_func_trt_trx_sees_eq(THD *thd, Item* a, Item* b) : Item_func_trt_trx_sees(thd, a, b) { accept_eq= true; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("trt_trx_sees_eq") }; return name; } }; #endif /* ITEM_VERS_INCLUDED */ opt_trace.h 0000644 00000020452 15156036166 0006711 0 ustar 00 #ifndef OPT_TRACE_INCLUDED #define OPT_TRACE_INCLUDED /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "opt_trace_context.h" // Opt_trace_context #include "sql_lex.h" #include "my_json_writer.h" #include "sql_select.h" class Item; class THD; struct TABLE_LIST; /* User-visible information about a trace. */ struct Opt_trace_info { /** String containing trace. If trace has been end()ed, this is 0-terminated, which is only to aid debugging or unit testing; this property is not relied upon in normal server usage. If trace has not been ended, this is not 0-terminated. That rare case can happen when a substatement reads OPTIMIZER_TRACE (at that stage, the top statement is still executing so its trace is not ended yet, but may still be read by the sub-statement). */ const char *trace_ptr; size_t trace_length; //// String containing original query. const char *query_ptr; size_t query_length; const CHARSET_INFO *query_charset; ///< charset of query string /** How many bytes this trace is missing (for traces which were truncated because of @@@@optimizer-trace-max-mem-size). The trace is not extended beyond trace-max-mem-size. */ size_t missing_bytes; /* Whether user lacks privilege to see this trace. If this is set to TRUE, then we return an empty trace */ bool missing_priv; }; /** Instantiate this class to start tracing a THD's actions (generally at a statement's start), and to set the "original" query (not transformed, as sent by client) for the new trace. Destructor will end the trace. @param thd the THD @param tbl list of tables read/written by the statement. @param sql_command SQL command being prepared or executed @param set_vars what variables are set by this command (only used if sql_command is SQLCOM_SET_OPTION) @param query query @param length query's length @param charset charset which was used to encode this query */ class Opt_trace_start { public: Opt_trace_start(THD *thd_arg): ctx(&thd_arg->opt_trace), traceable(false) {} void init(THD *thd, TABLE_LIST *tbl, enum enum_sql_command sql_command, List<set_var_base> *set_vars, const char *query, size_t query_length, const CHARSET_INFO *query_charset); ~Opt_trace_start(); private: Opt_trace_context *const ctx; /* True: the query will be traced False: otherwise */ bool traceable; }; /** Prints SELECT query to optimizer trace. It is not the original query (as in @c Opt_trace_context::set_query()) but a printout of the parse tree (Item-s). @param thd the THD @param select_lex query's parse tree @param trace_object Json_writer object to which the query will be added */ void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex, Json_writer_object *trace_object); void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab); void trace_plan_prefix(Json_writer_object *jsobj, JOIN *join, uint idx, table_map join_tables); void print_final_join_order(JOIN *join); void print_best_access_for_table(THD *thd, POSITION *pos); void trace_condition(THD * thd, const char *name, const char *transform_type, Item *item, const char *table_name= nullptr); /* Security related (need to add a proper comment here) */ /** If the security context is not that of the connected user, inform the trace system that a privilege is missing. With one exception: see below. @param thd This serves to eliminate the following issue. Any information readable by a SELECT may theoretically end up in the trace. And a SELECT may read information from other places than tables: - from views (reading their bodies) - from stored routines (reading their bodies) - from files (reading their content), with LOAD_FILE() - from the list of connections (reading their queries...), with I_S.PROCESSLIST. If the connected user has EXECUTE privilege on a routine which does a security context change, the routine can retrieve information internally (if allowed by the SUID context's privileges), and present only a portion of it to the connected user. But with tracing on, all information is possibly in the trace. So the connected user receives more information than the routine's definer intended to provide. Fixing this issue would require adding, near many privilege checks in the server, a new optimizer-trace-specific check done against the connected user's context, to verify that the connected user has the right to see the retrieved information. Instead, our chosen simpler solution is that if we see a security context change where SUID user is not the connected user, we disable tracing. With only one safe exception: if the connected user has all global privileges (because then she/he can find any information anyway). By "all global privileges" we mean everything but WITH GRANT OPTION (that latter one isn't related to information gathering). Read access to I_S.OPTIMIZER_TRACE by another user than the connected user is restricted: @see fill_optimizer_trace_info(). */ void opt_trace_disable_if_no_security_context_access(THD *thd); void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl); /** If tracing is on, checks additional privileges for a view, to make sure that the user has the right to do SHOW CREATE VIEW. For that: - this function checks SHOW VIEW - SELECT is tested in opt_trace_disable_if_no_tables_access() - SELECT + SHOW VIEW is sufficient for SHOW CREATE VIEW. We also check underlying tables. If a privilege is missing, notifies the trace system. This function should be called when the view's underlying tables have not yet been merged. @param thd THD context @param view view to check @param underlying_tables underlying tables/views of 'view' */ void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view, TABLE_LIST *underlying_tables); /** If tracing is on, checks additional privileges on a stored routine, to make sure that the user has the right to do SHOW CREATE PROCEDURE/FUNCTION. For that, we use the same checks as in those SHOW commands. If a privilege is missing, notifies the trace system. This function is not redundant with opt_trace_disable_if_no_security_context_access(). Indeed, for a SQL SECURITY INVOKER routine, there is no context change, but we must still verify that the invoker can do SHOW CREATE. For triggers, see note in sp_head::execute_trigger(). @param thd @param sp routine to check */ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp); /** Fills information_schema.OPTIMIZER_TRACE with rows (one per trace) @retval 0 ok @retval 1 error */ int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *); #define OPT_TRACE_TRANSFORM(thd, object_level0, object_level1, \ select_number, from, to) \ Json_writer_object object_level0(thd); \ Json_writer_object object_level1(thd, "transformation"); \ object_level1.add_select_number(select_number).add("from", from).add("to", to); #define OPT_TRACE_VIEWS_TRANSFORM(thd, object_level0, object_level1, \ derived, name, select_number, algorithm) \ Json_writer_object trace_wrapper(thd); \ Json_writer_object trace_derived(thd, derived); \ trace_derived.add("table", name).add_select_number(select_number) \ .add("algorithm", algorithm); #endif create_tmp_table.h 0000644 00000005370 15156036166 0010225 0 ustar 00 #ifndef CREATE_TMP_TABLE_INCLUDED #define CREATE_TMP_TABLE_INCLUDED /* Copyright (c) 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Class for creating internal tempory tables in sql_select.cc */ class Create_tmp_table: public Data_type_statistics { protected: // The following members are initialized only in start() Field **m_from_field, **m_default_field; KEY_PART_INFO *m_key_part_info; uchar *m_group_buff, *m_bitmaps; // The following members are initialized in ctor uint m_alloced_field_count; bool m_using_unique_constraint; uint m_temp_pool_slot; ORDER *m_group; bool m_distinct; bool m_save_sum_fields; bool m_with_cycle; ulonglong m_select_options; ha_rows m_rows_limit; uint m_group_null_items; // counter for distinct/other fields uint m_field_count[2]; // counter for distinct/other fields which can be NULL uint m_null_count[2]; // counter for distinct/other blob fields uint m_blobs_count[2]; // counter for "tails" of bit fields which do not fit in a byte uint m_uneven_bit[2]; public: enum counter {distinct, other}; /* shows which field we are processing: distinct/other (set in processing cycles) */ counter current_counter; Create_tmp_table(ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit); virtual ~Create_tmp_table() {} virtual bool choose_engine(THD *thd, TABLE *table, TMP_TABLE_PARAM *param); void add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols); TABLE *start(THD *thd, TMP_TABLE_PARAM *param, const LEX_CSTRING *table_alias); bool add_fields(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, List<Item> &fields); bool add_schema_fields(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, const ST_SCHEMA_TABLE &schema_table); bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, bool do_not_open, bool keep_row_order); void cleanup_on_failure(THD *thd, TABLE *table); }; #endif /* CREATE_TMP_TABLE_INCLUDED */ xa.h 0000644 00000003557 15156036166 0005350 0 ustar 00 #ifndef XA_INCLUDED #define XA_INCLUDED /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ class XID_cache_element; enum xa_states { XA_ACTIVE= 0, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY, XA_NO_STATE }; struct XID_STATE { XID_cache_element *xid_cache_element; bool check_has_uncommitted_xa() const; bool is_explicit_XA() const { return xid_cache_element != 0; } void set_error(uint error); void set_online_alter_cache(Online_alter_cache_list *); void set_rollback_only(); void er_xaer_rmfail() const; XID *get_xid() const; enum xa_states get_state_code() const; }; void xid_cache_init(void); void xid_cache_free(void); bool xid_cache_insert(XID *xid); bool xid_cache_insert(THD *thd, XID_STATE *xid_state, XID *xid); void xid_cache_delete(THD *thd, XID_STATE *xid_state); bool trans_xa_start(THD *thd); bool trans_xa_end(THD *thd); bool trans_xa_prepare(THD *thd); bool trans_xa_commit(THD *thd); bool trans_xa_rollback(THD *thd); bool trans_xa_detach(THD *thd); bool mysql_xa_recover(THD *thd); void xa_recover_get_fields(THD *thd, List<Item> *field_list, my_hash_walk_action *action); #endif /* XA_INCLUDED */ sql_admin.h 0000644 00000005543 15156036166 0006704 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TABLE_MAINTENANCE_H #define SQL_TABLE_MAINTENANCE_H /* Must be able to hold ALTER TABLE t PARTITION BY ... KEY ALGORITHM = 1 ... */ #define SQL_ADMIN_MSG_TEXT_SIZE (128 * 1024) bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list, const LEX_CSTRING *key_cache_name); bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list); int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache, KEY_CACHE *dst_cache); void fill_check_table_metadata_fields(THD *thd, List<Item>* fields); /** Sql_cmd_analyze_table represents the ANALYZE TABLE statement. */ class Sql_cmd_analyze_table : public Sql_cmd { public: /** Constructor, used to represent a ANALYZE TABLE statement. */ Sql_cmd_analyze_table() = default; ~Sql_cmd_analyze_table() = default; bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_ANALYZE; } }; /** Sql_cmd_check_table represents the CHECK TABLE statement. */ class Sql_cmd_check_table : public Sql_cmd { public: /** Constructor, used to represent a CHECK TABLE statement. */ Sql_cmd_check_table() = default; ~Sql_cmd_check_table() = default; bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_CHECK; } }; /** Sql_cmd_optimize_table represents the OPTIMIZE TABLE statement. */ class Sql_cmd_optimize_table : public Sql_cmd { public: /** Constructor, used to represent a OPTIMIZE TABLE statement. */ Sql_cmd_optimize_table() = default; ~Sql_cmd_optimize_table() = default; bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_OPTIMIZE; } }; /** Sql_cmd_repair_table represents the REPAIR TABLE statement. */ class Sql_cmd_repair_table : public Sql_cmd { public: /** Constructor, used to represent a REPAIR TABLE statement. */ Sql_cmd_repair_table() = default; ~Sql_cmd_repair_table() = default; bool execute(THD *thd) override; enum_sql_command sql_command_code() const override { return SQLCOM_REPAIR; } }; #endif log_event_data_type.h 0000644 00000003542 15156036167 0010747 0 ustar 00 /* Copyright (c) 2024, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef LOG_EVENT_DATA_TYPE_H #define LOG_EVENT_DATA_TYPE_H class Log_event_data_type { public: enum { CHUNK_SIGNED= 0, CHUNK_UNSIGNED= 1, CHUNK_DATA_TYPE_NAME= 2 }; protected: LEX_CSTRING m_data_type_name; Item_result m_type; uint m_charset_number; bool m_is_unsigned; public: Log_event_data_type() :m_data_type_name({NULL,0}), m_type(STRING_RESULT), m_charset_number(my_charset_bin.number), m_is_unsigned(false) { } Log_event_data_type(const LEX_CSTRING &data_type_name_arg, Item_result type_arg, uint charset_number_arg, bool is_unsigned_arg) :m_data_type_name(data_type_name_arg), m_type(type_arg), m_charset_number(charset_number_arg), m_is_unsigned(is_unsigned_arg) { } const LEX_CSTRING & data_type_name() const { return m_data_type_name; } Item_result type() const { return m_type; } uint charset_number() const { return m_charset_number; } bool is_unsigned() const { return m_is_unsigned; } bool unpack_optional_attributes(const char *str, const char *end); }; #endif // LOG_EVENT_DATA_TYPE_H sql_command.h 0000644 00000011556 15156036167 0007234 0 ustar 00 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* When a command is added here, be sure it's also added in mysqld.cc in "struct show_var_st status_vars[]= {" ... If the command returns a result set or is not allowed in stored functions or triggers, please also make sure that sp_get_flags_for_command (sp_head.cc) returns proper flags for the added SQLCOM_. */ enum enum_sql_command { SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX, SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS, SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_BINLOG_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_TRIGGERS, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL, SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION, SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC, SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC, SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE, SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW, SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER, SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE, SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER, SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE, SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN, SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT, SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_CONTRIBUTORS, SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER, SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT, SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_CREATE_TRIGGER, SQLCOM_ALTER_DB_UPGRADE, SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES, SQLCOM_SIGNAL, SQLCOM_RESIGNAL, SQLCOM_SHOW_RELAYLOG_EVENTS, SQLCOM_GET_DIAGNOSTICS, SQLCOM_SHOW_CLIENT_STATS, SQLCOM_SHOW_THREAD_STATS, SQLCOM_ENABLE_GOVERNOR, SQLCOM_ENABLE_RECONN_GOVERNOR, SQLCOM_ENABLE_GOVERNOR_LVE, SQLCOM_ENABLE_RECONN_GOVERNOR_LVE, SQLCOM_SLAVE_ALL_START, SQLCOM_SLAVE_ALL_STOP, SQLCOM_SHOW_EXPLAIN, SQLCOM_SHOW_ANALYZE, SQLCOM_SHUTDOWN, SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE, SQLCOM_COMPOUND, SQLCOM_SHOW_GENERIC, SQLCOM_ALTER_USER, SQLCOM_SHOW_CREATE_USER, SQLCOM_EXECUTE_IMMEDIATE, SQLCOM_CREATE_SEQUENCE, SQLCOM_DROP_SEQUENCE, SQLCOM_ALTER_SEQUENCE, SQLCOM_CREATE_PACKAGE, SQLCOM_DROP_PACKAGE, SQLCOM_CREATE_PACKAGE_BODY, SQLCOM_DROP_PACKAGE_BODY, SQLCOM_SHOW_CREATE_PACKAGE, SQLCOM_SHOW_CREATE_PACKAGE_BODY, SQLCOM_SHOW_STATUS_PACKAGE, SQLCOM_SHOW_STATUS_PACKAGE_BODY, SQLCOM_SHOW_PACKAGE_BODY_CODE, SQLCOM_BACKUP, SQLCOM_BACKUP_LOCK, /* When a command is added here, be sure it's also added in mysqld.cc in "struct show_var_st com_status_vars[]= {" ... */ /* This should be the last !!! */ SQLCOM_END }; wsrep_server_service.h 0000644 00000007057 15156036167 0011206 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_SERVER_SERVICE_H #define WSREP_SERVER_SERVICE_H /* wsrep-lib */ #include "wsrep/server_service.hpp" #include "wsrep/exception.hpp" // not_impemented_error(), remove when finished #include "wsrep/storage_service.hpp" class Wsrep_server_state; /* wsrep::server_service interface implementation */ class Wsrep_server_service : public wsrep::server_service { public: Wsrep_server_service(Wsrep_server_state& server_state) : m_server_state(server_state) { } wsrep::storage_service* storage_service(wsrep::client_service&) override; wsrep::storage_service* storage_service(wsrep::high_priority_service&) override; void release_storage_service(wsrep::storage_service*) override; wsrep::high_priority_service* streaming_applier_service(wsrep::client_service&) override; wsrep::high_priority_service* streaming_applier_service(wsrep::high_priority_service&) override; void release_high_priority_service(wsrep::high_priority_service*) override; void background_rollback(wsrep::unique_lock<wsrep::mutex> &, wsrep::client_state &) override; void bootstrap() override; void log_message(enum wsrep::log::level, const char*) override; void log_dummy_write_set(wsrep::client_state&, const wsrep::ws_meta&) override { throw wsrep::not_implemented_error(); } void log_view(wsrep::high_priority_service*, const wsrep::view&) override; void recover_streaming_appliers(wsrep::client_service&) override; void recover_streaming_appliers(wsrep::high_priority_service&) override; wsrep::view get_view(wsrep::client_service&, const wsrep::id& own_id) override; wsrep::gtid get_position(wsrep::client_service&) override; void set_position(wsrep::client_service&, const wsrep::gtid&) override; void log_state_change(enum wsrep::server_state::state, enum wsrep::server_state::state) override; bool sst_before_init() const override; std::string sst_request() override; int start_sst(const std::string&, const wsrep::gtid&, bool) override; int wait_committing_transactions(int) override; void debug_sync(const char*) override; private: Wsrep_server_state& m_server_state; }; /** Helper method to create new streaming applier. @param orig_thd Original thd context to copy operation context from. @param ctx Context string for debug logging. */ class Wsrep_applier_service; Wsrep_applier_service* wsrep_create_streaming_applier(THD *orig_thd, const char *ctx); /** Helper method to create new storage service. @param orig_thd Original thd context to copy operation context from. @param ctx Context string for debug logging. */ class Wsrep_storage_service; Wsrep_storage_service* wsrep_create_storage_service(THD *orig_thd, const char *ctx); /** Suppress all error logging from wsrep/Galera library. */ void wsrep_suppress_error_logging(); #endif /* WSREP_SERVER_SERVICE */ source_revision.h 0000644 00000000103 15156036167 0010137 0 ustar 00 #define SOURCE_REVISION "054a893f1645b77e52a329a7fc8cf614eebd1fad" sql_db.h 0000644 00000004432 15156036167 0006176 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_DB_INCLUDED #define SQL_DB_INCLUDED #include "hash.h" /* HASH */ class THD; int mysql_create_db(THD *thd, const Lex_ident_db &db, DDL_options_st options, const Schema_specification_st *create); bool mysql_alter_db(THD *thd, const Lex_ident_db &db, const Schema_specification_st *create); bool mysql_rm_db(THD *thd, const Lex_ident_db &db, bool if_exists); bool mysql_upgrade_db(THD *thd, const Lex_ident_db &old_db); uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name, bool force_switch); bool mysql_opt_change_db(THD *thd, const LEX_CSTRING *new_db_name, LEX_STRING *saved_db_name, bool force_switch, bool *cur_db_changed); bool my_dboptions_cache_init(void); void my_dboptions_cache_free(void); bool check_db_dir_existence(const char *db_name); int load_db_opt(THD *thd, const char *path, Schema_specification_st *create); int load_db_opt_by_name(THD *thd, const char *db_name, Schema_specification_st *db_create_info); CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name); bool my_dbopt_init(void); void my_dbopt_cleanup(void); void drop_database_objects(THD *thd, const LEX_CSTRING *path, const LEX_CSTRING *db, bool rm_mysql_schema); my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error); #define MY_DB_OPT_FILE "db.opt" #endif /* SQL_DB_INCLUDED */ event_db_repository.h 0000644 00000007100 15156036167 0011012 0 ustar 00 #ifndef _EVENT_DB_REPOSITORY_H_ #define _EVENT_DB_REPOSITORY_H_ /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @addtogroup Event_Scheduler @{ @file event_db_repository.h Data Dictionary related operations of Event Scheduler. This is a private header file of Events module. Please do not include it directly. All public declarations of Events module should be stored in events.h and event_data_objects.h. */ enum enum_events_table_field { ET_FIELD_DB = 0, ET_FIELD_NAME, ET_FIELD_BODY, ET_FIELD_DEFINER, ET_FIELD_EXECUTE_AT, ET_FIELD_INTERVAL_EXPR, ET_FIELD_TRANSIENT_INTERVAL, ET_FIELD_CREATED, ET_FIELD_MODIFIED, ET_FIELD_LAST_EXECUTED, ET_FIELD_STARTS, ET_FIELD_ENDS, ET_FIELD_STATUS, ET_FIELD_ON_COMPLETION, ET_FIELD_SQL_MODE, ET_FIELD_COMMENT, ET_FIELD_ORIGINATOR, ET_FIELD_TIME_ZONE, ET_FIELD_CHARACTER_SET_CLIENT, ET_FIELD_COLLATION_CONNECTION, ET_FIELD_DB_COLLATION, ET_FIELD_BODY_UTF8, ET_FIELD_COUNT /* a cool trick to count the number of fields :) */ }; int events_table_index_read_for_db(THD *thd, TABLE *schema_table, TABLE *event_table); int events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table); class Event_basic; class Event_parse_data; class Event_db_repository { public: Event_db_repository() = default; bool create_event(THD *thd, Event_parse_data *parse_data, bool *event_already_exists); bool update_event(THD *thd, Event_parse_data *parse_data, LEX_CSTRING *new_dbname, LEX_CSTRING *new_name); bool drop_event(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *name, bool drop_if_exists); void drop_schema_events(THD *thd, const LEX_CSTRING *schema); bool find_named_event(const LEX_CSTRING *db, const LEX_CSTRING *name, TABLE *table); bool load_named_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name, Event_basic *et); static bool open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table); bool fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db); bool update_timing_fields_for_event(THD *thd, const LEX_CSTRING *event_db_name, const LEX_CSTRING *event_name, my_time_t last_executed, ulonglong status); public: static bool check_system_tables(THD *thd); private: bool index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table, const char *db); bool table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table); private: /* Prevent use of these */ Event_db_repository(const Event_db_repository &); void operator=(Event_db_repository &); }; /** @} (End of group Event_Scheduler) */ #endif /* _EVENT_DB_REPOSITORY_H_ */ event_data_objects.h 0000644 00000010133 15156036167 0010550 0 ustar 00 #ifndef _EVENT_DATA_OBJECTS_H_ #define _EVENT_DATA_OBJECTS_H_ /* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @addtogroup Event_Scheduler @{ @file event_data_objects.h */ #include "event_parse_data.h" #include "thr_lock.h" /* thr_lock_type */ class Field; class THD; class Time_zone; struct TABLE; void init_scheduler_psi_keys(void); class Event_queue_element_for_exec { public: Event_queue_element_for_exec() : dbname{nullptr, 0}, name{nullptr, 0} {} ~Event_queue_element_for_exec(); bool init(const LEX_CSTRING &dbname, const LEX_CSTRING &name); LEX_CSTRING dbname; LEX_CSTRING name; bool dropped; THD *thd; private: /* Prevent use of these */ Event_queue_element_for_exec(const Event_queue_element_for_exec &); void operator=(Event_queue_element_for_exec &); #ifdef HAVE_PSI_INTERFACE public: PSI_statement_info* get_psi_info() { return & psi_info; } static PSI_statement_info psi_info; #endif }; class Event_basic { protected: MEM_ROOT mem_root; public: LEX_CSTRING dbname; LEX_CSTRING name; LEX_CSTRING definer;// combination of user and host Time_zone *time_zone; Event_basic(); virtual ~Event_basic(); virtual bool load_from_row(THD *thd, TABLE *table) = 0; protected: bool load_string_fields(Field **fields, ...); bool load_time_zone(THD *thd, const LEX_CSTRING *tz_name); }; class Event_queue_element : public Event_basic { public: int on_completion; int status; uint32 originator; my_time_t last_executed; my_time_t execute_at; my_time_t starts; my_time_t ends; bool starts_null; bool ends_null; bool execute_at_null; longlong expression; interval_type interval; bool dropped; uint execution_count; Event_queue_element(); virtual ~Event_queue_element(); virtual bool load_from_row(THD *thd, TABLE *table) override; bool compute_next_execution_time(); void mark_last_executed(THD *thd); }; class Event_timed : public Event_queue_element { Event_timed(const Event_timed &); /* Prevent use of these */ void operator=(Event_timed &); public: LEX_CSTRING body; LEX_CSTRING definer_user; LEX_CSTRING definer_host; LEX_CSTRING comment; ulonglong created; ulonglong modified; sql_mode_t sql_mode; class Stored_program_creation_ctx *creation_ctx; LEX_CSTRING body_utf8; Event_timed(); virtual ~Event_timed(); void init(); virtual bool load_from_row(THD *thd, TABLE *table) override; int get_create_event(THD *thd, String *buf); }; class Event_job_data : public Event_basic { public: LEX_CSTRING body; LEX_CSTRING definer_user; LEX_CSTRING definer_host; sql_mode_t sql_mode; class Stored_program_creation_ctx *creation_ctx; Event_job_data(); virtual bool load_from_row(THD *thd, TABLE *table) override; bool execute(THD *thd, bool drop); private: bool construct_sp_sql(THD *thd, String *sp_sql); bool construct_drop_event_sql(THD *thd, String *sp_sql); Event_job_data(const Event_job_data &); /* Prevent use of these */ void operator=(Event_job_data &); }; /* Compares only the schema part of the identifier */ bool event_basic_db_equal(const LEX_CSTRING *db, Event_basic *et); /* Compares the whole identifier*/ bool event_basic_identifier_equal(const LEX_CSTRING *db, const LEX_CSTRING *name, Event_basic *b); /** @} (End of group Event_Scheduler) */ #endif /* _EVENT_DATA_OBJECTS_H_ */ wsrep_on.h 0000644 00000003266 15156036167 0006572 0 ustar 00 /* Copyright 2022 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #ifndef WSREP_ON_H #define WSREP_ON_H #ifdef WITH_WSREP extern bool WSREP_ON_; extern bool WSREP_PROVIDER_EXISTS_; extern my_bool wsrep_emulate_bin_log; extern ulong wsrep_forced_binlog_format; #define WSREP_ON unlikely(WSREP_ON_) /* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to * avoid compiler warnings (GCC 6 and later) */ #define WSREP_NNULL(thd) \ (WSREP_PROVIDER_EXISTS_ && thd->variables.wsrep_on) #define WSREP(thd) \ (thd && WSREP_NNULL(thd)) #define WSREP_CLIENT_NNULL(thd) \ (WSREP_NNULL(thd) && thd->wsrep_client_thread) #define WSREP_CLIENT(thd) \ (WSREP(thd) && thd->wsrep_client_thread) #define WSREP_EMULATE_BINLOG_NNULL(thd) \ (WSREP_NNULL(thd) && wsrep_emulate_bin_log) #define WSREP_EMULATE_BINLOG(thd) \ (WSREP(thd) && wsrep_emulate_bin_log) #else #define WSREP_ON false #define WSREP(T) (0) #define WSREP_NNULL(T) (0) #define WSREP_EMULATE_BINLOG(thd) (0) #define WSREP_EMULATE_BINLOG_NNULL(thd) (0) #endif #endif datadict.h 0000644 00000003244 15156036167 0006507 0 ustar 00 #ifndef DATADICT_INCLUDED #define DATADICT_INCLUDED /* Copyright (c) 2010, Oracle and/or its affiliates. Copyright (c) 2017 MariaDB corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "handler.h" /* Data dictionary API. */ enum Table_type { TABLE_TYPE_UNKNOWN, TABLE_TYPE_NORMAL, /* Normal table */ TABLE_TYPE_SEQUENCE, TABLE_TYPE_VIEW }; /* Take extra care when using dd_frm_type() - it only checks the .frm file, and it won't work for any engine that supports discovery. Prefer to use ha_table_exists() instead. To check whether it's an frm of a view, use dd_frm_is_view(). */ enum Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name, LEX_CSTRING *partition_engine_name, LEX_CUSTRING *table_version); static inline bool dd_frm_is_view(THD *thd, char *path) { return dd_frm_type(thd, path, NULL, NULL, NULL) == TABLE_TYPE_VIEW; } bool dd_recreate_table(THD *thd, const char *db, const char *table_name); #endif // DATADICT_INCLUDED handle_connections_win.h 0000644 00000001564 15156036167 0011447 0 ustar 00 /* Copyright (c) 2018 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** Handles incoming socket and pipe connections, on Windows. Creates new (THD) connections.. */ extern void handle_connections_win(); extern void network_init_win(); sql_select.h 0000644 00000265730 15156036167 0007102 0 ustar 00 #ifndef SQL_SELECT_INCLUDED #define SQL_SELECT_INCLUDED /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2008, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file @brief classes to use when handling where clause */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "procedure.h" #include "sql_array.h" /* Array */ #include "records.h" /* READ_RECORD */ #include "opt_range.h" /* SQL_SELECT, QUICK_SELECT_I */ #include "filesort.h" #include "cset_narrowing.h" typedef struct st_join_table JOIN_TAB; /* Values in optimize */ #define KEY_OPTIMIZE_EXISTS 1U #define KEY_OPTIMIZE_REF_OR_NULL 2U #define KEY_OPTIMIZE_EQ 4U inline uint get_hash_join_key_no() { return MAX_KEY; } inline bool is_hash_join_key_no(uint key) { return key == MAX_KEY; } typedef struct keyuse_t { TABLE *table; Item *val; /**< or value if no field */ table_map used_tables; uint key, keypart, optimize; key_part_map keypart_map; ha_rows ref_table_rows; /** If true, the comparison this value was created from will not be satisfied if val has NULL 'value'. */ bool null_rejecting; /* !NULL - This KEYUSE was created from an equality that was wrapped into an Item_func_trig_cond. This means the equality (and validity of this KEYUSE element) can be turned on and off. The on/off state is indicted by the pointed value: *cond_guard == TRUE <=> equality condition is on *cond_guard == FALSE <=> equality condition is off NULL - Otherwise (the source equality can't be turned off) */ bool *cond_guard; /* 0..64 <=> This was created from semi-join IN-equality # sj_pred_no. MAX_UINT Otherwise */ uint sj_pred_no; /* If this is NULL than KEYUSE is always enabled. Otherwise it points to the enabling flag for this keyuse (true <=> enabled) */ bool *validity_ref; bool is_for_hash_join() { return is_hash_join_key_no(key); } } KEYUSE; struct KEYUSE_EXT: public KEYUSE { /* This keyuse can be used only when the partial join being extended contains the tables from this table map */ table_map needed_in_prefix; /* The enabling flag for keyuses usable for splitting */ bool validity_var; }; /// Used when finding key fields struct KEY_FIELD { Field *field; Item_bool_func *cond; Item *val; ///< May be empty if diff constant uint level; uint optimize; bool eq_func; /** If true, the condition this struct represents will not be satisfied when val IS NULL. */ bool null_rejecting; bool *cond_guard; /* See KEYUSE::cond_guard */ uint sj_pred_no; /* See KEYUSE::sj_pred_no */ }; #define NO_KEYPART ((uint)(-1)) class store_key; const int NO_REF_PART= uint(-1); typedef struct st_table_ref { bool key_err; /** True if something was read into buffer in join_read_key. */ bool has_record; uint key_parts; ///< num of ... uint key_length; ///< length of key_buff int key; ///< key no uchar *key_buff; ///< value to look for with key uchar *key_buff2; ///< key_buff+key_length store_key **key_copy; // /* Bitmap of key parts which refer to constants. key_copy only has copiers for non-const key parts. */ key_part_map const_ref_part_map; Item **items; ///< val()'s for each keypart /* Array of pointers to trigger variables. Some/all of the pointers may be NULL. The ref access can be used iff for each used key part i, (!cond_guards[i] || *cond_guards[i]) This array is used by subquery code. The subquery code may inject triggered conditions, i.e. conditions that can be 'switched off'. A ref access created from such condition is not valid when at least one of the underlying conditions is switched off (see subquery code for more details) */ bool **cond_guards; /** (null_rejecting & (1<<i)) means the condition is '=' and no matching rows will be produced if items[i] IS NULL (see add_not_null_conds()) */ key_part_map null_rejecting; table_map depend_map; ///< Table depends on these tables. /* null byte position in the key_buf. Used for REF_OR_NULL optimization */ uchar *null_ref_key; /* ref_or_null optimization: number of key part that alternates between the lookup value or NULL (there's only one such part). If we're not using ref_or_null, the value is NO_REF_PART */ uint null_ref_part; /* The number of times the record associated with this key was used in the join. */ ha_rows use_count; /* TRUE <=> disable the "cache" as doing lookup with the same key value may produce different results (because of Index Condition Pushdown) */ bool disable_cache; /* If true, this ref access was constructed from equalities generated by LATERAL DERIVED (aka GROUP BY splitting) optimization */ bool uses_splitting; bool tmp_table_index_lookup_init(THD *thd, KEY *tmp_key, Item_iterator &it, bool value, uint skip= 0); bool is_access_triggered(); } TABLE_REF; /* The structs which holds the join connections and join states */ enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF, JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL, JT_UNIQUE_SUBQUERY, JT_INDEX_SUBQUERY, JT_INDEX_MERGE, JT_HASH, JT_HASH_RANGE, JT_HASH_NEXT, JT_HASH_INDEX_MERGE}; class JOIN; enum enum_nested_loop_state { NESTED_LOOP_KILLED= -2, NESTED_LOOP_ERROR= -1, NESTED_LOOP_OK= 0, NESTED_LOOP_NO_MORE_ROWS= 1, NESTED_LOOP_QUERY_LIMIT= 3, NESTED_LOOP_CURSOR_LIMIT= 4 }; /* Possible sj_strategy values */ enum sj_strategy_enum { SJ_OPT_NONE=0, SJ_OPT_DUPS_WEEDOUT=1, SJ_OPT_LOOSE_SCAN =2, SJ_OPT_FIRST_MATCH =3, SJ_OPT_MATERIALIZE =4, SJ_OPT_MATERIALIZE_SCAN=5 }; /* Values for JOIN_TAB::packed_info */ #define TAB_INFO_HAVE_VALUE 1U #define TAB_INFO_USING_INDEX 2U #define TAB_INFO_USING_WHERE 4U #define TAB_INFO_FULL_SCAN_ON_NULL 8U typedef enum_nested_loop_state (*Next_select_func)(JOIN *, struct st_join_table *, bool); Next_select_func setup_end_select_func(JOIN *join); int rr_sequential(READ_RECORD *info); int read_record_func_for_rr_and_unpack(READ_RECORD *info); Item *remove_pushed_top_conjuncts(THD *thd, Item *cond); Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond, COND_EQUAL **cond_eq, List<Item> &new_conds, Item::cond_result *cond_value); #include "sql_explain.h" /************************************************************************************** * New EXPLAIN structures END *************************************************************************************/ class JOIN_CACHE; class SJ_TMP_TABLE; class JOIN_TAB_RANGE; class AGGR_OP; class Filesort; struct SplM_plan_info; class SplM_opt_info; typedef struct st_join_table { TABLE *table; TABLE_LIST *tab_list; KEYUSE *keyuse; /**< pointer to first used key */ KEY *hj_key; /**< descriptor of the used best hash join key not supported by any index */ SQL_SELECT *select; COND *select_cond; COND *on_precond; /**< part of on condition to check before accessing the first inner table */ QUICK_SELECT_I *quick; /* The value of select_cond before we've attempted to do Index Condition Pushdown. We may need to restore everything back if we first choose one index but then reconsider (see test_if_skip_sort_order() for such scenarios). NULL means no index condition pushdown was performed. */ Item *pre_idx_push_select_cond; /* Pointer to the associated ON expression. on_expr_ref=!NULL except for degenerate joins. Optimization phase: *on_expr_ref!=NULL for tables that are the single tables on the inner side of the outer join (t1 LEFT JOIN t2 ON...) Execution phase: *on_expr_ref!=NULL for tables that are first inner tables within an outer join (which may have multiple tables) */ Item **on_expr_ref; COND_EQUAL *cond_equal; /**< multiple equalities for the on expression */ st_join_table *first_inner; /**< first inner table for including outerjoin */ bool found; /**< true after all matches or null complement */ bool not_null_compl;/**< true before null complement is added */ st_join_table *last_inner; /**< last table for embedding outer join */ st_join_table *first_upper; /**< first inner table for embedding outer join */ st_join_table *first_unmatched; /**< used for optimization purposes only */ /* For join tabs that are inside an SJM bush: root of the bush */ st_join_table *bush_root_tab; /* TRUE <=> This join_tab is inside an SJM bush and is the last leaf tab here */ bool last_leaf_in_bush; /* ptr - this is a bush, and ptr points to description of child join_tab range NULL - this join tab has no bush children */ JOIN_TAB_RANGE *bush_children; /* Special content for EXPLAIN 'Extra' column or NULL if none */ enum explain_extra_tag info; Table_access_tracker *tracker; Table_access_tracker *jbuf_tracker; Time_and_counter_tracker *jbuf_unpack_tracker; Counter_tracker *jbuf_loops_tracker; // READ_RECORD::Setup_func materialize_table; READ_RECORD::Setup_func read_first_record; Next_select_func next_select; READ_RECORD read_record; /* Currently the following two fields are used only for a [NOT] IN subquery if it is executed by an alternative full table scan when the left operand of the subquery predicate is evaluated to NULL. */ READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */ READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */ key_map const_keys; /**< Keys with constant part */ key_map checked_keys; /**< Keys checked in find_best */ key_map needed_reg; key_map keys; /**< all keys with can be used */ /* Either #rows in the table or 1 for const table. */ ha_rows records; /* Number of records that will be scanned (yes scanned, not returned) by the best 'independent' access method, i.e. table scan or QUICK_*_SELECT) */ ha_rows found_records; /* Cost of accessing the table using "ALL" or range/index_merge access method (but not 'index' for some reason), i.e. this matches method which E(#records) is in found_records. */ double read_time; /* Copy of POSITION::records_init, set by get_best_combination() */ double records_init; /* Copy of POSITION::records_read, set by get_best_combination() */ double records_read; /* Copy of POSITION::records_out, set by get_best_combination() */ double records_out; /* Copy of POSITION::read_time, set by get_best_combination(). The cost of accessing the table in course of the join execution. */ double join_read_time; double join_loops; /* The selectivity of the conditions that can be pushed to the table */ double cond_selectivity; /* Startup cost for execution */ double startup_cost; double partial_join_cardinality; /* set by estimate_scan_time() */ double cached_scan_and_compare_time; ALL_READ_COST cached_scan_and_compare_cost; /* Used with force_index_join */ ALL_READ_COST cached_forced_index_cost; /* dependent is the table that must be read before the current one Used for example with STRAIGHT_JOIN or outer joins */ table_map dependent; /* key_dependent is dependent but add those tables that are used to compare with a key field in a simple expression. See add_key_field(). It is only used to prune searches in best_extension_by_limited_search() */ table_map key_dependent; /* Tables that have expression in their attached condition clause that depends on this table. */ table_map related_tables; /* Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra' column, or 0 if there is no info. */ uint packed_info; /* This is set for embedded sub queries. It contains the table map of the outer expression, like 'A' in the following expression: WHERE A in (SELECT ....) */ table_map embedded_dependent; /* 1 - use quick select 2 - use "Range checked for each record" */ uint use_quick; /* Index to use. Note: this is valid only for 'index' access, but not range or ref access. */ uint index; uint status; ///< Save status for cache uint used_fields; uint cached_covering_key; // Set by estimate_scan_time() ulong used_fieldlength; ulong max_used_fieldlength; uint used_blobs; uint used_null_fields; uint used_uneven_bit_fields; uint cached_forced_index; enum join_type type, cached_forced_index_type; /* If first key part is used for any key in 'key_dependent' */ bool key_start_dependent; bool cached_eq_ref_table,eq_ref_table; bool shortcut_for_distinct; bool sorted; bool cached_pfs_batch_update; /* If it's not 0 the number stored this field indicates that the index scan has been chosen to access the table data and we expect to scan this number of rows for the table. */ ha_rows limit; TABLE_REF ref; /* TRUE <=> condition pushdown supports other tables presence */ bool icp_other_tables_ok; /* TRUE <=> condition pushed to the index has to be factored out of the condition pushed to the table */ bool idx_cond_fact_out; bool use_join_cache; /* TRUE <=> it is prohibited to join this table using join buffer */ bool no_forced_join_cache; uint used_join_cache_level; JOIN_CACHE *cache; /* Index condition for BKA access join */ Item *cache_idx_cond; SQL_SELECT *cache_select; AGGR_OP *aggr; JOIN *join; /* Embedding SJ-nest (may be not the direct parent), or NULL if none. This variable holds the result of table pullout. */ TABLE_LIST *emb_sj_nest; /* FirstMatch variables (final QEP) */ struct st_join_table *first_sj_inner_tab; struct st_join_table *last_sj_inner_tab; /* Variables for semi-join duplicate elimination */ SJ_TMP_TABLE *flush_weedout_table; SJ_TMP_TABLE *check_weed_out_table; /* for EXPLAIN only: */ SJ_TMP_TABLE *first_weedout_table; /** reference to saved plan and execution statistics */ Explain_table_access *explain_plan; /* If set, means we should stop join enumeration after we've got the first match and return to the specified join tab. May point to join->join_tab[-1] which means stop join execution after the first match. */ struct st_join_table *do_firstmatch; /* ptr - We're doing a LooseScan, this join tab is the first (i.e. "driving") join tab), and ptr points to the last join tab handled by the strategy. loosescan_match_tab->found_match should be checked to see if the current value group had a match. NULL - Not doing a loose scan on this join tab. */ struct st_join_table *loosescan_match_tab; /* TRUE <=> we are inside LooseScan range */ bool inside_loosescan_range; /* Buffer to save index tuple to be able to skip duplicates */ uchar *loosescan_buf; /* Index used by LooseScan (we store it here separately because ref access stores it in tab->ref.key, while range scan stores it in tab->index, etc) */ uint loosescan_key; /* Length of key tuple (depends on #keyparts used) to store in the above */ uint loosescan_key_len; /* Used by LooseScan. TRUE<=> there has been a matching record combination */ bool found_match; /* Used by DuplicateElimination. tab->table->ref must have the rowid whenever we have a current record. */ int keep_current_rowid; /* NestedOuterJoins: Bitmap of nested joins this table is part of */ nested_join_map embedding_map; /* Tmp table info */ TMP_TABLE_PARAM *tmp_table_param; /* Sorting related info */ Filesort *filesort; SORT_INFO *filesort_result; /* Non-NULL value means this join_tab must do window function computation before reading. */ Window_funcs_computation* window_funcs_step; /** List of topmost expressions in the select list. The *next* JOIN_TAB in the plan should use it to obtain correct values. Same applicable to all_fields. These lists are needed because after tmp tables functions will be turned to fields. These variables are pointing to tmp_fields_list[123]. Valid only for tmp tables and the last non-tmp table in the query plan. @see JOIN::make_aggr_tables_info() */ List<Item> *fields; /** List of all expressions in the select list */ List<Item> *all_fields; /* Pointer to the ref array slice which to switch to before sending records. Valid only for tmp tables. */ Ref_ptr_array *ref_array; /** Number of records saved in tmp table */ ha_rows send_records; /** HAVING condition for checking prior saving a record into tmp table*/ Item *having; /** TRUE <=> remove duplicates on this table. */ bool distinct; /* Semi-join strategy to be used for this join table. This is a copy of POSITION::sj_strategy field. This field is set up by the fix_semijoin_strategies_for_picked_join_order. */ enum sj_strategy_enum sj_strategy; uint n_sj_tables; bool preread_init_done; /* true <=> split optimization has been applied to this materialized table */ bool is_split_derived; /* Bitmap of split materialized derived tables that can be filled just before this join table is to be joined. All parameters of the split derived tables belong to tables preceding this join table. */ table_map split_derived_to_update; /* Cost info to the range filter used when joining this join table (Defined when the best join order has been already chosen) */ Range_rowid_filter_cost_info *range_rowid_filter_info; /* Rowid filter to be used when joining this join table */ Rowid_filter *rowid_filter; /* True if the plan requires a rowid filter and it's not built yet */ bool need_to_build_rowid_filter; bool build_range_rowid_filter(); void clear_range_rowid_filter(); void cleanup(); inline bool is_using_loose_index_scan() { const SQL_SELECT *sel= get_sql_select(); return (sel && sel->quick && (sel->quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); } bool is_using_agg_loose_index_scan () { const SQL_SELECT *sel= get_sql_select(); return (is_using_loose_index_scan() && ((QUICK_GROUP_MIN_MAX_SELECT *)sel->quick)->is_agg_distinct()); } const SQL_SELECT *get_sql_select() { return filesort ? filesort->select : select; } bool is_inner_table_of_semi_join_with_first_match() { return first_sj_inner_tab != NULL; } bool is_inner_table_of_semijoin() { return emb_sj_nest != NULL; } bool is_inner_table_of_outer_join() { return first_inner != NULL; } bool is_single_inner_of_semi_join_with_first_match() { return first_sj_inner_tab == this && last_sj_inner_tab == this; } bool is_single_inner_of_outer_join() { return first_inner == this && first_inner->last_inner == this; } bool is_first_inner_for_outer_join() { return first_inner == this; } bool use_match_flag() { return is_first_inner_for_outer_join() || first_sj_inner_tab == this ; } bool check_only_first_match() { return is_inner_table_of_semi_join_with_first_match() || (is_inner_table_of_outer_join() && table->reginfo.not_exists_optimize); } bool is_last_inner_table() { return (first_inner && first_inner->last_inner == this) || last_sj_inner_tab == this; } /* Check whether the table belongs to a nest of inner tables of an outer join or to a nest of inner tables of a semi-join */ bool is_nested_inner() { if (first_inner && (first_inner != first_inner->last_inner || first_inner->first_upper)) return TRUE; if (first_sj_inner_tab && first_sj_inner_tab != last_sj_inner_tab) return TRUE; return FALSE; } struct st_join_table *get_first_inner_table() { if (first_inner) return first_inner; return first_sj_inner_tab; } void set_select_cond(COND *to, uint line) { DBUG_PRINT("info", ("select_cond changes %p -> %p at line %u tab %p", select_cond, to, line, this)); select_cond= to; } COND *set_cond(COND *new_cond) { COND *tmp_select_cond= select_cond; set_select_cond(new_cond, __LINE__); if (select) select->cond= new_cond; return tmp_select_cond; } void calc_used_field_length(bool max_fl); ulong get_used_fieldlength() { if (!used_fieldlength) calc_used_field_length(FALSE); return used_fieldlength; } ulong get_max_used_fieldlength() { if (!max_used_fieldlength) calc_used_field_length(TRUE); return max_used_fieldlength; } double get_partial_join_cardinality() { return partial_join_cardinality; } bool hash_join_is_possible(); int make_scan_filter(); bool is_ref_for_hash_join() { return is_hash_join_key_no(ref.key); } KEY *get_keyinfo_by_key_no(uint key) { return (is_hash_join_key_no(key) ? hj_key : table->key_info+key); } void estimate_scan_time(); double get_examined_rows(); bool preread_init(); bool pfs_batch_update(); bool is_sjm_nest() { return MY_TEST(bush_children); } /* If this join_tab reads a non-merged semi-join (also called jtbm), return the select's number. Otherwise, return 0. */ int get_non_merged_semijoin_select() const { Item_in_subselect *subq; if (table->pos_in_table_list && (subq= table->pos_in_table_list->jtbm_subselect)) { return subq->unit->first_select()->select_number; } return 0; /* Not a merged semi-join */ } bool access_from_tables_is_allowed(table_map used_tables, table_map sjm_lookup_tables) { table_map used_sjm_lookup_tables= used_tables & sjm_lookup_tables; return !used_sjm_lookup_tables || (emb_sj_nest && !(used_sjm_lookup_tables & ~emb_sj_nest->sj_inner_tables)); } bool keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, KEYUSE *keyuse); void remove_redundant_bnl_scan_conds(); bool save_explain_data(Explain_table_access *eta, table_map prefix_tables, bool distinct, struct st_join_table *first_top_tab); bool use_order() const; ///< Use ordering provided by chosen index? bool sort_table(); bool remove_duplicates(); void partial_cleanup(); void add_keyuses_for_splitting(); SplM_plan_info *choose_best_splitting(uint idx, table_map remaining_tables, const POSITION *join_positions, table_map *spl_pd_boundary); bool fix_splitting(SplM_plan_info *spl_plan, table_map excluded_tables, bool is_const_table); } JOIN_TAB; #include "sql_join_cache.h" enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); enum_nested_loop_state sub_select(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); enum_nested_loop_state sub_select_postjoin_aggr(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); enum_nested_loop_state end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), bool end_of_records); enum_nested_loop_state end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), bool end_of_records); class Semi_join_strategy_picker { public: /* Called when starting to build a new join prefix */ virtual void set_empty() = 0; /* Update internal state after another table has been added to the join prefix */ virtual void set_from_prev(POSITION *prev) = 0; virtual bool check_qep(JOIN *join, uint idx, table_map remaining_tables, const JOIN_TAB *new_join_tab, double *record_count, double *read_time, table_map *handled_fanout, sj_strategy_enum *strategy, POSITION *loose_scan_pos) = 0; virtual void mark_used() = 0; virtual ~Semi_join_strategy_picker() = default; }; /* Duplicate Weedout strategy optimization state */ class Duplicate_weedout_picker : public Semi_join_strategy_picker { /* The first table that the strategy will need to handle */ uint first_dupsweedout_table; /* Tables that we will need to have in the prefix to do the weedout step (all inner and all outer that the involved semi-joins are correlated with) */ table_map dupsweedout_tables; bool is_used; public: void set_empty() override { dupsweedout_tables= 0; first_dupsweedout_table= MAX_TABLES; is_used= FALSE; } void set_from_prev(POSITION *prev) override; bool check_qep(JOIN *join, uint idx, table_map remaining_tables, const JOIN_TAB *new_join_tab, double *record_count, double *read_time, table_map *handled_fanout, sj_strategy_enum *stratey, POSITION *loose_scan_pos) override; void mark_used() override { is_used= TRUE; } friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join); }; class Firstmatch_picker : public Semi_join_strategy_picker { /* Index of the first inner table that we intend to handle with this strategy */ uint first_firstmatch_table; /* Tables that were not in the join prefix when we've started considering FirstMatch strategy. */ table_map first_firstmatch_rtbl; /* Tables that need to be in the prefix before we can calculate the cost of using FirstMatch strategy. */ table_map firstmatch_need_tables; bool is_used; bool in_firstmatch_prefix() { return (first_firstmatch_table != MAX_TABLES); } void invalidate_firstmatch_prefix() { first_firstmatch_table= MAX_TABLES; } public: void set_empty() override { invalidate_firstmatch_prefix(); is_used= FALSE; } void set_from_prev(POSITION *prev) override; bool check_qep(JOIN *join, uint idx, table_map remaining_tables, const JOIN_TAB *new_join_tab, double *record_count, double *read_time, table_map *handled_fanout, sj_strategy_enum *strategy, POSITION *loose_scan_pos) override; void mark_used() override { is_used= TRUE; } friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join); }; class LooseScan_picker : public Semi_join_strategy_picker { public: /* The first (i.e. driving) table we're doing loose scan for */ uint first_loosescan_table; /* Tables that need to be in the prefix before we can calculate the cost of using LooseScan strategy. */ table_map loosescan_need_tables; /* keyno - Planning to do LooseScan on this key. If keyuse is NULL then this is a full index scan, otherwise this is a ref+loosescan scan (and keyno matches the KEUSE's) MAX_KEY - Not doing a LooseScan */ uint loosescan_key; // final (one for strategy instance ) uint loosescan_parts; /* Number of keyparts to be kept distinct */ bool is_used; void set_empty() override { first_loosescan_table= MAX_TABLES; is_used= FALSE; } void set_from_prev(POSITION *prev) override; bool check_qep(JOIN *join, uint idx, table_map remaining_tables, const JOIN_TAB *new_join_tab, double *record_count, double *read_time, table_map *handled_fanout, sj_strategy_enum *strategy, POSITION *loose_scan_pos) override; void mark_used() override { is_used= TRUE; } friend class Loose_scan_opt; friend void best_access_path(JOIN *join, JOIN_TAB *s, table_map remaining_tables, const POSITION *join_positions, uint idx, bool disable_jbuf, double record_count, POSITION *pos, POSITION *loose_scan_pos); friend bool get_best_combination(JOIN *join); friend int setup_semijoin_loosescan(JOIN *join); friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join); }; class Sj_materialization_picker : public Semi_join_strategy_picker { bool is_used; /* The last inner table (valid once we're after it) */ uint sjm_scan_last_inner; /* Tables that we need to have in the prefix to calculate the correct cost. Basically, we need all inner tables and outer tables mentioned in the semi-join's ON expression so we can correctly account for fanout. */ table_map sjm_scan_need_tables; public: void set_empty() override { sjm_scan_need_tables= 0; sjm_scan_last_inner= 0; is_used= FALSE; } void set_from_prev(POSITION *prev) override; bool check_qep(JOIN *join, uint idx, table_map remaining_tables, const JOIN_TAB *new_join_tab, double *record_count, double *read_time, table_map *handled_fanout, sj_strategy_enum *strategy, POSITION *loose_scan_pos) override; void mark_used() override { is_used= TRUE; } friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join); }; class Range_rowid_filter_cost_info; class Rowid_filter; /** Information about a position of table within a join order. Used in join optimization. */ class POSITION { public: /* The table that's put into join order */ JOIN_TAB *table; /* number of rows that will be read from the table */ double records_init; /* Number of rows left after filtering, calculated in best_access_path() In case of use_cond_selectivity > 1 it contains rows after the used rowid filter (if such one exists). If use_cond_selectivity <= 1 it contains the minimum rows of any rowid filtering or records_init if no filter exists. */ double records_after_filter; /* Number of expected rows before applying the full WHERE clause. This includes rowid filter and table->cond_selectivity if use_cond_selectivity > 1. See matching_candidates_in_table(). Should normally not be used. */ double records_read; /* The number of rows after applying the WHERE clause. Same as the "fanout": number of output rows that will be produced (after pushed down selection condition is applied) per each row combination of previous tables. In best_access_path() it is set to the minum number of accepted rows for any possible access method or filter: records_out takes into account table->cond_selectivity, the WHERE clause related to this table calculated in calculate_cond_selectivity_for_table(), and the used rowid filter. After best_access_path() records_out it does not yet take into account the part of the WHERE clause involving preceding tables. records_out is updated in best_extension_by_limited_search() to take these tables into account by calling table_after_join_selectivity(). */ double records_out; /* Values from prev_record_reads call for EQ_REF table*/ double prev_record_reads, identical_keys; /* The selectivity of the pushed down conditions */ double cond_selectivity; /* Cost accessing the table in course of the entire complete join execution, i.e. cost of one access method use (e.g. 'range' or 'ref' scan ) times number the access method will be invoked and checking the WHERE clause. */ double read_time; /* record combinations before this table */ double loops; double prefix_record_count; /* Cost for the join prefix */ double prefix_cost; /* NULL - 'index' or 'range' or 'index_merge' or 'ALL' access is used. Other - [eq_]ref[_or_null] access is used. Pointer to {t.keypart1 = expr} */ KEYUSE *key; /* Cardinality of current partial join ending with this position */ double partial_join_cardinality; /* Info on splitting plan used at this position */ SplM_plan_info *spl_plan; /* If spl_plan is NULL the value of spl_pd_boundary is 0. Otherwise spl_pd_boundary contains the bitmap of the table from the current partial join ending at this position that starts the sub-sequence of tables S from which no conditions are allowed to be used in the plan spl_plan for the split table joined at this position. */ table_map spl_pd_boundary; /* Cost info for the range filter used at this position */ Range_rowid_filter_cost_info *range_rowid_filter_info; /* If ref-based access is used: bitmap of tables this table depends on */ table_map ref_depend_map; /* tables that may help best_access_path() to find a better key */ table_map key_dependent; /* Bitmap of semi-join inner tables that are in the join prefix and for which there's no provision for how to eliminate semi-join duplicates they produce. */ table_map dups_producing_tables; table_map inner_tables_handled_with_other_sjs; Duplicate_weedout_picker dups_weedout_picker; Firstmatch_picker firstmatch_picker; LooseScan_picker loosescan_picker; Sj_materialization_picker sjmat_picker; ulonglong refills; /* Current optimization state: Semi-join strategy to be used for this and preceding join tables. Join optimizer sets this for the *last* join_tab in the duplicate-generating range. That is, in order to interpret this field, one needs to traverse join->[best_]positions array from right to left. When you see a join table with sj_strategy!= SJ_OPT_NONE, some other field (depending on the strategy) tells how many preceding positions this applies to. The values of covered_preceding_positions->sj_strategy must be ignored. */ enum sj_strategy_enum sj_strategy; /* Type of join (EQ_REF, REF etc) */ enum join_type type; /* Valid only after fix_semijoin_strategies_for_picked_join_order() call: if sj_strategy!=SJ_OPT_NONE, this is the number of subsequent tables that are covered by the specified semi-join strategy */ uint n_sj_tables; uint forced_index; // If force_index() is used /* TRUE <=> join buffering will be used. At the moment this is based on *very* imprecise guesses made in best_access_path(). */ bool use_join_buffer; /* True if we can use join_buffer togethere with firstmatch */ bool firstmatch_with_join_buf; POSITION(); }; typedef Bounds_checked_array<Item_null_result*> Item_null_array; typedef struct st_rollup { enum State { STATE_NONE, STATE_INITED, STATE_READY }; State state; Item_null_array null_items; Ref_ptr_array *ref_pointer_arrays; List<Item> *fields; } ROLLUP; class JOIN_TAB_RANGE: public Sql_alloc { public: JOIN_TAB *start; JOIN_TAB *end; }; class Pushdown_query; /** @brief Class to perform postjoin aggregation operations @details The result records are obtained on the put_record() call. The aggrgation process is determined by the write_func, it could be: end_write Simply store all records in tmp table. end_write_group Perform grouping using join->group_fields, records are expected to be sorted. end_update Perform grouping using the key generated on tmp table. Input records aren't expected to be sorted. Tmp table uses the heap engine end_update_unique Same as above, but the engine is myisam. Lazy table initialization is used - the table will be instantiated and rnd/index scan started on the first put_record() call. */ class AGGR_OP :public Sql_alloc { public: JOIN_TAB *join_tab; AGGR_OP(JOIN_TAB *tab) : join_tab(tab), write_func(NULL) {}; enum_nested_loop_state put_record() { return put_record(false); }; /* Send the result of operation further (to a next operation/client) This function is called after all records were put into tmp table. @return return one of enum_nested_loop_state values. */ enum_nested_loop_state end_send(); /** write_func setter */ void set_write_func(Next_select_func new_write_func) { write_func= new_write_func; } private: /** Write function that would be used for saving records in tmp table. */ Next_select_func write_func; enum_nested_loop_state put_record(bool end_of_records); bool prepare_tmp_table(); }; class JOIN :public Sql_alloc { private: JOIN(const JOIN &rhs); /**< not implemented */ JOIN& operator=(const JOIN &rhs); /**< not implemented */ protected: /** The subset of the state of a JOIN that represents an optimized query execution plan. Allows saving/restoring different JOIN plans for the same query. */ class Join_plan_state { public: DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */ POSITION *best_positions; /* Copy of JOIN::best_positions */ /* Copies of the JOIN_TAB::keyuse pointers for each JOIN_TAB. */ KEYUSE **join_tab_keyuse; /* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */ key_map *join_tab_checked_keys; SJ_MATERIALIZATION_INFO **sj_mat_info; my_bool error; public: Join_plan_state(uint tables) : error(0) { keyuse.elements= 0; keyuse.buffer= NULL; keyuse.malloc_flags= 0; best_positions= 0; /* To detect errors */ error= my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME), &best_positions, sizeof(*best_positions) * (tables + 1), &join_tab_keyuse, sizeof(*join_tab_keyuse) * tables, &join_tab_checked_keys, sizeof(*join_tab_checked_keys) * tables, &sj_mat_info, sizeof(sj_mat_info) * tables, NullS) == 0; } Join_plan_state(JOIN *join); ~Join_plan_state() { delete_dynamic(&keyuse); my_free(best_positions); } }; /* Results of reoptimizing a JOIN via JOIN::reoptimize(). */ enum enum_reopt_result { REOPT_NEW_PLAN, /* there is a new reoptimized plan */ REOPT_OLD_PLAN, /* no new improved plan can be found, use the old one */ REOPT_ERROR, /* an irrecovarable error occurred during reoptimization */ REOPT_NONE /* not yet reoptimized */ }; /* Support for plan reoptimization with rewritten conditions. */ enum_reopt_result reoptimize(Item *added_where, table_map join_tables, Join_plan_state *save_to); /* Choose a subquery plan for a table-less subquery. */ bool choose_tableless_subquery_plan(); void handle_implicit_grouping_with_window_funcs(); public: void save_query_plan(Join_plan_state *save_to); void reset_query_plan(); void restore_query_plan(Join_plan_state *restore_from); public: JOIN_TAB *join_tab, **best_ref; /* List of fields that aren't under an aggregate function */ List<Item_field> non_agg_fields; JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs List<JOIN_TAB_RANGE> join_tab_ranges; /* Base tables participating in the join. After join optimization is done, the tables are stored in the join order (but the only really important part is that const tables are first). */ TABLE **table; /** The table which has an index that allows to produce the requried ordering. A special value of 0x1 means that the ordering will be produced by passing 1st non-const table to filesort(). NULL means no such table exists. */ TABLE *sort_by_table; /* If true, there is ORDER BY x LIMIT n clause and for certain join orders, it is possible to short-cut the join execution, i.e. stop it as soon as n output rows were produced. See join_limit_shortcut_is_applicable(). */ bool limit_shortcut_applicable; /* Used during join optimization: if true, we're building a join order that will short-cut join execution as soon as #LIMIT rows are produced. */ bool limit_optimization_mode; /* Number of tables in the join. (In MySQL, it is named 'tables' and is also the number of elements in join->join_tab array. In MariaDB, the latter is not true, so we've renamed the variable) */ uint table_count; uint outer_tables; /**< Number of tables that are not inside semijoin */ uint const_tables; /* Number of tables in the top join_tab array. Normally this matches (join_tab_ranges.head()->end - join_tab_ranges.head()->start). We keep it here so that it is saved/restored with JOIN::restore_tmp. */ uint top_join_tab_count; uint aggr_tables; ///< Number of post-join tmp tables uint send_group_parts; /* This represents the number of items in ORDER BY *after* removing all const items. This is computed before other optimizations take place, such as removal of ORDER BY when it is a prefix of GROUP BY, for example: GROUP BY a, b ORDER BY a This is used when deciding to send rows, by examining the correct number of items in the group_fields list when ORDER BY was previously eliminated. */ uint with_ties_order_count; /* True if the query has GROUP BY. (that is, if group_by != NULL. when DISTINCT is converted into GROUP BY, it will set this, too. It is not clear why we need a separate var from group_list) */ bool group; bool need_distinct; /** Indicates that grouping will be performed on the result set during query execution. This field belongs to query execution. If 'sort_and_group' is set, then the optimizer is going to use on of the following algorithms to resolve GROUP BY. - If one table, sort the table and then calculate groups on the fly. - If more than one table, create a temporary table to hold the join, sort it and then resolve group by on the fly. The 'on the fly' calculation is done in end_send_group() @see make_group_fields, alloc_group_fields, JOIN::exec, setup_end_select_func */ bool sort_and_group; bool first_record,full_join, no_field_update; bool hash_join; bool do_send_rows; table_map const_table_map; /* Tables one is allowed to use in choose_plan(). Either all or set to a mapt of the tables in the materialized semi-join nest */ table_map allowed_tables; /** Bitmap of semijoin tables that the current partial plan decided to materialize and access by lookups */ table_map sjm_lookup_tables; /** Bitmap of semijoin tables that the chosen plan decided to materialize to scan the results of materialization */ table_map sjm_scan_tables; /* Constant tables for which we have found a row (as opposed to those for which we didn't). */ table_map found_const_table_map; /* Tables removed by table elimination. Set to 0 before the elimination. */ table_map eliminated_tables; /* Bitmap of all inner tables from outer joins (set at start of make_join_statistics) */ table_map outer_join; /* Bitmap of tables used in the select list items */ table_map select_list_used_tables; /* Tables that has HA_NON_COMPARABLE_ROWID (does not support rowid) set */ table_map not_usable_rowid_map; /* Tables that have a possiblity to use EQ_ref */ table_map eq_ref_tables; table_map allowed_top_level_tables; ha_rows send_records,found_records, accepted_rows; /* LIMIT for the JOIN operation. When not using aggregation or DISITNCT, this is the same as select's LIMIT clause specifies. Note that this doesn't take sql_calc_found_rows into account. */ ha_rows row_limit; /* How many output rows should be produced after GROUP BY. (if sql_calc_found_rows is used, LIMIT is ignored) */ ha_rows select_limit; /* Number of duplicate rows found in UNION. */ ha_rows duplicate_rows; /** Used to fetch no more than given amount of rows per one fetch operation of server side cursor. The value is checked in end_send and end_send_group in fashion, similar to offset_limit_cnt: - fetch_limit= HA_POS_ERROR if there is no cursor. - when we open a cursor, we set fetch_limit to 0, - on each fetch iteration we add num_rows to fetch to fetch_limit NOTE: currently always HA_POS_ERROR. */ ha_rows fetch_limit; /* Finally picked QEP. This is result of join optimization */ POSITION *best_positions; POSITION *sort_positions; /* Temporary space used by greedy_search */ POSITION *next_sort_position; /* Next free space in sort_positions */ Pushdown_query *pushdown_query; JOIN_TAB *original_join_tab; uint original_table_count; uint sort_space; /******* Join optimization state members start *******/ /* pointer - we're doing optimization for a semi-join materialization nest. NULL - otherwise */ TABLE_LIST *emb_sjm_nest; /* Current join optimization state */ POSITION *positions; /* Bitmap of nested joins embedding the position at the end of the current partial join (valid only during join optimizer run). */ nested_join_map cur_embedding_map; /* Bitmap of inner tables of semi-join nests that have a proper subset of their tables in the current join prefix. That is, of those semi-join nests that have their tables both in and outside of the join prefix. (Note: tables that are constants but have not been pulled out of semi-join nests are not considered part of semi-join nests) */ table_map cur_sj_inner_tables; /* A copy of thd->variables.optimizer_prune_level */ uint prune_level; /* If true, do extra heuristic pruning (enabled based on optimizer_extra_pruning_depth) */ bool extra_heuristic_pruning; #ifndef DBUG_OFF void dbug_verify_sj_inner_tables(uint n_positions) const; int dbug_join_tab_array_size; #endif /* We also maintain a stack of join optimization states in join->positions[] */ /******* Join optimization state members end *******/ /* Tables within complex firstmatch ranges (i.e. those where inner tables are interleaved with outer tables). Join buffering cannot be used for these. */ table_map complex_firstmatch_tables; Next_select_func first_select; /* The cost of best complete join plan found so far during optimization, after optimization phase - cost of picked join order (not taking into account the changes made by test_if_skip_sort_order()). */ double best_read; /* Estimated result rows (fanout) of the join operation. If this is a subquery that is reexecuted multiple times, this value includes the estiamted # of reexecutions. This value is equal to the multiplication of all join->positions[i].records_read of a JOIN. */ double join_record_count; List<Item> *fields; /* Used only for FETCH ... WITH TIES to identify peers. */ List<Cached_item> order_fields; /* Used during GROUP BY operations to identify when a group has changed. */ List<Cached_item> group_fields, group_fields_cache; THD *thd; Item_sum **sum_funcs, ***sum_funcs_end; /** second copy of sumfuncs (for queries with 2 temporary tables */ Item_sum **sum_funcs2, ***sum_funcs_end2; Procedure *procedure; Item *having; Item *tmp_having; ///< To store having when processed temporary table Item *having_history; ///< Store having for explain ORDER *group_list_for_estimates; bool having_is_correlated; ulonglong select_options; /* Bitmap of allowed types of the join caches that can be used for join operations */ uint allowed_join_cache_types; bool allowed_semijoin_with_cache; bool allowed_outer_join_with_cache; /* Maximum level of the join caches that can be used for join operations */ uint max_allowed_join_cache_level; select_result *result; TMP_TABLE_PARAM tmp_table_param; MYSQL_LOCK *lock; /// unit structure (with global parameters) for this select SELECT_LEX_UNIT *unit; /// select that processed SELECT_LEX *select_lex; /** TRUE <=> optimizer must not mark any table as a constant table. This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..): when we optimize the select that reads the results of the union from a temporary table, we must not mark the temp. table as constant because the number of rows in it may vary from one subquery execution to another. */ bool no_const_tables; /* This flag is set if we call no_rows_in_result() as par of end_group(). This is used as a simple speed optimization to avoiding calling restore_no_rows_in_result() in ::reinit() */ bool no_rows_in_result_called; /** This is set if SQL_CALC_ROWS was calculated by filesort() and should be taken from the appropriate JOIN_TAB */ bool filesort_found_rows; bool subq_exit_fl; ROLLUP rollup; ///< Used with rollup bool mixed_implicit_grouping; bool select_distinct; ///< Set if SELECT DISTINCT /** If we have the GROUP BY statement in the query, but the group_list was emptied by optimizer, this flag is TRUE. It happens when fields in the GROUP BY are from constant table */ bool group_optimized_away; /* simple_xxxxx is set if ORDER/GROUP BY doesn't include any references to other tables than the first non-constant table in the JOIN. It's also set if ORDER/GROUP BY is empty. Used for deciding for or against using a temporary table to compute GROUP/ORDER BY. */ bool simple_order, simple_group; /* ordered_index_usage is set if an ordered index access should be used instead of a filesort when computing ORDER/GROUP BY. */ enum { ordered_index_void, // No ordered index avail. ordered_index_group_by, // Use index for GROUP BY ordered_index_order_by // Use index for ORDER BY } ordered_index_usage; /** Is set only in case if we have a GROUP BY clause and no ORDER BY after constant elimination of 'order'. */ bool no_order; /** Is set if we have a GROUP BY and we have ORDER BY on a constant. */ bool skip_sort_order; bool need_tmp; bool hidden_group_fields; /* TRUE if there was full cleunap of the JOIN */ bool cleaned; DYNAMIC_ARRAY keyuse; Item::cond_result cond_value, having_value; /** Impossible where after reading const tables (set in make_join_statistics()) */ bool impossible_where; bool prepared; /* All fields used in the query processing. Initially this is a list of fields from the query's SQL text. Then, ORDER/GROUP BY and Window Function code add columns that need to be saved to be available in the post-group-by context. These extra columns are added to the front, because this->fields_list points to the suffix of this list. */ List<Item> all_fields; ///Above list changed to use temporary table List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3; ///Part, shared with list above, emulate following list List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; /* The original field list as it was passed to mysql_select(). This refers to select_lex->item_list. CAUTION: this list is a suffix of this->all_fields list, that is, it shares elements with that list! */ List<Item> &fields_list; List<Item> procedure_fields_list; int error; ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select COND *conds; // ---"--- Item *conds_history; // store WHERE for explain COND *outer_ref_cond; ///<part of conds containing only outer references COND *pseudo_bits_cond; // part of conds containing special bita TABLE_LIST *tables_list; ///<hold 'tables' parameter of mysql_select List<TABLE_LIST> *join_list; ///< list of joined tables in reverse order COND_EQUAL *cond_equal; COND_EQUAL *having_equal; /* Constant codition computed during optimization, but evaluated during join execution. Typically expensive conditions that should not be evaluated at optimization time. */ Item *exec_const_cond; /* Constant ORDER and/or GROUP expressions that contain subqueries. Such expressions need to evaluated to verify that the subquery indeed returns a single row. The evaluation of such expressions is delayed until query execution. */ List<Item> exec_const_order_group_cond; SQL_SELECT *select; ///<created in optimisation phase JOIN_TAB *return_tab; ///<used only for outer joins /* Used pointer reference for this select. select_lex->ref_pointer_array contains five "slices" of the same length: |========|========|========|========|========| ref_ptrs items0 items1 items2 items3 */ Ref_ptr_array ref_ptrs; // Copy of the initial slice above, to be used with different lists Ref_ptr_array items0, items1, items2, items3; // Used by rollup, to restore ref_ptrs after overwriting it. Ref_ptr_array current_ref_ptrs; const char *zero_result_cause; ///< not 0 if exec must return zero result bool union_part; ///< this subselect is part of union enum join_optimization_state { NOT_OPTIMIZED=0, OPTIMIZATION_IN_PROGRESS=1, OPTIMIZATION_PHASE_1_DONE=2, OPTIMIZATION_DONE=3}; // state of JOIN optimization enum join_optimization_state optimization_state; bool initialized; ///< flag to avoid double init_execution calls Explain_select *explain; enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE, QEP_DELETED} have_query_plan; // if keep_current_rowid=true, whether they should be saved in temporary table bool tmp_table_keep_current_rowid; /* Additional WHERE and HAVING predicates to be considered for IN=>EXISTS subquery transformation of a JOIN object. */ Item *in_to_exists_where; Item *in_to_exists_having; /* Temporary tables used to weed-out semi-join duplicates */ List<TABLE> sj_tmp_tables; /* SJM nests that are executed with SJ-Materialization strategy */ List<SJ_MATERIALIZATION_INFO> sjm_info_list; /** Exec time only: TRUE <=> current group has been sent */ bool group_sent; /** TRUE if the query contains an aggregate function but has no GROUP BY clause. */ bool implicit_grouping; bool with_two_phase_optimization; /* Saved execution plan for this join */ Join_plan_state *save_qep; /* Info on splittability of the table materialized by this plan*/ SplM_opt_info *spl_opt_info; /* Contains info on keyuses usable for splitting */ Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting; JOIN_TAB *sort_and_group_aggr_tab; /* Flag is set to true if select_lex was found to be degenerated before the optimize_cond() call in JOIN::optimize_inner() method. */ bool is_orig_degenerated; JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, select_result *result_arg) :fields_list(fields_arg) { init(thd_arg, fields_arg, select_options_arg, result_arg); } void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, select_result *result_arg); /* True if the plan guarantees that it will be returned zero or one row */ bool only_const_tables() { return const_tables == table_count; } /* Number of tables actually joined at the top level */ uint exec_join_tab_cnt() { return tables_list ? top_join_tab_count : 0; } /* Number of tables in the join which also includes the temporary tables created for GROUP BY, DISTINCT , WINDOW FUNCTION etc. */ uint total_join_tab_cnt() { return exec_join_tab_cnt() + aggr_tables - 1; } int prepare(TABLE_LIST *tables, COND *conds, uint og_num, ORDER *order, bool skip_order_by, ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit); bool prepare_stage2(); int optimize(); int optimize_inner(); int optimize_stage2(); int optimize_stage2_and_finish(); bool build_explain(); int reinit(); int init_execution(); int exec() __attribute__((warn_unused_result)); int exec_inner(); bool prepare_result(List<Item> **columns_list); int destroy(); void restore_tmp(); bool alloc_func_list(); bool flatten_subqueries(); bool optimize_unflattened_subqueries(); bool make_range_rowid_filters(); bool init_range_rowid_filters(); bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields, bool before_group_by); /// Initialzes a slice, see comments for ref_ptrs above. Ref_ptr_array ref_ptr_array_slice(size_t slice_num) { size_t slice_sz= select_lex->ref_pointer_array.size() / 5U; DBUG_ASSERT(select_lex->ref_pointer_array.size() % 5 == 0); DBUG_ASSERT(slice_num < 5U); return Ref_ptr_array(&select_lex->ref_pointer_array[slice_num * slice_sz], slice_sz); } /** Overwrites one slice with the contents of another slice. In the normal case, dst and src have the same size(). However: the rollup slices may have smaller size than slice_sz. */ void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr) { DBUG_ASSERT(dst_arr.size() >= src_arr.size()); if (src_arr.size() == 0) return; void *dest= dst_arr.array(); const void *src= src_arr.array(); memcpy(dest, src, src_arr.size() * src_arr.element_size()); } /// Overwrites 'ref_ptrs' and remembers the source as 'current'. void set_items_ref_array(Ref_ptr_array src_arr) { copy_ref_ptr_array(ref_ptrs, src_arr); current_ref_ptrs= src_arr; } /// Initializes 'items0' and remembers that it is 'current'. void init_items_ref_array() { items0= ref_ptr_array_slice(1); copy_ref_ptr_array(items0, ref_ptrs); current_ref_ptrs= items0; } bool rollup_init(); bool rollup_process_const_fields(); bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, Item_sum ***func); int rollup_send_data(uint idx); int rollup_write_data(uint idx, TMP_TABLE_PARAM *tmp_table_param, TABLE *table); void join_free(); /** Cleanup this JOIN, possibly for reuse */ void cleanup(bool full); void clear(table_map *cleared_tables); void inline clear_sum_funcs(); bool send_row_on_empty_set() { return (do_send_rows && implicit_grouping && !group_optimized_away && having_value != Item::COND_FALSE); } bool empty_result() { return (zero_result_cause && !implicit_grouping); } bool change_result(select_result *new_result, select_result *old_result); bool is_top_level_join() const { return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex)); } void cache_const_exprs(); inline table_map all_tables_map() { return (table_map(1) << table_count) - 1; } void drop_unused_derived_keys(); bool get_best_combination(); bool add_sorting_to_table(JOIN_TAB *tab, ORDER *order); inline void eval_select_list_used_tables(); /* Return the table for which an index scan can be used to satisfy the sort order needed by the ORDER BY/(implicit) GROUP BY clause */ JOIN_TAB *get_sort_by_join_tab() { return (need_tmp || !sort_by_table || skip_sort_order || ((group || tmp_table_param.sum_func_count) && !group_list)) ? NULL : join_tab+const_tables; } bool setup_subquery_caches(); bool shrink_join_buffers(JOIN_TAB *jt, ulonglong curr_space, ulonglong needed_space); void set_allowed_join_cache_types(); bool is_allowed_hash_join_access() { return MY_TEST(allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) && max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT; } /* Check if we need to create a temporary table. This has to be done if all tables are not already read (const tables) and one of the following conditions holds: - We are using DISTINCT (simple distinct's are already optimized away) - We are using an ORDER BY or GROUP BY on fields not in the first table - We are using different ORDER BY and GROUP BY orders - The user wants us to buffer the result. - We are using WINDOW functions. When the WITH ROLLUP modifier is present, we cannot skip temporary table creation for the DISTINCT clause just because there are only const tables. */ bool test_if_need_tmp_table() { return ((const_tables != table_count && ((select_distinct || !simple_order || !simple_group) || (group_list && order) || MY_TEST(select_options & OPTION_BUFFER_RESULT))) || (rollup.state != ROLLUP::STATE_NONE && select_distinct) || select_lex->have_window_funcs()); } bool choose_subquery_plan(table_map join_tables); void get_partial_cost_and_fanout(int end_tab_idx, table_map filter_map, double *read_time_arg, double *record_count_arg); void get_prefix_cost_and_fanout(uint n_tables, double *read_time_arg, double *record_count_arg); double get_examined_rows(); /* defined in opt_subselect.cc */ bool transform_max_min_subquery(); /* True if this JOIN is a subquery under an IN predicate. */ bool is_in_subquery() { return (unit->item && unit->item->is_in_predicate()); } bool save_explain_data(Explain_query *output, bool can_overwrite, bool need_tmp_table, bool need_order, bool distinct); int save_explain_data_intern(Explain_query *output, bool need_tmp_table, bool need_order, bool distinct, const char *message); JOIN_TAB *first_breadth_first_tab() { return join_tab; } bool check_two_phase_optimization(THD *thd); bool inject_cond_into_where(Item *injected_cond); bool check_for_splittable_materialized(); void add_keyuses_for_splitting(); bool inject_best_splitting_cond(table_map remaining_tables); bool fix_all_splittings_in_plan(); bool inject_splitting_cond_for_all_tables_with_split_opt(); void make_notnull_conds_for_range_scans(); bool transform_in_predicates_into_in_subq(THD *thd); bool optimize_upper_rownum_func(); void calc_allowed_top_level_tables(SELECT_LEX *lex); table_map get_allowed_nj_tables(uint idx); private: /** Create a temporary table to be used for processing DISTINCT/ORDER BY/GROUP BY. @note Will modify JOIN object wrt sort/group attributes @param tab the JOIN_TAB object to attach created table to @param tmp_table_fields List of items that will be used to define column types of the table. @param tmp_table_group Group key to use for temporary table, NULL if none. @param save_sum_fields If true, do not replace Item_sum items in @c tmp_fields list with Item_field items referring to fields in temporary table. @returns false on success, true on failure */ bool create_postjoin_aggr_table(JOIN_TAB *tab, List<Item> *tmp_table_fields, ORDER *tmp_table_group, bool save_sum_fields, bool distinct, bool keep_row_ordermake); /** Optimize distinct when used on a subset of the tables. E.g.,: SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b In this case we can stop scanning t2 when we have found one t1.a */ void optimize_distinct(); void cleanup_item_list(List<Item> &items) const; bool add_having_as_table_cond(JOIN_TAB *tab); bool make_aggr_tables_info(); bool add_fields_for_current_rowid(JOIN_TAB *cur, List<Item> *fields); void free_pushdown_handlers(List<TABLE_LIST>& join_list); void init_join_cache_and_keyread(); bool prepare_sum_aggregators(THD *thd,Item_sum **func_ptr, bool need_distinct); bool transform_in_predicates_into_equalities(THD *thd); bool transform_date_conds_into_sargable(); bool transform_all_conds_and_on_exprs(THD *thd, Item_transformer transformer); bool transform_all_conds_and_on_exprs_in_join_list(THD *thd, List<TABLE_LIST> *join_list, Item_transformer transformer); }; enum enum_with_bush_roots { WITH_BUSH_ROOTS, WITHOUT_BUSH_ROOTS}; enum enum_with_const_tables { WITH_CONST_TABLES, WITHOUT_CONST_TABLES}; JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_bush_roots include_bush_roots, enum enum_with_const_tables const_tbls); JOIN_TAB *next_linear_tab(JOIN* join, JOIN_TAB* tab, enum enum_with_bush_roots include_bush_roots); JOIN_TAB *first_top_level_tab(JOIN *join, enum enum_with_const_tables with_const); JOIN_TAB *next_top_level_tab(JOIN *join, JOIN_TAB *tab); typedef struct st_select_check { uint const_ref,reg_ref; } SELECT_CHECK; extern const char *join_type_str[]; /* Extern functions in sql_select.cc */ void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, List<Item> &fields, bool reset_with_sum_func); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, Ref_ptr_array ref_pointer_array, List<Item> &new_list1, List<Item> &new_list2, uint elements, List<Item> &fields); void copy_fields(TMP_TABLE_PARAM *param); bool copy_funcs(Item **func_ptr, const THD *thd); uint find_shortest_key(TABLE *table, const key_map *usable_keys); bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args); /* functions from opt_sum.cc */ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order); int opt_sum_query(THD* thd, List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds); /* from sql_delete.cc, used by opt_range.cc */ extern "C" int refpos_order_cmp(void *arg, const void *a,const void *b); /** class to copying an field/item to a key struct */ class store_key :public Sql_alloc { public: bool null_key; /* TRUE <=> the value of the key has a null part */ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; enum Type { FIELD_STORE_KEY, ITEM_STORE_KEY, CONST_ITEM_STORE_KEY }; store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length) :null_key(0), null_ptr(null), err(0) { to_field=field_arg->new_key_field(thd->mem_root, field_arg->table, ptr, length, null, 1); } store_key(store_key &arg) :Sql_alloc(), null_key(arg.null_key), to_field(arg.to_field), null_ptr(arg.null_ptr), err(arg.err) {} virtual ~store_key() = default; /** Not actually needed */ virtual enum Type type() const=0; virtual const char *name() const=0; virtual bool store_key_is_const() { return false; } /** @brief sets ignore truncation warnings mode and calls the real copy method @details this function makes sure truncation warnings when preparing the key buffers don't end up as errors (because of an enclosing INSERT/UPDATE). */ enum store_key_result copy(THD *thd) { enum_check_fields org_count_cuted_fields= thd->count_cuted_fields; Use_relaxed_field_copy urfc(to_field->table->in_use); /* If needed, perform CharsetNarrowing for making ref access lookup keys. */ Utf8_narrow do_narrow(to_field, do_cset_narrowing); store_key_result result= copy_inner(); do_narrow.stop(); thd->count_cuted_fields= org_count_cuted_fields; return result; } protected: Field *to_field; // Store data here uchar *null_ptr; uchar err; /* This is set to true if we need to do Charset Narrowing when making a lookup key. */ bool do_cset_narrowing= false; virtual enum store_key_result copy_inner()=0; }; class store_key_field: public store_key { Copy_field copy_field; const char *field_name; public: store_key_field(THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Field *from_field, const char *name_arg) :store_key(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err : (uchar*) 0, length), field_name(name_arg) { if (to_field) { copy_field.set(to_field,from_field,0); setup_charset_narrowing(); } } enum Type type() const override { return FIELD_STORE_KEY; } const char *name() const override { return field_name; } void change_source_field(Item_field *fld_item) { copy_field.set(to_field, fld_item->field, 0); field_name= fld_item->full_name(); setup_charset_narrowing(); } /* Setup CharsetNarrowing if necessary */ void setup_charset_narrowing() { do_cset_narrowing= Utf8_narrow::should_do_narrowing(copy_field.to_field, copy_field.from_field->charset()); } protected: enum store_key_result copy_inner() override { TABLE *table= copy_field.to_field->table; MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); /* It looks like the next statement is needed only for a simplified hash function over key values used now in BNLH join. When the implementation of this function will be replaced for a proper full version this statement probably should be removed. */ bzero(copy_field.to_ptr,copy_field.to_length); copy_field.do_copy(©_field); dbug_tmp_restore_column_map(&table->write_set, old_map); null_key= to_field->is_null(); return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } }; class store_key_item :public store_key { protected: Item *item; /* Flag that forces usage of save_val() method which save value of the item instead of save_in_field() method which saves result. */ bool use_value; public: store_key_item(THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Item *item_arg, bool val) :store_key(thd, to_field_arg, ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null() ? &err : (uchar*) 0, length), item(item_arg), use_value(val) { /* Setup CharsetNarrowing to be done if necessary */ do_cset_narrowing= Utf8_narrow::should_do_narrowing(to_field, item->collation.collation); } store_key_item(store_key &arg, Item *new_item, bool val) :store_key(arg), item(new_item), use_value(val) {} enum Type type() const override { return ITEM_STORE_KEY; } const char *name() const override { return "func"; } protected: enum store_key_result copy_inner() override { TABLE *table= to_field->table; MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); int res= FALSE; /* It looks like the next statement is needed only for a simplified hash function over key values used now in BNLH join. When the implementation of this function will be replaced for a proper full version this statement probably should be removed. */ to_field->reset(); if (use_value) item->save_val(to_field); else res= item->save_in_field(to_field, 1); /* Item::save_in_field() may call Item::val_xxx(). And if this is a subquery we need to check for errors executing it and react accordingly */ if (!res && table->in_use->is_error()) res= 1; /* STORE_KEY_FATAL */ dbug_tmp_restore_column_map(&table->write_set, old_map); null_key= to_field->is_null() || item->null_value; return ((err != 0 || res < 0 || res > 2) ? STORE_KEY_FATAL : (store_key_result) res); } }; class store_key_const_item :public store_key_item { bool inited; public: store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Item *item_arg) :store_key_item(thd, to_field_arg, ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null() ? &err : (uchar*) 0, length, item_arg, FALSE), inited(0) { } store_key_const_item(store_key &arg, Item *new_item) :store_key_item(arg, new_item, FALSE), inited(0) {} enum Type type() const override { return CONST_ITEM_STORE_KEY; } const char *name() const override { return "const"; } bool store_key_is_const() override { return true; } protected: enum store_key_result copy_inner() override { int res; if (!inited) { inited=1; TABLE *table= to_field->table; MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); if ((res= item->save_in_field(to_field, 1))) { if (!err) err= res < 0 ? 1 : res; /* 1=STORE_KEY_FATAL */ } /* Item::save_in_field() may call Item::val_xxx(). And if this is a subquery we need to check for errors executing it and react accordingly */ if (!err && to_field->table->in_use->is_error()) err= 1; /* STORE_KEY_FATAL */ dbug_tmp_restore_column_map(&table->write_set, old_map); } null_key= to_field->is_null() || item->null_value; return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } }; void best_access_path(JOIN *join, JOIN_TAB *s, table_map remaining_tables, const POSITION *join_positions, uint idx, bool disable_jbuf, double record_count, POSITION *pos, POSITION *loose_scan_pos); bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref); bool error_if_full_join(JOIN *join); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); int get_quick_record(SQL_SELECT *select); int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List <Item> &all_fields, ORDER *order, bool from_window_spec= false); int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List<Item> &all_fields, ORDER *order, bool *hidden_group_fields, bool from_window_spec= false); bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select, Ref_ptr_array ref_pointer_array); int join_read_key2(THD *thd, struct st_join_table *tab, TABLE *table, struct st_table_ref *table_ref); bool handle_select(THD *thd, LEX *lex, select_result *result, ulonglong setup_tables_done_option); bool mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &list, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulonglong select_type, select_result *result, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); /* General routine to change field->ptr of a NULL-terminated array of Field objects. Useful when needed to call val_int, val_str or similar and the field data is not in table->record[0] but in some other structure. set_key_field_ptr changes all fields of an index using a key_info object. All methods presume that there is at least one field to change. */ class Virtual_tmp_table: public TABLE { /** Destruct collected fields. This method can be called on errors, when we could not make the virtual temporary table completely, e.g. when some of the fields could not be created or added. This is needed to avoid memory leaks, as some fields can be BLOB variants and thus can have String onboard. Strings must be destructed as they store data on the heap (not on MEM_ROOT). */ void destruct_fields() { for (uint i= 0; i < s->fields; i++) { field[i]->free(); delete field[i]; // to invoke the field destructor } s->fields= 0; // safety } protected: /** The number of the fields that are going to be in the table. We remember the number of the fields at init() time, and at open() we check that all of the fields were really added. */ uint m_alloced_field_count; /** Setup field pointers and null-bit pointers. */ void setup_field_pointers(); public: /** Create a new empty virtual temporary table on the thread mem_root. After creation, the caller must: - call init() - populate the table with new fields using add(). - call open(). @param thd - Current thread. */ static void *operator new(size_t size, THD *thd) throw(); static void operator delete(void *ptr, size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *, THD *) throw(){} Virtual_tmp_table(THD *thd) : m_alloced_field_count(0) { reset(); temp_pool_slot= MY_BIT_NONE; in_use= thd; copy_blobs= true; alias.set("", 0, &my_charset_bin); } ~Virtual_tmp_table() { if (s) destruct_fields(); } /** Allocate components for the given number of fields. - fields[] - s->blob_fields[], - bitmaps: def_read_set, def_write_set, tmp_set, eq_join_set, cond_set. @param field_count - The number of fields we plan to add to the table. @returns false - on success. @returns true - on error. */ bool init(uint field_count); /** Add one Field to the end of the field array, update members: s->reclength, s->fields, s->blob_fields, s->null_fuelds. */ bool add(Field *new_field) { DBUG_ASSERT(s->fields < m_alloced_field_count); new_field->init(this); field[s->fields]= new_field; s->reclength+= new_field->pack_length(); if (!(new_field->flags & NOT_NULL_FLAG)) s->null_fields++; if (new_field->flags & BLOB_FLAG) { // Note, s->blob_fields was incremented in Field_blob::Field_blob DBUG_ASSERT(s->blob_fields); DBUG_ASSERT(s->blob_fields <= m_alloced_field_count); s->blob_field[s->blob_fields - 1]= s->fields; } new_field->field_index= s->fields++; return false; } /** Add fields from a Spvar_definition list @returns false - on success. @returns true - on error. */ bool add(List<Spvar_definition> &field_list); /** Open a virtual table for read/write: - Setup end markers in TABLE::field and TABLE_SHARE::blob_fields, - Allocate a buffer in TABLE::record[0]. - Set field pointers (Field::ptr, Field::null_pos, Field::null_bit) to the allocated record. This method is called when all of the fields have been added to the table. After calling this method the table is ready for read and write operations. @return false - on success @return true - on error (e.g. could not allocate the record buffer). */ bool open(); void set_all_fields_to_null() { for (uint i= 0; i < s->fields; i++) field[i]->set_null(); } /** Set all fields from a compatible item list. The number of fields in "this" must be equal to the number of elements in "value". */ bool sp_set_all_fields_from_item_list(THD *thd, List<Item> &items); /** Set all fields from a compatible item. The number of fields in "this" must be the same with the number of elements in "value". */ bool sp_set_all_fields_from_item(THD *thd, Item *value); /** Find a ROW element index by its name Assumes that "this" is used as a storage for a ROW-type SP variable. @param [OUT] idx - the index of the found field is returned here @param [IN] field_name - find a field with this name @return true - on error (the field was not found) @return false - on success (idx[0] was set to the field index) */ bool sp_find_field_by_name(uint *idx, const LEX_CSTRING &name) const; /** Find a ROW element index by its name. If the element is not found, and error is issued. @param [OUT] idx - the index of the found field is returned here @param [IN] var_name - the name of the ROW variable (for error reporting) @param [IN] field_name - find a field with this name @return true - on error (the field was not found) @return false - on success (idx[0] was set to the field index) */ bool sp_find_field_by_name_or_error(uint *idx, const LEX_CSTRING &var_name, const LEX_CSTRING &field_name) const; }; /** Create a reduced TABLE object with properly set up Field list from a list of field definitions. The created table doesn't have a table handler associated with it, has no keys, no group/distinct, no copy_funcs array. The sole purpose of this TABLE object is to use the power of Field class to read/write data to/from table->record[0]. Then one can store the record in any container (RB tree, hash, etc). The table is created in THD mem_root, so are the table's fields. Consequently, if you don't BLOB fields, you don't need to free it. @param thd connection handle @param field_list list of column definitions @return 0 if out of memory, or a TABLE object ready for read and write in case of success */ inline Virtual_tmp_table * create_virtual_tmp_table(THD *thd, List<Spvar_definition> &field_list) { Virtual_tmp_table *table; if (!(table= new(thd) Virtual_tmp_table(thd))) return NULL; /* If "simulate_create_virtual_tmp_table_out_of_memory" debug option is enabled, we now enable "simulate_out_of_memory". This effectively makes table->init() fail on OOM inside multi_alloc_root(). This is done to test that ~Virtual_tmp_table() called from the "delete" below correcly handles OOM. */ DBUG_EXECUTE_IF("simulate_create_virtual_tmp_table_out_of_memory", DBUG_SET("+d,simulate_out_of_memory");); if (table->init(field_list.elements) || table->add(field_list) || table->open()) { delete table; return NULL; } return table; } /** Create a new virtual temporary table consisting of a single field. SUM(DISTINCT expr) and similar numeric aggregate functions use this. @param thd - Current thread @param field - The field that will be added into the table. @return NULL - On error. @return !NULL - A pointer to the created table that is ready for read and write. */ inline TABLE * create_virtual_tmp_table(THD *thd, Field *field) { Virtual_tmp_table *table; DBUG_ASSERT(field); if (!(table= new(thd) Virtual_tmp_table(thd))) return NULL; if (table->init(1) || table->add(field) || table->open()) { delete table; return NULL; } return table; } int test_if_item_cache_changed(List<Cached_item> &list); int join_init_read_record(JOIN_TAB *tab); void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key); inline Item * and_items(THD *thd, Item* cond, Item *item) { return (cond ? (new (thd->mem_root) Item_cond_and(thd, cond, item)) : item); } inline Item * or_items(THD *thd, Item* cond, Item *item) { return (cond ? (new (thd->mem_root) Item_cond_or(thd, cond, item)) : item); } bool choose_plan(JOIN *join, table_map join_tables, TABLE_LIST *emb_sjm_nest); void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab, table_map last_remaining_tables, bool first_alt, uint no_jbuf_before, double *outer_rec_count, double *reopt_cost); Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, bool *inherited_fl); extern bool test_if_ref(Item *, Item_field *left_item,Item *right_item); inline bool optimizer_flag(const THD *thd, ulonglong flag) { return (thd->variables.optimizer_switch & flag); } /* int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 select_options); */ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, ha_rows limit, ha_rows *scanned_limit, bool *need_sort, bool *reverse); ORDER *simple_remove_const(ORDER *order, COND *where); bool const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field= NULL, Item **const_item= NULL); bool cond_is_datetime_is_null(Item *cond); bool cond_has_datetime_is_null(Item *cond); /* Table elimination entry point function */ void eliminate_tables(JOIN *join); /* Index Condition Pushdown entry point function */ void push_index_cond(JOIN_TAB *tab, uint keyno); #define OPT_LINK_EQUAL_FIELDS 1 /* EXPLAIN-related utility functions */ int print_explain_message_line(select_result_sink *result, uint8 options, bool is_analyze, uint select_number, const char *select_type, ha_rows *rows, const char *message); void explain_append_mrr_info(QUICK_RANGE_SELECT *quick, String *res); int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table, key_map possible_keys); void unpack_to_base_table_fields(TABLE *table); /**************************************************************************** Temporary table support for SQL Runtime ***************************************************************************/ #define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128 #define AVG_STRING_LENGTH_TO_PACK_ROWS 64 #define RATIO_TO_PACK_ROWS 2 #define MIN_STRING_LENGTH_TO_PACK_ROWS 10 void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group); TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit, const LEX_CSTRING *alias, bool do_not_open=FALSE, bool keep_row_order= FALSE); TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param, const ST_SCHEMA_TABLE &schema_table, longlong select_options, const LEX_CSTRING &alias, bool do_not_open, bool keep_row_order); void free_tmp_table(THD *thd, TABLE *entry); bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, TMP_ENGINE_COLUMNDEF *start_recinfo, TMP_ENGINE_COLUMNDEF **recinfo, int error, bool ignore_last_dupp_key_error, bool *is_duplicate); bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, TMP_ENGINE_COLUMNDEF *start_recinfo, TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options); bool instantiate_tmp_table(TABLE *table, KEY *keyinfo, TMP_ENGINE_COLUMNDEF *start_recinfo, TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options); bool open_tmp_table(TABLE *table); void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist); void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array); bool sort_and_filter_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse, bool skip_unprefixed_keyparts); struct TMPTABLE_COSTS { double create; double lookup; double write; double avg_io_cost; double cache_hit_ratio; double block_size; }; TMPTABLE_COSTS get_tmp_table_costs(THD *thd, double row_count, uint row_size, bool blobs_used, bool add_row_copy_cost); struct st_cond_statistic { Item *cond; Field *field_arg; ulong positive; }; typedef struct st_cond_statistic COND_STATISTIC; ulong check_selectivity(THD *thd, ulong rows_to_read, TABLE *table, List<COND_STATISTIC> *conds); class Pushdown_query: public Sql_alloc { public: SELECT_LEX *select_lex; bool store_data_in_temp_table; group_by_handler *handler; Item *having; Pushdown_query(SELECT_LEX *select_lex_arg, group_by_handler *handler_arg) : select_lex(select_lex_arg), store_data_in_temp_table(0), handler(handler_arg), having(0) {} ~Pushdown_query() { delete handler; } /* Function that calls the above scan functions */ int execute(JOIN *); }; class derived_handler; class Pushdown_derived: public Sql_alloc { public: TABLE_LIST *derived; derived_handler *handler; Pushdown_derived(TABLE_LIST *tbl, derived_handler *h); int execute(); }; class select_handler; bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b); int test_if_group_changed(List<Cached_item> &list); int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); JOIN_TAB *first_explain_order_tab(JOIN* join); JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab); bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl); bool check_simple_equality(THD *thd, const Item::Context &ctx, Item *left_item, Item *right_item, COND_EQUAL *cond_equal); void propagate_new_equalities(THD *thd, Item *cond, List<Item_equal> *new_equalities, COND_EQUAL *inherited, bool *is_simplifiable_cond); #define PREV_BITS(type, N_BITS) ((type)my_set_bits(N_BITS)) double estimate_post_group_cardinality(JOIN *join, double join_output_card); bool dbug_user_var_equals_str(THD *thd, const char *name, const char *value); #endif /* SQL_SELECT_INCLUDED */ sql_sequence.h 0000644 00000012071 15156036167 0007417 0 ustar 00 /* Copyright (c) 2017, MariaDB corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_SEQUENCE_INCLUDED #define SQL_SEQUENCE_INCLUDED #define seq_field_used_min_value 1 #define seq_field_used_max_value 2 #define seq_field_used_start 4 #define seq_field_used_increment 8 #define seq_field_used_cache 16 #define seq_field_used_cycle 32 #define seq_field_used_restart 64 #define seq_field_used_restart_value 128 /* Field position in sequence table for some fields we refer to directly */ #define NEXT_FIELD_NO 0 #define MIN_VALUE_FIELD_NO 1 #define ROUND_FIELD_NO 7 /** sequence_definition is used when defining a sequence as part of create */ class sequence_definition :public Sql_alloc { public: sequence_definition(): min_value(1), max_value(LONGLONG_MAX-1), start(1), increment(1), cache(1000), round(0), restart(0), cycle(0), used_fields(0) {} longlong reserved_until; longlong min_value; longlong max_value; longlong start; longlong increment; longlong cache; ulonglong round; longlong restart; // alter sequence restart value bool cycle; uint used_fields; // Which fields where used in CREATE bool check_and_adjust(bool set_reserved_until); void store_fields(TABLE *table); void read_fields(TABLE *table); int write_initial_sequence(TABLE *table); int write(TABLE *table, bool all_fields); /* This must be called after sequence data has been updated */ void adjust_values(longlong next_value); inline void print_dbug() { DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld", reserved_until, start, increment, min_value, max_value, cache, round)); } protected: /* The following values are the values from sequence_definition merged with global auto_increment_offset and auto_increment_increment */ longlong real_increment; longlong next_free_value; }; /** SEQUENCE is in charge of managing the sequence values. It's also responsible to generate new values and updating the sequence table (engine=SQL_SEQUENCE) trough it's specialized handler interface. If increment is 0 then the sequence will be using auto_increment_increment and auto_increment_offset variables, just like AUTO_INCREMENT is using. */ class SEQUENCE :public sequence_definition { public: enum seq_init { SEQ_UNINTIALIZED, SEQ_IN_PREPARE, SEQ_IN_ALTER, SEQ_READY_TO_USE }; SEQUENCE(); ~SEQUENCE(); int read_initial_values(TABLE *table); int read_stored_values(TABLE *table); void write_lock(TABLE *table); void write_unlock(TABLE *table); void read_lock(TABLE *table); void read_unlock(TABLE *table); void copy(sequence_definition *seq) { sequence_definition::operator= (*seq); adjust_values(reserved_until); all_values_used= 0; } longlong next_value(TABLE *table, bool second_round, int *error); int set_value(TABLE *table, longlong next_value, ulonglong round_arg, bool is_used); longlong increment_value(longlong value) { if (real_increment > 0) { if (value > max_value - real_increment || value + real_increment > max_value) value= max_value + 1; else value+= real_increment; } else { if (value + real_increment < min_value || value < min_value - real_increment) value= min_value - 1; else value+= real_increment; } return value; } bool all_values_used; seq_init initialized; private: mysql_rwlock_t mutex; }; /** Class to cache last value of NEXT VALUE from the sequence */ class SEQUENCE_LAST_VALUE { public: SEQUENCE_LAST_VALUE(uchar *key_arg, uint length_arg) :key(key_arg), length(length_arg) {} ~SEQUENCE_LAST_VALUE() { my_free((void*) key); } /* Returns 1 if table hasn't been dropped or re-created */ bool check_version(TABLE *table); void set_version(TABLE *table); const uchar *key; uint length; bool null_value; longlong value; uchar table_version[MY_UUID_SIZE]; }; class Create_field; extern bool prepare_sequence_fields(THD *thd, List<Create_field> *fields); extern bool check_sequence_fields(LEX *lex, List<Create_field> *fields, const LEX_CSTRING db, const LEX_CSTRING table_name); extern bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list); #endif /* SQL_SEQUENCE_INCLUDED */ sql_partition_admin.h 0000644 00000013464 15156036167 0010777 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_PARTITION_ADMIN_H #define SQL_PARTITION_ADMIN_H #ifndef WITH_PARTITION_STORAGE_ENGINE /** Stub class that returns a error if the partition storage engine is not supported. */ class Sql_cmd_partition_unsupported : public Sql_cmd { public: Sql_cmd_partition_unsupported() {} ~Sql_cmd_partition_unsupported() {} /* Override SQLCOM_*, since it is an ALTER command */ virtual enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } bool execute(THD *thd) override; }; class Sql_cmd_alter_table_exchange_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_exchange_partition() {} ~Sql_cmd_alter_table_exchange_partition() {} }; class Sql_cmd_alter_table_analyze_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_analyze_partition() {} ~Sql_cmd_alter_table_analyze_partition() {} }; class Sql_cmd_alter_table_check_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_check_partition() {} ~Sql_cmd_alter_table_check_partition() {} }; class Sql_cmd_alter_table_optimize_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_optimize_partition() {} ~Sql_cmd_alter_table_optimize_partition() {} }; class Sql_cmd_alter_table_repair_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_repair_partition() {} ~Sql_cmd_alter_table_repair_partition() {} }; class Sql_cmd_alter_table_truncate_partition : public Sql_cmd_partition_unsupported { public: Sql_cmd_alter_table_truncate_partition() {} ~Sql_cmd_alter_table_truncate_partition() {} }; #else /** Class that represents the ALTER TABLE t1 ANALYZE PARTITION p statement. */ class Sql_cmd_alter_table_exchange_partition : public Sql_cmd_common_alter_table { public: /** Constructor, used to represent a ALTER TABLE EXCHANGE PARTITION statement. */ Sql_cmd_alter_table_exchange_partition() : Sql_cmd_common_alter_table() {} ~Sql_cmd_alter_table_exchange_partition() = default; bool execute(THD *thd) override; private: bool exchange_partition(THD *thd, TABLE_LIST *, Alter_info *); }; /** Class that represents the ALTER TABLE t1 ANALYZE PARTITION p statement. */ class Sql_cmd_alter_table_analyze_partition : public Sql_cmd_analyze_table { public: /** Constructor, used to represent a ALTER TABLE ANALYZE PARTITION statement. */ Sql_cmd_alter_table_analyze_partition() : Sql_cmd_analyze_table() {} ~Sql_cmd_alter_table_analyze_partition() = default; bool execute(THD *thd) override; /* Override SQLCOM_ANALYZE, since it is an ALTER command */ enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; /** Class that represents the ALTER TABLE t1 CHECK PARTITION p statement. */ class Sql_cmd_alter_table_check_partition : public Sql_cmd_check_table { public: /** Constructor, used to represent a ALTER TABLE CHECK PARTITION statement. */ Sql_cmd_alter_table_check_partition() : Sql_cmd_check_table() {} ~Sql_cmd_alter_table_check_partition() = default; bool execute(THD *thd) override; /* Override SQLCOM_CHECK, since it is an ALTER command */ enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; /** Class that represents the ALTER TABLE t1 OPTIMIZE PARTITION p statement. */ class Sql_cmd_alter_table_optimize_partition : public Sql_cmd_optimize_table { public: /** Constructor, used to represent a ALTER TABLE OPTIMIZE PARTITION statement. */ Sql_cmd_alter_table_optimize_partition() : Sql_cmd_optimize_table() {} ~Sql_cmd_alter_table_optimize_partition() = default; bool execute(THD *thd) override; /* Override SQLCOM_OPTIMIZE, since it is an ALTER command */ enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; /** Class that represents the ALTER TABLE t1 REPAIR PARTITION p statement. */ class Sql_cmd_alter_table_repair_partition : public Sql_cmd_repair_table { public: /** Constructor, used to represent a ALTER TABLE REPAIR PARTITION statement. */ Sql_cmd_alter_table_repair_partition() : Sql_cmd_repair_table() {} ~Sql_cmd_alter_table_repair_partition() = default; bool execute(THD *thd) override; /* Override SQLCOM_REPAIR, since it is an ALTER command */ enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; /** Class that represents the ALTER TABLE t1 TRUNCATE PARTITION p statement. */ class Sql_cmd_alter_table_truncate_partition : public Sql_cmd_truncate_table { public: /** Constructor, used to represent a ALTER TABLE TRUNCATE PARTITION statement. */ Sql_cmd_alter_table_truncate_partition() = default; virtual ~Sql_cmd_alter_table_truncate_partition() = default; bool execute(THD *thd) override; /* Override SQLCOM_TRUNCATE, since it is an ALTER command */ enum_sql_command sql_command_code() const override { return SQLCOM_ALTER_TABLE; } }; #endif /* WITH_PARTITION_STORAGE_ENGINE */ #endif /* SQL_PARTITION_ADMIN_H */ welcome_copyright_notice.h 0000644 00000002652 15156036170 0012012 0 ustar 00 /* Copyright (c) 2011, 2017, Oracle and/or its affiliates. Copyright (c) 2011, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _welcome_copyright_notice_h_ #define _welcome_copyright_notice_h_ #define COPYRIGHT_NOTICE_CURRENT_YEAR "2018" /* This define specifies copyright notice which is displayed by every MySQL program on start, or on help screen. */ #define ORACLE_WELCOME_COPYRIGHT_NOTICE(first_year) \ "Copyright (c) " first_year ", " COPYRIGHT_NOTICE_CURRENT_YEAR \ ", Oracle, MariaDB Corporation Ab and others.\n" #ifdef VER static inline void print_version() { /* NOTE mysql.cc is not using this function! */ printf("%s from %s, client %s for %s (%s)\n", my_progname, MYSQL_SERVER_VERSION, VER, SYSTEM_TYPE, MACHINE_TYPE); } #endif #endif /* _welcome_copyright_notice_h_ */ event_parse_data.h 0000644 00000005523 15156036170 0010232 0 ustar 00 /* Copyright (c) 2008, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _EVENT_PARSE_DATA_H_ #define _EVENT_PARSE_DATA_H_ #include "sql_alloc.h" class Item; class THD; class sp_name; #define EVEX_GET_FIELD_FAILED -2 #define EVEX_BAD_PARAMS -5 #define EVEX_MICROSECOND_UNSUP -6 #define EVEX_MAX_INTERVAL_VALUE 1000000000L class Event_parse_data : public Sql_alloc { public: /* ENABLED = feature can function normally (is turned on) SLAVESIDE_DISABLED = feature is turned off on slave DISABLED = feature is turned off */ enum enum_status { ENABLED = 1, DISABLED, SLAVESIDE_DISABLED }; enum enum_on_completion { /* On CREATE EVENT, DROP is the DEFAULT as per the docs. On ALTER EVENT, "no change" is the DEFAULT. */ ON_COMPLETION_DEFAULT = 0, ON_COMPLETION_DROP, ON_COMPLETION_PRESERVE }; int on_completion; int status; bool status_changed; uint32 originator; /* do_not_create will be set if STARTS time is in the past and on_completion == ON_COMPLETION_DROP. */ bool do_not_create; bool body_changed; LEX_CSTRING dbname; LEX_CSTRING name; LEX_CSTRING definer;// combination of user and host LEX_CSTRING comment; Item* item_starts; Item* item_ends; Item* item_execute_at; my_time_t starts; my_time_t ends; my_time_t execute_at; bool starts_null; bool ends_null; bool execute_at_null; sp_name *identifier; Item* item_expression; longlong expression; interval_type interval; static Event_parse_data * new_instance(THD *thd); bool check_parse_data(THD *thd); bool check_dates(THD *thd, int previous_on_completion); private: void init_definer(THD *thd); void init_name(THD *thd, sp_name *spn); int init_execute_at(THD *thd); int init_interval(THD *thd); int init_starts(THD *thd); int init_ends(THD *thd); Event_parse_data(); ~Event_parse_data(); void report_bad_value(const char *item_name, Item *bad_item); void check_if_in_the_past(THD *thd, my_time_t ltime_utc); Event_parse_data(const Event_parse_data &); /* Prevent use of these */ void check_originator_id(THD *thd); void operator=(Event_parse_data &); }; #endif sql_locale.h 0000644 00000006247 15156036170 0007050 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_LOCALE_INCLUDED #define SQL_LOCALE_INCLUDED typedef struct my_locale_errmsgs { const char *language; const char ***errmsgs; } MY_LOCALE_ERRMSGS; typedef struct st_typelib TYPELIB; class MY_LOCALE { public: uint number; const char *name; const char *description; const bool is_ascii; TYPELIB *month_names; TYPELIB *ab_month_names; TYPELIB *day_names; TYPELIB *ab_day_names; uint max_month_name_length; uint max_day_name_length; uint decimal_point; uint thousand_sep; const char *grouping; MY_LOCALE_ERRMSGS *errmsgs; MY_LOCALE(uint number_par, const char *name_par, const char *descr_par, bool is_ascii_par, TYPELIB *month_names_par, TYPELIB *ab_month_names_par, TYPELIB *day_names_par, TYPELIB *ab_day_names_par, uint max_month_name_length_par, uint max_day_name_length_par, uint decimal_point_par, uint thousand_sep_par, const char *grouping_par, MY_LOCALE_ERRMSGS *errmsgs_par) : number(number_par), name(name_par), description(descr_par), is_ascii(is_ascii_par), month_names(month_names_par), ab_month_names(ab_month_names_par), day_names(day_names_par), ab_day_names(ab_day_names_par), max_month_name_length(max_month_name_length_par), max_day_name_length(max_day_name_length_par), decimal_point(decimal_point_par), thousand_sep(thousand_sep_par), grouping(grouping_par), errmsgs(errmsgs_par) {} my_repertoire_t repertoire() const { return is_ascii ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_EXTENDED; } /* Get a non-abbreviated month name by index @param month - the month index 0..11 */ LEX_CSTRING month_name(uint month) const { if (month > 11) return Lex_cstring("##", 2); return Lex_cstring_strlen(month_names->type_names[month]); } /* Get a non-abbreviated weekday name by index @param weekday - the weekday index 0..6 */ LEX_CSTRING day_name(uint weekday) const { if (weekday > 6) return Lex_cstring("##", 2); return Lex_cstring_strlen(day_names->type_names[weekday]); } }; /* Exported variables */ extern MY_LOCALE my_locale_en_US; extern MYSQL_PLUGIN_IMPORT MY_LOCALE *my_locales[]; extern MY_LOCALE *my_default_lc_messages; extern MY_LOCALE *my_default_lc_time_names; /* Exported functions */ MY_LOCALE *my_locale_by_name(const char *name); MY_LOCALE *my_locale_by_number(uint number); void cleanup_errmsgs(void); #endif /* SQL_LOCALE_INCLUDED */ wsrep_plugin.h 0000644 00000002544 15156036170 0007444 0 ustar 00 /* Copyright 2022 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WSREP_PLUGIN_H #define WSREP_PLUGIN_H class option; struct st_mysql_sys_var; /* Returns true if provider plugin was initialized and is active */ bool wsrep_provider_plugin_enabled(); /* Set the given sysvars array for provider plugin. Must be called before the plugin is initialized. */ void wsrep_provider_plugin_set_sysvars(st_mysql_sys_var **); /* Construct a sysvar corresponding to the given provider option */ struct st_mysql_sys_var * wsrep_make_sysvar_for_option(wsrep::provider_options::option *); /* Destroy a sysvar created by make_sysvar_for_option */ void wsrep_destroy_sysvar(struct st_mysql_sys_var *); #endif /* WSREP_PLUGIN_H */ sql_basic_types.h 0000644 00000022463 15156036170 0010114 0 ustar 00 /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* File that includes common types used globally in MariaDB */ #ifndef SQL_TYPES_INCLUDED #define SQL_TYPES_INCLUDED typedef ulonglong sql_mode_t; typedef int64 query_id_t; enum enum_nullability { NOT_NULL, NULLABLE }; /* "fuzzydate" with strict data type control. Represents a mixture of *only* data type conversion flags, without rounding. Please keep "explicit" in constructors and conversion methods. */ class date_conv_mode_t { public: enum value_t { CONV_NONE= 0U, /* FUZZY_DATES is used for the result will only be used for comparison purposes. Conversion is as relaxed as possible. */ FUZZY_DATES= 1U, TIME_ONLY= 4U, INTERVAL_hhmmssff= 8U, INTERVAL_DAY= 16U, RANGE0_LAST= INTERVAL_DAY, NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES }; /* BIT-OR for all known values. Let's have a separate enum for it. - We don't put this value "value_t", to avoid handling it in switch(). - We don't put this value as a static const inside the class, because "gdb" would display it every time when we do "print" for a time_round_mode_t value. - We can't put into a function returning this value, because it's not allowed to use functions in static_assert. */ enum known_values_t { KNOWN_MODES= FUZZY_DATES | TIME_ONLY | INTERVAL_hhmmssff | INTERVAL_DAY | NO_ZERO_IN_DATE | NO_ZERO_DATE | INVALID_DATES }; private: value_t m_mode; public: // Constructors explicit date_conv_mode_t(ulonglong fuzzydate) :m_mode((value_t) fuzzydate) { } // Conversion operators explicit operator ulonglong() const { return m_mode; } explicit operator bool() const { return m_mode != 0; } // Unary operators ulonglong operator~() const { return ~m_mode; } // Dyadic bitwise operators date_conv_mode_t operator&(const date_conv_mode_t &other) const { return date_conv_mode_t(m_mode & other.m_mode); } date_conv_mode_t operator&(const ulonglong other) const { return date_conv_mode_t(m_mode & other); } date_conv_mode_t operator|(const date_conv_mode_t &other) const { return date_conv_mode_t(m_mode | other.m_mode); } // Dyadic bitwise assignment operators date_conv_mode_t &operator&=(const date_conv_mode_t &other) { m_mode= value_t(m_mode & other.m_mode); return *this; } date_conv_mode_t &operator|=(const date_conv_mode_t &other) { m_mode= value_t(m_mode | other.m_mode); return *this; } }; /* Fractional rounding mode for temporal data types. */ class time_round_mode_t { public: enum value_t { /* Use FRAC_NONE when the value needs no rounding nor truncation, because it is already known not to haveany fractional digits outside of the requested precision. */ FRAC_NONE= 0, FRAC_TRUNCATE= date_conv_mode_t::RANGE0_LAST << 1, // 32 FRAC_ROUND= date_conv_mode_t::RANGE0_LAST << 2 // 64 }; // BIT-OR for all known values. See comments in time_conv_mode_t. enum known_values_t { KNOWN_MODES= FRAC_TRUNCATE | FRAC_ROUND }; private: value_t m_mode; public: // Constructors explicit time_round_mode_t(ulonglong mode) :m_mode((value_t) mode) { #ifdef MYSQL_SERVER DBUG_ASSERT(mode == FRAC_NONE || mode == FRAC_TRUNCATE || mode == FRAC_ROUND); #endif } // Conversion operators explicit operator ulonglong() const { return m_mode; } value_t mode() const { return m_mode; } // Comparison operators bool operator==(const time_round_mode_t &other) { return m_mode == other.m_mode; } }; /* "fuzzydate" with strict data type control. Used as a parameter to get_date() and represents a mixture of: - data type conversion flags - fractional second rounding flags Please keep "explicit" in constructors and conversion methods. */ class date_mode_t { public: enum value_t { CONV_NONE= date_conv_mode_t::CONV_NONE, // 0 FUZZY_DATES= date_conv_mode_t::FUZZY_DATES, // 1 TIME_ONLY= date_conv_mode_t::TIME_ONLY, // 4 INTERVAL_hhmmssff= date_conv_mode_t::INTERVAL_hhmmssff, // 8 INTERVAL_DAY= date_conv_mode_t::INTERVAL_DAY, // 16 FRAC_TRUNCATE= time_round_mode_t::FRAC_TRUNCATE, // 32 FRAC_ROUND= time_round_mode_t::FRAC_ROUND, // 64 NO_ZERO_IN_DATE= date_conv_mode_t::NO_ZERO_IN_DATE, // (1UL << 23) NO_ZERO_DATE= date_conv_mode_t::NO_ZERO_DATE, // (1UL << 24) INVALID_DATES= date_conv_mode_t::INVALID_DATES, // (1UL << 25) }; protected: value_t m_mode; public: // Constructors explicit date_mode_t(ulonglong fuzzydate) :m_mode((value_t) fuzzydate) { } // Conversion operators explicit operator ulonglong() const { return m_mode; } explicit operator bool() const { return m_mode != 0; } explicit operator date_conv_mode_t() const { return date_conv_mode_t(ulonglong(m_mode) & date_conv_mode_t::KNOWN_MODES); } explicit operator time_round_mode_t() const { return time_round_mode_t(ulonglong(m_mode) & time_round_mode_t::KNOWN_MODES); } // Unary operators ulonglong operator~() const { return ~m_mode; } bool operator!() const { return !m_mode; } // Dyadic bitwise operators date_mode_t operator&(const date_mode_t &other) const { return date_mode_t(m_mode & other.m_mode); } date_mode_t operator&(ulonglong other) const { return date_mode_t(m_mode & other); } date_mode_t operator|(const date_mode_t &other) const { return date_mode_t(m_mode | other.m_mode); } // Dyadic bitwise assignment operators date_mode_t &operator&=(const date_mode_t &other) { m_mode= value_t(m_mode & other.m_mode); return *this; } date_mode_t &operator|=(const date_mode_t &other) { m_mode= value_t(m_mode | other.m_mode); return *this; } date_mode_t &operator|=(const date_conv_mode_t &other) { m_mode= value_t(m_mode | ulonglong(other)); return *this; } }; // Bitwise OR out-of-class operators for data type mixtures static inline date_mode_t operator|(const date_mode_t &a, const date_conv_mode_t &b) { return date_mode_t(ulonglong(a) | ulonglong(b)); } static inline date_mode_t operator|(const date_conv_mode_t &a, const time_round_mode_t &b) { return date_mode_t(ulonglong(a) | ulonglong(b)); } static inline date_mode_t operator|(const date_conv_mode_t &a, const date_mode_t &b) { return date_mode_t(ulonglong(a) | ulonglong(b)); } // Bitwise AND out-of-class operators for data type mixtures static inline date_conv_mode_t operator&(const date_mode_t &a, const date_conv_mode_t &b) { return date_conv_mode_t(ulonglong(a) & ulonglong(b)); } static inline date_conv_mode_t operator&(const date_conv_mode_t &a, const date_mode_t &b) { return date_conv_mode_t(ulonglong(a) & ulonglong(b)); } static inline date_conv_mode_t operator&(sql_mode_t &a, const date_conv_mode_t &b) { return date_conv_mode_t(a & ulonglong(b)); } static const date_conv_mode_t TIME_CONV_NONE (date_conv_mode_t::CONV_NONE), TIME_FUZZY_DATES (date_conv_mode_t::FUZZY_DATES), TIME_TIME_ONLY (date_conv_mode_t::TIME_ONLY), TIME_INTERVAL_hhmmssff (date_conv_mode_t::INTERVAL_hhmmssff), TIME_INTERVAL_DAY (date_conv_mode_t::INTERVAL_DAY), TIME_NO_ZERO_IN_DATE (date_conv_mode_t::NO_ZERO_IN_DATE), TIME_NO_ZERO_DATE (date_conv_mode_t::NO_ZERO_DATE), TIME_INVALID_DATES (date_conv_mode_t::INVALID_DATES); // An often used combination static const date_conv_mode_t TIME_NO_ZEROS (date_conv_mode_t::NO_ZERO_DATE| date_conv_mode_t::NO_ZERO_IN_DATE); // Flags understood by str_to_xxx, number_to_xxx, check_date static const date_conv_mode_t TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE | date_mode_t::NO_ZERO_DATE | date_mode_t::INVALID_DATES); static const time_round_mode_t TIME_FRAC_NONE (time_round_mode_t::FRAC_NONE), TIME_FRAC_TRUNCATE (time_round_mode_t::FRAC_TRUNCATE), TIME_FRAC_ROUND (time_round_mode_t::FRAC_ROUND); #endif wqueue.h 0000644 00000003035 15156036170 0006235 0 ustar 00 /* Copyright (c) 2007, 2008, Sun Microsystems, Inc, Copyright (c) 2011, 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef WQUEUE_INCLUDED #define WQUEUE_INCLUDED #include <my_pthread.h> /* info about requests in a waiting queue */ typedef struct st_pagecache_wqueue { struct st_my_thread_var *last_thread; /* circular list of waiting threads */ } WQUEUE; void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); void wqueue_add_and_wait(WQUEUE *wqueue, struct st_my_thread_var *thread, mysql_mutex_t *lock); void wqueue_release_queue(WQUEUE *wqueue); void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue); #endif sp_head.h 0000644 00000115160 15156036170 0006330 0 ustar 00 /* -*- C++ -*- */ /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. Copyright (c) 2020, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_HEAD_H_ #define _SP_HEAD_H_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif /* It is necessary to include set_var.h instead of item.h because there are dependencies on include order for set_var.h and item.h. This will be resolved later. */ #include "sql_class.h" // THD, set_var.h: THD #include "set_var.h" // Item #include "sp_pcontext.h" // sp_pcontext #include <stddef.h> #include "sp.h" /** @defgroup Stored_Routines Stored Routines @ingroup Runtime_Environment @{ */ uint sp_get_flags_for_command(LEX *lex); class sp_instr; class sp_instr_opt_meta; class sp_instr_jump_if_not; /** Number of PSI_statement_info instruments for internal stored programs statements. */ #ifdef HAVE_PSI_INTERFACE void init_sp_psi_keys(void); #endif /*************************************************************************/ /** Stored_program_creation_ctx -- base class for creation context of stored programs (stored routines, triggers, events). */ class Stored_program_creation_ctx :public Default_object_creation_ctx { public: CHARSET_INFO *get_db_cl() { return m_db_cl; } public: virtual Stored_program_creation_ctx *clone(MEM_ROOT *mem_root) = 0; protected: Stored_program_creation_ctx(THD *thd) : Default_object_creation_ctx(thd), m_db_cl(thd->variables.collation_database) { } Stored_program_creation_ctx(CHARSET_INFO *client_cs, CHARSET_INFO *connection_cl, CHARSET_INFO *db_cl) : Default_object_creation_ctx(client_cs, connection_cl), m_db_cl(db_cl) { } protected: void change_env(THD *thd) const override { thd->variables.collation_database= m_db_cl; Default_object_creation_ctx::change_env(thd); } protected: /** db_cl stores the value of the database collation. Both character set and collation attributes are used. Database collation is included into the context because it defines the default collation for stored-program variables. */ CHARSET_INFO *m_db_cl; }; /*************************************************************************/ class sp_name : public Sql_alloc, public Database_qualified_name { public: bool m_explicit_name; /**< Prepend the db name? */ sp_name(const LEX_CSTRING *db, const LEX_CSTRING *name, bool use_explicit_name) : Database_qualified_name(db, name), m_explicit_name(use_explicit_name) { if (lower_case_table_names && m_db.length) m_db.length= my_casedn_str(files_charset_info, (char*) m_db.str); } /** Create temporary sp_name object from MDL key. Store in qname_buff */ sp_name(const MDL_key *key, char *qname_buff); ~sp_name() = default; }; bool check_routine_name(const LEX_CSTRING *ident); class sp_head :private Query_arena, public Database_qualified_name, public Sql_alloc { sp_head(const sp_head &)= delete; void operator=(sp_head &)= delete; protected: MEM_ROOT main_mem_root; #ifdef PROTECT_STATEMENT_MEMROOT /* The following data member is wholly for debugging purpose. It can be used for possible crash analysis to determine how many times the stored routine was executed before the mem_root marked read_only was requested for a memory chunk. Additionally, a value of this data member is output to the log with DBUG_PRINT. */ ulong executed_counter; #endif public: /** Possible values of m_flags */ enum { HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE IS_INVOKED= 32, // Is set if this sp_head is being used HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit' /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ HAS_COMMIT_OR_ROLLBACK= 128, LOG_SLOW_STATEMENTS= 256, // Used by events LOG_GENERAL_LOG= 512, // Used by events HAS_SQLCOM_RESET= 1024, HAS_SQLCOM_FLUSH= 2048, /** Marks routines that directly (i.e. not by calling other routines) change tables. Note that this flag is set automatically based on type of statements used in the stored routine and is different from routine characteristic provided by user in a form of CONTAINS SQL, READS SQL DATA, MODIFIES SQL DATA clauses. The latter are accepted by parser but pretty much ignored after that. We don't rely on them: a) for compatibility reasons. b) because in CONTAINS SQL case they don't provide enough information anyway. */ MODIFIES_DATA= 4096, /* Marks routines that have column type references: DECLARE a t1.a%TYPE; */ HAS_COLUMN_TYPE_REFS= 8192, /* Set if has FETCH GROUP NEXT ROW instr. Used to ensure that only functions with AGGREGATE keyword use the instr. */ HAS_AGGREGATE_INSTR= 16384 }; sp_package *m_parent; const Sp_handler *m_handler; uint m_flags; // Boolean attributes of a stored routine /** Instrumentation interface for SP. */ PSI_sp_share *m_sp_share; Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */ const char *m_tmp_query; ///< Temporary pointer to sub query string private: /* Private to guarantee that m_chistics.comment is properly set to: - a string which is alloced on this->mem_root - or (NULL,0) set_chistics() makes sure this. */ Sp_chistics m_chistics; void set_chistics(const st_sp_chistics &chistics); inline void set_chistics_agg_type(enum enum_sp_aggregate_type type) { m_chistics.agg_type= type; } public: sql_mode_t m_sql_mode; ///< For SHOW CREATE and execution bool m_explicit_name; /**< Prepend the db name? */ LEX_CSTRING m_qname; ///< db.name LEX_CSTRING m_params; LEX_CSTRING m_body; LEX_CSTRING m_body_utf8; LEX_CSTRING m_defstr; AUTHID m_definer; const st_sp_chistics &chistics() const { return m_chistics; } const LEX_CSTRING &comment() const { return m_chistics.comment; } void set_suid(enum_sp_suid_behaviour suid) { m_chistics.suid= suid; } enum_sp_suid_behaviour suid() const { return m_chistics.suid; } bool detistic() const { return m_chistics.detistic; } enum_sp_data_access daccess() const { return m_chistics.daccess; } enum_sp_aggregate_type agg_type() const { return m_chistics.agg_type; } /** Is this routine being executed? */ virtual bool is_invoked() const { return m_flags & IS_INVOKED; } /** Get the value of the SP cache version, as remembered when the routine was inserted into the cache. */ ulong sp_cache_version() const; /** Set the value of the SP cache version. */ void set_sp_cache_version(ulong version_arg) const { m_sp_cache_version= version_arg; } sp_rcontext *rcontext_create(THD *thd, Field *retval, List<Item> *args); sp_rcontext *rcontext_create(THD *thd, Field *retval, Item **args, uint arg_count); sp_rcontext *rcontext_create(THD *thd, Field *retval, Row_definition_list *list, bool switch_security_ctx); bool eq_routine_spec(const sp_head *) const; private: /** Version of the stored routine cache at the moment when the routine was added to it. Is used only for functions and procedures, not used for triggers or events. When sp_head is created, its version is 0. When it's added to the cache, the version is assigned the global value 'Cversion'. If later on Cversion is incremented, we know that the routine is obsolete and should not be used -- sp_cache_flush_obsolete() will purge it. */ mutable ulong m_sp_cache_version; Stored_program_creation_ctx *m_creation_ctx; /** Boolean combination of (1<<flag), where flag is a member of LEX::enum_binlog_stmt_unsafe. */ uint32 unsafe_flags; bool new_query_arena_is_set; public: inline Stored_program_creation_ctx *get_creation_ctx() { return m_creation_ctx; } inline void set_creation_ctx(Stored_program_creation_ctx *creation_ctx) { m_creation_ctx= creation_ctx->clone(mem_root); } longlong m_created; longlong m_modified; /** Recursion level of the current SP instance. The levels are numbered from 0 */ ulong m_recursion_level; /** A list of diferent recursion level instances for the same procedure. For every recursion level we have a sp_head instance. This instances connected in the list. The list ordered by increasing recursion level (m_recursion_level). */ sp_head *m_next_cached_sp; /** Pointer to the first element of the above list */ sp_head *m_first_instance; /** Pointer to the first free (non-INVOKED) routine in the list of cached instances for this SP. This pointer is set only for the first SP in the list of instences (see above m_first_cached_sp pointer). The pointer equal to 0 if we have no free instances. For non-first instance value of this pointer meanless (point to itself); */ sp_head *m_first_free_instance; /** Pointer to the last element in the list of instances of the SP. For non-first instance value of this pointer meanless (point to itself); */ sp_head *m_last_cached_sp; /** Set containing names of stored routines used by this routine. Note that unlike elements of similar set for statement elements of this set are not linked in one list. Because of this we are able save memory by using for this set same objects that are used in 'sroutines' sets for statements of which this stored routine consists. */ HASH m_sroutines; // Pointers set during parsing const char *m_param_begin; const char *m_param_end; private: /* A pointer to the body start inside the cpp buffer. Used only during parsing. Should be removed eventually. The affected functions/methods should be fixed to get the cpp body start as a parameter, rather than through this member. */ const char *m_cpp_body_begin; public: /* Security context for stored routine which should be run under definer privileges. */ Security_context m_security_ctx; protected: sp_head(MEM_ROOT *mem_root, sp_package *parent, const Sp_handler *handler, enum_sp_aggregate_type agg_type); virtual ~sp_head(); public: static void destroy(sp_head *sp); static sp_head *create(sp_package *parent, const Sp_handler *handler, enum_sp_aggregate_type agg_type, MEM_ROOT *sp_mem_root); /// Initialize after we have reset mem_root void init(LEX *lex); /** Copy sp name from parser. */ bool init_sp_name(const sp_name *spname); /** Set the body-definition start position. */ void set_body_start(THD *thd, const char *cpp_body_start); /** Set the statement-definition (body-definition) end position. */ void set_stmt_end(THD *thd, const char *cpp_body_end); bool execute_trigger(THD *thd, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name, GRANT_INFO *grant_info); bool execute_function(THD *thd, Item **args, uint argcount, Field *return_fld, sp_rcontext **nctx, Query_arena *call_arena); bool execute_procedure(THD *thd, List<Item> *args); static void show_create_routine_get_fields(THD *thd, const Sp_handler *sph, List<Item> *fields); bool show_create_routine(THD *thd, const Sp_handler *sph); MEM_ROOT *get_main_mem_root() { return &main_mem_root; } int add_instr(sp_instr *instr); bool add_instr_jump(THD *thd, sp_pcontext *spcont); bool add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest); bool add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont, sp_label *lab); bool add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont) { return add_instr_jump_forward_with_backpatch(thd, spcont, spcont->last_label()); } bool add_instr_freturn(THD *thd, sp_pcontext *spcont, Item *item, sp_expr_lex *lex); bool add_instr_preturn(THD *thd, sp_pcontext *spcont); Item *adjust_assignment_source(THD *thd, Item *val, Item *val2); /** @param thd - the current thd @param spcont - the current parse context @param spv - the SP variable @param val - the value to be assigned to the variable @param lex - the LEX that was used to create "val" @param responsible_to_free_lex - if the generated sp_instr_set should free "lex". @retval true - on error @retval false - on success */ bool set_local_variable(THD *thd, sp_pcontext *spcont, const Sp_rcontext_handler *rh, sp_variable *spv, Item *val, LEX *lex, bool responsible_to_free_lex, const LEX_CSTRING &value_query); bool set_local_variable_row_field(THD *thd, sp_pcontext *spcont, const Sp_rcontext_handler *rh, sp_variable *spv, uint field_idx, Item *val, LEX *lex, const LEX_CSTRING &value_query); bool set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont, const Sp_rcontext_handler *rh, sp_variable *spv, const LEX_CSTRING *field_name, Item *val, LEX *lex, const LEX_CSTRING &value_query); bool check_package_routine_end_name(const LEX_CSTRING &end_name) const; bool check_standalone_routine_end_name(const sp_name *end_name) const; bool check_group_aggregate_instructions_function() const; bool check_group_aggregate_instructions_forbid() const; bool check_group_aggregate_instructions_require() const; private: /** Generate a code to set a single cursor parameter variable. @param thd - current thd, for mem_root allocations. @param param_spcont - the context of the parameter block @param idx - the index of the parameter @param prm - the actual parameter (contains information about the assignment source expression Item, its free list, and its LEX) */ bool add_set_cursor_param_variable(THD *thd, sp_pcontext *param_spcont, uint idx, sp_assignment_lex *prm) { DBUG_ASSERT(idx < param_spcont->context_var_count()); sp_variable *spvar= param_spcont->get_context_variable(idx); /* add_instr() gets free_list from m_thd->free_list. Initialize it before the set_local_variable() call. */ DBUG_ASSERT(m_thd->free_list == NULL); m_thd->free_list= prm->get_free_list(); if (set_local_variable(thd, param_spcont, &sp_rcontext_handler_local, spvar, prm->get_item(), prm, true, prm->get_expr_str())) return true; /* Safety: The item and its free_list are now fully owned by the sp_instr_set instance, created by set_local_variable(). The sp_instr_set instance is now responsible for freeing the item and the free_list. Reset the "item" and the "free_list" members of "prm", to avoid double pointers to the same objects from "prm" and from the sp_instr_set instance. */ prm->set_item_and_free_list(NULL, NULL); return false; } /** Generate a code to set all cursor parameter variables. This method is called only when parameters exists, and the number of formal parameters matches the number of actual parameters. See also comments to add_open_cursor(). */ bool add_set_cursor_param_variables(THD *thd, sp_pcontext *param_spcont, List<sp_assignment_lex> *parameters) { DBUG_ASSERT(param_spcont->context_var_count() == parameters->elements); sp_assignment_lex *prm; List_iterator<sp_assignment_lex> li(*parameters); for (uint idx= 0; (prm= li++); idx++) { if (add_set_cursor_param_variable(thd, param_spcont, idx, prm)) return true; } return false; } /** Generate a code to set all cursor parameter variables for a FOR LOOP, e.g.: FOR index IN cursor(1,2,3) @param */ bool add_set_for_loop_cursor_param_variables(THD *thd, sp_pcontext *param_spcont, sp_assignment_lex *param_lex, Item_args *parameters); bool bind_input_param(THD *thd, Item *arg_item, uint arg_no, sp_rcontext *nctx, bool is_function); bool bind_output_param(THD *thd, Item *arg_item, uint arg_no, sp_rcontext *octx, sp_rcontext *nctx); public: /** Generate a code for an "OPEN cursor" statement. @param thd - current thd, for mem_root allocations @param spcont - the context of the cursor @param offset - the offset of the cursor @param param_spcont - the context of the cursor parameter block @param parameters - the list of the OPEN actual parameters The caller must make sure that the number of local variables in "param_spcont" (formal parameters) matches the number of list elements in "parameters" (actual parameters). NULL in either of them means 0 parameters. */ bool add_open_cursor(THD *thd, sp_pcontext *spcont, uint offset, sp_pcontext *param_spcont, List<sp_assignment_lex> *parameters); /** Generate an initiation code for a CURSOR FOR LOOP, e.g.: FOR index IN cursor -- cursor without parameters FOR index IN cursor(1,2,3) -- cursor with parameters The code generated by this method does the following during SP run-time: - Sets all cursor parameter vartiables from "parameters" - Initializes the index ROW-type variable from the cursor (the structure is copied from the cursor to the index variable) - The cursor gets opened - The first records is fetched from the cursor to the variable "index". @param thd - the current thread (for mem_root and error reporting) @param spcont - the current parse context @param index - the loop "index" ROW-type variable @param pcursor - the cursor @param coffset - the cursor offset @param param_lex - the LEX that owns Items in "parameters" @param parameters - the cursor parameters Item array @retval true - on error (EOM) @retval false - on success */ bool add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont, sp_variable *index, const sp_pcursor *pcursor, uint coffset, sp_assignment_lex *param_lex, Item_args *parameters); /** Returns true if any substatement in the routine directly (not through another routine) modifies data/changes table. @sa Comment for MODIFIES_DATA flag. */ bool modifies_data() const { return m_flags & MODIFIES_DATA; } inline uint instructions() { return (uint)m_instr.elements; } inline sp_instr * last_instruction() { sp_instr *i; get_dynamic(&m_instr, (uchar*)&i, m_instr.elements-1); return i; } bool replace_instr_to_nop(THD *thd, uint ip); /* Resets lex in 'thd' and keeps a copy of the old one. @todo Conflicting comment in sp_head.cc */ bool reset_lex(THD *thd); bool reset_lex(THD *thd, sp_lex_local *sublex); /** Merge two LEX instances. @param oldlex - the upper level LEX we're going to restore to. @param sublex - the local lex that have just parsed some substatement. @returns - false on success, true on error (e.g. failed to merge the routine list or the table list). This method is shared by: - restore_lex(), when the old LEX is popped by sp_head::m_lex.pop() - THD::restore_from_local_lex_to_old_lex(), when the old LEX is stored in the caller's local variable. */ bool merge_lex(THD *thd, LEX *oldlex, LEX *sublex); /** Restores lex in 'thd' from our copy, but keeps some status from the one in 'thd', like ptr, tables, fields, etc. @todo Conflicting comment in sp_head.cc */ bool restore_lex(THD *thd) { DBUG_ENTER("sp_head::restore_lex"); /* There is no a need to free the current thd->lex here. - In the majority of the cases restore_lex() is called on success and thd->lex does not need to be deleted. - In cases when restore_lex() is called on error, e.g. from sp_create_assignment_instr(), thd->lex is already linked to some sp_instr_xxx (using sp_lex_keeper). Note, we don't get to here in case of a syntax error when the current thd->lex is not yet completely initialized and linked. It gets automatically deleted by the Bison %destructor in sql_yacc.yy. */ LEX *oldlex= (LEX *) m_lex.pop(); if (!oldlex) DBUG_RETURN(false); // Nothing to restore // This restores thd->lex and thd->stmt_lex DBUG_RETURN(thd->restore_from_local_lex_to_old_lex(oldlex)); } /** Delete all auxiliary LEX objects created on parsing a statement and restore a value of the data member THD::lex to point on the LEX object that was actual before parsing started. */ void unwind_aux_lexes_and_restore_original_lex(); /** Iterate through the LEX stack from the top (the newest) to the bottom (the oldest) and find the one that contains a non-zero spname. @returns - the address of spname, or NULL of no spname found. */ const sp_name *find_spname_recursive() { uint count= m_lex.elements; for (uint i= 0; i < count; i++) { const LEX *tmp= m_lex.elem(count - i - 1); if (tmp->spname) return tmp->spname; } return NULL; } /// Put the instruction on the backpatch list, associated with the label. int push_backpatch(THD *thd, sp_instr *, sp_label *); int push_backpatch_goto(THD *thd, sp_pcontext *ctx, sp_label *lab); /// Update all instruction with this label in the backpatch list to /// the current position. void backpatch(sp_label *); void backpatch_goto(THD *thd, sp_label *, sp_label *); /// Check for unresolved goto label bool check_unresolved_goto(); /// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. int new_cont_backpatch(sp_instr_opt_meta *i); /// Add an instruction to the current level int add_cont_backpatch(sp_instr_opt_meta *i); /// Backpatch (and pop) the current level to the current position. void do_cont_backpatch(); /// Add cpush instructions for all cursors declared in the current frame bool sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext); const LEX_CSTRING *name() const { return &m_name; } char *create_string(THD *thd, ulong *lenp); Field *create_result_field(uint field_max_length, const LEX_CSTRING *field_name, TABLE *table) const; /** Check and prepare an instance of Column_definition for field creation (fill all necessary attributes), for variables, parameters and function return values. @param[in] thd Thread handle @param[in] lex Yacc parsing context @param[out] field_def An instance of create_field to be filled @retval false on success @retval true on error */ bool fill_field_definition(THD *thd, Column_definition *field_def) { const Type_handler *h= field_def->type_handler(); return h->Column_definition_fix_attributes(field_def) || field_def->sp_prepare_create_field(thd, mem_root); } bool row_fill_field_definitions(THD *thd, Row_definition_list *row) { /* Prepare all row fields. This will (among other things) - convert VARCHAR lengths from character length to octet length - calculate interval lengths for SET and ENUM */ List_iterator<Spvar_definition> it(*row); for (Spvar_definition *def= it++; def; def= it++) { if (fill_spvar_definition(thd, def)) return true; } return false; } /** Check and prepare a Column_definition for a variable or a parameter. */ bool fill_spvar_definition(THD *thd, Column_definition *def) { if (fill_field_definition(thd, def)) return true; def->pack_flag|= FIELDFLAG_MAYBE_NULL; return false; } bool fill_spvar_definition(THD *thd, Column_definition *def, LEX_CSTRING *name) { def->field_name= *name; return fill_spvar_definition(thd, def); } private: /** Set a column type reference for a parameter definition */ void fill_spvar_using_type_reference(sp_variable *spvar, Qualified_column_ident *ref) { spvar->field_def.set_column_type_ref(ref); spvar->field_def.field_name= spvar->name; m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; } void fill_spvar_using_table_rowtype_reference(THD *thd, sp_variable *spvar, Table_ident *ref) { spvar->field_def.set_table_rowtype_ref(ref); spvar->field_def.field_name= spvar->name; fill_spvar_definition(thd, &spvar->field_def); m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; } public: bool spvar_fill_row(THD *thd, sp_variable *spvar, Row_definition_list *def); bool spvar_fill_type_reference(THD *thd, sp_variable *spvar, const LEX_CSTRING &table, const LEX_CSTRING &column); bool spvar_fill_type_reference(THD *thd, sp_variable *spvar, const LEX_CSTRING &db, const LEX_CSTRING &table, const LEX_CSTRING &column); bool spvar_fill_table_rowtype_reference(THD *thd, sp_variable *spvar, const LEX_CSTRING &table); bool spvar_fill_table_rowtype_reference(THD *thd, sp_variable *spvar, const LEX_CSTRING &db, const LEX_CSTRING &table); void set_c_chistics(const st_sp_chistics &chistics); void set_info(longlong created, longlong modified, const st_sp_chistics &chistics, sql_mode_t sql_mode); void set_definer(const char *definer, size_t definerlen) { AUTHID tmp; tmp.parse(definer, definerlen); m_definer.copy(mem_root, &tmp.user, &tmp.host); } void set_definer(const LEX_CSTRING *user_name, const LEX_CSTRING *host_name) { m_definer.copy(mem_root, user_name, host_name); } void set_definition_string(LEX_STRING &defstr) { m_definition_string= defstr; } void reset_thd_mem_root(THD *thd); void restore_thd_mem_root(THD *thd); /** Optimize the code. */ void optimize(); /** Helper used during flow analysis during code optimization. See the implementation of <code>opt_mark()</code>. @param ip the instruction to add to the leads list @param leads the list of remaining paths to explore in the graph that represents the code, during flow analysis. */ void add_mark_lead(uint ip, List<sp_instr> *leads); inline sp_instr * get_instr(uint i) { sp_instr *ip; if (i < m_instr.elements) get_dynamic(&m_instr, (uchar*)&ip, i); else ip= NULL; return ip; } #ifdef PROTECT_STATEMENT_MEMROOT int has_all_instrs_executed(); void reset_instrs_executed_counter(); #endif /* Add tables used by routine to the table list. */ bool add_used_tables_to_table_list(THD *thd, TABLE_LIST ***query_tables_last_ptr, TABLE_LIST *belong_to_view); /** Check if this stored routine contains statements disallowed in a stored function or trigger, and set an appropriate error message if this is the case. */ bool is_not_allowed_in_function(const char *where) { if (m_flags & CONTAINS_DYNAMIC_SQL) my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL"); else if (m_flags & MULTI_RESULTS) my_error(ER_SP_NO_RETSET, MYF(0), where); else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); else if (m_flags & HAS_COMMIT_OR_ROLLBACK) my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); else if (m_flags & HAS_SQLCOM_RESET) my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "RESET"); else if (m_flags & HAS_SQLCOM_FLUSH) my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); return MY_TEST(m_flags & (CONTAINS_DYNAMIC_SQL | MULTI_RESULTS | HAS_SET_AUTOCOMMIT_STMT | HAS_COMMIT_OR_ROLLBACK | HAS_SQLCOM_RESET | HAS_SQLCOM_FLUSH)); } #ifndef DBUG_OFF int show_routine_code(THD *thd); #endif /* This method is intended for attributes of a routine which need to propagate upwards to the Query_tables_list of the caller (when a property of a sp_head needs to "taint" the calling statement). */ void propagate_attributes(Query_tables_list *prelocking_ctx) { DBUG_ENTER("sp_head::propagate_attributes"); /* If this routine needs row-based binary logging, the entire top statement too (we cannot switch from statement-based to row-based only for this routine, as in statement-based the top-statement may be binlogged and the substatements not). */ DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x", prelocking_ctx->get_stmt_unsafe_flags())); DBUG_PRINT("info", ("sp_head(%p=%s)->unsafe_flags: 0x%x", this, name()->str, unsafe_flags)); prelocking_ctx->set_stmt_unsafe_flags(unsafe_flags); DBUG_VOID_RETURN; } sp_pcontext *get_parse_context() { return m_pcont; } /* Check EXECUTE access: - in case of a standalone rotuine, for the routine itself - in case of a package routine, for the owner package body */ bool check_execute_access(THD *thd) const; virtual sp_package *get_package() { return NULL; } virtual void init_psi_share(); protected: MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root THD *m_thd; ///< Set if we have reset mem_root sp_pcontext *m_pcont; ///< Parse context List<LEX> m_lex; ///< Temp. store for the other lex DYNAMIC_ARRAY m_instr; ///< The "instructions" enum backpatch_instr_type { GOTO, CPOP, HPOP }; typedef struct { sp_label *lab; sp_instr *instr; backpatch_instr_type instr_type; } bp_t; List<bp_t> m_backpatch; ///< Instructions needing backpatching List<bp_t> m_backpatch_goto; // Instructions needing backpatching (for goto) /** We need a special list for backpatching of instructions with a continue destination (in the case of a continue handler catching an error in the test), since it would otherwise interfere with the normal backpatch mechanism - e.g. jump_if_not instructions have two different destinations which are to be patched differently. Since these occur in a more restricted way (always the same "level" in the code), we don't need the label. */ List<sp_instr_opt_meta> m_cont_backpatch; uint m_cont_level; // The current cont. backpatch level /** Multi-set representing optimized list of tables to be locked by this routine. Does not include tables which are used by invoked routines. @note For prelocking-free SPs this multiset is constructed too. We do so because the same instance of sp_head may be called both in prelocked mode and in non-prelocked mode. */ HASH m_sptabs; /** Text of the query CREATE PROCEDURE/FUNCTION/TRIGGER/EVENT ... used for DDL parsing. */ LEX_STRING m_definition_string; bool execute(THD *thd, bool merge_da_on_success); /** Perform a forward flow analysis in the generated code. Mark reachable instructions, for the optimizer. */ void opt_mark(); /** Merge the list of tables used by query into the multi-set of tables used by routine. */ bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check); /// Put the instruction on the a backpatch list, associated with the label. int push_backpatch(THD *thd, sp_instr *, sp_label *, List<bp_t> *list, backpatch_instr_type itype); public: /* List of lists of Item_trigger_field objects representing all fields in old/new version of row in trigger. We use this list of lists for checking whenever all such fields are valid at trigger creation time and for binding these fields to TABLE object at table open (although for latter pointer to table being opened is probably enough). */ SQL_I_List<SQL_I_List<Item_trigger_field> > m_trg_table_fields; /** The object of the Trigger class corresponding to this sp_head object. This data member is set on table's triggers loading at the function check_n_load and is used at the method sp_lex_instr::parse_expr for accessing to the trigger's table after re-parsing of failed trigger's instruction. */ Trigger *m_trg= nullptr; /* List of Item_trigger_field objects created on parsing a current instruction of trigger's body */ SQL_I_List<Item_trigger_field> m_cur_instr_trig_field_items; }; // class sp_head : public Sql_alloc class sp_package: public sp_head { bool validate_public_routines(THD *thd, sp_package *spec); bool validate_private_routines(THD *thd); public: class LexList: public List<LEX> { public: LexList() { elements= 0; } // Find a package routine by a non qualified name LEX *find(const LEX_CSTRING &name, enum_sp_type type); // Find a package routine by a package-qualified name, e.g. 'pkg.proc' LEX *find_qualified(const LEX_CSTRING &name, enum_sp_type type); // Check if a routine with the given qualified name already exists bool check_dup_qualified(const LEX_CSTRING &name, const Sp_handler *sph) { if (!find_qualified(name, sph->type())) return false; my_error(ER_SP_ALREADY_EXISTS, MYF(0), sph->type_str(), name.str); return true; } bool check_dup_qualified(const sp_head *sp) { return check_dup_qualified(sp->m_name, sp->m_handler); } void cleanup(); }; /* The LEX for a new package subroutine is initially assigned to m_current_routine. After scanning parameters, return type and chistics, the parser detects if we have a declaration or a definition, e.g.: PROCEDURE p1(a INT); vs PROCEDURE p1(a INT) AS BEGIN NULL; END; (i.e. either semicolon or the "AS" keyword) m_current_routine is then added either to m_routine_implementations, or m_routine_declarations, and then m_current_routine is set to NULL. */ LEX *m_current_routine; LexList m_routine_implementations; LexList m_routine_declarations; LEX *m_top_level_lex; sp_rcontext *m_rcontext; uint m_invoked_subroutine_count; bool m_is_instantiated; bool m_is_cloning_routine; private: sp_package(MEM_ROOT *mem_root, LEX *top_level_lex, const sp_name *name, const Sp_handler *sph); ~sp_package(); public: static sp_package *create(LEX *top_level_lex, const sp_name *name, const Sp_handler *sph, MEM_ROOT *sp_mem_root); bool add_routine_declaration(LEX *lex) { return m_routine_declarations.check_dup_qualified(lex->sphead) || m_routine_declarations.push_back(lex, &main_mem_root); } bool add_routine_implementation(LEX *lex) { return m_routine_implementations.check_dup_qualified(lex->sphead) || m_routine_implementations.push_back(lex, &main_mem_root); } sp_package *get_package() override { return this; } void init_psi_share() override; bool is_invoked() const override { /* Cannot flush a package out of the SP cache when: - its initialization block is running - one of its subroutine is running */ return sp_head::is_invoked() || m_invoked_subroutine_count > 0; } sp_variable *find_package_variable(const LEX_CSTRING *name) const { /* sp_head::m_pcont is a special level for routine parameters. Variables declared inside CREATE PACKAGE BODY reside in m_children.at(0). */ sp_pcontext *ctx= m_pcont->child_context(0); return ctx ? ctx->find_variable(name, true) : NULL; } bool validate_after_parser(THD *thd); bool instantiate_if_needed(THD *thd); }; bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access); bool check_db_routine_access(THD *thd, privilege_t privilege, const char *db, const char *name, const Sp_handler *sph, bool no_errors); #ifndef NO_EMBEDDED_ACCESS_CHECKS bool sp_change_security_context(THD *thd, sp_head *sp, Security_context **backup); void sp_restore_security_context(THD *thd, Security_context *backup); bool set_routine_security_ctx(THD *thd, sp_head *sp, Security_context **save_ctx); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ TABLE_LIST * sp_add_to_query_tables(THD *thd, LEX *lex, const LEX_CSTRING *db, const LEX_CSTRING *name, thr_lock_type locktype, enum_mdl_type mdl_type); /** @} (end of group Stored_Routines) */ #endif /* _SP_HEAD_H_ */ my_rnd.h 0000644 00000001766 15156036170 0006223 0 ustar 00 /* Copyright (C) 2013 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 or later of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _my_rnd_h #define _my_rnd_h C_MODE_START struct my_rnd_struct { unsigned long seed1,seed2,max_value; double max_value_dbl; }; void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2); double my_rnd(struct my_rnd_struct *rand_st); C_MODE_END #endif /* _my_rnd_h */ wsrep_types.h 0000644 00000002126 15156036170 0007306 0 ustar 00 /* Copyright 2018 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Wsrep typedefs to better conform to coding style. */ #ifndef WSREP_TYPES_H #define WSREP_TYPES_H #include "wsrep/seqno.hpp" #include "wsrep/view.hpp" #include "wsrep/allowlist_service.hpp" typedef wsrep::id Wsrep_id; typedef wsrep::seqno Wsrep_seqno; typedef wsrep::view Wsrep_view; typedef enum wsrep::allowlist_service::allowlist_key Wsrep_allowlist_key; #endif /* WSREP_TYPES_H */ my_counter.h 0000644 00000003271 15156036171 0007111 0 ustar 00 #ifndef MY_COUNTER_H_INCLUDED #define MY_COUNTER_H_INCLUDED /* Copyright (C) 2018 MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <atomic> template <typename Type> class Atomic_counter { std::atomic<Type> m_counter; Type add(Type i) { return m_counter.fetch_add(i, std::memory_order_relaxed); } Type sub(Type i) { return m_counter.fetch_sub(i, std::memory_order_relaxed); } public: Atomic_counter(const Atomic_counter<Type> &rhs) { m_counter.store(rhs, std::memory_order_relaxed); } Atomic_counter(Type val): m_counter(val) {} Atomic_counter() = default; Type operator++(int) { return add(1); } Type operator--(int) { return sub(1); } Type operator++() { return add(1) + 1; } Type operator--() { return sub(1) - 1; } Type operator+=(const Type i) { return add(i) + i; } Type operator-=(const Type i) { return sub(i) - i; } operator Type() const { return m_counter.load(std::memory_order_relaxed); } Type operator=(const Type val) { m_counter.store(val, std::memory_order_relaxed); return val; } }; #endif /* MY_COUNTER_H_INCLUDED */ my_atomic.h 0000644 00000016161 15156036171 0006710 0 ustar 00 #ifndef MY_ATOMIC_INCLUDED #define MY_ATOMIC_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2018, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This header defines five atomic operations: my_atomic_add#(&var, what) my_atomic_add#_explicit(&var, what, memory_order) 'Fetch and Add' add 'what' to *var, and return the old value of *var All memory orders are valid. my_atomic_fas#(&var, what) my_atomic_fas#_explicit(&var, what, memory_order) 'Fetch And Store' store 'what' in *var, and return the old value of *var All memory orders are valid. my_atomic_cas#(&var, &old, new) my_atomic_cas#_weak_explicit(&var, &old, new, succ, fail) my_atomic_cas#_strong_explicit(&var, &old, new, succ, fail) 'Compare And Swap' if *var is equal to *old, then store 'new' in *var, and return TRUE otherwise store *var in *old, and return FALSE succ - the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All memory orders are valid. fail - the memory synchronization ordering for the load operation if the comparison fails. Cannot be MY_MEMORY_ORDER_RELEASE or MY_MEMORY_ORDER_ACQ_REL and cannot specify stronger ordering than succ. The weak form is allowed to fail spuriously, that is, act as if *var != *old even if they are equal. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. my_atomic_load#(&var) my_atomic_load#_explicit(&var, memory_order) return *var Order must be one of MY_MEMORY_ORDER_RELAXED, MY_MEMORY_ORDER_CONSUME, MY_MEMORY_ORDER_ACQUIRE, MY_MEMORY_ORDER_SEQ_CST. my_atomic_store#(&var, what) my_atomic_store#_explicit(&var, what, memory_order) store 'what' in *var Order must be one of MY_MEMORY_ORDER_RELAXED, MY_MEMORY_ORDER_RELEASE, MY_MEMORY_ORDER_SEQ_CST. '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr). The first version orders memory accesses according to MY_MEMORY_ORDER_SEQ_CST, the second version (with _explicit suffix) orders memory accesses according to given memory order. memory_order specifies how non-atomic memory accesses are to be ordered around an atomic operation: MY_MEMORY_ORDER_RELAXED - there are no constraints on reordering of memory accesses around the atomic variable. MY_MEMORY_ORDER_CONSUME - no reads in the current thread dependent on the value currently loaded can be reordered before this load. This ensures that writes to dependent variables in other threads that release the same atomic variable are visible in the current thread. On most platforms, this affects compiler optimization only. MY_MEMORY_ORDER_ACQUIRE - no reads in the current thread can be reordered before this load. This ensures that all writes in other threads that release the same atomic variable are visible in the current thread. MY_MEMORY_ORDER_RELEASE - no writes in the current thread can be reordered after this store. This ensures that all writes in the current thread are visible in other threads that acquire the same atomic variable. MY_MEMORY_ORDER_ACQ_REL - no reads in the current thread can be reordered before this load as well as no writes in the current thread can be reordered after this store. The operation is read-modify-write operation. It is ensured that all writes in another threads that release the same atomic variable are visible before the modification and the modification is visible in other threads that acquire the same atomic variable. MY_MEMORY_ORDER_SEQ_CST - The operation has the same semantics as acquire-release operation, and additionally has sequentially-consistent operation ordering. We choose implementation as follows: on Windows using Visual C++ the native implementation should be preferable. When using gcc we prefer the Solaris implementation before the gcc because of stability preference, we choose gcc builtins if available. */ #if defined(_MSC_VER) #include "atomic/generic-msvc.h" #elif defined(HAVE_SOLARIS_ATOMIC) #include "atomic/solaris.h" #elif defined(HAVE_GCC_C11_ATOMICS) #include "atomic/gcc_builtins.h" #endif #ifndef MY_MEMORY_ORDER_SEQ_CST #define MY_MEMORY_ORDER_RELAXED #define MY_MEMORY_ORDER_CONSUME #define MY_MEMORY_ORDER_ACQUIRE #define MY_MEMORY_ORDER_RELEASE #define MY_MEMORY_ORDER_ACQ_REL #define MY_MEMORY_ORDER_SEQ_CST #define my_atomic_store32_explicit(P, D, O) my_atomic_store32((P), (D)) #define my_atomic_store64_explicit(P, D, O) my_atomic_store64((P), (D)) #define my_atomic_storeptr_explicit(P, D, O) my_atomic_storeptr((P), (D)) #define my_atomic_load32_explicit(P, O) my_atomic_load32((P)) #define my_atomic_load64_explicit(P, O) my_atomic_load64((P)) #define my_atomic_loadptr_explicit(P, O) my_atomic_loadptr((P)) #define my_atomic_fas32_explicit(P, D, O) my_atomic_fas32((P), (D)) #define my_atomic_fas64_explicit(P, D, O) my_atomic_fas64((P), (D)) #define my_atomic_fasptr_explicit(P, D, O) my_atomic_fasptr((P), (D)) #define my_atomic_add32_explicit(P, A, O) my_atomic_add32((P), (A)) #define my_atomic_add64_explicit(P, A, O) my_atomic_add64((P), (A)) #define my_atomic_addptr_explicit(P, A, O) my_atomic_addptr((P), (A)) #define my_atomic_cas32_weak_explicit(P, E, D, S, F) \ my_atomic_cas32((P), (E), (D)) #define my_atomic_cas64_weak_explicit(P, E, D, S, F) \ my_atomic_cas64((P), (E), (D)) #define my_atomic_casptr_weak_explicit(P, E, D, S, F) \ my_atomic_casptr((P), (E), (D)) #define my_atomic_cas32_strong_explicit(P, E, D, S, F) \ my_atomic_cas32((P), (E), (D)) #define my_atomic_cas64_strong_explicit(P, E, D, S, F) \ my_atomic_cas64((P), (E), (D)) #define my_atomic_casptr_strong_explicit(P, E, D, S, F) \ my_atomic_casptr((P), (E), (D)) #endif #endif /* MY_ATOMIC_INCLUDED */ gtid_index.h 0000644 00000047045 15156036171 0007052 0 ustar 00 /* Copyright (c) 2023 Kristian Nielsen <knielsen@knielsen-hq.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef GTID_INDEX_H #define GTID_INDEX_H #include "my_global.h" #include "mysqld.h" #include "mariadb.h" #include "rpl_gtid.h" /* This implements an on-disk index for each binlog file to speed up access to the binlog at a specific offset or GTID position. This is primarily used when a slave connects to the master, but also by user calling BINLOG_GTID_POS(). A connecting slave first scans the binlog files to find the last one with an initial GTID_LIST event that lies before the starting GTID position. Then a sequential scan of the binlog file is done until the requested GTID position is found. The binlog index conceptually extends this using index records corresponding to different offset within one binlog file. Each record functions as if it was the initial GTID_LIST event of a new binlog file, allowing the sequential scan to start from the corresponding position. By having sufficiently many index records, the scan will be fast. The code that adds one record to the index is in two parts, a "sync" path and an "async" path. The "sync" path in process_gtid_check_batch() does the minimum amount of work which needs to run as part of transaction commit. The actual writing of the index, in async_update(), can then be done as a background task, minimizing the performance impact on transaction processing. The "sync" and "async" paths each run single threaded, but can execute in parallel with each other. The index file is written incrementally together with the binlog file. However there is no fsync()'s of the index file needed while writing. A partially written index left by a crashing server will be re-written during binlog recovery. A reader is allowed to use the index as it is begin written (for the "hot" binlog file); such access is protected by mutex. In case of lost or corrupt index, fallback to full sequential scan is done (so performance will be affected but not correct functionality). The index file is structured like a B+-tree. The index is append-only, so also resembles a log-structured merge-tree, but with no merging of levels needed as it covers a single fixed-size binlog file. This makes the building of the tree relatively simple. Keys in the tree consist of a GTID state (corresponding to a GTID_LIST event) and the associated binlog file offset. All keys (except the first key in each level of the tree) are delta-compressed to save space, holding only the (domain_id, server_id) pairs that differ from the previous record. The file is page-based. The first page contains the leftmost leaf node, and the root node is at the end of the file. An incompletely written index file can be detected by the last page in the file not being a root node page. Nodes in the B+-tree usually fit in one page, but a node can be split across multiple pages if GTID states are very large. Page format: The first page contains an extra file header: Offset Size Description 0 4 MAGIC header identifying the file as a binlog index 4 1 Major version number. A new major version of the file format is not readable by older server versions. 5 1 Minor version number. Formats differing only in minor version are backwards compatible and can be read by older servers. 6 2 Padding/unused. 8 4 Page size. Each page additionally contains this header: Offset Size Description 0 1 Flags 1 3 Padding/unused The last 4 bytes of each page is a 32-bit CRC. An interior node is a sequence of <child ptr> <key> <child ptr> <key> ... <key> <child ptr> while a leaf node has only keys. A child pointer is stored as 4 byte integer. The first page is 1, so that 0 can be used to denote "not present". Format of a key: Offset Size Description 0 4 Number of GTIDs in the key, plus 1. Or 0 for EOF. 4 4 Binlog file offset 8 4 Domain_id of first GTID 12 4 Server_id of first GTID 16 8 Seq_no of first GTID ... and so on for each GTID in the key. A node typically fits in one page. But if the GTID state is very big (or the page size very small), multiple pages may be used. When a node is split, it can be split after a child pointer or before or after a GTID, but not elsewhere. Here is an example GTID index with page_size=64 containing 3 records: Offset GTID state 0x11d [empty] 0x20e [0-1-1] 0x2ad [0-1-2] The example contains 3 nodes, each stored in a single page. Two leaf nodes and one interior root node. Page 1 (leaf node page with file header): fe fe 0c 01 "magic" identifying the file as a binlog GTID index 01 00 Major version 1, minor version 0 00 00 Padding / currently unused 40 00 00 00 Page size (64 bytes in this example) 05 Flag PAGE_FLAG_IS_LEAF | PAGE_FLAG_LAST (single-page leaf node) 00 00 00 Padding / current unused Key 1: 01 00 00 00 <GTID_count + 1> = 1 (entry has zero GTIDs in it) 1d 01 00 00 Binlog file offset = 0x11d [Empty GTID state at the very start of the binlog] Key 2: 02 00 00 00 GTID_count = 1 0e 02 00 00 Binlog file offset = 0x20e 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 GTID 0-1-1 00 00 00 00 00 Zero denotes end-of-node 00 00 00 00 00 00 00 (Unused space in the page) 0e 4f ac 43 Checksum / CRC Page 2 (leaf node): 05 Flag PAGE_FLAG_IS_LEAF | PAGE_FLAG_LAST (single-page leaf node) 00 00 00 Unused Key 1: 02 00 00 00 GTID_count = 1 ad 02 00 00 Binlog file offset = 0x2ad 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 GTID 0-1-2 00 00 00 00 End-of-node 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Unused space in the page) 0c 4e c2 b9 CRC Page 3 (root node): 0c PAGE_FLAG_ROOT | PAGE_FLAG_LAST (interior root node) 00 00 00 Unused Child pointer: 01 00 00 00 Pointer to page 1 Key for next child page: 02 00 00 00 GTID_count = 1 ad 02 00 00 Binlog offset = 0x2ad 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 GTID 0-1-2 Child pointer: 02 00 00 00 Pointer to page 2 00 00 0 000 Zero denotes end-of-node 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Unused) 8155 a3c7 CRC Below is an example of the logical B-Tree structure of a larger GTID index with a total of 12 keys. We use S0, S1, ..., S11 to denote a key, which consists of a GTID state (as seen in @@binlog_gtid_state and GTID_LIST_EVENT) and the associated binlog file offset. D1, D2, ..., D11 denote the same keys, but delta-compressed, so that D1 stores only those GTIDs that are not the same as in S0. Pages are denoted by P1, P2, ..., P8. In the example, P1, P2, P3, P5, and P6 are leaf pages, the rest are interior node pages. P8 is the root node (the root is always the last page in the index). The contents of each page is listed in square brackets [...]. So P1[S0 D1 D2] is a leaf page with 3 keys, and P7[P5 <D10+D11> P6] is an interior node page with one key <D10+D11> and two child-page pointers to P5 and P6. The notation <D10+D11> denotes the delta-compression of key S11 relative to S9; all GTIDs in S11 that are not present in S9. In the code, this is computed by combining D10 and D11, hence the use of the notation "D10+D11" instead of the equivalent "S11-S9". Here is the example B-Tree. It has 3 levels, with the leaf nodes at the top: P1[S0 D1 D2] P2[D3 D4 D5] P3[D6 D7 D8] P5[D9 D10] P6[D11] P4[P1 <S3> P2 <D4+D5+D6> P3] P7[P5 <D10+D11> P6] P8[P4 <S9> P7] To find eg. S4, we start from the root P8. S4<S9, so we follow the left child pointer to P4. S4>S3 and S4<S6 (S6=(S3+D4+D5+D6)), so we follow the child pointer to leaf page P2. The index is written completely append-only; this is possible since keys are always inserted in-order, at the end of the index. One page is kept in-memory at each level of the B-Tree; when a new key no longer fits the page, it is written out to disk and a new in-memory page is allocated for it. Here are the operations that occur while writing the index file from the above example. The left column is each key added to the index as the corresponding GTID is written into the binlog file (<EOF> is when the index is closed at binlog rotation). The right column are the operations performed, as follows: alloc(p) Allocate page p add_key(p,k) Insert the key k into the page p add_ptr(p,q) Insert a pointer to child page q in parent page p write(p) Write out page p to disk at the end of the index file. GTID STATE OPERATIONS S0 alloc(P1) add_key(P1,S0) D1 add_key(P1,D1) D2 add_key(P1,D2) D3 write(P1) alloc(P4) add_ptr(P4,P1) alloc(P2) add_key(P2,D3) add_key(P4,S3) D4 add_key(P2,D4) D5 add_key(P2,D5) D6 write(P2) add_ptr(P4,P2) alloc(P3) add_key(P3,D6) add_key(P4,D4+D5+D6) D7 add_key(P3,D7) D8 add_key(P3,D8) D9 write(P3) add_ptr(P4,P3) alloc(P5) add_key(P5,D9) write(P4) alloc(P8) add_ptr(P8,P4) alloc(P7) add_key(P8,S9) D10 add_key(P5,D10) D11 write(P5) add_ptr(P7,P5) alloc(P6) add_key(P6,D11) add_key(P7,D10+D11) <EOF> write(P6) add_ptr(P7,P6) write(P7) add_ptr(P8,P7) write(P8) After adding each record to the index, there is exactly one partial page allocated in-memory for each level present in the B-Tree; new pages being allocated as old pages fill up and are written to disk. */ class Gtid_index_base { public: /* +4 for ".idx" prefix. */ static constexpr size_t GTID_INDEX_FILENAME_MAX_SIZE= FN_REFLEN+4; protected: enum enum_page_flags { /* Set for a leaf node page, cleared for an interior node page. */ PAGE_FLAG_IS_LEAF= 1, /* This is a continuation page. */ PAGE_FLAG_IS_CONT= 2, /* No continuation page follows (the last page in a group). */ PAGE_FLAG_LAST= 4, /* Flag set to mark the root node. (The root node is normally the last page in the index file, but having an explicit flag allows us to detect a partially written index file with the root node missing. */ PAGE_FLAG_ROOT= 8, }; /* Minor version increment represents a backwards-compatible format (can be read by any server version that knows the format of the major version). Major version increment means a server should not attempt to read from the index. */ static constexpr uchar GTID_INDEX_VERSION_MAJOR= 1; static constexpr uchar GTID_INDEX_VERSION_MINOR= 0; static constexpr size_t GTID_INDEX_FILE_HEADER_SIZE= 12; static constexpr size_t GTID_INDEX_PAGE_HEADER_SIZE= 4; static constexpr size_t CHECKSUM_LEN= 4; #ifdef _MSC_VER /* Flexible array member is part of C99, but it is not standard in C++. All the compilers and platforms we support do support it, though. Just we need to disable on Windows a warning about using a non-standard C++ extension. */ #pragma warning(disable : 4200) #endif struct Node_page { Node_page *next; /* Pointer to allow to update the "flags" byte at page writeout. */ uchar *flag_ptr; /* Flexible array member; will be allocated to opt_gtid_index_page_size. */ uchar page[]; }; struct Index_node_base { Node_page *first_page; Node_page *current_page; /* The current_ptr is only valid if current_page != 0. */ uchar *current_ptr; Index_node_base(); ~Index_node_base(); void free_pages(); void reset(); }; public: static void make_gtid_index_file_name(char *out_name, size_t bufsize, const char *base_filename); protected: int update_gtid_state(rpl_binlog_state_base *state, const rpl_gtid *gtid_list, uint32 gtid_count); Node_page *alloc_page(); rpl_gtid *gtid_list_buffer(uint32 count); void build_index_filename(const char *filename); virtual int give_error(const char *msg) = 0; /* A buffer to hold a gtid_list temporarily. Increased as needed to hold largest needed list. */ rpl_gtid *gtid_buffer; uint32 gtid_buffer_alloc; size_t page_size; public: char index_file_name[GTID_INDEX_FILENAME_MAX_SIZE]; protected: Gtid_index_base(); virtual ~Gtid_index_base(); }; class Gtid_index_writer : public Gtid_index_base { private: const my_off_t offset_min_threshold; struct Index_node : public Index_node_base { rpl_binlog_state_base state; uint32 num_records; uint32 level; bool force_spill_page; Index_node(uint32 level_); ~Index_node(); void reset(); }; public: static void gtid_index_init(); static void gtid_index_cleanup(); protected: friend class Gtid_index_reader_hot; static void lock_gtid_index() { mysql_mutex_lock(>id_index_mutex); } static void unlock_gtid_index() { mysql_mutex_unlock(>id_index_mutex); } static const Gtid_index_writer *find_hot_index(const char *file_name); public: Gtid_index_writer(const char *filename, uint32 offset, rpl_binlog_state_base *binlog_state, uint32 opt_page_size, my_off_t opt_span_min); virtual ~Gtid_index_writer(); void process_gtid(uint32 offset, const rpl_gtid *gtid); int process_gtid_check_batch(uint32 offset, const rpl_gtid *gtid, rpl_gtid **out_gtid_list, uint32 *out_gtid_count); int async_update(uint32 event_offset, rpl_gtid *gtid_list, uint32 gtid_count); void close(); private: void insert_in_hot_index(); void remove_from_hot_index(); uint32 write_current_node(uint32 level, bool is_root); int reserve_space(Index_node *n, size_t bytes); int do_write_record(uint32 level, uint32 event_offset, const rpl_gtid *gtid_list, uint32 gtid_count); int add_child_ptr(uint32 level, my_off_t node_offset); int write_record(uint32 event_offset, const rpl_gtid *gtid_list, uint32 gtid_count); bool check_room(uint32 level, uint32 gtid_count); int alloc_level_if_missing(uint32 level); uchar *init_header(Node_page *page, bool is_leaf, bool is_first); int give_error(const char *msg) override; static mysql_mutex_t gtid_index_mutex; static Gtid_index_writer *hot_index_list; rpl_binlog_state_base pending_state; /* Next pointer for the hot_index_list linked list. */ Gtid_index_writer *next_hot_index; /* The currently being built index nodes, from leaf[0] to root[max_level]. */ Index_node **nodes; my_off_t previous_offset; uint32 max_level; File index_file; /* This is set if we encounter an error (such as out-of-memory or I/O error). Then we will no longer do any updates to the index, to prevent leaving a corrupt index. This is not fatal; the partial index will work up to where it got the error, and the code can fall-back to sequential scan of the binlog. */ bool error_state; /* Flag to help put the file header at the start of the very first page. */ bool file_header_written; /* Flag set while this object is visible in the "hot index" list. */ bool in_hot_index_list; }; class Gtid_index_reader : public Gtid_index_base { public: Gtid_index_reader(); virtual ~Gtid_index_reader(); int open_index_file(const char *binlog_filename); void close_index_file(); /* The search functions take either a binlog offset or GTID position to search for. They return: 0 for "not found" (searched position is earlier than start of index). 1 for "found" -1 for error. When found, the returned position is the last position in the index that lies at or before the searched position. The offset of the returned position is written to *out_offset. The number of GTIDs in the returned GTID state is written to *out_gtid_count; the list of found GTIDs can be accessed with search_gtid_list() and is valid only until next search or freeing of the Gtid_index_reader object. */ int search_offset(uint32 in_offset, uint32 *out_offset, uint32 *out_gtid_count); int search_gtid_pos(slave_connection_state *in_gtid_pos, uint32 *out_offset, uint32 *out_gtid_count); rpl_gtid *search_gtid_list(); protected: int search_cmp_offset(uint32 offset, rpl_binlog_state_base *state); int search_cmp_gtid_pos(uint32 offset, rpl_binlog_state_base *state); virtual int do_index_search(uint32 *out_offset, uint32 *out_gtid_count); int do_index_search_root(uint32 *out_offset, uint32 *out_gtid_count); int do_index_search_leaf(bool current_state_updated, uint32 *out_offset, uint32 *out_gtid_count); int next_page(); int find_bytes(uint32 num_bytes); virtual int get_child_ptr(uint32 *out_child_ptr); int get_offset_count(uint32 *out_offset, uint32 *out_gtid_count); int get_gtid_list(rpl_gtid *out_gtid_list, uint32 count); virtual int read_file_header(); int verify_checksum(Node_page *page); Node_page *alloc_and_read_page(); virtual int read_root_node(); virtual int read_node(uint32 page_ptr); int read_node_cold(uint32 page_ptr); int give_error(const char *msg) override; rpl_binlog_state_base current_state; rpl_binlog_state_base compare_state; Index_node_base cold_node; /* n points to either cold node or hot node in writer. */ Index_node_base *n; int (Gtid_index_reader::* search_cmp_function)(uint32, rpl_binlog_state_base *); slave_connection_state *in_search_gtid_pos; Node_page *read_page; uchar *read_ptr; File index_file; uint32 current_offset; uint32 in_search_offset; bool file_open; bool index_valid; bool has_root_node; uchar version_major; uchar version_minor; }; /* Sub-class of Gtid_index_reader that can additionally access in-memory "hot" pages of the index, which are partially filled pages of the current binlog file, not yet written to disk. */ class Gtid_index_reader_hot : public Gtid_index_reader { public: Gtid_index_reader_hot(); virtual ~Gtid_index_reader_hot() { } private: int do_index_search(uint32 *out_offset, uint32 *out_gtid_count) override; int get_child_ptr(uint32 *out_child_ptr) override; int read_file_header() override; int read_root_node() override; int read_node(uint32 page_ptr) override; int read_node_hot(); /* Pointer to the writer object, if we're reading a hot index. */ const Gtid_index_writer *hot_writer; /* The level we are currently reading in the hot writer .*/ uint32 hot_level; }; #endif /* GTID_INDEX_H */ sql_type_fixedbin_storage.h 0000644 00000012533 15156036171 0012162 0 ustar 00 #ifndef SQL_TYPE_FIXEDBIN_STORAGE #define SQL_TYPE_FIXEDBIN_STORAGE /* Copyright (c) 2019,2021 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This is a common code for plugin (?) types that are generally handled like strings, but have their own fixed size on-disk binary storage format and their own (variable size) canonical string representation. Examples are INET6 and UUID types. The MariaDB server uses three binary representations of a data type: 1. In-memory binary representation (user visible) This representation: - can be used in INSERT..VALUES (X'AABBCC') - can be used in WHERE conditions: WHERE c1=X'AABBCC' - is returned by CAST(x AS BINARY(N)) - is returned by Field::val_native() and Item::val_native() 2. In-record binary representation (user invisible) This representation: - is used in records (is pointed by Field::ptr) - must be comparable by memcmp() 3. Binlog binary (row) representation Usually, for string data types the binlog representation is based on the in-record representation with trailing byte compression: - trailing space compression for text string data types - trailing zero compression for binary string data types We have to have separate in-memory and in-record representations because we use HA_KEYTYPE_BINARY for indexing. The engine API does not have a way to pass a comparison function as a parameter. The default implementation below assumes that: - the in-memory and in-record representations are equal - the binlog representation is compatible with BINARY(N) This is OK for simple data types, like INET6. Data type implementations that need different representations can override the default implementation (like e.g. UUID does). */ /***********************************************************************/ template<size_t NATIVE_LEN, size_t MAX_CHAR_LEN> class FixedBinTypeStorage { protected: // The buffer that stores the in-memory binary representation char m_buffer[NATIVE_LEN]; FixedBinTypeStorage() = default; FixedBinTypeStorage & set_zero() { bzero(&m_buffer, sizeof(m_buffer)); return *this; } public: // Initialize from the in-memory binary representation FixedBinTypeStorage(const char *str, size_t length) { if (length != binary_length()) set_zero(); else memcpy(&m_buffer, str, sizeof(m_buffer)); } // Return the buffer with the in-memory representation Lex_cstring to_lex_cstring() const { return Lex_cstring(m_buffer, sizeof(m_buffer)); } static constexpr uint binary_length() { return NATIVE_LEN; } static constexpr uint max_char_length() { return MAX_CHAR_LEN; } // Compare the in-memory binary representations of two values static int cmp(const LEX_CSTRING &a, const LEX_CSTRING &b) { DBUG_ASSERT(a.length == binary_length()); DBUG_ASSERT(b.length == binary_length()); return memcmp(a.str, b.str, b.length); } /* Convert from the in-memory to the in-record representation. Used in Field::store_native(). */ static void memory_to_record(char *to, const char *from) { memcpy(to, from, NATIVE_LEN); } /* Convert from the in-record to the in-memory representation Used in Field::val_native(). */ static void record_to_memory(char *to, const char *from) { memcpy(to, from, NATIVE_LEN); } /* Hash the in-record representation Used in Field::hash(). */ static void hash_record(uchar *ptr, Hasher *hasher) { hasher->add(&my_charset_bin, ptr, binary_length()); } static bool only_zero_bytes(const char *ptr, size_t length) { for (uint i= 0 ; i < length; i++) { if (ptr[i] != 0) return false; } return true; } static ulong KEY_pack_flags(uint column_nr) { /* Return zero by default. A particular data type can override this method return some flags, e.g. HA_PACK_KEY to enable key prefix compression. */ return 0; } /* Convert from the in-record to the binlog representation. Used in Field::pack(), and in filesort to store the addon fields. By default, do what BINARY(N) does. */ static uchar *pack(uchar *to, const uchar *from, uint max_length) { return StringPack(&my_charset_bin, binary_length()).pack(to, from, max_length); } /* Convert from the in-binary-log to the in-record representation. Used in Field::unpack(). By default, do what BINARY(N) does. */ static const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) { return StringPack(&my_charset_bin, binary_length()).unpack(to, from, from_end, param_data); } }; #endif /* SQL_TYPE_FIXEDBIN_STORAGE */ heap.h 0000644 00000022410 15156036171 0005636 0 ustar 00 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file should be included when using heap_database_functions */ /* Author: Michael Widenius */ #ifndef _heap_h #define _heap_h #ifdef __cplusplus extern "C" { #endif #ifndef _my_base_h #include <my_base.h> #endif #include <my_pthread.h> #include <thr_lock.h> #include "my_compare.h" #include "my_tree.h" /* defines used by heap-functions */ #define HP_MAX_LEVELS 4 /* 128^5 records is enough */ #define HP_PTRS_IN_NOD 128 /* struct used with heap_functions */ typedef struct st_heapinfo /* Struct from heap_info */ { ulong records; /* Records in database */ ulong deleted; /* Deleted records in database */ ulong max_records; ulonglong data_length; ulonglong index_length; uint reclength; /* Length of one record */ int errkey; ulonglong auto_increment; time_t create_time; } HEAPINFO; /* Structs used by heap-database-handler */ typedef struct st_heap_ptrs { uchar *blocks[HP_PTRS_IN_NOD]; /* pointers to HP_PTRS or records */ } HP_PTRS; struct st_level_info { /* Number of unused slots in *last_blocks HP_PTRS block (0 for 0th level) */ uint free_ptrs_in_block; /* Maximum number of records that can be 'contained' inside of each element of last_blocks array. For level 0 - 1, for level 1 - HP_PTRS_IN_NOD, for level 2 - HP_PTRS_IN_NOD^2 and so forth. */ ulong records_under_level; /* Ptr to last allocated HP_PTRS (or records buffer for level 0) on this level. */ HP_PTRS *last_blocks; }; /* Heap table records and hash index entries are stored in HP_BLOCKs. HP_BLOCK is used as a 'growable array' of fixed-size records. Size of record is recbuffer bytes. The internal representation is as follows: HP_BLOCK is a hierarchical structure of 'blocks'. A block at level 0 is an array records_in_block records. A block at higher level is an HP_PTRS structure with pointers to blocks at lower levels. At the highest level there is one top block. It is stored in HP_BLOCK::root. See hp_find_block for a description of how record pointer is obtained from its index. See hp_get_new_block */ typedef struct st_heap_block { HP_PTRS *root; /* Top-level block */ struct st_level_info level_info[HP_MAX_LEVELS+1]; uint levels; /* number of used levels */ uint recbuffer; /* Length of one saved record */ ulong records_in_block; /* Records in one heap-block */ ulong last_allocated; /* number of records there is allocated space for */ size_t alloc_size; /* Allocate blocks of this size */ } HP_BLOCK; struct st_heap_info; /* For reference */ typedef struct st_hp_keydef /* Key definition with open */ { uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */ uint keysegs; /* Number of key-segment */ uint length; /* Length of key (automatic) */ uint8 algorithm; /* HASH / BTREE */ HA_KEYSEG *seg; HP_BLOCK block; /* Where keys are saved */ /* Number of buckets used in hash table. Used only to provide #records estimates for heap key scans. */ ha_rows hash_buckets; TREE rb_tree; int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo, const uchar *record, uchar *recpos); int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo, const uchar *record, uchar *recpos, int flag); uint (*get_key_length)(struct st_hp_keydef *keydef, const uchar *key); } HP_KEYDEF; typedef struct st_heap_share { HP_BLOCK block; HP_KEYDEF *keydef; ulonglong data_length,index_length,max_table_size; ulonglong auto_increment; ulong min_records,max_records; /* Params to open */ ulong records; /* records */ ulong blength; /* records rounded up to 2^n */ ulong deleted; /* Deleted records in database */ uint key_stat_version; /* version to indicate insert/delete */ uint key_version; /* Updated on key change */ uint file_version; /* Update on clear */ uint reclength; /* Length of one record */ uint visible; /* Offset to the visible/deleted mark */ uint changed; uint keys,max_key_length; uint currently_disabled_keys; /* saved value from "keys" when disabled */ uint open_count; uchar *del_link; /* Link to next block with del. rec */ char * name; /* Name of "memory-file" */ time_t create_time; THR_LOCK lock; my_bool delete_on_close; my_bool internal; /* Internal temporary table */ LIST open_list; uint auto_key; uint auto_key_type; /* real type of the auto key segment */ } HP_SHARE; struct st_hp_hash_info; typedef struct st_heap_info { HP_SHARE *s; uchar *current_ptr; struct st_hp_hash_info *current_hash_ptr; ulong current_record,next_block; int lastinx,errkey; int mode; /* Mode of file (READONLY..) */ uint opt_flag,update; uchar *lastkey; /* Last used key with rkey */ uchar *recbuf; /* Record buffer for rb-tree keys */ enum ha_rkey_function last_find_flag; TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1]; TREE_ELEMENT **last_pos; uint key_version; /* Version at last read */ uint file_version; /* Version at scan */ uint lastkey_len; my_bool implicit_emptied; THR_LOCK_DATA lock; LIST open_list; } HP_INFO; typedef struct st_heap_create_info { HP_KEYDEF *keydef; uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; uint keys; uint reclength; ulong max_records; ulong min_records; ulonglong max_table_size; ulonglong auto_increment; my_bool with_auto_increment; my_bool internal_table; /* TRUE if heap_create should 'pin' the created share by setting open_count to 1. Is only looked at if not internal_table. */ my_bool pin_share; } HP_CREATE_INFO; /* Prototypes for heap-functions */ extern HP_INFO *heap_open(const char *name, int mode); extern HP_INFO *heap_open_from_share(HP_SHARE *share, int mode); extern HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode); extern void heap_release_share(HP_SHARE *share, my_bool internal_table); extern int heap_close(HP_INFO *info); extern int heap_write(HP_INFO *info,const uchar *buff); extern int heap_update(HP_INFO *info,const uchar *old,const uchar *newdata); extern int heap_rrnd(HP_INFO *info,uchar *buf,uchar *pos); extern int heap_scan_init(HP_INFO *info); extern int heap_scan(HP_INFO *info, uchar *record); extern int heap_delete(HP_INFO *info,const uchar *buff); extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); extern int heap_create(const char *name, HP_CREATE_INFO *create_info, HP_SHARE **share, my_bool *created_new_share); extern int heap_delete_table(const char *name); extern void heap_drop_table(HP_INFO *info); extern int heap_extra(HP_INFO *info,enum ha_extra_function function); extern int heap_reset(HP_INFO *info); extern int heap_rename(const char *old_name,const char *new_name); extern int heap_panic(enum ha_panic_function flag); extern int heap_rsame(HP_INFO *info,uchar *record,int inx); extern int heap_rnext(HP_INFO *info,uchar *record); extern int heap_rprev(HP_INFO *info,uchar *record); extern int heap_rfirst(HP_INFO *info,uchar *record,int inx); extern int heap_rlast(HP_INFO *info,uchar *record,int inx); extern void heap_clear(HP_INFO *info); extern void heap_clear_keys(HP_INFO *info); extern int heap_disable_indexes(HP_INFO *info); extern int heap_enable_indexes(HP_INFO *info); extern int heap_indexes_are_disabled(HP_INFO *info); extern void heap_update_auto_increment(HP_INFO *info, const uchar *record); ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const key_range *min_key, const key_range *max_key); int hp_panic(enum ha_panic_function flag); int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag); extern uchar * heap_find(HP_INFO *info,int inx,const uchar *key); extern int heap_check_heap(const HP_INFO *info, my_bool print_status); extern uchar *heap_position(HP_INFO *info); /* The following is for programs that uses the old HEAP interface where pointer to rows where a long instead of a (uchar*). */ #if defined(WANT_OLD_HEAP_VERSION) || defined(OLD_HEAP_VERSION) extern int heap_rrnd_old(HP_INFO *info,uchar *buf,ulong pos); extern ulong heap_position_old(HP_INFO *info); #endif #ifdef OLD_HEAP_VERSION typedef ulong HEAP_PTR; #define heap_position(A) heap_position_old(A) #define heap_rrnd(A,B,C) heap_rrnd_old(A,B,C) #else typedef uchar *HEAP_PTR; #endif #ifdef __cplusplus } #endif #endif threadpool.h 0000644 00000011312 15156036171 0007061 0 ustar 00 /* Copyright (C) 2012, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #ifdef HAVE_POOL_OF_THREADS #define MAX_THREAD_GROUPS 100000 /* Threadpool parameters */ extern uint threadpool_min_threads; /* Minimum threads in pool */ extern uint threadpool_idle_timeout; /* Shutdown idle worker threads after this timeout */ extern uint threadpool_size; /* Number of parallel executing threads */ extern uint threadpool_max_size; extern uint threadpool_stall_limit; /* time interval in milliseconds for stall checks*/ extern uint threadpool_max_threads; /* Maximum threads in pool */ extern uint threadpool_oversubscribe; /* Maximum active threads in group */ extern uint threadpool_prio_kickup_timer; /* Time before low prio item gets prio boost */ extern my_bool threadpool_exact_stats; /* Better queueing time stats for information_schema, at small performance cost */ extern my_bool threadpool_dedicated_listener; /* Listener thread does not pick up work items. */ #ifdef _WIN32 extern uint threadpool_mode; /* Thread pool implementation , windows or generic */ #define TP_MODE_WINDOWS 0 #define TP_MODE_GENERIC 1 #endif #define DEFAULT_THREADPOOL_STALL_LIMIT 500U struct TP_connection; struct st_vio; extern void tp_callback(TP_connection *c); extern void tp_timeout_handler(TP_connection *c); /* Threadpool statistics */ struct TP_STATISTICS { /* Current number of worker thread. */ Atomic_counter<uint32_t> num_worker_threads; }; extern TP_STATISTICS tp_stats; /* Functions to set threadpool parameters */ extern void tp_set_min_threads(uint val); extern void tp_set_max_threads(uint val); extern void tp_set_threadpool_size(uint val); extern void tp_set_threadpool_stall_limit(uint val); extern int tp_get_idle_thread_count(); extern int tp_get_thread_count(); enum TP_PRIORITY { TP_PRIORITY_HIGH, TP_PRIORITY_LOW, TP_PRIORITY_AUTO }; enum TP_STATE { TP_STATE_IDLE, TP_STATE_RUNNING, TP_STATE_PENDING }; /* Connection structure, encapsulates THD + structures for asynchronous IO and pool. Platform specific parts are specified in subclasses called connection_t, inside threadpool_win.cc and threadpool_unix.cc */ class CONNECT; struct TP_connection { THD* thd; CONNECT* connect; TP_STATE state; TP_PRIORITY priority; TP_connection(CONNECT *c) : thd(0), connect(c), state(TP_STATE_IDLE), priority(TP_PRIORITY_HIGH) {} virtual ~TP_connection() = default; /* Initialize io structures windows threadpool, epoll etc */ virtual int init() = 0; virtual void set_io_timeout(int sec) = 0; /* Read for the next client command (async) with specified timeout */ virtual int start_io() = 0; virtual void wait_begin(int type)= 0; virtual void wait_end() = 0; IF_WIN(virtual,) void init_vio(st_vio *){}; }; struct TP_pool { virtual ~TP_pool() = default; virtual int init()= 0; virtual TP_connection *new_connection(CONNECT *)= 0; virtual void add(TP_connection *c)= 0; virtual int set_max_threads(uint){ return 0; } virtual int set_min_threads(uint){ return 0; } virtual int set_pool_size(uint){ return 0; } virtual int set_idle_timeout(uint){ return 0; } virtual int set_oversubscribe(uint){ return 0; } virtual int set_stall_limit(uint){ return 0; } virtual int get_thread_count() { return tp_stats.num_worker_threads; } virtual int get_idle_thread_count(){ return 0; } virtual void resume(TP_connection* c)=0; }; #ifdef _WIN32 struct TP_pool_win:TP_pool { TP_pool_win(); int init() override; ~TP_pool_win() override; TP_connection *new_connection(CONNECT *c) override; void add(TP_connection *) override; int set_max_threads(uint) override; int set_min_threads(uint) override; void resume(TP_connection *c) override; }; #endif struct TP_pool_generic :TP_pool { TP_pool_generic(); ~TP_pool_generic(); int init() override; TP_connection *new_connection(CONNECT *c) override; void add(TP_connection *) override; int set_pool_size(uint) override; int set_stall_limit(uint) override; int get_idle_thread_count() override; void resume(TP_connection* c) override; }; #endif /* HAVE_POOL_OF_THREADS */ proxy_protocol.h 0000644 00000001044 15156036171 0010023 0 ustar 00 #include "my_net.h" struct proxy_peer_info { struct sockaddr_storage peer_addr; int port; bool is_local_command; }; extern bool has_proxy_protocol_header(NET *net); extern int parse_proxy_protocol_header(NET *net, proxy_peer_info *peer_info); extern bool is_proxy_protocol_allowed(const sockaddr *remote_addr); extern int init_proxy_protocol_networks(const char *spec); extern void destroy_proxy_protocol_networks(); extern int set_proxy_protocol_networks(const char *spec); extern bool proxy_protocol_networks_valid(const char *spec); sql_test.h 0000644 00000003065 15156036171 0006564 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_TEST_INCLUDED #define SQL_TEST_INCLUDED #include "mysqld.h" #include "opt_trace_context.h" class JOIN; struct TABLE_LIST; typedef class Item COND; typedef class st_select_lex SELECT_LEX; struct SORT_FIELD; #ifndef DBUG_OFF void print_where(COND *cond,const char *info, enum_query_type query_type); void TEST_filesort(SORT_FIELD *sortorder,uint s_length); void TEST_join(JOIN *join); void print_plan(JOIN* join,uint idx, double record_count, double read_time, double current_read_time, const char *info); void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array); void print_sjm(SJ_MATERIALIZATION_INFO *sjm); void dump_TABLE_LIST_graph(SELECT_LEX *select_lex, TABLE_LIST* tl); #endif void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array); void mysql_print_status(); #endif /* SQL_TEST_INCLUDED */ opt_trace_context.h 0000644 00000006333 15156036171 0010453 0 ustar 00 #ifndef OPT_TRACE_CONTEXT_INCLUDED #define OPT_TRACE_CONTEXT_INCLUDED #include "sql_array.h" class Opt_trace_context; struct Opt_trace_info; class Json_writer; class Opt_trace_stmt { public: /** Constructor, starts a trace for information_schema and dbug. @param ctx_arg context */ Opt_trace_stmt(Opt_trace_context *ctx_arg); ~Opt_trace_stmt(); void set_query(const char *query_ptr, size_t length, const CHARSET_INFO *charset); void open_struct(const char *key, char opening_bracket); void close_struct(const char *saved_key, char closing_bracket); void fill_info(Opt_trace_info* info); void add(const char *key, char *opening_bracket, size_t val_length); Json_writer* get_current_json() {return current_json;} void missing_privilege(); void disable_tracing_for_children(); void enable_tracing_for_children(); bool is_enabled() { return I_S_disabled == 0; } void set_allowed_mem_size(size_t mem_size); size_t get_length(); size_t get_truncated_bytes(); bool get_missing_priv() { return missing_priv; } private: Opt_trace_context *ctx; String query; // store the query sent by the user Json_writer *current_json; // stores the trace bool missing_priv; ///< whether user lacks privilege to see this trace /* 0 <=> this trace should be in information_schema. !=0 tracing is disabled, this currently happens when we want to trace a sub-statement. For now traces are only collect for the top statement not for the sub-statments. */ uint I_S_disabled; }; class Opt_trace_context { public: Opt_trace_context(); ~Opt_trace_context(); void start(THD *thd, TABLE_LIST *tbl, enum enum_sql_command sql_command, const char *query, size_t query_length, const CHARSET_INFO *query_charset, ulong max_mem_size_arg); void end(); void set_query(const char *query, size_t length, const CHARSET_INFO *charset); void delete_traces(); void set_allowed_mem_size(size_t mem_size); size_t remaining_mem_size(); private: Opt_trace_stmt* top_trace() { return *(traces.front()); } public: /* This returns the top trace from the list of traces. This function is used when we want to see the contents of the INFORMATION_SCHEMA.OPTIMIZER_TRACE table. */ Opt_trace_stmt* get_top_trace() { if (!traces.elements()) return NULL; return top_trace(); } /* This returns the current trace, to which we are still writing and has not been finished */ Json_writer* get_current_json() { if (!is_started()) return NULL; return current_trace->get_current_json(); } bool empty() { return static_cast<uint>(traces.elements()) == 0; } bool is_started() { return current_trace && current_trace->is_enabled(); } bool disable_tracing_if_required(); bool enable_tracing_if_required(); bool is_enabled(); void missing_privilege(); static const char *flag_names[]; enum { FLAG_DEFAULT = 0, FLAG_ENABLED = 1 << 0 }; private: /* List of traces (currently it stores only 1 trace) */ Dynamic_array<Opt_trace_stmt*> traces; Opt_trace_stmt *current_trace; size_t max_mem_size; }; #endif /* OPT_TRACE_CONTEXT_INCLUDED */ contributors.h 0000644 00000011416 15156036171 0007462 0 ustar 00 #ifndef CONTRIBUTORS_INCLUDED #define CONTRIBUTORS_INCLUDED /* Copyright (c) 2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Structure of the name list */ struct show_table_contributors_st { const char *name; const char *location; const char *comment; }; /* Output from "SHOW CONTRIBUTORS" Get permission before editing. Names should be encoded using UTF-8. See also https://mariadb.com/kb/en/log-of-mariadb-contributions/ */ struct show_table_contributors_st show_table_contributors[]= { /* MariaDB Foundation sponsors, alphabetical by tier */ {"Amazon", "https://www.amazon.com/", "Diamond Sponsor of the MariaDB Foundation"}, {"Acronis", "https://www.acronis.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"Alibaba Cloud", "https://www.alibabacloud.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"C<onstructor", "https://www.constructor.org/", "Platinum Sponsor of the MariaDB Foundation"}, {"Development Bank of Singapore", "https://www.dbs.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"Intel", "https://www.intel.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"MariaDB plc", "https://mariadb.com/", "Founding member, Platinum Sponsor of the MariaDB Foundation"}, {"ServiceNow", "https://servicenow.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"WebPros", "https://webpros.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"IBM", "https://www.ibm.com/", "Gold Sponsor of the MariaDB Foundation"}, {"IONOS", "https://www.ionos.com/", "Gold Sponsor of the MariaDB Foundation"}, {"Automattic", "https://automattic.com/", "Silver Sponsor of the MariaDB Foundation"}, {"SkySQL", "https://skysql.com/", "Silver Sponsor of the MariaDB Foundation"}, {"team.blue", "https://team.blue/", "Silver Sponsor of the MariaDB Foundation"}, {"Tencent Cloud", "https://cloud.tencent.com/", "Silver Sponsor of the MariaDB Foundation"}, {"Wikimedia Foundation", "https://www.wikimediafoundation.org/", "Silver Sponsor of the MariaDB Foundation"}, {"Cyber Leo", "https://cyberleo.com/", "Bronze Sponsor of the MariaDB Foundation"}, {"Hetzner", "https://www.hetzner.com/", "Bronze Sponsor of the MariaDB Foundation"}, {"Rumahweb", "https://rumahweb.com/", "Bronze Sponsor of the MariaDB Foundation"}, {"Tasjeel.ae", "https://tasjeel.ae/", "Bronze Sponsor of the MariaDB Foundation"}, {"Galera Cluster", "https://galeracluster.com/", "Sponsor of the MariaDB Foundation"}, {"Percona", "https://www.percona.com/", "Sponsor of the MariaDB Foundation"}, {"Vettabase", "https://vettabase.com/", "Technology partner of the MariaDB Foundation"}, {"Booking.com", "", "Previous Sponsor of the MariaDB Foundation"}, {"Jelastic.com", "", "Previous Sponsor of the MariaDB Foundation"}, {"Microsoft", "", "Previous Sponsor of the MariaDB Foundation"}, {"Nexedi", "", "Previous Sponsor of the MariaDB Foundation"}, {"Open Query", "", "Previous Sponsor of the MariaDB Foundation"}, {"Planeetta Web Hosting", "", "Previous Sponsor of the MariaDB Foundation"}, {"SpringbokSQL", "", "Previous Sponsor of the MariaDB Foundation"}, {"Tencent Games", "", "Previous Sponsor of the MariaDB Foundation"}, {"Tencent Game DBA", "", "Previous Sponsor of the MariaDB Foundation"}, {"Tencent TDSQL", "", "Previous Sponsor of the MariaDB Foundation"}, {"Verkkokauppa", "", "Previous Sponsor of the MariaDB Foundation"}, {"Virtuozzo", "", "Previous Sponsor of the MariaDB Foundation"}, {"Visma", "", "Previous Sponsor of the MariaDB Foundation"}, {"Webyog", "", "Previous Sponsor of the MariaDB Foundation"}, /* Sponsors of important features */ {"Google", "USA", "Sponsoring encryption, parallel replication and GTID"}, {"Facebook", "USA", "Sponsoring non-blocking API, LIMIT ROWS EXAMINED etc"}, /* Individual contributors, names in historical order, newer first */ {"Ronald Bradford", "Brisbane, Australia", "EFF contribution for UC2006 Auction"}, {"Sheeri Kritzer", "Boston, Mass. USA", "EFF contribution for UC2006 Auction"}, {"Mark Shuttleworth", "London, UK.", "EFF contribution for UC2006 Auction"}, {NULL, NULL, NULL} }; #endif /* CONTRIBUTORS_INCLUDED */ multi_range_read.h 0000644 00000055231 15156036172 0010232 0 ustar 00 /* Copyright (c) 2009, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @defgroup DS-MRR declarations @{ */ /** A Disk-Sweep implementation of MRR Interface (DS-MRR for short) This is a "plugin"(*) for storage engines that allows to 1. When doing index scans, read table rows in rowid order; 2. when making many index lookups, do them in key order and don't lookup the same key value multiple times; 3. Do both #1 and #2, when applicable. These changes are expected to speed up query execution for disk-based storage engines running io-bound loads and "big" queries (ie. queries that do joins and enumerate lots of records). (*) - only conceptually. No dynamic loading or binary compatibility of any kind. General scheme of things: SQL Layer code | | | v v v -|---|---|---- handler->multi_range_read_XXX() function calls | | | _____________________________________ / DS-MRR module \ | (order/de-duplicate lookup keys, | | scan indexes in key order, | | order/de-duplicate rowids, | | retrieve full record reads in rowid | | order) | \_____________________________________/ | | | -|---|---|----- handler->read_range_first()/read_range_next(), | | | handler->index_read(), handler->rnd_pos() calls. | | | v v v Storage engine internals Currently DS-MRR is used by MyISAM, InnoDB and Maria storage engines. Potentially it can be used with any table handler that has disk-based data storage and has better performance when reading data in rowid order. */ #include "sql_lifo_buffer.h" class DsMrr_impl; class Mrr_ordered_index_reader; /* A structure with key parameters that's shared among several classes */ class Key_parameters { public: uint key_tuple_length; /* Length of index lookup tuple, in bytes */ key_part_map key_tuple_map; /* keyparts used in index lookup tuples */ /* This is = key_tuple_length if we copy keys to buffer = sizeof(void*) if we're using pointers to materialized keys. */ uint key_size_in_keybuf; /* TRUE <=> don't copy key values, use pointers to them instead. */ bool use_key_pointers; /* TRUE <=> We can get at most one index tuple for a lookup key */ bool index_ranges_unique; }; /** A class to enumerate (record, range_id) pairs that match given key value. @note The idea is that we have a Lifo_buffer which holds (key, range_id) pairs ordered by key value. From the front of the buffer we see (key_val1, range_id1), (key_val1, range_id2) ... (key_val2, range_idN) we take the first elements that have the same key value (key_val1 in the example above), and make lookup into the table. The table will have multiple matches for key_val1: == Table Index == ... key_val1 -> key_val1, index_tuple1 key_val1, index_tuple2 ... key_val1, index_tupleN ... Our goal is to produce all possible combinations, i.e. we need: {(key_val1, index_tuple1), range_id1} {(key_val1, index_tuple1), range_id2} ... ... | {(key_val1, index_tuple1), range_idN}, {(key_val1, index_tuple2), range_id1} {(key_val1, index_tuple2), range_id2} ... ... | {(key_val1, index_tuple2), range_idN}, ... ... ... {(key_val1, index_tupleK), range_idN} */ class Key_value_records_iterator { /* Use this to get table handler, key buffer and other parameters */ Mrr_ordered_index_reader *owner; /* Iterator to get (key, range_id) pairs from */ Lifo_buffer_iterator identical_key_it; /* Last of the identical key values (when we get this pointer from identical_key_it, it will be time to stop). */ uchar *last_identical_key_ptr; /* FALSE <=> we're right after the init() call, the record has been already read with owner->file->index_read_map() call */ bool get_next_row; public: int init(Mrr_ordered_index_reader *owner_arg); int get_next(range_id_t *range_info); void move_to_next_key_value(); }; /* Buffer manager interface. Mrr_reader objects use it to inqure DsMrr_impl to manage buffer space for them. */ typedef struct st_buffer_manager { public: /* Opaque value to be passed as the first argument to all member functions */ void *arg; /* This is called when we've freed more space from the rowid buffer. The callee will get the unused space from the rowid buffer and give it to the key buffer. */ void (*redistribute_buffer_space)(void *arg); /* This is called when both key and rowid buffers are empty, and so it's time to reset them to their original size (They've lost their original size, because we were dynamically growing rowid buffer and shrinking key buffer). */ void (*reset_buffer_sizes)(void *arg); } Buffer_manager; /* Mrr_reader - DS-MRR execution strategy abstraction A reader produces ([index]_record, range_info) pairs, and requires periodic refill operations. - one starts using the reader by calling reader->get_next(), - when a get_next() call returns HA_ERR_END_OF_FILE, one must call refill_buffer() before they can make more get_next() calls. - when refill_buffer() returns HA_ERR_END_OF_FILE, this means the real end of stream and get_next() should not be called anymore. Both functions can return other error codes, these mean unrecoverable errors after which one cannot continue. */ class Mrr_reader { public: virtual int get_next(range_id_t *range_info) = 0; virtual int refill_buffer(bool initial) = 0; virtual ~Mrr_reader() = default; /* just to remove compiler warning */ }; /* A common base for readers that do index scans and produce index tuples */ class Mrr_index_reader : public Mrr_reader { protected: handler *file; /* Handler object to use */ public: virtual int init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, void *seq_init_param, uint n_ranges, uint mode, Key_parameters *key_par, Lifo_buffer *key_buffer, Buffer_manager *buf_manager_arg) = 0; /* Get pointer to place where every get_next() call will put rowid */ virtual uchar *get_rowid_ptr() = 0; /* Get the rowid (call this after get_next() call) */ virtual void position(); virtual bool skip_record(range_id_t range_id, uchar *rowid) = 0; virtual void interrupt_read() {} virtual void resume_read() {} }; /* A "bypass" index reader that just does and index scan. The index scan is done by calling default MRR implementation (i.e. handler::multi_range_read_XXX()) functions. */ class Mrr_simple_index_reader : public Mrr_index_reader { public: int init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, void *seq_init_param, uint n_ranges, uint mode, Key_parameters *key_par, Lifo_buffer *key_buffer, Buffer_manager *buf_manager_arg) override; int get_next(range_id_t *range_info) override; int refill_buffer(bool initial) override { return initial? 0: HA_ERR_END_OF_FILE; } uchar *get_rowid_ptr() override { return file->ref; } bool skip_record(range_id_t range_id, uchar *rowid) override { return (file->mrr_funcs.skip_record && file->mrr_funcs.skip_record(file->mrr_iter, range_id, rowid)); } }; /* A reader that sorts the key values before it makes the index lookups. */ class Mrr_ordered_index_reader : public Mrr_index_reader { public: int init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, void *seq_init_param, uint n_ranges, uint mode, Key_parameters *key_par, Lifo_buffer *key_buffer, Buffer_manager *buf_manager_arg) override; int get_next(range_id_t *range_info) override; int refill_buffer(bool initial) override; uchar *get_rowid_ptr() override { return file->ref; } bool skip_record(range_id_t range_info, uchar *rowid) override { return (mrr_funcs.skip_record && mrr_funcs.skip_record(mrr_iter, range_info, rowid)); } bool skip_index_tuple(range_id_t range_info) { return (mrr_funcs.skip_index_tuple && mrr_funcs.skip_index_tuple(mrr_iter, range_info)); } bool set_interruption_temp_buffer(uint rowid_length, uint key_len, uint saved_pk_len, uchar **space_start, uchar *space_end); void set_no_interruption_temp_buffer(); void interrupt_read() override; void resume_read() override; void position() override; private: Key_value_records_iterator kv_it; bool scanning_key_val_iter; /* Buffer to store (key, range_id) pairs */ Lifo_buffer *key_buffer; /* This manages key buffer allocation and sizing for us */ Buffer_manager *buf_manager; Key_parameters keypar; /* index scan and lookup tuple parameters */ /* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */ bool is_mrr_assoc; /* Range sequence iteration members */ RANGE_SEQ_IF mrr_funcs; range_seq_t mrr_iter; /* TRUE == reached eof when enumerating ranges */ bool source_exhausted; /* Following members are for interrupt_read()/resume_read(). The idea is that in some cases index scan that is done by this object is interrupted by rnd_pos() calls made by Mrr_ordered_rndpos_reader. The problem is that we're sharing handler->record[0] with that object, and it destroys its contents. We need to save/restore our current - index tuple (for pushed index condition checks) - clustered primary key values (again, for pushed index condition checks) - rowid of the last record we've retrieved (in case this rowid matches multiple ranges and we'll need to return it again) */ bool support_scan_interruptions; /* Space where we save the rowid of the last record we've returned */ uchar *saved_rowid; /* TRUE <=> saved_rowid has the last saved rowid */ bool have_saved_rowid; uchar *saved_key_tuple; /* Saved current key tuple */ uchar *saved_primary_key; /* Saved current primary key tuple */ /* TRUE<=> saved_key_tuple (and saved_primary_key when applicable) have valid values. */ bool read_was_interrupted; static int compare_keys(void *arg, const void *key1, const void *key2); static int compare_keys_reverse(void *arg, const void *key1, const void *key2); friend class Key_value_records_iterator; friend class DsMrr_impl; friend class Mrr_ordered_rndpos_reader; }; /* A reader that gets rowids from an Mrr_index_reader, and then sorts them before getting full records with handler->rndpos() calls. */ class Mrr_ordered_rndpos_reader : public Mrr_reader { public: int init(handler *file, Mrr_index_reader *index_reader, uint mode, Lifo_buffer *buf, Rowid_filter *filter); int get_next(range_id_t *range_info) override; int refill_buffer(bool initial) override; private: handler *file; /* Handler to use */ /* This what we get (rowid, range_info) pairs from */ Mrr_index_reader *index_reader; /* index_reader->get_next() puts rowid here */ uchar *index_rowid; /* TRUE <=> index_reader->refill_buffer() call has returned EOF */ bool index_reader_exhausted; /* TRUE <=> We should call index_reader->refill_buffer(). This happens if 1. we've made index_reader->get_next() call which returned EOF 2. we haven't made any index_reader calls (and our first call should be index_reader->refill_buffer(initial=TRUE) */ bool index_reader_needs_refill; /* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */ bool is_mrr_assoc; /* When reading from ordered rowid buffer: the rowid element of the last buffer element that has rowid identical to this one. */ uchar *last_identical_rowid; /* Buffer to store (rowid, range_id) pairs */ Lifo_buffer *rowid_buffer; /* Rowid filter to be checked against (if any) */ Rowid_filter *rowid_filter; int refill_from_index_reader(); }; /* A primitive "factory" of various Mrr_*_reader classes (the point is to get various kinds of readers without having to allocate them on the heap) */ class Mrr_reader_factory { public: Mrr_ordered_rndpos_reader ordered_rndpos_reader; Mrr_ordered_index_reader ordered_index_reader; Mrr_simple_index_reader simple_index_reader; }; #define DSMRR_IMPL_SORT_KEYS HA_MRR_IMPLEMENTATION_FLAG1 #define DSMRR_IMPL_SORT_ROWIDS HA_MRR_IMPLEMENTATION_FLAG2 /* DS-MRR implementation for one table. Create/use one object of this class for each ha_{myisam/innobase/etc} object. That object will be further referred to as "the handler" DsMrr_impl supports has the following execution strategies: - Bypass DS-MRR, pass all calls to default MRR implementation, which is an MRR-to-non-MRR call converter. - Key-Ordered Retrieval - Rowid-Ordered Retrieval DsMrr_impl will use one of the above strategies, or a combination of them, according to the following diagram: (mrr function calls) | +----------------->-----------------+ | | ___________v______________ _______________v________________ / default: use lookup keys \ / KEY-ORDERED RETRIEVAL: \ | (or ranges) in whatever | | sort lookup keys and then make | | order they are supplied | | index lookups in index order | \__________________________/ \________________________________/ | | | | | +---<---+ | +--------------->-----------|----+ | | | | | | +---------------+ | | ______v___ ______ | _______________v_______________ | / default: read \ | / ROWID-ORDERED RETRIEVAL: \ | | table records | | | Before reading table records, | v | in random order | v | sort their rowids and then | | \_________________/ | | read them in rowid order | | | | \_______________________________/ | | | | | | | | +-->---+ | +----<------+-----------<--------+ | | | v v v (table records and range_ids) The choice of strategy depends on MRR scan properties, table properties (whether we're scanning clustered primary key), and @@optimizer_switch settings. Key-Ordered Retrieval --------------------- The idea is: if MRR scan is essentially a series of lookups on tbl.key=value1 OR tbl.key=value2 OR ... OR tbl.key=valueN then it makes sense to collect and order the set of lookup values, i.e. sort(value1, value2, .. valueN) and then do index lookups in index order. This results in fewer index page fetch operations, and we also can avoid making multiple index lookups for the same value. That is, if value1=valueN we can easily discover that after sorting and make one index lookup for them instead of two. Rowid-Ordered Retrieval ----------------------- If we do a regular index scan or a series of index lookups, we'll be hitting table records at random. For disk-based engines, this is much slower than reading the same records in disk order. We assume that disk ordering of rows is the same as ordering of their rowids (which is provided by handler::cmp_ref()) In order to retrieve records in different order, we must separate index scanning and record fetching, that is, MRR scan uses the following steps: 1. Scan the index (and only index, that is, with HA_EXTRA_KEYREAD on) and fill a buffer with {rowid, range_id} pairs 2. Sort the buffer by rowid value 3. for each {rowid, range_id} pair in the buffer get record by rowid and return the {record, range_id} pair 4. Repeat the above steps until we've exhausted the list of ranges we're scanning. Buffer space management considerations -------------------------------------- With regards to buffer/memory management, MRR interface specifies that - SQL layer provides multi_range_read_init() with buffer of certain size. - MRR implementation may use (i.e. have at its disposal till the end of the MRR scan) all of the buffer, or return the unused end of the buffer to SQL layer. DS-MRR needs buffer in order to accumulate and sort rowids and/or keys. When we need to accumulate/sort only keys (or only rowids), it is fairly trivial. When we need to accumulate/sort both keys and rowids, efficient buffer use gets complicated. We need to: - First, accumulate keys and sort them - Then use the keys (smaller values go first) to obtain rowids. A key is not needed after we've got matching rowids for it. - Make sure that rowids are accumulated at the front of the buffer, so that we can return the end part of the buffer to SQL layer, should there be too few rowid values to occupy the buffer. All of these goals are achieved by using the following scheme: | | We get an empty buffer from SQL layer. | *-| | *----| First, we fill the buffer with keys. Key_buffer | *-------| part grows from end of the buffer space to start | *----------| (In this picture, the buffer is big enough to | *-------------| accomodate all keys and even have some space left) | *=============| We want to do key-ordered index scan, so we sort the keys |-x *===========| Then we use the keys get rowids. Rowids are |----x *========| stored from start of buffer space towards the end. |--------x *=====| The part of the buffer occupied with keys |------------x *===| gradually frees up space for rowids. In this |--------------x *=| picture we run out of keys before we've ran out |----------------x | of buffer space (it can be other way as well). |================x | Then we sort the rowids. | |~~~| The unused part of the buffer is at the end, so we can return it to the SQL layer. |================* Sorted rowids are then used to read table records in disk order */ class DsMrr_impl { public: typedef void (handler::*range_check_toggle_func_t)(bool on); void init(handler *h_arg, TABLE *table_arg) { primary_file= h_arg; table= table_arg; } int dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, void *seq_init_param, uint n_ranges, uint mode, HANDLER_BUFFER *buf); void dsmrr_close(); int dsmrr_next(range_id_t *range_info); ha_rows dsmrr_info(uint keyno, uint n_ranges, uint keys, uint key_parts, uint *bufsz, uint *flags, Cost_estimate *cost); ha_rows dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq, void *seq_init_param, uint n_ranges, uint *bufsz, uint *flags, ha_rows limit, Cost_estimate *cost); int dsmrr_explain_info(uint mrr_mode, char *str, size_t size); private: /* Buffer to store (key, range_id) pairs */ Lifo_buffer *key_buffer= nullptr; /* The "owner" handler object (the one that is expected to "own" this object and call its functions). */ handler *primary_file; TABLE *table; /* Always equal to primary_file->table */ /* Secondary handler object. (created when needed, we need it when we need to run both index scan and rnd_pos() scan at the same time) */ handler *secondary_file= nullptr; /* The rowid filter that DS-MRR has "unpushed" from the storage engine. If it's present, DS-MRR will use it. */ Rowid_filter *rowid_filter= nullptr; uint keyno; /* index we're running the scan on */ /* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */ bool is_mrr_assoc; Mrr_reader_factory reader_factory; Mrr_reader *strategy; bool strategy_exhausted; Mrr_index_reader *index_strategy; /* The whole buffer space that we're using */ uchar *full_buf; uchar *full_buf_end; /* When using both rowid and key buffers: the boundary between key and rowid parts of the buffer. This is the "original" value, actual memory ranges used by key and rowid parts may be different because of dynamic space reallocation between them. */ uchar *rowid_buffer_end; /* One of the following two is used for key buffer: forward is used when we only need key buffer, backward is used when we need both key and rowid buffers. */ Forward_lifo_buffer forward_key_buf; Backward_lifo_buffer backward_key_buf; /* Buffer to store (rowid, range_id) pairs, or just rowids if is_mrr_assoc==FALSE */ Forward_lifo_buffer rowid_buffer; bool choose_mrr_impl(uint keyno, ha_rows rows, uint *flags, uint *bufsz, Cost_estimate *cost); bool get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags, uint *buffer_size, uint extra_mem_overhead, Cost_estimate *cost); bool check_cpk_scan(THD *thd, TABLE_SHARE *share, uint keyno, uint mrr_flags); bool setup_buffer_sharing(uint key_size_in_keybuf, key_part_map key_tuple_map); /* Buffer_manager and its member functions */ Buffer_manager buf_manager; static void redistribute_buffer_space(void *dsmrr_arg); static void reset_buffer_sizes(void *dsmrr_arg); static void do_nothing(void *dsmrr_arg); Lifo_buffer* get_key_buffer() { return key_buffer; } friend class Key_value_records_iterator; friend class Mrr_ordered_index_reader; friend class Mrr_ordered_rndpos_reader; int setup_two_handlers(); void close_second_handler(); }; /** @} (end of group DS-MRR declarations) */ procedure.h 0000644 00000015243 15156036172 0006720 0 ustar 00 #ifndef PROCEDURE_INCLUDED #define PROCEDURE_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* When using sql procedures */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif /* It is necessary to include set_var.h instead of item.h because there are dependencies on include order for set_var.h and item.h. This will be resolved later. */ #include "sql_class.h" /* select_result, set_var.h: THD */ #include "set_var.h" /* Item */ #define PROC_NO_SORT 1 /**< Bits in flags */ #define PROC_GROUP 2 /**< proc must have group */ /* Procedure items used by procedures to store values for send_result_set_metadata */ class Item_proc :public Item { public: Item_proc(THD *thd, const char *name_par): Item(thd) { this->name.str= name_par; this->name.length= strlen(name_par); } enum Type type() const override { return Item::PROC_ITEM; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { /* We can get to here when using a CURSOR for a query with PROCEDURE: DECLARE c CURSOR FOR SELECT * FROM t1 PROCEDURE analyse(); OPEN c; */ return create_tmp_field_ex_simple(root, table, src, param); } virtual void set(double nr)=0; virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0; virtual void set(longlong nr)=0; const Type_handler *type_handler() const override=0; void set(const char *str) { set(str,(uint) strlen(str), default_charset()); } unsigned int size_of() { return sizeof(*this);} bool check_vcol_func_processor(void *arg) override { DBUG_ASSERT(0); // impossible return mark_unsupported_function("proc", arg, VCOL_IMPOSSIBLE); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } protected: Item* shallow_copy(THD *thd) const override { return nullptr; } }; class Item_proc_real :public Item_proc { double value; public: Item_proc_real(THD *thd, const char *name_par, uint dec): Item_proc(thd, name_par) { decimals=dec; max_length=float_length(dec); } const Type_handler *type_handler() const override { return &type_handler_double; } void set(double nr) override { value=nr; } void set(longlong nr) override { value=(double) nr; } void set(const char *str,uint length,CHARSET_INFO *cs) override { int err_not_used; char *end_not_used; value= cs->strntod((char*) str,length, &end_not_used, &err_not_used); } double val_real() override { return value; } longlong val_int() override { return (longlong) value; } String *val_str(String *s) override { s->set_real(value,decimals,default_charset()); return s; } my_decimal *val_decimal(my_decimal *) override; unsigned int size_of() { return sizeof(*this);} }; class Item_proc_int :public Item_proc { longlong value; public: Item_proc_int(THD *thd, const char *name_par): Item_proc(thd, name_par) { max_length=11; } const Type_handler *type_handler() const override { if (unsigned_flag) return &type_handler_ulonglong; return &type_handler_slonglong; } void set(double nr) override { value=(longlong) nr; } void set(longlong nr) override { value=nr; } void set(const char *str,uint length, CHARSET_INFO *cs) override { int err; value= cs->strntoll(str,length,10,NULL,&err); } double val_real() override { return (double) value; } longlong val_int() override { return value; } String *val_str(String *s) override { s->set(value, default_charset()); return s; } my_decimal *val_decimal(my_decimal *) override; unsigned int size_of() { return sizeof(*this);} protected: Item *shallow_copy(THD *thd) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; class Item_proc_string :public Item_proc { String value; public: Item_proc_string(THD *thd, const char *name_par, uint length): Item_proc(thd, name_par) { this->max_length=length; value.set_thread_specific(); } const Type_handler *type_handler() const override { return &type_handler_varchar; } void set(double nr) override { value.set_real(nr, 2, default_charset()); } void set(longlong nr) override { value.set(nr, default_charset()); } void set(const char *str, uint length, CHARSET_INFO *cs) override { value.copy(str,length,cs); } double val_real() override { int err_not_used; char *end_not_used; CHARSET_INFO *cs= value.charset(); return cs->strntod((char*) value.ptr(), value.length(), &end_not_used, &err_not_used); } longlong val_int() override { int err; CHARSET_INFO *cs=value.charset(); return cs->strntoll(value.ptr(), value.length(), 10, NULL, &err); } String *val_str(String*) override { return null_value ? (String*) 0 : &value; } my_decimal *val_decimal(my_decimal *) override; void cleanup() override { value.free(); } unsigned int size_of() { return sizeof(*this);} protected: Item *shallow_copy(THD *thd) const override { return nullptr; } Item *deep_copy(THD *thd) const override { return nullptr; } }; /* The procedure class definitions */ class Procedure { protected: List<Item> *fields; select_result *result; public: const uint flags; ORDER *group,*param_fields; Procedure(select_result *res,uint flags_par) :result(res),flags(flags_par), group(0),param_fields(0) {} virtual ~Procedure() {group=param_fields=0; fields=0; } virtual void add(void)=0; virtual void end_group(void)=0; virtual int send_row(List<Item> &fields)=0; virtual bool change_columns(THD *thd, List<Item> &fields)= 0; virtual void update_refs(void) {} virtual int end_of_records() { return 0; } }; Procedure *setup_procedure(THD *thd,ORDER *proc_param,select_result *result, List<Item> &field_list,int *error); #endif /* PROCEDURE_INCLUDED */ threadpool_generic.h 0000644 00000007601 15156036172 0010564 0 ustar 00 /* Copyright(C) 2019, 2020, MariaDB * * This program is free software; you can redistribute itand /or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/ #if defined (HAVE_POOL_OF_THREADS) #include <my_global.h> #include <sql_plist.h> #include <my_pthread.h> #include <mysqld.h> #include <threadpool.h> #include <violite.h> #ifdef _WIN32 #include <windows.h> #include "threadpool_winsockets.h" /* AIX may define this, too ?*/ #define HAVE_IOCP #endif #ifdef _WIN32 typedef HANDLE TP_file_handle; #else typedef int TP_file_handle; #define INVALID_HANDLE_VALUE -1 #endif #ifdef __linux__ #include <sys/epoll.h> typedef struct epoll_event native_event; #elif defined(HAVE_KQUEUE) #include <sys/event.h> typedef struct kevent native_event; #elif defined (__sun) #include <port.h> typedef port_event_t native_event; #elif defined (HAVE_IOCP) typedef OVERLAPPED_ENTRY native_event; #else #error threadpool is not available on this platform #endif struct thread_group_t; /* Per-thread structure for workers */ struct worker_thread_t { ulonglong event_count; /* number of request handled by this thread */ thread_group_t* thread_group; worker_thread_t* next_in_list; worker_thread_t** prev_in_list; mysql_cond_t cond; bool woken; }; typedef I_P_List<worker_thread_t, I_P_List_adapter<worker_thread_t, & worker_thread_t::next_in_list, & worker_thread_t::prev_in_list>, I_P_List_counter > worker_list_t; struct TP_connection_generic :public TP_connection { TP_connection_generic(CONNECT* c); ~TP_connection_generic(); int init() override { return 0; } void set_io_timeout(int sec) override; int start_io() override; void wait_begin(int type) override; void wait_end() override; thread_group_t* thread_group; TP_connection_generic* next_in_queue; TP_connection_generic** prev_in_queue; ulonglong abs_wait_timeout; ulonglong enqueue_time; TP_file_handle fd; bool bound_to_poll_descriptor; int waiting; bool fix_group; #ifdef _WIN32 win_aiosocket win_sock{}; void init_vio(st_vio *vio) override { win_sock.init(vio);} #endif }; typedef I_P_List<TP_connection_generic, I_P_List_adapter<TP_connection_generic, & TP_connection_generic::next_in_queue, & TP_connection_generic::prev_in_queue>, I_P_List_counter, I_P_List_fast_push_back<TP_connection_generic> > connection_queue_t; const int NQUEUES = 2; /* We have high and low priority queues*/ enum class operation_origin { WORKER, LISTENER }; struct thread_group_counters_t { ulonglong thread_creations; ulonglong thread_creations_due_to_stall; ulonglong wakes; ulonglong wakes_due_to_stall; ulonglong throttles; ulonglong stalls; ulonglong dequeues[2]; ulonglong polls[2]; }; struct thread_group_t { mysql_mutex_t mutex; connection_queue_t queues[NQUEUES]; worker_list_t waiting_threads; worker_thread_t* listener; pthread_attr_t* pthread_attr; TP_file_handle pollfd; int thread_count; int active_thread_count; int connection_count; /* Stats for the deadlock detection timer routine.*/ int io_event_count; int queue_event_count; ulonglong last_thread_creation_time; int shutdown_pipe[2]; bool shutdown; bool stalled; thread_group_counters_t counters; char pad[CPU_LEVEL1_DCACHE_LINESIZE]; }; #define TP_INCREMENT_GROUP_COUNTER(group,var) do {group->counters.var++;}while(0) extern thread_group_t* all_groups; #endif discover.h 0000644 00000003042 15156036172 0006540 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef DISCOVER_INCLUDED #define DISCOVER_INCLUDED int extension_based_table_discovery(MY_DIR *dirp, const char *ext, handlerton::discovered_list *tl); #ifdef MYSQL_SERVER int readfrm(const char *name, const uchar **data, size_t *length); int writefile(const char *path, const char *db, const char *table, bool tmp_table, const uchar *frmdata, size_t len); /* a helper to delete an frm file, given a path w/o .frm extension */ inline void deletefrm(const char *path) { char frm_name[FN_REFLEN]; strxnmov(frm_name, sizeof(frm_name)-1, path, reg_ext, NullS); mysql_file_delete(key_file_frm, frm_name, MYF(0)); } int ext_table_discovery_simple(MY_DIR *dirp, handlerton::discovered_list *result); #endif #endif /* DISCOVER_INCLUDED */ records.h 0000644 00000006113 15156036172 0006365 0 ustar 00 #ifndef SQL_RECORDS_H #define SQL_RECORDS_H /* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "table.h" struct st_join_table; class handler; class THD; class SQL_SELECT; class Copy_field; class SORT_INFO; struct READ_RECORD; void end_read_record(READ_RECORD *info); void free_cache(READ_RECORD *info); /** A context for reading through a single table using a chosen access method: index read, scan, etc, use of cache, etc. Use by: READ_RECORD read_record; init_read_record(&read_record, ...); while (read_record.read_record()) { ... } end_read_record(); */ struct READ_RECORD { typedef int (*Read_func)(READ_RECORD*); typedef void (*Unlock_row_func)(st_join_table *); typedef int (*Setup_func)(struct st_join_table*); TABLE *table; /* Head-form */ Unlock_row_func unlock_row; Read_func read_record_func; Read_func read_record_func_and_unpack_calls; THD *thd; SQL_SELECT *select; uint ref_length, reclength, rec_cache_size, error_offset; /** Counting records when reading result from filesort(). Used when filesort leaves the result in the filesort buffer. */ ha_rows unpack_counter; uchar *ref_pos; /* pointer to form->refpos */ uchar *rec_buf; /* to read field values after filesort */ uchar *cache,*cache_pos,*cache_end,*read_positions; /* Structure storing information about sorting */ SORT_INFO *sort_info; struct st_io_cache *io_cache; bool print_error; int read_record() { return read_record_func(this); } uchar *record() const { return table->record[0]; } /* SJ-Materialization runtime may need to read fields from the materialized table and unpack them into original table fields: */ Copy_field *copy_field; Copy_field *copy_field_end; public: READ_RECORD() : table(NULL), cache(NULL) {} ~READ_RECORD() { end_read_record(this); } }; bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, SORT_INFO *sort, int use_record_cache, bool print_errors, bool disable_rr_cache); bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse); void rr_unlock_row(st_join_table *tab); #endif /* SQL_RECORDS_H */ my_apc.h 0000644 00000011213 15156036172 0006171 0 ustar 00 #ifndef SQL_MY_APC_INCLUDED #define SQL_MY_APC_INCLUDED /* Copyright (c) 2011, 2013 Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Interface ~~~~~~~~~ ( - This is an APC request queue - We assume there is a particular owner thread which periodically calls process_apc_requests() to serve the call requests. - Other threads can post call requests, and block until they are exectued. ) Implementation ~~~~~~~~~~~~~~ - The target has a mutex-guarded request queue. - After the request has been put into queue, the requestor waits for request to be satisfied. The worker satisifes the request and signals the requestor. */ class THD; /* Target for asynchronous procedure calls (APCs). - A target is running in some particular thread, - One can make calls to it from other threads. */ class Apc_target { mysql_mutex_t *LOCK_thd_kill_ptr; public: Apc_target() : enabled(0), apc_calls(NULL) {} ~Apc_target() { DBUG_ASSERT(!enabled && !apc_calls);} void init(mysql_mutex_t *target_mutex); /* Destroy the target. The target must be disabled when this call is made. */ void destroy() { DBUG_ASSERT(!enabled); } /* Enter ther state where the target is available for serving APC requests */ void enable() { enabled++; } /* Make the target unavailable for serving APC requests. @note This call will serve all requests that were already enqueued */ void disable() { DBUG_ASSERT(enabled); mysql_mutex_lock(LOCK_thd_kill_ptr); bool process= !--enabled && have_apc_requests(); mysql_mutex_unlock(LOCK_thd_kill_ptr); if (unlikely(process)) process_apc_requests(true); } void process_apc_requests(bool force); /* A lightweight function, intended to be used in frequent checks like this: if (apc_target.have_requests()) apc_target.process_apc_requests() */ inline bool have_apc_requests() { return MY_TEST(apc_calls); } inline bool is_enabled() { return enabled; } /* Functor class for calls you can schedule */ class Apc_call { public: /* This function will be called in the target thread */ virtual void call_in_target_thread()= 0; virtual ~Apc_call() = default; }; /* Make a call in the target thread (see function definition for details) */ bool make_apc_call(THD *caller_thd, Apc_call *call, int timeout_sec, bool *timed_out); #ifndef DBUG_OFF int n_calls_processed; /* Number of calls served by this target */ #endif private: class Call_request; /* Non-zero value means we're enabled. It's an int, not bool, because one can call enable() N times (and then needs to call disable() N times before the target is really disabled) */ int enabled; /* Circular, double-linked list of all enqueued call requests. We use this structure, because we - process requests sequentially: requests are added at the end of the list and removed from the front. With circular list, we can keep one pointer, and access both front an back of the list with it. - a thread that has posted a request may time out (or be KILLed) and cancel the request, which means we need a fast request-removal operation. */ Call_request *apc_calls; class Call_request { public: Apc_call *call; /* Functor to be called */ /* The caller will actually wait for "processed==TRUE" */ bool processed; /* Condition that will be signalled when the request has been served */ mysql_cond_t COND_request; /* Double linked-list linkage */ Call_request *next; Call_request *prev; const char *what; /* (debug) state of the request */ }; void enqueue_request(Call_request *qe); void dequeue_request(Call_request *qe); /* return the first call request in queue, or NULL if there are none enqueued */ Call_request *get_first_in_queue() { return apc_calls; } }; #ifdef HAVE_PSI_INTERFACE void init_show_explain_psi_keys(void); #else #define init_show_explain_psi_keys() /* no-op */ #endif #endif //SQL_MY_APC_INCLUDED sql_bootstrap.h 0000644 00000003424 15156036172 0007622 0 ustar 00 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_BOOTSTRAP_H #define SQL_BOOTSTRAP_H /** The maximum size of a bootstrap query. Increase this size if parsing a longer query during bootstrap is necessary. The longest query in use depends on the documentation content, see the file fill_help_tables.sql */ #define MAX_BOOTSTRAP_QUERY_SIZE 60000 /** The maximum size of a bootstrap query, expressed in a single line. Do not increase this size, use the multiline syntax instead. */ #define MAX_BOOTSTRAP_LINE_SIZE 20000 #define MAX_BOOTSTRAP_ERROR_LEN 256 #define READ_BOOTSTRAP_SUCCESS 0 #define READ_BOOTSTRAP_EOF 1 #define READ_BOOTSTRAP_ERROR 2 #define READ_BOOTSTRAP_QUERY_SIZE 3 typedef void *fgets_input_t; typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t, int *error); #ifdef __cplusplus extern "C" { #endif int read_bootstrap_query(char *query, int *query_length, fgets_input_t input, fgets_fn_t fgets_fn, int preserve_delimiter, int *error); #ifdef __cplusplus } #endif #endif pfs_stage_provider.h 0000644 00000003024 15156036172 0010607 0 ustar 00 /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_STAGE_PROVIDER_H #define PFS_STAGE_PROVIDER_H /** @file include/pfs_stage_provider.h Performance schema instrumentation (declarations). */ #ifdef HAVE_PSI_STAGE_INTERFACE #ifdef MYSQL_SERVER #ifndef EMBEDDED_LIBRARY #ifndef MYSQL_DYNAMIC_PLUGIN #include "mysql/psi/psi.h" #define PSI_STAGE_CALL(M) pfs_ ## M ## _v1 C_MODE_START void pfs_register_stage_v1(const char *category, PSI_stage_info_v1 **info_array, int count); PSI_stage_progress* pfs_start_stage_v1(PSI_stage_key key, const char *src_file, int src_line); PSI_stage_progress* pfs_get_current_stage_progress_v1(); void pfs_end_stage_v1(); C_MODE_END #endif /* MYSQL_DYNAMIC_PLUGIN */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_SERVER */ #endif /* HAVE_PSI_STAGE_INTERFACE */ #endif item_func.h 0000644 00000417333 15156036172 0006707 0 ustar 00 #ifndef ITEM_FUNC_INCLUDED #define ITEM_FUNC_INCLUDED /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Function items used by mysql */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #ifdef HAVE_IEEEFP_H extern "C" /* Bug in BSDI include file */ { #include <ieeefp.h> } #endif #include "sql_udf.h" // udf_handler #include "my_decimal.h" // string2my_decimal #include <cmath> extern bool st_append_json(String *s, CHARSET_INFO *json_cs, const uchar *js, uint js_len); class Item_func :public Item_func_or_sum { void sync_with_sum_func_and_with_field(List<Item> &list); protected: virtual bool check_arguments() const { return check_argument_types_scalar(0, arg_count); } bool check_argument_types_like_args0() const; bool check_argument_types_scalar(uint start, uint end) const; bool check_argument_types_traditional_scalar(uint start, uint end) const; bool check_argument_types_or_binary(const Type_handler *handler, uint start, uint end) const; bool check_argument_types_can_return_int(uint start, uint end) const; bool check_argument_types_can_return_real(uint start, uint end) const; bool check_argument_types_can_return_str(uint start, uint end) const; bool check_argument_types_can_return_text(uint start, uint end) const; bool check_argument_types_can_return_date(uint start, uint end) const; bool check_argument_types_can_return_time(uint start, uint end) const; void print_cast_temporal(String *str, enum_query_type query_type); void print_schema_qualified_name(String *to, const LEX_CSTRING &schema_name, const LEX_CSTRING &function_name) const { // e.g. oracle_schema.func() to->append(schema_name); to->append('.'); to->append(function_name); } void print_sql_mode_qualified_name(String *to, enum_query_type query_type, const LEX_CSTRING &function_name) const { const Schema *func_schema= schema(); if (!func_schema || func_schema == Schema::find_implied(current_thd)) to->append(function_name); else print_schema_qualified_name(to, func_schema->name(), function_name); } void print_sql_mode_qualified_name(String *to, enum_query_type query_type) const { return print_sql_mode_qualified_name(to, query_type, func_name_cstring()); } void update_nullability_post_fix_fields(); bool aggregate_args2_for_comparison_with_conversion(THD *thd, Type_handler_hybrid_field_type *th); public: // Print an error message for a builtin-schema qualified function call static void wrong_param_count_error(const LEX_CSTRING &schema_name, const LEX_CSTRING &func_name); table_map not_null_tables_cache= 0; enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, GE_FUNC,GT_FUNC,FT_FUNC, LIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC, COND_AND_FUNC, COND_OR_FUNC, XOR_FUNC, BETWEEN, IN_FUNC, MULT_EQUAL_FUNC, INTERVAL_FUNC, ISNOTNULLTEST_FUNC, SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC, SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC, SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC, SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING, SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, SP_RELATE_FUNC, NOT_FUNC, NOT_ALL_FUNC, TEMPTABLE_ROWID, NOW_FUNC, NOW_UTC_FUNC, SYSDATE_FUNC, TRIG_COND_FUNC, SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC, DYNCOL_FUNC, JSON_EXTRACT_FUNC, JSON_VALID_FUNC, ROWNUM_FUNC, CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC, // Used by ColumnStore/spider, DATE_FUNC, YEAR_FUNC }; /* A function bitmap. Useful when some operation needs to be applied only to certain functions. For now we only need to distinguish some comparison predicates. */ enum Bitmap : ulonglong { BITMAP_NONE= 0, BITMAP_EQ= 1ULL << EQ_FUNC, BITMAP_EQUAL= 1ULL << EQUAL_FUNC, BITMAP_NE= 1ULL << NE_FUNC, BITMAP_LT= 1ULL << LT_FUNC, BITMAP_LE= 1ULL << LE_FUNC, BITMAP_GE= 1ULL << GE_FUNC, BITMAP_GT= 1ULL << GT_FUNC, BITMAP_LIKE= 1ULL << LIKE_FUNC, BITMAP_BETWEEN= 1ULL << BETWEEN, BITMAP_IN= 1ULL << IN_FUNC, BITMAP_MULT_EQUAL= 1ULL << MULT_EQUAL_FUNC, BITMAP_OTHER= 1ULL << 63, BITMAP_ALL= 0xFFFFFFFFFFFFFFFFULL, BITMAP_ANY_EQUALITY= BITMAP_EQ | BITMAP_EQUAL | BITMAP_MULT_EQUAL, BITMAP_EXCEPT_ANY_EQUALITY= BITMAP_ALL & ~BITMAP_ANY_EQUALITY, }; ulonglong bitmap_bit() const { Functype type= functype(); return 1ULL << (type > 63 ? 63 : type); } static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) { switch (type) { case EQ_FUNC: return SCALAR_CMP_EQ; case EQUAL_FUNC: return SCALAR_CMP_EQUAL; case LT_FUNC: return SCALAR_CMP_LT; case LE_FUNC: return SCALAR_CMP_LE; case GE_FUNC: return SCALAR_CMP_GE; case GT_FUNC: return SCALAR_CMP_GT; default: break; } DBUG_ASSERT(0); return SCALAR_CMP_EQ; } enum Type type() const override { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } Item_func(THD *thd): Item_func_or_sum(thd) { DBUG_ASSERT(with_flags == item_with_t::NONE); with_flags= item_with_t::NONE; } Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a) { with_flags= a->with_flags; } Item_func(THD *thd, Item *a, Item *b): Item_func_or_sum(thd, a, b) { with_flags= a->with_flags | b->with_flags; } Item_func(THD *thd, Item *a, Item *b, Item *c): Item_func_or_sum(thd, a, b, c) { with_flags|= a->with_flags | b->with_flags | c->with_flags; } Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_func_or_sum(thd, a, b, c, d) { with_flags= a->with_flags | b->with_flags | c->with_flags | d->with_flags; } Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e): Item_func_or_sum(thd, a, b, c, d, e) { with_flags= (a->with_flags | b->with_flags | c->with_flags | d->with_flags | e->with_flags); } Item_func(THD *thd, List<Item> &list): Item_func_or_sum(thd, list) { set_arguments(thd, list); } // Constructor used for Item_cond_and/or (see Item comment) Item_func(THD *thd, Item_func *item): Item_func_or_sum(thd, item), not_null_tables_cache(item->not_null_tables_cache) { } bool fix_fields(THD *, Item **ref) override; void cleanup() override { Item_func_or_sum::cleanup(); used_tables_and_const_cache_init(); } void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) override; void quick_fix_field() override; table_map not_null_tables() const override; void update_used_tables() override { used_tables_and_const_cache_init(); used_tables_and_const_cache_update_and_join(arg_count, args); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) override; SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) override { DBUG_ENTER("Item_func::get_mm_tree"); DBUG_RETURN(const_item() ? get_mm_tree_for_const(param) : NULL); } bool eq(const Item *item, const Eq_config &config) const override; virtual Item *key_item() const { return args[0]; } void set_arguments(THD *thd, List<Item> &list) { Item_args::set_arguments(thd, list); sync_with_sum_func_and_with_field(list); list.empty(); // Fields are used } void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags) override; void print(String *str, enum_query_type query_type) override; void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type) const; void print_args_parenthesized(String *str, enum_query_type query_type) const { str->append('('); print_args(str, 0, query_type); str->append(')'); } bool is_null() override { update_null_value(); return null_value; } String *val_str_from_val_str_ascii(String *str, String *str2); void signal_divide_by_null(); friend class udf_handler; Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return tmp_table_field_from_field_type(root, table); } Item *get_tmp_table_item(THD *thd) override; void fix_char_length_ulonglong(ulonglong max_char_length_arg) { ulonglong max_result_length= max_char_length_arg * collation.collation->mbmaxlen; if (max_result_length >= MAX_BLOB_WIDTH) { max_length= MAX_BLOB_WIDTH; set_maybe_null(); } else max_length= (uint32) max_result_length; } Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override; Item* compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t) override; void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order) override; bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; // bool is_expensive_processor(void *arg); // virtual bool is_expensive() { return 0; } inline void raise_numeric_overflow(const char *type_name) { char buf[256]; String str(buf, sizeof(buf), system_charset_info); str.length(0); print(&str, QT_NO_DATA_EXPANSION); my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe()); } inline double raise_float_overflow() { raise_numeric_overflow("DOUBLE"); return 0.0; } inline longlong raise_integer_overflow() { raise_numeric_overflow(unsigned_flag ? "BIGINT UNSIGNED": "BIGINT"); return 0; } inline int raise_decimal_overflow() { raise_numeric_overflow("DECIMAL"); return E_DEC_OVERFLOW; } /** Throw an error if the input double number is not finite, i.e. is either +/-INF or NAN. */ inline double check_float_overflow(double value) { return std::isfinite(value) ? value : raise_float_overflow(); } /** Throw an error if the input BIGINT value represented by the (longlong value, bool unsigned flag) pair cannot be returned by the function, i.e. is not compatible with this Item's unsigned_flag. */ inline longlong check_integer_overflow(longlong value, bool val_unsigned) { return check_integer_overflow(Longlong_hybrid(value, val_unsigned)); } // Check if the value is compatible with Item::unsigned_flag. inline longlong check_integer_overflow(const Longlong_hybrid &sval) { Longlong_null res= sval.val_int(unsigned_flag); return res.is_null() ? raise_integer_overflow() : res.value(); } // Check if the value is compatible with Item::unsigned_flag. longlong check_integer_overflow(const ULonglong_hybrid &uval) { Longlong_null res= uval.val_int(unsigned_flag); return res.is_null() ? raise_integer_overflow() : res.value(); } /** Throw an error if the error code of a DECIMAL operation is E_DEC_OVERFLOW. */ inline int check_decimal_overflow(int error) { return (error == E_DEC_OVERFLOW) ? raise_decimal_overflow() : error; } bool has_timestamp_args() { DBUG_ASSERT(fixed()); for (uint i= 0; i < arg_count; i++) { if (args[i]->type() == Item::FIELD_ITEM && args[i]->field_type() == MYSQL_TYPE_TIMESTAMP) return TRUE; } return FALSE; } bool has_date_args() { DBUG_ASSERT(fixed()); for (uint i= 0; i < arg_count; i++) { if (args[i]->type() == Item::FIELD_ITEM && (args[i]->field_type() == MYSQL_TYPE_DATE || args[i]->field_type() == MYSQL_TYPE_DATETIME)) return TRUE; } return FALSE; } bool has_time_args() { DBUG_ASSERT(fixed()); for (uint i= 0; i < arg_count; i++) { if (args[i]->type() == Item::FIELD_ITEM && (args[i]->field_type() == MYSQL_TYPE_TIME || args[i]->field_type() == MYSQL_TYPE_DATETIME)) return TRUE; } return FALSE; } bool has_datetime_args() { DBUG_ASSERT(fixed()); for (uint i= 0; i < arg_count; i++) { if (args[i]->type() == Item::FIELD_ITEM && args[i]->field_type() == MYSQL_TYPE_DATETIME) return TRUE; } return FALSE; } Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { /* By default only substitution for a field whose two different values are never equal is allowed in the arguments of a function. This is overruled for the direct arguments of comparison functions. */ Item_args::propagate_equal_fields(thd, Context_identity(), cond); return this; } bool has_rand_bit() { return used_tables() & RAND_TABLE_BIT; } bool excl_dep_on_table(table_map tab_map) override { if (used_tables() & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) return false; return !(used_tables() & ~tab_map) || Item_args::excl_dep_on_table(tab_map); } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { if (has_rand_bit() || with_subquery()) return false; return Item_args::excl_dep_on_grouping_fields(sel); } bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override { return Item_args::excl_dep_on_in_subq_left_part(subq_pred); } /* We assume the result of any function that has a TIMESTAMP argument to be timezone-dependent, since a TIMESTAMP value in both numeric and string contexts is interpreted according to the current timezone. The only exception is UNIX_TIMESTAMP() which returns the internal representation of a TIMESTAMP argument verbatim, and thus does not depend on the timezone. */ bool check_valid_arguments_processor(void *bool_arg) override { return has_timestamp_args(); } bool find_function_processor (void *arg) override { return functype() == *(Functype *) arg; } void no_rows_in_result() override { for (uint i= 0; i < arg_count; i++) { args[i]->no_rows_in_result(); } } void restore_to_before_no_rows_in_result() override { for (uint i= 0; i < arg_count; i++) { args[i]->restore_to_before_no_rows_in_result(); } } void convert_const_compared_to_int_field(THD *thd); Item_func *get_item_func() override { return this; } bool is_simplified_cond_processor(void *) override { return const_item() && !val_bool(); } }; class Item_real_func :public Item_func { public: Item_real_func(THD *thd): Item_func(thd) { collation= DTCollation_numeric(); } Item_real_func(THD *thd, Item *a): Item_func(thd, a) { collation= DTCollation_numeric(); } Item_real_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { collation= DTCollation_numeric(); } Item_real_func(THD *thd, List<Item> &list): Item_func(thd, list) { collation= DTCollation_numeric(); } String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *decimal_value) override; longlong val_int() override { DBUG_ASSERT(fixed()); return Converter_double_to_longlong(val_real(), unsigned_flag).result(); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_real(thd, ltime, fuzzydate); } const Type_handler *type_handler() const override { return &type_handler_double; } bool fix_length_and_dec(THD *thd) override { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; } }; /** Functions whose returned field type is determined at fix_fields() time. */ class Item_hybrid_func: public Item_func, public Type_handler_hybrid_field_type { protected: bool fix_attributes(Item **item, uint nitems); public: Item_hybrid_func(THD *thd): Item_func(thd) { } Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { } Item_hybrid_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { } Item_hybrid_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) { } Item_hybrid_func(THD *thd, List<Item> &list): Item_func(thd, list) { } Item_hybrid_func(THD *thd, Item_hybrid_func *item) :Item_func(thd, item), Type_handler_hybrid_field_type(item) { } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } void fix_length_and_dec_long_or_longlong(uint char_length, bool unsigned_arg) { collation= DTCollation_numeric(); unsigned_flag= unsigned_arg; max_length= char_length; set_handler(Type_handler::type_handler_long_or_longlong(char_length, unsigned_arg)); } void fix_length_and_dec_ulong_or_ulonglong_by_nbits(uint nbits) { uint digits= Type_handler_bit::Bit_decimal_notation_int_digits_by_nbits(nbits); collation= DTCollation_numeric(); unsigned_flag= true; max_length= digits; if (nbits > 32) set_handler(&type_handler_ulonglong); else set_handler(&type_handler_ulong); } }; class Item_handled_func: public Item_func { public: class Handler { public: virtual ~Handler() = default; virtual String *val_str(Item_handled_func *, String *) const= 0; virtual String *val_str_ascii(Item_handled_func *, String *) const= 0; virtual double val_real(Item_handled_func *) const= 0; virtual longlong val_int(Item_handled_func *) const= 0; virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0; virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; virtual bool val_native(THD *thd, Item_handled_func *, Native *to) const { DBUG_ASSERT(0); to->length(0); return true; } virtual const Type_handler * return_type_handler(const Item_handled_func *item) const= 0; virtual const Type_handler * type_handler_for_create_select(const Item_handled_func *item) const { return return_type_handler(item); } virtual bool fix_length_and_dec(Item_handled_func *) const= 0; }; class Handler_str: public Handler { public: String *val_str_ascii(Item_handled_func *item, String *str) const override { return item->Item::val_str_ascii(str); } double val_real(Item_handled_func *item) const override { DBUG_ASSERT(item->fixed()); StringBuffer<64> tmp; String *res= item->val_str(&tmp); return res ? item->double_from_string_with_check(res) : 0.0; } longlong val_int(Item_handled_func *item) const override { DBUG_ASSERT(item->fixed()); StringBuffer<22> tmp; String *res= item->val_str(&tmp); return res ? item->longlong_from_string_with_check(res) : 0; } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return item->val_decimal_from_string(to); } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzydate) const override { return item->get_date_from_string(thd, to, fuzzydate); } }; /** Abstract class for functions returning TIME, DATE, DATETIME or string values, whose data type depends on parameters and is set at fix_fields time. */ class Handler_temporal: public Handler { public: String *val_str(Item_handled_func *item, String *to) const override { StringBuffer<MAX_FIELD_WIDTH> ascii_buf; return item->val_str_from_val_str_ascii(to, &ascii_buf); } }; /** Abstract class for functions returning strings, which are generated from get_date() results, when get_date() can return different MYSQL_TIMESTAMP_XXX per row. */ class Handler_temporal_string: public Handler_temporal { public: const Type_handler *return_type_handler(const Item_handled_func *) const override { return &type_handler_string; } const Type_handler * type_handler_for_create_select(const Item_handled_func *item) const override { return return_type_handler(item)->type_handler_for_tmp_table(item); } double val_real(Item_handled_func *item) const override { return Temporal_hybrid(item).to_double(); } longlong val_int(Item_handled_func *item) const override { return Temporal_hybrid(item).to_longlong(); } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return Temporal_hybrid(item).to_decimal(to); } String *val_str_ascii(Item_handled_func *item, String *to) const override { return Temporal_hybrid(item).to_string(to, item->decimals); } }; class Handler_date: public Handler_temporal { public: const Type_handler *return_type_handler(const Item_handled_func *) const override { return &type_handler_newdate; } bool fix_length_and_dec(Item_handled_func *item) const override { item->fix_attributes_date(); return false; } double val_real(Item_handled_func *item) const override { return Date(item).to_double(); } longlong val_int(Item_handled_func *item) const override { return Date(item).to_longlong(); } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return Date(item).to_decimal(to); } String *val_str_ascii(Item_handled_func *item, String *to) const override { return Date(item).to_string(to); } }; class Handler_time: public Handler_temporal { public: const Type_handler *return_type_handler(const Item_handled_func *) const override { return &type_handler_time2; } double val_real(Item_handled_func *item) const override { return Time(item).to_double(); } longlong val_int(Item_handled_func *item) const override { return Time(item).to_longlong(); } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return Time(item).to_decimal(to); } String *val_str_ascii(Item_handled_func *item, String *to) const override { return Time(item).to_string(to, item->decimals); } bool val_native(THD *thd, Item_handled_func *item, Native *to) const override { return Time(thd, item).to_native(to, item->decimals); } }; class Handler_datetime: public Handler_temporal { public: const Type_handler *return_type_handler(const Item_handled_func *) const override { return &type_handler_datetime2; } double val_real(Item_handled_func *item) const override { return Datetime(item).to_double(); } longlong val_int(Item_handled_func *item) const override { return Datetime(item).to_longlong(); } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return Datetime(item).to_decimal(to); } String *val_str_ascii(Item_handled_func *item, String *to) const override { return Datetime(item).to_string(to, item->decimals); } }; class Handler_int: public Handler { public: String *val_str(Item_handled_func *item, String *to) const override { longlong nr= val_int(item); if (item->null_value) return 0; to->set_int(nr, item->unsigned_flag, item->collation.collation); return to; } String *val_str_ascii(Item_handled_func *item, String *to) const override { return item->Item::val_str_ascii(to); } double val_real(Item_handled_func *item) const override { return item->unsigned_flag ? (double) ((ulonglong) val_int(item)) : (double) val_int(item); } my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const override { return item->val_decimal_from_int(to); } bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzydate) const override { return item->get_date_from_int(thd, to, fuzzydate); } longlong val_int(Item_handled_func *item) const override { Longlong_null tmp= to_longlong_null(item); item->null_value= tmp.is_null(); return tmp.value(); } virtual Longlong_null to_longlong_null(Item_handled_func *item) const= 0; }; class Handler_slong: public Handler_int { public: const Type_handler *return_type_handler(const Item_handled_func *item) const override { return &type_handler_slong; } bool fix_length_and_dec(Item_handled_func *item) const override { item->unsigned_flag= false; item->collation= DTCollation_numeric(); item->fix_char_length(11); return false; } }; class Handler_slong2: public Handler_slong { public: bool fix_length_and_dec(Item_handled_func *func) const override { bool rc= Handler_slong::fix_length_and_dec(func); func->max_length= 2; return rc; } }; class Handler_ulonglong: public Handler_int { public: const Type_handler *return_type_handler(const Item_handled_func *item) const override { return &type_handler_ulonglong; } bool fix_length_and_dec(Item_handled_func *item) const override { item->unsigned_flag= true; item->collation= DTCollation_numeric(); item->fix_char_length(21); return false; } }; protected: const Handler *m_func_handler; public: Item_handled_func(THD *thd, Item *a) :Item_func(thd, a), m_func_handler(NULL) { } Item_handled_func(THD *thd, Item *a, Item *b) :Item_func(thd, a, b), m_func_handler(NULL) { } void set_func_handler(const Handler *handler) { m_func_handler= handler; } const Type_handler *type_handler() const override { return m_func_handler->return_type_handler(this); } Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { DBUG_ASSERT(fixed()); const Type_handler *h= m_func_handler->type_handler_for_create_select(this); return h->make_and_init_table_field(root, &name, Record_addr(maybe_null()), *this, table); } String *val_str(String *to) override { return m_func_handler->val_str(this, to); } String *val_str_ascii(String *to) override { return m_func_handler->val_str_ascii(this, to); } double val_real() override { return m_func_handler->val_real(this); } longlong val_int() override { return m_func_handler->val_int(this); } my_decimal *val_decimal(my_decimal *to) override { return m_func_handler->val_decimal(this, to); } bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) override { return m_func_handler->get_date(thd, this, to, fuzzydate); } bool val_native(THD *thd, Native *to) override { return m_func_handler->val_native(thd, this, to); } }; /** Functions that at fix_fields() time determine the returned field type, trying to preserve the exact data type of the arguments. The descendants have to implement "native" value methods, i.e. str_op(), date_op(), int_op(), real_op(), decimal_op(). fix_fields() chooses which of the above value methods will be used during execution time, according to the returned field type. For example, if fix_fields() determines that the returned value type is MYSQL_TYPE_LONG, then: - int_op() is chosen as the execution time native method. - val_int() returns the result of int_op() as is. - all other methods, i.e. val_real(), val_decimal(), val_str(), get_date(), call int_op() first, then convert the result to the requested data type. */ class Item_func_hybrid_field_type: public Item_hybrid_func { /* Helper methods to make sure that the result of decimal_op(), str_op() and date_op() is properly synched with null_value. */ bool date_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { bool rc= date_op(thd, ltime, date_mode_t(0)); DBUG_ASSERT(!rc ^ null_value); return rc; } bool time_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { bool rc= time_op(thd, ltime); DBUG_ASSERT(!rc ^ null_value); DBUG_ASSERT(rc || ltime->time_type == MYSQL_TIMESTAMP_TIME); return rc; } String *str_op_with_null_check(String *str) { String *res= str_op(str); DBUG_ASSERT((res != NULL) ^ null_value); return res; } public: // Value methods that involve no conversion String *val_str_from_str_op(String *str) { return str_op_with_null_check(&str_value); } longlong val_int_from_int_op() { return int_op(); } double val_real_from_real_op() { return real_op(); } // Value methods that involve conversion String *val_str_from_real_op(String *str); String *val_str_from_int_op(String *str); String *val_str_from_date_op(String *str); String *val_str_from_time_op(String *str); my_decimal *val_decimal_from_str_op(my_decimal *dec); my_decimal *val_decimal_from_real_op(my_decimal *dec); my_decimal *val_decimal_from_int_op(my_decimal *dec); my_decimal *val_decimal_from_date_op(my_decimal *dec); my_decimal *val_decimal_from_time_op(my_decimal *dec); longlong val_int_from_str_op(); longlong val_int_from_real_op(); longlong val_int_from_date_op(); longlong val_int_from_time_op(); double val_real_from_str_op(); double val_real_from_date_op(); double val_real_from_time_op(); double val_real_from_int_op(); public: Item_func_hybrid_field_type(THD *thd): Item_hybrid_func(thd) { collation= DTCollation_numeric(); } Item_func_hybrid_field_type(THD *thd, Item *a): Item_hybrid_func(thd, a) { collation= DTCollation_numeric(); } Item_func_hybrid_field_type(THD *thd, Item *a, Item *b): Item_hybrid_func(thd, a, b) { collation= DTCollation_numeric(); } Item_func_hybrid_field_type(THD *thd, Item *a, Item *b, Item *c): Item_hybrid_func(thd, a, b, c) { collation= DTCollation_numeric(); } Item_func_hybrid_field_type(THD *thd, List<Item> &list): Item_hybrid_func(thd, list) { collation= DTCollation_numeric(); } double val_real() override { DBUG_ASSERT(fixed()); return Item_func_hybrid_field_type::type_handler()-> Item_func_hybrid_field_type_val_real(this); } longlong val_int() override { DBUG_ASSERT(!is_cond()); DBUG_ASSERT(fixed()); return Item_func_hybrid_field_type::type_handler()-> Item_func_hybrid_field_type_val_int(this); } my_decimal *val_decimal(my_decimal *dec) override { DBUG_ASSERT(fixed()); return Item_func_hybrid_field_type::type_handler()-> Item_func_hybrid_field_type_val_decimal(this, dec); } String *val_str(String*str) override { DBUG_ASSERT(fixed()); String *res= Item_func_hybrid_field_type::type_handler()-> Item_func_hybrid_field_type_val_str(this, str); DBUG_ASSERT(null_value == (res == NULL)); return res; } bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) override { DBUG_ASSERT(fixed()); return Item_func_hybrid_field_type::type_handler()-> Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode); } bool val_native(THD *thd, Native *to) override { DBUG_ASSERT(fixed()); return native_op(thd, to); } /** @brief Performs the operation that this functions implements when the result type is INT. @return The result of the operation. */ virtual longlong int_op()= 0; Longlong_null to_longlong_null_op() { longlong nr= int_op(); /* C++ does not guarantee the order of parameter evaluation, so to make sure "null_value" is passed to the constructor after the int_op() call, int_op() is caled on a separate line. */ return Longlong_null(nr, null_value); } Longlong_hybrid_null to_longlong_hybrid_null_op() { return Longlong_hybrid_null(to_longlong_null_op(), unsigned_flag); } /** @brief Performs the operation that this functions implements when the result type is REAL. @return The result of the operation. */ virtual double real_op()= 0; Double_null to_double_null_op() { // val_real() must be caleed on a separate line. See to_longlong_null() double nr= real_op(); return Double_null(nr, null_value); } /** @brief Performs the operation that this functions implements when the result type is DECIMAL. @param A pointer where the DECIMAL value will be allocated. @return - 0 If the result is NULL - The same pointer it was given, with the area initialized to the result of the operation. */ virtual my_decimal *decimal_op(my_decimal *)= 0; /** @brief Performs the operation that this functions implements when the result type is a string type. @return The result of the operation. */ virtual String *str_op(String *)= 0; /** @brief Performs the operation that this functions implements when field type is DATETIME or DATE. @return The result of the operation. */ virtual bool date_op(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate)= 0; /** @brief Performs the operation that this functions implements when field type is TIME. @return The result of the operation. */ virtual bool time_op(THD *thd, MYSQL_TIME *res)= 0; virtual bool native_op(THD *thd, Native *native)= 0; }; /* This class resembles SQL standard CASE-alike expressions: CASE and its abbreviations COALESCE, NULLIF, IFNULL, IF. <case expression> ::= <case abbreviation> | <case specification> */ class Item_func_case_expression: public Item_func_hybrid_field_type { public: Item_func_case_expression(THD *thd) :Item_func_hybrid_field_type(thd) { } Item_func_case_expression(THD *thd, Item *a) :Item_func_hybrid_field_type(thd, a) { } Item_func_case_expression(THD *thd, Item *a, Item *b) :Item_func_hybrid_field_type(thd, a, b) { } Item_func_case_expression(THD *thd, Item *a, Item *b, Item *c) :Item_func_hybrid_field_type(thd, a, b, c) { } Item_func_case_expression(THD *thd, List<Item> &list): Item_func_hybrid_field_type(thd, list) { } bool find_not_null_fields(table_map allowed) override { return false; } }; class Item_func_numhybrid: public Item_func_hybrid_field_type { protected: inline void fix_decimals() { DBUG_ASSERT(result_type() == DECIMAL_RESULT); if (decimals == NOT_FIXED_DEC && decimals >= max_length) decimals= decimal_digits_t(max_length - 1); } public: Item_func_numhybrid(THD *thd): Item_func_hybrid_field_type(thd) { } Item_func_numhybrid(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a) { } Item_func_numhybrid(THD *thd, Item *a, Item *b): Item_func_hybrid_field_type(thd, a, b) { } Item_func_numhybrid(THD *thd, Item *a, Item *b, Item *c): Item_func_hybrid_field_type(thd, a, b, c) { } Item_func_numhybrid(THD *thd, List<Item> &list): Item_func_hybrid_field_type(thd, list) { } String *str_op(String *str) override { DBUG_ASSERT(0); return 0; } bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { DBUG_ASSERT(0); return true; } bool time_op(THD *thd, MYSQL_TIME *ltime) override { DBUG_ASSERT(0); return true; } bool native_op(THD *thd, Native *to) override { DBUG_ASSERT(0); return true; } }; /* function where type of result detected by first argument */ class Item_func_num1: public Item_func_numhybrid { public: Item_func_num1(THD *thd, Item *a): Item_func_numhybrid(thd, a) {} Item_func_num1(THD *thd, Item *a, Item *b): Item_func_numhybrid(thd, a, b) {} bool check_partition_func_processor(void *int_arg) override { return FALSE; } bool check_vcol_func_processor(void *arg) override { return FALSE; } }; /* Base class for operations like '+', '-', '*' */ class Item_num_op :public Item_func_numhybrid { protected: bool check_arguments() const override { return false; // Checked by aggregate_for_num_op() } public: Item_num_op(THD *thd, Item *a, Item *b): Item_func_numhybrid(thd, a, b) {} virtual void result_precision()= 0; void print(String *str, enum_query_type query_type) override { print_op(str, query_type); } bool fix_type_handler(const Type_aggregator *aggregator); void fix_length_and_dec_double() { aggregate_numeric_attributes_real(args, arg_count); max_length= float_length(decimals); } void fix_length_and_dec_decimal() { unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag; result_precision(); fix_decimals(); } void fix_length_and_dec_int() { unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag; result_precision(); decimals= 0; set_handler(type_handler_long_or_longlong()); } void fix_length_and_dec_temporal(bool downcast_decimal_to_int) { set_handler(&type_handler_newdecimal); fix_length_and_dec_decimal(); if (decimals == 0 && downcast_decimal_to_int) set_handler(type_handler_long_or_longlong()); } bool need_parentheses_in_default() override { return true; } }; class Item_int_func :public Item_func { public: /* QQ: shouldn't 20 characters be enough: Max unsigned = 18,446,744,073,709,551,615 = 20 digits, 20 characters Max signed = 9,223,372,036,854,775,807 = 19 digits, 19 characters Min signed = -9,223,372,036,854,775,808 = 19 digits, 20 characters */ Item_int_func(THD *thd): Item_func(thd) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item *a): Item_func(thd, a) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_func(thd, a, b, c, d) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, List<Item> &list): Item_func(thd, list) { collation= DTCollation_numeric(); fix_char_length(21); } Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) { collation= DTCollation_numeric(); } double val_real() override; String *val_str(String*str) override; my_decimal *val_decimal(my_decimal *decimal_value) override { return val_decimal_from_int(decimal_value); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_int(thd, ltime, fuzzydate); } const Type_handler *type_handler() const override= 0; bool fix_length_and_dec(THD *thd) override { return FALSE; } }; class Item_long_func: public Item_int_func { public: Item_long_func(THD *thd): Item_int_func(thd) { } Item_long_func(THD *thd, Item *a): Item_int_func(thd, a) {} Item_long_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} Item_long_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} Item_long_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { } Item_long_func(THD *thd, Item_long_func *item) :Item_int_func(thd, item) {} const Type_handler *type_handler() const override { if (unsigned_flag) return &type_handler_ulong; return &type_handler_slong; } bool fix_length_and_dec(THD *thd) override { max_length= 11; return FALSE; } }; class Item_long_ge0_func: public Item_int_func { public: Item_long_ge0_func(THD *thd): Item_int_func(thd) { } Item_long_ge0_func(THD *thd, Item *a): Item_int_func(thd, a) {} Item_long_ge0_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} Item_long_ge0_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} Item_long_ge0_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { } Item_long_ge0_func(THD *thd, Item_long_ge0_func *item) :Item_int_func(thd, item) {} const Type_handler *type_handler() const override { DBUG_ASSERT(!unsigned_flag); return &type_handler_slong_ge0; } bool fix_length_and_dec(THD *) override { max_length= 10; return FALSE; } }; class Item_func_hash: public Item_int_func { public: Item_func_hash(THD *thd, List<Item> &item): Item_int_func(thd, item) {} longlong val_int() override; bool fix_length_and_dec(THD *thd) override; const Type_handler *type_handler() const override { return &type_handler_slong; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<hash>") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_hash>(thd, this); } }; class Item_func_hash_mariadb_100403: public Item_func_hash { public: Item_func_hash_mariadb_100403(THD *thd, List<Item> &item) :Item_func_hash(thd, item) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<hash_mariadb_100403>") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_hash_mariadb_100403>(thd, this); } }; class Item_longlong_func: public Item_int_func { public: Item_longlong_func(THD *thd): Item_int_func(thd) { } Item_longlong_func(THD *thd, Item *a): Item_int_func(thd, a) {} Item_longlong_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} Item_longlong_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} Item_longlong_func(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_int_func(thd, a, b, c, d) {} Item_longlong_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { } Item_longlong_func(THD *thd, Item_longlong_func *item) :Item_int_func(thd, item) {} const Type_handler *type_handler() const override { if (unsigned_flag) return &type_handler_ulonglong; return &type_handler_slonglong; } }; class Cursor_ref { protected: LEX_CSTRING m_cursor_name; uint m_cursor_offset; class sp_cursor *get_open_cursor_or_error(); Cursor_ref(const LEX_CSTRING *name, uint offset) :m_cursor_name(*name), m_cursor_offset(offset) { } void print_func(String *str, const LEX_CSTRING &func_name); }; class Item_func_cursor_rowcount: public Item_longlong_func, public Cursor_ref { public: Item_func_cursor_rowcount(THD *thd, const LEX_CSTRING *name, uint offset) :Item_longlong_func(thd), Cursor_ref(name, offset) { set_maybe_null(); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("%ROWCOUNT") }; return name; } longlong val_int() override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC); } void print(String *str, enum_query_type query_type) override { return Cursor_ref::print_func(str, func_name_cstring()); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cursor_rowcount>(thd, this); } }; class Item_func_connection_id :public Item_long_func { longlong value; public: Item_func_connection_id(THD *thd): Item_long_func(thd) { unsigned_flag=1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("connection_id") }; return name; } bool fix_length_and_dec(THD *thd) override; bool fix_fields(THD *thd, Item **ref) override; longlong val_int() override { DBUG_ASSERT(fixed()); return value; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_connection_id>(thd, this); } }; class Item_func_signed :public Item_int_func { public: Item_func_signed(THD *thd, Item *a): Item_int_func(thd, a) { unsigned_flag= 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_signed") }; return name; } const Type_handler *type_handler() const override { return Type_handler::type_handler_long_or_longlong(max_char_length(), false); } longlong val_int() override { longlong value= args[0]->val_int_signed_typecast(); null_value= args[0]->null_value; return value; } void fix_length_and_dec_double() { fix_char_length(MAX_BIGINT_WIDTH); } void fix_length_and_dec_sint_ge0() { uint32 digits= args[0]->decimal_precision(); DBUG_ASSERT(digits > 0); DBUG_ASSERT(digits <= MY_INT64_NUM_DECIMAL_DIGITS); fix_char_length(digits + (unsigned_flag ? 0 : 1/*sign*/)); } void fix_length_and_dec_generic() { uint32 char_length= MY_MIN(args[0]->max_char_length(), MY_INT64_NUM_DECIMAL_DIGITS); /* args[0]->max_char_length() can return 0. Reserve max_length to fit at least one character for one digit, plus one character for the sign (if signed). */ set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1)); fix_char_length(char_length); } void fix_length_and_dec_string() { /* For strings, use decimal_int_part() instead of max_char_length(). This is important for Item_hex_hybrid: SELECT CAST(0x1FFFFFFFF AS SIGNED); Length is 5, decimal_int_part() is 13. */ uint32 char_length= MY_MIN(args[0]->decimal_int_part(), MY_INT64_NUM_DECIMAL_DIGITS); set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1)); fix_char_length(char_length); } bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this); } void print(String *str, enum_query_type query_type) override; decimal_digits_t decimal_precision() const override { return args[0]->decimal_precision(); } bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_signed>(thd, this); } }; class Item_func_unsigned :public Item_func_signed { public: Item_func_unsigned(THD *thd, Item *a): Item_func_signed(thd, a) { unsigned_flag= 1; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_unsigned") }; return name; } const Type_handler *type_handler() const override { if (max_char_length() <= MY_INT32_NUM_DECIMAL_DIGITS - 1) return &type_handler_ulong; return &type_handler_ulonglong; } longlong val_int() override { longlong value= args[0]->val_int_unsigned_typecast(); null_value= args[0]->null_value; return value; } bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this); } decimal_digits_t decimal_precision() const override { return decimal_digits_t(max_length); } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_unsigned>(thd, this); } }; class Item_decimal_typecast :public Item_func { my_decimal decimal_value; public: Item_decimal_typecast(THD *thd, Item *a, decimal_digits_t len, decimal_digits_t dec) :Item_func(thd, a) { decimals= dec; collation= DTCollation_numeric(); fix_char_length(my_decimal_precision_to_length_no_truncation(len, dec, unsigned_flag)); } String *val_str(String *str) override { return VDec(this).to_string(str); } double val_real() override { return VDec(this).to_double(); } longlong val_int() override { return VDec(this).to_longlong(unsigned_flag); } my_decimal *val_decimal(my_decimal*) override; bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) override { return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, NULL, NULL); } const Type_handler *type_handler() const override { return &type_handler_newdecimal; } void fix_length_and_dec_generic() {} bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("decimal_typecast") }; return name; } void print(String *str, enum_query_type query_type) override; bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_decimal_typecast>(thd, this); } }; class Item_real_typecast: public Item_real_func { protected: double val_real_with_truncate(double max_value); public: Item_real_typecast(THD *thd, Item *a, uint len, uint dec) :Item_real_func(thd, a) { decimals= (uint8) dec; max_length= (uint32) len; } bool need_parentheses_in_default() override { return true; } void print(String *str, enum_query_type query_type) override; void fix_length_and_dec_generic() { set_maybe_null(); } }; class Item_float_typecast :public Item_real_typecast { public: Item_float_typecast(THD *thd, Item *a) :Item_real_typecast(thd, a, MAX_FLOAT_STR_LENGTH, NOT_FIXED_DEC) { } const Type_handler *type_handler() const override { return &type_handler_float; } bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_float_typecast_fix_length_and_dec(this); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("float_typecast") }; return name; } double val_real() override { return (double) (float) val_real_with_truncate(FLT_MAX); } String *val_str(String*str) override { Float nr(Item_float_typecast::val_real()); if (null_value) return 0; nr.to_string(str, decimals); return str; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_float_typecast>(thd, this); } }; class Item_double_typecast :public Item_real_typecast { public: Item_double_typecast(THD *thd, Item *a, uint len, uint dec): Item_real_typecast(thd, a, len, dec) { } bool fix_length_and_dec(THD *thd) override { return args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("double_typecast") }; return name; } double val_real() override { return val_real_with_truncate(DBL_MAX); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_double_typecast>(thd, this); } }; class Item_func_additive_op :public Item_num_op { public: Item_func_additive_op(THD *thd, Item *a, Item *b): Item_num_op(thd, a, b) {} void result_precision() override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} }; class Item_func_plus :public Item_func_additive_op { public: Item_func_plus(THD *thd, Item *a, Item *b): Item_func_additive_op(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("+") }; return name; } enum precedence precedence() const override { return ADD_PRECEDENCE; } bool fix_length_and_dec(THD *thd) override; longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_plus>(thd, this); } }; class Item_func_minus :public Item_func_additive_op { bool m_depends_on_sql_mode_no_unsigned_subtraction; public: Item_func_minus(THD *thd, Item *a, Item *b): Item_func_additive_op(thd, a, b), m_depends_on_sql_mode_no_unsigned_subtraction(false) { } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("-") }; return name; } enum precedence precedence() const override { return ADD_PRECEDENCE; } Sql_mode_dependency value_depends_on_sql_mode() const override; longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; bool fix_length_and_dec(THD *thd) override; void fix_unsigned_flag(); void fix_length_and_dec_double() { Item_func_additive_op::fix_length_and_dec_double(); fix_unsigned_flag(); } void fix_length_and_dec_decimal() { Item_func_additive_op::fix_length_and_dec_decimal(); fix_unsigned_flag(); } void fix_length_and_dec_int() { Item_func_additive_op::fix_length_and_dec_int(); fix_unsigned_flag(); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_minus>(thd, this); } }; class Item_func_mul :public Item_num_op { public: Item_func_mul(THD *thd, Item *a, Item *b): Item_num_op(thd, a, b) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("*") }; return name; } enum precedence precedence() const override { return MUL_PRECEDENCE; } longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; void result_precision() override; bool fix_length_and_dec(THD *thd) override; bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_mul>(thd, this); } }; class Item_func_div :public Item_num_op { public: uint prec_increment; Item_func_div(THD *thd, Item *a, Item *b): Item_num_op(thd, a, b) {} longlong int_op() override { DBUG_ASSERT(0); return 0; } double real_op() override; my_decimal *decimal_op(my_decimal *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("/") }; return name; } enum precedence precedence() const override { return MUL_PRECEDENCE; } bool fix_length_and_dec(THD *thd) override; void fix_length_and_dec_double(); void fix_length_and_dec_int(); void result_precision() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_div>(thd, this); } }; class Item_func_int_div :public Item_int_func { public: Item_func_int_div(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("DIV") }; return name; } enum precedence precedence() const override { return MUL_PRECEDENCE; } const Type_handler *type_handler() const override { return type_handler_long_or_longlong(); } bool fix_length_and_dec(THD *thd) override; void print(String *str, enum_query_type query_type) override { print_op(str, query_type); } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_int_div>(thd, this); } }; class Item_func_mod :public Item_num_op { public: Item_func_mod(THD *thd, Item *a, Item *b): Item_num_op(thd, a, b) {} longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("MOD") }; return name; } enum precedence precedence() const override { return MUL_PRECEDENCE; } void result_precision() override; bool fix_length_and_dec(THD *thd) override; void fix_length_and_dec_double() { Item_num_op::fix_length_and_dec_double(); unsigned_flag= args[0]->unsigned_flag; } void fix_length_and_dec_decimal() { result_precision(); fix_decimals(); } void fix_length_and_dec_int() { result_precision(); DBUG_ASSERT(decimals == 0); set_handler(type_handler_long_or_longlong()); } bool check_partition_func_processor(void *int_arg) override {return FALSE;} bool check_vcol_func_processor(void *arg) override { return FALSE;} protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_mod>(thd, this); } }; class Item_func_neg :public Item_func_num1 { public: Item_func_neg(THD *thd, Item *a): Item_func_num1(thd, a) {} double real_op() override; longlong int_op() override; my_decimal *decimal_op(my_decimal *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("-") }; return name; } enum Functype functype() const override { return NEG_FUNC; } enum precedence precedence() const override { return NEG_PRECEDENCE; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); args[0]->print_parenthesised(str, query_type, precedence()); } void fix_length_and_dec_int(); void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); bool fix_length_and_dec(THD *thd) override; decimal_digits_t decimal_precision() const override { return args[0]->decimal_precision(); } bool need_parentheses_in_default() override { return true; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_neg>(thd, this); } }; class Item_func_abs :public Item_func_num1 { public: Item_func_abs(THD *thd, Item *a): Item_func_num1(thd, a) {} double real_op() override; longlong int_op() override; my_decimal *decimal_op(my_decimal *) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("abs") }; return name; } void fix_length_and_dec_int(); void fix_length_and_dec_sint_ge0(); void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_abs>(thd, this); } }; // A class to handle logarithmic and trigonometric functions class Item_dec_func :public Item_real_func { bool check_arguments() const override { return check_argument_types_can_return_real(0, arg_count); } public: Item_dec_func(THD *thd, Item *a): Item_real_func(thd, a) {} Item_dec_func(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {} bool fix_length_and_dec(THD *thd) override { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); set_maybe_null(); return FALSE; } }; class Item_func_exp :public Item_dec_func { public: Item_func_exp(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("exp") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_exp>(thd, this); } }; class Item_func_ln :public Item_dec_func { public: Item_func_ln(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ln") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ln>(thd, this); } }; class Item_func_log :public Item_dec_func { public: Item_func_log(THD *thd, Item *a): Item_dec_func(thd, a) {} Item_func_log(THD *thd, Item *a, Item *b): Item_dec_func(thd, a, b) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("log") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_log>(thd, this); } }; class Item_func_log2 :public Item_dec_func { public: Item_func_log2(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("log2") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_log2>(thd, this); } }; class Item_func_log10 :public Item_dec_func { public: Item_func_log10(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("log10") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_log10>(thd, this); } }; class Item_func_sqrt :public Item_dec_func { public: Item_func_sqrt(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sqrt") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sqrt>(thd, this); } }; class Item_func_pow :public Item_dec_func { public: Item_func_pow(THD *thd, Item *a, Item *b): Item_dec_func(thd, a, b) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("pow") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_pow>(thd, this); } }; class Item_func_acos :public Item_dec_func { public: Item_func_acos(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("acos") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_acos>(thd, this); } }; class Item_func_asin :public Item_dec_func { public: Item_func_asin(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("asin") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_asin>(thd, this); } }; class Item_func_atan :public Item_dec_func { public: Item_func_atan(THD *thd, Item *a): Item_dec_func(thd, a) {} Item_func_atan(THD *thd, Item *a, Item *b): Item_dec_func(thd, a, b) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("atan") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_atan>(thd, this); } }; class Item_func_cos :public Item_dec_func { public: Item_func_cos(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cos") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cos>(thd, this); } }; class Item_func_sin :public Item_dec_func { public: Item_func_sin(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sin") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sin>(thd, this); } }; class Item_func_tan :public Item_dec_func { public: Item_func_tan(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("tan") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_tan>(thd, this); } }; class Item_func_cot :public Item_dec_func { public: Item_func_cot(THD *thd, Item *a): Item_dec_func(thd, a) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("cot") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_cot>(thd, this); } }; class Item_func_int_val :public Item_func_hybrid_field_type { public: Item_func_int_val(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a) {} bool check_partition_func_processor(void *int_arg) override { return FALSE; } bool check_vcol_func_processor(void *arg) override { return FALSE; } virtual decimal_round_mode round_mode() const= 0; void fix_length_and_dec_double(); void fix_length_and_dec_int_or_decimal(); void fix_length_and_dec_time() { fix_attributes_time(0); set_handler(&type_handler_time2); } void fix_length_and_dec_datetime() { fix_attributes_datetime(0); set_handler(&type_handler_datetime2); // Thinks like CEILING(TIMESTAMP'0000-01-01 23:59:59.9') returns NULL set_maybe_null(); } bool fix_length_and_dec(THD *thd) override; String *str_op(String *str) override { DBUG_ASSERT(0); return 0; } bool native_op(THD *thd, Native *to) override; }; class Item_func_ceiling :public Item_func_int_val { public: Item_func_ceiling(THD *thd, Item *a): Item_func_int_val(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ceiling") }; return name; } decimal_round_mode round_mode() const override { return CEILING; } longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ceiling>(thd, this); } }; class Item_func_floor :public Item_func_int_val { public: Item_func_floor(THD *thd, Item *a): Item_func_int_val(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("floor") }; return name; } decimal_round_mode round_mode() const override { return FLOOR; } longlong int_op() override; double real_op() override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_floor>(thd, this); } }; /* This handles round and truncate */ class Item_func_round :public Item_func_hybrid_field_type { bool truncate; void fix_length_and_dec_decimal(uint decimals_to_set); void fix_length_and_dec_double(uint decimals_to_set); bool test_if_length_can_increase(); public: Item_func_round(THD *thd, Item *a, Item *b, bool trunc_arg) :Item_func_hybrid_field_type(thd, a, b), truncate(trunc_arg) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING truncate_name= {STRING_WITH_LEN("truncate") }; static LEX_CSTRING round_name= {STRING_WITH_LEN("round") }; return truncate ? truncate_name : round_name; } double real_op() override; longlong int_op() override; my_decimal *decimal_op(my_decimal *) override; bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool time_op(THD *thd, MYSQL_TIME *ltime) override; bool native_op(THD *thd, Native *to) override; String *str_op(String *str) override { DBUG_ASSERT(0); return NULL; } void fix_arg_decimal(); void fix_arg_int(const Type_handler *preferred, const Type_std_attributes *preferred_attributes, bool use_decimal_on_length_increase); void fix_arg_slong_ge0(); void fix_arg_hex_hybrid(); void fix_arg_double(); void fix_arg_time(); void fix_arg_datetime(); void fix_arg_temporal(const Type_handler *h, uint int_part_length); bool fix_length_and_dec(THD *thd) override { /* We don't want to translate ENUM/SET to CHAR here. So let's real_type_handler(), not type_handler(). */ return args[0]->real_type_handler()->Item_func_round_fix_length_and_dec(this); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_round>(thd, this); } }; class Item_func_rand :public Item_real_func { struct my_rnd_struct *rand; bool first_eval; // TRUE if val_real() is called 1st time bool check_arguments() const override { return check_argument_types_can_return_int(0, arg_count); } void seed_random (Item * val); public: Item_func_rand(THD *thd, Item *a): Item_real_func(thd, a), rand(0), first_eval(TRUE) {} Item_func_rand(THD *thd): Item_real_func(thd) {} double val_real() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rand") }; return name; } bool const_item() const override { return 0; } void update_used_tables() override; bool fix_fields(THD *thd, Item **ref) override; void cleanup() override { first_eval= TRUE; Item_real_func::cleanup(); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rand>(thd, this); } }; class Item_func_rownum final :public Item_longlong_func { /* This points to a variable that contains the number of rows accpted so far in the result set */ ha_rows *accepted_rows; SELECT_LEX *select; public: Item_func_rownum(THD *thd); longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rownum") }; return name; } enum Functype functype() const override { return ROWNUM_FUNC; } void update_used_tables() override {} bool const_item() const override { return 0; } void fix_after_optimize(THD *thd) override; bool fix_length_and_dec(THD *thd) override { unsigned_flag= 1; used_tables_cache= RAND_TABLE_BIT; const_item_cache=0; set_maybe_null(); return FALSE; } void cleanup() override { Item_longlong_func::cleanup(); /* Ensure we don't point to freed memory */ accepted_rows= 0; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } bool check_handler_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } /* This function is used in insert, update and delete */ void store_pointer_to_row_counter(ha_rows *row_counter) { accepted_rows= row_counter; } protected: Item *shallow_copy(THD *thd) const override { return 0; } }; void fix_rownum_pointers(THD *thd, SELECT_LEX *select_lex, ha_rows *ptr); class Item_func_sign :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_real(func_name_cstring()); } public: Item_func_sign(THD *thd, Item *a): Item_long_func(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sign") }; return name; } decimal_digits_t decimal_precision() const override { return 1; } bool fix_length_and_dec(THD *thd) override { fix_char_length(2); return FALSE; } longlong val_int() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sign>(thd, this); } }; class Item_func_units :public Item_real_func { LEX_CSTRING name; double mul,add; bool check_arguments() const override { return check_argument_types_can_return_real(0, arg_count); } public: Item_func_units(THD *thd, char *name_arg, Item *a, double mul_arg, double add_arg): Item_real_func(thd, a), mul(mul_arg), add(add_arg) { name.str= name_arg; name.length= strlen(name_arg); } double val_real() override; LEX_CSTRING func_name_cstring() const override { return name; } bool fix_length_and_dec(THD *thd) override { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_units>(thd, this); } }; /** Item_func_min_max does not derive from Item_func_hybrid_field_type because the way how its methods val_xxx() and get_date() work depend not only by its arguments, but also on the context in which LEAST() and GREATEST() appear. For example, using Item_func_min_max in a CAST like this: CAST(LEAST('11','2') AS SIGNED) forces Item_func_min_max to compare the arguments as numbers rather than strings. Perhaps this should be changed eventually (see MDEV-5893). */ class Item_func_min_max :public Item_hybrid_func { String tmp_value; int cmp_sign; protected: bool check_arguments() const override { return false; // Checked by aggregate_for_min_max() } bool fix_attributes(Item **item, uint nitems); public: Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg): Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg) {} String *val_str_native(String *str); double val_real_native(); longlong val_int_native(); longlong val_uint_native(); my_decimal *val_decimal_native(my_decimal *); bool get_date_native(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); bool get_time_native(THD *thd, MYSQL_TIME *res); double val_real() override { DBUG_ASSERT(fixed()); return Item_func_min_max::type_handler()-> Item_func_min_max_val_real(this); } longlong val_int() override { DBUG_ASSERT(fixed()); return Item_func_min_max::type_handler()-> Item_func_min_max_val_int(this); } String *val_str(String *str) override { DBUG_ASSERT(fixed()); return Item_func_min_max::type_handler()-> Item_func_min_max_val_str(this, str); } my_decimal *val_decimal(my_decimal *dec) override { DBUG_ASSERT(fixed()); return Item_func_min_max::type_handler()-> Item_func_min_max_val_decimal(this, dec); } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override { DBUG_ASSERT(fixed()); return Item_func_min_max::type_handler()-> Item_func_min_max_get_date(thd, this, res, fuzzydate); } bool val_native(THD *thd, Native *to) override; void aggregate_attributes_real(Item **items, uint nitems) { /* Aggregating attributes for the double data type for LEAST/GREATEST is almost the same with aggregating for CASE-alike hybrid functions, (CASE..THEN, COALESCE, IF, etc). There is one notable difference though, when a numeric argument is mixed with a string argument: - CASE-alike functions return a string data type in such cases COALESCE(10,'x') -> VARCHAR(2) = '10' - LEAST/GREATEST returns double: GREATEST(10,'10e4') -> DOUBLE = 100000 As the string argument can represent a number in the scientific notation, like in the example above, max_length of the result can be longer than max_length of the arguments. To handle this properly, max_length is additionally assigned to the result of float_length(decimals). */ Item_func::aggregate_attributes_real(items, nitems); max_length= float_length(decimals); } bool fix_length_and_dec(THD *thd) override { if (aggregate_for_min_max(func_name_cstring(), args, arg_count)) return true; fix_attributes(args, arg_count); return false; } }; class Item_func_min :public Item_func_min_max { public: Item_func_min(THD *thd, List<Item> &list): Item_func_min_max(thd, list, 1) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("least") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_min>(thd, this); } }; class Item_func_max :public Item_func_min_max { public: Item_func_max(THD *thd, List<Item> &list): Item_func_min_max(thd, list, -1) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("greatest") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_max>(thd, this); } }; /* Objects of this class are used for ROLLUP queries to wrap up each constant item referred to in GROUP BY list. */ class Item_func_rollup_const :public Item_func { public: Item_func_rollup_const(THD *thd, Item *a): Item_func(thd, a) { name= a->name; } double val_real() override { return val_real_from_item(args[0]); } longlong val_int() override { return val_int_from_item(args[0]); } String *val_str(String *str) override { return val_str_from_item(args[0], str); } bool val_native(THD *thd, Native *to) override { return val_native_from_item(thd, args[0], to); } my_decimal *val_decimal(my_decimal *dec) override { return val_decimal_from_item(args[0], dec); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return get_date_from_item(thd, args[0], ltime, fuzzydate); } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("rollup_const") }; return name; } bool const_item() const override { return 0; } const Type_handler *type_handler() const override { return args[0]->type_handler(); } bool fix_length_and_dec(THD *thd) override { Type_std_attributes::set(*args[0]); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_rollup_const>(thd, this); } }; class Item_long_func_length: public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_str(func_name_cstring()); } public: Item_long_func_length(THD *thd, Item *a): Item_long_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { max_length=10; return FALSE; } }; class Item_func_octet_length :public Item_long_func_length { String value; public: Item_func_octet_length(THD *thd, Item *a): Item_long_func_length(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("octet_length") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_octet_length>(thd, this); } }; class Item_func_bit_length :public Item_longlong_func { String value; public: Item_func_bit_length(THD *thd, Item *a): Item_longlong_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { max_length= 11; // 0x100000000*8 = 34,359,738,368 return FALSE; } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("bit_length") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_length>(thd, this); } }; class Item_func_char_length :public Item_long_func_length { String value; public: Item_func_char_length(THD *thd, Item *a): Item_long_func_length(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("char_length") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_char_length>(thd, this); } }; class Item_func_coercibility :public Item_long_func { longlong m_cached_collation_derivation; bool check_arguments() const override { return args[0]->check_type_can_return_str(func_name_cstring()); } public: Item_func_coercibility(THD *thd, Item *a): Item_long_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("coercibility") }; return name; } bool fix_length_and_dec(THD *thd) override; bool eval_not_null_tables(void *) override { not_null_tables_cache= 0; return false; } bool find_not_null_fields(table_map allowed) override { return false; } Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) override { return this; } bool const_item() const override { return true; } table_map used_tables() const override { return 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_coercibility>(thd, this); } }; /* In the corner case LOCATE could return (4,294,967,296 + 1), which would not fit into Item_long_func range. But string lengths are limited with max_allowed_packet, which cannot be bigger than 1024*1024*1024. */ class Item_func_locate :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_str(0, 2) || (arg_count > 2 && args[2]->check_type_can_return_int(func_name_cstring())); } String value1,value2; DTCollation cmp_collation; public: Item_func_locate(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {} Item_func_locate(THD *thd, Item *a, Item *b, Item *c) :Item_long_func(thd, a, b, c) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("locate") }; return name; } longlong val_int() override; bool fix_length_and_dec(THD *thd) override { max_length= MY_INT32_NUM_DECIMAL_DIGITS; return agg_arg_charsets_for_comparison(cmp_collation, args, 2); } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_locate>(thd, this); } }; class Item_func_field :public Item_long_func { String value,tmp; Item_result cmp_type; DTCollation cmp_collation; public: Item_func_field(THD *thd, List<Item> &list): Item_long_func(thd, list) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("field") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_field>(thd, this); } }; class Item_func_ascii :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_str(0, arg_count); } String value; public: Item_func_ascii(THD *thd, Item *a): Item_long_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ascii") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=3; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ascii>(thd, this); } }; class Item_func_ord :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_str(func_name_cstring()); } String value; public: Item_func_ord(THD *thd, Item *a): Item_long_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { fix_char_length(7); return FALSE; } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("ord") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_ord>(thd, this); } }; class Item_func_find_in_set :public Item_long_func { bool check_arguments() const override { return check_argument_types_can_return_str(0, 2); } String value,value2; uint enum_value; ulonglong enum_bit; DTCollation cmp_collation; public: Item_func_find_in_set(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b), enum_value(0) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("find_in_set") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_find_in_set>(thd, this); } }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ class Item_func_bit_operator: public Item_handled_func { bool check_arguments() const override { return check_argument_types_can_return_int(0, arg_count); } protected: bool fix_length_and_dec_op1_std(const Handler *ha_int, const Handler *ha_dec) { set_func_handler(args[0]->cmp_type() == INT_RESULT ? ha_int : ha_dec); return m_func_handler->fix_length_and_dec(this); } bool fix_length_and_dec_op2_std(const Handler *ha_int, const Handler *ha_dec) { set_func_handler(args[0]->cmp_type() == INT_RESULT && args[1]->cmp_type() == INT_RESULT ? ha_int : ha_dec); return m_func_handler->fix_length_and_dec(this); } public: Item_func_bit_operator(THD *thd, Item *a) :Item_handled_func(thd, a) {} Item_func_bit_operator(THD *thd, Item *a, Item *b) :Item_handled_func(thd, a, b) {} void print(String *str, enum_query_type query_type) override { print_op(str, query_type); } bool need_parentheses_in_default() override { return true; } }; class Item_func_bit_or :public Item_func_bit_operator { public: Item_func_bit_or(THD *thd, Item *a, Item *b) :Item_func_bit_operator(thd, a, b) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("|") }; return name; } enum precedence precedence() const override { return BITOR_PRECEDENCE; } Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_or>(thd, this); } }; class Item_func_bit_and :public Item_func_bit_operator { public: Item_func_bit_and(THD *thd, Item *a, Item *b) :Item_func_bit_operator(thd, a, b) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("&") }; return name; } enum precedence precedence() const override { return BITAND_PRECEDENCE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_and>(thd, this); } }; class Item_func_bit_count :public Item_handled_func { bool check_arguments() const override { return args[0]->check_type_can_return_int(func_name_cstring()); } public: Item_func_bit_count(THD *thd, Item *a): Item_handled_func(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("bit_count") }; return name; } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_count>(thd, this); } }; class Item_func_shift_left :public Item_func_bit_operator { public: Item_func_shift_left(THD *thd, Item *a, Item *b) :Item_func_bit_operator(thd, a, b) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("<<") }; return name; } enum precedence precedence() const override { return SHIFT_PRECEDENCE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_shift_left>(thd, this); } }; class Item_func_shift_right :public Item_func_bit_operator { public: Item_func_shift_right(THD *thd, Item *a, Item *b) :Item_func_bit_operator(thd, a, b) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN(">>") }; return name; } enum precedence precedence() const override { return SHIFT_PRECEDENCE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_shift_right>(thd, this); } }; class Item_func_bit_neg :public Item_func_bit_operator { public: Item_func_bit_neg(THD *thd, Item *a): Item_func_bit_operator(thd, a) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("~") }; return name; } enum precedence precedence() const override { return NEG_PRECEDENCE; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); args[0]->print_parenthesised(str, query_type, precedence()); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_neg>(thd, this); } }; class Item_func_last_insert_id :public Item_longlong_func { bool check_arguments() const override { return check_argument_types_can_return_int(0, arg_count); } public: Item_func_last_insert_id(THD *thd): Item_longlong_func(thd) {} Item_func_last_insert_id(THD *thd, Item *a): Item_longlong_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("last_insert_id") }; return name; } bool fix_length_and_dec(THD *thd) override { unsigned_flag= true; if (arg_count) max_length= args[0]->max_length; return FALSE; } bool fix_fields(THD *thd, Item **ref) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_last_insert_id>(thd, this); } }; class Item_func_benchmark :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_int(func_name_cstring()) || args[1]->check_type_scalar(func_name_cstring()); } public: Item_func_benchmark(THD *thd, Item *count_expr, Item *expr): Item_long_func(thd, count_expr, expr) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("benchmark") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=1; base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; } void print(String *str, enum_query_type query_type) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_benchmark>(thd, this); } }; void item_func_sleep_init(void); void item_func_sleep_free(void); class Item_func_sleep :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_can_return_real(func_name_cstring()); } public: Item_func_sleep(THD *thd, Item *a): Item_long_func(thd, a) {} bool fix_length_and_dec(THD *thd) override { fix_char_length(1); return FALSE; } bool const_item() const override { return 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sleep") }; return name; } table_map used_tables() const override { return used_tables_cache | RAND_TABLE_BIT; } bool is_expensive() override { return 1; } longlong val_int() override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sleep>(thd, this); } }; #ifdef HAVE_DLOPEN class Item_udf_func :public Item_func { /** Mark "this" as non-deterministic if it uses no tables and is not a constant at the same time. */ void set_non_deterministic_if_needed() { if (!const_item_cache && !used_tables_cache) used_tables_cache= RAND_TABLE_BIT; } protected: udf_handler udf; bool is_expensive_processor(void *arg) override { return TRUE; } class VDec_udf: public Dec_ptr_and_buffer { public: VDec_udf(Item_udf_func *func, udf_handler *udf) { my_bool tmp_null_value; m_ptr= udf->val_decimal(&tmp_null_value, &m_buffer); DBUG_ASSERT(is_null() == (tmp_null_value != 0)); func->null_value= is_null(); } }; public: Item_udf_func(THD *thd, udf_func *udf_arg): Item_func(thd), udf(udf_arg) {} Item_udf_func(THD *thd, udf_func *udf_arg, List<Item> &list): Item_func(thd, list), udf(udf_arg) {} LEX_CSTRING func_name_cstring() const override { const char *tmp= udf.name(); return { tmp, strlen(tmp) }; } enum Functype functype() const override { return UDF_FUNC; } bool fix_fields(THD *thd, Item **ref) override { DBUG_ASSERT(fixed() == 0); bool res= udf.fix_fields(thd, this, arg_count, args); set_non_deterministic_if_needed(); base_flags|= item_base_t::FIXED; return res; } void fix_num_length_and_dec(); void update_used_tables() override { /* TODO: Make a member in UDF_INIT and return if a UDF is deterministic or not. Currently UDF_INIT has a member (const_item) that is an in/out parameter to the init() call. The code in udf_handler::fix_fields also duplicates the arguments handling code in Item_func::fix_fields(). The lack of information if a UDF is deterministic makes writing a correct update_used_tables() for UDFs impossible. One solution to this would be : - Add a is_deterministic member of UDF_INIT - (optionally) deprecate the const_item member of UDF_INIT - Take away the duplicate code from udf_handler::fix_fields() and make Item_udf_func call Item_func::fix_fields() to process its arguments as for any other function. - Store the deterministic flag returned by <udf>_init into the udf_handler. - Don't implement Item_udf_func::fix_fields, implement Item_udf_func::fix_length_and_dec() instead (similar to non-UDF functions). - Override Item_func::update_used_tables to call Item_func::update_used_tables() and add a RAND_TABLE_BIT to the result of Item_func::update_used_tables() if the UDF is non-deterministic. - (optionally) rename RAND_TABLE_BIT to NONDETERMINISTIC_BIT to better describe its usage. The above would require a change of the UDF API. Until that change is done here's how the current code works: We call Item_func::update_used_tables() only when we know that the function depends on real non-const tables and is deterministic. This can be done only because we know that the optimizer will call update_used_tables() only when there's possibly a new const table. So update_used_tables() can only make a Item_func more constant than it is currently. That's why we don't need to do anything if a function is guaranteed to return non-constant (it's non-deterministic) or is already a const. */ if ((used_tables_cache & ~PSEUDO_TABLE_BITS) && !(used_tables_cache & RAND_TABLE_BIT)) { Item_func::update_used_tables(); set_non_deterministic_if_needed(); } } void cleanup() override; bool eval_not_null_tables(void *opt_arg) override { not_null_tables_cache= 0; return 0; } bool find_not_null_fields(table_map allowed) override { return false; } bool is_expensive() override { return 1; } void print(String *str, enum_query_type query_type) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { return false; } }; class Item_func_udf_float :public Item_udf_func { public: Item_func_udf_float(THD *thd, udf_func *udf_arg): Item_udf_func(thd, udf_arg) {} Item_func_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} longlong val_int() override { DBUG_ASSERT(fixed()); return Converter_double_to_longlong(Item_func_udf_float::val_real(), unsigned_flag).result(); } my_decimal *val_decimal(my_decimal *dec_buf) override { double res=val_real(); if (null_value) return NULL; double2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf); return dec_buf; } double val_real() override; String *val_str(String *str) override; const Type_handler *type_handler() const override { return &type_handler_double; } bool fix_length_and_dec(THD *thd) override { fix_num_length_and_dec(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_udf_float>(thd, this); } }; class Item_func_udf_int :public Item_udf_func { public: Item_func_udf_int(THD *thd, udf_func *udf_arg): Item_udf_func(thd, udf_arg) {} Item_func_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} longlong val_int() override; double val_real() override { return (double) Item_func_udf_int::val_int(); } my_decimal *val_decimal(my_decimal *decimal_value) override { return val_decimal_from_int(decimal_value); } String *val_str(String *str) override; const Type_handler *type_handler() const override { if (unsigned_flag) return &type_handler_ulonglong; return &type_handler_slonglong; } bool fix_length_and_dec(THD *thd) override { decimals= 0; max_length= 21; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_udf_int>(thd, this); } }; class Item_func_udf_decimal :public Item_udf_func { public: Item_func_udf_decimal(THD *thd, udf_func *udf_arg): Item_udf_func(thd, udf_arg) {} Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} longlong val_int() override { return VDec_udf(this, &udf).to_longlong(unsigned_flag); } double val_real() override { return VDec_udf(this, &udf).to_double(); } my_decimal *val_decimal(my_decimal *) override; String *val_str(String *str) override { return VDec_udf(this, &udf).to_string_round(str, decimals); } const Type_handler *type_handler() const override { return &type_handler_newdecimal; } bool fix_length_and_dec(THD *thd) override { fix_num_length_and_dec(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_udf_decimal>(thd, this); } }; class Item_func_udf_str :public Item_udf_func { public: Item_func_udf_str(THD *thd, udf_func *udf_arg): Item_udf_func(thd, udf_arg) {} Item_func_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} String *val_str(String *) override; double val_real() override { int err_not_used; char *end_not_used; String *res; res= val_str(&str_value); return res ? res->charset()->strntod((char*) res->ptr(), res->length(), &end_not_used, &err_not_used) : 0.0; } longlong val_int() override { int err_not_used; String *res; res=val_str(&str_value); return res ? res->charset()->strntoll(res->ptr(),res->length(),10, (char**) 0, &err_not_used) : (longlong) 0; } my_decimal *val_decimal(my_decimal *dec_buf) override { String *res=val_str(&str_value); if (!res) return NULL; string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf); return dec_buf; } const Type_handler *type_handler() const override { return string_type_handler(); } bool fix_length_and_dec(THD *thd) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_udf_str>(thd, this); } }; #else /* Dummy functions to get yy_*.cc files compiled */ class Item_func_udf_float :public Item_real_func { public: Item_func_udf_float(THD *thd, udf_func *udf_arg): Item_real_func(thd) {} Item_func_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): Item_real_func(thd, list) {} double val_real() { DBUG_ASSERT(fixed()); return 0.0; } }; class Item_func_udf_int :public Item_int_func { public: Item_func_udf_int(THD *thd, udf_func *udf_arg): Item_int_func(thd) {} Item_func_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): Item_int_func(thd, list) {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } longlong val_int() { DBUG_ASSERT(fixed()); return 0; } }; class Item_func_udf_decimal :public Item_int_func { public: Item_func_udf_decimal(THD *thd, udf_func *udf_arg): Item_int_func(thd) {} Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_int_func(thd, list) {} const Type_handler *type_handler() const override { return &type_handler_slonglong; } my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed()); return 0; } }; class Item_func_udf_str :public Item_func { public: Item_func_udf_str(THD *thd, udf_func *udf_arg): Item_func(thd) {} Item_func_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): Item_func(thd, list) {} String *val_str(String *) { DBUG_ASSERT(fixed()); null_value=1; return 0; } double val_real() { DBUG_ASSERT(fixed()); null_value= 1; return 0.0; } longlong val_int() { DBUG_ASSERT(fixed()); null_value=1; return 0; } bool fix_length_and_dec(THD *thd) override { base_flags|= item_base_t::MAYBE_NULL; max_length=0; return FALSE; } }; #endif /* HAVE_DLOPEN */ void mysql_ull_cleanup(THD *thd); void mysql_ull_set_explicit_lock_duration(THD *thd); class Item_func_lock :public Item_long_func { public: Item_func_lock(THD *thd): Item_long_func(thd) { } Item_func_lock(THD *thd, Item *a): Item_long_func(thd, a) {} Item_func_lock(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {} table_map used_tables() const override { return used_tables_cache | RAND_TABLE_BIT; } bool const_item() const override { return 0; } bool is_expensive() override { return 1; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } }; class Item_func_get_lock final :public Item_func_lock { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()) || args[1]->check_type_can_return_real(func_name_cstring()); } String value; public: Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_func_lock(thd, a, b) {} longlong val_int() override final; LEX_CSTRING func_name_cstring() const override final { static LEX_CSTRING name= {STRING_WITH_LEN("get_lock") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 1; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override final { return get_item_copy<Item_func_get_lock>(thd, this); } }; class Item_func_release_all_locks final :public Item_func_lock { public: Item_func_release_all_locks(THD *thd): Item_func_lock(thd) { unsigned_flag= 1; } longlong val_int() override final; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("release_all_locks") }; return name; } protected: Item *shallow_copy(THD *thd) const override final { return get_item_copy<Item_func_release_all_locks>(thd, this); } }; class Item_func_release_lock final :public Item_func_lock { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()); } String value; public: Item_func_release_lock(THD *thd, Item *a): Item_func_lock(thd, a) {} longlong val_int() override final; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("release_lock") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length= 1; set_maybe_null(); return FALSE; } protected: Item *shallow_copy(THD *thd) const override final { return get_item_copy<Item_func_release_lock>(thd, this); } }; /* replication functions */ class Item_master_pos_wait :public Item_longlong_func { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()) || args[1]->check_type_can_return_int(func_name_cstring()) || (arg_count > 2 && args[2]->check_type_can_return_int(func_name_cstring())) || (arg_count > 3 && args[3]->check_type_general_purpose_string(func_name_cstring())); } String value; public: Item_master_pos_wait(THD *thd, Item *a, Item *b) :Item_longlong_func(thd, a, b) {} Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c): Item_longlong_func(thd, a, b, c) {} Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_longlong_func(thd, a, b, c, d) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("master_pos_wait") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=21; set_maybe_null(); return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_master_pos_wait>(thd, this); } }; class Item_master_gtid_wait :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()) || (arg_count > 1 && args[1]->check_type_can_return_real(func_name_cstring())); } String value; public: Item_master_gtid_wait(THD *thd, Item *a) :Item_long_func(thd, a) {} Item_master_gtid_wait(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("master_gtid_wait") }; return name; } bool fix_length_and_dec(THD *thd) override { max_length=2; return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_master_gtid_wait>(thd, this); } }; /* Handling of user definable variables */ class user_var_entry; /** A class to set and get user variables */ class Item_func_user_var :public Item_hybrid_func { protected: user_var_entry *m_var_entry; public: LEX_CSTRING name; // keep it public Item_func_user_var(THD *thd, const LEX_CSTRING *a) :Item_hybrid_func(thd), m_var_entry(NULL), name(*a) { } Item_func_user_var(THD *thd, const LEX_CSTRING *a, Item *b) :Item_hybrid_func(thd, b), m_var_entry(NULL), name(*a) { } Item_func_user_var(THD *thd, Item_func_user_var *item) :Item_hybrid_func(thd, item), m_var_entry(item->m_var_entry), name(item->name) { } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { DBUG_ASSERT(fixed()); return create_tmp_field_ex_from_handler(root, table, src, param, type_handler()); } Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return create_table_field_from_handler(root, table); } bool check_vcol_func_processor(void *arg) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; class Item_func_set_user_var :public Item_func_user_var { /* The entry_thread_id variable is used: 1) to skip unnecessary updates of the entry field (see above); 2) to reset the entry field that was initialized in the other thread (for example, an item tree of a trigger that updates user variables may be shared between several connections, and the entry_thread_id field prevents updates of one connection user variables from a concurrent connection calling the same trigger that initially updated some user variable it the first connection context). */ my_thread_id entry_thread_id; String value; my_decimal decimal_buff; bool null_item; union { longlong vint; double vreal; String *vstr; my_decimal *vdec; } save_result; public: Item_func_set_user_var(THD *thd, const LEX_CSTRING *a, Item *b): Item_func_user_var(thd, a, b), entry_thread_id(0) {} Item_func_set_user_var(THD *thd, Item_func_set_user_var *item) :Item_func_user_var(thd, item), entry_thread_id(item->entry_thread_id), value(item->value), decimal_buff(item->decimal_buff), null_item(item->null_item), save_result(item->save_result) {} enum Functype functype() const override { return SUSERVAR_FUNC; } double val_real() override; longlong val_int() override; String *val_str(String *str) override; my_decimal *val_decimal(my_decimal *) override; double val_result() override; longlong val_int_result() override; bool val_bool_result() override; String *str_result(String *str) override; my_decimal *val_decimal_result(my_decimal *) override; bool is_null_result() override; bool update_hash(void *ptr, size_t length, const Type_handler *th, CHARSET_INFO *cs); bool send(Protocol *protocol, st_value *buffer) override; void make_send_field(THD *thd, Send_field *tmp_field) override; bool check(bool use_result_field); void save_item_result(Item *item); bool update(); bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; void print(String *str, enum_query_type query_type) override; enum precedence precedence() const override { return ASSIGN_PRECEDENCE; } void print_as_stmt(String *str, enum_query_type query_type); LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("set_user_var") }; return name; } int save_in_field(Field *field, bool no_conversions, bool can_use_result_field); int save_in_field(Field *field, bool no_conversions) override { return save_in_field(field, no_conversions, 1); } void save_org_in_field(Field *field, fast_field_copier data __attribute__ ((__unused__))) override { (void) save_in_field(field, 1, 0); } bool register_field_in_read_map(void *arg) override; bool register_field_in_bitmap(void *arg) override; bool set_entry(THD *thd, bool create_if_not_exists); void cleanup() override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_set_user_var>(thd, this); } public: bool excl_dep_on_table(table_map tab_map) override { return false; } }; class Item_func_get_user_var :public Item_func_user_var, private Settable_routine_parameter { public: Item_func_get_user_var(THD *thd, const LEX_CSTRING *a): Item_func_user_var(thd, a) {} enum Functype functype() const override { return GUSERVAR_FUNC; } LEX_CSTRING get_name() { return name; } double val_real() override; longlong val_int() override; my_decimal *val_decimal(my_decimal*) override; String *val_str(String* str) override; bool fix_length_and_dec(THD *thd) override; void print(String *str, enum_query_type query_type) override; /* We must always return variables as strings to guard against selects of type select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b) */ LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("get_user_var") }; return name; } bool const_item() const override; table_map used_tables() const override { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, const Eq_config &config) const override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_get_user_var>(thd, this); } private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; public: Settable_routine_parameter *get_settable_routine_parameter() override { return this; } }; /* This item represents user variable used as out parameter (e.g in LOAD DATA), and it is supposed to be used only for this purprose. So it is simplified a lot. Actually you should never obtain its value. The only two reasons for this thing being an Item is possibility to store it in List<Item> and desire to place this code somewhere near other functions working with user variables. */ class Item_user_var_as_out_param :public Item_fixed_hybrid, public Load_data_outvar { LEX_CSTRING org_name; user_var_entry *entry; public: Item_user_var_as_out_param(THD *thd, const LEX_CSTRING *a) :Item_fixed_hybrid(thd) { DBUG_ASSERT(a->length < UINT_MAX32); org_name= *a; set_name(thd, a->str, a->length, system_charset_info); } Load_data_outvar *get_load_data_outvar() override { return this; } bool load_data_set_null(THD *thd, const Load_data_param *param) override { set_null_value(param->charset()); return false; } bool load_data_set_no_data(THD *thd, const Load_data_param *param) override { set_null_value(param->charset()); return false; } bool load_data_set_value(THD *thd, const char *pos, uint length, const Load_data_param *param) override { set_value(pos, length, param->charset()); return false; } void load_data_print_for_log_event(THD *thd, String *to) const override; bool load_data_add_outvar(THD *thd, Load_data_param *param) const override { return param->add_outvar_user_var(thd); } uint load_data_fixed_length() const override { return 0; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { DBUG_ASSERT(0); return NULL; } /* We should return something different from FIELD_ITEM here */ enum Type type() const override { return CONST_ITEM;} double val_real() override; longlong val_int() override; String *val_str(String *str) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; my_decimal *val_decimal(my_decimal *decimal_buffer) override; /* fix_fields() binds variable name with its entry structure */ bool fix_fields(THD *thd, Item **ref) override; void set_null_value(CHARSET_INFO* cs); void set_value(const char *str, uint length, CHARSET_INFO* cs); const Type_handler *type_handler() const override { return &type_handler_double; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_user_var_as_out_param>(thd, this); } Item *deep_copy(THD *thd) const override { return shallow_copy_with_checks(thd); } }; /* A system variable */ #define GET_SYS_VAR_CACHE_LONG 1 #define GET_SYS_VAR_CACHE_DOUBLE 2 #define GET_SYS_VAR_CACHE_STRING 4 class Item_func_get_system_var :public Item_func { sys_var *var; enum_var_type var_type, orig_var_type; LEX_CSTRING component; longlong cached_llval; double cached_dval; String cached_strval; bool cached_null_value; query_id_t used_query_id; uchar cache_present; public: Item_func_get_system_var(THD *thd, sys_var *var_arg, enum_var_type var_type_arg, LEX_CSTRING *component_arg, const char *name_arg, size_t name_len_arg); enum Functype functype() const override { return GSYSVAR_FUNC; } void update_null_value() override; bool fix_length_and_dec(THD *thd) override; void print(String *str, enum_query_type query_type) override; bool const_item() const override { return true; } table_map used_tables() const override { return 0; } const Type_handler *type_handler() const override; double val_real() override; longlong val_int() override; String* val_str(String*) override; my_decimal *val_decimal(my_decimal *dec_buf) override { return val_decimal_from_real(dec_buf); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } /* TODO: fix to support views */ LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("get_system_var") }; return name; } /** Indicates whether this system variable is written to the binlog or not. Variables are written to the binlog as part of "status_vars" in Query_log_event, as an Intvar_log_event, or a Rand_log_event. @return true if the variable is written to the binlog, false otherwise. */ bool is_written_to_binlog(); bool eq(const Item *item, const Eq_config &config) const override; void cleanup() override; bool check_vcol_func_processor(void *arg) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_get_system_var>(thd, this); } }; /* for fulltext search */ class Item_func_match :public Item_real_func { public: uint key, match_flags; bool join_key; DTCollation cmp_collation; FT_INFO *ft_handler; TABLE *table; Item_func_match *master; // for master-slave optimization Item *concat_ws; // Item_func_concat_ws String value; // value of concat_ws String search_value; // key_item()'s value converted to cmp_collation Item_func_match(THD *thd, List<Item> &a, uint b): Item_real_func(thd, a), key(0), match_flags(b), join_key(0), ft_handler(0), table(0), master(0), concat_ws(0) { } void cleanup() override { DBUG_ENTER("Item_func_match::cleanup"); Item_real_func::cleanup(); if (!master && ft_handler) ft_handler->please->close_search(ft_handler); ft_handler= 0; concat_ws= 0; table= 0; // required by Item_func_match::eq() DBUG_VOID_RETURN; } bool is_expensive_processor(void *arg) override { return TRUE; } enum Functype functype() const override { return FT_FUNC; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("match") }; return name; } bool eval_not_null_tables(void *opt_arg) override { not_null_tables_cache= 0; return 0; } bool find_not_null_fields(table_map allowed) override { return false; } bool fix_fields(THD *thd, Item **ref) override; bool eq(const Item *, const Eq_config &config) const override; /* The following should be safe, even if we compare doubles */ longlong val_int() override { DBUG_ASSERT(fixed()); return val_real() != 0.0; } double val_real() override; void print(String *str, enum_query_type query_type) override; bool fix_index(); bool init_search(THD *thd, bool no_order); bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function("match ... against()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_match>(thd, this); } Item *deep_copy(THD *thd) const override { return nullptr; } private: /** Check whether storage engine for given table, allows FTS Boolean search on non-indexed columns. @todo A flag should be added to the extended fulltext API so that it may be checked whether search on non-indexed columns are supported. Currently, it is not possible to check for such a flag since @c this->ft_handler is not yet set when this function is called. The current hack is to assume that search on non-indexed columns are supported for engines that does not support the extended fulltext API (e.g., MyISAM), while it is not supported for other engines (e.g., InnoDB) @param table_arg Table for which storage engine to check @retval true if BOOLEAN search on non-indexed columns is supported @retval false otherwise */ bool allows_search_on_non_indexed_columns(TABLE* table_arg) { // Only Boolean search may support non_indexed columns if (!(match_flags & FT_BOOL)) return false; DBUG_ASSERT(table_arg && table_arg->file); // Assume that if extended fulltext API is not supported, // non-indexed columns are allowed. This will be true for MyISAM. if ((table_arg->file->ha_table_flags() & HA_CAN_FULLTEXT_EXT) == 0) return true; return false; } }; class Item_func_bit_xor : public Item_func_bit_operator { public: Item_func_bit_xor(THD *thd, Item *a, Item *b) :Item_func_bit_operator(thd, a, b) {} bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("^") }; return name; } enum precedence precedence() const override { return BITXOR_PRECEDENCE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_bit_xor>(thd, this); } }; class Item_func_is_free_lock :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()); } String value; public: Item_func_is_free_lock(THD *thd, Item *a): Item_long_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("is_free_lock") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=1; set_maybe_null(); return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_is_free_lock>(thd, this); } }; class Item_func_is_used_lock :public Item_long_func { bool check_arguments() const override { return args[0]->check_type_general_purpose_string(func_name_cstring()); } String value; public: Item_func_is_used_lock(THD *thd, Item *a): Item_long_func(thd, a) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("is_used_lock") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals=0; max_length=10; set_maybe_null(); return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_is_used_lock>(thd, this); } }; struct Lex_cast_type_st: public Lex_length_and_dec_st { private: const Type_handler *m_type_handler; CHARSET_INFO *m_charset; public: void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec, CHARSET_INFO *cs= NULL) { m_type_handler= handler; m_charset= cs; Lex_length_and_dec_st::operator=(length_and_dec); } bool set(const Type_handler *handler, const Lex_length_and_dec_st & length_and_dec, Sql_used *used, const Charset_collation_map_st &map, const Lex_column_charset_collation_attrs_st &cscl, CHARSET_INFO *defcs) { CHARSET_INFO *tmp= cscl.resolved_to_character_set(used, map, defcs); if (!tmp) return true; set(handler, length_and_dec, tmp); return false; } void set(const Type_handler *handler) { m_type_handler= handler; m_charset= NULL; Lex_length_and_dec_st::reset(); } const Type_handler *type_handler() const { return m_type_handler; } CHARSET_INFO *charset() const { return m_charset; } Item *create_typecast_item(THD *thd, Item *item) const { return m_type_handler-> create_typecast_item(thd, item, Type_cast_attributes(*this, m_charset)); } Item *create_typecast_item_or_error(THD *thd, Item *item) const; }; class Item_func_row_count :public Item_longlong_func { public: Item_func_row_count(THD *thd): Item_longlong_func(thd) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("row_count") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals= 0; base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_row_count>(thd, this); } }; /* * * Stored FUNCTIONs * */ class Item_func_sp :public Item_func, public Item_sp { private: const Sp_handler *m_handler; bool execute(); protected: bool is_expensive_processor(void *arg) override { return is_expensive(); } bool check_arguments() const override { // sp_prepare_func_item() checks that the number of columns is correct return false; } public: Item_func_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, const Sp_handler *sph); Item_func_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, const Sp_handler *sph, List<Item> &list); virtual ~Item_func_sp() = default; void update_used_tables() override; void cleanup() override; LEX_CSTRING func_name_cstring() const override; const Type_handler *type_handler() const override; Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override { return result_type() != STRING_RESULT ? sp_result_field : create_table_field_from_handler(root, table); } void make_send_field(THD *thd, Send_field *tmp_field) override; longlong val_int() override { if (execute()) return (longlong) 0; return sp_result_field->val_int(); } double val_real() override { if (execute()) return 0.0; return sp_result_field->val_real(); } my_decimal *val_decimal(my_decimal *dec_buf) override { if (execute()) return NULL; return sp_result_field->val_decimal(dec_buf); } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { if (execute()) return true; return sp_result_field->get_date(ltime, fuzzydate); } String *val_str(String *str) override { String buf; char buff[20]; buf.set(buff, 20, str->charset()); buf.length(0); if (execute()) return NULL; /* result_field will set buf pointing to internal buffer of the resul_field. Due to this it will change any time when SP is executed. In order to prevent occasional corruption of returned value, we make here a copy. */ sp_result_field->val_str(&buf); str->copy(buf); return str; } bool val_native(THD *thd, Native *to) override { if (execute()) return true; return (null_value= sp_result_field->val_native(to)); } void update_null_value() override { execute(); } bool change_context_processor(void *cntx) override { context= (Name_resolution_context *)cntx; return FALSE; } enum Functype functype() const override { return FUNC_SP; } bool fix_fields(THD *thd, Item **ref) override; bool fix_length_and_dec(THD *thd) override; bool is_expensive() override; inline Field *get_sp_result_field() { return sp_result_field; } const sp_name *get_sp_name() const { return m_name; } bool check_vcol_func_processor(void *arg) override; bool limit_index_condition_pushdown_processor(void *opt_arg) override { return TRUE; } protected: Item *shallow_copy(THD *thd) const override { return 0; } public: bool eval_not_null_tables(void *opt_arg) override { not_null_tables_cache= 0; return 0; } bool excl_dep_on_grouping_fields(st_select_lex *sel) override { return false; } bool find_not_null_fields(table_map allowed) override { return false; } }; class Item_func_found_rows :public Item_longlong_func { public: Item_func_found_rows(THD *thd): Item_longlong_func(thd) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("found_rows") }; return name; } bool fix_length_and_dec(THD *thd) override { decimals= 0; base_flags&= ~item_base_t::MAYBE_NULL; return FALSE; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_found_rows>(thd, this); } }; class Item_func_oracle_sql_rowcount :public Item_longlong_func { public: Item_func_oracle_sql_rowcount(THD *thd): Item_longlong_func(thd) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("SQL%ROWCOUNT") }; return name; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_oracle_sql_rowcount>(thd, this); } }; class Item_func_sqlcode: public Item_long_func { public: Item_func_sqlcode(THD *thd): Item_long_func(thd) { } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("SQLCODE") }; return name; } void print(String *str, enum_query_type query_type) override { str->append(func_name_cstring()); } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); } bool fix_length_and_dec(THD *thd) override { base_flags&= ~item_base_t::MAYBE_NULL; null_value= false; max_length= 11; return FALSE; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_sqlcode>(thd, this); } }; void uuid_short_init(); ulonglong server_uuid_value(); class Item_func_uuid_short :public Item_longlong_func { public: Item_func_uuid_short(THD *thd): Item_longlong_func(thd) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("uuid_short") }; return name; } longlong val_int() override; bool const_item() const override { return false; } bool fix_length_and_dec(THD *thd) override { max_length= 21; unsigned_flag=1; return FALSE; } table_map used_tables() const override { return RAND_TABLE_BIT; } bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_uuid_short>(thd, this); } }; class Item_func_last_value :public Item_func { protected: Item *last_value; public: Item_func_last_value(THD *thd, List<Item> &list): Item_func(thd, list) {} double val_real() override; longlong val_int() override; String *val_str(String *) override; my_decimal *val_decimal(my_decimal *) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool val_native(THD *thd, Native *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("last_value") }; return name; } const Type_handler *type_handler() const override { return last_value->type_handler(); } bool eval_not_null_tables(void *) override { not_null_tables_cache= 0; return 0; } bool find_not_null_fields(table_map allowed) override { return false; } bool const_item() const override { return 0; } void evaluate_sideeffects(); void update_used_tables() override { Item_func::update_used_tables(); copy_flags(last_value, item_base_t::MAYBE_NULL); } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_last_value>(thd, this); } }; /* Implementation for sequences: NEXT VALUE FOR sequence and NEXTVAL() */ class Item_func_nextval :public Item_longlong_func { protected: TABLE_LIST *table_list; TABLE *table; bool print_table_list_identifier(THD *thd, String *to) const; bool check_access(THD *, privilege_t); public: Item_func_nextval(THD *thd, TABLE_LIST *table_list_arg): Item_longlong_func(thd), table_list(table_list_arg), table(0) {} longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("nextval") }; return name; } bool fix_fields(THD *thd, Item **ref) override { /* Don't check privileges, if it's parse_vcol_defs() */ return (table_list->table && check_sequence_privileges(thd)) || Item_longlong_func::fix_fields(thd, ref); } bool check_sequence_privileges(void *thd) override { return check_access((THD*)thd, INSERT_ACL | SELECT_ACL); } bool fix_length_and_dec(THD *thd) override { unsigned_flag= 0; max_length= MAX_BIGINT_WIDTH; set_maybe_null(); /* In case of errors */ return FALSE; } /* update_table() function must be called during the value function as in case of DEFAULT the sequence table may not yet be open while fix_fields() are called */ void update_table() { table= table_list->table; DBUG_ASSERT(table); } bool const_item() const override { return 0; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_nextval>(thd, this); } public: void print(String *str, enum_query_type query_type) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_NEXTVAL); } }; /* Implementation for sequences: LASTVAL(sequence), PostgreSQL style */ class Item_func_lastval :public Item_func_nextval { public: Item_func_lastval(THD *thd, TABLE_LIST *table_list_arg): Item_func_nextval(thd, table_list_arg) {} bool check_sequence_privileges(void *thd) override { return check_access((THD*)thd, SELECT_ACL); } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("lastval") }; return name; } protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_lastval>(thd, this); } }; /* Implementation for sequences: SETVAL(sequence), PostgreSQL style */ class Item_func_setval :public Item_func_nextval { longlong nextval; ulonglong round; bool is_used; public: Item_func_setval(THD *thd, TABLE_LIST *table_list_arg, longlong nextval_arg, ulonglong round_arg, bool is_used_arg) : Item_func_nextval(thd, table_list_arg), nextval(nextval_arg), round(round_arg), is_used(is_used_arg) {} bool check_sequence_privileges(void *thd) override { return check_access((THD*)thd, INSERT_ACL); } longlong val_int() override; LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("setval") }; return name; } void print(String *str, enum_query_type query_type) override; protected: Item *shallow_copy(THD *thd) const override { return get_item_copy<Item_func_setval>(thd, this); } }; class Interruptible_wait; Item *get_system_var(THD *thd, enum_var_type var_type, const LEX_CSTRING *name, const LEX_CSTRING *component); extern bool check_reserved_words(const LEX_CSTRING *name); double my_double_round(double value, longlong dec, bool dec_unsigned, bool truncate); extern bool volatile mqh_used; bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, const Type_handler *th, CHARSET_INFO *cs); #endif /* ITEM_FUNC_INCLUDED */ lf.h 0000644 00000014476 15156036172 0005340 0 ustar 00 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef INCLUDE_LF_INCLUDED #define INCLUDE_LF_INCLUDED #include <my_atomic.h> C_MODE_START /* wait-free dynamic array, see lf_dynarray.c 4 levels of 256 elements each mean 4311810304 elements in an array - it should be enough for a while */ #define LF_DYNARRAY_LEVEL_LENGTH 256 #define LF_DYNARRAY_LEVELS 4 typedef struct { void * volatile level[LF_DYNARRAY_LEVELS]; uint size_of_element; } LF_DYNARRAY; typedef int (*lf_dynarray_func)(void *, void *); void lf_dynarray_init(LF_DYNARRAY *array, uint element_size); void lf_dynarray_destroy(LF_DYNARRAY *array); void *lf_dynarray_value(LF_DYNARRAY *array, uint idx); void *lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx); int lf_dynarray_iterate(LF_DYNARRAY *array, lf_dynarray_func func, void *arg); /* pin manager for memory allocator, lf_alloc-pin.c */ #define LF_PINBOX_PINS 4 #define LF_PURGATORY_SIZE 100 typedef void lf_pinbox_free_func(void *, void *, void*); typedef struct { LF_DYNARRAY pinarray; lf_pinbox_free_func *free_func; void *free_func_arg; uint free_ptr_offset; uint32 volatile pinstack_top_ver; /* this is a versioned pointer */ uint32 volatile pins_in_array; /* number of elements in array */ } LF_PINBOX; typedef struct { void * volatile pin[LF_PINBOX_PINS]; LF_PINBOX *pinbox; void *purgatory; uint32 purgatory_count; uint32 volatile link; /* avoid false sharing */ char pad[CPU_LEVEL1_DCACHE_LINESIZE]; } LF_PINS; /* compile-time assert to make sure we have enough pins. */ #define lf_pin(PINS, PIN, ADDR) \ do { \ compile_time_assert(PIN < LF_PINBOX_PINS); \ my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR)); \ } while(0) #define lf_unpin(PINS, PIN) lf_pin(PINS, PIN, NULL) #define lf_assert_pin(PINS, PIN) assert((PINS)->pin[PIN] != 0) #define lf_assert_unpin(PINS, PIN) assert((PINS)->pin[PIN] == 0) void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset, lf_pinbox_free_func *free_func, void * free_func_arg); void lf_pinbox_destroy(LF_PINBOX *pinbox); LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox); void lf_pinbox_put_pins(LF_PINS *pins); void lf_pinbox_free(LF_PINS *pins, void *addr); /* memory allocator, lf_alloc-pin.c */ typedef struct st_lf_allocator { LF_PINBOX pinbox; uchar * volatile top; uint element_size; uint32 volatile mallocs; void (*constructor)(uchar *); /* called, when an object is malloc()'ed */ void (*destructor)(uchar *); /* called, when an object is free()'d */ } LF_ALLOCATOR; void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset); void lf_alloc_destroy(LF_ALLOCATOR *allocator); uint lf_alloc_pool_count(LF_ALLOCATOR *allocator); /* shortcut macros to access underlying pinbox functions from an LF_ALLOCATOR see lf_pinbox_get_pins() and lf_pinbox_put_pins() */ #define lf_alloc_free(PINS, PTR) lf_pinbox_free((PINS), (PTR)) #define lf_alloc_get_pins(A) lf_pinbox_get_pins(&(A)->pinbox) #define lf_alloc_put_pins(PINS) lf_pinbox_put_pins(PINS) #define lf_alloc_direct_free(ALLOC, ADDR) \ do { \ if ((ALLOC)->destructor) \ (ALLOC)->destructor((uchar*) ADDR); \ my_free(ADDR); \ } while(0) void *lf_alloc_new(LF_PINS *pins); C_MODE_END /* extendible hash, lf_hash.cc */ #include <hash.h> C_MODE_START typedef struct st_lf_hash LF_HASH; typedef void (*lf_hash_initializer)(LF_HASH *hash, void *dst, const void *src); #define LF_HASH_UNIQUE 1 /* lf_hash overhead per element (that is, sizeof(LF_SLIST) */ extern const int LF_HASH_OVERHEAD; struct st_lf_hash { LF_DYNARRAY array; /* hash itself */ LF_ALLOCATOR alloc; /* allocator for elements */ my_hash_get_key get_key; /* see HASH */ lf_hash_initializer initializer; /* called when an element is inserted */ my_hash_function hash_function; /* see HASH */ CHARSET_INFO *charset; /* see HASH */ uint key_offset, key_length; /* see HASH */ uint element_size; /* size of memcpy'ed area on insert */ uint flags; /* LF_HASH_UNIQUE, etc */ int32 volatile size; /* size of array */ int32 volatile count; /* number of elements in the hash */ }; void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, uint key_offset, uint key_length, my_hash_get_key get_key, CHARSET_INFO *charset); void lf_hash_destroy(LF_HASH *hash); int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data); void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins, my_hash_value_type hash_value, const void *key, uint keylen); int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins, my_hash_walk_action action, void *argument); #define lf_hash_size(hash) \ my_atomic_load32_explicit(&(hash)->count, MY_MEMORY_ORDER_RELAXED) /* shortcut macros to access underlying pinbox functions from an LF_HASH see lf_pinbox_get_pins() and lf_pinbox_put_pins() */ #define lf_hash_get_pins(HASH) lf_alloc_get_pins(&(HASH)->alloc) #define lf_hash_put_pins(PINS) lf_pinbox_put_pins(PINS) #define lf_hash_search_unpin(PINS) lf_unpin((PINS), 2) /* cleanup */ C_MODE_END #endif wsrep_thd.h 0000644 00000026337 15156036173 0006736 0 ustar 00 /* Copyright (C) 2013-2025 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #ifndef WSREP_THD_H #define WSREP_THD_H #include <my_config.h> #include "mysql/service_wsrep.h" #include "wsrep/client_state.hpp" #include "sql_class.h" #include "wsrep_utils.h" #include <deque> class Wsrep_thd_queue { public: Wsrep_thd_queue(THD* t) : thd(t) { mysql_mutex_init(key_LOCK_wsrep_thd_queue, &LOCK_wsrep_thd_queue, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_thd_queue, NULL); } ~Wsrep_thd_queue() { mysql_mutex_destroy(&LOCK_wsrep_thd_queue); mysql_cond_destroy(&COND_wsrep_thd_queue); } bool push_back(THD* thd) { DBUG_ASSERT(thd); wsp::auto_lock lock(&LOCK_wsrep_thd_queue); std::deque<THD*>::iterator it = queue.begin(); while (it != queue.end()) { if (*it == thd) { return true; } it++; } queue.push_back(thd); mysql_cond_signal(&COND_wsrep_thd_queue); return false; } THD* pop_front() { wsp::auto_lock lock(&LOCK_wsrep_thd_queue); while (queue.empty()) { if (thd->killed != NOT_KILLED) return NULL; thd->mysys_var->current_mutex= &LOCK_wsrep_thd_queue; thd->mysys_var->current_cond= &COND_wsrep_thd_queue; mysql_cond_wait(&COND_wsrep_thd_queue, &LOCK_wsrep_thd_queue); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; } THD* ret= queue.front(); queue.pop_front(); return ret; } private: THD* thd; std::deque<THD*> queue; mysql_mutex_t LOCK_wsrep_thd_queue; mysql_cond_t COND_wsrep_thd_queue; }; int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, void *, system_status_var *, enum enum_var_type scope); bool wsrep_create_appliers(long threads, bool mutex_protected=false); void wsrep_create_rollbacker(); bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd); /* Abort transaction for victim_thd. This function is called from MDL BF abort codepath. */ void wsrep_abort_thd(THD *bf_thd, THD *victim_thd, my_bool signal) __attribute__((nonnull(1,2))); /** Kill wsrep connection with kill_signal. Object thd is not guaranteed to exist anymore when this function returns. Asserts that the caller holds victim_thd->LOCK_thd_kill, victim_thd->LOCK_thd_data. @param thd THD object for connection that executes the KILL. @param victim_thd THD object for connection to be killed. @param kill_signal Kill signal. @return Zero if the kill was successful, otherwise non-zero error code. */ uint wsrep_kill_thd(THD *thd, THD *victim_thd, killed_state kill_signal); /* Backup kill status for commit. */ void wsrep_backup_kill_for_commit(THD *); /* Restore KILL status after commit. */ void wsrep_restore_kill_after_commit(THD *); /* Helper methods to deal with thread local storage. The purpose of these methods is to hide the details of thread local storage handling when operating with wsrep storage access and streaming applier THDs With one-thread-per-connection thread handling thread specific variables are allocated when the thread is started and deallocated before thread exits (my_thread_init(), my_thread_end()). However, with pool-of-threads thread handling new thread specific variables are allocated for each THD separately (see threadpool_add_connection()), and the variables in thread local storage are assigned from currently active thread (see thread_attach()). This must be taken into account when storing/resetting thread local storage and when creating streaming applier THDs. */ /** Create new variables for thread local storage. With one-thread-per-connection thread handling this is a no op, with pool-of-threads new variables are created via my_thread_init(). It is assumed that the caller has called wsrep_reset_threadvars() to clear the thread local storage before this call. @return Zero in case of success, non-zero otherwise. */ int wsrep_create_threadvars(); /** Delete variables which were created by wsrep_create_threadvars(). The caller must store variables into thread local storage before this call via wsrep_store_threadvars(). */ void wsrep_delete_threadvars(); /** Assign variables from current thread local storage into THD. This should be called for THDs whose lifetime is limited to single thread execution or which may share the operation context with some parent THD (e.g. storage access) and thus don't require separately allocated globals. With one-thread-per-connection thread handling this is a no-op, with pool-of-threads the variables which are currently stored into thread local storage are assigned to THD. */ void wsrep_assign_from_threadvars(THD *); /** Helper struct to save variables from thread local storage. */ struct Wsrep_threadvars { THD* cur_thd; st_my_thread_var* mysys_var; }; /** Save variables from thread local storage into Wsrep_threadvars struct. */ Wsrep_threadvars wsrep_save_threadvars(); /** Restore variables into thread local storage from Wsrep_threadvars struct. */ void wsrep_restore_threadvars(const Wsrep_threadvars&); /** Store variables into thread local storage. */ void wsrep_store_threadvars(THD *); /** Reset thread local storage. */ void wsrep_reset_threadvars(THD *); static inline enum wsrep::client_error wsrep_current_error(const THD* thd) { return thd->wsrep_cs().current_error(); } static inline enum wsrep::provider::status wsrep_current_error_status(const THD* thd) { return thd->wsrep_cs().current_error_status(); } /** Helper functions to override error status In many contexts it is desirable to mask the original error status set for THD or it is necessary to change OK status to error. This function implements the common logic for the most of the cases. Rules: * If the diagnostics are has OK or EOF status, override it unconditionally * If the error is either ER_ERROR_DURING_COMMIT or ER_LOCK_DEADLOCK it is usually the correct error status to be returned to client, so don't override those by default */ static inline void wsrep_override_error(THD *thd, uint error, const char *format= 0, ...) { Diagnostics_area *da= thd->get_stmt_da(); if (da->is_ok() || da->is_eof() || !da->is_set() || (da->is_error() && da->sql_errno() != error && da->sql_errno() != ER_ERROR_DURING_COMMIT && da->sql_errno() != ER_LOCK_DEADLOCK)) { da->reset_diagnostics_area(); va_list args; va_start(args, format); if (!format) format= ER_THD(thd, error); my_printv_error(error, format, MYF(0), args); va_end(args); } } static inline void wsrep_override_error(THD* thd, wsrep::client_error ce, enum wsrep::provider::status status) { DBUG_ASSERT(ce != wsrep::e_success); switch (ce) { case wsrep::e_error_during_commit: if (status == wsrep::provider::error_size_exceeded) wsrep_override_error(thd, ER_UNKNOWN_ERROR, "Maximum writeset size exceeded"); else /* TODO: Figure out better error number */ if (status) wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, "Error while appending streaming replication fragment" "(provider status: %s)", wsrep::provider::to_string(status).c_str()); else wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, "Error while appending streaming replication fragment"); break; case wsrep::e_deadlock_error: switch (thd->lex->sql_command) { case SQLCOM_XA_END: case SQLCOM_XA_PREPARE: wsrep_override_error(thd, ER_XA_RBDEADLOCK); break; default: wsrep_override_error(thd, ER_LOCK_DEADLOCK); break; } break; case wsrep::e_interrupted_error: wsrep_report_query_interrupted(thd, __FILE__, __LINE__); wsrep_override_error(thd, ER_QUERY_INTERRUPTED); break; case wsrep::e_size_exceeded_error: wsrep_override_error(thd, ER_UNKNOWN_ERROR, "Maximum writeset size exceeded"); break; case wsrep::e_append_fragment_error: /* TODO: Figure out better error number */ if (status) wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, "Error while appending streaming replication fragment" "(provider status: %s)", wsrep::provider::to_string(status).c_str()); else wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, "Error while appending streaming replication fragment"); break; case wsrep::e_not_supported_error: wsrep_override_error(thd, ER_NOT_SUPPORTED_YET); break; case wsrep::e_timeout_error: wsrep_override_error(thd, ER_LOCK_WAIT_TIMEOUT); break; default: wsrep_override_error(thd, ER_UNKNOWN_ERROR); } } /** Helper function to log THD wsrep context. @param thd Pointer to THD @param message Optional message @param function Function where the call was made from */ static inline void wsrep_log_thd(const THD *thd, const char *message, const char *function) { WSREP_DEBUG("%s %s\n" " thd: %llu thd_ptr: %p client_mode: %s client_state: %s trx_state: %s\n" " next_trx_id: %lld trx_id: %lld seqno: %lld\n" " is_streaming: %d fragments: %zu\n" " sql_errno: %u message: %s\n" #define WSREP_THD_LOG_QUERIES #ifdef WSREP_THD_LOG_QUERIES " command: %d query: %.72s" #endif /* WSREP_OBSERVER_LOG_QUERIES */ , function, message ? message : "", thd->thread_id, thd, wsrep_thd_client_mode_str(thd), wsrep_thd_client_state_str(thd), wsrep_thd_transaction_state_str(thd), (long long)thd->wsrep_next_trx_id(), (long long)thd->wsrep_trx_id(), (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_trx().is_streaming(), thd->wsrep_sr().fragments().size(), (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0), (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->message() : "") #ifdef WSREP_THD_LOG_QUERIES , thd->lex->sql_command, wsrep_thd_query(thd) #endif /* WSREP_OBSERVER_LOG_QUERIES */ ); } #define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__) #endif /* WSREP_THD_H */ sql_const.h 0000644 00000024106 15156036173 0006734 0 ustar 00 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file File containing constants that can be used throughout the server. @note This file shall not contain or include any declarations of any kinds. */ #ifndef SQL_CONST_INCLUDED #define SQL_CONST_INCLUDED #include <mysql_version.h> #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ /* extra 4+4 bytes for slave tmp tables */ #define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4) #define MAX_ALIAS_NAME 256 #define MAX_FIELD_NAME (NAME_LEN+1) /* Max colum name length +1 */ #define MAX_SYS_VAR_LENGTH 32 #define MAX_KEY MAX_INDEXES /* Max used keys */ #define MAX_REF_PARTS 32 /* Max parts used as ref */ /* Maximum length of the data part of an index lookup key. The "data part" is defined as the value itself, not including the NULL-indicator bytes or varchar length bytes ("the Extras"). We need this value because there was a bug where length of the Extras were not counted. You probably need MAX_KEY_LENGTH, not this constant. */ #define MAX_DATA_LENGTH_FOR_KEY 3072 #if SIZEOF_OFF_T > 4 #define MAX_REFLENGTH 8 /* Max length for record ref */ #else #define MAX_REFLENGTH 4 /* Max length for record ref */ #endif #define MAX_HOSTNAME (HOSTNAME_LENGTH + 1) /* len+1 in mysql.user */ #define MAX_CONNECTION_NAME NAME_LEN #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FILENAME_MBWIDTH 5 #define MAX_FIELD_CHARLENGTH 255 /* In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead: - 2 bytes for the length - 1 byte for NULL bits to avoid the "Row size too large" error for these three corner definitions: CREATE TABLE t1 (c VARBINARY(65533)); CREATE TABLE t1 (c VARBINARY(65534)); CREATE TABLE t1 (c VARBINARY(65535)); Like VARCHAR(65536), they will be converted to BLOB automatically in non-strict mode. */ #define MAX_FIELD_VARCHARLENGTH (65535-2-1) #define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */ /* Max column width +1 */ #define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1) #define MAX_BIT_FIELD_LENGTH 64 /* Max length in bits for bit fields */ #define MAX_DATE_WIDTH 10 /* YYYY-MM-DD */ #define MIN_TIME_WIDTH 10 /* -HHH:MM:SS */ #define MAX_TIME_WIDTH 16 /* -DDDDDD HH:MM:SS */ #define MAX_TIME_FULL_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ #define MAX_DATETIME_FULL_WIDTH 26 /* YYYY-MM-DD HH:MM:SS.###### */ #define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */ #define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */ #define MAX_DATETIME_PRECISION 6 #define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */ #define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3)) #define OUTER_REF_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-2)) #define RAND_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-1)) #define PSEUDO_TABLE_BITS (PARAM_TABLE_BIT | OUTER_REF_TABLE_BIT | \ RAND_TABLE_BIT) #define CONNECT_STRING_MAXLEN 65535 /* stored in 2 bytes in .frm */ #define MAX_FIELDS 4096 /* Limit in the .frm file */ #define MAX_PARTITIONS 8192 #define MAX_SELECT_NESTING (SELECT_NESTING_MAP_SIZE - 1) #define MAX_SORT_MEMORY 2048*1024 #define MIN_SORT_MEMORY 1024 /* Some portable defines */ #define STRING_BUFFER_USUAL_SIZE 80 /* Memory allocated when parsing a statement / saving a statement */ #define MEM_ROOT_BLOCK_SIZE 8192 #define MEM_ROOT_PREALLOC 8192 #define TRANS_MEM_ROOT_BLOCK_SIZE 4096 #define TRANS_MEM_ROOT_PREALLOC 4096 #define DEFAULT_ERROR_COUNT 64 #define EXTRA_RECORDS 10 /* Extra records in sort */ #define SCROLL_EXTRA 5 /* Extra scroll-rows. */ #define FIELD_NAME_USED ((uint) 32768) /* Bit set if fieldname used */ #define FORM_NAME_USED ((uint) 16384) /* Bit set if formname used */ #define FIELD_NR_MASK 16383 /* To get fieldnumber */ #define FERR -1 /* Error from my_functions */ #define CREATE_MODE 0 /* Default mode on new files */ #define NAMES_SEP_CHAR 255 /* Char to sep. names */ /* This is used when reading large blocks, sequential read. We assume that reading this much will be roughly the same cost as 1 seek / fetching one row from the storage engine. Cost of one read of DISK_CHUNK_SIZE is DISK_SEEK_BASE_COST (ms). */ #define DISK_CHUNK_SIZE (uint) (65536) /* Size of diskbuffer for tmpfiles */ #define FRM_VER_TRUE_VARCHAR (FRM_VER+4) /* 10 */ #define FRM_VER_EXPRESSSIONS (FRM_VER+5) /* 11 */ #define FRM_VER_CURRENT FRM_VER_EXPRESSSIONS /*************************************************************************** Configuration parameters ****************************************************************************/ #define ACL_CACHE_SIZE 256 #define MAX_PASSWORD_LENGTH 32 #define HOST_CACHE_SIZE 128 #define MAX_ACCEPT_RETRY 10 // Test accept this many times #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 #define SEQUENCES_HASH_SIZE 16 #define TABLE_OPEN_CACHE_MIN 200 #define TABLE_OPEN_CACHE_DEFAULT 2000 #define TABLE_DEF_CACHE_DEFAULT 400 /** We must have room for at least 400 table definitions in the table cache, since otherwise there is no chance prepared statements that use these many tables can work. Prepared statements use table definition cache ids (table_map_id) as table version identifiers. If the table definition cache size is less than the number of tables used in a statement, the contents of the table definition cache is guaranteed to rotate between a prepare and execute. This leads to stable validation errors. In future we shall use more stable version identifiers, for now the only solution is to ensure that the table definition cache can contain at least all tables of a given statement. */ #define TABLE_DEF_CACHE_MIN 400 /** Maximum number of connections default value. 151 is larger than Apache's default max children, to avoid "too many connections" error in a common setup. */ #define MAX_CONNECTIONS_DEFAULT 151 /* Stack reservation. Feel free to raise this by the smallest amount you can to get the "execution_constants" test to pass. */ #ifndef __has_feature #define __has_feature(x) 0 #endif #if defined(__clang__) && __has_feature(memory_sanitizer) && !defined(DBUG_OFF) #define STACK_MIN_SIZE 44000 #else #define STACK_MIN_SIZE 16000 // Abort if less stack during eval. #endif #define STACK_MIN_SIZE_FOR_OPEN (1024*80) #define STACK_BUFF_ALLOC 352 ///< For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 ///< Abort read after this many int. #endif /* Allocations with MEM_ROOT. We should try to keep these as powers of 2 and not higher than 32768 to get full benefit of allocators like tcmalloc that will for these use a local heap without locks. */ #define QUERY_ALLOC_BLOCK_SIZE 32768 #define QUERY_ALLOC_PREALLOC_SIZE 32768 /* 65536 could be better */ #define TRANS_ALLOC_BLOCK_SIZE 8192 #define TRANS_ALLOC_PREALLOC_SIZE 4096 #define RANGE_ALLOC_BLOCK_SIZE 4096 #define ACL_ALLOC_BLOCK_SIZE 1024 #define UDF_ALLOC_BLOCK_SIZE 1024 #define TABLE_PREALLOC_BLOCK_SIZE 8192 #define TABLE_ALLOC_BLOCK_SIZE 4096 #define WARN_ALLOC_BLOCK_SIZE 2048 #define WARN_ALLOC_PREALLOC_SIZE 1024 #define TMP_TABLE_BLOCK_SIZE 16384 #define TMP_TABLE_PREALLOC_SIZE 32768 #define SHOW_ALLOC_BLOCK_SIZE 32768 /* The following parameters is to decide when to use an extra cache to optimise seeks when reading a big table in sorted order */ #define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (10L*1024*1024) #define MIN_ROWS_TO_USE_TABLE_CACHE 100 #define MIN_ROWS_TO_USE_BULK_INSERT 100 /* The lower bound of accepted rows when using filter. This is used to ensure that filters are not too agressive. */ #define MIN_ROWS_AFTER_FILTERING 1.0 /** Number of rows in a reference table when refered through a not unique key. This value is only used when we don't know anything about the key distribution. */ #define MATCHING_ROWS_IN_OTHER_TABLE 10 #define MY_CHARSET_BIN_MB_MAXLEN 1 /** Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used). */ #define KEY_DEFAULT_PACK_LENGTH 8 /** Characters shown for the command in 'show processlist'. */ #define PROCESS_LIST_WIDTH 100 /* Characters shown for the command in 'information_schema.processlist' */ #define PROCESS_LIST_INFO_WIDTH 65535 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 /* -[digits].E+## */ #define MAX_FLOAT_STR_LENGTH (FLT_DIG + 6) /* -[digits].E+### */ #define MAX_DOUBLE_STR_LENGTH (DBL_DIG + 7) /* Default time to wait before aborting a new client connection that does not respond to "initial server greeting" timely */ #define CONNECT_TIMEOUT 10 /* Wait 5 minutes before removing thread from thread cache */ #define THREAD_CACHE_TIMEOUT 5*60 /* The following can also be changed from the command line */ #define DEFAULT_CONCURRENCY 10 #define DELAYED_LIMIT 100 /**< pause after xxx inserts */ #define DELAYED_QUEUE_SIZE 1000 #define DELAYED_WAIT_TIMEOUT (5*60) /**< Wait for delayed insert */ #define MAX_CONNECT_ERRORS 100 ///< errors before disabling host #define LONG_TIMEOUT ((ulong) 3600L*24L*365L) /** Maximum length of time zone name that we support (Time zone name is char(64) in db). mysqlbinlog needs it. */ #define MAX_TIME_ZONE_NAME_LENGTH (NAME_LEN + 1) #define SP_PSI_STATEMENT_INFO_COUNT 19 #endif /* SQL_CONST_INCLUDED */ uniques.h 0000644 00000010201 15156036173 0006407 0 ustar 00 /* Copyright (c) 2016 MariaDB corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef UNIQUE_INCLUDED #define UNIQUE_INCLUDED #include "filesort.h" /* Unique -- class for unique (removing of duplicates). Puts all values to the TREE. If the tree becomes too big, it's dumped to the file. User can request sorted values, or just iterate through them. In the last case tree merging is performed in memory simultaneously with iteration, so it should be ~2-3x faster. */ class Unique :public Sql_alloc { DYNAMIC_ARRAY file_ptrs; ulong max_elements; /* Total number of elements that will be stored in-memory */ size_t max_in_memory_size; IO_CACHE file; TREE tree; /* Number of elements filtered out due to min_dupl_count when storing results to table. See Unique::get */ ulong filtered_out_elems; uint size; uint full_size; /* Size of element + space needed to store the number of duplicates found for the element. */ uint min_dupl_count; /* Minimum number of occurences of element required for it to be written to record_pointers. always 0 for unions, > 0 for intersections */ bool with_counters; bool merge(TABLE *table, uchar *buff, size_t size, bool without_last_merge); bool flush(); public: ulong elements; SORT_INFO sort; Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, uint size_arg, size_t max_in_memory_size_arg, uint min_dupl_count_arg= 0); ~Unique(); ulong elements_in_tree() { return tree.elements_in_tree; } inline bool unique_add(void *ptr) { DBUG_ENTER("unique_add"); DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements)); if (!(tree.flag & TREE_ONLY_DUPS) && tree.elements_in_tree >= max_elements && flush()) DBUG_RETURN(1); DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg)); } bool is_in_memory() { return (my_b_tell(&file) == 0); } void close_for_expansion() { tree.flag= TREE_ONLY_DUPS; } bool get(TABLE *table); /* Cost of searching for an element in the tree */ inline static double get_search_cost(ulonglong tree_elems, double compare_factor) { return log((double) tree_elems) * compare_factor / M_LN2; } static double get_use_cost(THD *thd, uint *buffer, size_t nkeys, uint key_size, size_t max_in_memory_size, double compare_factor, bool intersect_fl, bool *in_memory); inline static int get_cost_calc_buff_size(size_t nkeys, uint key_size, size_t max_in_memory_size) { size_t max_elems_in_tree= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); if (max_elems_in_tree == 0) max_elems_in_tree= 1; return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); } void reset(); bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg); uint get_size() const { return size; } size_t get_max_in_memory_size() const { return max_in_memory_size; } friend int unique_write_to_file(void* key, element_count count, void *unique); friend int unique_write_to_ptrs(void* key, element_count count, void *unique); friend int unique_write_to_file_with_count(void *key, element_count count, void *unique); friend int unique_intersect_write_to_ptrs(void *key, element_count count, void *unique); }; #endif /* UNIQUE_INCLUDED */ replication.h 0000644 00000036315 15156036173 0007245 0 ustar 00 /* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef REPLICATION_H #define REPLICATION_H /*************************************************************************** NOTE: plugin locking. The plugin is locked on Binlog_transmit_observer::transmit_start and is unlocked after Binlog_transmit_observer::transmit_stop. All other master observable events happen between these two and don't lock the plugin at all. Also a plugin is locked on Binlog_relay_IO_observer::thread_start and unlocked after Binlog_relay_IO_observer::thread_stop. ***************************************************************************/ #include <mysql.h> typedef struct st_mysql MYSQL; #ifdef __cplusplus extern "C" { #endif /** Transaction observer flags. */ enum Trans_flags { /** Transaction is a real transaction */ TRANS_IS_REAL_TRANS = 1 }; /** Transaction observer parameter */ typedef struct Trans_param { uint32 server_id; uint32 flags; /* The latest binary log file name and position written by current transaction, if binary log is disabled or no log event has been written into binary log file by current transaction (events written into transaction log cache are not counted), these two member will be zero. */ const char *log_file; my_off_t log_pos; } Trans_param; /** Observes and extends transaction execution */ typedef struct Trans_observer { uint32 len; /** This callback is called after transaction commit This callback is called right after commit to storage engines for transactional tables. For non-transactional tables, this is called at the end of the statement, before sending statement status, if the statement succeeded. @note The return value is currently ignored by the server. @note This hook is called wo/ any global mutex held @param param The parameter for transaction observers @retval 0 Success @retval 1 Failure */ int (*after_commit)(Trans_param *param); /** This callback is called after transaction rollback This callback is called right after rollback to storage engines for transactional tables. For non-transactional tables, this is called at the end of the statement, before sending statement status, if the statement failed. @note The return value is currently ignored by the server. @param param The parameter for transaction observers @note This hook is called wo/ any global mutex held @retval 0 Success @retval 1 Failure */ int (*after_rollback)(Trans_param *param); } Trans_observer; /** Binlog storage flags */ enum Binlog_storage_flags { /** Binary log was sync:ed */ BINLOG_STORAGE_IS_SYNCED = 1, /** First(or alone) in a group commit */ BINLOG_GROUP_COMMIT_LEADER = 2, /** Last(or alone) in a group commit */ BINLOG_GROUP_COMMIT_TRAILER = 4 }; /** Binlog storage observer parameters */ typedef struct Binlog_storage_param { uint32 server_id; } Binlog_storage_param; /** Observe binlog logging storage */ typedef struct Binlog_storage_observer { uint32 len; /** This callback is called after binlog has been flushed This callback is called after cached events have been flushed to binary log file. Whether the binary log file is synchronized to disk is indicated by the bit BINLOG_STORAGE_IS_SYNCED in @a flags. @note: this hook is called with LOCK_log mutex held @param param Observer common parameter @param log_file Binlog file name been updated @param log_pos Binlog position after update @param flags flags for binlog storage @retval 0 Success @retval 1 Failure */ int (*after_flush)(Binlog_storage_param *param, const char *log_file, my_off_t log_pos, uint32 flags); /** This callback is called after binlog has been synced This callback is called after events flushed to disk has been sync:ed ("group committed"). @note: this hook is called with LOCK_after_binlog_sync mutex held @param param Observer common parameter @param log_file Binlog file name been updated @param log_pos Binlog position after update @param flags flags for binlog storage @retval 0 Success @retval 1 Failure */ int (*after_sync)(Binlog_storage_param *param, const char *log_file, my_off_t log_pos, uint32 flags); } Binlog_storage_observer; /** Replication binlog transmitter (binlog dump) observer parameter. */ typedef struct Binlog_transmit_param { uint32 server_id; uint32 flags; } Binlog_transmit_param; /** Observe and extends the binlog dumping thread. */ typedef struct Binlog_transmit_observer { uint32 len; /** This callback is called when binlog dumping starts @param param Observer common parameter @param log_file Binlog file name to transmit from @param log_pos Binlog position to transmit from @retval 0 Success @retval 1 Failure */ int (*transmit_start)(Binlog_transmit_param *param, const char *log_file, my_off_t log_pos); /** This callback is called when binlog dumping stops @param param Observer common parameter @retval 0 Success @retval 1 Failure */ int (*transmit_stop)(Binlog_transmit_param *param); /** This callback is called to reserve bytes in packet header for event transmission This callback is called when resetting transmit packet header to reserve bytes for this observer in packet header. The @a header buffer is allocated by the server code, and @a size is the size of the header buffer. Each observer can only reserve a maximum size of @a size in the header. @param param Observer common parameter @param header Pointer of the header buffer @param size Size of the header buffer @param len Header length reserved by this observer @retval 0 Success @retval 1 Failure */ int (*reserve_header)(Binlog_transmit_param *param, unsigned char *header, unsigned long size, unsigned long *len); /** This callback is called before sending an event packet to slave @param param Observer common parameter @param packet Binlog event packet to send @param len Length of the event packet @param log_file Binlog file name of the event packet to send @param log_pos Binlog position of the event packet to send @retval 0 Success @retval 1 Failure */ int (*before_send_event)(Binlog_transmit_param *param, unsigned char *packet, unsigned long len, const char *log_file, my_off_t log_pos ); /** This callback is called after sending an event packet to slave @param param Observer common parameter @param event_buf Binlog event packet buffer sent @param len length of the event packet buffer @retval 0 Success @retval 1 Failure */ int (*after_send_event)(Binlog_transmit_param *param, const char *event_buf, unsigned long len); /** This callback is called after resetting master status This is called when executing the command RESET MASTER, and is used to reset status variables added by observers. @param param Observer common parameter @retval 0 Success @retval 1 Failure */ int (*after_reset_master)(Binlog_transmit_param *param); } Binlog_transmit_observer; /** Binlog relay IO flags */ enum Binlog_relay_IO_flags { /** Binary relay log was sync:ed */ BINLOG_RELAY_IS_SYNCED = 1 }; /** Replication binlog relay IO observer parameter */ typedef struct Binlog_relay_IO_param { uint32 server_id; /* Master host, user and port */ char *host; char *user; unsigned int port; char *master_log_name; my_off_t master_log_pos; MYSQL *mysql; /* the connection to master */ } Binlog_relay_IO_param; /** Observes and extends the service of slave IO thread. */ typedef struct Binlog_relay_IO_observer { uint32 len; /** This callback is called when slave IO thread starts @param param Observer common parameter @retval 0 Success @retval 1 Failure */ int (*thread_start)(Binlog_relay_IO_param *param); /** This callback is called when slave IO thread stops @param param Observer common parameter @retval 0 Success @retval 1 Failure */ int (*thread_stop)(Binlog_relay_IO_param *param); /** This callback is called before slave requesting binlog transmission from master This is called before slave issuing BINLOG_DUMP command to master to request binlog. @param param Observer common parameter @param flags binlog dump flags @retval 0 Success @retval 1 Failure */ int (*before_request_transmit)(Binlog_relay_IO_param *param, uint32 flags); /** This callback is called after read an event packet from master @param param Observer common parameter @param packet The event packet read from master @param len Length of the event packet read from master @param event_buf The event packet return after process @param event_len The length of event packet return after process @retval 0 Success @retval 1 Failure */ int (*after_read_event)(Binlog_relay_IO_param *param, const char *packet, unsigned long len, const char **event_buf, unsigned long *event_len); /** This callback is called after written an event packet to relay log @param param Observer common parameter @param event_buf Event packet written to relay log @param event_len Length of the event packet written to relay log @param flags flags for relay log @retval 0 Success @retval 1 Failure */ int (*after_queue_event)(Binlog_relay_IO_param *param, const char *event_buf, unsigned long event_len, uint32 flags); /** This callback is called after reset slave relay log IO status @param param Observer common parameter @retval 0 Success @retval 1 Failure */ int (*after_reset_slave)(Binlog_relay_IO_param *param); } Binlog_relay_IO_observer; /** Register a transaction observer @param observer The transaction observer to register @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer already exists */ int register_trans_observer(Trans_observer *observer, void *p); /** Unregister a transaction observer @param observer The transaction observer to unregister @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer not exists */ int unregister_trans_observer(Trans_observer *observer, void *p); /** Register a binlog storage observer @param observer The binlog storage observer to register @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer already exists */ int register_binlog_storage_observer(Binlog_storage_observer *observer, void *p); /** Unregister a binlog storage observer @param observer The binlog storage observer to unregister @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer not exists */ int unregister_binlog_storage_observer(Binlog_storage_observer *observer, void *p); /** Register a binlog transmit observer @param observer The binlog transmit observer to register @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer already exists */ int register_binlog_transmit_observer(Binlog_transmit_observer *observer, void *p); /** Unregister a binlog transmit observer @param observer The binlog transmit observer to unregister @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer not exists */ int unregister_binlog_transmit_observer(Binlog_transmit_observer *observer, void *p); /** Register a binlog relay IO (slave IO thread) observer @param observer The binlog relay IO observer to register @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer already exists */ int register_binlog_relay_io_observer(Binlog_relay_IO_observer *observer, void *p); /** Unregister a binlog relay IO (slave IO thread) observer @param observer The binlog relay IO observer to unregister @param p pointer to the internal plugin structure @retval 0 Success @retval 1 Observer not exists */ int unregister_binlog_relay_io_observer(Binlog_relay_IO_observer *observer, void *p); /** Get the value of user variable as an integer. This function will return the value of variable @a name as an integer. If the original value of the variable is not an integer, the value will be converted into an integer. @param name user variable name @param value pointer to return the value @param null_value if not NULL, the function will set it to true if the value of variable is null, set to false if not @retval 0 Success @retval 1 Variable not found */ int get_user_var_int(const char *name, long long int *value, int *null_value); /** Get the value of user variable as a double precision float number. This function will return the value of variable @a name as real number. If the original value of the variable is not a real number, the value will be converted into a real number. @param name user variable name @param value pointer to return the value @param null_value if not NULL, the function will set it to true if the value of variable is null, set to false if not @retval 0 Success @retval 1 Variable not found */ int get_user_var_real(const char *name, double *value, int *null_value); /** Get the value of user variable as a string. This function will return the value of variable @a name as string. If the original value of the variable is not a string, the value will be converted into a string. @param name user variable name @param value pointer to the value buffer @param len length of the value buffer @param precision precision of the value if it is a float number @param null_value if not NULL, the function will set it to true if the value of variable is null, set to false if not @retval 0 Success @retval 1 Variable not found */ int get_user_var_str(const char *name, char *value, unsigned long len, unsigned int precision, int *null_value); #ifdef __cplusplus } #endif #endif /* REPLICATION_H */ embedded_priv.h 0000644 00000003305 15156036173 0007516 0 ustar 00 /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Prototypes for the embedded version of MySQL */ #include <sql_common.h> C_MODE_START void lib_connection_phase(NET *net, int phase); void init_embedded_mysql(MYSQL *mysql, ulong client_flag); void *create_embedded_thd(ulong client_flag); int check_embedded_connection(MYSQL *mysql, const char *db); void free_old_query(MYSQL *mysql); THD *embedded_get_current_thd(); void embedded_set_current_thd(THD *thd); extern MYSQL_METHODS embedded_methods; /* This one is used by embedded library to gather returning data */ typedef struct embedded_query_result { MYSQL_ROWS **prev_ptr; unsigned int warning_count, server_status; struct st_mysql_data *next; my_ulonglong affected_rows, insert_id; char info[MYSQL_ERRMSG_SIZE]; MYSQL_FIELD *fields_list; unsigned int last_errno; char sqlstate[SQLSTATE_LENGTH+1]; } EQR; typedef struct st_mariadb_field_extension { MARIADB_CONST_STRING metadata[MARIADB_FIELD_ATTR_LAST+1]; /* 10.5 */ } MARIADB_FIELD_EXTENSION; C_MODE_END sql_analyze_stmt.h 0000644 00000030634 15156036173 0010323 0 ustar 00 /* Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* == ANALYZE-stmt classes == This file contains classes for supporting "ANALYZE statement" feature. These are a set of data structures that can be used to store the data about how the statement executed. There are two kinds of data collection: 1. Various counters. We assume that incrementing counters has very low overhead. Because of that, execution code increments counters unconditionally (even when not running "ANALYZE $statement" commands. You run regular SELECT/ UPDATE/DELETE/etc and the counters are incremented). As a free bonus, this lets us print detailed information into the slow query log, should the query be slow. 2. Timing data. Measuring the time it took to run parts of query has noticeable overhead. Because of that, we measure the time only when running "ANALYZE $stmt"). */ /* fake microseconds as cycles if cycles isn't available */ static inline double timer_tracker_frequency() { #if (MY_TIMER_ROUTINE_CYCLES) return static_cast<double>(sys_timer_info.cycles.frequency); #else return static_cast<double>(sys_timer_info.microseconds.frequency); #endif } class Gap_time_tracker; void attach_gap_time_tracker(THD *thd, Gap_time_tracker *gap_tracker, ulonglong timeval); void process_gap_time_tracker(THD *thd, ulonglong timeval); /* A class for tracking time it takes to do a certain action */ class Exec_time_tracker { protected: ulonglong count; ulonglong cycles; ulonglong last_start; ulonglong measure() const { #if (MY_TIMER_ROUTINE_CYCLES) return my_timer_cycles(); #else return my_timer_microseconds(); #endif } void cycles_stop_tracking(THD *thd) { ulonglong end= measure(); cycles += end - last_start; process_gap_time_tracker(thd, end); if (my_gap_tracker) attach_gap_time_tracker(thd, my_gap_tracker, end); } /* The time spent after stop_tracking() call on this object and any subsequent time tracking call will be billed to this tracker. */ Gap_time_tracker *my_gap_tracker; public: Exec_time_tracker() : count(0), cycles(0), my_gap_tracker(NULL) {} void set_gap_tracker(Gap_time_tracker *gap_tracker) { my_gap_tracker= gap_tracker; } // interface for collecting time void start_tracking(THD *thd) { last_start= measure(); process_gap_time_tracker(thd, last_start); } void stop_tracking(THD *thd) { count++; cycles_stop_tracking(thd); } // interface for getting the time ulonglong get_loops() const { return count; } inline double cycles_to_ms(ulonglong cycles_arg) const { // convert 'cycles' to milliseconds. return 1000.0 * static_cast<double>(cycles_arg) / timer_tracker_frequency(); } double get_time_ms() const { return cycles_to_ms(cycles); } ulonglong get_cycles() const { return cycles; } bool has_timed_statistics() const { return cycles > 0; } }; /* Tracker for time spent between the calls to Exec_time_tracker's {start| stop}_tracking(). @seealso Gap_time_tracker_data in sql_class.h */ class Gap_time_tracker { ulonglong cycles; public: Gap_time_tracker() : cycles(0) {} void log_time(ulonglong start, ulonglong end) { cycles += end - start; } double get_time_ms() const { // convert 'cycles' to milliseconds. return 1000.0 * static_cast<double>(cycles) / timer_tracker_frequency(); } }; /* A class for counting certain actions (in all queries), and optionally collecting the timings (in ANALYZE queries). */ class Time_and_counter_tracker: public Exec_time_tracker { public: const bool timed; Time_and_counter_tracker(bool timed_arg) : timed(timed_arg) {} /* Loops are counted in both ANALYZE and regular queries, as this is cheap */ void incr_loops() { count++; } /* Unlike Exec_time_tracker::stop_tracking, we don't increase loops. */ void stop_tracking(THD *thd) { cycles_stop_tracking(thd); } }; #define ANALYZE_START_TRACKING(thd, tracker) \ { \ (tracker)->incr_loops(); \ if (unlikely((tracker)->timed)) \ { (tracker)->start_tracking(thd); } \ } #define ANALYZE_STOP_TRACKING(thd, tracker) \ if (unlikely((tracker)->timed)) \ { (tracker)->stop_tracking(thd); } /* Just a counter to increment one value. Wrapped in a class to be uniform with other counters used by ANALYZE. */ class Counter_tracker { public: Counter_tracker() : r_scans(0) {} ha_rows r_scans; inline void on_scan_init() { r_scans++; } bool has_scans() const { return (r_scans != 0); } ha_rows get_loops() const { return r_scans; } }; /* A class for collecting read statistics. The idea is that we run several scans. Each scans gets rows, and then filters some of them out. We count scans, rows, and rows left after filtering. (note: at the moment, the class is not actually tied to a physical table. It can be used to track reading from files, buffers, etc). */ class Table_access_tracker { public: Table_access_tracker() : r_scans(0), r_rows(0), r_rows_after_where(0) {} ha_rows r_scans; /* how many scans were ran on this join_tab */ ha_rows r_rows; /* How many rows we've got after that */ ha_rows r_rows_after_where; /* Rows after applying attached part of WHERE */ double get_avg_rows() const { return r_scans ? static_cast<double>(r_rows) / static_cast<double>(r_scans) : 0; } double get_filtered_after_where() const { return r_rows > 0 ? static_cast<double>(r_rows_after_where) / static_cast<double>(r_rows) : 1.0; } inline void on_scan_init() { r_scans++; } inline void on_record_read() { r_rows++; } inline void on_record_after_where() { r_rows_after_where++; } bool has_scans() const { return (r_scans != 0); } ha_rows get_loops() const { return r_scans; } }; class Json_writer; /* This stores the data about how filesort executed. A few things from here (e.g. r_used_pq, r_limit) belong to the query plan, however, these parameters are calculated right during the execution so we can't easily put them into the query plan. The class is designed to handle multiple invocations of filesort(). */ class Filesort_tracker : public Sql_alloc { public: Filesort_tracker(bool do_timing) : time_tracker(do_timing), r_limit(0), r_used_pq(0), r_examined_rows(0), r_sorted_rows(0), r_output_rows(0), sort_passes(0), sort_buffer_size(0), r_using_addons(false), r_packed_addon_fields(false), r_sort_keys_packed(false) {} /* Functions that filesort uses to report various things about its execution */ inline void report_use(THD *thd, ha_rows r_limit_arg) { if (!time_tracker.get_loops()) r_limit= r_limit_arg; else r_limit= (r_limit != r_limit_arg)? 0: r_limit_arg; ANALYZE_START_TRACKING(thd, &time_tracker); } inline void incr_pq_used() { r_used_pq++; } inline void report_row_numbers(ha_rows examined_rows, ha_rows sorted_rows, ha_rows returned_rows) { r_examined_rows += examined_rows; r_sorted_rows += sorted_rows; r_output_rows += returned_rows; } inline void report_merge_passes_at_start(ulong passes) { sort_passes -= passes; } inline void report_merge_passes_at_end(THD *thd, ulong passes) { ANALYZE_STOP_TRACKING(thd, &time_tracker); sort_passes += passes; } inline void report_sort_buffer_size(size_t bufsize) { if (sort_buffer_size) sort_buffer_size= ulonglong(-1); // multiple buffers of different sizes else sort_buffer_size= bufsize; } inline void report_addon_fields_format(bool addons_packed) { r_using_addons= true; r_packed_addon_fields= addons_packed; } inline void report_sort_keys_format(bool sort_keys_packed) { r_sort_keys_packed= sort_keys_packed; } void get_data_format(String *str); /* Functions to get the statistics */ void print_json_members(Json_writer *writer); ulonglong get_r_loops() const { return time_tracker.get_loops(); } double get_avg_examined_rows() const { return static_cast<double>(r_examined_rows) / static_cast<double>(get_r_loops()); } double get_avg_returned_rows() const { return static_cast<double>(r_output_rows) / static_cast<double>(get_r_loops()); } double get_r_filtered() const { return r_examined_rows > 0 ? static_cast<double>(r_sorted_rows) / static_cast<double>(r_examined_rows) : 1.0; } private: Time_and_counter_tracker time_tracker; //ulonglong r_loops; /* How many times filesort was invoked */ /* LIMIT is typically a constant. There is never "LIMIT 0". HA_POS_ERROR means we never had a limit 0 means different values of LIMIT were used in different filesort invocations other value means the same LIMIT value was used every time. */ ulonglong r_limit; ulonglong r_used_pq; /* How many times PQ was used */ /* How many rows were examined (before checking the select->cond) */ ulonglong r_examined_rows; /* How many rows were put into sorting (this is examined_rows minus rows that didn't pass the WHERE condition) */ ulonglong r_sorted_rows; /* How many rows were returned. This is equal to r_sorted_rows, unless there was a LIMIT N clause in which case filesort would not have returned more than N rows. */ ulonglong r_output_rows; /* How many sorts in total (divide by r_count to get the average) */ ulonglong sort_passes; /* 0 - means not used (or not known (ulonglong)-1 - multiple other - value */ ulonglong sort_buffer_size; bool r_using_addons; bool r_packed_addon_fields; bool r_sort_keys_packed; }; /** A class to collect data about how rowid filter is executed. It stores information about how rowid filter container is filled, containers size and observed selectivity. The observed selectivity is calculated in this way. Some elements elem_set are checked if they belong to container. Observed selectivity is calculated as the count of elem_set elements that belong to container devided by all elem_set elements. */ class Rowid_filter_tracker : public Sql_alloc { private: /* A member to track the time to fill the rowid filter */ Time_and_counter_tracker time_tracker; /* Size of the rowid filter container buffer */ size_t container_buff_size; /* Count of elements that were used to fill the rowid filter container */ uint container_elements; /* Elements counts used for observed selectivity calculation */ uint n_checks; uint n_positive_checks; public: Rowid_filter_tracker(bool do_timing) : time_tracker(do_timing), container_buff_size(0), container_elements(0), n_checks(0), n_positive_checks(0) {} inline void start_tracking(THD *thd) { ANALYZE_START_TRACKING(thd, &time_tracker); } inline void stop_tracking(THD *thd) { ANALYZE_STOP_TRACKING(thd, &time_tracker); } /* Save container buffer size in bytes */ inline void report_container_buff_size(uint elem_size) { container_buff_size= container_elements * elem_size / 8; } Time_and_counter_tracker *get_time_tracker() { return &time_tracker; } double get_time_fill_container_ms() const { return time_tracker.get_time_ms(); } void increment_checked_elements_count(bool was_checked) { n_checks++; if (was_checked) n_positive_checks++; } inline void set_container_elements_count(uint elements) { container_elements= elements; } uint get_container_elements() const { return container_elements; } uint get_container_lookups() { return n_checks; } double get_r_selectivity_pct() const { return n_checks ? static_cast<double>(n_positive_checks) / static_cast<double>(n_checks) : 0; } size_t get_container_buff_size() const { return container_buff_size; } }; sql_expression_cache.h 0000644 00000010407 15156036173 0011127 0 ustar 00 /* Copyright (c) 2010, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef SQL_EXPRESSION_CACHE_INCLUDED #define SQL_EXPRESSION_CACHE_INCLUDED #include "sql_select.h" /** Interface for expression cache @note Parameters of an expression cache interface are set on the creation of the cache. They are passed when a cache object of the implementation class is constructed. That's why they are not visible in this interface. */ extern ulong subquery_cache_miss, subquery_cache_hit; class Expression_cache :public Sql_alloc { public: enum result {ERROR, HIT, MISS}; Expression_cache()= default; virtual ~Expression_cache() = default; /** Shall check the presence of expression value in the cache for a given set of values of the expression parameters. Return the result of the expression if it's found in the cache. */ virtual result check_value(Item **value)= 0; /** Shall put the value of an expression for given set of its parameters into the expression cache */ virtual my_bool put_value(Item *value)= 0; /** Print cache parameters */ virtual void print(String *str, enum_query_type query_type)= 0; /** Is this cache initialized */ virtual bool is_inited()= 0; /** Initialize this cache */ virtual void init()= 0; /** Save this object's statistics into Expression_cache_tracker object */ virtual void update_tracker()= 0; }; struct st_table_ref; struct st_join_table; class Item_field; class Expression_cache_tracker :public Sql_alloc { public: enum expr_cache_state {UNINITED, STOPPED, OK}; Expression_cache_tracker(Expression_cache *c) : cache(c), hit(0), miss(0), state(UNINITED) {} private: // This can be NULL if the cache is already deleted Expression_cache *cache; public: ulong hit, miss; enum expr_cache_state state; static const char* state_str[3]; void set(ulong h, ulong m, enum expr_cache_state s) {hit= h; miss= m; state= s;} void detach_from_cache() { cache= NULL; } void fetch_current_stats() { if (cache) cache->update_tracker(); } }; /** Implementation of expression cache over a temporary table */ class Expression_cache_tmptable :public Expression_cache { public: Expression_cache_tmptable(THD *thd, List<Item> &dependants, Item *value); virtual ~Expression_cache_tmptable(); result check_value(Item **value) override; my_bool put_value(Item *value) override; void print(String *str, enum_query_type query_type) override; bool is_inited() override { return inited; }; void init() override; void set_tracker(Expression_cache_tracker *st) { tracker= st; update_tracker(); } void update_tracker() override { if (tracker) { tracker->set(hit, miss, (inited ? (cache_table ? Expression_cache_tracker::OK : Expression_cache_tracker::STOPPED) : Expression_cache_tracker::UNINITED)); } } private: void disable_cache(); /* tmp table parameters */ TMP_TABLE_PARAM cache_table_param; /* temporary table to store this cache */ TABLE *cache_table; /* Thread handle for the temporary table */ THD *table_thd; /* EXPALIN/ANALYZE statistics */ Expression_cache_tracker *tracker; /* TABLE_REF for index lookup */ struct st_table_ref ref; /* Cached result */ Item_field *cached_result; /* List of parameter items */ List<Item> &items; /* Value Item example */ Item *val; /* hit/miss counters */ ulong hit, miss; /* Set on if the object has been successfully initialized with init() */ bool inited; }; #endif /* SQL_EXPRESSION_CACHE_INCLUDED */ my_nosys.h 0000644 00000002636 15156036173 0006613 0 ustar 00 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* Header to remove use of my_functions in functions where we need speed and where calls to posix functions should work */ #ifndef _my_nosys_h #define _my_nosys_h #ifdef __cplusplus extern "C" { #endif #ifndef __MY_NOSYS__ #define __MY_NOSYS__ #ifndef HAVE_STDLIB_H #include <malloc.h> #endif #undef my_read #undef my_write #undef my_seek #define my_read(a,b,c,d) my_quick_read(a,b,c,d) #define my_write(a,b,c,d) my_quick_write(a,b,c) extern size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count, myf myFlags); extern size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count); #endif /* __MY_NOSYS__ */ #ifdef __cplusplus } #endif #endif group_by_handler.h 0000644 00000006716 15156036173 0010261 0 ustar 00 /* Copyright (c) 2014, 2015 SkySQL Ab & MariaDB Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef GROUP_BY_HANDLER_INCLUDED #define GROUP_BY_HANDLER_INCLUDED class Select_limit_counters; /* This file implements the group_by_handler interface. This interface can be used by storage handlers that can intercept summary or GROUP BY queries from MariaDB and itself return the result to the user or upper level. It is part of the Storage Engine API Both main and sub queries are supported. Here are some examples of what the storage engine could intersept: SELECT count(*) FROM t1; SELECT a,count(*) FROM t1 group by a; SELECT a,count(*) as sum FROM t1 where b > 10 group by a, order by sum; SELECT a,count(*) FROM t1,t2; SELECT a, (select sum(*) from t2 where t1.a=t2.a) from t2; */ /** The structure describing various parts of the query The engine is supposed to take out parts that it can do internally. For example, if the engine can return results sorted according to the specified order_by clause, it sets Query::order_by=NULL before returning. At the moment the engine must take group_by (or return an error), and optionally can take distinct, where, order_by, and having. The engine should not modify the select list. It is the extended SELECT clause (extended, because it has more items than the original user-specified SELECT clause) and it contains all aggregate functions, used in the query. */ struct Query { List<Item> *select; /* Number of auxiliary fields. */ int n_aux; bool distinct; TABLE_LIST *from; Item *where; ORDER *group_by; ORDER *order_by; Item *having; // LIMIT Select_limit_counters *limit; }; class group_by_handler { public: THD *thd; handlerton *ht; /* Temporary table where all results should be stored in record[0] The table has a field for every item from the Query::select list, except for const items and some other exceptions, see Create_tmp_table::add_fields() for which items are included and which are skipped. */ TABLE *table; group_by_handler(THD *thd_arg, handlerton *ht_arg) : thd(thd_arg), ht(ht_arg), table(0) {} virtual ~group_by_handler() = default; /* Functions to scan data. All these returns 0 if ok, error code in case of error */ /* Initialize group_by scan, prepare for next_row(). If this is a sub query with group by, this can be called many times for a query. */ virtual int init_scan()= 0; /* Return next group by result in table->record[0]. Return 0 if row found, HA_ERR_END_OF_FILE if last row and other error number in case of fatal error. */ virtual int next_row()= 0; /* End scanning */ virtual int end_scan()=0; /* Report errors */ virtual void print_error(int error, myf errflag); }; #endif //GROUP_BY_HANDLER_INCLUDED log_slow.h 0000644 00000004612 15156036174 0006555 0 ustar 00 /* Copyright (C) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 or later of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /* Defining what to log to slow log */ #ifndef LOG_SLOW_INCLUDED #define LOG_SLOW_INCLUDED #define LOG_SLOW_VERBOSITY_INIT 0 #define LOG_SLOW_VERBOSITY_INNODB (1U << 0) /* Old option */ #define LOG_SLOW_VERBOSITY_QUERY_PLAN (1U << 1) #define LOG_SLOW_VERBOSITY_EXPLAIN (1U << 2) #define LOG_SLOW_VERBOSITY_STORAGE_ENGINE (1U << 3) /* Replaces InnoDB */ #define LOG_SLOW_VERBOSITY_WARNINGS (1U << 4) #define LOG_SLOW_VERBOSITY_FULL (1U << 5) #define LOG_SLOW_VERBOSITY_ENGINE (LOG_SLOW_VERBOSITY_FULL | \ LOG_SLOW_VERBOSITY_INNODB | \ LOG_SLOW_VERBOSITY_STORAGE_ENGINE) #define QPLAN_INIT QPLAN_QC_NO #define QPLAN_ADMIN (1U << 0) #define QPLAN_FILESORT (1U << 1) #define QPLAN_FILESORT_DISK (1U << 2) #define QPLAN_FILESORT_PRIORITY_QUEUE (1U << 3) #define QPLAN_FULL_JOIN (1U << 4) #define QPLAN_FULL_SCAN (1U << 5) #define QPLAN_NOT_USING_INDEX (1U << 6) #define QPLAN_QC (1U << 7) #define QPLAN_QC_NO (1U << 8) #define QPLAN_TMP_TABLE (1U << 9) #define QPLAN_TMP_DISK (1U << 10) /* ... */ #define QPLAN_STATUS (1UL << 31) /* not in the slow_log_filter */ #define QPLAN_MAX (1UL << 31) /* reserved as placeholder */ /* Bits for log_slow_disabled_statements */ #define LOG_SLOW_DISABLE_ADMIN (1 << 0) #define LOG_SLOW_DISABLE_CALL (1 << 1) #define LOG_SLOW_DISABLE_SLAVE (1 << 2) #define LOG_SLOW_DISABLE_SP (1 << 3) /* Bits for log_disabled_statements */ #define LOG_DISABLE_SLAVE (1 << 0) #define LOG_DISABLE_SP (1 << 1) #endif /* LOG_SLOW_INCLUDED */ myisam.h 0000644 00000042275 15156036174 0006236 0 ustar 00 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ /* This file should be included when using myisam_functions */ #ifndef _myisam_h #define _myisam_h #ifdef __cplusplus extern "C" { #endif #include <my_base.h> #include <m_ctype.h> #include "keycache.h" #include "my_compare.h" #include <myisamchk.h> #include <mysql/plugin.h> #include <my_check_opt.h> /* Limit max keys according to HA_MAX_POSSIBLE_KEY; See myisamchk.h for details */ #if MAX_INDEXES > HA_MAX_POSSIBLE_KEY #define MI_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ #else #define MI_MAX_KEY MAX_INDEXES /* Max allowed keys */ #endif #define MI_MAX_POSSIBLE_KEY_BUFF HA_MAX_POSSIBLE_KEY_BUFF /* The following defines can be increased if necessary. But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH. */ #define MI_MAX_KEY_LENGTH 1000 /* Max length in bytes */ #define MI_MAX_KEY_SEG 16 /* Max segments for key */ #define MI_NAME_IEXT ".MYI" #define MI_NAME_DEXT ".MYD" /* Possible values for myisam_block_size (must be power of 2) */ #define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ #define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ #define MI_MAX_KEY_BLOCK_LENGTH 16384 /* In the following macros '_keyno_' is 0 .. keys-1. If there can be more keys than bits in the key_map, the highest bit is for all upper keys. They cannot be switched individually. This means that clearing of high keys is ignored, setting one high key sets all high keys. */ #define MI_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) #define MI_KEYMAP_HIGH_MASK (1ULL << (MI_KEYMAP_BITS - 1)) #define mi_get_mask_all_keys_active(_keys_) \ (((_keys_) < MI_KEYMAP_BITS) ? \ ((1ULL << (_keys_)) - 1ULL) : \ (~ 0ULL)) #if MI_MAX_KEY > MI_KEYMAP_BITS #define mi_is_key_active(_keymap_,_keyno_) \ (((_keyno_) < MI_KEYMAP_BITS) ? \ MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \ MY_TEST((_keymap_) & MI_KEYMAP_HIGH_MASK)) #define mi_set_key_active(_keymap_,_keyno_) \ (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \ (1ULL << (_keyno_)) : \ MI_KEYMAP_HIGH_MASK) #define mi_clear_key_active(_keymap_,_keyno_) \ (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \ (~ (1ULL << (_keyno_))) : \ (~ (0ULL)) /*ignore*/ ) #else #define mi_is_key_active(_keymap_,_keyno_) \ MY_TEST((_keymap_) & (1ULL << (_keyno_))) #define mi_set_key_active(_keymap_,_keyno_) \ (_keymap_)|= (1ULL << (_keyno_)) #define mi_clear_key_active(_keymap_,_keyno_) \ (_keymap_)&= (~ (1ULL << (_keyno_))) #endif #define mi_is_any_key_active(_keymap_) \ MY_TEST((_keymap_)) #define mi_is_all_keys_active(_keymap_,_keys_) \ ((_keymap_) == mi_get_mask_all_keys_active(_keys_)) #define mi_set_all_keys_active(_keymap_,_keys_) \ (_keymap_)= mi_get_mask_all_keys_active(_keys_) #define mi_clear_all_keys_active(_keymap_) \ (_keymap_)= 0 #define mi_intersect_keys_active(_to_,_from_) \ (_to_)&= (_from_) #define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ ((_keymap1_) & (_keymap2_) & \ mi_get_mask_all_keys_active(_keys_)) #define mi_copy_keys_active(_to_,_maxkeys_,_from_) \ (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \ (_from_)) /* Param to/from mi_info */ typedef struct st_mi_isaminfo /* Struct from h_info */ { ha_rows records; /* Records in database */ ha_rows deleted; /* Deleted records in database */ my_off_t recpos; /* Pos for last used record */ my_off_t newrecpos; /* Pos if we write new record */ my_off_t dupp_key_pos; /* Position to record with dupp key */ my_off_t data_file_length, /* Length of data file */ max_data_file_length, index_file_length, max_index_file_length, delete_length; ulong reclength; /* Recordlength */ ulong mean_reclength; /* Mean recordlength (if packed) */ ulonglong auto_increment; ulonglong key_map; /* Which keys are used */ char *data_file_name, *index_file_name; uint keys; /* Number of keys in use */ uint options; /* HA_OPTION_... used */ int errkey, /* With key was dupplicated on err */ sortkey; /* clustered by this key */ File filenr; /* (uniq) filenr for datafile */ time_t create_time; /* When table was created */ time_t check_time; time_t update_time; uint reflength; ulong record_offset; ulong *rec_per_key; /* for sql optimizing */ } MI_ISAMINFO; typedef struct st_mi_create_info { const char *index_file_name, *data_file_name; /* If using symlinks */ ha_rows max_rows; ha_rows reloc_rows; ulonglong auto_increment; ulonglong data_file_length; ulonglong key_file_length; uint old_options; uint16 language; my_bool with_auto_increment; } MI_CREATE_INFO; struct st_myisam_info; /* For reference */ struct st_mi_isam_share; typedef struct st_myisam_info MI_INFO; struct st_mi_s_param; typedef struct st_mi_keydef /* Key definition with open & info */ { struct st_mi_isam_share *share; /* Pointer to base (set in mi_open) */ uint16 keysegs; /* Number of key-segment */ uint16 flag; /* NOSAME, PACK_USED */ uint8 key_alg; /* BTREE, RTREE */ uint16 block_length; /* Length of keyblock (auto) */ uint16 underflow_block_length; /* When to execute underflow */ uint16 keylength; /* Tot length of keyparts (auto) */ uint16 minlength; /* min length of (packed) key (auto) */ uint16 maxlength; /* max length of (packed) key (auto) */ uint16 block_size_index; /* block_size (auto) */ uint32 version; /* For concurrent read/write */ uint32 ftkey_nr; /* full-text index number */ HA_KEYSEG *seg,*end; struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo, uchar *page,uchar *key, uint key_len,uint comp_flag,uchar * *ret_pos, uchar *buff, my_bool *was_last_key); uint (*get_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar * *page, uchar *key); int (*pack_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar *next_key, uchar *org_key, uchar *prev_key, uchar *key, struct st_mi_s_param *s_temp); void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos, struct st_mi_s_param *s_temp); int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); } MI_KEYDEF; #define MI_UNIQUE_HASH_LENGTH 4 typedef struct st_unique_def /* Segment definition of unique */ { uint16 keysegs; /* Number of key-segment */ uchar key; /* Mapped to which key */ uint8 null_are_equal; HA_KEYSEG *seg,*end; } MI_UNIQUEDEF; typedef struct st_mi_decode_tree /* Decode huff-table */ { uint16 *table; uint quick_table_bits; uchar *intervalls; } MI_DECODE_TREE; struct st_mi_bit_buff; /* Note that null markers should always be first in a row ! When creating a column, one should only specify: type, length, null_bit and null_pos */ typedef struct st_columndef /* column information */ { enum en_fieldtype type; uint16 length; /* length of field */ uint32 offset; /* Offset to position in row */ uint8 null_bit; /* If column may be 0 */ uint16 null_pos; /* position for null marker */ #ifndef NOT_PACKED_DATABASES void (*unpack)(struct st_columndef *rec,struct st_mi_bit_buff *buff, uchar *start,uchar *end); enum en_fieldtype base_type; uint space_length_bits,pack_type; MI_DECODE_TREE *huff_tree; #endif } MI_COLUMNDEF; extern char * myisam_log_filename; /* Name of logfile */ extern ulong myisam_block_size; extern ulong myisam_concurrent_insert; extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; extern my_off_t myisam_max_temp_length; extern ulong myisam_data_pointer_size; /* usually used to check if a symlink points into the mysql data home */ /* which is normally forbidden */ extern int (*myisam_test_invalid_symlink)(const char *filename); extern ulonglong myisam_mmap_size, myisam_mmap_used; extern mysql_mutex_t THR_LOCK_myisam_mmap; /* Prototypes for myisam-functions */ extern int mi_close(struct st_myisam_info *file); extern int mi_delete(struct st_myisam_info *file,const uchar *buff); extern struct st_myisam_info *mi_open(const char *name,int mode, uint wait_if_locked); extern int mi_panic(enum ha_panic_function function); extern int mi_rfirst(struct st_myisam_info *file,uchar *buf,int inx); extern int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, key_part_map keypart_map, enum ha_rkey_function search_flag); extern int mi_rlast(struct st_myisam_info *file,uchar *buf,int inx); extern int mi_rnext(struct st_myisam_info *file,uchar *buf,int inx); extern int mi_rnext_same(struct st_myisam_info *info, uchar *buf); extern int mi_rprev(struct st_myisam_info *file,uchar *buf,int inx); extern int mi_rrnd(struct st_myisam_info *file,uchar *buf, my_off_t pos); extern int mi_scan_init(struct st_myisam_info *file); extern int mi_scan(struct st_myisam_info *file,uchar *buf); extern int mi_rsame(struct st_myisam_info *file,uchar *record,int inx); extern int mi_rsame_with_pos(struct st_myisam_info *file,uchar *record, int inx, my_off_t pos); extern int mi_update(struct st_myisam_info *file,const uchar *old, const uchar *new_record); extern int mi_write(struct st_myisam_info *file,const uchar *buff); extern my_off_t mi_position(struct st_myisam_info *file); extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag); extern int mi_lock_database(struct st_myisam_info *file,int lock_type); extern int mi_create(const char *name,uint keys,MI_KEYDEF *keydef, uint columns, MI_COLUMNDEF *columndef, uint uniques, MI_UNIQUEDEF *uniquedef, MI_CREATE_INFO *create_info, uint flags); extern int mi_delete_table(const char *name); extern int mi_rename(const char *from, const char *to); extern int mi_extra(struct st_myisam_info *file, enum ha_extra_function function, void *extra_arg); extern int mi_reset(struct st_myisam_info *file); extern ha_rows mi_records_in_range(MI_INFO *info,int inx, const key_range *min_key, const key_range *max_key, page_range *pages); extern int mi_log(int activate_log); extern int mi_is_changed(struct st_myisam_info *info); extern int mi_delete_all_rows(struct st_myisam_info *info); extern ulong _mi_calc_blob_length(uint length , const uchar *pos); extern uint mi_get_pointer_length(ulonglong file_length, uint def); extern int mi_make_backup_of_index(struct st_myisam_info *info, time_t backup_time, myf flags); #define myisam_max_key_length() HA_MAX_KEY_LENGTH #define myisam_max_key_segments() HA_MAX_KEY_SEG #define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */ /* this is used to pass to mysql_myisamchk_table */ #define MYISAMCHK_REPAIR 1 /* equivalent to myisamchk -r */ #define MYISAMCHK_VERIFY 2 /* Verify, run repair if failure */ typedef uint mi_bit_type; typedef struct st_sort_key_blocks SORT_KEY_BLOCKS; typedef struct st_sort_ftbuf SORT_FT_BUF; typedef struct st_mi_bit_buff { /* Used for packing of record */ mi_bit_type current_byte; uint bits; uchar *pos, *end, *blob_pos, *blob_end; uint error; } MI_BIT_BUFF; typedef struct st_sort_info { /* sync things */ mysql_mutex_t mutex; mysql_cond_t cond; MI_INFO *info; HA_CHECK *param; uchar *buff; SORT_KEY_BLOCKS *key_block, *key_block_end; SORT_FT_BUF *ft_buf; my_off_t filelength, dupp, buff_length; ha_rows max_records; uint current_key, total_keys; volatile uint got_error; uint threads_running; myf myf_rw; enum data_file_type new_data_file_type; } MI_SORT_INFO; typedef struct st_mi_sort_param { pthread_t thr; IO_CACHE read_cache, tempfile, tempfile_for_exceptions; DYNAMIC_ARRAY buffpek; MI_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ MI_KEYDEF *keyinfo; MI_SORT_INFO *sort_info; HA_KEYSEG *seg; uchar **sort_keys; uchar *rec_buff; void *wordlist, *wordptr; MEM_ROOT wordroot; uchar *record; MY_TMPDIR *tmpdir; /* The next two are used to collect statistics, see update_key_parts for description. */ ulonglong unique[HA_MAX_KEY_SEG+1]; ulonglong notnull[HA_MAX_KEY_SEG+1]; my_off_t pos,max_pos,filepos,start_recpos; uint key, key_length,real_key_length; uint maxbuffers, find_length; ulonglong sortbuff_size; ha_rows keys; my_bool fix_datafile, master; my_bool calc_checksum; /* calculate table checksum */ int (*key_cmp)(void *, const void *, const void *); int (*key_read)(struct st_mi_sort_param *,void *); int (*key_write)(struct st_mi_sort_param *, const void *); void (*lock_in_memory)(HA_CHECK *); int (*write_keys)(struct st_mi_sort_param *, uchar **, ulonglong , struct st_buffpek *, IO_CACHE *); my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, uint, ulonglong); } MI_SORT_PARAM; /* functions in mi_check */ void myisamchk_init(HA_CHECK *param); int chk_status(HA_CHECK *param, MI_INFO *info); int chk_del(HA_CHECK *param, MI_INFO *info, ulonglong test_flag); int chk_size(HA_CHECK *param, MI_INFO *info); int chk_key(HA_CHECK *param, MI_INFO *info); int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend); int mi_repair(HA_CHECK *param, MI_INFO *info, char * name, int rep_quick); int mi_sort_index(HA_CHECK *param, MI_INFO *info, char * name); int mi_repair_by_sort(HA_CHECK *param, MI_INFO *info, const char * name, int rep_quick); int mi_repair_parallel(HA_CHECK *param, MI_INFO *info, const char * name, int rep_quick); int change_to_newfile(const char * filename, const char * old_ext, const char * new_ext, time_t backup_time, myf myflags); int lock_file(HA_CHECK *param, File file, my_off_t start, int lock_type, const char *filetype, const char *filename); void lock_memory(HA_CHECK *param); void update_auto_increment_key(HA_CHECK *param, MI_INFO *info, my_bool repair); int update_state_info(HA_CHECK *param, MI_INFO *info,uint update); void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, ulonglong *unique, ulonglong *notnull, ulonglong records); int filecopy(HA_CHECK *param, File to,File from,my_off_t start, my_off_t length, const char *type); int movepoint(MI_INFO *info,uchar *record,my_off_t oldpos, my_off_t newpos, uint prot_key); int write_data_suffix(MI_SORT_INFO *sort_info, my_bool fix_datafile); int test_if_almost_full(MI_INFO *info); int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, my_bool force); int mi_init_bulk_insert(MI_INFO *info, size_t cache_size, ha_rows rows); void mi_flush_bulk_insert(MI_INFO *info, uint inx); int mi_end_bulk_insert(MI_INFO *info, my_bool abort); int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map, KEY_CACHE *key_cache); void mi_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves); int write_data_suffix(MI_SORT_INFO *sort_info, my_bool fix_datafile); int flush_pending_blocks(MI_SORT_PARAM *param); int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); int thr_write_keys(MI_SORT_PARAM *sort_param); int sort_write_record(MI_SORT_PARAM *sort_param); int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulonglong); my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows); struct OPTIMIZER_COSTS; void myisam_update_optimizer_costs(struct OPTIMIZER_COSTS *costs); #ifdef __cplusplus } #endif #endif config.h 0000644 00000034336 15156036174 0006203 0 ustar 00 /* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef MY_CONFIG_H #define MY_CONFIG_H #define DOT_FRM_VERSION 6 /* Headers we may want to use. */ #define STDC_HEADERS 1 #define _GNU_SOURCE 1 #define HAVE_ALLOCA_H 1 #define HAVE_ARPA_INET_H 1 #define HAVE_ASM_TERMBITS_H 1 #define HAVE_CRYPT_H 1 #define HAVE_CURSES_H 1 /* #undef HAVE_BFD_H */ /* #undef HAVE_NDIR_H */ #define HAVE_DIRENT_H 1 #define HAVE_DLFCN_H 1 #define HAVE_EXECINFO_H 1 #define HAVE_FCNTL_H 1 #define HAVE_FENV_H 1 #define HAVE_FLOAT_H 1 #define HAVE_FNMATCH_H 1 #define HAVE_FPU_CONTROL_H 1 #define HAVE_GETMNTENT 1 /* #undef HAVE_GETMNTENT_IN_SYS_MNTAB */ /* #undef HAVE_GETMNTINFO */ /* #undef HAVE_GETMNTINFO64 */ /* #undef HAVE_GETMNTINFO_TAKES_statvfs */ #define HAVE_GRP_H 1 /* #undef HAVE_IA64INTRIN_H */ /* #undef HAVE_IEEEFP_H */ #define HAVE_INTTYPES_H 1 /* #undef HAVE_KQUEUE */ #define HAVE_LIMITS_H 1 #define HAVE_LINK_H 1 #define HAVE_LINUX_UNISTD_H 1 #define HAVE_LINUX_MMAN_H 1 #define HAVE_LOCALE_H 1 #define HAVE_MALLOC_H 1 #define HAVE_MEMORY_H 1 #define HAVE_NETINET_IN_H 1 #define HAVE_PATHS_H 1 #define HAVE_POLL_H 1 #define HAVE_PWD_H 1 #define HAVE_SCHED_H 1 /* #undef HAVE_SELECT_H */ /* #undef HAVE_SOLARIS_LARGE_PAGES */ #define HAVE_STDDEF_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STDARG_H 1 #define HAVE_STRINGS_H 1 #define HAVE_STRING_H 1 #define HAVE_STDINT_H 1 /* #undef HAVE_SYNCH_H */ /* #undef HAVE_SYSENT_H */ #define HAVE_SYS_DIR_H 1 #define HAVE_SYS_FILE_H 1 /* #undef HAVE_SYS_FPU_H */ #define HAVE_SYS_IOCTL_H 1 /* #undef HAVE_SYS_MALLOC_H */ #define HAVE_SYS_MMAN_H 1 /* #undef HAVE_SYS_MNTENT_H */ /* #undef HAVE_SYS_NDIR_H */ /* #undef HAVE_SYS_PTE_H */ /* #undef HAVE_SYS_PTEM_H */ #define HAVE_SYS_PRCTL_H 1 #define HAVE_SYS_RESOURCE_H 1 #define HAVE_SYS_SELECT_H 1 #define HAVE_SYS_SOCKET_H 1 /* #undef HAVE_SYS_SOCKIO_H */ #define HAVE_SYS_UTSNAME_H 1 #define HAVE_SYS_STAT_H 1 /* #undef HAVE_SYS_STREAM_H */ #define HAVE_SYS_SYSCALL_H 1 #define HAVE_SYS_TIMEB_H 1 #define HAVE_SYS_TIMES_H 1 #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_UN_H 1 /* #undef HAVE_SYS_VADVISE_H */ #define HAVE_SYS_STATVFS_H 1 #define HAVE_UCONTEXT_H 1 #define HAVE_TERM_H 1 /* #undef HAVE_TERMBITS_H */ #define HAVE_TERMIOS_H 1 #define HAVE_TERMIO_H 1 #define HAVE_TERMCAP_H 1 #define HAVE_TIME_H 1 #define HAVE_UNISTD_H 1 #define HAVE_UTIME_H 1 /* #undef HAVE_VARARGS_H */ /* #undef HAVE_SYS_UTIME_H */ #define HAVE_SYS_WAIT_H 1 #define HAVE_SYS_PARAM_H 1 /* Libraries */ /* #undef HAVE_LIBWRAP */ #define HAVE_SYSTEMD 1 #define HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES 1 /* Does "struct timespec" have a "sec" and "nsec" field? */ /* #undef HAVE_TIMESPEC_TS_SEC */ /* Readline */ /* #undef HAVE_HIST_ENTRY */ /* #undef USE_LIBEDIT_INTERFACE */ #define USE_NEW_READLINE_INTERFACE 1 #define FIONREAD_IN_SYS_IOCTL 1 #define GWINSZ_IN_SYS_IOCTL 1 /* #undef TIOCSTAT_IN_SYS_IOCTL */ /* #undef FIONREAD_IN_SYS_FILIO */ /* Functions we may want to use. */ #define HAVE_ACCEPT4 1 #define HAVE_ACCESS 1 #define HAVE_ALLOCA 1 /* #undef HAVE_BFILL */ #define HAVE_INDEX 1 #define HAVE_CLOCK_GETTIME 1 #define HAVE_CRYPT 1 #define HAVE_CUSERID 1 #define HAVE_DLADDR 1 #define HAVE_DLERROR 1 #define HAVE_DLOPEN 1 #define HAVE_FCHMOD 1 #define HAVE_FCNTL 1 #define HAVE_FDATASYNC 1 #define HAVE_DECL_FDATASYNC 1 #define HAVE_FEDISABLEEXCEPT 1 #define HAVE_FESETROUND 1 /* #undef HAVE_FP_EXCEPT */ #define HAVE_FSEEKO 1 #define HAVE_FSYNC 1 #define HAVE_FTIME 1 #define HAVE_GETIFADDRS 1 #define HAVE_GETCWD 1 #define HAVE_GETHOSTBYADDR_R 1 /* #undef HAVE_GETHRTIME */ /* #undef HAVE_GETPAGESIZES */ #define HAVE_GETPASS 1 /* #undef HAVE_GETPASSPHRASE */ #define HAVE_GETPWNAM 1 #define HAVE_GETPWUID 1 #define HAVE_GETRLIMIT 1 #define HAVE_GETRUSAGE 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_GETWD 1 #define HAVE_GMTIME_R 1 /* #undef gmtime_r */ #define HAVE_IN_ADDR_T 1 #define HAVE_INITGROUPS 1 #define HAVE_LDIV 1 #define HAVE_LRAND48 1 #define HAVE_LOCALTIME_R 1 #define HAVE_LSTAT 1 /* #define HAVE_MLOCK 1 see Bug#54662 */ #define HAVE_NL_LANGINFO 1 #define HAVE_MADVISE 1 #define HAVE_DECL_MADVISE 1 /* #undef HAVE_DECL_MHA_MAPSIZE_VA */ #define HAVE_MALLINFO 1 /* #undef HAVE_MALLINFO2 */ /* #undef HAVE_MALLOC_ZONE */ #define HAVE_MEMCPY 1 #define HAVE_MEMMOVE 1 #define HAVE_MKSTEMP 1 #define HAVE_MKOSTEMP 1 #define HAVE_MLOCKALL 1 #define HAVE_MMAP 1 #define HAVE_MMAP64 1 #define HAVE_MPROTECT 1 #define HAVE_PERROR 1 #define HAVE_POLL 1 #define HAVE_POSIX_FALLOCATE 1 #define HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE 1 #define HAVE_PREAD 1 /* #undef HAVE_READ_REAL_TIME */ /* #undef HAVE_PTHREAD_ATTR_CREATE */ #define HAVE_PTHREAD_ATTR_GETGUARDSIZE 1 #define HAVE_PTHREAD_ATTR_GETSTACKSIZE 1 #define HAVE_PTHREAD_ATTR_SETSCOPE 1 #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 #define HAVE_PTHREAD_GETATTR_NP 1 /* #undef HAVE_PTHREAD_CONDATTR_CREATE */ #define HAVE_PTHREAD_GETAFFINITY_NP 1 #define HAVE_PTHREAD_KEY_DELETE 1 /* #undef HAVE_PTHREAD_KILL */ #define HAVE_PTHREAD_RWLOCK_RDLOCK 1 #define HAVE_PTHREAD_SIGMASK 1 /* #undef HAVE_PTHREAD_YIELD_NP */ #define HAVE_PTHREAD_YIELD_ZERO_ARG 1 #define PTHREAD_ONCE_INITIALIZER PTHREAD_ONCE_INIT #define HAVE_PUTENV 1 /* #undef HAVE_READDIR_R */ #define HAVE_READLINK 1 #define HAVE_REALPATH 1 #define HAVE_RENAME 1 /* #undef HAVE_RWLOCK_INIT */ #define HAVE_SCHED_YIELD 1 #define HAVE_SELECT 1 #define HAVE_SETENV 1 #define HAVE_SETLOCALE 1 #define HAVE_SETMNTENT 1 #define HAVE_SETUPTERM 1 #define HAVE_SIGSET 1 #define HAVE_SIGACTION 1 /* #undef HAVE_SIGTHREADMASK */ #define HAVE_SIGWAIT 1 #define HAVE_SIGWAITINFO 1 #define HAVE_SLEEP 1 #define HAVE_STPCPY 1 #define HAVE_STRERROR 1 #define HAVE_STRCOLL 1 #define HAVE_STRNLEN 1 #define HAVE_STRPBRK 1 #define HAVE_STRTOK_R 1 #define HAVE_STRTOLL 1 #define HAVE_STRTOUL 1 #define HAVE_STRTOULL 1 /* #undef HAVE_TELL */ /* #undef HAVE_THR_YIELD */ #define HAVE_TIME 1 #define HAVE_TIMES 1 #define HAVE_VIDATTR 1 #define HAVE_VIO_READ_BUFF 1 #define HAVE_VASPRINTF 1 #define HAVE_VSNPRINTF 1 #define HAVE_FTRUNCATE 1 #define HAVE_TZNAME 1 /* Symbols we may use */ /* #undef HAVE_SYS_ERRLIST */ /* used by stacktrace functions */ #define HAVE_BACKTRACE 1 #define HAVE_BACKTRACE_SYMBOLS 1 #define HAVE_BACKTRACE_SYMBOLS_FD 1 /* #undef HAVE_PRINTSTACK */ #define HAVE_IPV6 1 /* #undef ss_family */ /* #undef HAVE_SOCKADDR_IN_SIN_LEN */ /* #undef HAVE_SOCKADDR_IN6_SIN6_LEN */ #define STRUCT_TIMESPEC_HAS_TV_SEC 1 #define STRUCT_TIMESPEC_HAS_TV_NSEC 1 #define STRUCT_TM_HAS_TM_GMTOFF 1 /* this means that valgrind headers and macros are available */ /* #undef HAVE_VALGRIND_MEMCHECK_H */ /* this means WITH_VALGRIND - we change some code paths for valgrind */ /* #undef HAVE_valgrind */ /* Types we may use */ #ifdef __APPLE__ /* Special handling required for OSX to support universal binaries that mix 32 and 64 bit architectures. */ #if(__LP64__) #define SIZEOF_LONG 8 #else #define SIZEOF_LONG 4 #endif #define SIZEOF_VOIDP SIZEOF_LONG #define SIZEOF_CHARP SIZEOF_LONG #define SIZEOF_SIZE_T SIZEOF_LONG #else /* No indentation, to fetch the lines from verification scripts */ #define SIZEOF_LONG 8 #define SIZEOF_VOIDP 8 #define SIZEOF_CHARP 8 #define SIZEOF_SIZE_T 8 #endif #define HAVE_LONG 1 #define HAVE_CHARP 1 #define SIZEOF_INT 4 #define HAVE_INT 1 #define SIZEOF_LONG_LONG 8 #define HAVE_LONG_LONG 1 #define SIZEOF_OFF_T 8 #define HAVE_OFF_T 1 /* #undef SIZEOF_UCHAR */ /* #undef HAVE_UCHAR */ #define SIZEOF_UINT 4 #define HAVE_UINT 1 #define SIZEOF_ULONG 8 #define HAVE_ULONG 1 /* #undef SIZEOF_INT8 */ /* #undef HAVE_INT8 */ /* #undef SIZEOF_UINT8 */ /* #undef HAVE_UINT8 */ /* #undef SIZEOF_INT16 */ /* #undef HAVE_INT16 */ /* #undef SIZEOF_UINT16 */ /* #undef HAVE_UINT16 */ /* #undef SIZEOF_INT32 */ /* #undef HAVE_INT32 */ /* #undef SIZEOF_UINT32 */ /* #undef HAVE_UINT32 */ /* #undef SIZEOF_INT64 */ /* #undef HAVE_INT64 */ /* #undef SIZEOF_UINT64 */ /* #undef HAVE_UINT64 */ #define SOCKET_SIZE_TYPE socklen_t #define HAVE_MBSTATE_T 1 #define MAX_INDEXES 64 #define QSORT_TYPE_IS_VOID 1 #define RETQSORTTYPE void #define RETSIGTYPE void #define VOID_SIGHANDLER 1 #define HAVE_SIGHANDLER_T 1 #define STRUCT_RLIMIT struct rlimit #ifdef __APPLE__ #if __BIG_ENDIAN #define WORDS_BIGENDIAN 1 #endif #else /* #undef WORDS_BIGENDIAN */ #endif /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #define C_HAS_inline 1 #if !(C_HAS_inline) #ifndef __cplusplus # define inline #endif #endif #define TARGET_OS_LINUX 1 #define HAVE_WCTYPE_H 1 #define HAVE_WCHAR_H 1 #define HAVE_LANGINFO_H 1 #define HAVE_MBRLEN 1 #define HAVE_MBSRTOWCS 1 #define HAVE_MBRTOWC 1 #define HAVE_WCWIDTH 1 #define HAVE_ISWLOWER 1 #define HAVE_ISWUPPER 1 #define HAVE_TOWLOWER 1 #define HAVE_TOWUPPER 1 #define HAVE_ISWCTYPE 1 #define HAVE_WCHAR_T 1 #define HAVE_STRCASECMP 1 #define HAVE_TCGETATTR 1 #define HAVE_WEAK_SYMBOL 1 #define HAVE_ABI_CXA_DEMANGLE 1 #define HAVE_ATTRIBUTE_CLEANUP 1 #define HAVE_POSIX_SIGNALS 1 /* #undef HAVE_BSD_SIGNALS */ /* #undef HAVE_SVR3_SIGNALS */ /* #undef HAVE_V7_SIGNALS */ #define HAVE_ERR_remove_thread_state 1 /* #undef HAVE_X509_check_host */ /* #undef HAVE_SOLARIS_STYLE_GETHOST */ #define HAVE_GCC_C11_ATOMICS 1 /* #undef HAVE_SOLARIS_ATOMIC */ /* #undef NO_FCNTL_NONBLOCK */ /* #undef _LARGE_FILES */ #define _LARGEFILE_SOURCE 1 /* #undef _LARGEFILE64_SOURCE */ #define TIME_WITH_SYS_TIME 1 #define STACK_DIRECTION -1 #define SYSTEM_TYPE "Linux" #define MACHINE_TYPE "x86_64" #define DEFAULT_MACHINE "x86_64" #define HAVE_DTRACE 1 #define SIGNAL_WITH_VIO_CLOSE 1 /* Windows stuff, mostly functions, that have Posix analogs but named differently */ #ifdef _WIN32 #define S_IROTH _S_IREAD #define S_IFIFO _S_IFIFO #define SIGQUIT SIGTERM #define SIGPIPE SIGINT #define sigset_t int #define mode_t int #define popen _popen #define pclose _pclose #define ssize_t SSIZE_T #define strcasecmp _stricmp #define strncasecmp _strnicmp #define strtok_r strtok_s #define tzname _tzname #define P_tmpdir "C:\\TEMP" #define setenv(a,b,c) _putenv_s(a,b) #define HAVE_SETENV #define NOMINMAX 1 #define PSAPI_VERSION 2 /* for GetProcessMemoryInfo() */ #endif /* _WIN32 */ /* MySQL features */ #define LOCAL_INFILE_MODE_OFF 0 #define LOCAL_INFILE_MODE_ON 1 #define LOCAL_INFILE_MODE_AUTO 2 #define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_AUTO #define ENABLED_PROFILING 1 /* #undef EXTRA_DEBUG */ /* #undef USE_SYMDIR */ /* Character sets and collations */ #define MYSQL_DEFAULT_CHARSET_NAME "latin1" #define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci" #define USE_MB #define USE_MB_IDENT /* This should mean case insensitive file system */ /* #undef FN_NO_CASE_SENSE */ /* Whether an anonymous private mapping is unaccessible after madvise(MADV_DONTNEED) or madvise(MADV_FREE) or similar has been invoked; this is the case with Microsoft Windows VirtualFree(MEM_DECOMMIT) */ /* #undef HAVE_UNACCESSIBLE_AFTER_MEM_DECOMMIT */ #define HAVE_CHARSET_armscii8 1 #define HAVE_CHARSET_ascii 1 #define HAVE_CHARSET_big5 1 #define HAVE_CHARSET_cp1250 1 #define HAVE_CHARSET_cp1251 1 #define HAVE_CHARSET_cp1256 1 #define HAVE_CHARSET_cp1257 1 #define HAVE_CHARSET_cp850 1 #define HAVE_CHARSET_cp852 1 #define HAVE_CHARSET_cp866 1 #define HAVE_CHARSET_cp932 1 #define HAVE_CHARSET_dec8 1 #define HAVE_CHARSET_eucjpms 1 #define HAVE_CHARSET_euckr 1 #define HAVE_CHARSET_gb2312 1 #define HAVE_CHARSET_gbk 1 #define HAVE_CHARSET_geostd8 1 #define HAVE_CHARSET_greek 1 #define HAVE_CHARSET_hebrew 1 #define HAVE_CHARSET_hp8 1 #define HAVE_CHARSET_keybcs2 1 #define HAVE_CHARSET_koi8r 1 #define HAVE_CHARSET_koi8u 1 #define HAVE_CHARSET_latin1 1 #define HAVE_CHARSET_latin2 1 #define HAVE_CHARSET_latin5 1 #define HAVE_CHARSET_latin7 1 #define HAVE_CHARSET_macce 1 #define HAVE_CHARSET_macroman 1 #define HAVE_CHARSET_sjis 1 #define HAVE_CHARSET_swe7 1 #define HAVE_CHARSET_tis620 1 #define HAVE_CHARSET_ucs2 1 #define HAVE_CHARSET_ujis 1 #define HAVE_CHARSET_utf8mb4 1 #define HAVE_CHARSET_utf8mb3 1 #define HAVE_CHARSET_utf16 1 #define HAVE_CHARSET_utf32 1 #define HAVE_UCA_COLLATIONS 1 #define HAVE_COMPRESS 1 #define HAVE_EncryptAes128Ctr 1 #define HAVE_EncryptAes128Gcm 1 #define HAVE_des 1 #define HAVE_hkdf 1 /* Stuff that always need to be defined (compile breaks without it) */ #define HAVE_SPATIAL 1 #define HAVE_RTREE_KEYS 1 #define HAVE_QUERY_CACHE 1 #define BIG_TABLES 1 /* Important storage engines (those that really need define WITH_<ENGINE>_STORAGE_ENGINE for the whole server) */ #define WITH_INNOBASE_STORAGE_ENGINE 1 #define WITH_PARTITION_STORAGE_ENGINE 1 #define WITH_PERFSCHEMA_STORAGE_ENGINE 1 #define WITH_ARIA_STORAGE_ENGINE 1 #define USE_ARIA_FOR_TMP_TABLES 1 #define DEFAULT_MYSQL_HOME "/usr" #define SHAREDIR "/usr/share/mariadb" #define DEFAULT_BASEDIR "/usr" #define MYSQL_DATADIR "/var/lib/mysql" #define DEFAULT_CHARSET_HOME "/usr" #define PLUGINDIR "/usr/lib64/mysql/plugin" #define DEFAULT_SYSCONFDIR "/etc" #define DEFAULT_TMPDIR P_tmpdir /* #undef SO_EXT */ #define MYSQL_VERSION_MAJOR 11 #define MYSQL_VERSION_MINOR 4 #define MYSQL_VERSION_PATCH 10 #define MYSQL_VERSION_EXTRA "" #define PACKAGE "mysql" #define PACKAGE_BUGREPORT "" #define PACKAGE_NAME "MySQL Server" #define PACKAGE_STRING "MySQL Server 11.4.10" #define PACKAGE_TARNAME "mysql" #define PACKAGE_VERSION "11.4.10" #define VERSION "11.4.10" #define PROTOCOL_VERSION 10 #define PCRE2_CODE_UNIT_WIDTH 8 #define MALLOC_LIBRARY "system" /* time_t related defines */ #define SIZEOF_TIME_T 8 /* #undef TIME_T_UNSIGNED */ #ifndef EMBEDDED_LIBRARY /* #undef WSREP_INTERFACE_VERSION */ #define WITH_WSREP 1 #endif #if !defined(__STDC_FORMAT_MACROS) #define __STDC_FORMAT_MACROS #endif // !defined(__STDC_FORMAT_MACROS) #endif #define HAVE_VFORK 1 service_versions.h 0000644 00000004355 15156036174 0010324 0 ustar 00 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. Copyright (c) 2012, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifdef _WIN32 #define SERVICE_VERSION __declspec(dllexport) void * #else #define SERVICE_VERSION void * #endif #define VERSION_debug_sync 0x1000 #define VERSION_kill_statement 0x1000 #define VERSION_base64 0x0100 #define VERSION_encryption 0x0300 #define VERSION_encryption_scheme 0x0100 #define VERSION_logger 0x0100 #define VERSION_my_crypt 0x0100 #define VERSION_my_md5 0x0100 #define VERSION_my_print_error 0x0100 #define VERSION_my_sha1 0x0101 #define VERSION_my_sha2 0x0100 #define VERSION_my_snprintf 0x0100 #define VERSION_progress_report 0x0100 #define VERSION_thd_alloc 0x0200 #define VERSION_thd_autoinc 0x0100 #define VERSION_thd_error_context 0x0200 #define VERSION_thd_rnd 0x0100 #define VERSION_thd_specifics 0x0100 #define VERSION_thd_timezone 0x0100 #define VERSION_thd_wait 0x0100 #define VERSION_wsrep 0x0500 #define VERSION_json 0x0100 #define VERSION_sql_service 0x0102 #define VERSION_thd_mdl 0x0100 #define VERSION_print_check_msg 0x0100 #define VERSION_provider_bzip2 0x0100 #define VERSION_provider_lz4 0x0100 #define VERSION_provider_lzma 0x0100 #define VERSION_provider_lzo 0x0100 #define VERSION_provider_snappy 0x0100 charset_collations.h 0000644 00000014642 15156036174 0010614 0 ustar 00 /* Copyright (c) 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef LEX_CHARSET_COLLATIONS_INCLUDED #define LEX_CHARSET_COLLATIONS_INCLUDED #include "sql_used.h" struct Charset_collation_map_st { public: struct Elem_st { protected: CHARSET_INFO *m_from; // From a character set CHARSET_INFO *m_to; // To a collation static size_t print_lex_string(char *dst, const LEX_CSTRING &str) { memcpy(dst, str.str, str.length); return str.length; } public: /* Size in text format: 'utf8mb4=utf8mb4_unicode_ai_ci' */ static constexpr size_t text_size_max() { return MY_CS_CHARACTER_SET_NAME_SIZE + 1 + MY_CS_COLLATION_NAME_SIZE; } CHARSET_INFO *from() const { return m_from; } CHARSET_INFO *to() const { return m_to; } void set_to(CHARSET_INFO *cl) { m_to= cl; } size_t print(char *dst) const { const char *dst0= dst; dst+= print_lex_string(dst, m_from->cs_name); *dst++= '='; dst+= print_lex_string(dst, m_to->coll_name); return (size_t) (dst - dst0); } int cmp_by_charset_id(const Elem_st &rhs) const { return m_from->number < rhs.m_from->number ? -1 : m_from->number > rhs.m_from->number ? +1 : 0; } }; class Elem: public Elem_st { public: Elem(CHARSET_INFO *from, CHARSET_INFO *to) { m_from= from; m_to= to; } }; protected: Elem_st m_element[8]; // Should be enough for now uint m_count; uint m_version; static int cmp_by_charset_id(const void *a, const void *b) { return static_cast<const Elem_st*>(a)-> cmp_by_charset_id(*static_cast<const Elem_st*>(b)); } void sort() { qsort(m_element, m_count, sizeof(Elem_st), cmp_by_charset_id); } const Elem_st *find_elem_by_charset_id(uint id) const { if (!m_count) return NULL; int first= 0, last= ((int) m_count) - 1; for ( ; first <= last; ) { const int middle= (first + last) / 2; DBUG_ASSERT(middle >= 0); DBUG_ASSERT(middle < (int) m_count); const uint middle_id= m_element[middle].from()->number; if (middle_id == id) return &m_element[middle]; if (middle_id < id) first= middle + 1; else last= middle - 1; } return NULL; } bool insert(const Elem_st &elem) { DBUG_ASSERT(elem.from()->state & MY_CS_PRIMARY); if (m_count >= array_elements(m_element)) return true; m_element[m_count]= elem; m_count++; sort(); return false; } bool insert_or_replace(const Elem_st &elem) { DBUG_ASSERT(elem.from()->state & MY_CS_PRIMARY); const Elem_st *found= find_elem_by_charset_id(elem.from()->number); if (found) { const_cast<Elem_st*>(found)->set_to(elem.to()); return false; } return insert(elem); } public: void init() { m_count= 0; m_version= 0; } uint count() const { return m_count; } uint version() const { return m_version; } void set(const Charset_collation_map_st &rhs, uint version_increment) { uint version= m_version; *this= rhs; m_version= version + version_increment; } const Elem_st & operator[](uint pos) const { DBUG_ASSERT(pos < m_count); return m_element[pos]; } bool insert_or_replace(const class Lex_exact_charset &cs, const class Lex_extended_collation &cl, bool error_on_conflicting_duplicate); bool insert_or_replace(const LEX_CSTRING &cs, const LEX_CSTRING &cl, bool error_on_conflicting_duplicate, myf utf8_flag); CHARSET_INFO *get_collation_for_charset(Sql_used *used, CHARSET_INFO *cs) const { DBUG_ASSERT(cs->state & MY_CS_PRIMARY); const Elem_st *elem= find_elem_by_charset_id(cs->number); used->used|= Sql_used::CHARACTER_SET_COLLATIONS_USED; if (elem) return elem->to(); return cs; } size_t text_format_nbytes_needed() const { return (Elem_st::text_size_max() + 1/* for ',' */) * m_count; } size_t print(char *dst, size_t nbytes_available) const { const char *dst0= dst; const char *end= dst + nbytes_available; for (uint i= 0; i < m_count; i++) { if (Elem_st::text_size_max() + 1/* for ',' */ > (size_t) (end - dst)) break; if (i > 0) *dst++= ','; dst+= m_element[i].print(dst); } return dst - dst0; } static constexpr size_t binary_size_max() { return 1/*count*/ + 4 * array_elements(m_element); } size_t to_binary(char *dst) const { const char *dst0= dst; *dst++= (char) (uchar) m_count; for (uint i= 0; i < m_count; i++) { int2store(dst, (uint16) m_element[i].from()->number); dst+= 2; int2store(dst, (uint16) m_element[i].to()->number); dst+= 2; } return (size_t) (dst - dst0); } size_t from_binary(const char *src, size_t srclen) { const char *src0= src; init(); if (!srclen) return 0; // Empty uint count= (uchar) *src++; if (srclen < 1 + 4 * count) return 0; for (uint i= 0; i < count; i++, src+= 4) { CHARSET_INFO *cs, *cl; if (!(cs= get_charset(uint2korr(src), MYF(0))) || !(cl= get_charset(uint2korr(src + 2), MYF(0)))) { /* Unpacking from binary format happens on the slave side. If for some reasons the slave does not know about a character set or a collation, just skip the pair here. This pair might not even be needed. */ continue; } insert_or_replace(Elem(cs, cl)); } return src - src0; } bool from_text(const LEX_CSTRING &str, myf utf8_flag); }; #endif // LEX_CHARSET_COLLATIONS_INCLUDED
Upload File
Create Folder