1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842
|
/* Copyright (c) 2000, 2025, 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, version 2.0,
as published by the Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have 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 */
/**
@defgroup GROUP_PARSER Parser
@{
*/
#ifndef SQL_LEX_INCLUDED
#define SQL_LEX_INCLUDED
#include <string.h>
#include <sys/types.h> // TODO: replace with cstdint
#include <algorithm>
#include <cstring>
#include <functional>
#include <map>
#include <memory>
#include <new>
#include <string>
#include <utility>
#include "lex_string.h"
#include "m_ctype.h"
#include "m_string.h"
#include "map_helpers.h"
#include "mem_root_deque.h"
#include "memory_debugging.h"
#include "my_alloc.h" // Destroy_only
#include "my_base.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_inttypes.h" // TODO: replace with cstdint
#include "my_sqlcommand.h"
#include "my_sys.h"
#include "my_table_map.h"
#include "my_thread_local.h"
#include "mysql/components/services/bits/psi_bits.h"
#include "mysql/service_mysql_alloc.h" // my_free
#include "mysql_com.h"
#include "mysqld_error.h"
#include "prealloced_array.h" // Prealloced_array
#include "sql/dd/info_schema/table_stats.h" // dd::info_schema::Table_stati...
#include "sql/dd/info_schema/tablespace_stats.h" // dd::info_schema::Tablesp...
#include "sql/enum_query_type.h"
#include "sql/handler.h"
#include "sql/item.h" // Name_resolution_context
#include "sql/item_subselect.h" // Subquery_strategy
#include "sql/iterators/row_iterator.h"
#include "sql/join_optimizer/materialize_path_parameters.h"
#include "sql/key_spec.h" // KEY_CREATE_INFO
#include "sql/mdl.h"
#include "sql/mem_root_array.h" // Mem_root_array
#include "sql/parse_tree_node_base.h" // enum_parsing_context
#include "sql/parser_yystype.h"
#include "sql/query_options.h" // OPTION_NO_CONST_TABLES
#include "sql/query_term.h"
#include "sql/set_var.h"
#include "sql/sql_array.h"
#include "sql/sql_connect.h" // USER_RESOURCES
#include "sql/sql_const.h"
#include "sql/sql_data_change.h" // enum_duplicates
#include "sql/sql_error.h" // warn_on_deprecated_charset
#include "sql/sql_list.h"
#include "sql/sql_plugin_ref.h"
#include "sql/sql_servers.h" // Server_options
#include "sql/sql_udf.h" // Item_udftype
#include "sql/table.h" // Table_ref
#include "sql/thr_malloc.h"
#include "sql/trigger_def.h" // enum_trigger_action_time_type
#include "sql/visible_fields.h"
#include "sql_chars.h"
#include "sql_string.h"
#include "thr_lock.h" // thr_lock_type
#include "violite.h" // SSL_type
class Alter_info;
class Event_parse_data;
class Field;
class Item_cond;
class Item_func_get_system_var;
class Item_func_match;
class Item_func_set_user_var;
class Item_rollup_group_item;
class Item_rollup_sum_switcher;
class Item_sum;
class JOIN;
class Opt_hints_global;
class Opt_hints_qb;
class PT_subquery;
class PT_with_clause;
class Parse_tree_root;
class Protocol;
class Query_result;
class Query_result_interceptor;
class Query_result_union;
class Query_block;
class Query_expression;
class Select_lex_visitor;
class Sql_cmd;
class THD;
class Value_generator;
class Window;
class partition_info;
class sp_head;
class sp_name;
class sp_pcontext;
struct LEX;
struct NESTED_JOIN;
struct PSI_digest_locker;
struct sql_digest_state;
union Lexer_yystype;
struct Lifted_fields_map;
const size_t INITIAL_LEX_PLUGIN_LIST_SIZE = 16;
constexpr const int MAX_SELECT_NESTING{sizeof(nesting_map) * 8 - 1};
/*
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();
/*
If we encounter a diagnostics statement (GET DIAGNOSTICS, or e.g.
the old SHOW WARNINGS|ERRORS, or "diagnostics variables" such as
@@warning_count | @@error_count, we'll set some hints so this
information is not lost. DA_KEEP_UNSPECIFIED is used in LEX constructor to
avoid leaving variables uninitialized.
*/
enum enum_keep_diagnostics {
DA_KEEP_NOTHING = 0, /**< keep nothing */
DA_KEEP_DIAGNOSTICS, /**< keep the diagnostics area */
DA_KEEP_COUNTS, /**< keep \@warning_count / \@error_count */
DA_KEEP_PARSE_ERROR, /**< keep diagnostics area after parse error */
DA_KEEP_UNSPECIFIED /**< keep semantics is unspecified */
};
enum enum_sp_suid_behaviour {
SP_IS_DEFAULT_SUID = 0,
SP_IS_NOT_SUID,
SP_IS_SUID
};
enum enum_sp_data_access {
SP_DEFAULT_ACCESS = 0,
SP_CONTAINS_SQL,
SP_NO_SQL,
SP_READS_SQL_DATA,
SP_MODIFIES_SQL_DATA
};
/**
enum_sp_type defines type codes of stored programs.
@note these codes are used when dealing with the mysql.routines system table,
so they must not be changed.
@note the following macros were used previously for the same purpose. Now they
are used for ACL only.
*/
enum class enum_sp_type {
FUNCTION = 1,
PROCEDURE,
TRIGGER,
EVENT,
/*
Must always be the last one.
Denotes an error condition.
*/
INVALID_SP_TYPE
};
inline enum_sp_type to_sp_type(longlong val) {
if (val >= static_cast<longlong>(enum_sp_type::FUNCTION) &&
val < static_cast<longlong>(enum_sp_type::INVALID_SP_TYPE))
return static_cast<enum_sp_type>(val);
else
return enum_sp_type::INVALID_SP_TYPE;
}
inline longlong to_longlong(enum_sp_type val) {
return static_cast<longlong>(val);
}
inline uint to_uint(enum_sp_type val) { return static_cast<uint>(val); }
/*
Values for the type enum. This reflects the order of the enum declaration
in the CREATE TABLE command. These values are used to enumerate object types
for the ACL statements.
These values were also used for enumerating stored program types. However, now
enum_sp_type should be used for that instead of them.
*/
#define TYPE_ENUM_FUNCTION 1
#define TYPE_ENUM_PROCEDURE 2
#define TYPE_ENUM_TRIGGER 3
#define TYPE_ENUM_PROXY 4
enum class Acl_type {
TABLE = 0,
FUNCTION = TYPE_ENUM_FUNCTION,
PROCEDURE = TYPE_ENUM_PROCEDURE,
};
const LEX_CSTRING sp_data_access_name[] = {
{STRING_WITH_LEN("")},
{STRING_WITH_LEN("CONTAINS SQL")},
{STRING_WITH_LEN("NO SQL")},
{STRING_WITH_LEN("READS SQL DATA")},
{STRING_WITH_LEN("MODIFIES SQL DATA")}};
enum class enum_view_create_mode {
VIEW_CREATE_NEW, // check that there are not such VIEW/table
VIEW_ALTER, // check that VIEW with such name exists
VIEW_CREATE_OR_REPLACE // check only that there are not such table
};
enum class enum_alter_user_attribute {
ALTER_USER_COMMENT_NOT_USED, // No user metadata ALTER in the AST
ALTER_USER_COMMENT, // A text comment is expected
ALTER_USER_ATTRIBUTE // A JSON object is expected
};
/* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 0x01
#define TL_OPTION_IGNORE_LEAVES 0x02
#define TL_OPTION_ALIAS 0x04
/* Structure for db & table in sql_yacc */
class Table_function;
class Table_ident {
public:
LEX_CSTRING db;
LEX_CSTRING table;
Query_expression *sel;
Table_function *table_function;
Table_ident(Protocol *protocol, const LEX_CSTRING &db_arg,
const LEX_CSTRING &table_arg, bool force);
Table_ident(const LEX_CSTRING &db_arg, const LEX_CSTRING &table_arg)
: db(db_arg), table(table_arg), sel(nullptr), table_function(nullptr) {}
Table_ident(const LEX_CSTRING &table_arg)
: table(table_arg), sel(nullptr), table_function(nullptr) {
db = NULL_CSTR;
}
/**
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.
*/
Table_ident(Query_expression *s) : sel(s), table_function(nullptr) {
db = EMPTY_CSTR; /* a subject to casedn_str */
table = EMPTY_CSTR;
}
/*
This constructor is used only for the case when we create a table function.
It has no name and doesn't belong to any database as it exists only
during query execution. Later, if there was an alias specified for the
table, it will be set by add_table_to_list.
*/
Table_ident(LEX_CSTRING &table_arg, Table_function *table_func_arg)
: table(table_arg), sel(nullptr), table_function(table_func_arg) {
/* We must have a table name here as this is used with add_table_to_list */
db = EMPTY_CSTR; /* a subject to casedn_str */
}
// True if we can tell from syntax that this is a table function.
bool is_table_function() const { return (table_function != nullptr); }
// True if we can tell from syntax that this is an unnamed derived table.
bool is_derived_table() const { return sel; }
void change_db(const char *db_name) {
db.str = db_name;
db.length = strlen(db_name);
}
};
using List_item = mem_root_deque<Item *>;
using Group_list_ptrs = Mem_root_array<ORDER *>;
/**
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 {
/*
The array of IGNORE_SERVER_IDS has a preallocation, and is not expected
to grow to any significant size, so no instrumentation.
*/
LEX_MASTER_INFO() : repl_ignore_server_ids(PSI_NOT_INSTRUMENTED) {
initialize();
}
char *host, *user, *password, *log_file_name, *bind_addr, *network_namespace;
uint port, connect_retry;
float heartbeat_period;
int sql_delay;
ulonglong pos;
ulong server_id, retry_count;
char *gtid;
char *view_id;
const char *channel; // identifier similar to database name
enum {
UNTIL_SQL_BEFORE_GTIDS = 0,
UNTIL_SQL_AFTER_GTIDS
} gtid_until_condition;
bool until_after_gaps;
bool slave_until;
bool for_channel;
/*
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,
retry_count_opt, auto_position, port_opt, get_public_key,
m_source_connection_auto_failover, m_gtid_only;
char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
char *ssl_crl, *ssl_crlpath, *tls_version;
/*
Ciphersuites used for TLS 1.3 communication with the master server.
*/
enum enum_tls_ciphersuites {
UNSPECIFIED = 0,
SPECIFIED_NULL,
SPECIFIED_STRING
};
enum enum_tls_ciphersuites tls_ciphersuites;
char *tls_ciphersuites_string;
char *public_key_path;
char *relay_log_name;
ulong relay_log_pos;
char *compression_algorithm;
uint zstd_compression_level;
Prealloced_array<ulong, 2> repl_ignore_server_ids;
/**
Flag that is set to `true` whenever `PRIVILEGE_CHECKS_USER` is set to `NULL`
as a part of a `CHANGE MASTER TO` statement.
*/
bool privilege_checks_none;
/**
Username and hostname parts of the `PRIVILEGE_CHECKS_USER`, when it's set to
a user.
*/
const char *privilege_checks_username, *privilege_checks_hostname;
/**
Flag indicating if row format should be enforced for this channel event
stream.
*/
int require_row_format;
/**
Identifies what is the slave policy on primary keys in tables.
If set to STREAM it just replicates the value of sql_require_primary_key.
If set to ON it fails when the source tries to replicate a table creation
or alter operation that does not have a primary key.
If set to OFF it does not enforce any policies on the channel for primary
keys.
*/
enum {
LEX_MI_PK_CHECK_UNCHANGED = 0,
LEX_MI_PK_CHECK_STREAM = 1,
LEX_MI_PK_CHECK_ON = 2,
LEX_MI_PK_CHECK_OFF = 3,
LEX_MI_PK_CHECK_GENERATE = 4
} require_table_primary_key_check;
enum {
LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED = 0,
LEX_MI_ANONYMOUS_TO_GTID_OFF,
LEX_MI_ANONYMOUS_TO_GTID_LOCAL,
LEX_MI_ANONYMOUS_TO_GTID_UUID
} assign_gtids_to_anonymous_transactions_type;
const char *assign_gtids_to_anonymous_transactions_manual_uuid{nullptr};
/// Initializes everything to zero/NULL/empty.
void initialize();
/// Sets all fields to their "unspecified" value.
void set_unspecified();
private:
// Not copyable or assignable.
LEX_MASTER_INFO(const LEX_MASTER_INFO &);
LEX_MASTER_INFO &operator=(const LEX_MASTER_INFO &);
};
struct LEX_RESET_SLAVE {
bool all;
};
enum sub_select_type {
UNSPECIFIED_TYPE,
GLOBAL_OPTIONS_TYPE,
DERIVED_TABLE_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)
/* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */
class Index_hint {
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(const char *str, uint length) {
key_name.str = str;
key_name.length = length;
}
void print(const THD *thd, String *str);
};
/*
Class Query_expression represents a query expression.
Class Query_block represents a query block.
In addition to what is explained below, the query block(s) of a query
expression is contained in a tree expressing the nesting of set operations,
cf. query_term.h
A query expression contains one or more query blocks (more than one means
that the query expression contains one or more set operations - UNION,
INTERSECT or EXCEPT - unless the query blocks are used to describe
subqueries). These classes are connected as follows: both classes have a
master, a slave, a next and a prev field. For class Query_block, master and
slave connect to objects of type Query_expression, whereas for class
Query_expression, they connect to Query_block. master is pointer to outer
node. slave is pointer to the first inner node.
neighbors are two Query_block or Query_expression objects on
the same level.
The structures are linked with the following pointers:
- list of neighbors (next/prev) (prev of first element point to slave
pointer of outer structure)
- For Query_block, this is a list of query blocks.
- For Query_expression, this is a list of subqueries.
- pointer to outer node (master), which is
If this is Query_expression
- pointer to outer query_block.
If this is Query_block
- pointer to outer Query_expression.
- pointer to inner objects (slave), which is either:
If this is an Query_expression:
- first query block that belong to this query expression.
If this is an Query_block
- first query expression that belong to this query block (subqueries).
- list of all Query_block objects (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.
In addition to the above mentioned link, the query's tree structure is
represented by the member m_query_term, see query_term.h
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
select1 select2 select3
|^^ |^
s||| ||master
l||| |+---------------------------------+
a||| +---------------------------------+|
v|||master slave ||
e||+-------------------------+ ||
V| neighbor | V|
unit1.1<+==================>unit1.2 unit2.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
select1 select2 select3
in the above picture)
main unit
|^^^
||||
||||
|||+------------------------------+
||+--------------+ |
slave||master | |
V| neighbor | neighbor |
select1<========>select2<========>select3
list of all query_block 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
*/
/**
This class represents a query expression (one query block or
several query blocks combined with UNION).
*/
class Query_expression {
/**
Intrusive double-linked list of all query expressions
immediately contained within the same query block.
*/
Query_expression *next;
Query_expression **prev;
/**
The query block wherein this query expression is contained,
NULL if the query block is the outer-most one.
*/
Query_block *master;
/// The first query block in this query expression.
Query_block *slave;
// The query set operation structure, see doc for Query_term.
Query_term *m_query_term{nullptr};
public:
/// Getter for m_query_term, q.v.
Query_term *query_term() const { return m_query_term; }
/// Setter for m_query_term, q.v.
void set_query_term(Query_term *qt) { m_query_term = qt; }
/// Convenience method to avoid down casting, i.e. interpret m_query_term
/// as a Query_term_set_op.
/// @retval a non-null node iff !is_simple
/// @retval nullptr if is_simple() holds.
Query_term_set_op *set_operation() const {
return is_simple() ? nullptr : down_cast<Query_term_set_op *>(m_query_term);
}
/// Return the query block iff !is_simple() holds
Query_block *non_simple_result_query_block() const {
if (is_simple())
return nullptr;
else
return m_query_term->query_block();
}
bool is_leaf_block(Query_block *qb);
Query_term *find_blocks_query_term(const Query_block *qb) const {
for (auto qt : query_terms<>()) {
if (qt->query_block() == qb) return qt;
}
return nullptr;
}
/**
Return iterator object over query terms rooted in m_query_term,
using either post order visiting (default) or pre order,
optionally skipping leaf nodes (query blocks corresponding to SELECTs or
table constructors). By default, we visit all nodes.
Usage: for (auto qt : query_terms<..>() { ... }
E.g.
for (auto qt : query_terms<>()) { } Visit all nodes, post order
for (auto qt : query_terms<QTC_PRE_ORDER, false>()) { }
Skip leaves, pre order
@tparam order == QTC_POST_ORDER if post order traversal is desired;default
== QTC_PRE_ORDER pre-order traversal
@tparam visit_leaves == VL_VISIT_LEAVES: if we want the traversal to include
leaf nodes i.e. the SELECTs or table constructors
== VL_SKIP_LEAVES: leaves will be skipped
@returns iterator object
*/
template <Visit_order order = QTC_POST_ORDER,
Visit_leaves visit_leaves = VL_VISIT_LEAVES>
Query_terms<order, visit_leaves> query_terms() const {
return Query_terms<order, visit_leaves>(m_query_term);
}
/**
Return the Query_block of the last query term in a n-ary set
operation that is the right side of the last DISTINCT set operation in that
n_ary set operation:
E.e. for
A UNION B UNION ALL C,
B's block will be returned. If no DISTINCT is present or not a set
operation, return nullptr.
@returns query block of last distinct right operand
*/
Query_block *last_distinct() const {
auto const setop = down_cast<Query_term_set_op *>(m_query_term);
if (setop->m_last_distinct > 0)
return setop->m_children[setop->m_last_distinct]->query_block();
else
return nullptr;
}
bool has_top_level_distinct() const {
if (is_simple()) return false;
return down_cast<Query_term_set_op *>(m_query_term)->m_last_distinct > 0;
}
private:
/**
Marker for subqueries in WHERE, HAVING, ORDER BY, GROUP BY and
SELECT item lists.
Must be read/written when holding LOCK_query_plan.
See Item_subselect::explain_subquery_checker
*/
enum_parsing_context explain_marker;
bool prepared; ///< All query blocks in query expression are prepared
bool optimized; ///< All query blocks in query expression are optimized
bool executed; ///< Query expression has been executed
///< Explain mode: query expression refers stored function
bool m_has_stored_program{false};
/// Object to which the result for this query expression is sent.
/// Not used if we materialize directly into a parent query expression's
/// result table (see optimize()).
Query_result *m_query_result;
/**
An iterator you can read from to get all records for this query.
May be nullptr even after create_access_paths(), or in the case of an
unfinished materialization (see optimize()).
*/
unique_ptr_destroy_only<RowIterator> m_root_iterator;
AccessPath *m_root_access_path = nullptr;
/**
If there is an unfinished materialization (see optimize()),
contains one element for each query block in this query expression.
*/
Mem_root_array<MaterializePathParameters::QueryBlock>
m_query_blocks_to_materialize;
private:
/**
Convert the executor structures to a set of access paths, storing the result
in m_root_access_path.
*/
void create_access_paths(THD *thd);
public:
/**
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT
UNCACHEABLE_RAND
UNCACHEABLE_SIDEEFFECT
*/
uint8 uncacheable;
explicit Query_expression(enum_parsing_context parsing_context);
/// @return true for a query expression without UNION/INTERSECT/EXCEPT or
/// multi-level ORDER, i.e. we have a "simple table".
bool is_simple() const { return m_query_term->term_type() == QT_QUERY_BLOCK; }
bool has_stored_program() const { return m_has_stored_program; }
/// Values for Query_expression::cleaned
enum enum_clean_state {
UC_DIRTY, ///< Unit isn't cleaned
UC_PART_CLEAN, ///< Unit were cleaned, except JOIN and JOIN_TABs were
///< kept for possible EXPLAIN
UC_CLEAN ///< Unit completely cleaned, all underlying JOINs were
///< freed
};
enum_clean_state cleaned; ///< cleanliness state
private:
/*
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
All hidden items are stripped away from this list.
*/
mem_root_deque<Item *> types;
public:
/**
Return the query block holding the top level ORDER BY, LIMIT and OFFSET.
If the query is not a set operation (UNION, INTERSECT or EXCEPT, and the
query expression has no multi-level ORDER BY/LIMIT, this represents the
single query block of the query itself, cf. documentation for class
Query_term.
@return query block containing the global parameters
*/
inline Query_block *global_parameters() const {
return query_term()->query_block();
}
/* LIMIT clause runtime counters */
ha_rows select_limit_cnt, offset_limit_cnt;
/// Points to subquery if this query expression is used in one, otherwise NULL
Item_subselect *item;
/**
The WITH clause which is the first part of this query expression. NULL if
none.
*/
PT_with_clause *m_with_clause;
/**
If this query expression is underlying of a derived table, the derived
table. NULL if none.
*/
Table_ref *derived_table;
/**
First query block (in this UNION) which references the CTE.
NULL if not the query expression of a recursive CTE.
*/
Query_block *first_recursive;
/**
If 'this' is body of lateral derived table:
map of tables in the same FROM clause as this derived table, and to which
the derived table's body makes references.
In pre-resolution stages, this is OUTER_REF_TABLE_BIT, just to indicate
that this has LATERAL; after resolution, which has found references in the
body, this is the proper map (with no PSEUDO_TABLE_BITS anymore).
*/
table_map m_lateral_deps;
/**
This query expression represents a scalar subquery and we need a run-time
check that the cardinality doesn't exceed 1.
*/
bool m_reject_multiple_rows{false};
/// @return true if query expression can be merged into an outer query
bool is_mergeable() const;
/// @return true if query expression is recommended to be merged
bool merge_heuristic(const LEX *lex) const;
/// @return the query block this query expression belongs to as subquery
Query_block *outer_query_block() const { return master; }
/// @return the first query block inside this query expression
Query_block *first_query_block() const { return slave; }
/// @return the next query expression within same query block (next subquery)
Query_expression *next_query_expression() const { return next; }
/// @return the query result object in use for this query expression
Query_result *query_result() const { return m_query_result; }
RowIterator *root_iterator() const { return m_root_iterator.get(); }
unique_ptr_destroy_only<RowIterator> release_root_iterator() {
return std::move(m_root_iterator);
}
AccessPath *root_access_path() const { return m_root_access_path; }
// Asks each query block to switch to an access path with in2exists
// conditions removed (if they were ever added).
// See JOIN::change_to_access_path_without_in2exists().
void change_to_access_path_without_in2exists(THD *thd);
void clear_root_access_path() {
m_root_access_path = nullptr;
m_root_iterator.reset();
}
/**
Ensures that there are iterators created for the access paths created
by optimize(), even if it was called with create_access_paths = false.
If there are already iterators, it is a no-op. optimize() must have
been called earlier.
The use case for this is if we have a query block that's not top-level,
but we figure out after the fact that we wanted to run it anyway.
The typical case would be that we notice that the query block can return
at most one row (a so-called const table), and want to run it during
optimization.
*/
bool force_create_iterators(THD *thd);
/// See optimize().
bool unfinished_materialization() const {
return !m_query_blocks_to_materialize.empty();
}
/// See optimize().
Mem_root_array<MaterializePathParameters::QueryBlock>
release_query_blocks_to_materialize() {
return std::move(m_query_blocks_to_materialize);
}
/// Set new query result object for this query expression
void set_query_result(Query_result *res) { m_query_result = res; }
/**
Whether there is a chance that optimize() is capable of materializing
directly into a result table if given one. Note that even if this function
returns true, optimize() can choose later not to do so, since it depends
on information (in particular, whether the query blocks can run under
the iterator executor or not) that is not available before optimize time.
TODO(sgunders): Now that all query blocks can run under the iterator
executor, the above may no longer be true. This needs investigation.
*/
bool can_materialize_directly_into_result() const;
bool prepare(THD *thd, Query_result *result,
mem_root_deque<Item *> *insert_field_list,
ulonglong added_options, ulonglong removed_options);
/**
If and only if materialize_destination is non-nullptr, it means that the
caller intends to materialize our result into the given table. If it is
advantageous (in particular, if this query expression is a UNION DISTINCT),
optimize() will not create an iterator by itself, but rather do an
unfinished materialize. This means that it will collect iterators for
all the query blocks and prepare them for materializing into the given
table, but not actually create a root iterator for this query expression;
the caller is responsible for calling release_query_blocks_to_materialize()
and creating the iterator itself.
Even if materialize_destination is non-nullptr, this function may choose
to make a regular iterator. The caller is responsible for checking
unfinished_materialization() if it has given a non-nullptr table.
@param thd Thread handle.
@param materialize_destination What table to try to materialize into,
or nullptr if the caller does not intend to materialize the result.
@param create_iterators If false, only access paths are created,
not iterators. Only top level query blocks (these that we are to call
exec() on) should have iterators. See also force_create_iterators().
@param finalize_access_paths Relevant for the hypergraph optimizer only.
If false, the given access paths will _not_ be finalized, so you cannot
create iterators from it before finalize() is called (see
FinalizePlanForQueryBlock()), and create_iterators must also be false.
This is relevant only if you are potentially optimizing multiple times
(see change_to_access_path_without_in2exists()), since you are only
allowed to finalize a query block once. "Fake" query blocks (see
query_term.h) are always finalized.
*/
bool optimize(THD *thd, TABLE *materialize_destination, bool create_iterators,
bool finalize_access_paths);
/**
For any non-finalized query block, finalize it so that we are allowed to
create iterators. Must be called after the final access path is chosen
(ie., after any calls to change_to_access_path_without_in2exists()).
*/
bool finalize(THD *thd);
/**
Do everything that would be needed before running Init() on the root
iterator. In particular, clear out data from previous execution iterations,
if needed.
*/
bool ClearForExecution();
bool ExecuteIteratorQuery(THD *thd);
bool execute(THD *thd);
bool explain(THD *explain_thd, const THD *query_thd);
bool explain_query_term(THD *explain_thd, const THD *query_thd,
Query_term *qt);
void cleanup(bool full);
/**
Destroy contained objects, in particular temporary tables which may
have their own mem_roots.
*/
void destroy();
void print(const THD *thd, String *str, enum_query_type query_type);
bool accept(Select_lex_visitor *visitor);
/**
Create a block to be used for ORDERING and LIMIT/OFFSET processing of a
query term, which isn't itself a query specification or table value
constructor. Such blocks are not included in the list starting in
Query_Expression::first_query_block, and Query_block::next_query_block().
They blocks are accessed via Query_term::query_block().
@param term the term on behalf of which we are making a post processing
block
@returns a query block
*/
Query_block *create_post_processing_block(Query_term_set_op *term);
bool prepare_query_term(THD *thd, Query_term *qts,
Query_result *common_result, ulonglong added_options,
ulonglong create_options, int level,
Mem_root_array<bool> &nullable);
void set_prepared() {
assert(!is_prepared());
prepared = true;
}
void set_optimized() {
assert(is_prepared() && !is_optimized());
optimized = true;
}
void set_executed() {
// assert(is_prepared() && is_optimized() && !is_executed());
assert(is_prepared() && is_optimized());
executed = true;
}
/// Reset this query expression for repeated evaluation within same execution
void reset_executed() {
assert(is_prepared() && is_optimized());
executed = false;
}
/// Clear execution state, needed before new execution of prepared statement
void clear_execution() {
// Cannot be enforced when called from Prepared_statement::execute():
// assert(is_prepared());
optimized = false;
executed = false;
cleaned = UC_DIRTY;
}
/// Check state of preparation of the contained query expression.
bool is_prepared() const { return prepared; }
/// Check state of optimization of the contained query expression.
bool is_optimized() const { return optimized; }
/**
Check state of execution of the contained query expression.
Should not be used to check the state of a complete statement, use
LEX::is_exec_completed() instead.
*/
bool is_executed() const { return executed; }
bool change_query_result(THD *thd, Query_result_interceptor *result,
Query_result_interceptor *old_result);
bool set_limit(THD *thd, Query_block *provider);
bool has_any_limit() const;
inline bool is_union() const;
inline bool is_set_operation() const;
/// Include a query expression below a query block.
void include_down(LEX *lex, Query_block *outer);
/// Exclude this unit and immediately contained query_block objects
void exclude_level();
/// Exclude subtree of current unit from tree of SELECTs
void exclude_tree();
/// Renumber query blocks of a query expression according to supplied LEX
void renumber_selects(LEX *lex);
void restore_cmd_properties();
bool save_cmd_properties(THD *thd);
friend class Query_block;
mem_root_deque<Item *> *get_unit_column_types();
mem_root_deque<Item *> *get_field_list();
size_t num_visible_fields() const;
// If we are doing a query with global LIMIT, we need somewhere to store the
// record count for FOUND_ROWS(). It can't be in any of the JOINs, since
// they may have their own LimitOffsetIterators, which will write to
// join->send_records whenever there is an OFFSET. Thus, we'll keep it here
// instead.
ha_rows send_records;
enum_parsing_context get_explain_marker(const THD *thd) const;
void set_explain_marker(THD *thd, enum_parsing_context m);
void set_explain_marker_from(THD *thd, const Query_expression *u);
#ifndef NDEBUG
/**
Asserts that none of {this unit and its children units} is fully cleaned
up.
*/
void assert_not_fully_clean();
#else
void assert_not_fully_clean() {}
#endif
void invalidate();
bool is_recursive() const { return first_recursive != nullptr; }
bool check_materialized_derived_query_blocks(THD *thd);
bool clear_correlated_query_blocks();
void fix_after_pullout(Query_block *parent_query_block,
Query_block *removed_query_block);
/**
If unit is a subquery, which forms an object of the upper level (an
Item_subselect, a derived Table_ref), adds to this object a map
of tables of the upper level which the unit references.
*/
void accumulate_used_tables(table_map map);
/**
If unit is a subquery, which forms an object of the upper level (an
Item_subselect, a derived Table_ref), returns the place of this object
in the upper level query block.
*/
enum_parsing_context place() const;
bool walk(Item_processor processor, enum_walk walk, uchar *arg);
/*
An exception: this is the only function that needs to adjust
explain_marker.
*/
friend bool parse_view_definition(THD *thd, Table_ref *view_ref);
};
typedef Bounds_checked_array<Item *> Ref_item_array;
class Semijoin_decorrelation;
/**
Query_block type enum
*/
enum class enum_explain_type {
EXPLAIN_NONE = 0,
EXPLAIN_PRIMARY,
EXPLAIN_SIMPLE,
EXPLAIN_DERIVED,
EXPLAIN_SUBQUERY,
EXPLAIN_UNION,
EXPLAIN_INTERSECT,
EXPLAIN_EXCEPT,
EXPLAIN_UNION_RESULT,
EXPLAIN_INTERSECT_RESULT,
EXPLAIN_EXCEPT_RESULT,
EXPLAIN_UNARY_RESULT,
EXPLAIN_MATERIALIZED,
// Total:
EXPLAIN_total ///< fake type, total number of all valid types
// Don't insert new types below this line!
};
/**
This class represents a query block, aka a query specification, which is
a query consisting of a SELECT keyword, followed by a table list,
optionally followed by a WHERE clause, a GROUP BY, etc.
*/
class Query_block : public Query_term {
public:
/**
@note the group_by and order_by lists below will probably be added to the
constructor when the parser is converted into a true bottom-up design.
//SQL_I_LIST<ORDER> *group_by, SQL_I_LIST<ORDER> order_by
*/
Query_block(MEM_ROOT *mem_root, Item *where, Item *having);
/// Query_term methods overridden
void debugPrint(int level, std::ostringstream &buf) const override;
/// Minion of debugPrint
void qbPrint(int level, std::ostringstream &buf) const;
Query_term_type term_type() const override { return QT_QUERY_BLOCK; }
const char *operator_string() const override { return "query_block"; }
Query_block *query_block() const override {
return const_cast<Query_block *>(this);
}
void label_children() override {}
void destroy_tree() override { m_parent = nullptr; }
bool open_result_tables(THD *, int) override;
/// end of overridden methods from Query_term
bool absorb_limit_of(Query_block *block);
Item *where_cond() const { return m_where_cond; }
Item **where_cond_ref() { return &m_where_cond; }
void set_where_cond(Item *cond) { m_where_cond = cond; }
Item *having_cond() const { return m_having_cond; }
Item **having_cond_ref() { return &m_having_cond; }
void set_having_cond(Item *cond) { m_having_cond = cond; }
void set_query_result(Query_result *result) { m_query_result = result; }
Query_result *query_result() const { return m_query_result; }
bool change_query_result(THD *thd, Query_result_interceptor *new_result,
Query_result_interceptor *old_result);
/// Set base options for a query block (and active options too)
void set_base_options(ulonglong options_arg) {
DBUG_EXECUTE_IF("no_const_tables", options_arg |= OPTION_NO_CONST_TABLES;);
// Make sure we do not overwrite options by accident
assert(m_base_options == 0 && m_active_options == 0);
m_base_options = options_arg;
m_active_options = options_arg;
}
/// Add base options to a query block, also update active options
void add_base_options(ulonglong options) {
assert(first_execution);
m_base_options |= options;
m_active_options |= options;
}
/**
Remove base options from a query block.
Active options are also updated, and we assume here that "extra" options
cannot override removed base options.
*/
void remove_base_options(ulonglong options) {
assert(first_execution);
m_base_options &= ~options;
m_active_options &= ~options;
}
/// Make active options from base options, supplied options and environment:
void make_active_options(ulonglong added_options, ulonglong removed_options);
/// Adjust the active option set
void add_active_options(ulonglong options) { m_active_options |= options; }
/// @return the active query options
ulonglong active_options() const { return m_active_options; }
/**
Set associated tables as read_only, ie. they cannot be inserted into,
updated or deleted from during this statement.
Commonly used for query blocks that are part of derived tables or
views that are materialized.
*/
void set_tables_readonly() {
// Set all referenced base tables as read only.
for (Table_ref *tr = leaf_tables; tr != nullptr; tr = tr->next_leaf)
tr->set_readonly();
}
/// @returns a map of all tables references in the query block
table_map all_tables_map() const { return (1ULL << leaf_table_count) - 1; }
bool remove_aggregates(THD *thd, Query_block *select);
Query_expression *master_query_expression() const { return master; }
Query_expression *first_inner_query_expression() const { return slave; }
Query_block *outer_query_block() const { return master->outer_query_block(); }
Query_block *next_query_block() const { return next; }
Table_ref *find_table_by_name(const Table_ident *ident);
Query_block *next_select_in_list() const { return link_next; }
void mark_as_dependent(Query_block *last, bool aggregate);
/// @returns true if query block references any tables
bool has_tables() const { return m_table_list.elements != 0; }
/// @return true if query block is explicitly grouped (non-empty GROUP BY)
bool is_explicitly_grouped() const { return group_list.elements != 0; }
/**
@return true if this query block is implicitly grouped, ie it is not
explicitly grouped but contains references to set functions.
The query will return max. 1 row (@see also is_single_grouped()).
*/
bool is_implicitly_grouped() const {
return m_agg_func_used && group_list.elements == 0;
}
/**
@return true if this query block is explicitly or implicitly grouped.
@note a query with DISTINCT is not considered to be aggregated.
@note in standard SQL, a query with HAVING is defined as grouped, however
MySQL allows HAVING without any aggregation to be the same as WHERE.
*/
bool is_grouped() const { return group_list.elements > 0 || m_agg_func_used; }
/// @return true if this query block contains DISTINCT at start of select list
bool is_distinct() const { return active_options() & SELECT_DISTINCT; }
/**
@return true if this query block contains an ORDER BY clause.
@note returns false if ORDER BY has been eliminated, e.g if the query
can return max. 1 row.
*/
bool is_ordered() const { return order_list.elements > 0; }
/**
Based on the structure of the query at resolution time, it is possible to
conclude that DISTINCT is useless and remove it.
This is the case if:
- all GROUP BY expressions are in SELECT list, so resulting group rows are
distinct,
- and ROLLUP is not specified, so it adds no row for NULLs.
@returns true if we can remove DISTINCT.
@todo could refine this to if ROLLUP were specified and all GROUP
expressions were non-nullable, because ROLLUP then adds only NULL values.
Currently, ROLLUP+DISTINCT is rejected because executor cannot handle
it in all cases.
*/
bool can_skip_distinct() const {
return is_grouped() && hidden_group_field_count == 0 &&
olap == UNSPECIFIED_OLAP_TYPE;
}
/// @return true if this query block has a LIMIT clause
bool has_limit() const { return select_limit != nullptr; }
/// @return true if query block references full-text functions
bool has_ft_funcs() const { return ftfunc_list->elements > 0; }
/// @returns true if query block is a recursive member of a recursive unit
bool is_recursive() const { return recursive_reference != nullptr; }
/**
Finds a group expression matching the given item, or nullptr if
none. When there are multiple candidates, ones that match in name are
given priority (such that “a AS c GROUP BY a,b,c” resolves to c, not a);
if there is still a tie, the leftmost is given priority.
@param item The item to search for.
@param [out] rollup_level If not nullptr, will be set to the group
expression's index (0-based).
*/
ORDER *find_in_group_list(Item *item, int *rollup_level) const;
int group_list_size() const;
/// @returns true if query block contains windows
bool has_windows() const { return m_windows.elements > 0; }
/// @returns true if query block contains window functions
bool has_wfs();
void invalidate();
uint get_in_sum_expr() const { return in_sum_expr; }
bool add_item_to_list(Item *item);
bool add_ftfunc_to_list(Item_func_match *func);
Table_ref *add_table_to_list(THD *thd, Table_ident *table, const char *alias,
ulong table_options,
thr_lock_type flags = TL_UNLOCK,
enum_mdl_type mdl_type = MDL_SHARED_READ,
List<Index_hint> *hints = nullptr,
List<String> *partition_names = nullptr,
LEX_STRING *option = nullptr,
Parse_context *pc = nullptr);
/**
Add item to the hidden part of select list
@param item item to add
@return Pointer to reference of the added item
*/
Item **add_hidden_item(Item *item);
/// Remove hidden items from select list
void remove_hidden_items();
Table_ref *get_table_list() const { return m_table_list.first; }
bool init_nested_join(THD *thd);
Table_ref *end_nested_join();
Table_ref *nest_last_join(THD *thd, size_t table_cnt = 2);
bool add_joined_table(Table_ref *table);
mem_root_deque<Item *> *get_fields_list() { return &fields; }
/// Wrappers over fields / get_fields_list() that hide items where
/// item->hidden, meant for range-based for loops. See sql/visible_fields.h.
auto visible_fields() { return VisibleFields(fields); }
auto visible_fields() const { return VisibleFields(fields); }
/// Check privileges for views that are merged into query block
bool check_view_privileges(THD *thd, Access_bitmask want_privilege_first,
Access_bitmask want_privilege_next);
/// Check privileges for all columns referenced from query block
bool check_column_privileges(THD *thd);
/// Check privileges for column references in subqueries of a query block
bool check_privileges_for_subqueries(THD *thd);
/// Resolve and prepare information about tables for one query block
bool setup_tables(THD *thd, Table_ref *tables, bool select_insert);
/// Resolve OFFSET and LIMIT clauses
bool resolve_limits(THD *thd);
/// Resolve derived table, view, table function information for a query block
bool resolve_placeholder_tables(THD *thd, bool apply_semijoin);
/// Propagate exclusion from table uniqueness test into subqueries
void propagate_unique_test_exclusion();
/// Merge name resolution context objects of a subquery into its parent
void merge_contexts(Query_block *inner);
/// Merge derived table into query block
bool merge_derived(THD *thd, Table_ref *derived_table);
bool flatten_subqueries(THD *thd);
/**
Update available semijoin strategies for semijoin nests.
Available semijoin strategies needs to be updated on every execution since
optimizer_switch setting may have changed.
@param thd Pointer to THD object for session.
Used to access optimizer_switch
*/
void update_semijoin_strategies(THD *thd);
/**
Returns which subquery execution strategies can be used for this query
block.
@param thd Pointer to THD object for session.
Used to access optimizer_switch
@retval SUBQ_MATERIALIZATION Subquery Materialization should be used
@retval SUBQ_EXISTS In-to-exists execution should be used
@retval CANDIDATE_FOR_IN2EXISTS_OR_MAT A cost-based decision should be made
*/
Subquery_strategy subquery_strategy(const THD *thd) const;
/**
Returns whether semi-join is enabled for this query block
@see @c Opt_hints_qb::semijoin_enabled for details on how hints
affect this decision. If there are no hints for this query block,
optimizer_switch setting determines whether semi-join is used.
@param thd Pointer to THD object for session.
Used to access optimizer_switch
@return true if semijoin is enabled,
false otherwise
*/
bool semijoin_enabled(const THD *thd) const;
void set_sj_candidates(Mem_root_array<Item_exists_subselect *> *sj_cand) {
sj_candidates = sj_cand;
}
bool has_sj_candidates() const {
return sj_candidates != nullptr && !sj_candidates->empty();
}
/// Add full-text function elements from a list into this query block
bool add_ftfunc_list(List<Item_func_match> *ftfuncs);
void set_lock_for_table(const Lock_descriptor &descriptor, Table_ref *table);
void set_lock_for_tables(thr_lock_type lock_type);
inline void init_order() {
assert(order_list.elements == 0);
order_list.elements = 0;
order_list.first = nullptr;
order_list.next = &order_list.first;
}
/*
This method created for reiniting LEX in mysql_admin_table() and can be
used only if you are going remove all Query_block & units except belonger
to LEX (LEX::unit & LEX::select, for other purposes use
Query_expression::exclude_level()
*/
void cut_subtree() { slave = nullptr; }
bool test_limit();
/**
Get offset for LIMIT.
Evaluate offset item if necessary.
@return Number of rows to skip.
@todo Integrate better with Query_expression::set_limit()
*/
ha_rows get_offset(const THD *thd) const;
/**
Get limit.
Evaluate limit item if necessary.
@return Limit of rows in result.
@todo Integrate better with Query_expression::set_limit()
*/
ha_rows get_limit(const THD *thd) const;
/// Assign a default name resolution object for this query block.
bool set_context(Name_resolution_context *outer_context);
/// Setup the array containing references to base items
bool setup_base_ref_items(THD *thd);
void print(const THD *thd, String *str, enum_query_type query_type);
/**
Print detail of the Query_block object.
@param thd Thread handler
@param query_type Options to print out string output
@param[out] str String of output.
*/
void print_query_block(const THD *thd, String *str,
enum_query_type query_type);
/**
Print detail of the UPDATE statement.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_update(const THD *thd, String *str, enum_query_type query_type);
/**
Print detail of the DELETE statement.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_delete(const THD *thd, String *str, enum_query_type query_type);
/**
Print detail of the INSERT statement.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_insert(const THD *thd, String *str, enum_query_type query_type);
/**
Print detail of Hints.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_hints(const THD *thd, String *str, enum_query_type query_type);
/**
Print error.
@param thd Thread handler
@param[out] str String of output
@retval false If there is no error
@retval true else
*/
bool print_error(const THD *thd, String *str);
/**
Print select options.
@param[out] str String of output
*/
void print_select_options(String *str);
/**
Print UPDATE options.
@param[out] str String of output
*/
void print_update_options(String *str);
/**
Print DELETE options.
@param[out] str String of output
*/
void print_delete_options(String *str);
/**
Print INSERT options.
@param[out] str String of output
*/
void print_insert_options(String *str);
/**
Print list of tables.
@param thd Thread handler
@param[out] str String of output
@param table_list Table_ref object
@param query_type Options to print out string output
*/
void print_table_references(const THD *thd, String *str,
Table_ref *table_list,
enum_query_type query_type);
/**
Print list of items in Query_block object.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_item_list(const THD *thd, String *str, enum_query_type query_type);
/**
Print assignments list. Used in UPDATE and
INSERT ... ON DUPLICATE KEY UPDATE ...
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
@param fields List columns to be assigned.
@param values List of values.
*/
void print_update_list(const THD *thd, String *str,
enum_query_type query_type,
const mem_root_deque<Item *> &fields,
const mem_root_deque<Item *> &values);
/**
Print column list to be inserted into. Used in INSERT.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_insert_fields(const THD *thd, String *str,
enum_query_type query_type);
/**
Print list of values, used in INSERT and for general VALUES clause.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
@param values List of values
@param prefix Prefix to print before each row in value list
= nullptr: No prefix wanted
*/
void print_values(const THD *thd, String *str, enum_query_type query_type,
const mem_root_deque<mem_root_deque<Item *> *> &values,
const char *prefix);
/**
Print list of tables in FROM clause.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_from_clause(const THD *thd, String *str,
enum_query_type query_type);
/**
Print list of conditions in WHERE clause.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_where_cond(const THD *thd, String *str,
enum_query_type query_type);
/**
Print list of items in GROUP BY clause.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_group_by(const THD *thd, String *str, enum_query_type query_type);
/**
Print list of items in HAVING clause.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_having(const THD *thd, String *str, enum_query_type query_type);
/**
Print details of Windowing functions.
@param thd Thread handler
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_windows(const THD *thd, String *str, enum_query_type query_type);
/**
Print list of items in ORDER BY clause.
@param thd Thread handle
@param[out] str String of output
@param query_type Options to print out string output
*/
void print_order_by(const THD *thd, String *str,
enum_query_type query_type) const;
void print_limit(const THD *thd, String *str,
enum_query_type query_type) const;
bool save_properties(THD *thd);
/**
Accept function for SELECT and DELETE.
@param visitor Select_lex_visitor Object
*/
bool accept(Select_lex_visitor *visitor);
void prune_sj_exprs(Item_func_eq *item, mem_root_deque<Table_ref *> *nest);
/**
Cleanup this subtree (this Query_block and all nested Query_blockes and
Query_expressions).
@param full if false only partial cleanup is done, JOINs and JOIN_TABs are
kept to provide info for EXPLAIN CONNECTION; if true, complete cleanup is
done, all JOINs are freed.
*/
void cleanup(bool full) override;
/*
Recursively cleanup the join of this select lex and of all nested
select lexes. This is not a full cleanup.
*/
void cleanup_all_joins();
/**
Destroy contained objects, in particular temporary tables which may
have their own mem_roots.
*/
void destroy();
/// @return true when query block is not part of a set operation and is not a
/// parenthesized query expression.
bool is_simple_query_block() const {
return master_query_expression()->is_simple();
}
/**
@return true if query block is found during preparation to produce no data.
Notice that if query is implicitly grouped, an aggregation row will
still be returned.
*/
bool is_empty_query() const { return m_empty_query; }
/// Set query block as returning no data
/// @todo This may also be set when we have an always false WHERE clause
void set_empty_query() {
assert(join == nullptr);
m_empty_query = true;
}
/*
For MODE_ONLY_FULL_GROUP_BY we need to know if
this query block is the aggregation query of at least one aggregate
function.
*/
bool agg_func_used() const { return m_agg_func_used; }
bool json_agg_func_used() const { return m_json_agg_func_used; }
void set_agg_func_used(bool val) { m_agg_func_used = val; }
void set_json_agg_func_used(bool val) { m_json_agg_func_used = val; }
bool right_joins() const { return m_right_joins; }
void set_right_joins() { m_right_joins = true; }
/// Lookup for Query_block type
enum_explain_type type() const;
/// Lookup for a type string
const char *get_type_str() { return type_str[static_cast<int>(type())]; }
static const char *get_type_str(enum_explain_type type) {
return type_str[static_cast<int>(type)];
}
bool is_dependent() const { return uncacheable & UNCACHEABLE_DEPENDENT; }
bool is_cacheable() const { return !uncacheable; }
/// @returns true if this query block outputs at most one row.
bool source_table_is_one_row() const {
return (m_table_list.size() == 0 &&
(!is_table_value_constructor || row_value_list->size() == 1));
}
/// Include query block inside a query expression.
void include_down(LEX *lex, Query_expression *outer);
/// Include a query block next to another query block.
void include_neighbour(LEX *lex, Query_block *before);
/// Include query block inside a query expression, but do not link.
void include_standalone(Query_expression *sel);
/// Include query block into global list.
void include_in_global(Query_block **plink);
/// Include chain of query blocks into global list.
void include_chain_in_global(Query_block **start);
/// Renumber query blocks of contained query expressions
void renumber(LEX *lex);
/**
Does permanent transformations which are local to a query block (which do
not merge it to another block).
*/
bool apply_local_transforms(THD *thd, bool prune);
/// Pushes parts of the WHERE condition of this query block to materialized
/// derived tables.
bool push_conditions_to_derived_tables(THD *thd);
bool get_optimizable_conditions(THD *thd, Item **new_where,
Item **new_having);
bool validate_outermost_option(LEX *lex, const char *wrong_option) const;
bool validate_base_options(LEX *lex, ulonglong options) const;
bool walk(Item_processor processor, enum_walk walk, uchar *arg);
bool add_tables(THD *thd, const Mem_root_array<Table_ident *> *tables,
ulong table_options, thr_lock_type lock_type,
enum_mdl_type mdl_type);
bool resolve_rollup_wfs(THD *thd);
bool setup_conds(THD *thd);
bool prepare(THD *thd, mem_root_deque<Item *> *insert_field_list);
bool optimize(THD *thd, bool finalize_access_paths);
void reset_nj_counters(mem_root_deque<Table_ref *> *join_list = nullptr);
// If the query block has exactly one single visible field, returns it.
// If not, returns nullptr.
Item *single_visible_field() const;
size_t num_visible_fields() const;
// Whether the SELECT list is empty (hidden fields are ignored).
// Typically used to distinguish INSERT INTO ... SELECT queries
// from INSERT INTO ... VALUES queries.
bool field_list_is_empty() const;
/// Creates a clone for the given expression by re-parsing the
/// expression. Used in condition pushdown to derived tables.
Item *clone_expression(THD *thd, Item *item, Table_ref *derived_table);
/// Returns an expression from the select list of the query block
/// using the field's index in a derived table.
Item *get_derived_expr(uint expr_index);
MaterializePathParameters::QueryBlock setup_materialize_query_block(
AccessPath *childPath, TABLE *dst_table);
// ************************************************
// * Members (most of these should not be public) *
// ************************************************
size_t m_added_non_hidden_fields{0};
/**
All expressions needed after join and filtering, ie., select list,
group by list, having clause, window clause, order by clause,
including hidden fields.
Does not include join conditions nor where clause.
This should ideally be changed into Mem_root_array<Item *>, but
find_order_in_list() depends on pointer stability (it stores a pointer
to an element in referenced_by[]). Similarly, there are some instances
of thd->change_item_tree() that store pointers to elements in this list.
Because of this, adding or removing elements in the middle is not allowed;
std::deque guarantees pointer stability only in the face of adding
or removing elements from either end, ie., {push,pop}_{front_back}.
Currently, all hidden items must be before all visible items.
This is primarily due to the requirement for pointer stability
but also because change_to_use_tmp_fields() depends on it when mapping
items to ref_item_array indexes. It would be good to get rid of this
requirement in the future.
*/
mem_root_deque<Item *> fields;
/**
All windows defined on the select, both named and inlined
*/
List<Window> m_windows;
/**
A pointer to ftfunc_list_alloc, list of full text search functions.
*/
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc{};
/// The VALUES items of a table value constructor.
mem_root_deque<mem_root_deque<Item *> *> *row_value_list{nullptr};
/// List of semi-join nests generated for this query block
mem_root_deque<Table_ref *> sj_nests;
/// List of tables in FROM clause - use Table_ref::next_local to traverse
SQL_I_List<Table_ref> m_table_list{};
/**
ORDER BY clause.
This list may be mutated during optimization (by remove_const() in the old
optimizer or by RemoveRedundantOrderElements() in the hypergraph optimizer),
so for prepared statements, we keep a copy of the ORDER.next pointers in
order_list_ptrs, and re-establish the original list before each execution.
*/
SQL_I_List<ORDER> order_list{};
Group_list_ptrs *order_list_ptrs{nullptr};
/**
GROUP BY clause.
This list may be mutated during optimization (by remove_const() in the old
optimizer or by RemoveRedundantOrderElements() in the hypergraph optimizer),
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{};
Group_list_ptrs *group_list_ptrs{nullptr};
// Used so that AggregateIterator knows which items to signal when the rollup
// level changes. Obviously only used in the presence of rollup.
Prealloced_array<Item_rollup_group_item *, 4> rollup_group_items{
PSI_NOT_INSTRUMENTED};
Prealloced_array<Item_rollup_sum_switcher *, 4> rollup_sums{
PSI_NOT_INSTRUMENTED};
/// Query-block-level hints, for this query block
Opt_hints_qb *opt_hints_qb{nullptr};
char *db{nullptr};
/**
If this query block is a recursive member of a recursive unit: the
Table_ref, in this recursive member, referencing the query
name.
*/
Table_ref *recursive_reference{nullptr};
/// Reference to LEX that this query block belongs to
LEX *parent_lex{nullptr};
/**
The set of those tables whose fields are referenced in the select list of
this select level.
*/
table_map select_list_tables{0};
table_map outer_join{0}; ///< Bitmap of all inner tables from outer joins
/**
Context for name resolution for all column references except columns
from joined tables.
*/
Name_resolution_context context{};
/**
Pointer to first object in list of Name res context objects that have
this query block as the base query block.
Includes field "context" which is embedded in this query block.
*/
Name_resolution_context *first_context;
/**
After optimization it is pointer to corresponding JOIN. This member
should be changed only when THD::LOCK_query_plan mutex is taken.
*/
JOIN *join{nullptr};
/// Set of table references contained in outer-most join nest
mem_root_deque<Table_ref *> m_table_nest;
/// Pointer to the set of table references in the currently active join
mem_root_deque<Table_ref *> *m_current_table_nest;
/// table embedding the above list
Table_ref *embedding{nullptr};
/**
Points to first leaf table of query block. After setup_tables() is done,
this is a list of base tables and derived tables. After derived tables
processing is done, this is a list of base tables only.
Use Table_ref::next_leaf to traverse the list.
*/
Table_ref *leaf_tables{nullptr};
/// Last table for LATERAL join, used by table functions
Table_ref *end_lateral_table{nullptr};
/// LIMIT clause, NULL if no limit is given
Item *select_limit{nullptr};
/// LIMIT ... OFFSET clause, NULL if no offset is given
Item *offset_limit{nullptr};
/**
Circular linked list of aggregate functions in nested query blocks.
This is needed if said aggregate functions depend on outer values
from this query block; if so, we want to add them as hidden items
in our own field list, to be able to evaluate them.
@see Item_sum::check_sum_func
*/
Item_sum *inner_sum_func_list{nullptr};
/**
Array of pointers to "base" items; one each for every selected expression
and referenced item in the query block. All references to fields are to
buffers associated with the primary input tables.
*/
Ref_item_array base_ref_items;
uint select_number{0}; ///< Query block number (used for EXPLAIN)
/**
Saved values of the WHERE and HAVING clauses. Allowed values are:
- COND_UNDEF if the condition was not specified in the query or if it
has not been optimized yet
- COND_TRUE if the condition is always true
- COND_FALSE if the condition is impossible
- COND_OK otherwise
*/
Item::cond_result cond_value{Item::COND_UNDEF};
Item::cond_result having_value{Item::COND_UNDEF};
/// Parse context: indicates where the current expression is being parsed
enum_parsing_context parsing_place{CTX_NONE};
/// Parse context: is inside a set function if this is positive
uint in_sum_expr{0};
/**
Three fields used by semi-join transformations to know when semi-join is
possible, and in which condition tree the subquery predicate is located.
*/
enum Resolve_place {
RESOLVE_NONE,
RESOLVE_JOIN_NEST,
RESOLVE_CONDITION,
RESOLVE_HAVING,
RESOLVE_SELECT_LIST
};
Resolve_place resolve_place{
RESOLVE_NONE}; ///< Indicates part of query being resolved
/**
Number of fields used in select list or where clause of current select
and all inner subselects.
*/
uint select_n_where_fields{0};
/**
Number of items in the select list, HAVING clause and ORDER BY clause. It is
used to reserve space in the base_ref_items array so that it is big enough
to hold hidden items for any of the expressions or sub-expressions in those
clauses.
*/
uint select_n_having_items{0};
/// Number of arguments of and/or/xor in where/having/on
uint saved_cond_count{0};
/// Number of predicates after preparation
uint cond_count{0};
/// Number of between predicates in where/having/on
uint between_count{0};
/// Maximal number of elements in multiple equalities
uint max_equal_elems{0};
/**
Number of Item_sum-derived objects in this SELECT. Keeps count of
aggregate functions and window functions(to allocate items in ref array).
See Query_block::setup_base_ref_items.
*/
uint n_sum_items{0};
/// Number of Item_sum-derived objects in children and descendant SELECTs
uint n_child_sum_items{0};
/// Keep track for allocation of base_ref_items: scalar subqueries may be
/// replaced by a field during scalar_to_derived transformation
uint n_scalar_subqueries{0};
/// Number of materialized derived tables and views in this query block.
uint materialized_derived_table_count{0};
/// Number of partitioned tables
uint partitioned_table_count{0};
/**
Number of wildcards used in the SELECT list. For example,
SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2;
has 3 wildcards.
*/
uint with_wild{0};
/// Original query table map before aj/sj processing.
table_map original_tables_map{};
/// Number of leaf tables in this query block.
uint leaf_table_count{0};
/// Number of derived tables and views in this query block.
uint derived_table_count{0};
/// Number of table functions in this query block
uint table_func_count{0};
/**
Nesting level of query block, outer-most query block has level 0,
its subqueries have level 1, etc. @see also sql/item_sum.h.
*/
int nest_level{0};
/// Indicates whether this query block contains the WITH ROLLUP clause
olap_type olap{UNSPECIFIED_OLAP_TYPE};
/// @see enum_condition_context
enum_condition_context condition_context{enum_condition_context::ANDS};
/// If set, the query block is of the form VALUES row_list.
bool is_table_value_constructor{false};
/// Describes context of this query block (e.g if it is a derived table).
sub_select_type linkage{UNSPECIFIED_TYPE};
/**
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT
UNCACHEABLE_RAND
UNCACHEABLE_SIDEEFFECT
*/
uint8 uncacheable{0};
void update_used_tables();
void restore_cmd_properties();
bool save_cmd_properties(THD *thd);
/**
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.
*/
bool first_execution{true};
/// True when semi-join pull-out processing is complete
bool sj_pullout_done{false};
/// Used by nested scalar_to_derived transformations
bool m_was_implicitly_grouped{false};
/// True: skip local transformations during prepare() call (used by INSERT)
bool skip_local_transforms{false};
bool is_item_list_lookup{false};
/// true when having fix field called in processing of this query block
bool having_fix_field{false};
/// true when GROUP BY fix field called in processing of this query block
bool group_fix_field{false};
/**
True if contains or aggregates set functions.
@note this is wrong when a locally found set function is aggregated
in an outer query block.
*/
bool with_sum_func{false};
/**
HAVING clause contains subquery => we can't close tables before
query processing end even if we use temporary table
*/
bool subquery_in_having{false};
/**
If true, use select_limit to limit number of rows selected.
Applicable when no explicit limit is supplied, and only for the
outermost query block of a SELECT statement.
*/
bool m_use_select_limit{false};
/// If true, limit object is added internally
bool m_internal_limit{false};
/// exclude this query block from unique_table() check
bool exclude_from_table_unique_test{false};
bool no_table_names_allowed{false}; ///< used for global order by
/// Keeps track of the current ORDER BY expression we are resolving for
/// ORDER BY, if any. Not used for GROUP BY or windowing ordering.
int m_current_order_by_number{0};
/// Hidden items added during optimization
/// @note that using this means we modify resolved data during optimization
uint hidden_items_from_optimization{0};
private:
friend class Query_expression;
friend class Condition_context;
/// Helper for save_properties()
bool save_order_properties(THD *thd, SQL_I_List<ORDER> *list,
Group_list_ptrs **list_ptrs);
bool record_join_nest_info(mem_root_deque<Table_ref *> *tables);
bool simplify_joins(THD *thd, mem_root_deque<Table_ref *> *join_list,
bool top, bool in_sj, Item **new_conds,
uint *changelog = nullptr);
/// Remove semijoin condition for this query block
void clear_sj_expressions(NESTED_JOIN *nested_join);
/// Build semijoin condition for th query block
bool build_sj_cond(THD *thd, NESTED_JOIN *nested_join,
Query_block *subq_query_block, table_map outer_tables_map,
Item **sj_cond, bool *simple_const);
bool decorrelate_condition(Semijoin_decorrelation &sj_decor,
Table_ref *join_nest);
bool convert_subquery_to_semijoin(THD *thd, Item_exists_subselect *subq_pred);
Table_ref *synthesize_derived(THD *thd, Query_expression *unit,
Item *join_cond, bool left_outer,
bool use_inner_join);
bool transform_subquery_to_derived(THD *thd, Table_ref **out_tl,
Query_expression *subs_query_expression,
Item_subselect *subq, bool use_inner_join,
bool reject_multiple_rows,
Item *join_condition,
Item *lifted_where_cond);
bool transform_table_subquery_to_join_with_derived(
THD *thd, Item_exists_subselect *subq_pred);
bool decorrelate_derived_scalar_subquery_pre(
THD *thd, Table_ref *derived, Item *lifted_where,
Lifted_fields_map *lifted_where_fields, bool *added_card_check);
bool decorrelate_derived_scalar_subquery_post(
THD *thd, Table_ref *derived, Lifted_fields_map *lifted_where_fields,
bool added_card_check);
void replace_referenced_item(Item *const old_item, Item *const new_item);
void remap_tables(THD *thd);
bool resolve_subquery(THD *thd);
void mark_item_as_maybe_null_if_rollup_item(Item *item);
Item *resolve_rollup_item(THD *thd, Item *item);
bool resolve_rollup(THD *thd);
bool setup_wild(THD *thd);
bool setup_order_final(THD *thd);
bool setup_group(THD *thd);
void fix_after_pullout(Query_block *parent_query_block,
Query_block *removed_query_block);
bool remove_redundant_subquery_clauses(THD *thd,
int hidden_group_field_count);
void repoint_contexts_of_join_nests(mem_root_deque<Table_ref *> join_list);
bool empty_order_list(Query_block *sl);
bool setup_join_cond(THD *thd, mem_root_deque<Table_ref *> *tables,
bool in_update);
bool find_common_table_expr(THD *thd, Table_ident *table_id, Table_ref *tl,
Parse_context *pc, bool *found);
/**
Transform eligible scalar subqueries in the SELECT list, WHERE condition,
HAVING condition or JOIN conditions of a query block[*] to an equivalent
derived table of a LEFT OUTER join, e.g. as shown in this uncorrelated
subquery:
[*] a.k.a "transformed query block" throughout this method and its minions.
<pre>
SELECT * FROM t1
WHERE t1.a > (SELECT COUNT(a) AS cnt FROM t2); ->
SELECT t1.* FROM t1 LEFT OUTER JOIN
(SELECT COUNT(a) AS cnt FROM t2) AS derived
ON TRUE WHERE t1.a > derived.cnt;
</pre>
Grouping in the transformed query block may necessitate the grouping to be
moved down to another derived table, cf. transform_grouped_to_derived.
Limitations:
- only implicitly grouped subqueries (guaranteed to have cardinality one)
are identified as scalar subqueries.
_ Correlated subqueries are not handled
@param[in,out] thd the session context
@returns true on error
*/
bool transform_scalar_subqueries_to_join_with_derived(THD *thd);
bool supported_correlated_scalar_subquery(THD *thd, Item::Css_info *subquery,
Item **lifted_where);
bool replace_item_in_expression(Item **expr, bool was_hidden,
Item::Item_replacement *info,
Item_transformer transformer);
bool transform_grouped_to_derived(THD *thd, bool *break_off);
bool replace_subquery_in_expr(THD *thd, Item::Css_info *subquery,
Table_ref *tr, Item **expr);
bool nest_derived(THD *thd, Item *join_cond,
mem_root_deque<Table_ref *> *join_list,
Table_ref *new_derived_table);
bool resolve_table_value_constructor_values(THD *thd);
// Delete unused columns from merged derived tables
void delete_unused_merged_columns(mem_root_deque<Table_ref *> *tables);
bool prepare_values(THD *thd);
bool check_only_full_group_by(THD *thd);
bool is_row_count_valid_for_semi_join();
/**
Copies all non-aggregated calls to the full-text search MATCH function from
the HAVING clause to the SELECT list (as hidden items), so that we can
materialize their result and not only their input. This is needed when the
result will be accessed after aggregation, as the result from MATCH cannot
be recalculated from its input alone. It also needs the underlying scan to
be positioned on the correct row. Storing the value before aggregation
removes the need for evaluating MATCH again after materialization.
*/
bool lift_fulltext_from_having_to_select_list(THD *thd);
//
// Members:
//
/**
Pointer to collection of subqueries candidate for semi/antijoin
conversion.
Template parameter is "true": no need to run DTORs on pointers.
*/
Mem_root_array<Item_exists_subselect *> *sj_candidates{nullptr};
/// How many expressions are part of the order by but not select list.
int hidden_order_field_count{0};
/**
Intrusive linked list of all query blocks within the same
query expression.
*/
Query_block *next{nullptr};
/// The query expression containing this query block.
Query_expression *master{nullptr};
/// The first query expression contained within this query block.
Query_expression *slave{nullptr};
/// Intrusive double-linked global list of query blocks.
Query_block *link_next{nullptr};
Query_block **link_prev{nullptr};
/// Result of this query block
Query_result *m_query_result{nullptr};
/**
Options assigned from parsing and throughout resolving,
should not be modified after resolving is done.
*/
ulonglong m_base_options{0};
/**
Active options. Derived from base options, modifiers added during
resolving and values from session variable option_bits. Since the latter
may change, active options are refreshed per execution of a statement.
*/
ulonglong m_active_options{0};
Table_ref *resolve_nest{
nullptr}; ///< Used when resolving outer join condition
/**
Condition to be evaluated after all tables in a query block are joined.
After all permanent transformations have been conducted by
Query_block::prepare(), this condition is "frozen", any subsequent changes
to it must be done with change_item_tree(), unless they only modify AND/OR
items and use a copy created by Query_block::get_optimizable_conditions().
Same is true for 'having_cond'.
*/
Item *m_where_cond;
/// Condition to be evaluated on grouped rows after grouping.
Item *m_having_cond;
/// Number of GROUP BY expressions added to all_fields
int hidden_group_field_count;
/// A backup of the items in base_ref_items at the end of preparation, so that
/// base_ref_items can be restored between executions of prepared statements.
/// Empty if it's a regular statement.
Ref_item_array m_saved_base_items;
/**
True if query block has semi-join nests merged into it. Notice that this
is updated earlier than sj_nests, so check this if info is needed
before the full resolver process is complete.
*/
bool has_sj_nests{false};
bool has_aj_nests{false}; ///< @see has_sj_nests; counts antijoin nests.
bool m_right_joins{false}; ///< True if query block has right joins
/// Allow merge of immediate unnamed derived tables
bool allow_merge_derived{true};
bool m_agg_func_used{false};
bool m_json_agg_func_used{false};
/**
True if query block does not generate any rows before aggregation,
determined during preparation (not optimization).
*/
bool m_empty_query{false};
static const char
*type_str[static_cast<int>(enum_explain_type::EXPLAIN_total)];
};
inline bool Query_expression::is_union() const {
Query_term *qt = query_term();
while (qt->term_type() == QT_UNARY)
qt = down_cast<Query_term_unary *>(qt)->m_children[0];
return qt->term_type() == QT_UNION;
}
inline bool Query_expression::is_set_operation() const {
Query_term *qt = query_term();
while (qt->term_type() == QT_UNARY)
qt = down_cast<Query_term_unary *>(qt)->m_children[0];
const Query_term_type type = qt->term_type();
return type == QT_UNION || type == QT_INTERSECT || type == QT_EXCEPT;
}
/// Utility RAII class to save/modify/restore the condition_context information
/// of a query block. @see enum_condition_context.
class Condition_context {
public:
Condition_context(
Query_block *select_ptr,
enum_condition_context new_type = enum_condition_context::NEITHER)
: select(nullptr), saved_value() {
if (select_ptr) {
select = select_ptr;
saved_value = select->condition_context;
// More restrictive wins over less restrictive:
if (new_type == enum_condition_context::NEITHER ||
(new_type == enum_condition_context::ANDS_ORS &&
saved_value == enum_condition_context::ANDS))
select->condition_context = new_type;
}
}
~Condition_context() {
if (select) select->condition_context = saved_value;
}
private:
Query_block *select;
enum_condition_context saved_value;
};
bool walk_join_list(mem_root_deque<Table_ref *> &list,
std::function<bool(Table_ref *)> action);
/**
Base class for secondary engine execution context objects. Secondary
storage engines may create classes derived from this one which
contain state they need to preserve between optimization and
execution of statements. The context objects should be allocated on
the execution MEM_ROOT.
*/
class Secondary_engine_execution_context {
public:
/**
Destructs the secondary engine execution context object. It is
called after the query execution has completed. Secondary engines
may override the destructor in subclasses and add code that
performs cleanup tasks that are needed after query execution.
*/
virtual ~Secondary_engine_execution_context() = default;
};
typedef struct struct_slave_connection {
char *user;
char *password;
char *plugin_auth;
char *plugin_dir;
void reset();
} LEX_SLAVE_CONNECTION;
struct st_sp_chistics {
LEX_CSTRING comment;
enum enum_sp_suid_behaviour suid;
bool detistic;
enum enum_sp_data_access daccess;
};
extern const LEX_STRING null_lex_str;
struct st_trg_chistics {
enum enum_trigger_action_time_type action_time;
enum enum_trigger_event_type event;
/**
FOLLOWS or PRECEDES as specified in the CREATE TRIGGER statement.
*/
enum enum_trigger_order_type ordering_clause;
/**
Trigger name referenced in the FOLLOWS/PRECEDES clause of the CREATE TRIGGER
statement.
*/
LEX_CSTRING anchor_trigger_name;
};
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:
Query_tables_list &operator=(Query_tables_list &&) = default;
/**
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_ref *query_tables;
/* Pointer to next_global member of last element in the previous list. */
Table_ref **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_ref **query_tables_own_last;
/*
Set of stored routines called by statement.
(Note that we use lazy-initialization for this hash).
See Sroutine_hash_entry for explanation why this hash uses binary
key comparison.
*/
enum { START_SROUTINES_HASH_SIZE = 16 };
std::unique_ptr<malloc_unordered_map<std::string, Sroutine_hash_entry *>>
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);
}
/**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
needs to be passed from open_tables() to lock_tables() which are
separated by some amount of code.
*/
uint table_count;
/*
These constructor and destructor serve for creation/destruction
of Query_tables_list instances which are used as backup storage.
*/
Query_tables_list() = default;
~Query_tables_list() = default;
/* 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 = std::move(*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_ref *table) {
*(table->prev_global = query_tables_last) = table;
query_tables_last = &table->next_global;
}
bool requires_prelocking() { return query_tables_own_last; }
void mark_as_requiring_prelocking(Table_ref **tables_own_last) {
query_tables_own_last = tables_own_last;
}
/* Return pointer to first not-own table in query-tables or 0 */
Table_ref *first_not_own_table() {
return (query_tables_own_last ? *query_tables_own_last : nullptr);
}
void chop_off_not_own_tables() {
if (query_tables_own_last) {
*query_tables_own_last = nullptr;
query_tables_last = query_tables_own_last;
query_tables_own_last = nullptr;
}
}
/**
All types of unsafe statements.
@note The int values of the enum elements are used to point to
bits in two bitmaps in two different places:
- Query_tables_list::binlog_stmt_flags
- THD::binlog_unsafe_warning_flags
Hence in practice this is not an enum at all, but a map from
symbols to bit indexes.
The ordering of elements in this enum must correspond to the order of
elements in the array binlog_stmt_unsafe_errcode.
*/
enum enum_binlog_stmt_unsafe {
/**
SELECT..LIMIT is unsafe because the set of rows returned cannot
be predicted.
*/
BINLOG_STMT_UNSAFE_LIMIT = 0,
/**
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 in composed
primary key.
*/
BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST,
/**
Using a plugin is unsafe.
*/
BINLOG_STMT_UNSAFE_FULLTEXT_PLUGIN,
BINLOG_STMT_UNSAFE_SKIP_LOCKED,
BINLOG_STMT_UNSAFE_NOWAIT,
/**
XA transactions and statements.
*/
BINLOG_STMT_UNSAFE_XA,
/**
If a substatement inserts into or updates a table that has a column with
an unsafe DEFAULT expression, it may not have the same effect on the
slave.
*/
BINLOG_STMT_UNSAFE_DEFAULT_EXPRESSION_IN_SUBSTATEMENT,
/**
DML or DDL statement that reads a ACL table is unsafe, because the row
are read without acquiring SE row locks. This would allow ACL tables to
be updated by concurrent thread. It would not have the same effect on the
slave.
*/
BINLOG_STMT_UNSAFE_ACL_TABLE_READ_IN_DML_DDL,
/**
Generating invisible primary key for a table created using CREATE TABLE...
SELECT... is unsafe because order in which rows are retrieved by the
SELECT determines which (if any) rows are inserted. This order cannot be
predicted and values for generated invisible primary key column may
differ on source and replica when @@session.binlog_format=STATEMENT.
*/
BINLOG_STMT_UNSAFE_CREATE_SELECT_WITH_GIPK,
/* 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 int BINLOG_STMT_UNSAFE_ALL_FLAGS =
((1 << 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_TRACE;
assert(unsafe_type >= 0 && unsafe_type < BINLOG_STMT_UNSAFE_COUNT);
binlog_stmt_flags |= (1U << unsafe_type);
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_TRACE;
assert((flags & ~BINLOG_STMT_UNSAFE_ALL_FLAGS) == 0);
binlog_stmt_flags |= flags;
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_TRACE;
return binlog_stmt_flags & BINLOG_STMT_UNSAFE_ALL_FLAGS;
}
/**
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_UNSAFE_COUNT + 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_TRACE;
binlog_stmt_flags |=
(1U << (BINLOG_STMT_UNSAFE_COUNT + BINLOG_STMT_TYPE_ROW_INJECTION));
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 NDEBUG
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:
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_TRACE;
assert(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
stmt_accessed_table_flag |= (1U << accessed_table);
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.
@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_TRACE;
assert(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
return (stmt_accessed_table_flag & (1U << accessed_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(NDEBUG)
DBUG_PRINT("LEX::is_mixed_stmt_unsafe",
("RESULT %02X %02X %02X\n", 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_using_match() { using_match = true; }
bool get_using_match() { return using_match; }
void set_stmt_unsafe_with_mixed_mode() { stmt_unsafe_with_mixed_mode = true; }
bool is_stmt_unsafe_with_mixed_mode() const {
return stmt_unsafe_with_mixed_mode;
}
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 = 0,
/** 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 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;
/**
It will be set true if 'MATCH () AGAINST' is used in the statement.
*/
bool using_match;
/**
This flag is set to true if statement is unsafe to be binlogged in STATEMENT
format, when in MIXED mode.
Currently this flag is set to true if stored program used in statement has
CREATE/DROP temporary table operation(s) as sub-statement(s).
*/
bool stmt_unsafe_with_mixed_mode{false};
};
/*
st_parsing_options contains the flags for constructions that are
allowed in the current statement.
*/
struct st_parsing_options {
bool allows_variable;
bool allows_select_into;
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.
(Copy '/' '*' and '*' '/' sequences to the preprocessed buffer.)
Typically, these are user comments '/' '*' ... '*' '/'.
*/
PRESERVE_COMMENT,
/**
Parsing comments that need to be discarded.
(Don't copy '/' '*' '!' and '*' '/' sequences to the preprocessed buffer.)
Typically, these are special comments '/' '*' '!' ... '*' '/',
or '/' '*' '!' 'M' 'M' 'm' 'm' 'm' ... '*' '/', where the comment
markers should not be expanded.
*/
DISCARD_COMMENT
};
/**
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, 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 {
public:
/**
Constructor
@param grammar_selector_token_arg See grammar_selector_token.
*/
explicit Lex_input_stream(uint grammar_selector_token_arg)
: grammar_selector_token(grammar_selector_token_arg) {}
/**
Object initializer. Must be called before usage.
@retval false OK
@retval true Error
*/
bool init(THD *thd, const char *buff, size_t length);
void reset(const char *buff, size_t length);
/**
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) {
assert(m_ptr + n <= m_end_of_query);
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() {
assert(m_ptr <= m_end_of_query);
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 {
assert(m_ptr <= m_end_of_query);
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 {
assert(m_ptr + n <= m_end_of_query);
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() {
assert(m_ptr <= m_end_of_query);
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) {
assert(m_ptr + n <= m_end_of_query);
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;
}
/**
Inject a character into the pre-processed stream.
Note, this function is used to inject a space instead of multi-character
C-comment. Thus there is no boundary checks here (basically, we replace
N-chars by 1-char here).
*/
char *cpp_inject(char ch) {
*m_cpp_ptr = ch;
return ++m_cpp_ptr;
}
/**
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); }
/**
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); }
/** 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; }
/** Mark the stream position as the start of a new token. */
void start_token() {
m_tok_start = m_ptr;
m_tok_end = m_ptr;
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 token start position, in the raw buffer. */
const char *get_tok_start() const { return m_tok_start; }
/** Get the token start position, in the pre-processed buffer. */
const char *get_cpp_tok_start() const { return m_cpp_tok_start; }
/** Get the token end position, in the raw buffer. */
const char *get_tok_end() const { return m_tok_end; }
/** Get the token end position, in the pre-processed buffer. */
const char *get_cpp_tok_end() const { return m_cpp_tok_end; }
/** Get the current stream pointer, in the raw buffer. */
const char *get_ptr() const { return m_ptr; }
/** Get the current stream pointer, in the pre-processed buffer. */
const char *get_cpp_ptr() const { return m_cpp_ptr; }
/** 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.
*/
assert(m_ptr > m_tok_start);
return (uint)((m_ptr - m_tok_start) - 1);
}
/** Get the utf8-body string. */
const char *get_body_utf8_str() const { return m_body_utf8; }
/** Get the utf8-body length. */
uint get_body_utf8_length() const {
return (uint)(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_literal(THD *thd, const LEX_STRING *txt,
const CHARSET_INFO *txt_cs,
const char *end_ptr);
uint get_lineno(const char *raw_ptr) const;
/** Current thread. */
THD *m_thd;
/** Current line number. */
uint yylineno;
/** Length of the last token parsed. */
uint yytoklen;
/** Interface with bison, value of the last token parsed. */
Lexer_yystype *yylval;
/**
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.*/
Lexer_yystype *lookahead_yylval;
/// Skip adding of the current token's digest since it is already added
///
/// Usually we calculate a digest token by token at the top-level function
/// of the lexer: MYSQLlex(). However, some complex ("hintable") tokens break
/// that data flow: for example, the `SELECT /*+ HINT(t) */` is the single
/// token from the main parser's point of view, and we add the "SELECT"
/// keyword to the digest buffer right after the lex_one_token() call,
/// but the "/*+ HINT(t) */" is a sequence of separate tokens from the hint
/// parser's point of view, and we add those tokens to the digest buffer
/// *inside* the lex_one_token() call. Thus, the usual data flow adds
/// tokens from the "/*+ HINT(t) */" string first, and only than it appends
/// the "SELECT" keyword token to that stream: "/*+ HINT(t) */ SELECT".
/// This is not acceptable, since we use the digest buffer to restore
/// query strings in their normalized forms, so the order of added tokens is
/// important. Thus, we add tokens of "hintable" keywords to a digest buffer
/// right in the hint parser and skip adding of them at the caller with the
/// help of skip_digest flag.
bool skip_digest;
void add_digest_token(uint token, Lexer_yystype *yylval);
void reduce_digest_token(uint token_left, uint token_right);
/**
True if this scanner tokenizes a partial query (partition expression,
generated column expression etc.)
@return true if parsing a partial query, otherwise false.
*/
bool is_partial_parser() const { return grammar_selector_token >= 0; }
/**
Outputs warnings on deprecated charsets in complete SQL statements
@param [in] cs The character set/collation to check for a deprecation.
@param [in] alias The name/alias of @p cs.
*/
void warn_on_deprecated_charset(const CHARSET_INFO *cs,
const char *alias) const {
if (!is_partial_parser()) {
::warn_on_deprecated_charset(m_thd, cs, alias);
}
}
/**
Outputs warnings on deprecated collations in complete SQL statements
@param [in] collation The collation to check for a deprecation.
*/
void warn_on_deprecated_collation(const CHARSET_INFO *collation) const {
if (!is_partial_parser()) {
::warn_on_deprecated_collation(m_thd, collation);
}
}
const CHARSET_INFO *query_charset;
private:
/** 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;
/** Beginning 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;
bool m_echo_saved;
/** 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;
/**
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;
/** Token character bitmaps, to detect 7bit strings. */
uchar tok_bitmap;
/** SQL_MODE = IGNORE_SPACE. */
bool ignore_space;
/**
true if we're parsing a prepared statement: in this mode
we should allow placeholders.
*/
bool stmt_prepare_mode;
/**
true if we should allow multi-statements.
*/
bool multi_statements;
/** 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.
*/
const CHARSET_INFO *m_underscore_cs;
/**
Current statement digest instrumentation.
*/
sql_digest_state *m_digest;
/**
The synthetic 1st token to prepend token stream with.
This token value tricks parser to simulate multiple %start-ing points.
Currently the grammar is aware of 4 such synthetic tokens:
1. GRAMMAR_SELECTOR_PART for partitioning stuff from DD,
2. GRAMMAR_SELECTOR_GCOL for generated column stuff from DD,
3. GRAMMAR_SELECTOR_EXPR for generic single expressions from DD/.frm.
4. GRAMMAR_SELECTOR_CTE for generic subquery expressions from CTEs.
5. -1 when parsing with the main grammar (no grammar selector available).
@note yylex() is expected to return the value of type int:
0 is for EOF and everything else for real token numbers.
Bison, in its turn, generates positive token numbers.
So, the negative grammar_selector_token means "not a token".
In other words, -1 is "empty value".
*/
const int grammar_selector_token;
bool text_string_is_7bit() const { return !(tok_bitmap & 0x80); }
};
class LEX_COLUMN {
public:
String column;
Access_bitmask rights;
LEX_COLUMN(const String &x, const Access_bitmask &y) : column(x), rights(y) {}
};
enum class role_enum;
/*
This structure holds information about grantor's context
*/
class LEX_GRANT_AS {
public:
LEX_GRANT_AS();
void cleanup();
public:
bool grant_as_used;
role_enum role_type;
LEX_USER *user;
List<LEX_USER> *role_list;
};
/**
The LEX object currently serves three different purposes:
- It contains some universal properties of an SQL command, such as
sql_command, presence of IGNORE in data change statement syntax, and list
of tables (query_tables).
- It contains some execution state variables, like m_exec_started
(set to true when execution is started), plugins (list of plugins used
by statement), insert_update_values_map (a map of objects used by certain
INSERT statements), etc.
- It contains a number of members that should be local to subclasses of
Sql_cmd, like purge_value_list (for the PURGE command), kill_value_list
(for the KILL command).
The LEX object is strictly a part of class Sql_cmd, for those SQL commands
that are represented by an Sql_cmd class. For the remaining SQL commands,
it is a standalone object linked to the current THD.
The lifecycle of a LEX object is as follows:
- The LEX object is constructed either on the execution mem_root
(for regular statements), on a Prepared_statement mem_root (for
prepared statements), on an SP mem_root (for stored procedure instructions),
or created on the current mem_root for short-lived uses.
- Call lex_start() to initialize a LEX object before use.
This initializes the execution state part of the object.
It also calls LEX::reset() to ensure that all members are properly inited.
- Parse and resolve the statement, using the LEX as a work area.
- Execute an SQL command: call set_exec_started() when starting to execute
(actually when starting to optimize).
Typically call is_exec_started() to distinguish between preparation
and optimization/execution stages of SQL command execution.
- Call clear_execution() when execution is finished. This will clear all
execution state associated with the SQL command, it also includes calling
LEX::reset_exec_started().
@todo - Create subclasses of Sql_cmd to contain data that are local
to specific commands.
@todo - Create a Statement context object that will hold the execution state
part of struct LEX.
@todo - Ensure that a LEX struct is never reused, thus making e.g
LEX::reset() redundant.
*/
struct LEX : public Query_tables_list {
friend bool lex_start(THD *thd);
Query_expression *unit; ///< Outer-most query expression
/// @todo: query_block can be replaced with unit->first-select()
Query_block *query_block; ///< First query block
Query_block *all_query_blocks_list; ///< List of all query blocks
private:
/* current Query_block in parsing */
Query_block *m_current_query_block;
public:
inline Query_block *current_query_block() const {
return m_current_query_block;
}
/*
We want to keep current_thd out of header files, so the debug assert
is moved to the .cc file.
*/
void assert_ok_set_current_query_block();
inline void set_current_query_block(Query_block *select) {
#ifndef NDEBUG
assert_ok_set_current_query_block();
#endif
m_current_query_block = select;
}
/// @return true if this is an EXPLAIN statement
bool is_explain() const { return explain_format != nullptr; }
bool is_explain_analyze = false;
/**
Whether the currently-running query should be (attempted) executed in
the hypergraph optimizer. This will not change after the query is
done parsing, so you can use it in any query phase to e.g. figure out
whether to inhibit some transformation that the hypergraph optimizer
does not properly understand yet.
*/
bool using_hypergraph_optimizer() const {
return m_using_hypergraph_optimizer;
}
void set_using_hypergraph_optimizer(bool use_hypergraph) {
m_using_hypergraph_optimizer = use_hypergraph;
}
private:
bool m_using_hypergraph_optimizer{false};
public:
LEX_STRING name;
char *help_arg;
char *to_log; /* For PURGE MASTER LOGS TO */
const char *x509_subject, *x509_issuer, *ssl_cipher;
// Widcard from SHOW ... LIKE <wildcard> statements.
String *wild;
Query_result *result;
LEX_STRING binlog_stmt_arg = {
nullptr, 0}; ///< Argument of the BINLOG event statement.
LEX_STRING ident;
LEX_USER *grant_user;
LEX_ALTER alter_password;
enum_alter_user_attribute alter_user_attribute;
LEX_STRING alter_user_comment_text;
LEX_GRANT_AS grant_as;
THD *thd;
/* Optimizer hints */
Opt_hints_global *opt_hints_global;
/* maintain a list of used plugins for this LEX */
typedef Prealloced_array<plugin_ref, INITIAL_LEX_PLUGIN_LIST_SIZE>
Plugins_array;
Plugins_array plugins;
/// Table being inserted into (may be a view)
Table_ref *insert_table;
/// Leaf table being inserted into (always a base table)
Table_ref *insert_table_leaf;
/** SELECT of CREATE VIEW statement */
LEX_STRING create_view_query_block;
/* 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;
List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
List<LEX_CSTRING> dynamic_privileges;
List<LEX_USER> *default_roles;
ulonglong bulk_insert_row_cnt;
// PURGE statement-specific fields:
List<Item> purge_value_list;
// KILL statement-specific fields:
List<Item> kill_value_list;
// other stuff:
List<set_var_base> var_list;
List<Item_func_set_user_var> set_var_list; // in-query assignment list
/**
List of placeholders ('?') for parameters of a prepared statement. Because
we append to this list during parsing, it is naturally sorted by
position of the '?' in the query string. The code which fills placeholders
with user-supplied values, and the code which writes a query for
statement-based logging, rely on this order.
This list contains only real placeholders, not the clones which originate
in a re-parsed CTE definition.
*/
List<Item_param> param_list;
bool locate_var_assignment(const Name_string &name);
void insert_values_map(Item_field *f1, Field *f2) {
if (!insert_update_values_map)
insert_update_values_map = new std::map<Item_field *, Field *>;
insert_update_values_map->insert(std::make_pair(f1, f2));
}
void destroy_values_map() {
if (insert_update_values_map) {
insert_update_values_map->clear();
delete insert_update_values_map;
insert_update_values_map = nullptr;
}
}
void clear_values_map() {
if (insert_update_values_map) {
insert_update_values_map->clear();
}
}
bool has_values_map() const { return insert_update_values_map != nullptr; }
std::map<Item_field *, Field *>::iterator begin_values_map() {
return insert_update_values_map->begin();
}
std::map<Item_field *, Field *>::iterator end_values_map() {
return insert_update_values_map->end();
}
private:
/*
With Visual Studio, an std::map will always allocate two small objects
on the heap. Sometimes we put LEX objects in a MEM_ROOT, and never run
the LEX DTOR. To avoid memory leaks, put this std::map on the heap,
and call clear_values_map() at the end of each statement.
*/
std::map<Item_field *, Field *> *insert_update_values_map;
public:
/*
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 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;
Item_sum *in_sum_func;
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO *create_info;
KEY_CREATE_INFO key_create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
LEX_SLAVE_CONNECTION slave_connection;
Server_options server_options;
USER_RESOURCES mqh;
LEX_RESET_SLAVE reset_slave_info;
ulong type;
/**
This field is used as a work field during resolving to validate
the use of aggregate functions. 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 since only non-aggregated data
is present, whereas MIN(i) in the HAVING clause is allowed because HAVING
operates on the output of a grouping operation.
Each query block is assigned a nesting level. This field is a bit field
that contains the value one in the position of that nesting level if
aggregate functions are allowed for that query block.
*/
nesting_map allow_sum_func;
/**
Windowing functions are not allowed in HAVING - in contrast to grouped
aggregate functions, since windowing in SQL logically follows after all
grouping operations. Nor are they allowed inside grouped aggregate
function arguments. One bit per query block, as also \c allow_sum_func. For
ORDER BY and QUALIFY predicates, window functions \em are allowed unless
they are contained in arguments of a grouped aggregate function. Nor are
references to outer window functions (via alias) allowed in subqueries, but
that is checked separately.
*/
nesting_map m_deny_window_func;
/// If true: during prepare, we did a subquery transformation (IN-to-EXISTS,
/// SOME/ANY) that doesn't currently work for subquery to a derived table
/// transformation.
bool m_subquery_to_derived_is_impossible;
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 `false` to get
syntax error back.
*/
bool expr_allows_subquery{true};
/**
If currently re-parsing a CTE's definition, this is the offset in bytes
of that definition in the original statement which had the WITH
clause. Otherwise this is 0.
*/
uint reparse_common_table_expr_at;
/**
If currently re-parsing a condition which is pushed down to a derived
table, this will be set to true.
*/
bool reparse_derived_table_condition{false};
/**
If currently re-parsing a condition that is being pushed down to a
derived table, this has the positions of all the parameters that are
part of that condition in the original statement. Otherwise it is empty.
*/
std::vector<uint> reparse_derived_table_params_at;
enum SSL_type ssl_type; /* defined in violite.h */
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
enum enum_var_type option_type;
enum_view_create_mode create_view_mode;
/// QUERY ID for SHOW PROFILE
my_thread_id show_profile_query_id;
uint profile_options;
uint grant, grant_tot_col;
/**
Set to true when GRANT ... GRANT OPTION ... TO ...
is used (vs. GRANT ... WITH GRANT OPTION).
The flag is used by @ref mysql_grant to grant GRANT OPTION (@ref GRANT_ACL)
to all dynamic privileges.
*/
bool grant_privilege;
uint slave_thd_opt, start_transaction_opt;
int select_number; ///< Number of query block (by EXPLAIN)
uint8 create_view_algorithm;
uint8 create_view_check;
/**
@todo ensure that correct CONTEXT_ANALYSIS_ONLY is set for all preparation
code, so we can fully rely on this field.
*/
uint8 context_analysis_only;
bool drop_if_exists;
/**
refers to optional IF EXISTS clause in REVOKE sql. This flag when set to
true will report warnings in case privilege being granted is not granted to
given user/role. When set to false error is reported.
*/
bool grant_if_exists;
/**
refers to optional IGNORE UNKNOWN USER clause in REVOKE sql. This flag when
set to true will report warnings in case target user/role for which
privilege being granted does not exists. When set to false error is
reported.
*/
bool ignore_unknown_user;
bool drop_temporary;
bool autocommit;
bool verbose, no_write_to_binlog;
// For show commands to show hidden columns and indexes.
bool m_extended_show;
enum enum_yes_no_unknown tx_chain, tx_release;
/**
Whether this query will return the same answer every time, given unchanged
data. Used to be for the query cache, but is now used to find out if an
expression is usable for partitioning.
*/
bool safe_to_cache_query;
private:
/// True if statement references UDF functions
bool m_has_udf{false};
bool ignore;
/// True if query has at least one external table
bool m_has_external_tables{false};
public:
bool is_ignore() const { return ignore; }
void set_ignore(bool ignore_param) { ignore = ignore_param; }
void set_has_udf() { m_has_udf = true; }
bool has_udf() const { return m_has_udf; }
void reset_has_external_tables() { m_has_external_tables = false; }
void set_has_external_tables() { m_has_external_tables = true; }
bool has_external_tables() const { return m_has_external_tables; }
st_parsing_options parsing_options;
Alter_info *alter_info;
/* Prepared statements SQL syntax:*/
LEX_CSTRING prepared_stmt_name; /* Statement name (in all queries) */
/*
Prepared statement query text or name of variable that holds the
prepared statement (in PREPARE ... queries)
*/
LEX_STRING prepared_stmt_code;
/* If true, prepared_stmt_code is a name of variable that holds the query */
bool prepared_stmt_code_is_varref;
/* Names of user variables holding parameters (in EXECUTE) */
List<LEX_STRING> prepared_stmt_params;
sp_head *sphead;
sp_name *spname;
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
bool all_privileges;
bool contains_plaintext_password;
enum_keep_diagnostics keep_diagnostics;
uint32 next_binlog_file_nr;
private:
bool m_broken; ///< see mark_broken()
/**
Set to true when execution has started (after parsing, tables opened and
query preparation is complete. Used to track arena state for SPs).
*/
bool m_exec_started;
/**
Set to true when execution is completed, ie optimization has been done
and execution is successful or ended in error.
*/
bool m_exec_completed;
/**
Current SP parsing context.
@see also sp_head::m_root_parsing_ctx.
*/
sp_pcontext *sp_current_parsing_ctx;
/**
Statement context for Query_block::make_active_options.
*/
ulonglong m_statement_options{0};
public:
/**
Gets the options that have been set for this statement. The options are
propagated to the Query_block objects and should usually be read with
#Query_block::active_options().
@return a bit set of options set for this statement
*/
ulonglong statement_options() { return m_statement_options; }
/**
Add options to values of m_statement_options. options is an ORed
bit set of options defined in query_options.h
@param options Add this set of options to the set already in
m_statement_options
*/
void add_statement_options(ulonglong options) {
m_statement_options |= options;
}
bool is_broken() const { return m_broken; }
/**
Certain permanent transformations (like in2exists), if they fail, may
leave the LEX in an inconsistent state. They should call the
following function, so that this LEX is not reused by another execution.
@todo If lex_start () were a member function of LEX, the "broken"
argument could always be "true" and thus could be removed.
*/
void mark_broken(bool broken = true) {
if (broken) {
/*
"OPEN <cursor>" cannot be re-prepared if the cursor uses no tables
("SELECT FROM DUAL"). Indeed in that case cursor_query is left empty
in constructions of sp_instr_cpush, and thus
sp_lex_instr::parse_expr() cannot re-prepare. So we mark the statement
as broken only if tables are used.
*/
if (is_metadata_used()) m_broken = true;
} else
m_broken = false;
}
bool check_preparation_invalid(THD *thd);
void cleanup(bool full) {
unit->cleanup(full);
if (full) {
m_IS_table_stats.invalidate_cache();
m_IS_tablespace_stats.invalidate_cache();
}
}
bool is_exec_started() const { return m_exec_started; }
void set_exec_started() { m_exec_started = true; }
void reset_exec_started() {
m_exec_started = false;
m_exec_completed = false;
}
/**
Check whether the statement has been executed (regardless of completion -
successful or in error).
Check this instead of Query_expression::is_executed() to determine
the state of a complete statement.
*/
bool is_exec_completed() const { return m_exec_completed; }
void set_exec_completed() { m_exec_completed = true; }
sp_pcontext *get_sp_current_parsing_ctx() { return sp_current_parsing_ctx; }
void set_sp_current_parsing_ctx(sp_pcontext *ctx) {
sp_current_parsing_ctx = ctx;
}
/// Check if the current statement uses meta-data (uses a table or a stored
/// routine).
bool is_metadata_used() const {
return query_tables != nullptr || has_udf() ||
(sroutines != nullptr && !sroutines->empty());
}
/// We have detected the presence of an alias of a window function with a
/// window on query block qb. Check if the reference is illegal at this point
/// during resolution.
/// @param qb The query block of the window function
/// @return true if window function is referenced from another query block
/// than its window, or if window functions are disallowed at the current
/// point during prepare, cf. also documentation of \c m_deny_window_func.
bool deny_window_function(Query_block *qb) const {
return qb != current_query_block() ||
((~allow_sum_func | m_deny_window_func) >>
current_query_block()->nest_level) &
0x1;
}
public:
st_sp_chistics sp_chistics;
Event_parse_data *event_parse_data;
bool only_view; /* used for SHOW CREATE TABLE/VIEW */
/*
view created to be run from definer (standard behaviour)
*/
uint8 create_view_suid;
/**
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.
*/
const char *stmt_definition_begin;
const char *stmt_definition_end;
/**
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;
bool is_lex_started; /* If lex_start() did run. For debugging. */
/// Set to true while resolving values in ON DUPLICATE KEY UPDATE clause
bool in_update_value_clause;
class Explain_format *explain_format;
// Maximum execution time for a statement.
ulong max_execution_time;
/*
To flag the current statement as dependent for binary logging
on explicit_defaults_for_timestamp
*/
bool binlog_need_explicit_defaults_ts;
/**
Used to inform the parser whether it should contextualize the parse
tree. When we get a pure parser this will not be needed.
*/
bool will_contextualize;
LEX();
virtual ~LEX();
/// Destroy contained objects, but not the LEX object itself.
void destroy() {
if (unit == nullptr) return;
unit->destroy();
unit = nullptr;
query_block = nullptr;
all_query_blocks_list = nullptr;
m_current_query_block = nullptr;
destroy_values_map();
}
/// Reset query context to initial state
void reset();
/// Create an empty query block within this LEX object.
Query_block *new_empty_query_block();
/// Create query expression object that contains one query block.
Query_block *new_query(Query_block *curr_query_block);
/// Create query block and attach it to the current query expression.
Query_block *new_set_operation_query(Query_block *curr_query_block);
/// Create top-level query expression and query block.
bool new_top_level_query();
/// Create query expression and query block in existing memory objects.
void new_static_query(Query_expression *sel_query_expression,
Query_block *select);
/// Create query expression under current_query_block and a query block under
/// the new query expression. The new query expression is linked in under
/// current_query_block. The new query block is linked in under the new
/// query expression.
///
/// @param thd current session context
/// @param current_query_block the root under which we create the new
/// expression
/// and block
/// @param where_clause any where clause for the block
/// @param having_clause any having clause for the block
/// @param ctx the parsing context
///
/// @returns the new query expression, or nullptr on error.
Query_expression *create_query_expr_and_block(
THD *thd, Query_block *current_query_block, Item *where_clause,
Item *having_clause, enum_parsing_context ctx);
inline bool is_ps_or_view_context_analysis() {
return (context_analysis_only &
(CONTEXT_ANALYSIS_ONLY_PREPARE | CONTEXT_ANALYSIS_ONLY_VIEW));
}
inline bool is_view_context_analysis() {
return (context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW);
}
void clear_execution();
/**
Set the current query as uncacheable.
@param curr_query_block Current select query block
@param cause Why this query is uncacheable.
@details
All query blocks representing subqueries, from the current one up to
the outer-most one, but excluding the main query block, are also set
as uncacheable.
*/
void set_uncacheable(Query_block *curr_query_block, uint8 cause) {
safe_to_cache_query = false;
if (m_current_query_block == nullptr) return;
Query_block *sl;
Query_expression *un;
for (sl = curr_query_block, un = sl->master_query_expression(); un != unit;
sl = sl->outer_query_block(), un = sl->master_query_expression()) {
sl->uncacheable |= cause;
un->uncacheable |= cause;
}
}
void set_trg_event_type_for_tables();
Table_ref *unlink_first_table(bool *link_to_local);
void link_first_table_back(Table_ref *first, bool link_to_local);
void first_lists_tables_same();
void restore_cmd_properties() { unit->restore_cmd_properties(); }
void restore_properties_for_insert() {
for (Table_ref *tr = insert_table->first_leaf_table(); tr != nullptr;
tr = tr->next_leaf)
tr->restore_properties();
}
bool save_cmd_properties(THD *thd) { return unit->save_cmd_properties(thd); }
bool can_use_merged();
bool can_not_use_merged();
bool need_correct_ident();
/*
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_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) {
return context_stack.push_front(context);
}
void pop_context() { context_stack.pop(); }
bool copy_db_to(char const **p_db, size_t *p_db_length) const;
bool copy_db_to(char **p_db, size_t *p_db_length) const {
return copy_db_to(const_cast<const char **>(p_db), p_db_length);
}
Name_resolution_context *current_context() { return context_stack.head(); }
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();
/**
@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 query_block (as the first added) will be at the tail
of the list.
*/
if (query_block == all_query_blocks_list &&
(sroutines == nullptr || sroutines->empty())) {
assert(!all_query_blocks_list->next_select_in_list());
return true;
}
return false;
}
void release_plugins();
/**
IS schema queries read some dynamic table statistics from SE.
These statistics are cached, to avoid opening of table more
than once while preparing a single output record buffer.
*/
dd::info_schema::Table_statistics m_IS_table_stats;
dd::info_schema::Tablespace_statistics m_IS_tablespace_stats;
bool accept(Select_lex_visitor *visitor);
bool set_wild(LEX_STRING);
void clear_privileges();
bool make_sql_cmd(Parse_tree_root *parse_tree);
private:
/**
Context object used by secondary storage engines to store query
state during optimization and execution.
*/
Secondary_engine_execution_context *m_secondary_engine_context{nullptr};
public:
/**
Gets the secondary engine execution context for this statement.
*/
Secondary_engine_execution_context *secondary_engine_execution_context()
const {
return m_secondary_engine_context;
}
/**
Sets the secondary engine execution context for this statement.
The old context object is destroyed, if there is one. Can be set
to nullptr to destroy the old context object and clear the
pointer.
The supplied context object should be allocated on the execution
MEM_ROOT, so that its memory doesn't have to be manually freed
after query execution.
*/
void set_secondary_engine_execution_context(
Secondary_engine_execution_context *context);
private:
bool m_is_replication_deprecated_syntax_used{false};
public:
bool is_replication_deprecated_syntax_used() {
return m_is_replication_deprecated_syntax_used;
}
void set_replication_deprecated_syntax_used() {
m_is_replication_deprecated_syntax_used = true;
}
private:
bool m_was_replication_command_executed{false};
public:
bool was_replication_command_executed() const {
return m_was_replication_command_executed;
}
void set_was_replication_command_executed() {
m_was_replication_command_executed = true;
}
bool set_channel_name(LEX_CSTRING name = {});
private:
bool rewrite_required{false};
public:
void set_rewrite_required() { rewrite_required = true; }
void reset_rewrite_required() { rewrite_required = false; }
bool is_rewrite_required() { return rewrite_required; }
};
/**
RAII class to ease the call of LEX::mark_broken() if error.
Used during preparation and optimization of DML queries.
*/
class Prepare_error_tracker {
public:
Prepare_error_tracker(THD *thd_arg) : thd(thd_arg) {}
~Prepare_error_tracker();
private:
THD *const thd;
};
/**
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(nullptr), yacc_yyvs(nullptr), yacc_yyls(nullptr) {
reset();
}
void reset() {
if (yacc_yyss != nullptr) {
my_free(yacc_yyss);
yacc_yyss = nullptr;
}
if (yacc_yyvs != nullptr) {
my_free(yacc_yyvs);
yacc_yyvs = nullptr;
}
if (yacc_yyls != nullptr) {
my_free(yacc_yyls);
yacc_yyls = nullptr;
}
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;
/**
Bison internal location value stack, yyls, when dynamically allocated using
my_yyoverflow().
*/
uchar *yacc_yyls;
/**
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
Query_block::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.
*/
};
/**
Input parameters to the parser.
*/
struct Parser_input {
/**
True if the text parsed corresponds to an actual query,
and not another text artifact.
This flag is used to disable digest parsing of nested:
- view definitions
- table trigger definitions
- table partition definitions
- event scheduler event definitions
*/
bool m_has_digest;
/**
True if the caller needs to compute a digest.
This flag is used to request explicitly a digest computation,
independently of the performance schema configuration.
*/
bool m_compute_digest;
Parser_input() : m_has_digest(false), m_compute_digest(false) {}
};
/**
Internal state of the parser.
The complete state consist of:
- input parameters that control the parser behavior
- state data used during lexical parsing,
- state data used during syntactic parsing.
*/
class Parser_state {
protected:
/**
Constructor for special parsers of partial SQL clauses (DD)
@param grammar_selector_token See Lex_input_stream::grammar_selector_token
*/
explicit Parser_state(int grammar_selector_token)
: m_input(), m_lip(grammar_selector_token), m_yacc(), m_comment(false) {}
public:
Parser_state() : m_input(), m_lip(~0U), m_yacc(), m_comment(false) {}
/**
Object initializer. Must be called before usage.
@retval false OK
@retval true Error
*/
bool init(THD *thd, const char *buff, size_t length) {
return m_lip.init(thd, buff, length);
}
void reset(const char *found_semicolon, size_t length) {
m_lip.reset(found_semicolon, length);
m_yacc.reset();
}
/// Signal that the current query has a comment
void add_comment() { m_comment = true; }
/// Check whether the current query has a comment
bool has_comment() const { return m_comment; }
public:
Parser_input m_input;
Lex_input_stream m_lip;
Yacc_state m_yacc;
/**
Current performance digest instrumentation.
*/
PSI_digest_locker *m_digest_psi;
private:
bool m_comment; ///< True if current query contains comments
};
/**
Parser state for partition expression parser (.frm/DD stuff)
*/
class Partition_expr_parser_state : public Parser_state {
public:
Partition_expr_parser_state();
partition_info *result;
};
/**
Parser state for generated column expression parser (.frm/DD stuff)
*/
class Gcol_expr_parser_state : public Parser_state {
public:
Gcol_expr_parser_state();
Value_generator *result;
};
/**
Parser state for single expression parser (.frm/DD stuff)
*/
class Expression_parser_state : public Parser_state {
public:
Expression_parser_state();
Item *result;
};
/**
Parser state for CTE subquery parser
*/
class Common_table_expr_parser_state : public Parser_state {
public:
Common_table_expr_parser_state();
PT_subquery *result;
};
/**
Parser state for Derived table's condition parser.
(Used in condition pushdown to derived tables)
*/
class Derived_expr_parser_state : public Parser_state {
public:
Derived_expr_parser_state();
Item *result;
};
struct st_lex_local : public LEX {
static void *operator new(size_t size) noexcept {
return (*THR_MALLOC)->Alloc(size);
}
static void *operator new(size_t size, MEM_ROOT *mem_root,
const std::nothrow_t &arg
[[maybe_unused]] = std::nothrow) noexcept {
return mem_root->Alloc(size);
}
static void operator delete(void *ptr [[maybe_unused]],
size_t size [[maybe_unused]]) {
TRASH(ptr, size);
}
static void operator delete(
void *, MEM_ROOT *, const std::nothrow_t &) noexcept { /* Never called */
}
};
extern bool lex_init(void);
extern void lex_free(void);
extern bool lex_start(THD *thd);
extern void lex_end(LEX *lex);
extern int MYSQLlex(union YYSTYPE *, struct YYLTYPE *, class THD *);
extern void trim_whitespace(const CHARSET_INFO *cs, LEX_STRING *str);
extern bool is_lex_native_function(const LEX_STRING *name);
bool is_keyword(const char *name, size_t len);
bool db_is_default_db(const char *db, size_t db_len, const THD *thd);
bool check_select_for_locking_clause(THD *);
void print_derived_column_names(const THD *thd, String *str,
const Create_col_name_list *column_names);
/**
@} (End of group GROUP_PARSER)
*/
/**
Check if the given string is invalid using the system charset.
@param string_val Reference to the string.
@param charset_info Pointer to charset info.
@return true if the string has an invalid encoding using
the system charset else false.
*/
inline bool is_invalid_string(const LEX_CSTRING &string_val,
const CHARSET_INFO *charset_info) {
size_t valid_len;
bool len_error;
if (validate_string(charset_info, string_val.str, string_val.length,
&valid_len, &len_error)) {
char hexbuf[7];
octet2hex(
hexbuf, string_val.str + valid_len,
static_cast<uint>(std::min<size_t>(string_val.length - valid_len, 3)));
my_error(ER_INVALID_CHARACTER_STRING, MYF(0), charset_info->csname, hexbuf);
return true;
}
return false;
}
/**
Check if the given string is invalid using the system charset.
@param string_val Reference to the string.
@param charset_info Pointer to charset info.
@param[out] invalid_sub_str If string has an invalid encoding then invalid
string in printable ASCII format is stored.
@return true if the string has an invalid encoding using
the system charset else false.
*/
inline bool is_invalid_string(const LEX_CSTRING &string_val,
const CHARSET_INFO *charset_info,
std::string &invalid_sub_str) {
size_t valid_len;
bool len_error;
if (validate_string(charset_info, string_val.str, string_val.length,
&valid_len, &len_error)) {
char printable_buff[32];
convert_to_printable(
printable_buff, sizeof(printable_buff), string_val.str + valid_len,
static_cast<uint>(std::min<size_t>(string_val.length - valid_len, 3)),
charset_info, 3);
invalid_sub_str = printable_buff;
return true;
}
return false;
}
/**
In debug mode, verify that we're not adding an item twice to the fields list
with inconsistent hidden flags. Must be called before adding the item to
fields.
*/
inline void assert_consistent_hidden_flags(const mem_root_deque<Item *> &fields
[[maybe_unused]],
Item *item [[maybe_unused]],
bool hidden [[maybe_unused]]) {
#ifndef NDEBUG
if (std::find(fields.begin(), fields.end(), item) != fields.end()) {
// The item is already in the list, so we can't add it
// with a different value for hidden.
assert(item->hidden == hidden);
}
#endif
}
bool walk_item(Item *item, Select_lex_visitor *visitor);
bool accept_for_order(SQL_I_List<ORDER> orders, Select_lex_visitor *visitor);
bool accept_table(Table_ref *t, Select_lex_visitor *visitor);
bool accept_for_join(mem_root_deque<Table_ref *> *tables,
Select_lex_visitor *visitor);
Table_ref *nest_join(THD *thd, Query_block *select, Table_ref *embedding,
mem_root_deque<Table_ref *> *jlist, size_t table_cnt,
const char *legend);
template <typename T>
inline bool WalkQueryExpression(Query_expression *query_expr, enum_walk walk,
T &&functor) {
return query_expr->walk(&Item::walk_helper_thunk<T>, walk,
reinterpret_cast<uchar *>(&functor));
}
#endif /* SQL_LEX_INCLUDED */
|