diff --git a/Cargo.lock b/Cargo.lock index 7a66e93b6..2f3e32609 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1628,6 +1628,7 @@ dependencies = [ "codspeed-criterion-compat", "insta", "krishiv-common", + "krishiv-functions", "krishiv-kernels", "krishiv-plan", "krishiv-sql", diff --git a/crates/krishiv-exec/proptest-regressions/aggregate/tests.txt b/crates/krishiv-exec/proptest-regressions/aggregate/tests.txt index 65aa4f2bb..ba7178692 100644 --- a/crates/krishiv-exec/proptest-regressions/aggregate/tests.txt +++ b/crates/krishiv-exec/proptest-regressions/aggregate/tests.txt @@ -11,3 +11,4 @@ cc 7542d02a4fff9fc126bafc252f439413d6797d4fdebf40af2e5344bfc36ae1fc cc 56b81a74e2d12a2bc1db117253670e6e23c2e37071f5088250fb33de42f48d45 cc faf07a9b578ca1ba7049877479f9bada8ccc52cbf5a596504f879c70a02ec834 cc dec162184755ea6700f7a2638ecd7b0ac68cca4e724255da308a13a0fbb52efa +cc 1e0670aeb42fa11d5a69c9c11f9e9d0a3a7e309b5e63a663afe5ca0833002ac3 # shrinks to data = [(None, Some(72), None, Some(-581861), Some(-3802927), None), (None, None, Some(false), None, None, Some(19572)), (None, None, Some(true), Some(751431), None, None), (None, Some(231), Some(true), None, None, None), (Some(583443515), Some(97), Some(false), Some(183436), None, None), (None, None, Some(false), Some(137134), Some(-175271), Some(6753)), (Some(67245141), None, Some(false), Some(-933573), Some(-1556519), None), (None, None, None, Some(511759), Some(-829346), None), (Some(171651165), None, Some(false), Some(-803160), None, None), (None, None, None, None, Some(818966), None), (Some(1400331949), None, None, None, None, Some(65018)), (None, Some(73), None, None, Some(9521000), None), (None, None, Some(false), None, Some(1120408), None), (None, Some(180), Some(true), None, Some(-8298981), None), (None, None, Some(false), None, Some(9087053), Some(22826)), (Some(543000570), None, Some(false), None, Some(6594598), Some(54918)), (None, Some(246), None, None, Some(1212875), Some(50085)), (None, Some(193), Some(false), Some(-473179), Some(-2678786), Some(22455)), (Some(1068645292), Some(16), None, Some(453640), Some(-6228937), None), (None, Some(141), Some(false), None, None, Some(46544)), (None, Some(114), Some(true), Some(-10293), Some(6620470), None), (Some(-1958527180), None, Some(true), None, None, Some(38716)), (Some(1719654648), None, Some(false), None, None, Some(2816)), (None, None, None, None, Some(-7244585), Some(45207)), (Some(-1081190992), None, None, Some(-891685), None, None), (None, Some(147), Some(true), Some(-507119), Some(6889488), None), (None, Some(128), None, None, None, None), (Some(-1290088279), None, Some(false), Some(-351839), Some(-6423915), Some(15039)), (Some(171351193), Some(172), None, Some(35982), Some(5196050), None), (Some(1605474126), Some(66), None, None, Some(-7861640), Some(50174)), (Some(1758782704), None, Some(false), Some(-140427), None, Some(11356)), (None, None, None, Some(-509943), None, None), (Some(1860946921), Some(100), Some(true), None, Some(8470953), Some(56959)), (None, Some(123), None, None, None, Some(32113)), (None, None, None, None, Some(5695305), Some(51759)), (Some(-778862016), None, None, Some(441862), None, Some(1239)), (Some(-697189916), Some(208), None, Some(-91725), None, Some(49151)), (Some(-1134370722), None, None, Some(809879), Some(3107258), Some(3510)), (None, None, None, Some(824211), None, None), (Some(1875429549), None, None, Some(345572), None, None), (None, None, None, Some(866595), None, None), (Some(-2108301021), None, None, None, Some(3411760), Some(39340)), (Some(1715221714), Some(237), None, Some(231752), Some(8098340), Some(37363)), (None, None, Some(false), Some(12568), Some(-5401267), None), (None, Some(151), Some(false), None, Some(-1875742), Some(62829)), (None, Some(62), Some(false), None, None, None), (Some(-483851612), Some(14), Some(false), None, Some(-4804093), Some(248)), (Some(1586530687), Some(41), None, None, Some(-2136025), None), (Some(1473376619), None, None, None, Some(4704829), Some(36788)), (Some(447899631), Some(54), None, Some(472915), Some(-2658021), None), (None, Some(109), Some(true), None, None, Some(61883)), (Some(-724407938), Some(68), None, None, Some(1411077), None), (None, Some(42), None, Some(570898), Some(-3124525), None), (None, Some(220), None, Some(95862), Some(1674191), Some(61927)), (None, None, Some(false), None, None, Some(52506)), (Some(1491914317), Some(194), None, Some(-593682), Some(4308159), Some(5290)), (Some(1292659264), None, Some(true), None, None, Some(32679)), (None, None, Some(true), Some(614074), Some(354625), None), (None, None, Some(false), None, Some(-5109825), Some(19170)), (None, None, Some(true), Some(734536), None, None), (Some(1774194187), None, None, None, None, Some(55310)), (None, None, None, Some(606470), None, None), (None, None, None, Some(-67935), Some(-5059957), Some(53530)), (None, Some(63), None, None, Some(-1584062), Some(16908)), (None, Some(89), None, Some(864493), Some(9833000), None), (None, Some(29), None, Some(227417), Some(7318563), None), (None, None, None, None, None, None), (Some(-1582655939), Some(138), Some(false), None, Some(2294772), None), (Some(1352642547), Some(163), None, None, None, Some(13388)), (None, None, Some(false), Some(559855), None, Some(18079)), (None, None, None, None, Some(8107047), None), (None, Some(123), None, Some(373300), Some(-6484428), None), (None, Some(102), None, None, Some(2569781), Some(58691)), (None, Some(31), Some(false), Some(119354), None, None), (None, None, Some(true), Some(-713239), Some(9721341), Some(32243)), (Some(-1592709164), None, None, Some(-854329), None, Some(34196)), (None, Some(139), Some(true), None, Some(-7294538), Some(56633)), (None, Some(226), Some(false), None, None, None), (Some(378105035), Some(47), None, Some(-912722), Some(-2525406), Some(47197)), (Some(882754217), Some(212), None, Some(352660), None, None), (Some(-1029982157), Some(89), Some(true), None, None, None), (None, None, Some(true), Some(-167377), None, Some(5166)), (None, None, Some(true), None, Some(16642), Some(16148)), (None, Some(196), Some(true), None, None, None), (None, Some(191), Some(true), Some(-965863), None, Some(54296)), (None, None, None, None, Some(2222739), None), (Some(-194927702), None, None, None, Some(2989998), None), (Some(846619005), Some(148), None, Some(-321957), Some(4516453), Some(15698)), (Some(548121317), None, None, None, Some(9237931), None), (Some(-882652716), Some(96), Some(true), Some(117548), Some(-2710483), None), (Some(-1608955021), None, None, Some(-304917), None, Some(41181)), (Some(942424340), Some(1), Some(true), None, None, Some(50352)), (None, Some(47), None, Some(750754), None, None), (None, Some(85), Some(false), Some(738880), None, None), (Some(983469077), None, Some(false), None, Some(9095493), Some(48845)), (None, Some(20), Some(true), Some(177701), Some(-3369124), Some(50251)), (None, None, None, Some(27339), None, Some(55063)), (None, Some(228), None, None, None, Some(9595)), (Some(2073478945), Some(1), Some(false), Some(336053), Some(-462795), None), (None, None, None, None, Some(8331847), Some(37095)), (Some(-1216247335), None, Some(false), None, None, Some(41478)), (Some(-49749141), Some(102), None, None, None, None), (Some(-470106835), None, Some(false), None, Some(434015), None), (Some(559021507), None, None, Some(668144), Some(4376285), None), (Some(-595145643), Some(162), None, Some(141278), Some(1954683), None), (None, None, Some(true), Some(920459), None, Some(52208)), (Some(-1728302470), None, Some(false), None, Some(9128253), None), (None, None, Some(false), Some(-506495), Some(2734555), Some(58300)), (None, None, Some(true), Some(325397), Some(2390256), None), (None, None, Some(false), None, Some(-9866769), Some(10660)), (None, None, Some(true), None, None, Some(5555)), (Some(-1276546384), Some(80), Some(false), Some(841140), Some(-7457972), None), (Some(-677519647), None, Some(false), Some(326322), None, Some(56484)), (Some(1513260567), Some(238), None, None, Some(-8730413), None), (None, Some(73), Some(false), None, Some(8836288), Some(48409)), (None, None, Some(true), None, Some(7973308), None), (Some(912329755), Some(121), Some(false), None, Some(6540386), Some(65477)), (None, None, Some(true), None, Some(-7092933), None), (Some(-923922993), Some(113), None, Some(-134646), None, Some(43838)), (Some(593484333), Some(65), None, None, Some(2706584), Some(9487)), (Some(1786911248), None, None, None, None, None), (None, Some(65), None, Some(-520568), Some(-2605363), Some(43157)), (Some(-1833232980), Some(142), Some(false), None, None, None), (Some(-1336880760), Some(243), Some(true), None, Some(929155), None), (Some(1226491714), Some(15), None, None, None, Some(37534)), (None, Some(144), None, None, None, Some(13700)), (Some(1471604712), None, None, None, None, None), (Some(711625778), Some(118), None, Some(578074), Some(1432746), Some(35345)), (Some(-533902075), Some(123), Some(false), None, Some(5840109), Some(57518)), (Some(-1628374250), None, None, Some(-936957), None, None), (Some(1637904461), Some(106), None, Some(269628), Some(9965809), Some(42218)), (Some(-1461762147), None, None, None, None, Some(52670)), (None, Some(9), None, Some(-640361), Some(2675290), None), (Some(548529140), None, Some(false), Some(458958), Some(7280217), None), (Some(2095545466), None, Some(false), Some(814756), Some(-815172), Some(39928)), (Some(-836461574), Some(80), None, None, Some(5276159), Some(63490)), (Some(1261347159), None, None, Some(-561001), None, None), (Some(827311114), None, None, Some(592355), None, Some(63952)), (Some(743874241), Some(196), None, Some(-673569), None, Some(18333)), (Some(1552530020), None, Some(false), None, Some(-4361006), Some(747)), (None, Some(43), Some(false), Some(-199080), Some(7803487), Some(38187)), (None, None, Some(false), None, Some(-7818627), None), (Some(607992367), Some(205), Some(false), None, None, Some(2098)), (None, None, None, None, None, None), (None, None, Some(true), Some(-190758), Some(84121), Some(33711)), (Some(2134590490), Some(126), Some(false), None, None, None), (Some(424513254), Some(213), Some(false), None, Some(-7487619), None), (Some(-1090050361), Some(38), Some(true), None, None, None), (Some(1568058198), None, Some(true), Some(703899), Some(2453001), None), (Some(1848600401), Some(130), Some(true), None, None, None), (Some(2125907586), Some(187), Some(true), Some(292389), Some(-8057435), None), (Some(419869553), Some(215), Some(true), None, Some(4733326), Some(42659)), (Some(1936679336), None, Some(true), None, None, None), (None, Some(5), Some(false), Some(-78652), None, Some(30079)), (Some(-746073943), Some(122), Some(false), None, Some(9824150), Some(40553)), (None, None, Some(true), None, None, None), (Some(1813350947), None, Some(true), None, Some(9864779), Some(22100)), (Some(-1962541416), Some(0), None, None, None, None), (None, None, None, Some(-146851), None, Some(22887)), (None, Some(240), None, None, Some(5999830), None), (Some(-4867317), None, Some(true), Some(637896), None, None), (None, None, None, None, None, None), (None, None, None, Some(-516880), Some(742382), Some(48836)), (None, Some(139), Some(true), None, Some(-526396), Some(14148)), (Some(1005223046), None, None, None, None, None), (None, Some(8), None, None, Some(8466723), Some(3721)), (Some(-655562398), Some(245), Some(false), None, Some(9693455), None), (Some(2079950524), None, None, Some(-32258), Some(2776666), Some(10578)), (Some(-861462760), None, Some(false), Some(55490), None, None), (None, Some(19), Some(true), None, Some(5490540), None), (None, Some(38), Some(false), None, Some(6615364), Some(2886)), (None, None, Some(false), None, Some(7467260), Some(55690)), (None, Some(248), None, Some(-145544), Some(-8549493), Some(62014)), (Some(2051976102), Some(124), Some(true), Some(499196), Some(7710718), Some(62239)), (Some(-1031468112), None, None, None, Some(8827673), None), (Some(1021627211), None, Some(false), Some(555000), Some(-6669739), Some(55643)), (None, None, Some(false), None, None, Some(50245)), (Some(135976255), None, None, None, Some(8827571), Some(7106)), (Some(-1226719838), None, Some(false), Some(-607112), None, None), (Some(-2105862085), Some(95), Some(true), None, Some(1354951), None), (Some(-93183335), None, None, Some(853986), None, None), (Some(-1032234177), Some(247), Some(true), Some(186448), None, None), (Some(-1779063904), None, None, None, Some(4976946), Some(19453)), (None, Some(66), Some(false), None, None, Some(5634)), (Some(-1793247311), Some(197), None, None, Some(5386815), Some(6064)), (Some(1113794346), None, None, None, None, Some(40792)), (Some(-798032377), Some(128), Some(true), None, Some(8866050), None), (None, None, Some(false), Some(-273320), None, None), (Some(271286151), Some(163), None, Some(643411), Some(-8343807), None), (None, None, None, None, Some(3945850), None), (Some(348006119), Some(144), Some(true), None, Some(-5349979), None), (None, None, Some(true), Some(579210), Some(-1946666), None), (Some(-1699553834), None, Some(false), Some(-482793), Some(-4186949), None), (None, Some(10), Some(false), Some(6218), Some(-570301), Some(17772)), (Some(-1584401907), Some(59), None, None, Some(-174596), Some(30351)), (None, Some(217), None, Some(50519), None, None), (None, None, Some(true), None, Some(-8546860), None), (Some(548039397), None, None, Some(-120691), None, None), (Some(952030099), Some(245), Some(false), Some(-911473), Some(-7580625), Some(54075)), (None, Some(117), Some(false), None, None, None), (None, None, Some(true), None, None, None), (None, Some(151), None, None, None, Some(54585)), (Some(469995399), None, None, Some(40295), None, Some(5872)), (None, Some(150), Some(true), Some(-20207), Some(-9240405), Some(38207)), (Some(510200649), None, None, Some(-937535), None, None), (None, None, Some(false), Some(377850), Some(-9101579), None), (None, None, None, Some(303611), Some(4928645), None), (None, Some(198), Some(true), Some(507979), Some(-6661390), None), (Some(2055722440), Some(29), None, Some(-43191), None, None), (Some(1192917554), Some(158), Some(false), None, Some(7778915), None), (Some(1113287370), Some(247), None, None, Some(2465275), None), (None, None, None, Some(-621858), Some(9330717), None), (None, Some(48), Some(true), None, None, None), (Some(785963354), None, Some(false), None, Some(-7045358), None), (None, Some(50), None, Some(-382429), Some(3816562), Some(52921)), (Some(-224222210), Some(147), Some(true), None, Some(-2845356), Some(28076)), (Some(-560620406), None, None, Some(870819), Some(7913916), Some(7005)), (None, Some(204), None, None, None, None), (Some(-31330391), None, Some(true), Some(-117316), Some(-5133580), None), (Some(-342957036), Some(156), None, None, None, Some(7020)), (None, Some(184), None, None, Some(2348360), None), (Some(1525298078), Some(192), None, None, None, Some(48272)), (Some(702325570), None, None, None, Some(5854795), None), (None, Some(246), None, Some(296037), Some(-9603117), Some(47693)), (Some(-755349577), None, None, Some(-212930), Some(6389683), None), (Some(-728431159), None, Some(false), Some(98939), Some(-2684383), Some(45885)), (None, Some(88), Some(false), Some(-46732), Some(4325494), None), (Some(1151825927), Some(44), None, Some(852393), None, None), (Some(-1281896162), None, Some(true), None, Some(8411259), Some(11589)), (Some(-1410941302), Some(75), Some(false), Some(-3149), None, None), (None, Some(149), None, None, None, Some(38225)), (None, None, None, Some(-367555), Some(-652458), None), (None, Some(103), Some(false), None, None, None), (Some(1802377455), None, None, Some(10481), Some(4586347), None), (Some(-1360864911), Some(162), Some(true), Some(-644178), None, None), (Some(-1970140031), Some(159), None, None, Some(8226184), Some(23354)), (None, None, Some(false), None, None, None), (Some(-436756396), None, None, Some(-195217), Some(-6009556), None), (Some(122825949), None, None, None, None, None), (Some(-505508051), Some(225), Some(false), None, Some(-1455181), Some(26837)), (Some(95936880), None, Some(true), None, None, None), (None, Some(78), Some(false), Some(-956083), Some(7931814), None), (None, None, Some(true), Some(-363872), Some(8119913), Some(9220)), (None, Some(137), Some(false), None, Some(-6950227), Some(25509)), (Some(-1220877615), None, Some(true), None, Some(1307585), Some(20700)), (Some(1118211415), Some(191), None, None, Some(7164490), Some(56129)), (Some(-35179027), None, Some(true), None, Some(1838381), Some(3943)), (None, None, Some(false), None, Some(-4600128), None), (Some(215785198), Some(183), None, Some(620029), Some(8434454), None), (Some(-961051578), None, None, None, Some(5071606), None), (None, Some(80), Some(false), Some(996394), None, None), (Some(-1675454537), Some(51), Some(true), None, Some(-6208801), Some(51489)), (Some(83071600), None, Some(false), None, Some(-1344517), Some(8846)), (Some(-146116818), Some(202), Some(false), Some(-216040), None, None), (Some(-15363857), Some(110), Some(true), None, None, None), (Some(-499559115), Some(157), None, Some(-413319), Some(9664367), None), (Some(-1016759964), Some(253), Some(true), Some(630014), None, None), (None, None, None, Some(275328), None, None), (Some(-2103367678), Some(12), None, None, Some(-5275370), Some(14437)), (None, Some(9), Some(false), Some(814901), Some(1439027), None), (Some(-1343874828), None, Some(true), Some(-499589), Some(5713667), Some(7309)), (None, None, None, None, None, Some(30958)), (None, Some(247), None, None, None, None), (None, None, None, Some(738147), None, None), (Some(882436964), Some(201), None, None, Some(-3350235), None), (Some(-138974946), None, None, None, Some(6678147), None), (Some(288714659), None, None, Some(318803), Some(4009047), Some(56166)), (None, None, Some(true), None, Some(-7913627), None), (Some(-303191441), None, Some(true), Some(506496), Some(-3457252), Some(51823)), (None, None, Some(false), Some(-401312), None, Some(40849)), (Some(-2044697865), Some(236), None, Some(-74124), Some(2211553), None), (Some(-892217828), None, Some(true), None, Some(2049958), None), (Some(1803558311), None, Some(false), None, Some(1275863), Some(34511)), (None, Some(155), Some(false), None, None, None), (Some(788014563), None, None, Some(-329969), None, Some(64478)), (None, Some(25), Some(true), Some(558320), Some(265013), None), (None, None, None, Some(-888526), Some(-5827254), Some(29342)), (Some(-1020673995), None, Some(true), Some(795927), None, None), (Some(309056490), None, Some(true), Some(-537544), None, None), (Some(-973869710), Some(160), None, Some(666629), None, None), (Some(-1123616058), Some(19), Some(true), Some(-449847), None, Some(5295)), (Some(-1258671271), Some(107), None, Some(856253), Some(-5715984), Some(23552)), (None, None, Some(false), Some(-326587), Some(6665939), Some(54927)), (Some(-652756204), Some(103), None, Some(-841377), None, None), (Some(198260966), None, None, None, None, Some(2596)), (Some(-1550322883), Some(51), Some(false), None, None, Some(64977)), (Some(-749651030), None, None, Some(520724), None, None), (Some(-747813109), None, Some(true), Some(635422), None, Some(22631)), (Some(-445188543), Some(109), Some(true), None, Some(9261625), None), (None, Some(8), Some(false), Some(-36013), Some(2075927), None), (None, None, Some(false), Some(-766133), Some(-2712328), Some(63489)), (Some(318210895), None, Some(false), None, None, None), (Some(-1038808475), None, None, None, Some(3287976), None), (None, None, None, None, None, Some(42565)), (None, None, Some(true), None, Some(2795642), None), (None, Some(106), Some(true), None, Some(9649743), None), (None, None, Some(false), Some(-497280), Some(-7416597), Some(48629)), (None, Some(28), None, Some(178560), Some(-3514929), Some(18216)), (None, Some(228), Some(false), Some(-332629), Some(7476365), Some(39378)), (Some(4919354), None, Some(true), Some(-307530), Some(1288719), Some(53858)), (None, None, None, Some(-64215), Some(-3338954), None), (None, Some(63), None, None, None, Some(9251)), (Some(1690289555), Some(65), None, None, None, Some(58847)), (Some(1749820347), None, Some(true), None, None, Some(15402)), (Some(1906941000), Some(44), Some(false), None, None, Some(62070)), (None, Some(223), None, Some(-706668), Some(-7919424), None), (None, None, None, None, Some(-2708398), Some(51494)), (None, Some(156), Some(false), Some(455230), None, Some(24566)), (Some(-1411531839), None, Some(false), Some(-727596), None, Some(8392)), (None, None, Some(true), Some(849773), Some(6652070), None), (None, Some(90), None, None, None, Some(41225)), (Some(-75149535), Some(40), None, None, Some(8741166), Some(56443)), (Some(1490034408), None, None, None, None, Some(57745)), (None, None, None, None, Some(5190509), Some(63205)), (None, Some(71), None, Some(218715), Some(-7323893), None), (None, None, None, Some(296759), None, None), (None, None, None, None, Some(5434872), Some(42416)), (None, Some(16), None, Some(860494), None, Some(54297)), (None, None, None, Some(943621), None, Some(65431)), (None, Some(227), Some(true), Some(-985077), None, None), (Some(1775678560), None, Some(false), None, None, None), (None, Some(141), None, Some(-934343), Some(3864408), None), (Some(558582379), Some(248), Some(false), None, None, None), (None, None, Some(false), Some(-173156), None, None), (Some(10133401), Some(65), None, None, None, Some(23022)), (Some(-1227652054), None, None, None, None, None), (None, None, None, Some(582308), Some(-1887123), None), (Some(1186963401), None, None, None, Some(-4611423), None), (None, None, Some(true), None, Some(9037924), Some(43633)), (None, None, None, Some(-424978), None, Some(33647)), (Some(-655255180), Some(234), Some(false), None, Some(495097), None), (Some(-1258773576), Some(243), Some(false), None, Some(6465298), Some(16235)), (None, None, Some(false), Some(992378), None, None), (Some(970020182), None, Some(true), None, None, None), (None, Some(199), None, None, Some(-7314315), Some(256)), (None, None, None, Some(498539), Some(5530650), Some(8563)), (None, Some(245), Some(false), None, Some(1615536), Some(48843)), (Some(292419403), None, None, None, None, None), (Some(-1898312082), Some(143), Some(false), Some(877932), Some(-8277300), None), (Some(143402522), None, Some(true), Some(406455), Some(8743231), None), (Some(-1968273737), Some(65), Some(true), Some(-148355), None, Some(52507)), (None, Some(91), None, None, Some(-6639249), Some(45421)), (Some(887452294), None, None, None, Some(-4955667), None), (None, Some(44), Some(true), None, None, Some(49999)), (None, None, Some(false), Some(514711), Some(9985471), None), (None, None, Some(false), Some(282705), Some(2459400), Some(42920)), (None, None, None, Some(54544), None, None), (None, Some(111), Some(false), Some(466051), None, None), (Some(501471927), None, Some(false), Some(285122), Some(1306129), None), (None, None, Some(false), None, None, None), (Some(1400482386), None, Some(false), None, None, Some(27096)), (Some(663448953), None, Some(false), None, Some(6392043), Some(61823)), (None, Some(198), Some(false), None, None, Some(3508)), (None, Some(59), Some(false), Some(-469240), Some(2368295), None), (None, Some(98), Some(false), Some(6078), Some(6063834), Some(5747)), (Some(794730929), Some(238), None, Some(951937), Some(-3385125), Some(20607)), (Some(-1424466045), Some(40), Some(true), None, None, None), (None, None, Some(true), Some(393878), None, Some(35349)), (None, Some(226), Some(true), Some(-246696), Some(8846398), None), (Some(991915291), None, Some(true), Some(-924085), Some(-7985887), None), (None, None, None, Some(-866960), Some(-695479), Some(29063)), (Some(-351474691), Some(199), None, None, Some(-5596304), Some(4253)), (Some(302243165), None, None, None, Some(-5698088), None), (None, Some(212), Some(false), Some(603270), None, None), (Some(1419888641), None, Some(true), Some(-304513), None, Some(47641)), (Some(-1238558392), None, Some(true), None, None, None), (Some(-520408895), Some(205), None, Some(-672622), Some(2745247), None), (Some(707321437), None, None, Some(-416737), None, None), (Some(-1664257807), None, Some(true), None, None, Some(24932)), (Some(-1681437845), Some(169), None, None, None, None), (Some(937558113), Some(53), None, Some(-470017), None, Some(55832)), (None, Some(105), Some(true), None, Some(-4486511), Some(46365)), (Some(-2035559327), None, Some(false), None, None, None), (None, None, None, None, Some(3599908), Some(64022)), (Some(194393975), Some(217), None, Some(365599), Some(-6279068), Some(35812)), (None, None, None, None, Some(-6789215), Some(33801)), (Some(2108969209), None, None, Some(462493), None, Some(1310)), (None, None, None, Some(732499), None, None), (None, Some(150), None, None, None, Some(13294)), (None, Some(36), None, None, None, None), (Some(-989257385), None, Some(true), None, Some(-6090131), None), (None, None, Some(true), None, None, None), (Some(1874195520), Some(111), Some(true), Some(205687), None, Some(41167)), (Some(1074399191), Some(66), None, Some(-615891), None, None), (Some(-705126563), None, None, None, Some(-9586487), Some(32713)), (None, Some(36), None, None, Some(3407291), Some(51698)), (None, Some(184), Some(false), Some(-964116), None, None), (Some(-1539695460), Some(110), Some(true), None, Some(-7870684), Some(40327)), (None, Some(97), Some(false), Some(-639592), None, Some(39891)), (Some(619658969), Some(48), Some(true), Some(-632936), None, None), (Some(-955536257), Some(195), None, None, Some(-6444945), None), (Some(-1828533505), None, None, None, None, None), (Some(1719350447), None, None, None, None, Some(63882)), (None, Some(234), None, Some(-556390), Some(6000779), None), (Some(132980337), Some(46), None, None, Some(8988770), None), (None, Some(250), None, None, Some(9903214), Some(57482)), (Some(61984518), None, Some(false), None, None, Some(21149)), (None, Some(66), Some(false), Some(-529266), None, Some(45839)), (None, Some(209), None, Some(-878238), None, Some(31251)), (None, Some(31), None, Some(-515391), None, None), (Some(-1829243588), None, Some(false), None, Some(387534), None), (Some(1528659133), None, Some(false), Some(716474), None, None), (None, Some(203), Some(false), Some(845917), Some(-6382633), None), (None, None, None, None, Some(7234761), None), (None, None, None, Some(229775), None, None), (None, Some(85), None, None, None, Some(10201)), (Some(-1645030793), Some(47), Some(true), Some(-294541), None, None), (None, Some(248), None, Some(-995989), Some(2100474), Some(12823)), (Some(726817569), Some(195), Some(false), Some(-767730), Some(-4019352), None), (None, Some(90), None, Some(633933), Some(4037799), None), (None, Some(24), None, None, Some(-859046), None), (Some(-1555238668), Some(212), None, Some(9051), Some(-1460601), Some(38965)), (Some(-1484910086), Some(161), None, Some(900283), None, None), (Some(1823752117), None, None, None, None, Some(40431)), (Some(-1156384491), Some(112), Some(true), Some(-409458), None, Some(20077)), (None, None, None, None, None, None), (Some(468595531), Some(163), None, Some(46994), Some(3084710), None), (None, Some(236), None, None, None, None), (Some(1589299814), Some(232), None, None, None, Some(62199)), (None, Some(171), Some(true), None, None, Some(64698)), (None, Some(107), None, Some(430331), Some(-4573189), Some(23560)), (None, None, None, None, None, Some(50869)), (None, None, Some(false), None, Some(-7528485), None), (None, Some(36), Some(true), None, Some(-8690406), Some(4477)), (Some(-1447753380), Some(33), None, Some(-794817), None, None), (None, Some(86), Some(true), Some(-161667), None, None), (None, None, Some(true), Some(768794), Some(-9490680), None), (None, Some(167), Some(true), Some(-70037), None, None), (None, Some(101), None, None, None, Some(30652)), (None, None, None, Some(541421), None, Some(8448)), (Some(-1221003647), None, Some(false), Some(879083), None, None), (Some(1528390175), None, Some(true), Some(689525), None, Some(13474)), (Some(-36813846), Some(235), Some(false), None, Some(4297017), Some(25664)), (Some(1888090001), Some(16), None, Some(38407), Some(8702450), Some(47384)), (Some(1822858159), Some(135), Some(false), Some(357166), Some(7750205), Some(34881)), (None, None, None, None, None, None), (None, Some(172), Some(false), None, Some(7377621), None), (None, Some(8), Some(false), None, Some(-2807860), None), (Some(593757424), None, None, Some(-166961), None, Some(4514)), (None, Some(16), Some(true), Some(407458), Some(1191787), Some(3631)), (Some(-593250051), Some(48), Some(true), Some(-219577), Some(7660958), Some(56094)), (None, None, Some(false), Some(489316), Some(3274522), None), (Some(393550113), None, Some(false), Some(-272895), None, None), (None, None, Some(true), Some(-475819), Some(-5540429), Some(5635)), (None, None, Some(false), None, None, None), (None, None, Some(true), None, None, Some(3332)), (Some(-294672133), None, None, None, Some(-824652), Some(51318)), (Some(2128027868), Some(196), None, None, None, Some(40254)), (Some(-1137486295), Some(83), Some(false), None, None, Some(23653)), (None, Some(89), Some(true), Some(77221), None, None), (None, None, Some(true), Some(-869127), Some(-9522699), None), (None, Some(22), None, Some(-523499), None, None), (None, None, None, None, None, None), (None, Some(115), Some(false), None, Some(-1434532), None), (Some(1040219169), Some(129), Some(true), Some(-730282), None, None), (Some(-1798576414), Some(52), None, None, None, Some(35532)), (Some(1351507983), Some(244), Some(false), None, Some(-4589159), None), (None, None, None, Some(617674), Some(-6306996), Some(11317)), (None, None, Some(false), Some(305348), None, None), (None, None, Some(false), None, Some(-8923124), None), (Some(-1658419779), None, None, None, None, None), (Some(-1989814498), Some(159), None, Some(-753051), None, None), (Some(321809720), None, None, Some(343691), Some(-8833814), Some(6238)), (Some(-721595817), Some(212), None, Some(-114580), Some(4982933), Some(20714)), (None, Some(40), None, Some(-35673), Some(-1020704), Some(25106)), (Some(1735770593), None, Some(true), Some(389471), None, Some(40509)), (Some(1915368158), Some(249), None, None, None, None), (Some(1155573608), None, None, None, None, Some(44008)), (Some(-1909274476), None, None, None, None, Some(11872)), (Some(-667561435), None, Some(true), None, Some(543323), Some(37510)), (Some(-1928410259), Some(6), None, Some(-341296), Some(1589703), None), (None, None, Some(true), None, None, None), (None, Some(168), None, Some(389271), None, None), (Some(97693840), Some(224), None, None, Some(440605), Some(64602)), (None, None, None, None, Some(6178540), None), (Some(1199445021), Some(48), Some(true), None, Some(2477881), Some(36471)), (Some(-906482894), Some(107), Some(true), None, None, Some(14885)), (Some(1588159430), Some(113), None, Some(655856), Some(-3240677), Some(32530)), (None, None, Some(false), None, Some(-885604), None), (None, Some(91), Some(true), Some(-727348), Some(744448), None), (None, Some(201), None, None, Some(-1047259), Some(29666)), (Some(1055252394), Some(201), Some(false), None, None, Some(32142)), (Some(-945870942), None, Some(true), None, Some(-3318132), None), (Some(1620541254), Some(88), Some(true), None, Some(3994405), None), (None, Some(28), None, None, None, Some(62325)), (None, Some(143), Some(false), Some(-518411), Some(-4311041), None), (None, Some(198), Some(true), Some(-249184), None, Some(51643)), (Some(731126354), None, None, Some(259647), Some(2382969), Some(179)), (Some(799102217), None, None, Some(265297), Some(-5870904), Some(26999)), (None, Some(60), Some(true), Some(193851), Some(4739932), Some(39863)), (None, Some(218), Some(false), None, Some(8834260), Some(55175)), (Some(1199239098), None, Some(false), None, Some(6134663), Some(48371)), (None, Some(147), None, None, Some(8321806), Some(57732)), (None, None, Some(true), Some(-640899), None, Some(21763)), (Some(854629607), None, None, None, Some(6381234), Some(19327)), (None, Some(231), Some(true), Some(-546761), Some(5482959), None), (Some(899699642), None, Some(true), Some(261765), Some(6255762), None), (None, Some(83), Some(true), Some(575739), None, Some(33074)), (None, None, Some(true), None, Some(-2192830), None), (Some(-770940307), Some(72), Some(true), None, None, Some(59254)), (Some(-443683050), Some(215), Some(true), Some(749213), Some(-6016533), Some(14987)), (None, None, None, None, Some(-8294894), Some(34428)), (None, None, None, None, Some(-823315), Some(41773)), (None, Some(65), Some(true), Some(936067), Some(-3012820), Some(53399)), (Some(678237727), None, None, Some(-669501), Some(4449960), None), (Some(844747017), Some(129), Some(false), None, None, Some(32548)), (Some(222190226), Some(211), None, None, None, Some(54587)), (None, None, Some(false), None, None, Some(43801)), (None, Some(235), Some(false), Some(-269663), None, Some(58899)), (None, Some(134), None, None, None, None), (Some(-1497218131), None, Some(true), Some(-99145), None, None), (Some(1292630948), Some(208), Some(false), Some(120890), Some(-6969302), None), (Some(1568814626), None, None, None, Some(-2932728), Some(16672)), (None, Some(149), Some(false), Some(577108), Some(4559621), None), (Some(-1661580385), None, None, Some(-579963), Some(-1001030), None), (Some(-1632395831), Some(35), None, None, None, None), (Some(1858521818), Some(211), Some(true), Some(-459210), None, Some(7261)), (None, None, Some(false), Some(112610), Some(-843395), None), (Some(-2112676158), None, None, None, Some(8984439), None), (Some(1025737836), None, None, None, None, Some(43701)), (Some(-1427069192), None, Some(true), Some(313792), None, Some(10159)), (None, None, Some(true), None, Some(575049), None), (None, None, Some(true), None, Some(-7437970), None), (Some(400601133), None, None, Some(309719), None, None), (None, None, None, Some(209749), Some(-4909110), None), (None, None, None, Some(393425), Some(2461969), Some(19768)), (None, Some(219), Some(false), Some(-232613), None, None), (None, Some(239), Some(true), Some(-855819), None, Some(35921)), (Some(-733022601), None, Some(false), None, None, Some(21632)), (Some(1902754760), None, Some(true), None, Some(-5450337), Some(20516)), (None, Some(2), Some(false), Some(332333), Some(-9310815), Some(13775)), (Some(761789288), Some(161), None, None, None, None), (None, None, None, Some(-24621), Some(-3633974), Some(36805)), (Some(-1929764872), None, Some(false), Some(383791), None, None), (None, None, None, None, Some(-292656), None), (Some(1338564732), Some(24), None, Some(43089), Some(-4785151), Some(27645)), (Some(-1483097016), None, Some(true), None, Some(-4990525), Some(61256)), (Some(914148223), Some(189), None, None, None, None), (None, None, None, None, None, None), (None, Some(234), Some(false), Some(-612009), None, Some(32591)), (Some(-558908293), None, Some(false), None, Some(-3347783), None), (None, None, Some(true), Some(-643164), Some(1608944), Some(51173)), (Some(-1657796686), Some(177), Some(true), Some(-498171), Some(-3656087), Some(5783)), (Some(1853165590), Some(142), None, None, None, None), (Some(478104834), Some(64), None, Some(-42708), None, Some(60185)), (None, Some(220), Some(true), Some(81914), Some(2397063), None), (None, Some(67), Some(true), None, Some(1261893), None), (None, Some(46), None, None, Some(4974348), Some(11417)), (Some(-1931053347), None, Some(true), Some(-210440), None, None), (None, None, None, Some(506869), Some(2528746), Some(35876)), (Some(-2106569465), Some(74), Some(true), Some(-458839), Some(-8793846), None), (Some(-1727017560), Some(142), Some(false), None, Some(-9242249), Some(23358)), (Some(-670294569), None, Some(false), Some(-80907), None, Some(36944)), (None, None, None, Some(-191012), Some(5861874), None), (Some(1427344797), None, None, None, Some(-8694508), Some(18402)), (Some(221333311), Some(175), None, Some(-580235), None, Some(14444)), (Some(1784475209), Some(49), Some(false), Some(-984041), None, None), (Some(514088369), None, None, Some(503364), Some(-2345437), Some(18925)), (None, None, None, None, Some(-4938740), Some(798)), (None, Some(184), None, Some(-376367), None, Some(6322)), (None, Some(29), Some(false), None, Some(110863), Some(38245)), (Some(565162384), None, None, Some(-510418), Some(370967), None), (None, Some(114), Some(false), None, None, None), (Some(-1647021435), Some(244), Some(false), None, Some(8866417), Some(16326)), (None, None, None, Some(85011), Some(9879841), Some(55395)), (None, None, Some(true), Some(220733), Some(5178959), Some(13553)), (Some(-1948593893), Some(128), Some(true), Some(954947), None, None), (None, Some(155), Some(true), Some(186616), Some(6973134), Some(28306)), (None, None, Some(true), None, None, Some(29630)), (None, None, Some(true), Some(239259), None, Some(5850)), (None, Some(23), None, None, Some(-2272531), None), (None, Some(150), None, Some(-532904), Some(9033351), None), (Some(989439574), Some(105), Some(false), None, None, None), (None, None, Some(true), None, Some(5035224), None), (Some(329563431), None, None, None, Some(7117274), None), (Some(-1670855429), Some(169), None, Some(396523), Some(-2334579), None), (None, Some(45), Some(true), None, None, Some(554)), (Some(1530823636), Some(64), None, None, Some(9740367), Some(33277)), (None, Some(42), None, Some(905646), Some(103628), None), (Some(-345730339), Some(94), None, None, None, Some(42787)), (None, Some(222), Some(false), Some(373661), Some(-4180073), None), (None, None, None, Some(424282), Some(7558472), None), (Some(1976191329), None, None, None, Some(-6522264), None), (None, Some(218), Some(true), None, Some(6982513), None), (None, Some(32), Some(false), None, None, None), (Some(-838242683), Some(125), None, None, Some(-9213583), Some(44752)), (None, Some(66), Some(false), None, None, None), (Some(-1818161812), None, None, None, Some(31022), None), (Some(667360908), Some(36), None, None, Some(-5033045), None), (Some(-1213255247), Some(98), None, Some(-688280), Some(-242390), None), (None, None, None, None, Some(-581728), Some(34185)), (Some(-2056990029), None, None, None, None, None), (None, None, Some(false), Some(-615437), Some(-4869800), None), (Some(-1710980209), None, Some(false), Some(548029), None, None), (Some(-935499094), None, Some(true), Some(89807), Some(1378564), Some(24230)), (Some(-1616636386), Some(232), None, Some(-143741), None, Some(8937)), (None, None, None, None, Some(6115840), Some(48464)), (None, None, Some(true), Some(652351), None, Some(8791)), (Some(141773506), Some(70), Some(false), None, None, Some(16662)), (None, None, Some(false), None, None, Some(43898)), (None, Some(243), None, None, Some(5548116), None), (Some(-806934069), Some(40), Some(false), None, Some(-3953960), None), (None, None, None, None, None, None), (None, Some(45), None, Some(582704), None, Some(57896)), (None, None, None, None, None, Some(50679)), (None, None, None, None, Some(6516406), Some(42231)), (None, None, Some(false), Some(350843), None, Some(49220)), (None, Some(117), Some(true), None, Some(-1614945), None), (Some(-1769689500), Some(88), Some(true), Some(-645867), None, Some(58967)), (None, Some(185), None, None, None, None), (Some(1430835682), Some(100), Some(false), None, Some(-6017012), Some(65080)), (None, None, Some(false), Some(392387), Some(-9030963), Some(1737)), (None, Some(150), Some(false), Some(962185), Some(-2187222), Some(64441)), (Some(1768595708), None, None, Some(938685), None, Some(34470)), (Some(1142892866), Some(33), Some(false), None, None, None), (Some(-417711213), None, Some(false), Some(-862928), Some(5782878), Some(59723)), (Some(-847325852), None, None, None, None, None), (None, None, Some(false), None, None, None), (None, None, None, Some(-90488), Some(-5969067), None), (None, Some(52), None, None, Some(-8075235), Some(20984)), (Some(-954194841), Some(87), None, None, Some(-161934), Some(59814)), (Some(1502348998), None, Some(false), None, None, None), (None, Some(52), Some(false), None, None, Some(45820)), (Some(-903188780), Some(230), None, None, None, Some(29803)), (None, Some(2), None, None, Some(-55193), None), (None, Some(89), None, Some(-550971), Some(5721794), None), (Some(1458028683), None, Some(true), Some(864234), None, None), (Some(1876891532), None, None, None, None, None), (Some(-688519812), None, Some(true), Some(-867928), None, Some(54748)), (Some(891098181), None, None, Some(913822), Some(-9646573), Some(5862)), (None, None, None, Some(195134), Some(-3249520), Some(11754)), (Some(109411725), Some(2), Some(true), None, None, Some(52631)), (Some(-1826121084), Some(118), Some(false), Some(827009), None, Some(43586)), (None, None, None, Some(119856), Some(-8713094), None), (Some(-1557101988), Some(26), None, None, None, Some(48345)), (None, Some(156), Some(false), Some(355971), Some(-8013721), Some(49413)), (None, None, None, Some(-484270), Some(3340476), None), (None, None, Some(true), Some(-674101), None, None), (None, None, Some(false), None, None, None), (Some(-1253874638), None, Some(true), None, None, None), (Some(-1520035098), Some(1), None, None, None, None), (Some(1322492305), None, Some(false), None, Some(-141587), None), (None, None, None, None, None, None), (Some(1421156765), Some(38), None, None, Some(1559123), Some(46685)), (None, None, None, None, None, None), (None, Some(93), None, None, None, None), (None, Some(84), None, None, Some(-6954803), Some(59235)), (None, None, None, Some(-431951), Some(7512037), Some(52058)), (Some(-265600767), Some(18), Some(false), Some(179157), Some(4918097), Some(6934)), (None, None, None, Some(458681), None, None), (Some(434460743), None, None, Some(766124), Some(5925102), Some(9388)), (None, None, None, Some(-997723), None, Some(65295)), (None, None, None, Some(607980), None, Some(38981)), (None, Some(205), None, Some(167048), Some(-5135926), Some(53099)), (Some(1385823032), None, Some(true), Some(323551), Some(1370447), None), (Some(1687654019), Some(1), None, Some(871864), None, Some(57234)), (None, Some(64), Some(false), None, None, None), (Some(1736819705), None, None, Some(-313857), None, Some(2894)), (Some(-1519510017), None, None, None, Some(7620879), None), (None, None, Some(false), Some(709137), Some(-6798937), None), (None, Some(155), None, None, None, Some(53971)), (None, None, None, Some(512547), None, None), (Some(-781268908), Some(180), Some(true), Some(320437), Some(-7784187), None), (None, Some(118), None, None, Some(-7104179), Some(64647)), (Some(-387141578), None, None, Some(724630), None, None), (Some(1118827776), Some(239), None, Some(758105), Some(-1875690), Some(34533)), (Some(-462294236), Some(141), None, None, None, None), (Some(-1830973123), None, None, None, Some(-9314100), None), (None, None, None, Some(-392056), Some(-2247313), Some(16455)), (Some(731587635), Some(231), Some(true), Some(524478), Some(4650604), Some(55120)), (None, Some(195), Some(false), None, Some(7814666), None), (Some(1928393249), Some(191), None, Some(-795534), Some(-5813891), Some(40791)), (Some(1765519746), None, None, None, Some(9978207), Some(59999)), (None, Some(215), Some(true), None, Some(933514), None), (None, None, None, Some(903812), None, Some(41290)), (None, None, None, Some(-915727), None, None), (None, None, None, Some(141691), Some(-3920585), Some(8333)), (Some(864517806), Some(35), Some(true), None, None, None), (None, Some(64), None, None, None, None), (None, Some(252), None, Some(919291), None, None), (None, None, Some(false), None, None, None), (Some(2065669927), None, Some(true), Some(141826), None, Some(32515)), (None, Some(31), None, Some(-788940), Some(8148973), None), (Some(-693672093), None, Some(true), None, None, None), (None, None, None, None, Some(5775146), None), (Some(-129523208), Some(18), Some(true), None, Some(-6320156), Some(34621)), (None, Some(196), None, Some(974833), Some(-4878860), None), (Some(1635783548), None, None, None, Some(-9718517), None), (Some(-429370960), Some(6), None, None, Some(-9342807), None), (Some(-275155882), None, Some(true), None, None, Some(25297)), (Some(242016790), None, None, None, Some(9543192), None), (Some(-1866162573), Some(66), None, None, Some(-7785590), None), (None, Some(31), Some(false), Some(-550992), Some(-8817836), None), (Some(1672145878), None, Some(true), Some(842278), None, Some(6507)), (Some(-170223892), None, Some(true), None, None, None), (None, None, None, None, None, Some(9910)), (Some(-143946099), None, None, Some(-511081), None, None), (None, None, Some(false), Some(-588143), Some(727221), Some(9259)), (None, Some(198), None, None, None, None), (None, None, None, None, None, Some(31941)), (Some(407682409), None, Some(false), Some(824637), None, None), (Some(-373462201), None, Some(true), Some(323908), Some(5720101), Some(57351)), (Some(-197223905), None, None, Some(-49593), Some(-1920177), None), (None, None, None, None, None, Some(59991)), (None, Some(43), Some(true), Some(-731230), None, None), (None, Some(237), None, Some(-27368), None, Some(53824)), (Some(891998699), None, Some(true), None, Some(7993086), Some(54189)), (None, Some(33), None, None, None, None), (Some(-1257928680), None, None, None, None, Some(13246)), (None, Some(87), None, Some(389473), None, Some(4967)), (None, Some(211), Some(false), Some(-527584), None, None), (None, Some(180), Some(true), Some(674187), Some(-4580403), Some(31359)), (None, Some(189), Some(false), None, None, Some(32027)), (None, Some(70), Some(false), None, Some(9463964), Some(54164)), (None, Some(165), None, Some(982878), None, Some(22431)), (None, Some(93), Some(false), None, Some(3143963), None), (None, Some(101), Some(false), None, None, Some(35329)), (Some(-1231248015), Some(130), None, Some(-484894), None, None), (Some(221121179), Some(189), None, None, None, Some(61318)), (None, None, None, None, None, None), (None, None, Some(false), None, None, Some(39788)), (None, Some(111), None, None, None, None), (None, None, None, Some(-131600), Some(6512762), None), (Some(-1368760893), Some(73), None, None, None, None), (Some(760782699), Some(48), Some(true), None, None, None), (Some(222293776), None, Some(true), Some(739968), None, Some(22231)), (None, Some(195), None, Some(-689926), Some(-2378584), Some(30634)), (Some(-1881212545), Some(69), None, Some(694643), Some(-9125345), None), (Some(1749396031), None, None, Some(698013), None, Some(18133)), (None, Some(190), Some(true), Some(-249805), None, None), (Some(-1028469524), Some(74), None, None, None, None), (None, None, None, None, None, Some(52913)), (None, Some(39), None, Some(595104), Some(-1848458), None), (Some(2039742879), Some(96), None, None, Some(9822352), None), (Some(-366821144), Some(195), None, None, Some(-3700742), Some(45380)), (None, Some(145), Some(false), Some(-671025), None, None), (None, None, Some(false), None, Some(-7624748), Some(65338)), (None, None, Some(false), None, Some(-7585031), Some(35863)), (None, Some(65), Some(true), None, None, None), (Some(2078122724), None, Some(false), Some(-378864), Some(-7338706), Some(39722)), (Some(1337282654), None, Some(true), None, Some(-5918090), None), (None, None, Some(true), Some(-170358), Some(-1933809), Some(40448)), (Some(1880572329), None, Some(true), Some(835997), Some(1567766), None), (None, None, Some(true), Some(-736181), Some(-8981710), None), (Some(559114209), Some(185), Some(false), Some(-53207), Some(2173032), None), (None, None, None, None, Some(-3317347), None), (Some(1321856838), Some(69), Some(false), Some(43950), Some(9886167), Some(50111)), (None, None, None, None, None, None), (Some(-1889246740), None, None, None, None, Some(54504)), (Some(49924813), Some(245), Some(false), None, None, None), (None, None, Some(false), None, Some(4082541), Some(11047)), (Some(-1566186335), None, Some(false), None, None, None), (Some(1764324594), None, Some(false), None, None, Some(32311)), (None, None, Some(true), None, Some(-2588345), Some(43784)), (Some(1534970158), None, None, None, None, Some(11664)), (None, Some(89), None, Some(597272), Some(-1173559), Some(27738)), (None, None, None, None, Some(-4913285), Some(16589)), (None, Some(19), None, Some(979671), None, Some(45313)), (None, Some(201), None, Some(985762), Some(3026607), None), (None, Some(185), Some(true), None, None, None), (None, Some(92), None, Some(-88241), None, Some(39098)), (None, None, None, None, None, None), (None, Some(70), None, None, Some(1160716), None), (Some(893384832), Some(235), Some(true), Some(152500), Some(8836235), None), (None, Some(200), Some(false), None, None, None), (Some(-2134451848), Some(75), None, Some(773274), None, Some(37948)), (Some(815587803), Some(117), Some(true), Some(776596), None, None), (Some(-1806020798), None, Some(true), Some(-461864), Some(-5723159), Some(17046)), (Some(919375473), Some(16), None, Some(-436836), None, Some(14531)), (Some(441638841), None, None, Some(762777), None, None), (None, Some(255), None, None, None, None), (None, None, Some(true), Some(-592147), Some(-5482792), None), (None, None, None, Some(-288248), None, None), (None, Some(208), None, Some(-66804), None, None), (None, None, Some(false), None, Some(9032068), Some(26500)), (None, Some(243), None, None, Some(-6398824), None), (Some(1819628537), Some(14), Some(false), None, None, Some(41443)), (Some(-889255554), None, Some(false), Some(-876285), Some(7256334), None), (Some(2127038665), Some(155), Some(true), None, None, None), (Some(1164629477), None, Some(true), None, Some(8441020), Some(63181)), (None, Some(17), Some(false), None, Some(-8025866), Some(44919)), (Some(-1143658392), None, None, None, Some(-4478517), Some(12056)), (None, None, Some(false), Some(-358040), Some(4745961), Some(26856)), (None, None, None, Some(-557118), None, Some(37425)), (None, None, None, Some(870887), Some(-6862787), Some(60297)), (None, Some(114), None, None, None, Some(33692)), (Some(1091950641), None, Some(false), None, Some(2239901), None), (None, Some(151), Some(false), None, None, Some(63155)), (Some(1785039909), None, Some(true), Some(185244), None, None), (Some(-468314299), None, None, None, Some(-6664748), Some(3177)), (Some(-373722135), Some(219), Some(true), None, None, Some(34968)), (Some(75462523), None, None, Some(-689294), Some(4936457), Some(64135)), (Some(-797372797), Some(101), Some(true), Some(-451871), Some(521562), Some(36009)), (Some(1066805358), Some(170), Some(true), None, Some(-2063880), Some(17840)), (Some(-781741961), None, Some(true), None, None, Some(16201)), (None, Some(92), None, None, Some(-4197967), Some(27658)), (None, None, Some(false), None, Some(-5186489), Some(35230)), (Some(1504987316), None, None, None, None, Some(31534)), (Some(-646618712), Some(154), Some(true), None, None, Some(26359)), (None, Some(72), None, None, None, None), (Some(903987067), Some(0), Some(true), None, Some(8859286), None), (None, None, None, None, Some(-5814971), None), (Some(-579878900), Some(4), None, None, None, None), (None, None, None, Some(656540), Some(2976140), Some(2226)), (None, None, Some(false), Some(305667), Some(8513142), Some(39651)), (Some(-1633952360), None, Some(false), None, None, None), (Some(696348758), Some(139), Some(false), Some(997644), None, Some(45682)), (None, Some(178), Some(true), Some(-626655), Some(9723937), None), (Some(-984334663), None, None, Some(743317), Some(-5747657), None), (Some(1839123245), Some(88), Some(false), Some(255443), Some(-3178465), Some(50731)), (None, None, None, Some(-665836), None, Some(21139)), (Some(-1978865346), None, None, None, Some(4494657), Some(49454)), (None, Some(205), None, Some(-239973), None, Some(27501)), (None, Some(246), None, Some(-817208), Some(-8118500), None), (Some(1191936132), Some(97), Some(false), Some(330759), Some(-2942976), Some(49374)), (None, None, None, Some(-733028), None, None), (Some(986548645), Some(172), None, None, Some(5213227), None), (None, None, Some(false), None, None, None), (None, Some(162), Some(false), None, None, Some(333)), (None, None, Some(true), Some(719424), Some(1484529), None), (Some(-2127909646), None, Some(true), Some(-458194), Some(2025634), Some(57830)), (Some(1490575391), None, None, Some(481172), Some(4086222), None), (Some(-1646533256), Some(94), Some(true), Some(-508638), Some(-6733450), Some(31565)), (None, Some(56), Some(false), Some(914137), Some(4995157), Some(50747)), (Some(-645988673), None, None, Some(-414074), Some(1976206), None), (Some(2041684617), None, None, Some(-923783), Some(-4062813), Some(11121)), (None, None, None, Some(-611899), None, Some(40381)), (None, None, None, None, Some(-5645614), Some(60766)), (Some(1996746296), None, Some(true), None, Some(-3154060), Some(5733)), (Some(1198435475), Some(63), None, Some(-696993), Some(2402133), Some(6960)), (None, Some(24), None, Some(-263655), None, Some(65188)), (None, Some(97), Some(true), Some(307650), None, None), (Some(582172037), Some(161), Some(true), Some(185905), None, None), (None, Some(254), None, None, None, Some(26061)), (Some(-964828908), None, None, Some(104882), Some(-2180942), Some(33116)), (None, None, Some(true), None, Some(3081187), None), (Some(-1546681411), None, None, Some(-178212), Some(9599440), None), (Some(-1362465730), Some(92), Some(false), Some(-143994), Some(5848420), None), (Some(-169513385), Some(73), None, Some(-559345), None, Some(12793)), (None, None, None, Some(993355), None, Some(49455)), (None, Some(254), None, None, Some(5971985), None), (Some(-1336719737), Some(147), None, Some(-18403), None, None), (Some(-1417996099), Some(228), None, Some(426491), Some(-2298696), None), (None, Some(43), Some(false), None, Some(-2339351), None), (Some(2088244076), None, None, None, Some(6949001), None), (Some(-654227269), None, None, None, Some(9553862), None), (None, None, None, Some(533656), Some(6404385), Some(48001)), (Some(-332528233), None, None, Some(483805), None, Some(57973)), (Some(539847309), None, Some(true), None, Some(-7932929), None), (Some(-677127213), Some(113), Some(true), None, Some(-9381505), Some(58252)), (Some(-2033966082), None, None, Some(553641), Some(-7621280), Some(16818)), (None, Some(94), None, None, Some(-9030150), None), (Some(-6969878), None, Some(false), None, Some(9709882), None), (Some(-511652228), Some(161), Some(false), None, Some(-8660697), None), (Some(1447754906), None, None, None, Some(-4818071), Some(56026)), (None, Some(27), None, None, Some(-308451), Some(36988)), (Some(-1361245727), Some(193), Some(false), Some(-926977), Some(8651859), None), (None, Some(21), None, None, Some(-6025830), Some(56494)), (Some(461396183), None, None, Some(-353998), Some(1598934), None), (None, None, None, Some(-501359), Some(-4569489), None), (None, Some(236), None, Some(70905), Some(-2893891), Some(535)), (Some(1708246679), None, Some(false), None, Some(-8998812), Some(7652)), (None, Some(85), Some(false), None, Some(3388267), Some(11594)), (Some(-418993577), None, None, None, None, None), (Some(-1935314722), None, Some(true), None, None, None), (None, Some(237), None, Some(359082), None, Some(35153)), (None, Some(30), Some(false), None, Some(6778213), Some(3385)), (Some(-1347650113), Some(5), Some(true), Some(994541), Some(6903299), None), (Some(-1780874149), Some(189), None, Some(192435), None, None), (None, Some(27), Some(false), None, None, Some(34333)), (Some(-700149351), Some(38), Some(true), Some(792168), Some(1960175), None), (None, None, Some(false), None, Some(-5132054), None), (None, Some(242), None, None, None, Some(10589)), (None, Some(247), Some(false), None, None, None), (None, None, None, None, Some(3292414), None), (None, None, None, Some(-723957), Some(-1117420), None), (Some(1640199135), None, None, None, Some(9553502), None), (None, None, Some(false), Some(739730), Some(9236699), None), (None, None, None, Some(-746276), Some(3743641), None), (Some(919245639), Some(29), None, Some(-580777), Some(-4470911), Some(4945)), (Some(1253175990), Some(223), Some(true), None, Some(-3899515), Some(5281)), (None, Some(93), Some(false), None, None, None), (None, None, Some(true), None, None, Some(36481)), (Some(-1963480052), None, None, None, None, Some(50843)), (Some(778806780), None, None, Some(844532), Some(-2907443), None), (Some(-1120937292), None, Some(true), None, None, None), (Some(1224098469), Some(66), None, Some(962057), Some(7682720), None), (Some(-699011748), None, Some(false), Some(-660286), None, None), (Some(-1479562774), Some(183), Some(true), Some(-129511), None, Some(21877)), (Some(-333152916), Some(63), None, Some(-237923), Some(4242280), Some(5796)), (None, Some(98), Some(true), Some(-600408), None, Some(31397)), (None, None, Some(true), Some(-331547), Some(3738745), None), (None, Some(232), Some(true), None, Some(6450613), Some(5062)), (Some(-758457602), None, Some(false), Some(-737276), Some(-280580), None), (None, Some(204), Some(false), Some(78629), Some(7639134), None), (None, Some(26), None, None, None, Some(1911)), (None, Some(249), Some(true), None, Some(-4869638), Some(16800)), (Some(-1469413043), None, Some(false), None, None, Some(43246)), (None, Some(232), Some(true), Some(129320), Some(7376608), None), (Some(-1039579225), None, Some(true), Some(621876), Some(-8156311), None), (None, Some(157), None, None, None, Some(43107)), (None, Some(233), None, None, None, None), (Some(597417906), Some(138), None, Some(524120), None, Some(64864)), (Some(1726666004), Some(222), Some(false), None, Some(-8891669), None), (Some(-801764449), Some(102), None, Some(-414973), None, None), (None, Some(98), None, Some(441903), None, None), (Some(-1053297316), Some(141), None, Some(673752), Some(4321143), Some(27627)), (None, None, None, Some(344726), None, None), (Some(-1773216871), None, Some(false), Some(380048), Some(-4253066), Some(48414)), (None, None, None, Some(-157205), None, Some(52058)), (Some(-1938955348), Some(250), None, Some(347377), Some(-8024668), Some(25770)), (None, Some(193), None, None, None, Some(37379)), (Some(1293012514), None, None, Some(-50066), None, None), (None, None, None, None, Some(-6399141), Some(10790)), (Some(591269625), None, None, None, Some(-9706691), None), (None, Some(177), None, None, None, None), (Some(-749366242), None, None, Some(-618524), None, None), (Some(157712461), Some(162), None, None, None, Some(15420)), (Some(832056920), Some(85), None, None, None, None), (Some(-174069390), Some(12), None, Some(463082), None, Some(5135)), (None, Some(225), Some(true), Some(-759766), None, Some(36135)), (None, Some(76), None, Some(-701598), None, None), (Some(887083957), Some(160), None, None, Some(-8314000), None), (None, None, None, Some(549678), None, Some(34465)), (Some(-1471325513), Some(157), None, None, None, Some(34535)), (None, Some(154), Some(true), None, Some(-4272560), Some(45855)), (Some(1950324183), None, None, Some(-562210), None, None), (Some(1776016616), None, Some(true), Some(-954696), Some(4333620), None), (Some(850350959), Some(53), Some(true), None, None, None), (None, None, Some(false), None, Some(-1330922), Some(14094)), (Some(1167698515), None, None, None, None, Some(52106)), (None, None, Some(true), None, Some(6075680), None), (Some(1201981386), Some(162), None, Some(-560162), Some(5055032), Some(54674)), (None, Some(208), Some(true), Some(-363783), None, None), (None, None, None, None, Some(525730), None), (Some(-1064831646), Some(198), None, None, Some(-7194349), None), (None, Some(85), None, Some(-922139), Some(8349060), None), (Some(-1051550040), Some(233), None, None, Some(5726468), Some(32801)), (Some(824906408), Some(67), None, Some(161084), None, None), (None, None, None, None, Some(623270), None), (None, Some(179), None, Some(-668646), None, None), (Some(1981478364), Some(26), Some(true), None, None, None), (None, Some(91), Some(false), None, Some(8885146), Some(20934)), (Some(972725676), Some(82), Some(true), None, None, None), (Some(648867640), Some(28), Some(false), None, None, None), (None, Some(44), None, Some(445579), Some(9036754), None), (None, Some(128), None, Some(556558), None, None), (Some(-1134245241), Some(53), None, Some(-906423), None, None), (Some(1689119793), None, Some(true), None, None, Some(12606)), (None, Some(235), Some(true), Some(132720), None, None), (Some(-261485697), Some(179), Some(true), Some(885277), None, Some(38082)), (Some(791320441), None, Some(false), None, None, None), (None, None, Some(false), Some(670863), Some(3956159), None), (None, Some(254), None, None, None, None), (Some(-692986561), None, Some(false), Some(27454), None, Some(35235)), (Some(-836956842), None, None, None, Some(7208031), Some(13009)), (Some(-1892202803), Some(68), Some(true), None, Some(-9928236), None), (None, None, None, Some(-221572), None, Some(56865)), (Some(-724987042), None, None, None, Some(8392345), None), (None, Some(57), None, Some(280522), Some(429597), None), (None, Some(174), Some(false), Some(529971), Some(1257859), None), (Some(-1686750136), Some(219), Some(false), Some(-873195), Some(-2047865), None), (Some(1339592951), None, None, None, Some(-7368019), None), (Some(969792462), Some(252), Some(true), None, None, None), (None, Some(186), Some(false), Some(717943), None, None), (Some(218845310), Some(39), Some(false), None, Some(-7947128), None), (Some(-954757537), None, None, None, Some(-8901359), None), (None, None, None, None, Some(7677241), Some(47072)), (None, Some(81), None, Some(23642), Some(3513647), Some(9108)), (None, Some(23), None, None, None, Some(11793)), (None, None, Some(false), Some(435306), Some(-7026443), Some(30913)), (None, Some(218), Some(false), None, None, Some(4951)), (None, Some(77), Some(true), Some(-125951), None, None), (None, Some(233), Some(true), None, None, None), (Some(1590147789), Some(109), None, None, None, Some(26231)), (None, Some(171), Some(true), Some(-128016), None, Some(12934)), (Some(1390183836), None, None, Some(-640557), Some(3750764), None), (None, None, Some(false), Some(465778), None, Some(63431)), (Some(1225688293), Some(211), None, None, None, None), (Some(1012989311), None, Some(true), Some(-475989), None, Some(49838)), (None, Some(86), None, None, Some(-2738394), Some(23965)), (Some(-1071743063), Some(100), Some(false), Some(-9611), Some(-3794142), None), (Some(2131589433), None, Some(false), Some(-576818), Some(-5414057), Some(14758)), (None, None, None, None, None, None), (Some(-2132289167), Some(180), None, Some(387885), None, None), (None, Some(169), Some(true), Some(-761473), Some(-6063628), Some(19491)), (None, Some(244), None, Some(190512), Some(7161409), None), (None, None, None, Some(-334962), None, Some(38822)), (Some(-820091398), None, Some(true), Some(-498094), None, None), (None, Some(216), None, None, None, None), (Some(845831514), None, None, None, Some(8755911), Some(17098)), (Some(-1946091115), None, Some(false), Some(-293075), None, Some(229)), (Some(-993164538), None, Some(false), Some(163103), None, None), (Some(-2119864263), Some(234), None, Some(-329185), None, Some(35237)), (Some(-1870239025), Some(219), Some(true), None, None, None), (Some(219958889), Some(21), None, None, None, None), (Some(1488209844), Some(195), Some(false), Some(550091), Some(-7770102), Some(29128)), (Some(135100429), None, Some(false), None, Some(-7779909), None), (Some(1544216450), Some(213), None, None, None, None), (Some(-438425010), Some(93), Some(true), None, None, None), (None, Some(218), None, None, None, None), (None, None, Some(true), None, None, None), (None, Some(181), Some(false), Some(228996), None, Some(63161)), (None, Some(133), Some(false), Some(986778), Some(454189), None), (Some(2012548555), None, Some(false), Some(-780185), Some(-5914507), Some(32423)), (Some(2118808285), Some(4), None, Some(-152720), Some(6255190), None), (Some(-407331133), None, Some(false), None, None, None), (Some(-723576732), None, Some(false), None, None, None), (Some(1898378526), None, Some(true), None, None, Some(12220)), (Some(-936662562), None, None, None, None, None), (None, None, Some(true), None, Some(8816751), None), (Some(-2030148165), Some(143), None, None, Some(-4318453), Some(63109)), (Some(472730939), None, Some(false), None, Some(-9400693), Some(29697)), (Some(1297376776), None, None, None, None, Some(48216)), (Some(125946477), None, None, Some(-392541), None, None), (Some(358678449), Some(10), None, None, Some(-1061295), Some(36954)), (None, None, None, None, None, None), (None, Some(97), None, Some(613299), Some(2584286), Some(51358)), (Some(1844563748), None, None, None, Some(-7709310), Some(35177)), (Some(-1305010894), None, None, None, None, None), (Some(876527928), None, Some(true), Some(965072), Some(-6199547), Some(23850)), (None, Some(143), None, Some(-20225), None, Some(52207)), (Some(-1730062289), None, None, None, None, Some(32267)), (None, None, None, None, None, Some(26880)), (None, Some(189), None, Some(-825077), None, None), (None, None, None, Some(622756), None, Some(34861)), (Some(-998463036), Some(90), None, Some(-631563), Some(-7047532), Some(39985)), (None, None, None, None, None, Some(65030)), (None, Some(84), None, None, None, None), (Some(810233495), Some(134), None, None, Some(-5929410), Some(27439)), (None, None, None, None, None, None), (None, Some(178), Some(true), Some(-735843), None, Some(51740)), (Some(1807210238), None, Some(true), None, None, Some(22458)), (None, None, Some(true), None, Some(2190981), None), (Some(1845054827), None, Some(true), Some(-571066), Some(8514436), Some(38948)), (Some(553135096), Some(17), Some(false), Some(673217), Some(-8063384), Some(3280)), (None, Some(108), Some(true), Some(901489), Some(4656669), Some(50381)), (None, Some(136), Some(false), Some(724572), Some(-4163310), Some(4790)), (Some(-1692506156), None, None, Some(-604492), Some(-6475715), None), (None, None, None, None, None, Some(42843)), (Some(-765596370), None, None, Some(188845), None, None), (None, None, None, Some(-998988), Some(1320884), Some(23688)), (None, Some(197), Some(true), None, Some(4690530), Some(63052)), (None, Some(247), None, None, Some(2860313), Some(21107)), (None, Some(25), None, Some(-664214), None, Some(42008)), (Some(1298383441), Some(27), None, Some(-252780), Some(8843779), None), (Some(-1693265447), Some(149), Some(false), None, None, Some(53847)), (None, Some(16), None, None, None, Some(33266)), (None, None, None, Some(954477), None, None), (Some(872144867), None, Some(true), None, None, Some(44438)), (Some(2104762446), Some(178), None, None, None, None), (None, Some(226), Some(true), Some(492307), None, None), (None, Some(201), None, Some(-889117), None, None), (None, None, Some(true), Some(414615), None, None), (Some(821970282), None, None, Some(-531185), None, None), (None, Some(125), Some(true), Some(-175704), Some(9518993), Some(1921)), (Some(-1786334232), Some(39), Some(true), None, Some(6231517), Some(57516)), (Some(-1465525585), Some(234), None, None, Some(1763940), None), (Some(1733280919), None, None, Some(526691), None, None), (Some(2057237956), Some(29), None, None, Some(-5926973), None), (None, Some(150), Some(false), Some(450406), None, Some(50937)), (None, None, Some(true), None, Some(7002049), Some(25677)), (Some(-2021961954), None, Some(true), Some(-591836), None, None), (Some(-302923367), Some(4), None, None, Some(-3166172), None), (Some(506118609), Some(240), Some(true), Some(850641), None, None), (Some(-1611097834), Some(114), None, Some(346267), Some(-1659911), Some(25643)), (None, Some(127), None, None, Some(5921300), Some(36243)), (None, None, None, None, None, Some(60169)), (Some(-795301360), Some(109), Some(true), Some(459320), Some(1413297), None), (Some(307430062), Some(113), None, None, Some(-6282463), Some(46266)), (None, None, None, Some(605248), Some(8120717), None), (Some(-1079031912), Some(91), Some(true), Some(863764), Some(3858849), None), (None, Some(182), Some(false), Some(83576), Some(9724371), None), (Some(116279169), None, Some(false), Some(953513), Some(3104898), None), (None, Some(106), None, Some(-580209), None, Some(53134)), (Some(-111361198), Some(110), None, None, None, None), (None, Some(42), Some(true), None, Some(8892027), None), (None, Some(20), Some(false), Some(348794), Some(-4302095), Some(39388)), (Some(-1326666559), Some(71), Some(false), Some(-450287), None, None), (None, Some(162), None, Some(144925), Some(-3411772), None), (None, None, None, Some(-348999), None, Some(44558)), (Some(908165045), None, None, None, None, Some(33479)), (Some(1910328527), Some(243), Some(false), Some(-844184), None, None), (Some(-1645709533), None, None, Some(343731), Some(2159277), None), (Some(-908550133), None, None, Some(987311), None, None), (Some(-227797150), None, None, Some(947159), Some(4797323), Some(18450)), (None, None, None, Some(-452075), None, None), (None, Some(59), None, None, Some(-8657018), Some(10906)), (Some(-126805663), None, Some(true), None, Some(4649564), None), (None, None, None, Some(301142), Some(-6835637), None), (Some(163862412), None, Some(false), Some(306746), Some(5847549), Some(5125)), (None, Some(167), None, Some(57130), Some(-5651351), None), (Some(-699325465), None, None, None, Some(7986976), None), (None, None, Some(false), Some(-349700), Some(3722385), Some(32740)), (None, None, None, Some(604016), Some(-4524713), None), (Some(900796364), None, Some(true), None, None, Some(34532)), (None, None, None, None, None, Some(23105)), (None, None, Some(true), None, None, Some(50156)), (None, None, None, None, Some(-7102651), None), (None, None, None, None, None, Some(51955)), (None, None, None, Some(949141), Some(4939907), Some(12379)), (Some(1066667353), Some(197), None, None, Some(-2608458), None), (Some(907009162), Some(185), Some(false), None, Some(-7920094), Some(3722)), (None, None, None, None, None, Some(40404)), (Some(2047497789), Some(199), None, None, Some(-4375378), Some(40649)), (None, None, Some(true), None, Some(6532157), Some(48489)), (Some(-641875677), None, Some(false), Some(-406375), None, None), (None, None, None, None, Some(5109256), Some(61083)), (Some(266470147), Some(86), Some(false), Some(26595), Some(-6739575), Some(23653)), (Some(1715364248), None, Some(true), None, None, Some(11776)), (None, None, Some(false), None, Some(7485447), None), (None, None, None, None, Some(-1881550), Some(11186)), (Some(-2015023165), None, None, None, None, Some(64565)), (Some(1991039528), Some(27), Some(false), None, None, None), (None, None, Some(false), Some(-964966), None, Some(42758)), (Some(-629339374), Some(28), None, Some(-706265), Some(-3844811), None), (None, None, Some(false), Some(-624681), None, Some(58891)), (None, None, None, Some(-730320), None, None), (Some(-1899978476), None, None, Some(540604), Some(-5258116), None), (None, None, None, None, Some(-2496638), Some(56647)), (None, None, None, None, None, Some(59519)), (Some(-1744043199), None, Some(true), None, None, Some(12647)), (None, None, Some(true), Some(189360), Some(-8949652), Some(14647)), (None, Some(99), Some(false), Some(214568), None, Some(37081)), (None, Some(6), None, Some(628196), None, Some(23092)), (Some(306033679), None, Some(false), None, Some(2423117), Some(2459)), (None, Some(194), None, Some(-662460), None, Some(59483)), (None, Some(18), Some(true), Some(721552), None, Some(22715)), (None, Some(198), Some(false), Some(-600551), None, Some(64458)), (Some(-1656265879), None, None, None, None, Some(822)), (None, None, Some(true), Some(512425), None, Some(23353)), (Some(-2010194289), None, None, Some(-861972), None, Some(60006)), (Some(-178268176), None, Some(false), Some(885882), None, Some(54590)), (Some(562630867), Some(195), None, None, Some(-8834362), Some(29200)), (Some(-668512835), None, None, Some(250232), Some(-8734618), Some(15440)), (Some(-1892673631), None, Some(true), None, Some(-6500944), Some(51736)), (Some(-291384829), Some(220), Some(true), Some(425769), Some(1809264), Some(23331)), (Some(-1817088212), None, None, None, None, Some(5348)), (Some(-637614366), None, Some(true), Some(-834210), Some(7329459), Some(63523)), (None, Some(18), Some(false), None, Some(9051990), Some(16889)), (None, Some(154), Some(false), Some(704318), Some(1619083), Some(52411)), (None, None, Some(true), None, Some(1249711), Some(60398)), (None, None, Some(true), Some(792872), Some(4116359), Some(33701)), (Some(1140074522), None, None, Some(-141058), None, None), (Some(1619111616), Some(226), Some(true), None, Some(-1193399), Some(50849)), (Some(-387855600), None, Some(true), Some(-541124), Some(-5476913), Some(50307)), (Some(-1902651803), None, None, Some(144305), Some(-6260027), Some(11694)), (Some(608789864), Some(183), None, None, None, None), (Some(-1699716652), None, None, None, Some(6128479), None), (None, None, Some(true), None, Some(-3928487), None), (None, None, None, None, None, Some(3346)), (Some(-2035476031), None, Some(false), None, None, None), (None, None, Some(false), Some(630957), None, None), (Some(-97435282), Some(48), None, None, Some(-5687563), None), (None, Some(171), Some(true), Some(-401377), None, Some(44605)), (None, Some(187), Some(false), None, None, None), (Some(-1604832479), Some(187), Some(false), None, None, Some(29088)), (None, Some(237), Some(true), Some(-237935), Some(-9708640), Some(39890)), (Some(2036018305), Some(12), None, None, None, Some(44723)), (None, None, None, Some(-420108), None, Some(18194)), (None, None, None, None, None, Some(30398)), (None, None, Some(false), Some(488999), None, Some(5170)), (Some(-1986593109), None, None, Some(203644), None, None), (None, None, None, Some(764497), None, None), (Some(527200265), None, Some(false), Some(915509), None, None), (None, None, Some(false), Some(383402), Some(-6921930), None), (Some(853190966), Some(128), None, Some(356746), Some(2688836), Some(55811)), (None, None, None, None, Some(-6759587), Some(2383)), (None, Some(240), Some(true), Some(425923), Some(2472689), Some(40805)), (Some(242677181), None, None, Some(564965), Some(-4272336), None), (Some(1194471772), Some(254), None, None, None, Some(49169)), (None, Some(236), None, Some(135038), Some(1650526), Some(4601)), (None, Some(162), None, None, None, Some(6594)), (None, None, None, None, Some(-6993120), None), (None, Some(141), Some(false), Some(907095), Some(4937363), None), (Some(185102954), Some(194), Some(false), None, Some(-9675382), Some(46940)), (None, Some(201), None, Some(314135), Some(-2857753), None), (None, Some(10), None, None, Some(-5871721), Some(51715)), (None, Some(168), Some(false), None, None, Some(34083)), (Some(-967362454), None, None, None, Some(7678205), Some(56280)), (None, Some(188), Some(false), Some(458259), Some(9460214), Some(38945)), (Some(2145755126), Some(115), Some(true), Some(-53614), None, Some(9828)), (Some(1111811510), None, None, Some(-669720), None, Some(3288)), (None, Some(67), Some(false), Some(165286), None, None), (Some(-1395619468), Some(23), Some(false), None, None, Some(61425)), (Some(-1582955041), None, None, Some(-990580), None, None), (Some(381385550), None, None, Some(-384734), None, Some(9184)), (None, Some(64), None, Some(207311), None, None), (Some(820375297), Some(225), Some(false), Some(37356), Some(-5729551), Some(56367)), (None, Some(50), Some(false), None, Some(2722803), None), (Some(-2064965857), Some(197), None, Some(773448), Some(-2653713), Some(33367)), (Some(-1414299507), Some(246), None, None, Some(-7819363), Some(3357)), (Some(849583899), Some(123), Some(true), Some(-584160), Some(-8542055), Some(12784)), (Some(296217284), None, None, Some(266242), Some(-8902314), None), (None, None, Some(false), Some(938946), None, None), (None, None, None, Some(437387), None, None), (Some(2094262998), None, None, Some(-624456), None, None), (Some(-220701293), None, None, None, None, None), (None, None, None, Some(-405189), None, None), (Some(1884612074), None, Some(false), Some(-685143), None, None), (Some(73253929), Some(12), Some(false), Some(-163281), None, Some(3544)), (Some(-1828767810), Some(70), Some(true), Some(825905), Some(-3480151), Some(47342)), (None, None, Some(false), None, None, Some(39514)), (Some(-728509714), Some(170), Some(false), None, None, Some(2199)), (None, None, None, Some(728908), None, None), (Some(-1950412052), Some(47), None, Some(-481936), None, None), (Some(-1437580513), None, None, None, Some(-57952), None), (Some(-496883721), Some(220), None, Some(-323635), None, Some(14371)), (Some(-1073254545), None, Some(true), Some(-969797), None, None), (Some(1911831120), None, Some(true), None, None, Some(12353)), (None, None, None, Some(-547133), None, Some(49111)), (None, Some(217), None, Some(53931), None, None), (None, None, None, None, None, None), (None, None, None, None, Some(3836665), Some(34268)), (None, Some(129), None, None, Some(-8207461), None), (Some(487296554), Some(206), None, None, None, Some(17068)), (Some(861192279), None, None, Some(156109), None, None), (None, None, Some(false), Some(654417), Some(1454137), None), (None, Some(176), Some(false), None, None, Some(44743)), (None, Some(50), Some(false), Some(894753), None, Some(40589)), (None, Some(23), Some(true), Some(368185), None, Some(31974)), (Some(-2055116030), None, None, Some(-212357), None, Some(59988)), (Some(1099908259), Some(211), None, Some(-790009), Some(-4835761), None), (None, None, None, Some(513647), Some(-3206595), Some(47417)), (None, None, Some(false), None, Some(-3970279), Some(26675)), (None, Some(140), None, Some(-947706), Some(-7995619), None), (Some(-2067460917), Some(4), None, None, Some(9906640), None), (None, None, None, Some(965375), Some(8396586), None), (None, Some(203), None, Some(-866691), Some(-1528023), Some(37682)), (Some(-2012000869), Some(211), None, Some(277148), Some(627424), Some(757)), (None, None, Some(false), None, None, Some(19181)), (None, None, None, None, None, Some(61526)), (Some(-77777978), None, None, Some(-586007), Some(294396), Some(34267)), (Some(1654958520), None, None, Some(-975187), Some(-5444348), Some(54667)), (Some(-2014736651), Some(59), Some(false), None, Some(3269837), None), (None, Some(109), Some(false), None, Some(-4593161), None), (Some(-598477904), Some(31), None, Some(-756892), Some(5903495), None), (None, Some(239), None, Some(-337920), Some(8779148), None), (Some(-892470136), None, Some(true), None, None, None), (None, Some(12), Some(false), Some(246616), None, Some(7680)), (None, Some(84), Some(false), None, None, Some(18373)), (None, None, Some(true), Some(583784), None, Some(36959)), (None, Some(0), None, None, None, Some(39591)), (None, Some(205), None, Some(-840951), Some(-6999375), Some(45045)), (None, Some(131), None, None, None, Some(52633)), (None, Some(178), Some(true), Some(498807), Some(-308452), Some(33832)), (Some(1673811769), None, None, None, Some(4062550), Some(64106)), (None, Some(30), None, None, None, Some(50406)), (None, None, None, Some(-587931), None, Some(12237)), (None, Some(79), Some(true), Some(662585), None, Some(58363)), (None, Some(29), None, Some(136605), None, Some(29799)), (Some(2134461118), Some(133), Some(true), None, None, Some(30361)), (None, None, None, Some(-588965), None, Some(36217)), (None, Some(178), Some(true), Some(832047), Some(1216865), Some(56351)), (Some(-2095841521), None, Some(true), Some(675521), Some(1314446), None), (None, Some(8), None, Some(-905941), None, None), (None, None, Some(false), Some(-393756), Some(8141505), None), (None, None, Some(false), None, Some(-687022), None), (Some(-1470266462), None, Some(false), Some(-984643), Some(812370), Some(14448)), (None, Some(187), None, Some(-271041), None, None), (None, None, Some(true), Some(522315), None, None), (None, None, Some(false), None, Some(-722753), None), (Some(779731951), None, None, Some(558349), None, Some(52124)), (Some(290050145), None, None, None, None, None), (None, None, Some(true), None, None, None), (None, None, Some(true), None, None, Some(5320)), (None, None, Some(false), None, Some(3391547), Some(19879)), (None, None, Some(false), Some(969075), None, Some(39917)), (None, None, Some(true), None, None, Some(20122)), (None, Some(233), None, Some(-715874), Some(-8340693), Some(12031)), (None, None, Some(true), Some(-911578), Some(-4858226), Some(22579)), (None, Some(158), None, None, None, Some(48967)), (Some(147001659), Some(139), None, Some(350747), Some(6753342), None), (Some(-73011112), None, Some(false), None, Some(4101516), Some(49004)), (None, None, None, Some(-298704), None, None), (Some(2125208515), Some(69), Some(false), None, None, None), (None, None, None, Some(-254194), Some(-7582277), None), (None, None, None, None, Some(1638814), Some(45938)), (None, Some(16), Some(true), None, Some(-8706881), Some(22672)), (Some(-1080636625), None, Some(true), Some(-282125), None, None), (None, None, None, Some(-35374), Some(-9842116), None), (Some(345492730), None, Some(true), Some(160578), Some(-7009888), Some(44596)), (None, Some(167), None, None, None, None), (None, Some(240), Some(true), None, Some(-5781537), Some(146)), (Some(-1001150232), Some(96), Some(false), None, Some(-5568601), None), (None, Some(35), None, Some(-324564), Some(1057267), None), (None, None, None, Some(258016), None, None), (None, None, Some(false), Some(-717460), None, None), (None, Some(210), Some(true), None, None, Some(53006)), (Some(-443010530), None, None, None, Some(-182639), Some(27404)), (None, None, Some(true), None, None, None), (Some(-655883668), None, Some(false), Some(-875646), Some(-7973159), None), (None, Some(166), Some(true), Some(-196536), Some(6121228), Some(9679)), (Some(703800017), Some(154), None, None, Some(3890569), Some(15115)), (None, Some(162), None, None, None, Some(4120)), (None, None, None, None, None, Some(48867)), (None, Some(194), None, None, None, Some(18877)), (Some(1869058200), Some(79), Some(false), Some(398631), None, None), (None, Some(238), None, Some(-761873), Some(-4889373), None), (None, Some(54), None, Some(-710729), Some(-3418633), Some(34754)), (None, None, None, None, Some(786471), None), (None, None, Some(false), Some(548945), None, None), (None, None, Some(false), Some(-495547), None, Some(47234)), (Some(-533100253), Some(59), None, Some(41757), Some(9292164), None), (Some(-1613833273), None, None, Some(506458), None, None), (None, None, None, None, None, Some(16697)), (None, None, None, Some(167883), None, None), (None, None, None, Some(633498), Some(1322699), None), (None, Some(173), None, None, None, None), (Some(2026833501), None, None, None, Some(-9357496), None), (None, None, None, Some(282782), None, Some(25624)), (Some(-760447189), Some(32), None, None, Some(-4145241), None), (Some(1054719991), None, None, None, None, None), (Some(-504722566), None, None, None, Some(3530099), None), (Some(434393325), None, Some(true), None, Some(6196883), Some(9917)), (None, None, None, None, Some(5677519), Some(61452)), (Some(-862247413), None, Some(true), None, Some(-61278), Some(56163)), (None, Some(241), None, None, None, None), (Some(-1117541401), None, Some(true), None, None, None), (None, None, Some(false), None, Some(222842), None), (None, None, None, None, Some(3773295), None), (None, None, None, None, Some(-9079000), None), (Some(20289247), None, None, Some(-392185), Some(-3659228), Some(60668)), (None, Some(134), None, None, Some(2488542), Some(43157)), (Some(295759408), None, Some(true), None, None, None), (None, Some(163), None, Some(693665), Some(2601736), None), (Some(1830479093), Some(26), None, Some(-346807), None, None), (None, Some(52), Some(true), Some(240645), Some(6645588), None), (Some(569857785), None, None, None, Some(-779251), Some(10349)), (Some(-512005245), None, None, None, Some(-3070248), None), (Some(1443701576), Some(166), None, None, None, Some(20753)), (Some(1229294161), Some(49), None, None, None, Some(14499)), (Some(-45817208), None, None, None, None, Some(39602)), (Some(2109832854), None, None, None, Some(-4845163), Some(33241)), (None, None, Some(true), None, None, Some(64952)), (None, None, None, Some(-159620), None, Some(57170)), (None, None, None, None, None, Some(13619)), (None, Some(200), Some(false), None, None, None), (Some(1115027850), Some(98), None, Some(896246), None, Some(63212)), (Some(-1819555080), Some(246), Some(true), Some(-990862), Some(8052213), None), (Some(2113866199), None, None, None, Some(8340677), Some(46158)), (None, Some(198), None, None, Some(8509772), None), (Some(-617575308), None, Some(true), None, None, None), (Some(1126180946), None, None, None, Some(1621096), Some(13626)), (None, Some(137), Some(true), Some(579457), Some(-10077), Some(16742)), (Some(-680655377), Some(46), Some(false), None, Some(-8225925), Some(52783)), (None, None, Some(false), None, None, Some(42091)), (None, Some(242), Some(true), None, Some(4681207), Some(52967)), (Some(965225923), None, Some(true), Some(-85793), None, Some(13053)), (Some(1151834803), Some(237), None, None, Some(3933332), None), (Some(2136731429), None, None, Some(-550133), Some(315887), None), (None, Some(116), Some(true), Some(-532263), Some(4693630), None), (Some(523674833), None, None, Some(-939541), None, None), (Some(982905501), Some(157), None, Some(365930), Some(8587781), None), (Some(1304503270), Some(182), Some(false), Some(27968), Some(-7713401), None), (Some(-1343382692), None, None, None, Some(6342341), Some(57261)), (None, None, Some(false), None, None, Some(32516)), (Some(1497487231), Some(78), None, None, Some(1025734), Some(5724)), (None, None, None, Some(-146410), Some(8538422), Some(54131)), (Some(-721149489), None, Some(false), None, None, Some(15269)), (None, None, Some(false), Some(-397952), None, Some(23818)), (None, None, Some(true), Some(601971), None, None), (Some(-1023429563), None, Some(false), None, None, Some(36442)), (Some(877808884), Some(88), Some(false), None, None, Some(45894)), (None, None, None, None, None, Some(35344)), (Some(-994735985), Some(2), None, None, None, Some(24852)), (None, Some(101), None, None, None, Some(41464)), (None, Some(255), Some(false), None, None, Some(47516)), (None, Some(48), Some(false), None, Some(8522277), Some(21076)), (None, None, Some(true), None, Some(763754), Some(31863)), (None, Some(80), None, None, Some(8789233), Some(41874)), (Some(444819266), None, Some(false), Some(-697695), None, Some(38269)), (None, None, Some(true), Some(396743), None, Some(12055)), (None, Some(250), None, None, Some(-8815765), None), (None, None, None, Some(-840834), Some(5610522), Some(54808)), (None, None, Some(true), Some(-419302), Some(6681182), None), (Some(-1444733704), Some(161), None, None, Some(-2667601), Some(60897)), (Some(1821055535), Some(55), Some(true), Some(-545339), Some(7295103), Some(43868)), (None, Some(228), Some(false), None, None, None), (Some(-1170236354), Some(165), Some(false), None, None, Some(46381)), (None, Some(168), None, Some(-354753), None, Some(59562)), (None, Some(19), Some(false), None, None, Some(55094)), (Some(319714457), Some(78), Some(true), None, None, None), (Some(-2499039), None, Some(true), Some(-444059), Some(341280), None), (None, None, None, Some(-52993), Some(475986), Some(53881)), (None, Some(16), None, None, None, Some(58237)), (Some(223943054), None, None, Some(-235062), None, None), (Some(-1269197722), Some(208), None, Some(-533396), Some(3627175), Some(27583)), (None, None, None, None, Some(-3056426), None), (Some(-1997930383), None, None, Some(-32947), None, None), (Some(1373505592), Some(169), None, None, None, None), (Some(1031227447), Some(217), None, None, None, Some(15636)), (Some(-1885183317), None, Some(true), None, Some(-1251629), None), (None, Some(63), None, Some(155390), None, Some(1313)), (Some(983903311), Some(154), None, Some(-916542), None, None), (None, None, Some(true), Some(389222), Some(-6134532), None), (None, Some(73), Some(true), Some(943143), None, None), (None, None, None, Some(334500), Some(-6919411), Some(17478)), (Some(-504274523), None, Some(false), Some(-781935), Some(-7415651), Some(1317)), (Some(-1636022090), Some(206), None, None, None, Some(58160)), (Some(519251604), None, None, Some(-280712), None, Some(37257)), (Some(-1940345799), Some(101), Some(true), Some(-289700), None, None), (Some(177020528), Some(58), Some(true), Some(231655), None, None), (Some(454861954), Some(41), None, None, None, Some(56446)), (Some(-403275109), None, None, Some(475077), Some(-8034893), Some(9506)), (Some(1784166820), None, Some(false), Some(106014), Some(9297769), None), (None, None, Some(false), Some(-104203), None, Some(42727)), (None, None, Some(true), None, Some(-7177171), None), (Some(-44897677), None, None, Some(566636), Some(-7093682), None), (Some(-205455436), None, Some(true), None, Some(-2765761), Some(39365)), (Some(-319473407), Some(139), None, Some(129171), None, Some(59651)), (Some(-897906465), Some(79), Some(true), Some(175534), None, None), (None, None, Some(true), None, None, None), (None, None, None, None, None, None), (Some(596787188), Some(79), None, Some(-676285), Some(6612057), Some(55967)), (Some(1131637886), None, None, None, None, Some(2607)), (None, None, None, None, None, Some(27215)), (None, None, None, None, Some(5083066), None), (None, Some(212), None, Some(-411250), None, Some(26064)), (None, Some(205), Some(true), None, None, Some(43092)), (Some(1547573846), Some(89), Some(true), None, None, None), (Some(1886444813), Some(142), None, Some(951058), Some(8086943), Some(893)), (Some(1999827185), None, Some(false), Some(-464132), Some(-6479469), Some(34431)), (Some(-1822675795), Some(28), None, None, Some(-6140334), Some(51474)), (Some(1703740613), Some(47), Some(false), Some(209390), None, Some(10914)), (None, Some(66), None, None, Some(1869713), None), (Some(-1548582251), None, None, Some(15779), Some(-5883183), None), (None, None, Some(true), Some(-334731), None, None), (None, None, None, None, Some(3210962), None), (None, Some(104), Some(true), Some(138823), None, None), (Some(-907386587), None, Some(false), Some(559795), Some(5196948), None), (None, None, Some(false), Some(-739985), None, Some(37275)), (Some(454093318), Some(125), Some(false), Some(-53624), None, None), (Some(-1645589574), Some(77), Some(false), None, Some(8620384), None), (None, None, None, None, None, Some(65239)), (Some(-217831808), None, None, None, None, None), (None, Some(246), None, Some(-765689), None, None), (None, None, Some(false), Some(194674), None, Some(31350)), (None, Some(37), Some(false), None, Some(-9436900), Some(37232)), (None, Some(202), Some(true), None, Some(-8204684), Some(9864)), (None, None, None, None, None, Some(39610)), (Some(1076293372), Some(90), Some(true), None, None, None), (Some(-1793266582), None, Some(false), None, Some(6462748), Some(50952)), (Some(982759499), None, None, None, None, None), (Some(389746447), Some(26), None, None, Some(-6722850), Some(3099)), (None, None, Some(false), None, Some(-1053441), None), (Some(684972153), Some(31), Some(true), None, None, None), (Some(-422120064), None, None, None, Some(5543630), Some(56414)), (None, Some(94), None, None, None, None), (Some(442666925), None, None, Some(521914), None, Some(22523)), (None, Some(181), None, Some(-927998), Some(6415611), None), (Some(-1123511400), None, None, None, None, None), (Some(-600546212), Some(23), Some(false), Some(-183892), None, Some(63387)), (Some(635769401), Some(6), Some(true), None, Some(9124081), Some(64077)), (Some(-936437149), Some(239), None, None, Some(2035241), None), (None, Some(45), None, Some(459913), None, None), (None, Some(77), Some(false), Some(-874012), None, None), (None, Some(183), Some(true), Some(-48560), None, Some(45992)), (None, None, Some(true), None, Some(-6203729), None), (Some(-1927145898), Some(26), None, Some(-672189), None, None), (None, Some(130), None, Some(-601360), None, None), (None, Some(47), Some(true), Some(282208), None, Some(18454)), (None, Some(60), Some(true), Some(-949295), None, Some(46314)), (Some(-559335396), None, Some(true), Some(-688743), Some(-8002174), Some(53726)), (Some(2003638095), None, None, None, Some(-9445214), Some(45012)), (None, None, Some(true), Some(564870), None, None), (None, Some(1), Some(false), Some(695856), None, None), (None, None, None, None, Some(-4750329), Some(55720)), (None, Some(104), Some(true), None, None, None), (Some(-1534495326), None, None, None, None, Some(46101)), (None, None, None, None, None, None), (Some(-1658962130), None, Some(false), Some(469839), Some(3168900), None), (Some(717327846), Some(49), Some(true), None, None, None), (Some(951171951), Some(13), Some(true), None, None, None), (None, None, None, Some(-551594), Some(8528658), Some(40029)), (Some(1054453871), Some(73), None, Some(712565), Some(-2922597), None), (None, Some(226), None, Some(-714866), None, None), (None, Some(109), None, None, Some(6024850), None), (Some(381488042), Some(193), None, None, Some(-8604227), None), (Some(1173577613), None, Some(true), None, None, Some(17836)), (Some(1988617366), None, Some(false), Some(-688673), None, None), (None, None, Some(true), Some(-708080), Some(-9322464), Some(13279)), (Some(-326385603), None, Some(true), Some(948670), None, None), (None, Some(22), None, Some(-727694), None, None), (Some(-1164123309), None, Some(true), Some(-208221), Some(9539064), None), (Some(-729500273), None, None, None, Some(-9908083), Some(16974)), (None, Some(218), None, None, Some(-554358), Some(19143)), (Some(-501212710), None, Some(false), Some(-484213), None, None), (None, Some(245), Some(true), None, None, Some(34130)), (Some(-1523272036), Some(19), None, None, Some(4085923), Some(13768)), (Some(-565471962), Some(48), Some(true), Some(690343), None, Some(2142)), (None, Some(195), Some(true), None, None, Some(63181)), (Some(-1759875710), None, None, None, Some(-4228772), Some(39561)), (Some(-2121363348), None, None, None, None, None), (Some(1753216541), None, Some(false), Some(359917), None, None), (Some(1039498096), Some(127), None, None, Some(-2537787), Some(32087)), (Some(805314100), None, Some(true), None, Some(3517415), Some(44224)), (None, Some(125), None, Some(-775337), Some(-2208689), None), (None, None, None, Some(955400), Some(7189037), None), (None, None, Some(false), None, None, None), (None, None, None, Some(-421600), None, None), (None, None, None, Some(748021), Some(-7130554), Some(56532)), (Some(1839715011), None, None, None, Some(-4311783), Some(19341)), (None, None, Some(true), Some(297852), None, None), (Some(789019470), None, None, Some(391244), None, Some(38927)), (Some(18871427), Some(72), None, Some(-714071), Some(9462716), Some(14413)), (None, Some(84), Some(true), Some(-385439), None, None), (None, Some(113), None, Some(-863489), Some(-328966), Some(30091)), (Some(-1083302048), Some(213), None, None, None, Some(14995)), (None, Some(33), Some(false), Some(-60866), None, Some(54558)), (None, None, None, Some(631751), None, Some(20162)), (Some(1242785853), None, None, Some(-444332), Some(-1708103), None), (Some(2112431899), Some(232), None, None, Some(-5276623), None), (Some(2002761071), None, Some(false), None, None, None), (None, None, Some(true), None, None, Some(39970)), (Some(-364066134), Some(50), None, Some(-573034), None, None), (Some(725358494), Some(81), Some(false), Some(373869), Some(9461443), Some(50592)), (Some(-1600354099), None, Some(false), Some(253304), Some(-4643144), None), (None, Some(247), Some(true), Some(-205085), Some(8766295), Some(50347)), (None, None, Some(true), None, None, Some(18689)), (None, None, None, None, None, None), (Some(647824305), None, None, Some(815057), None, Some(52003)), (Some(299566621), None, Some(true), None, Some(1576191), Some(33126)), (None, None, None, None, None, Some(31602)), (None, Some(231), None, None, Some(-5021941), Some(47244)), (None, None, None, Some(741994), None, None), (Some(-1656616899), Some(150), None, None, Some(-3069440), Some(40412)), (Some(-1692757837), None, Some(true), Some(352983), Some(5533858), None), (Some(-1480630261), None, Some(false), Some(-505894), None, None), (None, Some(108), Some(true), None, Some(-5437172), Some(38022)), (Some(-1672025650), Some(70), None, Some(563744), Some(-7327500), None), (None, Some(153), None, Some(757297), None, Some(228)), (None, None, None, Some(-721855), None, Some(26108)), (Some(2021216664), None, None, None, None, Some(25189)), (Some(-986531605), None, Some(true), Some(-843897), Some(1689139), None), (None, Some(125), None, None, Some(-5190989), Some(56071)), (Some(1717689552), Some(196), Some(false), None, Some(-699612), Some(56128)), (None, Some(75), Some(false), None, Some(-8435283), Some(62518)), (None, None, None, Some(842192), Some(-9909638), Some(55892)), (Some(21524936), None, Some(true), Some(-326415), Some(8441899), None), (Some(73005019), Some(100), Some(true), Some(215094), None, None), (Some(-495749653), Some(177), None, Some(726554), Some(-9120151), None), (Some(-1357577833), Some(234), Some(false), None, None, Some(16742)), (Some(-1562241984), Some(91), None, None, Some(-4165086), None), (Some(2041142520), Some(126), None, None, None, Some(42428)), (None, Some(107), None, None, Some(-4391573), Some(33670)), (Some(1341101369), None, None, Some(459494), None, Some(26740)), (Some(1578135490), Some(179), None, None, Some(5698776), None), (None, Some(61), None, Some(-54249), Some(838266), None), (Some(1579557375), None, Some(true), None, None, None), (Some(-966052808), Some(133), None, Some(-997247), None, Some(8374)), (Some(-2010132997), None, None, Some(76014), None, None), (None, Some(46), None, Some(-734542), None, None), (None, Some(175), Some(true), None, None, Some(34282)), (Some(-905064466), None, None, None, Some(-3175837), Some(9758)), (Some(469538878), None, Some(false), Some(989902), Some(5346509), None), (None, Some(223), None, Some(568029), Some(8831585), None), (Some(1750784853), None, Some(true), None, Some(1641450), None), (None, None, None, None, None, None), (Some(537248142), Some(69), None, Some(-228237), Some(1616048), None), (None, Some(58), None, None, None, Some(48583)), (None, None, Some(false), None, None, Some(19068)), (Some(294397203), Some(49), None, Some(544588), Some(-863775), Some(48430)), (Some(-1481663445), Some(50), Some(true), None, Some(-5722819), Some(62987)), (Some(-1023009537), Some(194), None, None, None, None), (Some(-1674880824), Some(167), None, Some(800875), None, None), (None, None, Some(false), None, None, None), (Some(-41716797), Some(52), None, Some(-367252), Some(5773097), Some(65309)), (None, Some(206), Some(false), Some(-490610), None, None), (Some(-1396582612), Some(232), Some(true), None, None, None), (Some(1300250475), None, None, Some(316405), None, None), (None, None, None, None, None, Some(6129)), (None, None, Some(true), Some(-44974), Some(9904075), None), (None, Some(240), Some(true), Some(-271647), Some(9457791), None), (None, Some(85), Some(true), Some(-476811), None, Some(19582)), (None, None, Some(true), None, None, Some(55519)), (Some(-1881967679), None, Some(true), None, Some(-5899370), None), (Some(-354622756), None, Some(false), None, None, Some(14410)), (None, None, Some(false), None, None, Some(47520)), (Some(1170389588), None, Some(false), None, None, None), (Some(-2102075499), Some(217), Some(false), Some(494818), Some(3475901), None), (None, None, Some(true), Some(-996570), Some(-7515256), Some(31949)), (Some(2095965144), Some(99), Some(false), None, Some(-5117274), Some(10225)), (Some(694527826), Some(18), Some(true), None, None, None), (None, Some(53), None, None, None, None), (None, None, Some(true), Some(-939572), None, None), (None, Some(70), Some(true), Some(-971184), Some(-4415412), None), (None, Some(36), Some(true), Some(-367000), None, None), (None, None, Some(true), None, None, Some(44575)), (None, Some(174), None, Some(988491), None, None), (Some(-1993133650), None, Some(false), None, Some(-3046733), None), (None, Some(195), Some(false), None, None, None), (Some(-1203138003), Some(103), Some(false), Some(243495), None, None), (None, None, None, Some(-153293), None, Some(32188)), (Some(-1501703625), None, None, None, Some(-9316870), Some(28722)), (None, Some(238), Some(false), Some(143102), Some(-9354199), Some(16774)), (Some(-2050381205), Some(234), None, None, Some(-1418781), Some(31284)), (None, None, None, None, Some(-6391261), Some(54012)), (Some(-796319458), Some(255), Some(false), Some(520908), Some(-1361508), None), (None, None, None, Some(776023), None, None), (None, Some(225), None, Some(-668962), None, Some(46335)), (Some(-600849719), Some(79), Some(false), None, Some(-8546991), None), (None, None, Some(false), None, None, Some(44903)), (None, None, None, None, None, None), (None, Some(58), Some(false), None, Some(4881290), None), (None, None, None, None, None, None), (None, Some(139), None, Some(-824928), None, None), (Some(1950889938), None, Some(true), None, None, Some(12391)), (None, Some(76), None, None, Some(6808461), Some(57357)), (None, None, None, None, Some(-6769586), None), (None, Some(103), Some(true), None, None, None), (None, Some(112), Some(true), None, Some(-4617130), None), (None, None, None, Some(609952), Some(3937631), None), (Some(-1287869889), Some(8), None, None, None, Some(9046)), (None, None, Some(true), None, Some(5623069), None), (None, Some(175), Some(true), None, Some(-6940277), None), (Some(489392036), Some(107), None, None, Some(9311678), Some(55300)), (Some(1153831346), Some(32), None, Some(-691925), Some(3904576), None), (None, None, None, Some(-408687), None, None), (None, Some(2), None, None, Some(5129236), None), (None, Some(66), None, None, Some(2169589), Some(39179)), (None, None, None, Some(496010), None, None), (Some(1595323958), Some(29), Some(true), None, Some(-8389418), None), (None, None, None, Some(-988890), None, Some(14940)), (Some(-1592453371), None, Some(true), Some(790085), None, Some(10423)), (None, Some(165), Some(true), Some(-678654), Some(4974631), Some(15759)), (Some(8111828), Some(197), Some(true), None, Some(-9938423), Some(41047)), (Some(-1328578832), Some(160), Some(false), None, Some(-2413856), None), (None, None, None, None, Some(6038242), Some(12702)), (Some(-1913366597), None, Some(false), Some(-416367), Some(9543504), Some(49895)), (None, Some(5), None, Some(-63259), None, Some(61387)), (None, None, Some(true), None, None, None), (Some(-1561171768), Some(78), None, None, None, None), (Some(887931338), Some(200), Some(false), Some(-461644), None, Some(44819)), (Some(752786680), None, None, Some(-614040), Some(-4628951), None), (Some(-1028006103), Some(35), None, None, Some(-6442513), None), (None, Some(126), Some(false), None, None, Some(28717)), (None, Some(247), None, None, Some(-2884269), None), (None, Some(32), Some(true), None, None, None), (Some(704654372), Some(94), Some(false), None, None, None), (Some(739165409), None, Some(false), None, None, None), (Some(828897611), Some(250), None, Some(874702), Some(1118160), None), (None, Some(38), None, None, None, Some(58814)), (None, Some(173), Some(false), Some(91152), None, None), (Some(-494768179), Some(178), Some(true), None, Some(6387933), None), (Some(1574205316), Some(109), None, None, Some(-5693499), Some(10438)), (None, Some(134), None, Some(335555), None, None), (Some(-488773374), Some(156), None, Some(-693118), None, Some(25354)), (None, Some(74), None, Some(-870663), None, Some(34131)), (Some(1425528398), Some(170), Some(false), Some(675035), None, None), (Some(196024890), Some(255), None, Some(-874729), None, None), (Some(675340051), None, Some(true), Some(242361), None, Some(38106)), (Some(2050179786), None, None, Some(-916718), Some(-2810615), Some(55954)), (Some(-655062967), None, None, Some(55057), None, Some(52264)), (None, Some(161), Some(true), None, None, Some(35607)), (None, Some(32), None, Some(-130415), Some(6065797), Some(24047)), (Some(1873018457), None, None, Some(625688), None, None), (Some(-641020392), Some(187), Some(true), Some(-661341), None, Some(53008)), (Some(-739664616), None, None, Some(-224306), Some(-1495665), Some(3994)), (None, None, Some(false), None, Some(3965354), Some(35877)), (None, Some(175), Some(true), None, Some(-8779427), Some(58169)), (None, None, None, Some(-334716), None, Some(58743)), (Some(-517520432), None, Some(true), Some(-332150), Some(-8918522), Some(4954)), (None, Some(217), None, Some(-722347), Some(5858128), Some(26732)), (Some(491926793), Some(253), None, None, Some(6773749), Some(45804)), (None, None, None, None, Some(-9645856), Some(40804)), (Some(-1932309558), None, Some(true), None, Some(3622259), None), (Some(-1589743274), Some(212), Some(true), Some(267570), None, None), (None, None, Some(true), None, None, None), (Some(-2006262346), None, Some(false), None, None, Some(31838)), (None, None, Some(true), Some(505081), None, Some(2926)), (Some(1887129353), Some(43), None, None, None, Some(42737)), (Some(454277385), Some(110), Some(true), None, None, Some(42626)), (None, None, None, None, None, None), (Some(-892844124), Some(228), Some(true), None, None, Some(56746)), (Some(1886817393), Some(196), None, None, Some(-9587717), None), (Some(1746552285), Some(17), Some(false), Some(345283), Some(4637108), Some(3557)), (Some(343013692), None, None, None, None, None), (Some(2074146024), None, Some(false), Some(-909692), None, Some(51250)), (Some(543227693), None, Some(true), Some(244201), Some(-5840903), Some(51610)), (None, Some(73), Some(true), None, None, Some(36146)), (None, Some(118), Some(false), Some(286342), None, Some(21706)), (Some(-363870229), None, None, Some(-472475), None, None), (None, None, None, Some(-515515), Some(-7555325), None), (None, Some(143), Some(true), None, Some(8098370), Some(17420)), (Some(178433580), Some(249), Some(false), None, None, Some(26614)), (None, None, None, Some(-748202), Some(-9603405), None), (Some(1848238396), None, None, Some(-643314), None, None), (None, None, Some(false), None, Some(-2987073), Some(55301)), (None, Some(147), None, Some(373117), None, None), (Some(-694888280), None, None, Some(282124), Some(537592), Some(54355)), (None, Some(145), Some(false), None, Some(7137963), Some(3214)), (None, Some(19), Some(true), None, Some(3440420), None), (None, Some(181), Some(false), None, None, Some(29969)), (None, None, Some(false), Some(-416950), Some(9340260), Some(59477)), (Some(-415773786), None, Some(true), None, Some(-76206), None), (Some(1227330337), None, Some(false), None, Some(763964), Some(7406)), (Some(-2109765871), Some(200), None, Some(43152), Some(-2722556), None), (None, Some(219), None, Some(373688), None, Some(57265)), (None, Some(227), Some(true), Some(141182), None, None), (Some(1025756823), None, Some(true), Some(461556), None, Some(56840)), (Some(404372366), Some(164), None, Some(-702055), None, None), (Some(-17208734), Some(223), Some(true), Some(-826270), None, Some(9677)), (Some(370331967), None, Some(true), None, None, None), (Some(875327116), Some(12), Some(true), Some(-749092), Some(-3586758), None), (None, None, None, None, Some(8694407), None), (None, Some(2), Some(true), Some(33182), Some(-4163515), None), (None, Some(132), Some(false), None, None, None), (None, None, None, None, Some(-4012766), None), (None, Some(144), None, None, Some(-2025569), None), (None, None, None, Some(-289778), Some(-9284229), None), (Some(896310015), None, Some(true), None, None, None), (Some(-1165843395), Some(12), Some(true), None, Some(-4034736), Some(49403)), (Some(853101438), Some(233), None, Some(273931), None, None), (None, None, None, None, Some(-1217143), None), (None, Some(214), None, None, Some(-8560024), None), (Some(-930354382), Some(89), Some(false), None, Some(-2555552), Some(17585)), (None, Some(243), Some(true), None, Some(-881785), Some(24164)), (None, Some(168), Some(false), Some(98222), None, Some(44314)), (None, None, Some(false), None, None, None), (None, None, None, Some(-189375), Some(9777735), Some(11034)), (Some(-560447580), Some(130), None, None, Some(6631660), Some(45923)), (Some(1288883618), None, None, Some(369327), Some(-6043148), None), (None, Some(31), Some(true), None, None, None), (None, Some(5), Some(true), None, Some(242217), Some(7370)), (Some(1635687319), None, None, Some(832776), None, None), (Some(-960166311), Some(20), Some(false), Some(740511), None, Some(348)), (Some(1096176385), Some(86), Some(true), Some(-668766), None, Some(31061)), (Some(1193833111), Some(204), None, Some(303117), None, Some(39502)), (Some(-850423749), None, None, None, Some(-7884415), Some(10631)), (Some(1775818932), None, None, None, None, None), (None, Some(66), None, None, Some(-6429197), None), (Some(-390295947), Some(94), None, None, None, None), (Some(1173372993), Some(36), Some(false), Some(-487578), Some(7084657), Some(32806)), (None, Some(255), Some(true), None, None, Some(4656)), (None, None, None, None, None, None), (Some(905107738), None, None, None, None, Some(59601)), (None, Some(33), None, None, None, None), (None, Some(121), None, Some(554090), None, Some(15476)), (None, None, Some(false), Some(510255), None, None), (None, None, None, Some(554994), Some(-348103), Some(42369)), (Some(1030973490), Some(77), None, None, None, None), (Some(612566428), None, None, Some(-829863), None, Some(3620)), (None, None, None, Some(705629), Some(4919374), None), (Some(-1178624221), None, Some(true), Some(-737882), Some(2041604), None), (None, Some(103), None, Some(-615253), None, Some(53543)), (Some(192771095), Some(110), None, Some(-252966), None, Some(24540)), (None, Some(1), None, None, None, Some(41873)), (None, Some(54), None, None, Some(3929565), None), (Some(-1152136520), None, None, Some(920020), Some(7292221), Some(41509)), (None, None, None, Some(20818), None, Some(42442)), (None, None, Some(true), Some(-186968), None, None), (Some(-450552785), Some(41), None, None, Some(144607), Some(26932)), (Some(511733660), Some(158), Some(true), None, None, None), (None, Some(21), None, None, Some(-4224428), None), (None, Some(0), None, Some(586514), Some(-3532406), None), (None, Some(236), Some(false), None, Some(8323778), None), (Some(1976262071), Some(83), Some(true), None, None, Some(13311)), (None, None, Some(true), None, None, None), (Some(-345533413), Some(176), None, Some(-817929), Some(-1163727), Some(2056)), (None, None, None, None, Some(6138594), Some(48925)), (None, Some(64), Some(true), None, Some(-99019), Some(48244)), (None, Some(124), Some(false), None, Some(-5094218), Some(1558)), (None, None, Some(true), None, Some(-3406043), None), (None, Some(79), None, Some(4752), Some(1580169), Some(46486)), (Some(500079141), Some(216), Some(true), None, None, Some(36053)), (Some(1722002936), None, Some(true), Some(-85449), Some(9517657), None), (None, None, None, Some(-749389), None, None), (Some(190162758), Some(246), None, Some(371684), Some(7623678), Some(51633)), (None, Some(76), None, None, Some(8584185), None), (None, Some(255), Some(true), Some(501779), Some(-3118876), Some(45505)), (Some(1826474235), None, None, Some(-285985), Some(9049837), None), (None, None, Some(true), None, Some(7203161), None), (None, Some(217), None, Some(869941), Some(-4235060), Some(35087)), (None, Some(214), Some(true), None, None, None), (None, Some(70), Some(false), None, Some(-6144214), Some(35720)), (None, None, Some(true), Some(312394), Some(2228781), Some(50165)), (Some(-1960103933), None, None, None, None, Some(38273)), (None, None, None, None, Some(-3367535), None), (Some(1086348860), None, None, None, None, None), (Some(-955527737), None, None, Some(67029), Some(5268707), None), (Some(-1915201341), Some(175), Some(false), None, None, Some(32755)), (None, None, None, Some(858492), None, Some(57220)), (Some(-334400150), None, None, Some(40408), None, None), (Some(-302136191), None, Some(false), None, None, Some(48374)), (None, None, Some(true), Some(-951436), Some(-1720514), None), (None, None, Some(false), None, None, None), (None, None, None, Some(119934), Some(6346158), Some(26546)), (None, Some(123), None, Some(849003), Some(2707939), Some(39866)), (Some(-202662528), None, Some(false), None, None, None), (Some(970231580), None, None, Some(112938), Some(-6795139), None), (None, None, None, None, Some(-4592468), None), (None, None, Some(true), None, Some(4661480), None), (Some(-665319133), None, None, Some(-46590), None, Some(64497)), (None, Some(247), None, Some(-59363), None, None), (Some(1858244378), Some(210), None, Some(508524), None, Some(29213)), (Some(256362617), None, None, Some(-47959), None, None), (None, None, Some(true), Some(-363372), Some(-5429242), Some(32554)), (None, None, Some(true), Some(-654666), None, Some(33246)), (Some(181997764), Some(116), None, Some(863272), Some(1676910), None), (None, Some(52), None, None, None, None), (None, Some(64), Some(true), None, Some(9804931), None), (None, Some(144), Some(false), None, None, None), (Some(649015478), Some(170), None, Some(672879), None, Some(7913)), (Some(-1853175174), None, Some(false), None, Some(-9987449), Some(62162)), (Some(-1822970732), Some(242), None, None, None, None), (None, None, Some(false), Some(-949309), None, Some(33036)), (None, Some(83), None, Some(-257231), Some(7148508), None), (None, Some(219), None, Some(-108082), None, Some(39267)), (None, Some(39), Some(false), Some(-903238), None, None), (None, None, None, Some(-486928), None, Some(46074)), (Some(17105706), None, None, None, None, Some(36887)), (Some(-634531239), Some(134), Some(true), Some(-437545), Some(-1448212), Some(55818)), (Some(-10777040), Some(48), Some(false), None, None, Some(64377)), (Some(-825999829), Some(84), Some(false), None, Some(-3991265), None), (None, Some(210), None, None, Some(5291848), Some(53571)), (None, Some(148), Some(true), Some(-900726), None, None), (Some(-499793506), None, None, None, Some(2695552), Some(5619)), (Some(-567092896), Some(195), None, None, Some(2788766), Some(33655)), (None, None, Some(false), Some(-16545), Some(6596571), None), (None, Some(226), Some(false), None, None, Some(32707)), (None, Some(67), None, Some(285759), Some(-476830), None), (Some(778111158), Some(251), Some(true), None, Some(-9258493), None), (Some(-580159509), Some(77), None, Some(-116336), None, None), (Some(-1573151956), None, None, Some(196225), Some(-8068257), Some(47151)), (None, Some(156), Some(true), Some(-300618), Some(-9658474), Some(23873)), (Some(-1794501384), Some(67), Some(false), None, None, None), (None, None, Some(false), None, None, None), (None, None, None, None, None, None), (None, Some(79), Some(true), Some(959039), None, None), (Some(-103630002), None, Some(true), None, Some(3198932), None), (None, Some(84), None, None, None, Some(48040)), (Some(393046582), None, None, None, None, None), (Some(-1957656436), None, Some(false), None, Some(659681), Some(13390)), (Some(224390230), Some(97), None, None, Some(7752841), None), (None, None, Some(true), Some(474064), None, Some(58446)), (Some(381313616), None, Some(false), Some(-809062), Some(-995951), None), (Some(-1772438673), Some(105), Some(false), None, None, None), (None, None, Some(false), Some(85431), Some(-7999317), Some(2869)), (None, None, Some(true), None, Some(-4142422), None), (None, None, None, None, None, Some(21703)), (None, None, Some(false), Some(651159), None, Some(28320)), (Some(1894326033), None, Some(true), Some(-734825), Some(-7930702), Some(33152)), (None, None, None, None, None, Some(16616)), (Some(462018456), None, None, None, None, None), (None, None, Some(true), None, Some(1167208), Some(38591)), (None, None, Some(true), None, Some(-2841776), Some(51497)), (Some(-971497262), None, Some(false), Some(-493929), None, Some(50985)), (Some(408172172), None, None, None, None, Some(53627)), (Some(1212751450), Some(128), None, None, Some(-3048445), Some(43163)), (Some(-335497057), Some(213), None, None, None, None), (None, None, None, Some(-312980), None, None), (Some(1466147007), None, None, Some(176965), Some(-6978728), None), (Some(1008683647), Some(63), Some(true), None, None, Some(18082)), (Some(-1587247560), Some(100), None, None, None, None), (Some(1249748279), None, None, Some(-703581), None, None), (Some(1036583398), None, Some(true), Some(733798), None, None), (Some(267680602), None, None, None, Some(-3080600), Some(51337)), (Some(839322734), None, None, None, Some(-3129700), None), (None, None, Some(true), Some(-564765), None, Some(5381)), (Some(-1340094786), None, Some(true), Some(-674944), Some(7313214), Some(3660)), (None, Some(227), Some(false), Some(114247), Some(8917940), Some(9593)), (Some(-1010611255), None, Some(false), Some(801540), None, None), (None, Some(127), Some(true), None, Some(1356850), Some(31120)), (None, None, None, None, None, Some(63962)), (None, Some(178), Some(true), Some(-942854), Some(5251318), None), (None, Some(243), Some(false), Some(-674595), None, Some(53718)), (Some(-288670236), Some(213), None, Some(345478), None, Some(32344)), (Some(-549518688), Some(174), None, None, None, Some(60959)), (Some(-1285317754), None, Some(true), None, None, Some(26928)), (Some(387817315), None, Some(true), None, None, None), (Some(-103837829), Some(234), None, None, Some(6602680), None), (None, None, Some(false), None, Some(-7583555), Some(5888)), (Some(1669126436), None, Some(true), None, Some(1322505), None), (Some(-883740894), None, Some(false), None, None, Some(46369)), (Some(569586026), None, Some(true), Some(-783787), Some(-9565370), None), (None, Some(153), None, Some(431343), Some(3904398), None), (Some(-1357309452), None, Some(true), Some(-438476), None, None), (Some(740002520), Some(236), Some(true), Some(674567), Some(-7545890), None), (Some(1319047847), None, Some(true), Some(759268), None, None), (Some(1813503376), Some(113), Some(false), None, None, Some(41543)), (Some(-1244752702), Some(137), Some(true), None, None, Some(12155)), (Some(946152775), None, None, None, None, None), (Some(1842553396), None, None, Some(148533), None, None), (Some(873285589), Some(138), Some(true), Some(878217), None, Some(62238)), (None, None, Some(false), Some(-470668), None, Some(12374)), (None, None, None, Some(-624163), None, None), (None, Some(194), Some(true), None, None, Some(39288)), (Some(37642651), Some(91), None, None, Some(-2715778), Some(2631)), (None, Some(129), None, Some(661333), None, None), (Some(746060937), Some(51), Some(true), None, None, None), (None, Some(104), Some(true), None, Some(-1032912), Some(33888)), (Some(-622232450), Some(38), None, Some(-421667), None, Some(61555)), (Some(-331229491), Some(5), None, None, Some(1425564), None), (Some(2024385856), None, None, None, None, Some(12868)), (None, Some(145), Some(true), Some(-699574), Some(7612936), None), (Some(-1332588473), None, Some(false), Some(159054), Some(2205607), Some(58453)), (None, Some(5), None, Some(-799073), None, None), (None, None, Some(true), Some(795574), Some(3610961), None), (Some(-219308940), Some(232), None, None, Some(9333734), None), (Some(1512454088), Some(237), Some(true), None, Some(-7291456), Some(62840)), (Some(-569459563), None, Some(true), Some(815370), None, Some(45073)), (Some(-268350575), None, Some(true), None, None, None), (None, None, None, Some(450997), None, Some(5102)), (None, Some(225), Some(true), Some(952678), None, Some(58810)), (None, Some(2), Some(false), Some(782533), Some(7929439), None), (None, None, None, None, None, None), (None, Some(49), None, Some(-879217), Some(9761806), None), (None, Some(198), None, Some(248239), Some(8507159), None), (None, None, None, Some(-1934), Some(-4009619), Some(3494)), (None, Some(97), None, None, None, None), (Some(1395535334), None, None, Some(586065), Some(9167003), None), (None, None, Some(true), None, Some(-7376342), None), (None, None, None, None, Some(-6744412), Some(43799)), (Some(1847652277), Some(18), Some(true), Some(-75225), Some(-5325244), None), (None, None, Some(false), Some(707687), Some(-6950680), None), (Some(-1597743144), Some(136), None, Some(-764707), None, None), (None, Some(64), Some(false), None, Some(-1717063), Some(37637)), (Some(-1616374732), None, Some(false), Some(561783), Some(8629666), None), (None, None, None, Some(55318), None, None), (None, None, None, None, None, Some(41417)), (Some(385694449), None, Some(true), None, None, None), (None, Some(204), Some(false), None, Some(-9282605), Some(54690)), (Some(-362256749), Some(30), None, Some(-840540), None, Some(50058)), (None, None, None, Some(-598667), Some(-4241604), None), (None, None, None, Some(748391), Some(-6228441), None), (None, None, None, None, None, None), (None, Some(238), Some(false), None, Some(-7023861), Some(18721)), (None, Some(85), None, Some(-804662), Some(-9074602), Some(36954)), (Some(1683458077), None, None, None, None, None), (Some(-402868158), Some(162), Some(false), None, Some(5222867), None), (None, Some(178), None, Some(-131903), None, Some(58341)), (None, Some(100), Some(false), None, None, Some(51580)), (None, Some(228), None, Some(-19552), None, Some(3109)), (None, None, Some(true), None, None, None), (Some(-1874801039), Some(197), None, Some(911443), None, Some(37618)), (Some(1573111948), Some(250), Some(false), None, Some(-2047870), None), (Some(-868527081), Some(151), Some(true), None, None, None), (None, None, None, Some(393786), Some(-7926527), Some(64203)), (Some(-1337562134), None, None, Some(-375804), None, Some(64125)), (None, Some(58), Some(false), Some(-945730), None, Some(34010)), (None, None, None, Some(-62933), Some(-8068019), Some(31456)), (None, None, Some(true), Some(33354), None, None), (Some(1322902247), Some(235), None, Some(594545), Some(9199255), Some(44663)), (Some(629508407), Some(36), None, Some(24288), None, None), (None, None, None, Some(52085), None, None), (None, Some(160), Some(true), Some(686760), Some(-7041128), Some(27294)), (None, Some(127), None, Some(412936), Some(-8277600), Some(63702)), (None, Some(193), None, Some(991295), Some(9352829), Some(62429)), (Some(707960181), None, None, Some(-990934), Some(1792825), None), (None, None, None, None, None, None), (None, Some(187), None, None, None, Some(36529)), (Some(-1290653138), None, None, None, Some(9656310), Some(33908)), (None, None, Some(false), Some(733338), Some(-5608605), None), (None, Some(152), Some(true), None, None, Some(19944)), (Some(1258294962), Some(138), None, None, Some(-8116747), None), (Some(1239271461), None, None, Some(-567834), None, None), (None, Some(113), Some(true), Some(353153), None, None), (None, None, Some(false), Some(929482), Some(-8145764), Some(27076)), (Some(1672123206), None, Some(false), None, None, Some(15303)), (None, None, None, Some(-521361), None, Some(11874)), (Some(2086670180), None, Some(false), None, None, Some(21042)), (None, Some(161), Some(true), Some(-930551), Some(9234415), Some(41240)), (None, Some(255), Some(true), Some(11546), None, Some(12580)), (None, Some(195), Some(false), Some(75436), Some(-1986020), Some(22213)), (None, Some(20), None, Some(-11591), Some(-3191180), Some(20796)), (Some(1949793942), Some(133), None, Some(993709), None, Some(41780)), (Some(-174257232), Some(241), Some(false), None, None, Some(35725)), (None, None, None, None, None, Some(32857)), (None, Some(245), Some(false), None, Some(7429887), Some(4447)), (None, None, Some(false), None, None, None), (Some(93667211), Some(163), None, None, None, Some(32383)), (Some(192513685), None, None, None, None, None), (None, None, None, Some(142149), Some(5842752), Some(57405)), (None, None, None, None, Some(9132068), Some(47263)), (Some(-1931770263), None, Some(true), Some(933027), Some(7995494), Some(46246)), (Some(144656410), None, None, None, Some(-473004), None), (Some(2117955398), None, None, None, Some(-7590476), Some(56611)), (Some(-1990302821), None, None, None, None, Some(27814)), (Some(-373152289), Some(181), Some(false), Some(-769120), None, None), (Some(-264968502), None, Some(true), None, None, Some(37619)), (None, Some(117), Some(false), None, None, Some(13809)), (Some(373242283), Some(81), Some(false), None, Some(-311545), None), (Some(-1024741027), Some(24), Some(true), Some(-982023), None, None), (None, Some(153), None, Some(1842), Some(6143839), None), (Some(1956651760), Some(181), None, None, Some(6515653), None), (Some(-1103159083), None, Some(true), None, Some(4261537), Some(41285)), (Some(-1931932282), None, None, Some(297250), Some(7433684), Some(34912)), (Some(462444261), None, Some(true), None, Some(-5445146), None), (Some(860292826), Some(247), None, Some(-213703), None, None), (Some(-381852425), Some(121), None, Some(-404582), None, Some(1361)), (Some(-1548256413), Some(9), None, Some(571850), None, Some(34196)), (Some(52143310), None, Some(false), Some(-65829), None, Some(48621)), (None, None, Some(true), None, Some(-6217987), Some(38261)), (None, Some(54), None, None, None, Some(6105)), (None, Some(225), None, Some(-235672), Some(5092464), None), (None, None, None, None, Some(-8736303), None), (Some(-296385478), Some(105), Some(false), None, None, None), (None, Some(145), Some(false), None, None, None), (Some(1102422587), Some(128), Some(true), None, None, None), (Some(-904269545), None, Some(false), Some(-904301), Some(9059885), None), (None, None, None, None, None, Some(58249)), (None, None, None, Some(878675), None, None), (None, Some(27), None, None, Some(-3214915), Some(57177)), (Some(1393786673), Some(119), Some(false), None, Some(-3729789), None), (Some(-1362398853), None, Some(false), None, None, None), (Some(-1888002617), None, None, Some(-522264), Some(9843564), Some(6260)), (Some(-560822389), None, None, None, Some(-9153866), Some(47969)), (Some(1318196230), None, None, None, None, None), (Some(-1828562853), None, Some(true), Some(-410698), None, Some(16435)), (Some(-523598045), Some(243), Some(false), None, None, None), (Some(1516486915), Some(20), Some(false), Some(28918), None, None), (Some(-1556176501), None, Some(true), None, Some(-8785882), Some(2116)), (None, Some(128), None, None, None, Some(16579)), (Some(-1809450864), Some(68), Some(false), Some(825352), Some(-418330), None), (None, Some(150), Some(true), None, None, Some(64936)), (None, Some(39), Some(true), None, None, None), (Some(860779393), Some(38), None, Some(-335906), None, None), (None, Some(102), None, Some(908240), Some(289377), Some(58751)), (Some(1225235432), None, Some(true), None, Some(-3974223), None), (None, None, Some(false), Some(470480), None, Some(55625)), (Some(1442221157), None, None, None, Some(9069158), None), (None, None, Some(true), Some(273268), None, Some(55322)), (Some(2096772039), None, Some(false), None, Some(9660192), None), (None, Some(100), Some(true), Some(-427850), None, None), (None, None, None, None, Some(7682733), None), (None, Some(60), Some(true), Some(-561213), None, None), (Some(1068793084), None, Some(false), Some(-984037), None, None), (Some(172359702), Some(134), Some(false), Some(-422912), None, None), (Some(1229113259), Some(223), Some(true), None, None, Some(40398)), (None, None, None, None, Some(2596755), None), (Some(-602657723), Some(192), None, None, Some(-2516839), None), (None, Some(162), Some(true), Some(-182634), Some(7944022), Some(62183)), (None, Some(147), None, None, None, Some(17458)), (Some(1712542372), None, None, None, None, None), (None, Some(16), None, Some(298247), Some(-1097818), None), (None, None, None, None, Some(3257946), None), (None, Some(142), None, Some(626523), Some(-7073955), Some(1022)), (Some(1841390575), None, Some(false), Some(883785), None, None), (Some(500694470), None, None, Some(-850455), None, None), (None, Some(167), Some(true), Some(-87627), Some(8730369), Some(52743)), (Some(-464791273), Some(116), Some(false), None, None, Some(33142)), (None, None, Some(false), Some(656826), Some(2576138), None), (None, Some(84), None, Some(886632), None, Some(2353)), (None, None, None, Some(213405), None, None), (Some(264851315), None, Some(true), None, None, None), (None, None, None, None, None, None), (Some(-855969609), Some(150), None, Some(840283), Some(-9091924), None), (None, Some(97), Some(true), None, None, Some(11258)), (None, Some(9), None, Some(-783133), Some(-4415201), Some(13342)), (None, Some(122), Some(false), Some(-635788), None, Some(33792)), (Some(1182532159), None, Some(true), Some(890213), None, None), (Some(-329236973), None, None, Some(27183), None, None), (Some(1841191140), None, None, None, Some(-4051932), None), (Some(953572669), None, None, None, Some(3835223), None), (None, Some(67), None, None, None, None), (None, Some(160), Some(false), None, None, Some(40531)), (None, Some(97), Some(false), Some(-717359), Some(-6721032), None), (Some(-599491963), None, None, None, Some(-7689506), None), (Some(-896781573), None, Some(false), None, Some(2125974), Some(60481)), (Some(885772727), Some(89), None, Some(669748), Some(7136188), None), (Some(-467784762), None, None, Some(98672), None, None), (Some(-1833752016), Some(75), Some(true), None, Some(5192160), None), (Some(-1260304910), Some(163), Some(false), Some(-842664), None, None), (Some(-1556039652), None, None, Some(705055), Some(2005765), Some(56445)), (Some(1741798598), None, None, Some(78708), Some(-4855449), Some(41034)), (None, None, Some(false), None, None, Some(31348)), (None, None, Some(true), Some(-201064), None, Some(58132)), (Some(-1495437847), None, Some(true), Some(320186), Some(1263910), None), (Some(-1150677001), None, Some(false), Some(942638), None, None), (None, None, Some(false), None, Some(-8211761), Some(23891)), (Some(-2555062), Some(219), Some(true), None, None, None), (None, None, Some(false), None, None, Some(61470)), (None, Some(128), None, Some(-712741), Some(-5496302), None), (Some(-695473381), None, None, None, Some(-3864303), None), (None, Some(204), None, None, Some(-5454500), Some(24881)), (Some(1339984266), None, Some(true), Some(720760), None, Some(30607)), (None, Some(18), None, Some(191765), Some(8193268), Some(9848)), (Some(887741042), None, None, Some(941897), Some(-4772533), None), (Some(1428032563), None, Some(true), Some(30704), Some(7687555), Some(2938)), (Some(-1863300844), Some(10), None, None, None, Some(45673)), (Some(-263557869), Some(50), Some(false), Some(-327875), None, None), (Some(-1815947431), Some(3), Some(false), Some(61190), Some(9596736), None), (None, None, None, None, None, Some(50739)), (Some(-1594086303), None, None, None, Some(-1102729), Some(39561)), (Some(-2131607230), None, Some(false), None, None, Some(26842)), (None, Some(4), Some(false), Some(-446174), None, None), (Some(613993128), Some(36), None, Some(-180466), Some(-1773882), None), (None, None, Some(false), Some(59837), Some(109063), None), (None, Some(184), Some(false), None, None, None), (None, None, None, None, Some(3596560), Some(56514)), (Some(-892758892), Some(37), Some(false), None, None, Some(14269)), (Some(1999021398), None, Some(false), Some(666448), None, None), (Some(-1070945873), Some(220), Some(false), None, Some(-4930690), Some(51197)), (None, Some(177), Some(true), None, None, None), (None, None, Some(false), None, None, Some(1623)), (Some(-91577790), None, None, None, Some(8246608), None), (None, Some(107), None, None, None, Some(53291)), (None, None, None, None, Some(38738), None), (None, None, None, Some(267885), None, Some(48510)), (None, Some(150), Some(false), Some(-77739), None, Some(17742)), (Some(480946096), Some(242), Some(true), None, None, None), (None, None, Some(false), Some(-634670), None, None), (None, None, None, None, None, Some(33233)), (None, Some(198), Some(true), Some(-629363), Some(-3210986), None), (Some(-607298847), Some(246), Some(true), Some(570038), None, Some(49793)), (Some(966505285), Some(127), Some(true), Some(-708315), None, Some(46218)), (None, Some(231), None, Some(-377818), Some(6718800), None), (Some(-1040466989), None, None, Some(196440), Some(6752663), Some(20037)), (None, Some(161), Some(false), None, Some(4265917), None), (Some(-1157244561), None, None, Some(-873815), None, None), (Some(-1459776614), Some(139), Some(true), Some(589646), Some(-2078028), Some(65280)), (None, None, Some(true), None, None, None), (Some(-7828968), Some(185), None, None, None, Some(29592)), (None, Some(71), None, Some(-463292), None, Some(13341)), (Some(-1283473066), None, Some(false), Some(453597), None, Some(9931)), (Some(-278377393), None, None, Some(-633334), None, Some(19620)), (Some(873913645), None, Some(false), Some(94754), Some(-191495), None), (None, None, None, Some(262041), None, Some(35561)), (Some(-852350858), Some(21), None, None, None, None), (Some(547538169), Some(227), Some(true), Some(-566348), None, None), (None, None, None, Some(-77745), Some(-8799570), None), (None, Some(115), Some(false), Some(759437), Some(1879339), Some(64280)), (None, None, Some(true), Some(-894824), Some(6768228), None), (None, Some(70), None, None, Some(1019058), None), (Some(1989835560), None, Some(true), Some(-680078), None, None), (Some(1566840977), Some(178), Some(true), None, None, None), (Some(1932164030), Some(64), Some(false), None, Some(-9190279), Some(32291)), (None, Some(56), None, None, None, None), (None, None, None, Some(197189), Some(1188429), Some(38113)), (None, Some(173), None, Some(6946), Some(-5188041), Some(60365)), (Some(609078742), None, Some(false), None, Some(8549269), None), (None, Some(129), None, None, None, None), (Some(666163202), Some(11), None, None, None, Some(59386)), (None, None, None, None, None, None), (Some(1674144177), Some(113), Some(false), Some(-12114), Some(609929), Some(38622)), (Some(1132317230), Some(56), None, Some(643442), Some(-4314212), Some(22115)), (None, None, Some(true), None, None, None), (Some(-2141948262), Some(147), Some(true), Some(203111), None, None), (Some(-648847258), Some(79), None, Some(-481493), Some(2671243), None), (Some(179909079), Some(41), None, Some(186066), None, Some(36145)), (Some(1749133109), None, Some(true), None, None, None), (None, None, Some(true), None, None, Some(11902)), (None, Some(162), Some(true), Some(-780155), Some(-2253878), None), (Some(1826194553), None, None, None, None, None), (Some(1246997800), None, Some(true), None, None, Some(5950)), (None, Some(152), None, None, None, Some(4886)), (Some(1376281055), None, None, Some(-327442), None, Some(62622)), (Some(1118790153), Some(21), None, None, None, None), (Some(1469972217), Some(103), Some(false), None, Some(6647621), Some(12853)), (None, None, Some(false), Some(863925), None, None), (None, Some(189), Some(true), None, Some(-2002009), Some(12080)), (Some(-1983484617), None, Some(true), Some(855205), None, None), (None, Some(132), Some(true), None, None, None), (Some(-907780310), Some(175), None, Some(-835891), Some(-1222715), Some(36214)), (None, Some(120), Some(true), Some(303357), Some(-205853), None), (None, None, Some(false), None, None, Some(36572)), (Some(-1561122367), None, None, None, Some(-9484500), None), (None, Some(117), None, None, None, Some(6160)), (Some(-416119483), Some(54), Some(true), None, None, None), (None, Some(149), None, Some(668130), None, None), (Some(-687073018), None, None, Some(987470), Some(8190258), None), (None, Some(52), Some(false), None, Some(3845314), Some(33067)), (Some(-802173265), None, Some(false), None, None, None), (Some(2096219515), Some(254), None, Some(-186854), Some(5614465), Some(29769)), (Some(2041258804), Some(240), None, None, None, None), (None, None, Some(false), None, Some(8490508), None), (Some(1264437489), Some(4), None, None, None, None), (None, Some(200), None, Some(188889), Some(-9989301), None), (None, Some(3), Some(true), None, Some(-8585761), Some(54234)), (None, Some(95), None, None, Some(-2593019), Some(34787)), (None, None, None, None, Some(-2956450), Some(53564)), (Some(-37150115), None, None, Some(-160073), Some(813853), Some(52795)), (None, Some(47), None, Some(738), None, Some(14158)), (None, Some(236), Some(true), Some(-391826), None, Some(53415)), (None, None, None, Some(-118745), None, None), (Some(-1308277837), None, Some(true), None, Some(7803885), None), (None, None, None, Some(-648589), None, None), (None, None, Some(false), Some(103430), None, Some(37303)), (None, None, None, None, None, None), (Some(1468305660), Some(184), None, None, Some(-8473072), None), (None, Some(190), None, None, None, None), (Some(1348138523), None, Some(false), Some(-441558), Some(-4932106), Some(12083)), (None, Some(52), None, Some(50525), Some(-8730634), None), (None, None, Some(false), Some(127216), None, None), (None, None, Some(false), Some(157075), None, Some(57721)), (Some(-374347847), None, None, None, None, Some(25144)), (Some(363981763), None, None, None, Some(-3241010), None), (Some(-578338303), Some(144), Some(true), None, Some(-1968389), Some(46352)), (None, Some(238), Some(false), Some(66926), Some(5034295), Some(49296)), (None, None, None, Some(621525), Some(-3093445), None), (None, Some(28), None, Some(-286181), None, None), (None, None, None, Some(-325340), Some(-3297762), Some(2971)), (None, Some(179), None, None, Some(9693962), Some(39736)), (Some(-118902670), Some(150), Some(true), None, Some(-4303088), None), (Some(-1309025079), None, None, None, Some(3059175), None), (Some(1697405208), Some(40), Some(false), None, None, None), (None, Some(125), Some(false), Some(995726), None, None), (None, None, Some(true), Some(-138505), Some(-2694770), None), (Some(-1673818807), None, Some(false), None, None, None), (None, None, Some(false), None, None, Some(10183)), (None, None, Some(true), None, Some(-6312194), Some(14865)), (None, None, None, Some(-479834), Some(3422698), None), (None, Some(133), Some(false), None, None, None), (None, None, None, Some(853578), None, Some(32607)), (None, None, Some(false), None, Some(5985508), Some(40532)), (None, None, None, Some(-328080), Some(-1619283), None), (Some(1327467629), Some(29), Some(false), None, Some(3814708), None), (Some(-26401841), None, Some(true), Some(74364), None, Some(6627)), (Some(-1809870087), Some(106), Some(true), Some(-526861), None, Some(1898)), (None, Some(141), Some(false), None, None, None), (None, Some(172), None, None, None, Some(60651)), (None, Some(107), None, Some(-213131), Some(7137416), None), (Some(1991653506), None, None, None, None, None), (None, Some(5), Some(true), None, Some(9704301), Some(18932)), (None, None, Some(false), Some(986359), Some(1105469), Some(60499)), (None, Some(248), Some(false), None, None, Some(62474)), (None, Some(128), None, None, None, Some(54165)), (Some(-2019659654), Some(222), None, Some(918405), None, None), (Some(557083045), None, Some(true), None, Some(1136500), None), (Some(-1772432855), Some(112), None, Some(550120), Some(3624977), None), (Some(425050627), None, None, Some(-910510), Some(-4097989), Some(44770)), (None, Some(91), Some(true), None, None, Some(54346)), (None, None, Some(true), Some(-481924), Some(72810), Some(32576)), (None, Some(189), None, None, None, None), (Some(1597270421), None, Some(true), Some(-824527), None, None), (None, Some(183), Some(false), None, Some(6294173), None), (None, None, Some(false), Some(-835689), None, Some(18509)), (None, None, Some(true), Some(-450052), Some(6908628), Some(22776)), (None, None, None, Some(-432100), None, Some(8338)), (Some(210177330), None, None, None, Some(9551210), Some(29615)), (Some(-1308567656), Some(80), None, Some(784458), Some(4302045), Some(12723)), (None, None, None, None, Some(3971111), Some(52839)), (Some(1373054555), Some(212), Some(false), None, Some(-4707123), Some(11554)), (Some(759898222), Some(240), Some(true), None, None, Some(14883)), (None, None, Some(true), Some(151131), Some(-6329570), None), (None, Some(254), None, Some(147097), Some(1517359), None), (Some(-2051793935), Some(196), None, Some(366850), None, Some(45073)), (None, None, None, None, None, None), (Some(1210352429), None, None, Some(-149700), None, Some(11445)), (Some(-1847624455), Some(225), Some(true), Some(-260546), Some(-2824441), None), (None, Some(164), None, Some(405837), Some(8131001), None), (None, Some(142), Some(true), None, None, None), (Some(381880860), Some(204), None, None, Some(-8905034), Some(29295)), (Some(1954972392), None, Some(false), None, Some(-1266690), Some(59621)), (Some(-2069725162), Some(38), Some(false), Some(-845792), None, Some(1121)), (Some(-369461884), None, Some(false), None, None, Some(35856)), (None, Some(240), Some(false), None, Some(-312242), None), (Some(-220868231), None, None, None, Some(-29410), None), (None, None, None, None, Some(2091577), Some(17104)), (Some(-857037686), None, None, Some(126848), Some(-2597866), None), (Some(1549019911), None, Some(true), None, None, Some(49781)), (Some(-909734587), None, None, Some(-268873), None, Some(1055)), (None, None, None, None, Some(-9666868), Some(62430)), (Some(-1636739495), Some(58), Some(false), Some(-468730), Some(-3540114), None), (None, None, None, Some(-255646), None, Some(30075)), (None, Some(141), None, None, Some(4422391), Some(32231)), (None, None, Some(false), None, Some(-3673119), None), (None, None, None, Some(633304), Some(-425657), Some(59850)), (Some(1836842012), Some(122), Some(false), None, None, Some(45916)), (Some(-1226290906), None, Some(true), Some(-102568), None, Some(3666)), (None, Some(30), None, None, Some(928275), None), (Some(-1529811210), Some(164), Some(true), None, Some(3744952), Some(19406)), (None, None, Some(false), Some(848648), None, None), (Some(256533666), None, None, Some(447303), Some(6907773), Some(2863)), (Some(-221456509), None, Some(false), Some(191171), Some(3605654), Some(27037)), (Some(-2030125243), Some(75), Some(false), Some(-444819), Some(7710194), Some(36738)), (None, Some(207), Some(true), None, None, Some(2677)), (None, None, Some(true), Some(-965755), Some(-8348209), None), (None, Some(195), Some(false), None, Some(6370148), None), (Some(1993349026), Some(43), None, Some(-118167), None, None), (None, Some(92), Some(true), Some(-631591), Some(-3856379), Some(57957)), (Some(1059523026), None, None, None, Some(4756865), None), (Some(705685079), None, Some(true), Some(471165), None, Some(18255)), (None, Some(144), None, Some(721818), Some(5143256), Some(11779)), (None, Some(6), None, Some(451742), None, None), (None, Some(237), None, None, None, None), (Some(-1620293645), Some(10), Some(false), Some(-460560), Some(9219420), Some(36494)), (None, Some(254), None, Some(-269072), None, None), (None, None, None, Some(508537), Some(-2278219), None), (Some(2119899758), Some(92), None, None, Some(1235077), None), (None, None, None, Some(874613), None, Some(5830)), (None, None, Some(false), Some(-566151), None, None), (None, None, None, None, None, Some(47184)), (Some(-1221728672), None, Some(false), None, None, None), (None, None, None, None, None, Some(4623)), (None, None, Some(true), None, None, Some(15432)), (Some(-1118589420), None, None, None, Some(-6501319), None), (None, None, Some(false), Some(945474), Some(-3787868), Some(14834)), (Some(1519998980), None, None, Some(-301515), None, Some(750)), (Some(1879385981), None, Some(false), Some(-244571), Some(1349307), None), (Some(-388693559), None, None, Some(-263646), Some(9805697), Some(390)), (Some(1588980722), None, Some(true), None, None, None), (Some(-1120709665), Some(0), None, None, Some(-1395434), None), (None, Some(165), Some(false), Some(-247405), Some(4885357), Some(55503)), (None, None, Some(false), None, None, Some(48799)), (Some(460047608), Some(65), None, Some(884712), Some(7375811), Some(61549)), (Some(-395844910), None, Some(false), Some(188505), None, None), (Some(-702150707), None, Some(true), None, Some(649167), None), (None, Some(132), None, Some(127067), None, None), (Some(837911211), None, None, Some(-78273), None, None), (Some(-424657734), None, None, None, None, None), (Some(-86246924), Some(61), Some(false), Some(490077), Some(-4423168), None), (None, Some(93), Some(false), None, Some(-9674567), Some(12170)), (None, Some(211), None, Some(171996), Some(-9478041), Some(50491)), (Some(202462280), None, Some(true), Some(-578540), None, None), (None, None, None, None, None, None), (Some(-1133057450), Some(227), Some(true), Some(538342), Some(-5175502), None), (None, Some(126), None, Some(74245), None, Some(10369)), (None, Some(18), None, Some(107890), Some(-9455351), Some(42539)), (Some(-1296706923), None, Some(true), Some(-69330), Some(2424397), Some(26084)), (None, Some(95), None, None, None, None), (None, Some(176), Some(true), Some(-836781), Some(-389883), None), (None, None, Some(false), Some(468355), Some(409569), Some(35433)), (Some(368937307), None, Some(false), None, None, Some(15929)), (None, Some(52), None, Some(-55062), Some(-2406593), Some(43927)), (Some(332815996), Some(117), None, None, Some(46533), None), (None, Some(205), Some(true), Some(-88768), Some(8357729), None), (None, Some(188), None, None, Some(-6800781), None), (None, None, Some(true), Some(-467052), None, None), (Some(936827110), None, Some(false), Some(-11846), None, None), (None, Some(244), None, Some(828799), None, Some(3337)), (None, Some(133), None, Some(266284), None, None), (Some(-1197824668), None, None, None, None, None), (None, None, None, Some(986440), Some(-843374), None), (None, None, Some(false), None, Some(-1205117), Some(50281)), (None, None, None, Some(376639), None, None), (None, None, Some(false), Some(-573755), Some(6606331), Some(24440)), (Some(-585004998), None, Some(false), Some(-554954), None, Some(25813)), (None, None, Some(false), Some(-181271), Some(-9773643), Some(6213)), (Some(510512702), None, Some(false), None, None, None), (None, Some(141), None, Some(367593), Some(4628054), Some(41619)), (Some(304558798), Some(44), Some(false), Some(-549676), Some(5863341), Some(15097)), (Some(1227596405), None, Some(true), Some(188481), None, None), (Some(1508616232), None, Some(true), None, Some(2573862), None), (None, None, None, Some(715299), Some(-6076511), Some(61605)), (Some(-1241772527), Some(238), None, Some(568649), Some(3267424), None), (Some(-111784142), Some(44), None, Some(-265658), Some(-9458411), None), (Some(1011398847), None, None, None, Some(-1101701), None), (None, None, None, Some(-99156), Some(-6109062), None), (Some(-1230027325), Some(229), None, Some(816731), None, Some(516)), (None, Some(117), None, None, Some(-8222445), Some(21551)), (None, None, None, None, Some(-9654933), None), (Some(1307889918), None, None, Some(-92143), None, Some(1899)), (Some(-1611404340), None, Some(false), None, Some(1168179), None), (Some(1548451954), None, Some(false), None, None, Some(41899)), (Some(1684112333), Some(141), Some(false), None, Some(-2242357), None), (None, Some(115), None, None, Some(-4602859), Some(48121)), (None, Some(228), Some(false), None, None, None), (Some(-148749052), Some(236), Some(false), None, Some(-9950340), Some(63798)), (None, None, Some(false), None, Some(-2005861), Some(60870)), (Some(-315802227), None, None, Some(-572122), None, Some(43916)), (Some(-303385669), None, None, Some(-578450), None, Some(52156)), (None, Some(44), None, Some(-295537), None, Some(39558)), (Some(397153985), None, None, Some(677022), Some(-4973493), Some(13092)), (None, None, Some(false), None, Some(-6798361), None), (None, None, None, None, Some(1774076), Some(50202)), (None, None, None, None, Some(6962102), None), (None, None, None, None, Some(3380724), None), (None, None, Some(false), None, None, Some(15496)), (Some(173798100), Some(41), Some(false), Some(516620), None, Some(754)), (None, None, Some(true), Some(166866), None, None), (Some(-572579038), Some(54), Some(true), Some(759464), Some(-4668583), None), (Some(2103528752), None, Some(true), Some(-788706), Some(-7646560), None), (Some(-1725342013), None, Some(true), None, Some(8125374), Some(16853)), (Some(1027498220), Some(24), None, None, Some(-8358459), Some(55186)), (None, Some(108), Some(true), None, Some(4739093), None), (Some(-1220151097), Some(17), None, None, Some(7151341), None), (Some(-359571555), None, None, None, None, None), (Some(45887305), Some(34), Some(true), None, Some(1736807), Some(20887)), (Some(-38743655), Some(125), None, Some(-83389), Some(8785834), None), (None, None, None, Some(658507), Some(-2868468), Some(32700)), (Some(2019577004), None, Some(true), Some(555848), Some(4603611), Some(53693)), (None, Some(182), Some(true), Some(-486943), Some(6644426), Some(9477)), (None, None, Some(true), None, Some(7994150), None), (None, None, None, Some(-305177), None, None), (None, None, Some(false), Some(889761), None, Some(11357)), (Some(-305152897), None, None, Some(507842), None, None), (Some(268923904), Some(241), Some(true), Some(214179), Some(1244302), Some(9222)), (Some(217963833), Some(108), Some(true), Some(-554635), None, None), (Some(-558089417), None, Some(true), Some(768866), Some(-7005701), None), (None, Some(79), Some(true), None, Some(-6693107), Some(25087)), (Some(-625104924), Some(165), Some(true), Some(812997), None, None), (None, None, None, Some(-591291), None, Some(33604)), (Some(888118257), None, None, Some(-612363), None, None), (None, Some(142), Some(true), None, Some(-6942768), Some(44638)), (Some(-703878532), None, Some(true), None, None, None), (Some(1608502324), Some(12), Some(true), Some(504689), Some(-8931226), None), (None, Some(16), Some(true), None, Some(8504171), Some(64624)), (None, None, Some(true), None, None, Some(21836)), (Some(-1440481067), Some(24), None, Some(-234401), None, None), (None, Some(27), Some(true), None, None, None), (None, Some(61), Some(true), None, Some(-8973033), None), (Some(1493130630), Some(47), Some(true), Some(-434235), None, None), (None, Some(229), None, None, Some(-3998734), Some(40084)), (None, Some(52), Some(false), None, Some(4922586), None), (None, Some(244), Some(false), None, Some(-102448), Some(59731)), (Some(581762094), None, Some(true), None, None, None), (None, None, Some(true), Some(74106), None, None), (Some(-888933532), Some(163), Some(false), None, Some(-2930193), None), (None, None, Some(false), None, None, Some(10126)), (Some(-710439890), Some(103), Some(true), None, Some(645296), None), (None, None, None, None, None, Some(54326)), (None, Some(80), None, None, None, None), (None, None, Some(false), Some(-520652), Some(-8960873), Some(18834)), (Some(-254973971), Some(35), None, None, None, Some(373)), (Some(659275833), Some(192), None, Some(-382236), Some(-6681661), Some(1033)), (None, Some(140), Some(true), None, None, Some(58751)), (Some(-846038027), None, Some(false), None, None, None), (None, None, Some(true), None, None, None), (None, Some(14), None, Some(-663673), Some(2161771), Some(9287)), (None, None, Some(true), Some(479683), None, Some(65138)), (None, None, Some(false), Some(-877324), None, Some(20258)), (Some(398433042), None, None, Some(-404331), Some(-5947481), None), (None, Some(233), Some(false), Some(425064), None, None), (None, Some(239), Some(true), Some(-356496), None, None), (Some(1801359759), None, Some(false), None, Some(-1750745), Some(58197)), (Some(388851129), Some(205), Some(true), None, Some(-1919867), None), (None, Some(141), Some(true), None, None, None), (None, Some(251), Some(false), None, None, Some(60228)), (Some(245695656), Some(78), Some(true), None, None, Some(13884)), (Some(-842620079), None, Some(false), Some(861058), None, Some(44941)), (None, Some(72), Some(false), Some(-620271), None, None), (Some(1763908587), None, None, None, Some(-2256989), None), (Some(-518912594), Some(145), None, Some(-125560), None, None), (None, None, Some(true), Some(-839404), Some(3275055), None), (Some(548299336), None, Some(true), None, None, None), (None, None, Some(true), Some(-831134), Some(-9981676), None), (Some(509574369), None, Some(false), None, None, None), (None, None, Some(true), Some(-71579), None, Some(19136)), (Some(1269999459), None, None, None, Some(-7542995), None), (None, Some(121), Some(true), Some(214315), Some(6347792), Some(54877)), (None, Some(33), Some(false), Some(930447), None, None), (Some(169642569), Some(242), Some(false), None, None, Some(10850)), (Some(-1804967900), Some(51), None, Some(-566740), Some(-7347464), None), (None, None, None, None, Some(1675520), Some(63975)), (None, None, None, None, None, None), (None, Some(24), Some(false), Some(514451), Some(9128841), Some(14373)), (Some(136837143), Some(203), Some(true), Some(-560317), Some(9006196), None), (Some(-1703363245), None, None, Some(1243), None, Some(58285)), (None, None, Some(true), Some(-996403), Some(-7245821), None), (None, Some(41), None, Some(382811), None, Some(24036)), (None, Some(165), Some(false), None, Some(-8206358), Some(7169)), (None, Some(210), Some(true), Some(-287562), None, None), (Some(392675437), Some(227), Some(false), Some(-616297), Some(3342409), None), (None, Some(157), None, Some(336454), Some(4304881), Some(547)), (Some(-20630773), Some(121), None, None, Some(8986134), None), (Some(186333579), None, Some(true), Some(-514999), None, None), (Some(-1696933107), Some(120), None, None, Some(4705869), Some(23133)), (Some(-621688380), Some(0), None, Some(982695), Some(4286807), None), (Some(-1065643696), Some(252), Some(true), None, None, None), (Some(674623288), Some(184), None, Some(-35630), None, None), (None, None, Some(false), None, None, Some(13749)), (None, None, Some(false), None, Some(3430065), None), (Some(2104887160), Some(226), None, None, Some(6284024), Some(59047)), (Some(556840054), Some(136), None, None, None, None), (Some(-155905852), None, None, Some(-61534), Some(-7262865), Some(23853)), (Some(-1951671312), None, Some(false), Some(18153), Some(-8090143), None), (Some(1467935139), Some(175), None, None, Some(-7626180), None), (None, Some(152), Some(false), None, None, None), (Some(-1762489161), Some(206), None, None, None, Some(23348)), (Some(56134995), Some(72), None, None, Some(-3667430), None), (None, None, None, None, None, None), (Some(-600107408), None, Some(false), None, None, None), (Some(-1438113421), None, Some(true), Some(-87578), Some(-1990193), None), (None, None, None, Some(-345359), None, None), (None, None, None, Some(-881758), Some(802229), Some(23369)), (Some(-54499666), Some(160), None, None, Some(-7984119), None), (Some(1168344526), Some(15), None, Some(910844), None, Some(62476)), (Some(1651040392), Some(189), None, None, Some(-609634), None), (Some(196408477), None, Some(false), None, Some(8157980), None), (Some(1309529011), None, Some(true), Some(-142227), Some(-6087166), Some(28768)), (None, None, Some(false), None, Some(8024959), Some(59673)), (None, None, Some(false), Some(-177974), None, Some(8313)), (None, Some(125), Some(true), None, Some(7184797), None), (None, Some(69), Some(false), None, None, None), (None, None, None, Some(307340), Some(7004156), None), (None, None, None, None, Some(-4613840), None), (None, None, Some(false), None, Some(2454415), None), (Some(-1558248089), None, Some(false), Some(-339780), None, None), (Some(946461742), None, Some(true), Some(119102), Some(-7541983), Some(9720)), (None, None, None, Some(-721864), Some(208963), Some(26441)), (None, Some(161), Some(true), None, None, Some(11051)), (None, Some(218), Some(true), Some(394166), Some(-1878122), None), (Some(-780254754), None, Some(false), None, None, None), (None, Some(69), Some(true), Some(-544644), None, None), (None, Some(76), Some(false), None, Some(7599656), Some(13381)), (None, Some(117), Some(false), None, None, Some(26309)), (None, None, None, Some(-796138), Some(6130012), None), (None, Some(119), Some(false), None, Some(-2907768), None), (Some(1332137018), None, None, Some(30528), None, None), (None, Some(156), Some(false), Some(-197977), Some(-5476801), Some(1200)), (Some(-1443252150), None, Some(true), Some(-793786), None, Some(483)), (None, Some(176), None, None, Some(-2894329), Some(52629)), (None, None, Some(true), Some(421647), Some(3803742), Some(20864)), (Some(-1934207099), Some(223), Some(false), None, None, Some(47870)), (None, None, Some(true), None, None, Some(31577)), (None, None, Some(true), Some(12295), None, Some(36751)), (Some(1208028012), None, None, Some(627070), Some(-9081936), Some(28436)), (Some(133815901), Some(201), None, None, None, Some(52579)), (Some(-369679648), Some(90), None, None, Some(-3931412), Some(31882)), (None, Some(20), Some(true), None, None, Some(34559)), (None, None, None, None, Some(2570518), None), (None, None, None, Some(325871), None, Some(64018)), (Some(-1640310687), None, Some(false), Some(569), None, Some(35329)), (None, None, None, Some(-802895), None, None), (Some(-356022148), Some(86), Some(false), Some(746555), Some(-8935344), Some(29015)), (Some(1536514648), Some(154), None, None, Some(4771037), None), (None, Some(195), Some(false), Some(874407), None, Some(15732)), (Some(1542975347), Some(129), Some(false), None, Some(9320356), Some(22712)), (Some(2132636430), Some(64), None, None, Some(5161317), Some(36385)), (None, Some(200), Some(true), None, None, Some(48004)), (Some(-1267202624), Some(35), Some(true), None, Some(-3797037), None), (None, None, None, Some(-411769), Some(4972837), None), (None, Some(58), None, Some(-586292), Some(4259904), None), (None, Some(166), Some(true), Some(-560312), Some(-201587), Some(25961)), (Some(-402640761), None, None, None, None, Some(62011)), (Some(-1091526186), None, Some(false), None, Some(-6400218), None), (Some(459243783), Some(246), Some(false), None, Some(3191044), None), (None, None, None, None, Some(-6870075), None), (None, None, None, Some(567561), Some(5019519), Some(36009)), (Some(913191230), None, Some(false), None, Some(-1495664), Some(2192)), (Some(-500798279), None, Some(true), Some(646510), Some(-8845508), None), (None, Some(243), None, None, None, Some(51059)), (Some(-384631853), None, Some(true), Some(796588), Some(3997620), Some(59477)), (Some(1896000931), Some(59), None, None, Some(-5572632), None), (Some(-1839160634), Some(171), Some(false), Some(736442), None, None), (None, Some(182), None, None, None, Some(811)), (Some(-880738363), Some(180), None, None, None, Some(27671)), (Some(-1108706122), Some(157), Some(false), Some(359522), Some(-8780409), Some(49625)), (Some(1880526398), None, None, Some(-76488), Some(5605666), None), (Some(-1615745983), None, Some(false), None, Some(2813246), None), (Some(-1227569726), None, None, Some(-292399), None, None), (Some(1339340587), None, Some(false), None, Some(-178929), None), (Some(559819327), Some(41), Some(true), Some(133747), Some(6375125), None), (None, Some(22), None, Some(-769353), None, Some(64121)), (None, None, Some(false), Some(535153), None, Some(12323)), (Some(661284035), None, Some(false), None, Some(1902645), Some(55932)), (Some(-719373597), None, None, Some(-202292), None, Some(56229)), (Some(-1904224658), Some(52), None, None, None, None), (Some(586628212), None, Some(false), None, None, None), (None, Some(48), Some(true), None, Some(7066621), None), (Some(1803727516), Some(132), None, Some(650521), None, None), (Some(-1447462730), Some(213), None, Some(52370), None, None), (Some(-2103744201), None, None, Some(-169560), Some(-9341079), None), (None, Some(178), None, None, None, Some(45520)), (None, Some(90), Some(true), Some(-189128), Some(8560241), Some(27853)), (Some(-1258454845), Some(111), None, Some(162345), Some(6076614), Some(54336)), (None, Some(135), None, None, None, None), (None, Some(109), Some(true), None, Some(9691565), None), (Some(-816386158), None, None, None, None, None), (Some(-1965689715), Some(202), None, Some(129470), Some(-3377172), None), (Some(843111949), None, Some(true), Some(843593), Some(-5452875), Some(35372)), (Some(882266610), None, Some(false), None, Some(156877), None), (None, None, None, Some(-985185), Some(-6216882), Some(9034)), (None, None, Some(true), Some(-431474), None, Some(61209)), (None, None, Some(false), Some(-96488), None, Some(21714)), (Some(1870908405), None, None, Some(-256762), Some(2687009), Some(18655)), (Some(-485625119), Some(251), None, Some(178097), None, None), (Some(-1476900395), None, Some(true), None, Some(5027409), Some(40644)), (Some(-706488552), Some(237), Some(true), None, Some(-7890587), None), (None, None, Some(false), None, Some(3392114), None), (Some(-341982638), None, None, Some(3121), Some(5475253), None), (None, None, Some(true), Some(148230), Some(-8605429), Some(10889)), (None, Some(50), None, Some(53003), Some(3291175), None), (None, None, Some(false), Some(997828), Some(7815397), Some(35653)), (Some(521297380), None, None, Some(-571906), Some(385075), None), (Some(-608421308), None, Some(true), Some(166676), Some(-111574), Some(45034)), (Some(-42876657), Some(34), None, Some(127659), None, Some(54816)), (Some(493587422), None, None, None, Some(7032334), None), (Some(230695561), None, None, Some(-263433), None, None), (None, None, None, Some(-992174), None, Some(1643)), (Some(2077258443), Some(97), None, None, Some(1871789), Some(15829)), (None, None, None, None, Some(7740524), None), (None, None, Some(false), Some(597528), None, Some(19224)), (None, Some(207), Some(true), None, Some(6836541), Some(18964)), (None, None, None, Some(566290), None, None), (Some(-1647155662), Some(155), None, None, None, None), (Some(1108184738), None, None, None, None, None), (None, Some(117), None, Some(-917696), Some(5548446), None), (None, Some(40), None, Some(227432), None, Some(29700)), (None, None, Some(false), Some(478031), None, None), (None, None, None, None, None, Some(47435)), (None, Some(237), Some(true), None, None, None), (Some(-116337419), None, None, Some(-453278), None, Some(44458)), (Some(-535284255), None, None, Some(887778), Some(8494959), Some(28991)), (Some(-343683462), None, None, Some(127021), None, Some(61574)), (Some(896424649), Some(174), None, Some(-433619), None, Some(27334)), (None, None, None, Some(-705234), None, None), (Some(272249546), Some(229), None, Some(258809), Some(9039774), Some(64407)), (None, Some(86), Some(true), None, Some(-1890370), Some(34544)), (None, Some(79), None, Some(-762444), None, Some(44070)), (Some(-53898477), None, None, None, Some(-5985576), None), (Some(1983383745), None, None, None, Some(-8696998), Some(8672)), (Some(-1498834023), None, None, Some(559923), None, Some(63476)), (Some(-2114872451), None, Some(false), None, None, None), (None, None, Some(true), None, None, Some(30651)), (None, Some(143), Some(false), Some(470420), None, None), (Some(-2018926712), None, None, None, None, None), (None, Some(10), Some(true), Some(698516), Some(280349), Some(63710)), (Some(-1827852264), Some(53), None, None, Some(-7526093), None), (None, None, Some(false), Some(507687), None, None), (None, Some(224), None, None, None, Some(50304)), (None, Some(51), None, None, Some(-273499), None), (None, Some(142), None, Some(604825), None, Some(23552)), (None, Some(168), None, Some(933647), None, None), (Some(-644590094), None, Some(false), None, Some(5920941), Some(60767)), (None, None, None, None, Some(4556990), None), (Some(593055986), None, Some(true), None, Some(-3348111), None), (None, None, None, Some(685051), None, None), (None, Some(6), Some(false), Some(674847), Some(7368354), Some(45294)), (Some(-1143499416), None, None, Some(-713004), None, None), (Some(1664432909), None, None, None, None, Some(20556)), (None, Some(24), None, None, Some(1783173), Some(6361)), (None, Some(2), Some(false), None, None, Some(16349)), (Some(-1764126884), Some(16), None, None, Some(7228753), Some(24563)), (None, Some(39), None, Some(522184), None, None), (None, None, Some(true), None, Some(-5240670), None), (Some(2064031274), Some(207), None, None, Some(-1195404), Some(37788)), (Some(1315929795), None, None, Some(334610), None, None), (Some(-495959338), None, None, Some(-339742), None, Some(10017)), (Some(194928449), Some(218), Some(true), Some(-189906), None, Some(35860)), (Some(-1783598442), None, None, None, None, None), (Some(-2045038731), None, None, None, None, None), (Some(392059974), None, Some(false), None, Some(-1402121), None), (Some(1376189305), None, Some(false), Some(887997), Some(-2156906), Some(15249)), (Some(-111281797), Some(24), Some(true), Some(-655745), None, Some(50532)), (None, Some(228), Some(false), None, Some(4514714), Some(29614)), (Some(-1764003724), Some(183), Some(true), None, Some(-142018), None), (Some(-949162973), None, Some(false), None, Some(9266135), None), (None, None, Some(true), None, None, None), (Some(-1994640877), Some(73), None, Some(47122), None, Some(40002)), (None, None, None, Some(632482), Some(-4194689), None), (None, None, Some(true), None, None, None), (None, Some(65), None, None, None, None), (None, None, Some(true), None, None, Some(52429)), (None, None, None, None, Some(9572949), Some(38039)), (None, None, None, Some(-407645), Some(7506981), None), (None, Some(60), Some(false), None, Some(7383634), Some(45799)), (None, None, None, Some(-715739), Some(2076611), Some(16610)), (None, Some(33), Some(true), Some(-600180), Some(2724082), None), (Some(632282183), None, Some(true), None, Some(-1020135), None), (None, None, None, Some(-840396), Some(-755965), Some(45158)), (None, Some(21), None, Some(-714623), None, None), (Some(-196612318), Some(232), Some(true), Some(-243055), None, None), (None, None, None, None, None, None), (None, Some(130), Some(false), Some(362886), Some(-779240), Some(30816)), (Some(-1934508960), None, None, Some(734626), Some(-422720), Some(45727)), (None, Some(72), None, None, None, None), (None, None, None, None, Some(8084736), None), (None, Some(34), None, None, Some(4587355), None), (Some(866849126), Some(132), Some(false), None, None, None), (Some(-1555309801), None, Some(true), None, None, Some(55137)), (None, Some(44), Some(false), Some(-786793), Some(-2312771), None), (Some(744738448), None, Some(false), Some(-878871), Some(-1234847), None), (None, None, Some(true), None, None, None), (None, Some(211), Some(true), None, None, Some(2149)), (None, Some(207), Some(false), Some(-530398), None, Some(9108)), (Some(701752768), Some(193), None, Some(201453), Some(5194576), Some(43310)), (Some(-868983754), None, Some(true), None, Some(7325624), Some(56067)), (Some(-1679663963), Some(112), Some(false), None, Some(3939734), None), (None, Some(63), None, None, Some(-6367948), Some(58725)), (Some(-1413298570), Some(203), None, Some(-403697), Some(9439299), None), (None, None, Some(true), Some(-246054), None, None), (Some(832064868), Some(142), None, Some(-858060), Some(-3841693), None), (Some(1392635386), Some(228), Some(true), Some(-723100), Some(9758819), None), (Some(-2077677619), Some(125), None, Some(-41052), Some(-9126104), Some(41652)), (None, Some(52), Some(true), None, None, Some(38876)), (Some(-12358359), None, Some(true), Some(-227910), Some(-7092519), Some(14901)), (None, Some(239), None, None, Some(2404464), Some(62858)), (None, None, None, None, None, Some(51621)), (None, None, None, None, None, None), (Some(-2036326127), None, Some(true), None, None, Some(41796)), (Some(-1628834965), None, None, None, None, None), (None, None, None, Some(485565), Some(-2167847), None), (None, Some(211), Some(false), Some(-96079), Some(2508493), None), (None, Some(128), None, None, Some(-5724955), None), (Some(1229787915), Some(88), Some(false), Some(-481561), Some(8205000), Some(7985)), (Some(-1857082494), Some(188), Some(true), None, Some(1839519), Some(397)), (Some(-1271728503), None, Some(true), Some(11465), None, Some(50381)), (Some(890101245), Some(231), None, Some(-374117), Some(1783537), None), (Some(-417737019), Some(103), None, Some(-657230), None, None), (None, None, Some(false), Some(457867), None, None), (None, None, Some(false), None, Some(1676950), Some(34573)), (None, Some(14), Some(true), Some(-596265), None, Some(20950)), (Some(939575594), Some(81), None, Some(79533), None, Some(9663)), (Some(254818208), Some(11), Some(true), None, None, Some(13780)), (Some(-828610418), None, None, None, Some(1537183), Some(47416)), (None, Some(125), None, Some(89786), None, Some(8567)), (Some(-1337471719), Some(150), None, None, Some(2966127), None), (None, None, Some(true), None, Some(-9165726), Some(1732)), (None, Some(121), None, Some(-207969), Some(-5999727), Some(9912)), (Some(2034067257), None, None, None, Some(7612017), Some(12267)), (None, Some(168), Some(true), Some(203215), None, Some(20520)), (None, None, Some(false), Some(-68119), None, None), (None, None, Some(true), Some(-408231), None, None), (Some(1535933576), None, Some(true), Some(577311), None, Some(63772)), (None, Some(101), None, Some(764131), None, Some(25500)), (Some(-10093959), None, Some(true), None, None, None), (None, Some(46), Some(true), None, Some(-1205710), Some(4376)), (None, None, Some(false), Some(255453), Some(-6407218), Some(40295)), (Some(1930716614), None, None, None, Some(1464808), None), (Some(-831197206), None, None, None, Some(-5906559), Some(36309)), (None, None, Some(true), Some(17270), Some(8244292), None), (Some(-1491537575), Some(224), Some(false), Some(137279), None, None), (None, Some(134), Some(false), None, None, Some(5694)), (Some(1279574468), None, Some(false), Some(13982), None, None), (Some(784608951), Some(26), None, None, Some(962207), Some(25408)), (Some(534679307), Some(101), None, Some(-270351), Some(450120), None), (None, Some(3), Some(true), None, Some(3052146), None), (None, None, None, None, None, None), (None, Some(43), Some(true), Some(-512900), None, Some(10298)), (None, None, Some(false), Some(-916236), Some(-5609068), None), (None, None, Some(false), None, Some(8714134), None), (None, Some(203), Some(true), Some(-470801), None, None), (Some(1429416598), Some(62), Some(true), None, None, Some(49969)), (Some(2127299642), None, None, Some(-249528), Some(-3042094), Some(4237)), (Some(1816544484), None, None, Some(702999), Some(-8295186), Some(51828)), (None, Some(228), None, None, Some(-8042215), Some(23187)), (None, None, None, None, None, None), (Some(-920153521), None, Some(true), Some(148636), None, Some(920)), (None, None, Some(true), None, Some(-54942), Some(24245)), (None, Some(99), Some(true), None, None, Some(18861)), (None, None, Some(true), None, None, Some(63620)), (Some(-1699734284), Some(70), Some(true), None, Some(-6670794), Some(26207)), (Some(12156221), None, Some(false), None, None, Some(31362)), (Some(1868135509), None, None, Some(-920281), None, Some(34106)), (None, None, None, Some(-649857), None, None), (None, None, None, Some(-211182), None, None), (None, Some(244), Some(false), None, None, Some(11801)), (Some(1198497472), None, Some(false), Some(-195792), Some(3591126), None), (None, None, Some(true), None, None, None), (Some(-1833820017), None, Some(false), Some(833438), Some(6294761), Some(10147)), (None, None, None, None, Some(-6728549), Some(64723)), (Some(691501366), Some(198), Some(true), Some(-262321), None, None), (None, Some(178), None, None, None, None), (None, None, None, Some(-178050), Some(-2610880), None), (None, Some(239), Some(true), Some(965101), None, Some(24016)), (None, None, Some(true), Some(833526), Some(6443155), None), (None, None, Some(false), Some(788595), None, Some(18224)), (None, Some(50), Some(false), Some(-955738), None, None), (Some(1878398985), None, None, Some(-53381), None, None), (Some(-88390446), Some(87), Some(false), None, None, Some(2086)), (None, None, None, None, None, Some(2865)), (Some(-673193339), Some(210), Some(true), None, None, Some(52958)), (None, None, Some(true), None, None, Some(1657)), (None, None, None, Some(558049), None, None), (None, Some(179), None, None, None, Some(20497)), (Some(1288906539), None, None, None, None, None), (None, None, Some(true), Some(51997), None, None), (None, None, Some(true), Some(784990), None, None), (None, None, Some(true), Some(-336293), Some(-3949557), None), (None, Some(196), None, Some(185088), None, None), (None, Some(187), Some(false), None, None, Some(51982)), (Some(-1174636072), None, Some(true), Some(-601009), Some(7413401), Some(36562)), (None, Some(236), None, Some(65739), None, Some(3685)), (None, None, None, None, None, None), (None, Some(68), None, None, None, None), (None, Some(53), None, Some(-233845), Some(7084648), None), (None, Some(136), Some(true), Some(79421), None, None), (None, None, Some(true), Some(-437528), None, Some(15243)), (None, Some(126), None, Some(-320809), Some(1460916), None), (None, Some(104), None, None, Some(1762), None), (None, None, Some(true), None, None, None), (Some(514058439), Some(17), None, Some(-12553), None, None), (Some(-1714259347), Some(126), None, Some(-820234), None, None), (None, Some(229), None, Some(172585), Some(5579671), Some(54891)), (None, None, Some(true), Some(-849791), None, None), (Some(-1402911117), Some(126), Some(false), Some(-164372), None, None), (Some(-791144103), None, Some(true), Some(780256), None, Some(18940)), (Some(1731946222), None, None, None, None, Some(35301)), (None, Some(222), Some(true), None, Some(8348985), Some(38934)), (None, Some(138), Some(false), None, None, None), (None, None, None, None, None, Some(37035)), (Some(2019062194), None, None, None, None, Some(7253)), (Some(293805022), Some(187), Some(false), None, Some(9960547), None), (Some(164052954), Some(144), Some(false), None, Some(-2278673), Some(45213)), (None, Some(7), None, None, None, Some(26646)), (None, None, Some(false), Some(566124), None, Some(35743)), (None, Some(213), None, None, None, None), (Some(995122743), None, Some(false), Some(-570120), None, Some(1866)), (Some(907647621), None, Some(false), Some(-206200), None, None), (Some(-1053424210), Some(183), Some(false), Some(-115435), None, Some(26753)), (None, None, Some(false), None, None, None), (None, None, None, Some(986267), None, Some(6550)), (None, Some(27), Some(true), Some(-28463), None, None), (Some(-842103807), Some(239), None, Some(-298854), None, None), (None, None, Some(true), Some(-475873), Some(3699414), None), (None, None, None, None, Some(-7558961), Some(20663)), (None, None, Some(true), Some(-508341), None, None), (None, Some(114), Some(false), Some(114193), Some(7859469), Some(43244)), (None, Some(155), None, None, Some(8591032), None), (None, None, None, None, Some(-4013215), None), (Some(-890752265), None, Some(true), None, Some(708394), Some(20579)), (None, None, Some(false), None, None, Some(25081)), (None, Some(69), Some(false), Some(-678721), None, Some(59772)), (Some(649341720), Some(83), None, None, Some(-8204531), Some(47331)), (Some(1227872477), None, None, Some(-777038), None, None), (None, Some(213), Some(false), None, None, None), (None, Some(243), None, None, None, Some(15355)), (Some(1668776384), None, None, None, Some(9214359), Some(64460)), (Some(495642642), None, None, None, None, Some(48263)), (None, None, Some(false), None, None, Some(7263)), (Some(1122847684), Some(25), None, None, Some(-9369055), None), (None, Some(58), None, None, Some(-7591937), None), (Some(157636229), Some(231), None, None, None, None), (None, None, None, None, Some(-1467210), Some(35213)), (Some(-1330429864), Some(81), Some(true), None, None, Some(11751)), (Some(478823713), Some(178), Some(false), Some(-49605), None, Some(59907)), (None, None, Some(true), None, Some(-2347638), Some(16184)), (Some(1752984512), None, None, Some(-615811), Some(-7733533), None), (None, Some(155), None, Some(-370487), Some(2717151), Some(8915)), (Some(1585779399), None, None, Some(941332), None, None), (Some(-1408248562), Some(66), Some(false), Some(-209119), None, Some(3629)), (None, Some(221), None, Some(-380050), None, None), (Some(1520359957), None, Some(false), Some(967394), None, Some(46217)), (None, None, None, None, Some(7933926), None), (None, None, None, None, Some(-370430), Some(48150)), (Some(-58860619), Some(237), Some(false), None, None, None), (None, Some(110), None, Some(-727618), Some(9320647), Some(40280)), (Some(1873673033), None, Some(true), None, None, None), (None, None, None, Some(366397), None, Some(13737)), (Some(13528974), None, None, None, Some(9615174), None), (Some(-66751258), Some(132), Some(false), None, Some(5459948), None), (None, Some(192), Some(true), None, None, None), (Some(1606073617), None, None, None, Some(2453958), Some(46912)), (None, None, None, None, Some(-214587), None), (None, None, None, None, Some(7300647), Some(54285)), (None, Some(106), None, Some(67151), None, None), (Some(-1702518510), Some(2), Some(true), None, None, None), (None, None, Some(true), Some(-625082), Some(-9876377), None), (Some(2106180670), Some(25), None, Some(-34391), Some(1794197), Some(10204)), (Some(-810439242), Some(237), Some(true), Some(-573209), None, None), (None, Some(188), None, None, Some(-6993562), None), (None, None, Some(true), None, Some(2634076), None), (Some(-661778607), Some(13), None, None, None, Some(47906)), (Some(883054436), None, None, None, Some(-5242369), Some(51734)), (None, None, None, Some(838091), None, Some(58847)), (None, None, None, None, Some(-2494457), None), (Some(-118840272), Some(230), Some(false), None, Some(-8550574), Some(4205)), (Some(-1059927369), Some(114), Some(true), Some(948679), None, None), (None, Some(249), Some(false), Some(-412009), None, None), (Some(1986804459), None, None, Some(837922), None, None), (None, None, None, None, Some(-9083673), None), (Some(-2121318139), None, Some(false), None, None, None), (None, None, Some(true), Some(-252241), None, None), (Some(796964809), Some(155), None, None, None, Some(65311)), (Some(207975991), None, None, None, None, Some(44057)), (None, Some(140), Some(false), Some(623089), None, None), (Some(-718226603), None, Some(true), Some(-514443), None, None), (None, Some(57), Some(false), None, None, Some(30652)), (Some(1759993268), Some(43), Some(false), Some(-664135), Some(-2361400), None), (Some(-1402356652), Some(36), Some(true), None, Some(-2507162), None), (Some(224845605), None, Some(true), None, Some(-203871), None), (Some(2142698349), None, Some(true), None, Some(-4368161), None), (None, Some(211), Some(false), Some(-796400), Some(6744202), None), (Some(-1398045927), None, None, None, Some(9570427), Some(12813)), (Some(-2028092683), None, Some(true), Some(989946), Some(-6733582), Some(42120)), (Some(-1146016876), None, Some(false), None, Some(-7021641), Some(1609)), (None, None, Some(true), Some(-368336), None, None), (Some(833776964), None, None, Some(742157), None, None), (None, None, Some(false), None, Some(-755823), None), (None, Some(242), None, None, None, None), (Some(-1912211211), None, None, Some(-590834), Some(-6029594), Some(33954)), (Some(2013421618), Some(1), None, None, Some(-7981399), None), (Some(711288520), None, Some(true), Some(871228), None, None), (None, Some(14), None, None, Some(-9525011), None), (None, Some(197), Some(false), Some(992458), None, None), (None, None, None, Some(6329), None, None), (None, Some(196), None, None, None, None), (None, None, Some(false), Some(-31618), None, None), (Some(-1926147804), Some(21), Some(false), Some(354119), None, None), (None, None, Some(true), Some(-475583), Some(9623485), Some(15265)), (None, Some(52), Some(false), Some(-251348), Some(6947793), Some(5373)), (Some(-1054559566), None, Some(true), None, Some(9844445), Some(12700)), (None, Some(174), Some(true), Some(974620), None, Some(64775)), (Some(-2053108740), None, Some(false), Some(-729581), Some(2502907), Some(47875)), (Some(-498456820), None, Some(true), None, None, None), (Some(887220505), Some(183), Some(true), None, None, Some(9253)), (Some(520646091), None, None, None, Some(4102373), None), (Some(-731793706), Some(162), Some(false), Some(-286657), None, None), (Some(938195525), Some(4), None, None, None, None), (Some(-1729673393), Some(123), Some(true), None, None, None), (None, Some(117), None, None, Some(-6509317), None), (None, Some(136), Some(true), Some(-512105), None, Some(9799)), (None, None, None, Some(-870855), Some(-4289831), Some(40651)), (None, None, None, None, None, Some(20029)), (Some(-1742133803), Some(96), None, Some(-944640), None, Some(64977)), (Some(270923504), None, None, Some(42598), None, None), (None, Some(146), Some(true), Some(-420371), None, Some(23107)), (Some(-814751990), None, Some(false), None, Some(-3923840), Some(64393)), (Some(-1334819683), None, None, None, None, Some(19424)), (None, Some(232), Some(false), Some(-948782), Some(-915317), Some(13838)), (None, None, Some(true), Some(-330429), Some(-5204732), Some(8739)), (Some(-2059990481), Some(21), None, Some(592578), Some(-4898754), None), (None, Some(135), None, None, None, None), (Some(-392321130), None, Some(true), Some(700212), Some(-342088), None), (Some(922400314), None, None, Some(613903), Some(-2169105), Some(29527)), (None, None, Some(true), Some(-48744), Some(-8541351), Some(29838)), (Some(-1832582085), Some(212), Some(false), None, Some(-5124801), None), (None, Some(132), Some(false), Some(-173332), Some(7265874), None), (Some(-509833337), Some(6), None, None, Some(1785824), Some(31429)), (None, Some(211), Some(false), Some(858431), None, Some(35921)), (None, Some(238), Some(false), Some(-890358), Some(-3719995), None), (None, Some(39), None, Some(-365622), None, None), (None, None, None, Some(713630), None, Some(31560)), (None, None, Some(false), Some(-684600), None, None), (None, None, None, None, None, Some(29629)), (Some(549008304), Some(228), None, Some(-297077), None, Some(48546)), (Some(425993718), None, None, Some(719051), Some(6419378), Some(56933)), (Some(929357952), Some(44), Some(false), None, Some(-1162464), Some(29085)), (Some(132784591), Some(163), None, None, None, Some(41045)), (Some(93986004), Some(25), Some(true), None, Some(8926563), None), (Some(-476741208), None, Some(true), None, Some(9412641), None), (Some(-135472132), None, Some(false), None, None, None), (None, Some(177), None, Some(743421), Some(8053836), None), (Some(-986877691), None, None, None, None, Some(63656)), (Some(1553338675), None, Some(false), Some(-977638), Some(3199820), Some(55157)), (None, Some(85), None, Some(-366222), None, Some(60378)), (None, None, Some(true), Some(629424), Some(2619813), Some(19463)), (None, None, Some(false), Some(511589), Some(3835000), None), (None, Some(254), None, Some(-259573), Some(-1988386), Some(36484)), (Some(634667869), None, None, None, Some(8597267), None), (None, Some(109), Some(true), Some(847677), Some(-8894965), None), (Some(-1600364659), Some(158), Some(false), None, None, None), (Some(-392662000), Some(62), Some(false), None, None, Some(16146)), (None, None, Some(true), Some(646312), None, None), (Some(-1872192386), None, None, None, None, None), (Some(390960239), None, Some(true), Some(-985051), Some(-2307359), None), (None, None, Some(true), Some(662863), Some(8631300), Some(27825)), (None, None, None, None, None, Some(44046)), (None, None, None, None, None, None), (None, None, None, None, None, None), (Some(-793922767), None, None, Some(-727382), Some(-1333827), None), (Some(988502694), None, None, None, Some(-6764366), None), (Some(1061247045), Some(186), Some(false), None, Some(7130568), None), (None, Some(178), Some(true), None, None, Some(27404)), (Some(1041535852), None, Some(true), None, None, Some(9008)), (None, Some(23), Some(false), None, Some(8405195), None), (Some(-1743274101), Some(231), None, None, Some(1811566), Some(49576)), (Some(-1185532297), None, Some(true), Some(537625), Some(334431), Some(24022)), (Some(-1750143197), Some(26), None, Some(-937743), None, Some(46461)), (None, Some(38), None, Some(-577371), None, Some(50118)), (None, Some(173), None, None, None, Some(35336)), (None, None, Some(false), None, Some(2028596), Some(24988)), (None, Some(168), None, None, Some(-8188777), None), (None, Some(107), None, Some(123282), None, Some(12142)), (None, Some(55), Some(false), Some(-225470), None, Some(58447)), (None, Some(76), None, None, Some(-9908209), Some(8293)), (Some(646828534), Some(226), Some(false), Some(-878633), None, None), (None, None, Some(true), None, None, Some(44972)), (Some(-2095916017), Some(209), None, None, None, None), (Some(787925442), Some(155), Some(false), Some(-903222), Some(-9081611), Some(9875)), (None, Some(58), Some(true), Some(225895), Some(3311378), Some(20407)), (Some(371408893), Some(12), Some(false), None, Some(-2224226), Some(14330)), (None, None, None, Some(-963486), None, Some(35135)), (None, Some(206), Some(true), None, Some(7469104), None), (Some(-1684730610), None, None, None, Some(8121923), Some(47358)), (Some(-1020599185), None, None, None, None, None), (Some(151528444), Some(76), None, Some(-309182), None, Some(7356)), (Some(-594185256), Some(197), None, None, None, None), (None, None, None, None, Some(-1684014), Some(13013)), (Some(-1707650857), None, Some(true), None, Some(-4857381), Some(14620)), (Some(-2054702264), None, Some(false), Some(706695), None, Some(53349)), (Some(-1608700092), Some(2), Some(true), None, None, None), (None, Some(13), None, Some(927364), Some(-845024), Some(41335)), (None, None, Some(true), Some(125015), Some(1617055), None), (None, Some(97), Some(true), Some(44236), Some(3696355), Some(22064)), (Some(690771861), None, Some(true), Some(300344), Some(-7877238), None), (None, Some(209), None, None, Some(2084127), Some(21680)), (None, Some(175), None, None, Some(2808518), None), (Some(46589450), Some(234), None, Some(238665), Some(8087260), Some(65313)), (Some(-1831340396), Some(76), None, Some(-360793), Some(-4315315), Some(45841)), (Some(1241573983), Some(225), Some(false), Some(829394), Some(-5749715), Some(11178)), (Some(-333084805), None, Some(true), Some(-570749), Some(-792413), None), (Some(1589062245), None, None, None, Some(-5174178), Some(37170)), (None, Some(12), Some(true), Some(-705829), Some(-1698661), Some(4913)), (Some(1409062248), Some(251), None, Some(-593058), None, Some(12748)), (Some(942378413), Some(90), None, None, Some(7719218), None), (None, None, Some(true), None, Some(5801667), Some(60144)), (Some(1570719797), None, None, Some(-792401), None, Some(39761)), (Some(-458495798), None, Some(true), Some(-36337), None, None), (None, Some(63), None, Some(408218), None, Some(44420)), (Some(-2032843090), None, Some(false), None, None, None), (None, Some(35), None, None, Some(-8351094), None), (Some(-979552398), Some(210), None, Some(-861691), None, Some(19652)), (Some(-110105152), None, None, Some(-288009), Some(-8805268), Some(27399)), (Some(-818834533), Some(87), Some(true), Some(-959938), Some(1597789), None), (Some(-2144985308), None, None, Some(265053), Some(-5126083), Some(31721)), (None, Some(140), None, None, None, Some(15050)), (Some(-549864893), Some(118), None, None, None, Some(51834)), (Some(422618694), Some(166), Some(false), Some(-841536), Some(-6681733), None), (None, Some(247), Some(true), None, None, Some(56764)), (None, Some(34), None, None, Some(-7158022), Some(56737)), (None, Some(38), Some(false), Some(100519), Some(3882748), Some(36789)), (None, None, Some(false), Some(-23243), Some(5589890), Some(43419)), (None, Some(254), Some(true), Some(-504037), Some(4090793), Some(30917)), (Some(-1186980587), None, None, None, Some(8187479), None), (Some(1859830490), Some(213), None, Some(509706), None, None), (None, None, Some(false), Some(-917884), Some(4640948), None), (Some(-284826265), Some(224), Some(true), None, None, None), (None, Some(4), Some(true), None, None, Some(39873)), (Some(1392708885), Some(24), Some(false), Some(-895966), Some(-6566666), None), (Some(334838310), Some(206), None, Some(521471), Some(-8620247), None), (None, Some(59), None, None, None, None), (Some(1534669353), None, None, Some(928415), Some(6802172), Some(65288)), (Some(-1117103514), Some(63), None, Some(-568016), None, Some(44815)), (None, None, Some(true), None, None, Some(34188)), (None, None, None, Some(452819), Some(-4294427), Some(51258)), (None, None, Some(true), None, None, None), (Some(862047971), None, None, Some(132881), None, None), (Some(-1387058204), None, Some(true), None, None, Some(6122)), (Some(1158652162), None, Some(true), Some(-223918), Some(-7861202), None), (None, Some(153), Some(false), None, None, None), (Some(-41457742), Some(196), Some(false), None, None, None), (Some(1824712196), Some(143), Some(false), Some(-863995), None, None), (Some(-631255801), None, Some(true), Some(-938210), Some(-8104976), None), (None, Some(103), None, None, Some(2742259), Some(8076)), (None, None, Some(true), None, Some(-332111), Some(11782)), (None, None, Some(true), None, None, Some(60451)), (None, Some(238), None, Some(218737), Some(-1932280), None), (Some(-743067615), None, None, None, None, Some(31960)), (Some(-498814967), Some(199), Some(false), None, Some(-9606101), Some(53059)), (Some(1250591670), Some(136), Some(false), None, None, None), (None, Some(241), Some(false), Some(-236481), Some(-4164748), None), (Some(854375233), Some(19), Some(true), None, None, None), (None, None, Some(false), None, None, None), (None, Some(200), None, Some(463908), Some(7871544), Some(3835)), (Some(1459036717), Some(11), None, None, None, Some(44046)), (Some(1629385961), Some(228), None, Some(254139), Some(-3796023), Some(10546)), (Some(-276055398), Some(149), Some(false), Some(-224594), None, Some(9015)), (None, None, Some(false), Some(113616), Some(-1954794), Some(44660)), (Some(1103864989), None, Some(false), Some(572597), Some(5758548), None), (Some(-1756383409), Some(170), None, Some(-567631), None, Some(18876)), (None, None, None, Some(578060), Some(1808191), None), (Some(1415365749), None, Some(false), None, None, Some(33128)), (None, None, None, None, None, None), (None, None, None, None, None, Some(29539)), (Some(-1080118554), None, Some(true), Some(998332), None, None), (Some(-285202167), Some(21), None, Some(867980), None, None), (Some(896896870), None, Some(true), None, Some(-5177706), None), (Some(-234499101), Some(118), Some(false), None, None, Some(25641)), (None, Some(186), None, Some(-895763), None, None), (None, None, None, Some(-873784), None, Some(24733)), (Some(134526659), None, None, Some(-122793), None, Some(6012)), (None, Some(153), None, Some(997615), Some(-4763662), Some(58748)), (None, Some(173), None, None, None, None), (Some(-1242521259), Some(195), None, None, None, Some(50456)), (Some(-908544394), None, None, None, Some(-6100671), None), (Some(-1741708117), Some(240), None, Some(962193), Some(-4370877), None), (Some(1773945363), None, Some(true), None, Some(8406514), None), (Some(2135097703), None, None, Some(-348718), Some(8963988), Some(60331)), (Some(-30505665), Some(77), Some(true), None, None, None), (None, Some(113), Some(false), Some(975267), None, None), (Some(33185160), None, None, None, Some(3173240), None), (None, Some(247), None, None, None, None), (Some(1885066090), None, None, Some(868191), None, Some(28866)), (Some(-719700434), None, Some(false), None, None, Some(45584)), (None, Some(49), None, Some(616479), None, Some(30328)), (None, None, None, Some(-696749), Some(-4829410), Some(14839)), (Some(-250673635), None, None, Some(965177), None, Some(63341)), (None, None, None, Some(-69305), None, Some(3717)), (Some(-1088544254), None, None, Some(649797), None, Some(5303)), (None, Some(78), None, Some(-471314), None, Some(6500)), (None, None, None, Some(975140), Some(-1064655), None), (None, None, Some(false), None, Some(-924430), Some(17589)), (Some(-1565179397), Some(173), None, Some(765328), Some(4865631), Some(17844)), (Some(-1230078097), None, Some(true), Some(111430), Some(2583666), Some(5372)), (Some(-1152316544), Some(181), None, None, Some(-9168818), None), (Some(1709216503), Some(63), Some(true), None, Some(237717), None), (Some(-78343898), None, None, None, None, None), (None, Some(158), None, Some(-967074), Some(6562290), None), (None, None, None, None, None, None), (Some(1963199553), Some(26), None, Some(-763721), None, None), (None, None, Some(true), Some(-939635), Some(-1242830), Some(15838)), (None, Some(216), Some(true), None, Some(-9090859), Some(36555)), (None, Some(146), None, None, Some(-7714678), Some(11677)), (None, None, None, None, None, Some(58404)), (Some(-1915936022), Some(145), None, Some(-73208), None, Some(14679)), (None, Some(221), Some(true), Some(-861070), None, None), (None, None, None, Some(-96005), None, None), (Some(1121753099), None, Some(false), Some(827001), Some(2731727), Some(47957)), (None, None, Some(false), Some(-356976), Some(5184774), None), (None, None, Some(true), Some(481454), Some(3304995), None), (Some(-707146686), None, None, Some(170296), Some(6997016), Some(53699)), (Some(-1374472463), Some(233), Some(true), None, Some(-9289428), None), (None, None, Some(false), None, Some(-4956897), None), (Some(1412820841), Some(83), Some(false), Some(-596881), Some(2721866), Some(14789)), (Some(-1606117990), Some(85), None, Some(746616), None, Some(22325)), (Some(-2062553524), None, None, None, None, Some(40634)), (None, Some(135), Some(true), None, None, Some(533)), (Some(1021272666), Some(56), None, None, None, None), (Some(-868362865), Some(30), None, Some(-392501), None, Some(1219)), (Some(1308647948), Some(108), None, Some(507885), None, Some(46232)), (Some(-1533569142), None, None, Some(-155033), None, None), (None, None, Some(true), Some(959623), None, Some(43827)), (Some(-985078729), Some(29), None, Some(960355), None, Some(45962)), (None, None, Some(false), Some(175935), Some(-3526335), None), (Some(2077828094), Some(98), None, Some(-152415), Some(3059991), None), (None, Some(24), Some(false), Some(912339), None, Some(42462)), (Some(2114830482), Some(26), Some(true), None, Some(6312516), Some(57935)), (Some(427109905), Some(130), None, Some(501148), Some(3892273), Some(11131)), (Some(1949940039), None, None, None, Some(-8698272), None), (Some(1321813741), Some(11), Some(false), Some(798831), Some(-775863), Some(1356)), (Some(1020783145), Some(221), Some(true), None, Some(-8842476), None), (Some(45797813), None, None, Some(161259), Some(-7757301), Some(11504)), (None, Some(255), None, Some(511798), Some(-482220), None), (None, Some(55), None, Some(-502193), None, None), (None, None, Some(true), None, None, Some(64334)), (None, Some(46), None, None, Some(-1251359), Some(1228)), (None, None, None, None, None, Some(13679)), (None, None, None, None, Some(1054960), None), (Some(1979852127), None, Some(true), Some(296975), Some(8315196), None), (Some(-518991990), Some(11), Some(false), None, Some(-3064262), Some(7662)), (None, None, None, Some(706031), Some(754851), Some(45692)), (Some(-1912409407), None, None, None, None, Some(59318)), (None, None, None, Some(971027), Some(-1727854), None), (None, None, Some(false), Some(314727), None, None), (None, None, Some(false), None, Some(7743859), Some(64584)), (None, Some(35), Some(true), Some(-917677), None, None), (None, Some(254), Some(false), None, None, Some(32307)), (Some(782913834), None, None, None, None, Some(22944)), (Some(2001144344), Some(192), Some(false), None, Some(2840752), Some(62592)), (Some(-1556583702), None, None, Some(-583936), None, Some(22765)), (Some(1062949395), None, None, None, None, None), (None, None, None, Some(282459), Some(9654836), None), (None, Some(95), Some(true), Some(-428455), Some(9280814), None), (None, Some(221), Some(true), Some(-715936), Some(-4386248), Some(18490)), (Some(1313604979), Some(125), None, Some(2064), Some(-3703755), Some(44421)), (Some(-809547013), None, Some(false), None, Some(-2618853), Some(29901)), (Some(-1621244742), None, None, None, None, Some(43005)), (Some(174286000), None, Some(false), Some(36194), Some(-8875495), None), (Some(-1018466593), None, None, Some(-740546), None, None), (Some(1670932832), None, Some(true), Some(-373909), Some(-9381909), None), (Some(-1727052127), Some(115), Some(false), Some(-311083), Some(5521009), Some(35045)), (Some(-395682195), Some(42), None, None, Some(9700994), Some(22890)), (Some(1456383039), Some(29), None, Some(-862411), Some(3527797), None), (None, Some(72), Some(true), Some(54351), None, None), (Some(-1077559054), Some(164), None, Some(-895101), None, Some(41846)), (None, None, None, Some(273995), Some(3531091), None), (None, Some(114), None, Some(-368062), Some(6393720), Some(2769)), (None, None, None, Some(-296569), Some(9249887), Some(38263)), (None, None, Some(true), Some(210668), None, None), (None, Some(136), Some(false), Some(308751), Some(1174179), None), (None, Some(56), None, Some(430485), None, None), (None, Some(150), None, Some(906208), Some(4306063), Some(36920)), (None, None, Some(true), Some(-882705), Some(-5377116), None), (None, None, Some(false), None, None, None), (None, None, None, Some(-261648), Some(-2584025), Some(41401)), (Some(490378081), None, Some(true), None, Some(-2354309), Some(6829)), (Some(-580446892), Some(38), None, None, None, None), (Some(211560711), None, Some(true), Some(-445304), None, None), (Some(-1376668163), Some(101), Some(false), None, None, Some(723)), (Some(-161253640), None, Some(true), Some(-557956), None, None), (None, Some(187), None, None, Some(-5584880), Some(17979)), (Some(-1619682467), Some(80), None, None, None, Some(31881)), (Some(832585460), Some(37), Some(false), Some(354749), Some(-5183266), Some(57420)), (Some(-527045169), Some(163), Some(false), Some(-459028), Some(-9202763), Some(48976)), (Some(-151566226), Some(36), Some(true), None, None, None), (Some(69425334), None, Some(false), None, Some(80550), None), (Some(1559358570), Some(47), Some(false), None, None, None), (Some(-627351334), Some(132), Some(false), None, None, Some(7563)), (None, None, Some(true), Some(507161), None, Some(27771)), (None, None, None, Some(274478), None, None), (None, Some(140), Some(true), None, Some(-7526607), Some(64934)), (Some(885371956), None, Some(false), Some(630053), Some(-4709241), None), (Some(-1418237212), Some(50), Some(true), Some(757365), Some(3050375), Some(55108)), (None, Some(242), Some(false), None, None, Some(18844)), (None, None, None, Some(-954334), Some(-7588603), None), (Some(-479299815), Some(65), None, None, Some(-5373200), None), (None, None, Some(false), Some(-976957), None, None), (None, None, Some(false), None, Some(959516), Some(15843)), (None, Some(168), Some(false), None, None, None), (None, Some(201), Some(true), Some(-394680), None, Some(50652)), (Some(1554444999), Some(133), None, Some(-772572), None, Some(27340)), (None, Some(214), None, None, None, None), (None, Some(5), None, Some(-496377), Some(-3277901), None), (None, Some(224), Some(false), None, Some(-7012140), Some(33045)), (Some(-1506801287), None, Some(true), Some(-157197), None, Some(19805)), (Some(-1703700919), None, None, Some(-572203), Some(-6189676), Some(25376)), (Some(-1952546408), None, Some(true), Some(-951672), Some(5917208), None), (None, None, Some(true), None, Some(6102341), Some(54608)), (Some(-1143118466), None, None, None, None, Some(38094)), (Some(-805179531), None, Some(false), Some(901110), Some(1161480), Some(54042)), (Some(-1305446773), None, None, None, Some(9867283), Some(35332)), (None, Some(235), Some(true), Some(541101), Some(-3269612), Some(9420)), (Some(289858877), None, None, None, None, None), (Some(652150717), Some(31), None, Some(-451656), Some(-551064), None), (None, None, Some(true), None, None, None), (None, Some(4), None, None, Some(-7083710), Some(17165)), (Some(-123829656), None, Some(false), Some(-61324), Some(935979), Some(62882)), (None, Some(196), None, None, Some(7810369), Some(33597)), (None, None, None, Some(163329), None, Some(47833)), (Some(1621675895), None, None, Some(-326442), None, Some(23140)), (None, None, Some(true), None, Some(-5794505), Some(5846)), (Some(-1125364889), None, Some(false), Some(375883), Some(3844592), None), (Some(1930509195), Some(1), None, Some(-14269), None, Some(45322)), (None, None, None, None, None, None), (Some(-1044273223), None, None, Some(-218843), Some(8572175), Some(35779)), (Some(-755772027), None, Some(true), None, Some(-3966708), None), (None, Some(182), Some(false), Some(302042), Some(511325), None), (Some(-16174730), None, None, None, Some(1078102), Some(51559)), (Some(-137496847), Some(38), Some(false), Some(392306), Some(2024764), None), (Some(1577455994), Some(210), None, Some(-672674), Some(-7249467), None), (Some(-2100233498), None, Some(false), None, None, None), (None, Some(188), None, Some(357887), Some(6492494), None), (Some(594889019), None, Some(false), None, Some(8008460), None), (Some(811896794), Some(58), Some(true), None, Some(-1450482), Some(16005)), (None, Some(16), None, None, Some(9346320), None), (Some(824363284), None, None, Some(248370), None, Some(7623)), (Some(-1384754141), Some(250), Some(true), None, Some(4059860), Some(6786)), (Some(-1480691769), None, Some(true), Some(-380821), None, Some(39307)), (Some(-2040183219), None, Some(false), None, Some(8321900), None), (None, Some(39), Some(true), Some(-485311), Some(-5092707), None), (Some(-147131668), Some(90), Some(false), Some(-411251), Some(-3904869), None), (Some(1502848868), None, None, Some(331627), Some(572339), None), (Some(1772874660), Some(28), Some(false), Some(-831682), Some(-9650168), Some(20750)), (Some(-1712040190), None, None, Some(162835), Some(-1218534), Some(46764)), (None, None, None, Some(-42295), Some(8233423), Some(17591)), (None, None, None, Some(319155), None, None), (Some(-1735527628), None, Some(true), None, Some(7140349), Some(16239)), (None, Some(52), None, Some(97790), Some(4165296), None), (None, None, None, None, None, Some(13761)), (None, None, None, Some(240244), Some(5099472), Some(7169)), (None, Some(202), None, None, Some(-7790239), None), (Some(-1421934260), Some(2), Some(true), None, None, None), (None, None, Some(false), None, Some(7764854), None), (Some(-691984894), None, None, None, Some(-6752878), Some(49099)), (Some(-1008191781), None, None, Some(-795287), None, None), (None, Some(219), None, None, None, Some(29771)), (None, Some(178), None, None, None, Some(20964)), (Some(88357351), Some(200), Some(false), Some(211938), None, Some(6230)), (Some(1846707939), Some(123), None, Some(-801383), None, None), (None, None, None, Some(-599633), Some(-9018192), None), (Some(-711567669), None, None, None, None, Some(59360)), (None, Some(52), None, None, Some(3857788), None), (None, None, None, None, Some(8943649), None), (None, None, Some(true), None, None, Some(59388)), (None, None, None, None, Some(5750626), Some(24399)), (None, None, Some(false), Some(243719), None, None), (Some(1915701682), Some(59), None, Some(-869658), None, None), (Some(2134504502), Some(240), None, Some(-131127), None, None), (None, None, None, None, Some(-3092201), Some(20795)), (Some(-1888404450), Some(72), None, Some(803474), None, Some(24908)), (None, None, Some(true), Some(575778), Some(-9252649), None), (Some(-469593226), Some(151), None, None, None, Some(60823)), (None, None, Some(false), None, None, None), (None, None, None, Some(803126), None, Some(3661)), (None, Some(91), Some(true), None, Some(-4495906), Some(10517)), (Some(-1417511668), None, None, Some(481494), None, None), (Some(753944411), None, None, None, Some(2118804), Some(41932)), (None, Some(15), None, Some(-123137), Some(3245243), Some(3938)), (None, None, None, None, None, Some(42195)), (None, Some(243), None, None, None, None), (None, None, Some(false), None, None, None), (None, Some(39), Some(true), None, Some(1829355), None), (None, None, Some(false), None, Some(3720029), None), (None, Some(230), Some(true), None, None, None), (Some(1779834709), None, None, Some(-881907), None, None), (Some(-1933209919), None, None, Some(-450021), Some(-4745738), Some(2322)), (Some(-1986302337), None, None, None, Some(-8754487), Some(33798)), (None, None, Some(false), Some(802716), None, Some(28215)), (Some(1318445768), Some(111), None, None, Some(8330855), Some(34020)), (None, None, None, None, Some(7299238), None), (Some(1554204544), None, Some(true), Some(883052), Some(2965751), None), (Some(218112195), None, None, None, None, None), (None, Some(199), Some(false), Some(576719), Some(2552907), Some(7883)), (Some(1198351396), Some(99), Some(true), Some(768593), Some(-1433247), Some(36420)), (Some(-1305915407), Some(186), None, None, None, None), (Some(756495055), Some(52), None, Some(353947), Some(-8957248), None), (Some(-2072341232), None, Some(false), Some(-573346), None, Some(31814)), (Some(1767591008), Some(63), None, None, None, None), (Some(496226465), None, Some(false), None, None, Some(45394)), (None, None, Some(true), None, Some(-8325919), Some(28501)), (None, Some(153), None, Some(20415), None, Some(11084)), (None, Some(244), None, None, None, None), (Some(-381852620), None, Some(false), None, None, Some(26585)), (Some(-827093163), Some(104), None, Some(-605065), Some(-304368), None), (None, None, Some(false), Some(276181), Some(-3437177), None), (None, None, Some(true), None, Some(6182406), None), (None, None, Some(true), None, None, Some(20246)), (None, None, None, None, Some(-4638022), None), (None, Some(79), None, None, None, None), (None, Some(182), Some(false), Some(42054), Some(7597566), Some(3349)), (None, None, Some(false), None, None, Some(18378)), (Some(2006344477), None, Some(true), Some(602504), Some(-2819993), None), (Some(-2087149188), None, None, None, None, None), (Some(1128593299), None, None, None, None, None), (Some(2083464778), Some(9), Some(true), Some(574942), Some(5814959), None), (Some(1239626302), None, None, None, Some(-2300192), None), (None, Some(103), Some(true), None, None, None), (None, None, Some(false), None, Some(-9355271), Some(58231)), (Some(1557584309), Some(238), None, Some(-505954), Some(7551676), Some(63191)), (None, None, Some(false), Some(-729277), Some(-9084557), Some(43417)), (Some(-710007689), Some(139), None, Some(-169528), None, Some(28441)), (Some(993559313), None, None, None, Some(198131), Some(47531)), (None, None, Some(false), None, Some(3453673), None), (None, None, None, None, None, None), (None, Some(213), None, None, Some(-5293076), Some(16978)), (Some(648410171), None, None, Some(-741384), Some(-5984742), Some(57241)), (None, None, Some(false), Some(-841733), None, Some(29194)), (Some(909506933), Some(226), Some(true), None, None, None), (Some(-116875909), None, None, Some(911670), Some(-3169897), Some(5011)), (None, None, Some(false), Some(760131), Some(6190334), None), (Some(-1070812104), Some(247), Some(true), Some(841453), None, None), (None, Some(63), None, Some(-400428), Some(2377665), None), (None, Some(156), None, Some(-638989), Some(4202143), Some(41395)), (Some(212759586), None, Some(true), None, Some(-1213502), None), (None, Some(123), Some(true), Some(-291703), None, Some(31641)), (None, Some(108), Some(false), None, None, Some(22814)), (Some(-610371801), None, None, None, None, Some(12711)), (Some(1287473199), Some(237), Some(false), Some(-274909), None, Some(48978)), (None, Some(244), None, Some(-990400), None, None), (None, None, None, Some(-161840), Some(-7875052), Some(31518)), (None, Some(163), Some(false), None, None, None), (None, Some(9), Some(false), None, Some(-9575600), None), (Some(-2005353703), Some(140), None, None, None, None), (Some(-108671103), Some(157), Some(false), None, Some(-4281259), Some(39926)), (Some(-2110598647), Some(195), Some(true), Some(-219477), None, Some(14766)), (None, None, None, None, None, None), (Some(1710360760), None, Some(true), None, None, Some(55442)), (Some(-1549155715), None, Some(true), Some(424047), None, Some(61966)), (None, None, None, Some(-837151), Some(3333215), Some(48628)), (Some(1853186315), None, None, None, None, Some(10249)), (None, Some(80), None, Some(-611194), None, None), (Some(500148374), None, Some(false), None, None, Some(52284)), (Some(469279884), Some(124), None, None, Some(-7596443), None), (None, None, None, Some(-76230), Some(5366825), None), (None, None, None, None, None, None), (None, None, None, Some(162169), None, Some(29576)), (Some(1904905485), None, Some(true), Some(547512), Some(851472), Some(64089)), (None, None, Some(false), None, Some(-2091042), None), (Some(628088141), None, Some(true), Some(-712450), None, None), (None, Some(6), None, None, None, Some(64589)), (None, None, None, Some(417889), None, None), (Some(1277488598), Some(114), Some(false), None, Some(-9183987), None), (None, None, Some(true), None, None, None), (Some(462292490), Some(218), None, Some(138298), None, None), (Some(1577803107), Some(227), Some(true), None, Some(-4375566), Some(60631)), (Some(-424202567), Some(253), Some(false), Some(-615223), Some(88615), None), (Some(324793952), Some(23), Some(false), Some(-501600), None, Some(20578)), (None, None, None, Some(37054), Some(9346808), Some(64998)), (None, None, Some(false), None, Some(-1487261), None), (None, None, None, Some(285634), Some(4495247), None), (Some(-1801832781), None, None, Some(124936), Some(-9318520), None), (None, None, None, Some(-757276), None, Some(6627)), (Some(1664835304), None, Some(true), None, Some(-7329740), Some(16244)), (None, Some(58), None, None, None, None), (Some(-1580101289), Some(195), Some(false), None, None, None), (Some(44487053), Some(254), Some(true), Some(-646400), None, None), (Some(-650982442), Some(238), Some(true), None, None, Some(15874)), (None, None, Some(false), Some(384287), None, Some(19677)), (Some(-975157575), None, Some(false), None, Some(-8177518), Some(28999)), (None, Some(200), Some(true), Some(-788176), Some(5667974), None), (Some(561311888), Some(176), None, None, None, None), (Some(-184391075), None, Some(true), None, Some(-3491056), Some(46647)), (None, None, None, Some(239995), Some(6104438), None), (Some(1264335932), Some(59), None, None, None, None), (None, Some(76), Some(false), None, None, None), (Some(2059824576), Some(56), Some(true), None, None, None), (None, None, Some(true), Some(-775767), Some(2838731), None), (None, Some(131), Some(false), Some(570448), Some(9695283), Some(58690)), (Some(1841249263), None, Some(true), Some(-79550), None, None), (None, Some(47), None, None, Some(2817205), Some(47999)), (None, Some(191), None, Some(-671479), None, None), (Some(251238740), None, None, Some(-955273), None, Some(17340)), (Some(1478570267), None, Some(true), Some(-197088), Some(-3011327), Some(26548)), (None, None, None, None, None, Some(197)), (Some(-1498072431), Some(225), None, Some(415405), Some(7189879), None), (Some(-2057553567), Some(94), None, None, Some(-7250083), Some(27719)), (Some(-464819372), None, None, Some(437281), Some(-6103493), Some(46616)), (None, Some(29), Some(true), None, None, None), (None, None, Some(true), None, Some(727398), Some(38139)), (None, Some(85), Some(false), None, Some(3754853), None), (Some(-1237373757), None, Some(true), Some(964516), Some(836757), None), (None, None, None, Some(632001), None, Some(14731)), (Some(869926062), None, Some(true), None, Some(234202), Some(40323)), (None, Some(103), Some(false), None, Some(4363377), Some(27207)), (None, Some(44), None, Some(-915021), None, Some(10129)), (Some(282238319), None, Some(true), Some(-821382), None, None), (None, None, None, None, Some(7869161), None), (None, Some(72), None, None, Some(1482145), Some(1679)), (Some(-918222000), Some(231), None, None, None, Some(16151)), (None, None, Some(true), None, None, None), (Some(1878121670), Some(185), None, Some(142911), Some(-4129328), None), (Some(580192886), None, Some(true), Some(-106060), None, Some(29618)), (None, Some(96), None, Some(-283206), Some(-9076582), None), (Some(23277787), None, Some(false), None, Some(7584125), Some(19726)), (None, None, Some(true), Some(886332), Some(-8580749), None), (Some(747676790), Some(72), Some(false), Some(200632), Some(-2994280), None), (None, Some(211), Some(true), Some(542219), Some(7080477), Some(31926)), (Some(-1995905594), Some(40), None, Some(459128), None, Some(34820)), (Some(-1592915378), Some(65), None, None, Some(-4180210), None), (Some(1435967193), Some(193), Some(true), None, Some(3327789), None), (Some(1498289605), Some(54), None, Some(770156), Some(-6831490), None), (Some(-1390256701), Some(71), None, Some(443796), None, None), (Some(1442253227), None, Some(true), Some(-653723), None, None), (Some(1937820566), None, None, None, None, Some(51894)), (Some(-129591987), None, None, Some(506966), None, Some(22348)), (Some(-2106430774), None, None, None, None, Some(12810)), (None, None, None, Some(475877), None, None), (Some(1369632027), None, None, Some(437339), None, Some(27528)), (Some(1973040074), None, None, None, Some(8106130), Some(1885)), (Some(-59210827), None, Some(true), Some(291614), Some(-6448130), Some(58634)), (None, None, None, Some(-198029), Some(-5122821), None), (Some(1577819284), Some(196), Some(false), None, None, Some(19503)), (Some(1233904242), Some(72), Some(true), Some(-865463), None, None), (Some(-1711660106), None, Some(false), None, None, None), (None, None, Some(false), Some(653812), Some(6213545), Some(42079)), (Some(1635716265), None, Some(true), Some(207344), Some(1134402), Some(37202)), (Some(-1646005399), Some(148), Some(false), Some(-112166), None, Some(21334)), (None, None, Some(true), Some(-731526), Some(8436117), Some(51300)), (None, None, None, Some(-89770), None, None), (None, Some(40), Some(true), Some(-590804), None, Some(53838)), (Some(-401065248), None, None, None, None, None), (Some(1350245913), None, None, None, None, None), (Some(-268195896), None, None, Some(-155056), None, Some(26351)), (Some(1633786176), None, Some(true), None, Some(1446905), Some(62230)), (Some(-1629888066), Some(216), Some(false), None, Some(-328481), None), (Some(1862628911), None, Some(true), Some(541866), Some(-979306), None), (None, None, Some(false), None, Some(7442167), None), (Some(1348200541), Some(235), None, None, Some(-5370427), Some(65082)), (Some(1946401324), Some(25), None, Some(170993), None, Some(42209)), (None, None, Some(false), None, None, Some(50961)), (None, None, Some(true), None, Some(8762643), None), (Some(1910801460), Some(23), None, Some(633282), None, None), (None, Some(169), None, None, None, None), (None, None, Some(false), Some(569149), Some(3041394), None), (None, Some(14), Some(false), None, Some(-1052337), Some(37715)), (None, Some(71), None, Some(-359101), Some(-98804), None), (None, None, None, Some(769863), Some(7319529), None), (Some(-1121332305), Some(42), None, None, Some(-2034009), Some(4405)), (None, Some(203), Some(false), None, Some(-3766059), None), (Some(360783402), Some(253), None, None, Some(-2068166), Some(3638)), (Some(-1063453699), None, Some(false), Some(324337), None, Some(24306)), (Some(-1907055529), None, Some(false), None, Some(7375473), Some(58019)), (Some(1999062295), None, None, None, None, None), (None, None, None, Some(-930277), Some(7663267), None), (Some(-1368130278), None, None, None, None, None), (Some(-1050856677), None, None, None, None, None), (None, None, Some(false), None, Some(-9219076), None), (None, Some(143), Some(true), None, Some(-1112228), None), (None, Some(134), Some(false), None, None, Some(53794)), (Some(1826497754), Some(119), None, None, Some(-3136306), Some(23551)), (Some(-1280005059), Some(117), Some(false), Some(-561566), Some(-8718660), None), (Some(-1623457682), None, Some(false), Some(-964519), None, None), (Some(-1194595891), Some(184), Some(true), Some(-86530), None, None), (Some(779545741), None, Some(false), Some(-794623), None, None), (None, Some(162), None, Some(236563), None, Some(2633)), (None, None, Some(true), None, None, None), (Some(1985996847), Some(14), Some(false), None, None, None), (None, Some(210), None, Some(-653829), None, None), (Some(1090112969), Some(189), None, Some(-786724), Some(-6064158), None), (Some(-319659457), Some(79), None, Some(-541900), Some(-85131), Some(37867)), (None, Some(26), Some(true), Some(349820), None, None), (Some(-1943050525), Some(94), None, Some(-917647), None, Some(3869)), (Some(1392219002), Some(80), None, None, Some(-4987940), Some(59541)), (Some(1320143164), None, Some(true), Some(-516620), None, Some(34146)), (None, None, Some(true), Some(-331493), None, None), (Some(1826286234), Some(79), None, None, Some(-3285378), None), (None, None, None, None, Some(-5141088), Some(19980)), (Some(926036581), Some(251), None, None, None, None), (Some(1661184939), None, Some(true), None, None, Some(17096)), (None, Some(126), Some(true), Some(-482566), None, Some(36893)), (None, None, None, None, None, Some(58932)), (Some(-1477784188), Some(232), Some(true), Some(-500082), None, None), (Some(561224682), None, None, None, Some(9484449), Some(25751)), (None, None, None, Some(684696), Some(-4606753), Some(11310)), (None, Some(191), Some(false), Some(-422778), Some(-3149129), Some(41756)), (None, Some(216), Some(true), None, None, None), (Some(-2022773977), Some(242), None, Some(-948719), None, None), (Some(500839964), Some(82), None, Some(130497), None, None), (Some(939124771), None, None, None, None, Some(53185)), (None, Some(82), None, None, Some(5511154), Some(14445)), (None, None, None, Some(-638298), Some(7322990), None), (Some(502400376), Some(22), None, Some(-923449), None, Some(61971)), (Some(1368804904), None, None, None, None, Some(8937)), (Some(-1741584583), None, None, Some(699444), Some(3185275), Some(36575)), (Some(1663786134), None, Some(true), None, Some(-3792227), Some(59730)), (Some(-2084032859), None, None, None, None, None), (Some(609995254), None, Some(false), Some(748081), None, Some(16026)), (None, None, None, Some(151300), Some(-490295), None), (Some(224872427), None, None, Some(-166109), None, Some(41954)), (None, None, Some(false), Some(685612), None, Some(13696)), (None, None, None, Some(674016), None, None), (Some(-1655838165), Some(142), Some(false), None, None, Some(39008)), (None, None, None, Some(-769165), None, None), (None, Some(39), Some(false), None, None, None), (Some(1775191960), Some(72), Some(true), Some(661258), Some(1056979), None), (Some(-391529371), Some(211), Some(true), None, Some(1840743), Some(53724)), (None, None, Some(true), Some(955149), None, Some(54904)), (Some(-1649512415), Some(248), None, Some(594207), Some(2723605), Some(12474)), (Some(-23821478), None, None, None, Some(-752578), None), (None, Some(6), None, None, None, Some(36026)), (None, None, Some(true), None, None, None), (Some(1453206010), None, Some(false), None, None, Some(39433)), (None, Some(116), Some(true), None, Some(1984215), None), (Some(67284461), Some(221), None, None, Some(5954894), None), (None, Some(76), Some(true), Some(725549), Some(-3260504), Some(14585)), (None, Some(207), Some(false), None, None, Some(48143)), (Some(-496887370), None, Some(true), None, None, Some(23416)), (Some(-1680019955), None, Some(true), Some(-449147), None, None), (None, Some(159), Some(false), None, None, None), (Some(-61604272), None, None, None, Some(-9672868), None), (None, Some(125), None, None, Some(-8029205), Some(532)), (Some(1485377449), None, None, None, None, None), (None, Some(183), Some(true), None, Some(-2187233), Some(14015)), (Some(-1947738920), None, Some(false), Some(603661), None, Some(63907)), (None, None, None, None, None, Some(39272)), (Some(406900331), Some(143), None, Some(-96299), Some(-6993027), None), (Some(1730840834), None, None, None, Some(-8962528), Some(29468)), (Some(1924924268), None, Some(true), Some(-29642), None, Some(3974)), (None, None, Some(true), None, None, None), (Some(1965599571), Some(119), Some(true), Some(601841), Some(-8482132), None), (Some(1183904957), None, Some(true), None, Some(-1305872), None), (Some(-1115770164), None, None, Some(-677105), None, None), (None, None, None, Some(81673), None, Some(49434)), (None, None, Some(false), None, None, None), (None, None, Some(true), None, Some(3736738), Some(3637)), (Some(-231096336), Some(182), None, None, None, None), (Some(-1857839040), None, None, Some(-557597), None, None), (None, Some(70), None, Some(877543), Some(-9476905), None), (None, Some(26), Some(false), None, Some(-5171765), Some(60873)), (Some(-691148737), Some(123), None, Some(339790), None, None), (Some(1728680771), None, Some(true), Some(-443201), Some(-7421985), Some(30963)), (None, None, Some(false), Some(-217368), Some(3650741), None), (None, None, None, Some(7533), Some(5698078), None), (Some(-2119451367), Some(198), None, None, Some(-7565803), None), (None, None, Some(false), Some(-428838), Some(-8218105), Some(6975)), (None, Some(200), None, None, None, Some(17378)), (None, Some(76), None, Some(-696106), None, None), (None, None, None, Some(768626), None, None), (None, Some(147), Some(true), Some(-778656), None, None), (Some(-273522755), Some(237), Some(true), None, Some(-5340994), None), (Some(693792697), Some(56), None, None, None, None), (None, None, None, None, Some(-8163899), None), (Some(-1900579521), Some(174), None, Some(710157), None, Some(64903)), (Some(-484968624), None, Some(true), Some(-579897), Some(-7771621), None), (None, Some(36), Some(true), Some(945220), None, None), (None, None, Some(true), None, None, None), (Some(1162637058), None, Some(true), Some(921949), None, Some(64360)), (Some(-817549691), Some(241), None, Some(-419264), Some(-4694367), None), (None, None, None, None, Some(-4137580), Some(5785)), (None, Some(18), None, Some(38096), Some(-5388330), Some(33800)), (Some(500566036), Some(233), None, Some(548496), None, Some(57615)), (Some(-741787202), Some(191), Some(false), None, None, Some(17628)), (None, None, None, None, Some(-2767383), Some(38259)), (Some(-1512833581), None, None, None, Some(8150719), Some(65028)), (Some(-571267976), None, Some(true), None, Some(-7509580), Some(50315)), (None, Some(203), None, None, None, Some(28840)), (Some(-188356428), None, Some(true), None, None, Some(23983)), (None, None, Some(true), None, Some(6991671), None), (Some(-1750585862), None, Some(false), None, None, Some(29871)), (Some(1542094417), Some(82), Some(false), Some(147774), None, None), (None, Some(19), None, Some(710332), None, None), (Some(-1236254167), None, None, Some(728580), None, Some(5503)), (None, Some(234), None, Some(81565), None, Some(38294)), (Some(-491908248), Some(69), None, Some(482234), None, None), (None, Some(116), Some(true), None, None, None), (Some(1360069983), Some(148), None, Some(290226), None, None), (Some(612958310), Some(145), None, Some(856423), None, None), (None, Some(234), Some(false), Some(104752), None, None), (Some(682662449), None, Some(true), None, None, Some(43712)), (None, None, None, Some(-259992), None, None), (None, None, Some(true), Some(616223), Some(-3200542), Some(31675)), (Some(-638763087), Some(230), Some(false), Some(-60109), None, None), (None, Some(146), None, None, None, None), (Some(2010587586), Some(165), None, None, None, None), (Some(207757978), Some(229), Some(false), Some(244146), Some(-7738677), Some(19165)), (Some(278868506), None, None, None, None, None), (None, Some(244), None, Some(-149396), Some(7414714), Some(51704)), (Some(1986887037), None, Some(false), None, None, None), (None, None, Some(true), None, None, Some(62987)), (None, Some(53), Some(true), Some(-511007), None, None), (Some(435711073), Some(92), Some(true), Some(135752), Some(6739759), None), (Some(1116358319), None, Some(true), Some(-664995), Some(6965316), Some(15335)), (Some(-1159894215), None, None, None, Some(-6534069), Some(8328)), (None, None, Some(false), None, Some(5558176), Some(60096)), (Some(-417152793), Some(140), Some(true), None, None, None), (None, None, Some(true), None, Some(-9221550), Some(42972)), (None, None, Some(true), None, Some(930753), None), (Some(147818444), Some(149), None, Some(-443810), None, None), (Some(703280140), Some(42), Some(false), None, Some(-1776294), Some(53453)), (None, None, Some(false), Some(-45546), None, None), (Some(-1709379412), None, Some(false), Some(-748072), Some(5139751), None), (None, None, None, None, Some(6002912), Some(18087)), (Some(-79633384), Some(129), None, Some(-389355), None, None), (None, Some(125), Some(false), Some(-164419), None, Some(13366)), (None, None, Some(false), Some(-193517), Some(-4974687), None), (Some(-623645743), Some(120), None, Some(-884235), Some(3316089), Some(36770)), (None, None, Some(true), None, Some(88348), Some(7568)), (Some(378422522), None, None, Some(262977), None, None), (None, None, Some(false), None, Some(2144872), Some(59174)), (Some(-439965276), None, None, None, None, Some(34405)), (None, None, Some(false), None, None, None), (None, None, None, None, None, Some(64876)), (None, None, None, Some(465261), None, None), (Some(-1699924791), Some(192), Some(false), Some(62394), None, Some(44548)), (None, None, None, None, Some(-1733118), Some(45298)), (Some(1735174961), Some(89), None, None, Some(-597837), Some(51535)), (Some(-664518539), None, Some(true), Some(472360), Some(1057784), Some(43958)), (None, Some(107), Some(false), Some(334307), Some(280827), Some(28988)), (Some(-1034242801), Some(165), Some(true), Some(-832450), None, Some(35922)), (Some(-1588746798), Some(126), None, Some(-253781), None, None), (None, None, None, Some(949687), None, Some(13645)), (None, Some(195), Some(false), Some(-519025), Some(9238148), None), (Some(1295010758), None, Some(true), None, Some(-1997284), None), (Some(-168202548), Some(219), Some(true), None, None, None), (Some(2065154047), Some(35), None, Some(558425), Some(3862504), Some(12128)), (None, None, None, None, Some(7226872), Some(14693)), (Some(-1180061458), Some(16), Some(false), None, Some(6142248), None), (None, None, Some(true), None, Some(-5063366), None), (None, None, Some(true), Some(347726), None, Some(58611)), (None, None, Some(true), Some(943865), None, None), (Some(-1226460762), Some(37), Some(true), Some(167948), None, Some(2116)), (None, Some(10), Some(false), None, Some(-462207), Some(8646)), (Some(77599602), None, Some(false), None, Some(-2435485), None), (Some(278285283), None, Some(false), None, Some(-6213977), None), (None, None, Some(false), Some(652967), Some(-2601382), Some(59464)), (None, Some(217), Some(true), Some(-914601), Some(542435), None), (None, Some(68), None, None, Some(1267658), Some(6497)), (Some(-1586039560), None, None, Some(344086), None, Some(13935)), (None, None, None, Some(-651407), Some(4601235), None), (None, None, None, Some(452285), None, Some(53915)), (Some(543703779), None, None, None, Some(5694544), Some(55331)), (Some(-1583108998), None, Some(false), None, None, None), (Some(288864774), Some(210), Some(true), None, Some(3368928), Some(45149)), (Some(117814994), None, None, None, Some(-4990653), None), (None, Some(142), Some(false), Some(-107678), None, Some(49839)), (Some(-1332948159), Some(238), Some(true), Some(200533), Some(3926851), Some(15066)), (Some(-1272022099), Some(19), Some(true), None, Some(6711559), None), (Some(-1325587998), None, None, None, None, Some(11353)), (Some(923568106), None, None, None, None, None), (Some(1176509442), None, None, Some(-62183), None, Some(11576)), (None, None, Some(false), None, Some(3534468), Some(20225)), (Some(-839646062), Some(172), Some(false), Some(376581), Some(-4926537), Some(9349)), (Some(364014035), None, Some(true), Some(202356), Some(7449579), None), (None, Some(222), None, None, Some(-7908611), Some(44193)), (None, Some(45), None, Some(713807), Some(5529949), Some(58107)), (Some(-1652315083), None, Some(false), None, None, Some(49619)), (Some(-573903268), Some(194), None, Some(-894642), None, Some(58240)), (Some(455355331), Some(23), None, Some(-245024), Some(-7049387), Some(58348)), (None, None, Some(true), Some(456689), Some(2446506), None), (Some(-1969581754), Some(1), None, Some(-158404), None, Some(50563)), (Some(-777055892), Some(22), None, Some(693623), None, None), (Some(-1780162476), Some(35), Some(false), Some(108553), Some(-9867913), None), (Some(2068285736), Some(67), Some(true), None, Some(2245063), None), (None, Some(230), Some(false), Some(-880958), Some(8267244), None), (Some(-77297013), None, Some(true), Some(-249210), None, Some(12997)), (Some(-1905174938), Some(114), None, None, Some(1193842), Some(13571)), (Some(-386428768), Some(207), Some(true), None, Some(3905542), None), (None, Some(28), None, None, Some(6835144), Some(7055)), (None, Some(51), None, Some(-910011), None, None), (Some(-128138636), None, Some(true), Some(-191162), Some(9116348), None), (Some(1899831764), Some(87), None, Some(-800250), None, None), (None, Some(204), None, Some(-488399), Some(3860684), None), (None, None, Some(true), Some(876697), None, Some(17386)), (None, Some(160), Some(false), None, None, Some(25145)), (Some(1457033840), Some(199), None, Some(841862), None, Some(765)), (Some(1178082912), Some(196), Some(false), Some(36479), None, Some(10760)), (None, Some(229), None, None, Some(2535717), Some(24770)), (Some(926182460), Some(42), Some(false), Some(506328), None, None), (Some(1511941039), Some(61), Some(false), None, None, Some(9174)), (None, None, Some(true), Some(-165693), None, Some(13528)), (None, Some(13), Some(false), None, Some(9786066), None), (None, Some(108), None, None, Some(-1383336), Some(59993)), (Some(-1370643112), None, None, None, Some(5959602), Some(28819)), (Some(888549987), None, Some(true), Some(960405), Some(7039792), Some(13790)), (None, None, Some(true), Some(679779), None, None), (Some(-147234753), None, Some(true), None, Some(-9962331), None), (None, Some(251), Some(false), None, Some(-6449772), Some(56021)), (None, Some(110), Some(false), Some(-822349), Some(-5646054), Some(60370)), (Some(309971697), Some(14), Some(false), Some(-885830), Some(9703175), Some(58222)), (Some(2118181873), None, None, Some(407951), None, None), (None, Some(133), Some(true), Some(529595), None, Some(11369)), (Some(988684745), Some(7), None, Some(976013), Some(4377684), None), (Some(-666497335), None, None, None, None, None), (None, None, Some(true), None, Some(-949486), None), (None, None, None, Some(-550624), None, None), (Some(-720402381), Some(83), None, None, None, Some(20044)), (Some(-1996763891), Some(181), Some(false), Some(269895), None, None), (Some(-789883469), Some(129), None, Some(-577760), Some(8034658), Some(31286)), (Some(-1148927485), Some(198), Some(true), Some(425231), Some(-506948), None), (Some(-1217708379), Some(33), Some(true), Some(70687), Some(9202729), None), (None, None, Some(true), Some(275662), Some(-2532416), None), (None, Some(77), Some(false), None, Some(525528), None), (Some(1389015222), Some(228), None, None, None, Some(46531)), (None, None, None, Some(-341832), Some(-3931308), Some(20191)), (Some(2008715454), Some(36), None, Some(102684), Some(294860), Some(6099)), (None, None, Some(false), Some(540482), None, Some(64969)), (Some(-1585582035), Some(76), Some(true), Some(-463610), Some(5900559), None), (None, None, None, None, None, Some(45231)), (None, Some(217), Some(true), Some(-266469), None, Some(2604)), (None, Some(255), None, Some(-714135), None, Some(64818)), (Some(2025382837), None, Some(true), None, None, Some(62969)), (None, Some(161), None, Some(-375837), None, None), (Some(-2057506822), Some(132), None, None, Some(-6219350), None), (None, None, None, None, None, Some(36135)), (None, Some(254), Some(false), Some(-441270), Some(-8506630), None), (None, Some(122), Some(true), Some(649830), None, Some(48565)), (None, None, Some(false), Some(-587927), Some(-3029981), None), (None, None, None, None, None, None), (Some(-190357458), None, Some(true), None, Some(-5333728), Some(19308)), (None, Some(128), Some(true), Some(-447749), Some(4892637), Some(7808)), (Some(1527513881), Some(114), None, Some(984238), None, None), (None, None, None, Some(196418), Some(-4825048), None), (None, Some(151), None, None, Some(-6175174), None), (Some(-211622107), Some(133), None, Some(338431), None, None), (None, None, None, None, Some(3061405), None), (Some(812051781), None, None, Some(568817), None, None), (None, None, None, Some(490870), None, Some(2993)), (None, Some(111), Some(true), None, Some(-478476), None), (None, Some(35), None, Some(498652), None, None), (Some(1602700970), None, None, None, None, None), (Some(-1320995150), None, None, Some(-968014), None, Some(36433)), (Some(-1035739179), None, Some(false), None, Some(-1599942), None), (Some(53736263), Some(190), Some(false), Some(607837), Some(-3010597), None), (Some(246093897), Some(82), None, None, Some(5248642), Some(19252)), (None, Some(50), None, None, None, Some(15787)), (Some(497511872), Some(26), None, None, Some(-3793853), Some(16900)), (Some(-1674736259), None, Some(false), None, Some(3755814), Some(62617)), (None, None, None, None, None, Some(6458)), (None, Some(3), Some(true), None, None, Some(58840)), (None, None, None, Some(-487012), None, Some(31880)), (None, None, Some(true), None, None, Some(36459)), (Some(2009417732), None, None, Some(541460), Some(8285729), Some(35330)), (Some(1171960018), Some(14), None, Some(-520960), None, Some(8294)), (None, Some(216), None, Some(-140245), None, Some(47669)), (Some(74252236), None, None, Some(-857461), None, None), (Some(-1826599372), Some(253), Some(false), None, None, None), (Some(1187706052), Some(224), Some(false), Some(-563558), None, Some(9984)), (Some(1899460038), Some(125), None, None, Some(4430019), Some(16141)), (None, None, Some(true), Some(-826032), Some(8486953), Some(11545)), (Some(-208918232), None, Some(false), None, None, None), (None, None, None, Some(-78406), None, None), (None, Some(115), None, None, None, None), (None, None, Some(false), None, None, Some(7422)), (Some(1744891829), None, None, Some(277905), Some(-7856250), None), (Some(1630932553), Some(141), None, Some(-226311), None, Some(65023)), (None, Some(68), Some(false), Some(-649199), None, Some(44428)), (None, None, None, None, Some(6387623), None), (None, Some(137), Some(false), Some(289719), None, None), (None, Some(165), None, None, Some(-9346262), None), (None, Some(209), None, None, None, Some(47620)), (None, Some(184), Some(true), None, None, Some(48820)), (Some(-655334458), Some(186), None, None, Some(-5657769), None), (None, Some(47), None, Some(-495499), Some(-6290698), Some(22939)), (None, Some(137), None, Some(-125258), None, None), (None, None, Some(true), Some(805754), Some(-4326231), None), (Some(-1306245244), Some(170), None, None, Some(-1346174), None), (Some(-1586436746), Some(50), Some(true), Some(768655), Some(-3594609), None), (None, None, None, None, Some(6295193), None), (None, None, None, None, None, Some(37290)), (None, Some(68), None, Some(-520184), None, Some(63262)), (Some(1727926796), Some(204), None, None, Some(-1113190), None), (None, Some(115), None, Some(-245439), None, Some(36406)), (Some(-1542272231), Some(6), Some(true), Some(-109759), None, None), (Some(1437689223), Some(25), Some(false), Some(-572925), None, None), (Some(-1637685), Some(143), None, Some(265817), None, Some(55758)), (Some(-1808211908), Some(164), None, None, Some(-79779), Some(35227)), (None, Some(49), Some(false), None, None, Some(45796)), (Some(-715513922), Some(246), Some(true), Some(-497283), None, Some(15910)), (None, None, None, Some(677363), None, None), (None, None, Some(false), None, Some(4570944), Some(16127)), (Some(867821955), Some(57), Some(true), None, Some(7498291), Some(36507)), (None, None, None, None, Some(-4931119), Some(60138)), (Some(818708584), None, Some(false), None, Some(464290), None), (None, None, Some(false), Some(924218), None, None), (None, Some(135), Some(false), None, Some(2329124), None), (Some(1625847195), None, Some(true), None, None, None), (None, None, Some(true), None, None, None), (None, None, None, Some(181194), None, Some(61431)), (Some(1094163652), None, None, None, Some(-142389), None), (None, Some(2), None, None, Some(4960983), Some(5385)), (None, None, Some(true), Some(-487845), None, Some(25726)), (None, None, None, Some(-908250), Some(-8688983), None), (Some(1496289413), Some(212), None, Some(781708), Some(2094566), Some(61484)), (Some(1052498692), None, Some(true), Some(278847), None, Some(5273)), (None, None, None, Some(-868569), None, None), (Some(-1369054484), None, Some(true), Some(-816120), Some(3029159), None), (None, None, None, Some(691631), Some(-7402409), None), (Some(32165323), None, None, None, None, None), (None, Some(125), None, None, None, Some(36672)), (None, None, Some(false), Some(297287), None, Some(42705)), (Some(-175031268), Some(109), None, Some(-569762), Some(-3416426), Some(13390)), (Some(1775897212), Some(241), None, None, Some(-9907854), None), (Some(-93922713), None, Some(true), Some(472826), Some(-8418413), Some(29158)), (Some(452282969), None, None, None, Some(4831469), Some(25962)), (Some(-597599801), Some(167), Some(true), Some(-541316), None, Some(7133)), (Some(-456798068), Some(105), None, Some(-945491), Some(-443694), Some(4217)), (Some(-700733698), Some(248), Some(true), Some(-248046), Some(-7525395), Some(32826)), (Some(2016259078), None, None, Some(522030), None, Some(41687)), (Some(426103175), Some(41), None, Some(-101614), None, Some(29972)), (Some(-99507827), Some(142), None, None, None, None), (Some(1056473731), None, None, Some(-35744), None, Some(60847)), (None, None, Some(false), None, None, Some(54488)), (None, None, None, Some(578380), Some(4894242), None), (None, Some(0), None, Some(843367), Some(-2698079), None), (Some(1770192384), None, None, Some(-660121), None, None), (Some(1318470940), Some(153), Some(true), Some(-645273), Some(-8151920), Some(30130)), (None, Some(142), None, None, None, Some(60293)), (Some(1528212441), Some(85), Some(true), None, Some(-2085514), Some(48960)), (None, None, Some(true), Some(31062), Some(-2002803), Some(45627)), (Some(-1332868473), None, None, None, None, None), (None, Some(213), None, Some(473211), Some(-6314245), Some(17619)), (Some(687943761), None, None, Some(410898), None, None), (None, None, Some(true), None, None, None), (Some(-1619802908), None, Some(true), Some(-196821), None, None), (Some(1774678690), Some(137), Some(true), None, Some(460701), None), (None, None, None, None, Some(-7003519), Some(63986)), (Some(2110544751), None, Some(false), Some(-166593), Some(-2892245), None), (None, None, None, None, Some(-1487025), Some(53949)), (Some(580345504), Some(201), Some(true), Some(774980), None, Some(44615)), (Some(1230523055), Some(216), Some(true), Some(178777), Some(6300595), None), (None, None, Some(false), None, Some(-4443470), Some(29241)), (Some(-1980952569), None, None, Some(-228734), None, Some(10232)), (Some(-384763833), None, None, None, Some(7874920), None), (Some(1006154169), Some(175), None, Some(-296065), Some(-9694007), Some(10581)), (Some(752405444), None, None, Some(-522025), None, Some(8655)), (None, Some(32), None, Some(-231621), Some(-9053358), Some(7339)), (None, None, None, None, None, None), (None, None, None, None, None, None), (Some(651456802), Some(227), None, None, None, None), (None, Some(136), Some(true), None, Some(3580634), Some(13015)), (None, None, None, None, None, Some(45118)), (Some(-1060889629), Some(103), None, None, None, None), (Some(686479330), Some(134), None, None, None, Some(53410)), (None, None, Some(true), None, Some(4681656), Some(35820)), (Some(2039233495), Some(64), None, None, None, None), (None, Some(79), None, None, None, Some(19930))], keys = 248, nkeys = 3, batch = 750, slots = 2, mode = 1, limit = 18, two = false, tight = true diff --git a/crates/krishiv-exec/tests/planner/folding.rs b/crates/krishiv-exec/tests/planner/folding.rs new file mode 100644 index 000000000..af0a8b56d --- /dev/null +++ b/crates/krishiv-exec/tests/planner/folding.rs @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: Apache-2.0 +//! Foldable expressions end to end, as Spark 4.2.0 answers them: a `LIMIT` +//! over casts, dates and datetime calls returns rows (the values the +//! analyzer folds, or what the downstream folders reduce to a literal); +//! the legacy `date_add` day count reads through a cast to string; `NaN` +//! and `-0.0` keep their values; `AND`/`OR` short-circuit like Spark's +//! Kleene logic. Each case runs with ANSI on and off. + +use std::sync::Arc; + +use arrow_array::{ArrayRef, Int32Array, RecordBatch}; +use arrow_schema::{DataType as ArrowType, Field, Schema}; +use krishiv_common::config::Config; +use krishiv_common::error::{ErrorClass, KrishivError}; +use krishiv_plan::analyzer::testing::{block_on, context}; +use krishiv_plan::analyzer::{ + Analyzer as _, DefaultAnalyzer, MemoryCatalog, ResolutionConf, TableColumn, +}; +use krishiv_plan::{Plan, SourceId}; + +use krishiv_exec::planner::{ + DefaultPlanner, MemoryTable, MemoryTables, PhysicalPlanner, PlanningContext, +}; + +use super::tpch::render; +use super::{Runnable, run}; + +struct Db { + ctx: krishiv_plan::analyzer::AnalysisContext, + tables: Arc, + config: Arc, +} + +fn db(ansi: bool) -> Db { + let schema = Arc::new(Schema::new(vec![Field::new("a", ArrowType::Int32, true)])); + let a: ArrayRef = Arc::new(Int32Array::from_iter((0..10).map(Some))); + let batches = vec![krishiv_types::batch::Batch::new( + RecordBatch::try_new(Arc::clone(&schema), vec![a]).unwrap(), + )]; + let columns = schema + .fields() + .iter() + .map(|f| TableColumn { + name: f.name().clone(), + data_type: krishiv_types::DataType::from_arrow(f.data_type()).unwrap(), + nullable: f.is_nullable(), + }) + .collect(); + let catalog = MemoryCatalog::new("spark_catalog").with_table(&["default"], "t", columns, None); + let tables = MemoryTables::new().with_table( + &["spark_catalog", "default", "t"], + Arc::new(MemoryTable::new(schema, batches)), + ); + let flag = if ansi { "true" } else { "false" }; + let mut config = Config::new(); + config.set("spark.sql.ansi.enabled", flag).unwrap(); + let conf = ResolutionConf::from_conf(|k| (k == "spark.sql.ansi.enabled").then_some(flag)); + Db { + ctx: context(catalog, conf), + tables: Arc::new(tables), + config: Arc::new(config), + } +} + +/// What a query returned: its rows rendered as Spark renders them, or the +/// error class. +type Outcome = Result, ErrorClass>; + +impl Db { + fn analyze(&self, sql: &str) -> Plan { + let plan = + krishiv_sql::parse_and_lower(sql, &krishiv_sql::ParserOptions::default(), SourceId(0)) + .unwrap_or_else(|e| panic!("{sql}: {e}")); + block_on(DefaultAnalyzer.analyze(&plan, &self.ctx)) + .unwrap_or_else(|e| panic!("{sql}: {e}")) + .plan + } + + fn execute(&self, plan: &Plan) -> Outcome { + let cx = PlanningContext::new(Arc::clone(&self.tables) as _, Arc::clone(&self.config)); + let physical = DefaultPlanner + .plan(plan, &cx) + .map_err(|e: KrishivError| e.error_class())?; + let runnable = Runnable::new(physical, Arc::clone(&self.tables) as _); + let batches = run(&runnable).map_err(|e| e.error_class())?; + let mut rows = Vec::new(); + for b in &batches { + for r in 0..b.num_rows() { + let cells: Vec = + b.columns().iter().map(|c| render(c.as_ref(), r)).collect(); + rows.push(cells.join("|")); + } + } + Ok(rows) + } + + fn rows(&self, sql: &str) -> Outcome { + let plan = self.analyze(sql); + let optimized = krishiv_optimizer::optimize(&plan).unwrap(); + self.execute(&optimized) + } +} + +fn digits(n: i32) -> Vec { + (0..n).map(|v| v.to_string()).collect() +} + +/// `LIMIT` over a foldable expression returns rows: the analyzer folds a +/// cast to string, a cast to date, and the datetime calls over them. +#[test] +fn limits_over_foldable_expressions_return_rows() { + for ansi in [true, false] { + let db = db(ansi); + for (sql, want) in [ + ( + "SELECT a FROM t LIMIT length(CAST(12 AS STRING))", + digits(2), + ), + ( + "SELECT a FROM t LIMIT year(DATE'2024-01-01') - 2020", + digits(4), + ), + ( + "SELECT a FROM t LIMIT year(CAST('2024-01-01' AS DATE)) - 2020", + digits(4), + ), + ( + "SELECT a FROM t LIMIT length(concat('a', CAST(1 AS STRING)))", + digits(2), + ), + ] { + assert_eq!(db.rows(sql), Ok(want), "{sql} (ansi {ansi})"); + } + } +} + +/// A foldable `LIMIT` the analyzer folder cannot evaluate is not an +/// error: it passes through, and what the downstream folders reduce runs. +/// (`IN` folds in the optimizer but not in the analyzer folder.) +#[test] +fn an_unevaluated_foldable_limit_passes_through() { + for ansi in [true, false] { + let db = db(ansi); + assert_eq!( + db.rows("SELECT a FROM t LIMIT CASE WHEN 1 IN (1, 2) THEN 2 ELSE 3 END"), + Ok(digits(2)), + "(ansi {ansi})" + ); + } +} + +/// The legacy day count reads through a cast to string, as Spark's +/// `StringLiteralCoercion` folds it. +#[test] +fn legacy_day_counts_read_through_casts() { + for ansi in [true, false] { + let db = db(ansi); + assert_eq!( + db.rows("SELECT date_add(DATE'2024-01-01', CAST(1 AS STRING))"), + Ok(vec!["2024-01-02".to_owned()]), + "(ansi {ansi})" + ); + } +} + +/// `NaN` and `-0.0` keep their values through casts and comparisons. +#[test] +fn nan_and_signed_zero_keep_their_values() { + for ansi in [true, false] { + let db = db(ansi); + for (sql, want) in [ + ("SELECT CAST('NaN' AS DOUBLE)", vec!["nan"]), + ("SELECT CAST('-0.0' AS DOUBLE)", vec!["-0.0"]), + ("SELECT CAST('Infinity' AS DOUBLE)", vec!["inf"]), + ("SELECT 0.0 = -0.0", vec!["true"]), + ] { + let want: Vec = want.into_iter().map(str::to_owned).collect(); + assert_eq!(db.rows(sql), Ok(want), "{sql} (ansi {ansi})"); + } + } +} + +/// `AND`/`OR` short-circuit as Spark's Kleene logic does: `false AND ...` +/// never raises, while `NULL AND ...` raises what the right side raises. +#[test] +fn and_or_short_circuit() { + for ansi in [true, false] { + let db = db(ansi); + assert_eq!( + db.rows("SELECT false AND 1/0 = 1"), + Ok(vec!["false".to_owned()]), + "(ansi {ansi})" + ); + assert_eq!( + db.rows("SELECT true OR 1/0 = 1"), + Ok(vec!["true".to_owned()]), + "(ansi {ansi})" + ); + } + assert_eq!( + db(true).rows("SELECT NULL AND 1/0 = 1"), + Err(ErrorClass::DivideByZero), + ); + assert_eq!( + db(false).rows("SELECT NULL AND 1/0 = 1"), + Ok(vec!["NULL".to_owned()]), + ); +} diff --git a/crates/krishiv-exec/tests/planner/main.rs b/crates/krishiv-exec/tests/planner/main.rs index fbfe0f376..53d31645b 100644 --- a/crates/krishiv-exec/tests/planner/main.rs +++ b/crates/krishiv-exec/tests/planner/main.rs @@ -11,11 +11,13 @@ )] mod exchanges; +mod folding; mod hints; mod listing; mod physical; mod runtime_filters; mod semantics; +mod sum_rewrite; mod tpch; mod window; mod write; diff --git a/crates/krishiv-exec/tests/planner/sum_rewrite.rs b/crates/krishiv-exec/tests/planner/sum_rewrite.rs new file mode 100644 index 000000000..b73f3f9bc --- /dev/null +++ b/crates/krishiv-exec/tests/planner/sum_rewrite.rs @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: Apache-2.0 +//! `SUM(x + c)` rewritten to `SUM(x) + c * COUNT(x)` by the optimizer: the +//! rows (or the error) of the optimised plan equal those of the plan as +//! analyzed, for generated data with NULLs and the extremes of each type, +//! under ANSI and legacy arithmetic, with and without `GROUP BY`, for +//! constants inside and outside the rewrite's bounds. + +use std::sync::Arc; + +use arrow_array::cast::AsArray; +use arrow_array::types::{Int32Type, Int64Type}; +use arrow_array::{Array, ArrayRef, Int8Array, Int16Array, Int32Array, Int64Array, RecordBatch}; +use arrow_schema::{DataType as ArrowType, Field, Schema}; +use krishiv_common::config::Config; +use krishiv_common::error::{ErrorClass, KrishivError}; +use krishiv_plan::analyzer::testing::{block_on, context}; +use krishiv_plan::analyzer::{ + Analyzer as _, DefaultAnalyzer, MemoryCatalog, ResolutionConf, TableColumn, +}; +use krishiv_plan::{Plan, SourceId}; +use krishiv_types::batch::Batch; +use proptest::prelude::*; + +use krishiv_exec::planner::{ + DefaultPlanner, MemoryTable, MemoryTables, PhysicalPlanner, PlanningContext, +}; + +use super::{Runnable, run}; + +/// One generated row of `s(g, ti, si, i, l)`. +type Row = ( + Option, + Option, + Option, + Option, + Option, +); + +struct Db { + ctx: krishiv_plan::analyzer::AnalysisContext, + tables: Arc, + config: Arc, +} + +fn db(rows: &[Row], batch: usize, ansi: bool) -> Db { + let schema = Arc::new(Schema::new(vec![ + Field::new("g", ArrowType::Int32, true), + Field::new("ti", ArrowType::Int8, true), + Field::new("si", ArrowType::Int16, true), + Field::new("i", ArrowType::Int32, true), + Field::new("l", ArrowType::Int64, true), + ])); + let mut batches = Vec::new(); + for chunk in rows.chunks(batch.max(1)) { + let cols: Vec = vec![ + Arc::new(Int32Array::from_iter(chunk.iter().map(|r| r.0))), + Arc::new(Int8Array::from_iter(chunk.iter().map(|r| r.1))), + Arc::new(Int16Array::from_iter(chunk.iter().map(|r| r.2))), + Arc::new(Int32Array::from_iter(chunk.iter().map(|r| r.3))), + Arc::new(Int64Array::from_iter(chunk.iter().map(|r| r.4))), + ]; + batches.push(Batch::new( + RecordBatch::try_new(Arc::clone(&schema), cols).unwrap(), + )); + } + let columns = schema + .fields() + .iter() + .map(|f| TableColumn { + name: f.name().clone(), + data_type: krishiv_types::DataType::from_arrow(f.data_type()).unwrap(), + nullable: true, + }) + .collect(); + let catalog = MemoryCatalog::new("spark_catalog").with_table(&["default"], "s", columns, None); + let tables = MemoryTables::new().with_table( + &["spark_catalog", "default", "s"], + Arc::new(MemoryTable::new(schema, batches)), + ); + let mut config = Config::new(); + config + .set( + "spark.sql.ansi.enabled", + if ansi { "true" } else { "false" }, + ) + .unwrap(); + let conf = ResolutionConf::from_conf(|k| { + (k == "spark.sql.ansi.enabled").then_some(if ansi { "true" } else { "false" }) + }); + Db { + ctx: context(catalog, conf), + tables: Arc::new(tables), + config: Arc::new(config), + } +} + +/// What a plan returned: its rows sorted, or the error class. +type Outcome = Result, ErrorClass>; + +impl Db { + fn analyze(&self, sql: &str) -> Plan { + let plan = + krishiv_sql::parse_and_lower(sql, &krishiv_sql::ParserOptions::default(), SourceId(0)) + .unwrap_or_else(|e| panic!("{sql}: {e}")); + block_on(DefaultAnalyzer.analyze(&plan, &self.ctx)) + .unwrap_or_else(|e| panic!("{sql}: {e}")) + .plan + } + + fn execute(&self, plan: &Plan) -> Outcome { + let cx = PlanningContext::new(Arc::clone(&self.tables) as _, Arc::clone(&self.config)); + let physical = DefaultPlanner + .plan(plan, &cx) + .map_err(|e: KrishivError| e.error_class())?; + let runnable = Runnable::new(physical, Arc::clone(&self.tables) as _); + let batches = run(&runnable).map_err(|e| e.error_class())?; + let mut rows = Vec::new(); + for b in &batches { + for r in 0..b.num_rows() { + let cells: Vec = b.columns().iter().map(|c| show(c, r)).collect(); + rows.push(cells.join("|")); + } + } + rows.sort(); + Ok(rows) + } + + /// The rows of `sql` as analyzed, and as optimised (also returned as + /// text). + fn both(&self, sql: &str) -> (Outcome, Outcome, String) { + let plan = self.analyze(sql); + let optimized = krishiv_optimizer::optimize(&plan).unwrap(); + ( + self.execute(&plan), + self.execute(&optimized), + optimized.root().to_string(), + ) + } +} + +fn show(a: &ArrayRef, row: usize) -> String { + if a.is_null(row) { + return "NULL".to_owned(); + } + match a.data_type() { + ArrowType::Int32 => a.as_primitive::().value(row).to_string(), + ArrowType::Int64 => a.as_primitive::().value(row).to_string(), + other => panic!("no test formatting for {other}"), + } +} + +fn int8() -> impl Strategy> { + prop_oneof![ + 1 => Just(None), + 2 => Just(Some(i8::MIN)), + 2 => Just(Some(i8::MAX)), + 6 => any::().prop_map(Some), + ] +} + +fn int16() -> impl Strategy> { + prop_oneof![ + 1 => Just(None), + 2 => Just(Some(i16::MIN)), + 2 => Just(Some(i16::MAX)), + 6 => any::().prop_map(Some), + ] +} + +fn int32() -> impl Strategy> { + prop_oneof![ + 1 => Just(None), + 2 => Just(Some(i32::MIN)), + 2 => Just(Some(i32::MAX)), + 6 => any::().prop_map(Some), + ] +} + +fn int64() -> impl Strategy> { + prop_oneof![ + 1 => Just(None), + 2 => Just(Some(i64::MIN)), + 2 => Just(Some(i64::MAX)), + 6 => any::().prop_map(Some), + ] +} + +fn rows() -> impl Strategy> { + let group = prop_oneof![1 => Just(None), 4 => (0..4_i32).prop_map(Some)]; + prop::collection::vec((group, int8(), int16(), int32(), int64()), 0..24) +} + +/// A constant inside the bound, or around it. +fn constant() -> impl Strategy { + prop_oneof![ + 6 => -100..=100_i32, + 2 => Just(65_536), + 2 => Just(-65_536), + 1 => Just(65_537), + 1 => Just(-65_537), + 1 => Just(i32::MAX), + 1 => Just(1_000_000), + ] +} + +/// A column expression, whether the rewrite takes it or not. +const COLUMNS: &[&str] = &[ + "si", + "ti", + "CAST(si AS BIGINT)", + "CAST(ti AS INT)", + "i", + "l", + "CAST(i AS BIGINT)", + "g", +]; + +/// A sum of `x` shifted by `c` in one of the four shapes. +fn sum_of(shape: u8, x: &str, c: i32) -> String { + match shape % 4 { + 0 => format!("SUM({x} + {c})"), + 1 => format!("SUM({c} + {x})"), + 2 => format!("SUM({x} - {c})"), + _ => format!("SUM({c} - {x})"), + } +} + +proptest! { + #![proptest_config(ProptestConfig { + cases: 96, + failure_persistence: None, + ..ProptestConfig::default() + })] + + /// The optimised plan returns what the analyzed plan does: the same + /// rows, or the same error class, whether the sums were rewritten. + #[test] + fn rewritten_sums_equal_the_original( + data in rows(), + batch in 1..8_usize, + ansi in any::(), + grouped in any::(), + picks in prop::collection::vec((0..COLUMNS.len(), any::(), constant()), 1..4), + ) { + let db = db(&data, batch, ansi); + let items: Vec = picks + .iter() + .map(|(col, shape, c)| sum_of(*shape, COLUMNS[*col], *c)) + .collect(); + let sql = if grouped { + format!("SELECT g, {} FROM s GROUP BY g", items.join(", ")) + } else { + format!("SELECT {} FROM s", items.join(", ")) + }; + let (original, optimized, _) = db.both(&sql); + prop_assert_eq!(original, optimized, "{} (ansi {})", sql, ansi); + } +} + +/// The rewrite really runs on the shapes it takes (the property above +/// would also hold if it never applied). +#[test] +fn the_rewrite_applies_and_agrees() { + for ansi in [true, false] { + let rows: Vec = vec![ + (Some(1), Some(i8::MAX), Some(i16::MAX), Some(1), Some(1)), + (Some(1), Some(i8::MIN), Some(i16::MIN), None, None), + (Some(2), None, None, Some(i32::MAX), Some(i64::MAX)), + (None, Some(7), Some(-7), Some(i32::MIN), Some(i64::MIN)), + ]; + let db = db(&rows, 2, ansi); + // The expected rows are those of Spark 4.2.0, ANSI on and off alike + // (no sum overflows). + for (sql, expected) in [ + ( + "SELECT SUM(si + 65536), SUM(si - 65536), SUM(65536 - si), SUM(si + 1), SUM(si) FROM s", + vec!["196600|-196616|196616|-5|-8"], + ), + ( + "SELECT g, SUM(ti + 1), SUM(CAST(si AS BIGINT) - 3) FROM s GROUP BY g", + vec!["1|1|-7", "2|NULL|NULL", "NULL|8|-10"], + ), + ("SELECT SUM(si + 1) FROM s WHERE si > 100000", vec!["NULL"]), + ] { + let (original, optimized, text) = db.both(sql); + assert!(text.contains("count("), "{sql}\n{text}"); + let expected: Vec = expected.into_iter().map(str::to_owned).collect(); + assert_eq!(original, Ok(expected), "{sql} (ansi {ansi})"); + assert_eq!(optimized, original, "{sql} (ansi {ansi})"); + } + } + // No rows: the sum is NULL, as the shifted sum is. + let empty = db(&[], 1, true); + let (original, optimized, text) = empty.both("SELECT SUM(si + 1) FROM s"); + assert!(text.contains("count("), "{text}"); + assert_eq!(original, Ok(vec!["NULL".to_owned()])); + assert_eq!(optimized, original); +} + +/// Where `x + c` can overflow per row the sum is left alone, so Spark's +/// error (ANSI) or wrap (legacy) is kept. +#[test] +fn per_row_overflow_is_kept() { + let rows: Vec = vec![(Some(0), None, None, Some(i32::MAX), Some(i64::MAX))]; + // Spark 4.2.0 without ANSI: `i + 1` and `l + 1` wrap. + for (sql, wrapped) in [ + ("SELECT SUM(i + 1) FROM s", "-2147483648"), + ("SELECT SUM(l + 1) FROM s", "-9223372036854775808"), + ] { + let ansi = db(&rows, 1, true); + let (original, optimized, text) = ansi.both(sql); + assert!(!text.contains("count("), "{sql}\n{text}"); + assert_eq!(original, Err(ErrorClass::ArithmeticOverflow), "{sql}"); + assert_eq!(optimized, original, "{sql}"); + let legacy = db(&rows, 1, false); + let (original, optimized, _) = legacy.both(sql); + assert_eq!(original, Ok(vec![wrapped.to_owned()]), "{sql}"); + assert_eq!(optimized, original, "{sql}"); + } +} + +/// The per-row check covers narrow additions too: `ti + 1Y` stays a +/// `TINYINT`, so with `ti = 127` the row overflows, and `si + 1S` stays a +/// `SMALLINT`, so with `si = 32767` it does. Without the rewrite's +/// per-row guard both would rewrite to `SUM(x) + c * COUNT(x)` and return +/// `128` and `32768`. +#[test] +fn narrow_per_row_overflow_is_kept() { + let rows: Vec = vec![(Some(0), Some(i8::MAX), Some(i16::MAX), None, None)]; + // Spark 4.2.0: `BINARY_ARITHMETIC_OVERFLOW` under ANSI, a wrap without. + for (sql, wrapped) in [ + ("SELECT SUM(ti + 1Y) FROM s", "-128"), + ("SELECT SUM(si + 1S) FROM s", "-32768"), + ] { + let ansi = db(&rows, 1, true); + let (original, optimized, text) = ansi.both(sql); + assert!(!text.contains("count("), "{sql}\n{text}"); + assert_eq!(original, Err(ErrorClass::BinaryArithmeticOverflow), "{sql}"); + assert_eq!(optimized, original, "{sql}"); + let legacy = db(&rows, 1, false); + let (original, optimized, _) = legacy.both(sql); + assert_eq!(original, Ok(vec![wrapped.to_owned()]), "{sql}"); + assert_eq!(optimized, original, "{sql}"); + } +} diff --git a/crates/krishiv-functions/src/registry/defs.rs b/crates/krishiv-functions/src/registry/defs.rs index 412c02acc..53b14d53d 100644 --- a/crates/krishiv-functions/src/registry/defs.rs +++ b/crates/krishiv-functions/src/registry/defs.rs @@ -116,14 +116,17 @@ fn date(c: &CallTypes<'_>) -> Result { typed(DataType::Date, c) } -/// Whether Spark's `date_add`/`date_sub` accepts `s` as a day count with -/// ANSI off: surrounding whitespace, a sign and digits that parse as an -/// `int`. A fraction, exponent or anything else is -/// `SECOND_FUNCTION_ARGUMENT_NOT_INTEGER`, not a truncation. -fn legacy_int(s: &str) -> bool { - let t = s.trim(); - let digits = t.strip_prefix(['+', '-']).unwrap_or(t); - !digits.is_empty() && digits.bytes().all(|b| b.is_ascii_digit()) && t.parse::().is_ok() +/// The day count `date_add`/`date_sub` without ANSI read `s` as: an `int` +/// with an optional sign, surrounded by whitespace or control characters +/// (`UTF8String.toIntExact`). A fraction is not read (`'1.5'`, `'1.'`), +/// nor an exponent, a hex number or one past `int` (checked against a +/// Spark 4.2 run of each). The typing rule here and the analyzer's shown +/// form of the call both read the day count through this. +#[must_use] +pub fn legacy_day_count(s: &str) -> Option { + s.trim_matches(|c: char| c.is_whitespace() || c.is_control()) + .parse::() + .ok() } /// `date_add`/`date_sub` with ANSI off: a string literal day count that is @@ -131,7 +134,7 @@ fn legacy_int(s: &str) -> bool { fn day_arith(function: &str, c: &CallTypes<'_>) -> Result { if !c.ansi() && let Some(Constant::String(s)) = c.constant(1) - && !legacy_int(s) + && legacy_day_count(s).is_none() { return Err(SecondFunctionArgumentNotInteger { function_name: function.to_owned(), @@ -391,9 +394,11 @@ fn min_max(c: &CallTypes<'_>) -> Result { } /// `first(x [, ignoreNulls])`: the type of `x`; the flag must be a boolean -/// literal. +/// literal (Spark matches `Literal(b, BooleanType)`, so `1 = 1` is rejected). fn pick(c: &CallTypes<'_>, function: &str) -> Result { - if c.args().len() > 1 && !matches!(c.constant(1), Some(Constant::Boolean(_))) { + if c.args().len() > 1 + && !(c.is_literal(1) && matches!(c.constant(1), Some(Constant::Boolean(_)))) + { return Err(LegacyErrorTemp1210 { func_name: function.to_owned(), } diff --git a/crates/krishiv-functions/src/registry/mod.rs b/crates/krishiv-functions/src/registry/mod.rs index 4357f419b..4a6fe7ef5 100644 --- a/crates/krishiv-functions/src/registry/mod.rs +++ b/crates/krishiv-functions/src/registry/mod.rs @@ -24,6 +24,7 @@ use std::fmt; use std::sync::{Arc, LazyLock}; pub use catalog::SparkFunction; +pub use defs::legacy_day_count; use crate::signature::{Arity, FunctionKind, Inputs, ResultType, SparkProfile}; diff --git a/crates/krishiv-functions/src/registry/tests.rs b/crates/krishiv-functions/src/registry/tests.rs index 5a36fb506..90ba42bd9 100644 --- a/crates/krishiv-functions/src/registry/tests.rs +++ b/crates/krishiv-functions/src/registry/tests.rs @@ -317,9 +317,17 @@ fn legacy_day_counts_and_binary_predicates() { let consts = [None, s(v)[0].clone()]; (def(name).result)(&CallTypes::new(&args, &consts).with_ansi(false)) }; - for ok in ["1", " -2 ", "+3", "007"] { + for ok in ["1", " -2 ", "+3", "-0", "2147483647", "007"] { assert!(legacy("date_add", ok).is_ok(), "{ok}"); } + // The day count the analyzer shows is read by the same function. + for (text, days) in [(" 12 ", Some(12)), ("-2", Some(-2)), ("+3", Some(3))] { + assert_eq!(super::legacy_day_count(text), days, "{text:?}"); + } + for bad in ["1.5", "1.", "1e2", "0x1", "2147483648", "abc", ""] { + assert_eq!(super::legacy_day_count(bad), None, "{bad:?}"); + assert!(legacy("date_add", bad).is_err(), "{bad:?}"); + } for (name, shown) in [ ("date_add", "date_add"), ("dateadd", "date_add"), @@ -335,9 +343,24 @@ fn legacy_day_counts_and_binary_predicates() { "{err}" ); } - // Spark rejects a fractional string even with ANSI off: the day count - // must parse as an `int`, not truncate. - for bad in ["1.2", "1.9", "7.", "", ".5", "1e3", "99999999999", "1-"] { + // A fraction is not an integer to `date_add` (Spark 3.5 to 4.2 raise on + // `'1.9'`, checked on each), nor are an exponent, a hex number or a + // value past `int`. Spark rejects a fractional string even with ANSI + // off: the day count must parse as an `int`, not truncate. + for bad in [ + "", + ".5", + "1e3", + "99999999999", + "1-", + "1.2", + "1.9", + "7.", + "1.0", + "0x1", + "2147483648", + "1 2", + ] { let err = legacy("date_add", bad).unwrap_err(); assert_eq!( err.error_class(), diff --git a/crates/krishiv-functions/src/scalar/mod.rs b/crates/krishiv-functions/src/scalar/mod.rs index 65267bc72..a96a8caf9 100644 --- a/crates/krishiv-functions/src/scalar/mod.rs +++ b/crates/krishiv-functions/src/scalar/mod.rs @@ -300,6 +300,19 @@ pub fn scalar_names() -> Vec<&'static str> { names } +/// Whether the result of the scalar function `name` depends only on its +/// arguments and `spark.sql.ansi.enabled`: the string, math and arithmetic +/// families. The datetime, session and hash families read the session time +/// zone, the user or the query start, so a caller that evaluates a call +/// before execution (constant folding) must not evaluate those. +#[must_use] +pub fn is_argument_pure(name: &str) -> bool { + let lower = name.to_ascii_lowercase(); + [string::NAMES, math::NAMES, arith::NAMES] + .iter() + .any(|names| names.contains(&lower.as_str())) +} + /// Binds the scalar function `name` (ASCII case-insensitive) to `args`. /// /// # Errors diff --git a/crates/krishiv-functions/src/signature.rs b/crates/krishiv-functions/src/signature.rs index eb9d7118b..e6f2d1cd9 100644 --- a/crates/krishiv-functions/src/signature.rs +++ b/crates/krishiv-functions/src/signature.rs @@ -131,6 +131,7 @@ impl ArgType { pub struct CallTypes<'a> { args: &'a [ArgType], constants: &'a [Option], + literals: &'a [bool], sql: Option<&'a dyn Fn(usize) -> Option>, ansi: bool, decimal_loss: bool, @@ -141,6 +142,7 @@ impl fmt::Debug for CallTypes<'_> { f.debug_struct("CallTypes") .field("args", &self.args) .field("constants", &self.constants) + .field("literals", &self.literals) .field("ansi", &self.ansi) .field("decimal_loss", &self.decimal_loss) .finish_non_exhaustive() @@ -155,12 +157,22 @@ impl<'a> CallTypes<'a> { Self { args, constants, + literals: &[], sql: None, ansi: true, decimal_loss: true, } } + /// With `literals[i]` telling whether argument `i` is a plain literal + /// (not merely foldable). Without it, every constant counts as a + /// literal. + #[must_use] + pub const fn with_literals(mut self, literals: &'a [bool]) -> Self { + self.literals = literals; + self + } + /// With `spark.sql.ansi.enabled = ansi` (on by default): some legacy /// typing rules differ. #[must_use] @@ -222,6 +234,17 @@ impl<'a> CallTypes<'a> { self.constants.get(i).and_then(Option::as_ref) } + /// Whether argument `i` is a plain literal: what Spark's rules that + /// match `Literal(..)` (the `ignoreNulls` flag of `first`) require, as + /// opposed to the foldable expressions [`Self::constant`] also gives. + #[must_use] + pub fn is_literal(&self, i: usize) -> bool { + match self.literals.get(i) { + Some(plain) => *plain && self.constant(i).is_some(), + None => self.constant(i).is_some(), + } + } + /// Whether any argument may be null. #[must_use] pub fn any_nullable(&self) -> bool { diff --git a/crates/krishiv-kernels/CLAUDE.md b/crates/krishiv-kernels/CLAUDE.md index 3a7758c66..2eb262329 100644 --- a/crates/krishiv-kernels/CLAUDE.md +++ b/crates/krishiv-kernels/CLAUDE.md @@ -12,6 +12,9 @@ Vectorised compute kernels (SIMD) with Spark semantics, Spark-observable Murmur3 has-nulls axis (compute-through-nulls makes it ~1.0x); `specialize` is the opt-in `const NULLS` axis for kernels whose work changes with NULLs (division, strings). A `LaneOp` reports a `Fault` (overflow, divide-by-zero); the policy maps each fault to wrap / NULL / raise. +- `Dispatch` (sealed): `KernelCtx` picks the CPU target at run time (three clones of each loop, plus scalar-operand + loops); `Baseline` runs the build-baseline loop only, a scalar repeated into an array (one loop per kernel), for + one-row/constant evaluation such as plan-time folding. Dispatching entry points take `ctx: &impl Dispatch`. - `unsafe_dispatch`: the only `unsafe` (calling `#[target_feature]` clones); `xtask source-guard` rejects `unsafe` in any other file here and `xtask budgets` counts unsafe sites. - `version`: the Spark version profile (`KernelCtx::with_spark_version`); error classes/messages differ by version. diff --git a/crates/krishiv-kernels/src/chunk.rs b/crates/krishiv-kernels/src/chunk.rs index 74bd70ad1..c7b725f41 100644 --- a/crates/krishiv-kernels/src/chunk.rs +++ b/crates/krishiv-kernels/src/chunk.rs @@ -19,11 +19,11 @@ use arrow_array::{Array, ArrowPrimitiveType}; use arrow_buffer::bit_chunk_iterator::BitChunks; use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer}; -use crate::dispatch::KernelCtx; +use crate::dispatch::Dispatch; use crate::error::{KernelError, with_capacity}; use crate::ops::Operand; use crate::policy::{Action, Fault, Overflow}; -use crate::unsafe_dispatch::{Kernel, run}; +use crate::unsafe_dispatch::{Kernel, run, scalar_loops}; /// Rows per chunk: one validity word. pub(crate) const CHUNK: usize = 64; @@ -53,6 +53,29 @@ pub(crate) enum Side<'a, T> { Scalar(T), } +impl<'a, T: Copy> Side<'a, T> { + /// This side as an array of `len` values: a scalar is repeated into + /// `buf` (for a dispatch without scalar loops, see + /// `unsafe_dispatch::Run::SCALAR_LOOPS`). + pub(crate) fn to_array<'b>( + self, + len: usize, + buf: &'b mut Vec, + ) -> Result, KernelError> + where + 'a: 'b, + { + Ok(match self { + Side::Array(a) => Side::Array(a), + Side::Scalar(v) => { + *buf = with_capacity(len)?; + buf.resize(len, v); + Side::Array(buf) + } + }) + } +} + /// Operands resolved once per batch. #[derive(Debug)] pub(crate) enum Resolved<'a, T> { @@ -124,7 +147,7 @@ fn checks, O: Overflow>() -> bool { /// Runs `op` over two resolved sides (`len` rows; `nulls` is the input /// validity). A raised fault becomes the error `raise(row, fault)`. pub(crate) fn compute( - ctx: &KernelCtx, + ctx: &impl Dispatch, l: Side<'_, T>, r: Side<'_, T>, nulls: Option, @@ -147,12 +170,12 @@ where let mut null_words = with_capacity::(if may_null { n_words } else { 0 })?; let n = nulls.as_ref(); macro_rules! go { - ($ls:literal, $rs:literal) => { + ($ls:literal, $rs:literal, $l:expr, $r:expr) => { run( ctx, Chunks::<'_, T, L, O, $ls, $rs> { - l, - r, + l: $l, + r: $r, validity: n, out: &mut out, null_words: &mut null_words, @@ -163,10 +186,20 @@ where ) }; } - let raised = match (l, r) { - (Side::Array(_), Side::Array(_)) => go!(false, false), - (Side::Array(_), Side::Scalar(_)) => go!(false, true), - (Side::Scalar(_), _) => go!(true, false), + let raised = if scalar_loops(ctx) { + match (l, r) { + (Side::Array(_), Side::Array(_)) => go!(false, false, l, r), + (Side::Array(_), Side::Scalar(_)) => go!(false, true, l, r), + (Side::Scalar(_), _) => go!(true, false, l, r), + } + } else { + let (mut lb, mut rb) = (Vec::new(), Vec::new()); + go!( + false, + false, + l.to_array(len, &mut lb)?, + r.to_array(len, &mut rb)? + ) }; if let Some((row, fault)) = raised { return Err(raise(row, fault)); @@ -459,7 +492,7 @@ mod tests { nulls: Option, ) -> Result, KernelError> { compute::( - &KernelCtx::new(), + &crate::KernelCtx::new(), Side::Array(a), Side::Array(b), nulls, diff --git a/crates/krishiv-kernels/src/compare.rs b/crates/krishiv-kernels/src/compare.rs index 7bf586f40..8a7e74872 100644 --- a/crates/krishiv-kernels/src/compare.rs +++ b/crates/krishiv-kernels/src/compare.rs @@ -22,10 +22,10 @@ use arrow_array::{Array, ArrowPrimitiveType, BooleanArray, GenericByteArray}; use arrow_buffer::{ArrowNativeType, BooleanBuffer, Buffer, NullBuffer}; use crate::chunk::{self, CHUNK, Resolved, Side, split}; -use crate::dispatch::KernelCtx; +use crate::dispatch::Dispatch; use crate::error::{KernelError, with_capacity}; use crate::ops::Operand; -use crate::unsafe_dispatch::{Kernel, run}; +use crate::unsafe_dispatch::{Kernel, run, scalar_loops}; mod sealed { pub trait Sealed {} @@ -174,7 +174,7 @@ compare_ops!( pub fn compare( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result where T: ArrowPrimitiveType, @@ -195,12 +195,12 @@ where }; let mut words = with_capacity::(len.div_ceil(CHUNK))?; macro_rules! go { - ($ls:literal, $rs:literal) => { + ($ls:literal, $rs:literal, $l:expr, $r:expr) => { run( ctx, Compare::<'_, T::Native, Op, $ls, $rs> { - l, - r, + l: $l, + r: $r, len, words: &mut words, op: PhantomData, @@ -208,10 +208,20 @@ where ) }; } - match (l, r) { - (Side::Array(_), Side::Array(_)) => go!(false, false), - (Side::Array(_), Side::Scalar(_)) => go!(false, true), - (Side::Scalar(_), _) => go!(true, false), + if scalar_loops(ctx) { + match (l, r) { + (Side::Array(_), Side::Array(_)) => go!(false, false, l, r), + (Side::Array(_), Side::Scalar(_)) => go!(false, true, l, r), + (Side::Scalar(_), _) => go!(true, false, l, r), + } + } else { + let (mut lb, mut rb) = (Vec::new(), Vec::new()); + go!( + false, + false, + l.to_array(len, &mut lb)?, + r.to_array(len, &mut rb)? + ); } Ok(BooleanArray::new(bits(words, len), nulls)) } diff --git a/crates/krishiv-kernels/src/decimal.rs b/crates/krishiv-kernels/src/decimal.rs index 1880e280b..dde442a4b 100644 --- a/crates/krishiv-kernels/src/decimal.rs +++ b/crates/krishiv-kernels/src/decimal.rs @@ -43,7 +43,7 @@ use arrow_array::{Array, ArrayRef, Decimal128Array, Int64Array, PrimitiveArray}; use arrow_buffer::{NullBuffer, ScalarBuffer, i256}; use crate::chunk::{self, LaneOp, Resolved, Side}; -use crate::dispatch::KernelCtx; +use crate::dispatch::Dispatch; use crate::error::{KernelError, with_capacity}; use crate::integer::{UnaryOp, at}; use crate::ops::{ArithOp, BinaryOp, IntNative, Operand}; @@ -821,7 +821,7 @@ pub fn decimal_binary( l: Operand<'_, Decimal128Type>, r: Operand<'_, Decimal128Type>, plan: &DecimalPlan, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result where Op: BinaryOp, @@ -845,7 +845,7 @@ fn binary_any( r: DecimalOperand<'_>, plan: &DecimalPlan, carrier: DecimalCarrier, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result where Op: BinaryOp, @@ -874,7 +874,7 @@ where /// The exact `+ - *` lanes of one input native `N` and result native `R`. fn fast_lanes( plan: &DecimalPlan, - ctx: &KernelCtx, + ctx: &impl Dispatch, sl: Side<'_, N>, sr: Side<'_, N>, nulls: Option, @@ -923,7 +923,7 @@ where /// The error of a raised row of `plan`. fn plan_error( plan: &DecimalPlan, - ctx: &KernelCtx, + ctx: &impl Dispatch, l: Side<'_, N>, r: Side<'_, N>, row: usize, @@ -975,7 +975,7 @@ pub fn decimal_arith( l: Operand<'_, Decimal128Type>, r: Operand<'_, Decimal128Type>, plan: &DecimalPlan, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result { let out = decimal_arith_any::(l.into(), r.into(), plan, DecimalCarrier::Decimal128, ctx)?; as_decimal128(&out) @@ -1024,7 +1024,7 @@ pub fn decimal_arith_any( r: DecimalOperand<'_>, plan: &DecimalPlan, carrier: DecimalCarrier, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result { if plan.is_fast() { return match plan.op { @@ -1062,7 +1062,7 @@ pub fn decimal_integral_divide( r: Operand<'_, Decimal128Type>, left: DecimalType, right: DecimalType, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result { decimal_integral_divide_any::(l.into(), r.into(), left, right, ctx) } @@ -1076,7 +1076,7 @@ pub fn decimal_integral_divide_any( r: DecimalOperand<'_>, left: DecimalType, right: DecimalType, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result { check_type(left)?; check_type(right)?; @@ -1312,7 +1312,7 @@ mod tests { .with_precision_and_scale(5, 0) .unwrap(); let p = plan(ArithOp::Add, (5, 0), (5, 0), (6, 0)); - let ctx = KernelCtx::new(); + let ctx = crate::KernelCtx::new(); let e = decimal_binary::( Operand::Array(&a), Operand::Array(&a), diff --git a/crates/krishiv-kernels/src/dispatch.rs b/crates/krishiv-kernels/src/dispatch.rs index 5f2e29f05..5f2123b0f 100644 --- a/crates/krishiv-kernels/src/dispatch.rs +++ b/crates/krishiv-kernels/src/dispatch.rs @@ -189,6 +189,57 @@ impl KernelCtx { } } +/// How a kernel entry point runs its loops; every dispatching entry point +/// takes `ctx: &impl Dispatch`. Sealed: the implementations are +/// [`KernelCtx`] (the CPU target chosen at run time, so each loop is +/// compiled once per [`Target`]) and [`Baseline`]. +pub trait Dispatch: crate::unsafe_dispatch::Run { + /// The Spark version whose errors kernels raise. + fn spark_version(&self) -> SparkVersion; +} + +impl Dispatch for KernelCtx { + #[inline] + fn spark_version(&self) -> SparkVersion { + self.version + } +} + +/// A dispatch that always runs the build-baseline code: an entry point +/// called with it instantiates one loop, without the per-target clones and +/// the scalar-operand loops a [`KernelCtx`] needs (a scalar operand is +/// repeated into an array first). For evaluating one row or a constant +/// (plan-time folding), where vector width does not matter but code size +/// does. The results are a [`KernelCtx`]'s: every target and operand shape +/// computes the same values. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Baseline { + version: SparkVersion, +} + +impl Baseline { + /// Raising the errors of Spark `version`. + #[must_use] + pub fn new(version: SparkVersion) -> Self { + Self { version } + } +} + +impl Dispatch for Baseline { + #[inline] + fn spark_version(&self) -> SparkVersion { + self.version + } +} + +impl KernelCtx { + /// This context's Spark version, on the baseline code only. + #[must_use] + pub fn baseline(&self) -> Baseline { + Baseline::new(self.version) + } +} + impl Default for KernelCtx { fn default() -> Self { Self::new() @@ -226,6 +277,198 @@ mod tests { assert!(!Target::X86_64V4.is_available() || Target::X86_64V3.is_available()); } + /// Float results compared by value: the same errors, validity and values, + /// a NaN equal to any NaN (Miri randomizes NaN payloads), every other + /// value bit for bit (so `-0.0` is not `0.0`). + #[track_caller] + fn same_floats( + a: Result, + b: Result, + ) { + use arrow_array::Array; + match (a, b) { + (Ok(a), Ok(b)) => { + assert_eq!(a.nulls(), b.nulls()); + assert_eq!(a.len(), b.len()); + for (i, (x, y)) in a.values().iter().zip(b.values().iter()).enumerate() { + assert!( + (x.is_nan() && y.is_nan()) || x.to_bits() == y.to_bits(), + "row {i}: {x} vs {y}" + ); + } + } + (a, b) => assert_eq!(a, b), + } + } + + /// `Baseline` computes what every available target computes, for every + /// operand shape, over several 64-row chunks, errors (with their row and + /// Spark version) included. `KRISHIV_REQUIRE_TARGETS` (set in CI) makes + /// a missing target a failure instead of a skipped comparison. + #[test] + fn baseline_matches_every_available_target() { + use arrow_array::types::{Decimal128Type, Float64Type, Int32Type}; + use arrow_array::{Array, Decimal128Array, Float64Array, Int32Array}; + + use crate::compare::{Less, compare}; + use crate::decimal::{DecimalOp, DecimalPlan, decimal_arith}; + use crate::integer::{self, UnaryOp}; + use crate::{Add, AnsiError, ArithOp, JavaWrap, Mul, NullOnOverflow, Operand, float}; + + let required = std::env::var("KRISHIV_REQUIRE_TARGETS").unwrap_or_default(); + Target::check_required(&required).unwrap(); + + // 150 rows: two full chunks and a partial one, with NULLs, zeros + // and overflowing values in each. + let a: Int32Array = (0..150) + .map(|i: i32| (i % 11 != 5).then_some(if i % 13 == 0 { i32::MAX } else { i * 7 - 300 })) + .collect(); + let b: Int32Array = (0..150) + .map(|i: i32| (i % 17 != 3).then_some(if i % 19 == 0 { 0 } else { i - 70 })) + .collect(); + // The only overflow is at row 100, in the second chunk. + let late: Int32Array = (0..150) + .map(|i| Some(if i == 100 { i32::MAX } else { i })) + .collect(); + let x: Float64Array = (0..150) + .map(|i| match i % 9 { + 0 => None, + 1 => Some(-0.0), + 2 => Some(f64::NAN), + 3 => Some(0.0), + _ => Some(f64::from(i) * 1.5 - 40.0), + }) + .collect(); + let d = Decimal128Array::from(vec![Some(99_999), None, Some(-5)]) + .with_precision_and_scale(5, 2) + .unwrap(); + let plan = DecimalPlan::new(DecimalOp::Multiply, (5, 2), (5, 2), (5, 2)).unwrap(); + let shapes: [(Operand<'_, Int32Type>, Operand<'_, Int32Type>); 6] = [ + (Operand::Array(&a), Operand::Array(&b)), + (Operand::Array(&a), Operand::Scalar(Some(7))), + (Operand::Array(&a), Operand::Scalar(Some(0))), + (Operand::Scalar(Some(-7)), Operand::Array(&b)), + (Operand::Scalar(None), Operand::Array(&b)), + (Operand::Array(&late), Operand::Scalar(Some(1))), + ]; + let fz = Operand::::Scalar(Some(0.0)); + let float_shapes: [(Operand<'_, Float64Type>, Operand<'_, Float64Type>); 4] = [ + (Operand::Array(&x), Operand::Array(&x)), + (Operand::Array(&x), Operand::Scalar(Some(2.5))), + (Operand::Array(&x), fz), + (Operand::Scalar(Some(-3.0)), Operand::Array(&x)), + ]; + let null_row = Int32Array::from(vec![None, Some(1)]); + for t in Target::available() { + let ctx = KernelCtx::with_target(t) + .unwrap() + .with_spark_version(SparkVersion::V4_0); + let base = ctx.baseline(); + assert_eq!(Dispatch::spark_version(&base), SparkVersion::V4_0); + for (l, r) in shapes { + assert_eq!( + integer::binary::(l, r, &ctx), + integer::binary::(l, r, &base) + ); + assert_eq!( + integer::binary::(l, r, &ctx), + integer::binary::(l, r, &base) + ); + assert_eq!( + integer::binary::(l, r, &ctx), + integer::binary::(l, r, &base) + ); + assert_eq!( + integer::remainder::(l, r, &ctx), + integer::remainder::(l, r, &base) + ); + assert_eq!( + integer::remainder::(l, r, &ctx), + integer::remainder::(l, r, &base) + ); + assert_eq!( + compare::(l, r, &ctx), + compare::(l, r, &base) + ); + } + // The cases above do raise: overflow and remainder by zero, the + // late overflow at its own row, past the first chunk. + let (l, r) = (Operand::Array(&a), Operand::Array(&b)); + assert!(integer::binary::(l, r, &base).is_err()); + let by_zero = (Operand::Array(&a), Operand::Scalar(Some(0))); + assert!( + integer::remainder::(by_zero.0, by_zero.1, &base).is_err() + ); + let late_add = integer::binary::( + Operand::Array(&late), + Operand::Scalar(Some(1)), + &base, + ); + assert_eq!(late_add.unwrap_err().row(), Some(100)); + // A scalar zero divisor never raises on a NULL row: NULL there, + // the error at the first valid row. + let one_null = Int32Array::from(vec![None::]); + for (l, ok) in [(&one_null, true), (&null_row, false)] { + let (l, r) = (Operand::Array(l), Operand::Scalar(Some(0))); + let got = integer::remainder::(l, r, &base); + assert_eq!(got, integer::remainder::(l, r, &ctx)); + assert_eq!(got.map_err(|e| e.row()).err(), (!ok).then_some(Some(1))); + } + assert!( + integer::remainder::( + Operand::Array(&one_null), + Operand::Scalar(Some(0)), + &base + ) + .unwrap() + .is_null(0) + ); + assert_eq!( + integer::unary::(UnaryOp::Negate, &a, &ctx), + integer::unary::(UnaryOp::Negate, &a, &base) + ); + for (fl, fr) in float_shapes { + for op in [ArithOp::Add, ArithOp::Subtract, ArithOp::Multiply] { + same_floats( + float::binary(op, fl, fr, &ctx), + float::binary(op, fl, fr, &base), + ); + } + same_floats( + float::divide::(fl, fr, &ctx), + float::divide::(fl, fr, &base), + ); + same_floats( + float::remainder::(fl, fr, &ctx), + float::remainder::(fl, fr, &base), + ); + same_floats( + float::remainder::(fl, fr, &ctx), + float::remainder::(fl, fr, &base), + ); + assert_eq!( + compare::(fl, fr, &ctx), + compare::(fl, fr, &base) + ); + } + assert!( + float::remainder::(Operand::Array(&x), fz, &base).is_err() + ); + let (dl, dr) = ( + Operand::Array(&d), + Operand::::Scalar(Some(-200)), + ); + assert_eq!( + decimal_arith::(dl, dr, &plan, &ctx), + decimal_arith::(dl, dr, &plan, &base) + ); + assert_eq!( + decimal_arith::(dr, dl, &plan, &ctx), + decimal_arith::(dr, dl, &plan, &base) + ); + } + } + #[test] fn selection_prefers_avx512_when_present() { assert_eq!(Target::select(true, true), Target::X86_64V4); diff --git a/crates/krishiv-kernels/src/float.rs b/crates/krishiv-kernels/src/float.rs index 4e31ad104..1a592079d 100644 --- a/crates/krishiv-kernels/src/float.rs +++ b/crates/krishiv-kernels/src/float.rs @@ -12,7 +12,7 @@ use arrow_array::{Array, ArrowPrimitiveType, PrimitiveArray}; use crate::chunk::{self, LaneOp, Resolved}; -use crate::dispatch::KernelCtx; +use crate::dispatch::Dispatch; use crate::error::KernelError; use crate::integer::{UnaryOp, finish}; use crate::ops::{ArithOp, Operand}; @@ -108,7 +108,7 @@ pub fn binary( op: ArithOp, l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: ArrowPrimitiveType, @@ -161,7 +161,7 @@ impl LaneOp for DivLane { pub fn divide( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: ArrowPrimitiveType, @@ -185,7 +185,7 @@ where pub fn remainder( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: ArrowPrimitiveType, diff --git a/crates/krishiv-kernels/src/integer.rs b/crates/krishiv-kernels/src/integer.rs index 43b469cb6..127e58e0c 100644 --- a/crates/krishiv-kernels/src/integer.rs +++ b/crates/krishiv-kernels/src/integer.rs @@ -22,7 +22,7 @@ use arrow_array::{Array, ArrowPrimitiveType, PrimitiveArray}; use arrow_buffer::{NullBuffer, ScalarBuffer}; use crate::chunk::{self, LaneOp, Resolved, Side}; -use crate::dispatch::KernelCtx; +use crate::dispatch::Dispatch; use crate::error::KernelError; use crate::ops::{ArithOp, BinaryOp, IntNative, Operand}; use crate::policy::{Fault, Overflow}; @@ -67,7 +67,7 @@ spark_integral!( /// The overflow error of `l op r` at `row`. pub(crate) fn overflow_error( - ctx: &KernelCtx, + ctx: &impl Dispatch, row: usize, op: ArithOp, l: T::Native, @@ -140,7 +140,7 @@ impl LaneOp for IntLane { pub fn binary( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: SparkIntegral, @@ -158,7 +158,7 @@ where pub fn binary_nulls_path( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: SparkIntegral, @@ -171,7 +171,7 @@ where fn binary_impl( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, force_nulls: bool, ) -> Result, KernelError> where @@ -232,7 +232,7 @@ impl LaneOp for RemLane { pub fn remainder( l: Operand<'_, T>, r: Operand<'_, T>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: SparkIntegral, @@ -286,7 +286,7 @@ impl LaneOp for DivLane { pub fn integral_divide( l: Operand<'_, Int64Type>, r: Operand<'_, Int64Type>, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> { let (l, r, nulls, len) = match chunk::resolve(l, r)? { Resolved::AllNull(len) => return Ok(PrimitiveArray::new_null(len)), @@ -340,7 +340,7 @@ impl LaneOp for UnaryLane { pub fn unary( op: UnaryOp, a: &PrimitiveArray, - ctx: &KernelCtx, + ctx: &impl Dispatch, ) -> Result, KernelError> where T: SparkIntegral, diff --git a/crates/krishiv-kernels/src/lib.rs b/crates/krishiv-kernels/src/lib.rs index 33e14bd62..aba6b963c 100644 --- a/crates/krishiv-kernels/src/lib.rs +++ b/crates/krishiv-kernels/src/lib.rs @@ -58,7 +58,7 @@ pub mod text; mod unsafe_dispatch; pub mod version; -pub use dispatch::{KernelCtx, Target}; +pub use dispatch::{Baseline, Dispatch, KernelCtx, Target}; pub use error::KernelError; pub use ops::{Add, ArithOp, Mul, Operand, Sub}; pub use policy::{AnsiError, JavaWrap, NullOnOverflow, Overflow, OverflowMode, Unchecked}; diff --git a/crates/krishiv-kernels/src/unsafe_dispatch.rs b/crates/krishiv-kernels/src/unsafe_dispatch.rs index dabb13924..cf35e1d3c 100644 --- a/crates/krishiv-kernels/src/unsafe_dispatch.rs +++ b/crates/krishiv-kernels/src/unsafe_dispatch.rs @@ -4,40 +4,81 @@ //! `cargo xtask source-guard` rejects `unsafe` in any other file of this //! crate, and `cargo xtask budgets` counts the blocks. -use crate::dispatch::{KernelCtx, Target}; +use crate::dispatch::{Baseline, KernelCtx, Target}; /// A kernel body: everything [`Kernel::run`] calls must be `#[inline]`d into /// it so the whole loop is compiled with the clone's target features. -pub(crate) trait Kernel { +/// (Nominally `pub` inside this private module: unnameable outside the +/// crate, as [`Run`] needs.) +pub trait Kernel { /// The kernel's result. type Output; /// Runs the kernel. Implementations are `#[inline(always)]`. fn run(self) -> Self::Output; } -/// Runs `kernel` compiled for the context's target. +/// How a [`crate::Dispatch`] runs a kernel body. Sealed: this module is +/// private, so no type outside the crate can implement it. +pub trait Run { + /// Whether a scalar operand gets its own loop (`` + /// monomorphs). Without them a kernel compiles one loop and a scalar is + /// repeated into an array first: a copy per call, nothing for one row. + const SCALAR_LOOPS: bool; + /// Runs `kernel` compiled for the target this dispatch chooses. + fn run_kernel(&self, kernel: K) -> K::Output; +} + +/// [`Run::SCALAR_LOOPS`] of `dispatch`'s type. +#[inline(always)] +pub(crate) fn scalar_loops(_dispatch: &D) -> bool { + D::SCALAR_LOOPS +} + +/// Runs `kernel` as `dispatch` chooses. #[inline] -pub(crate) fn run(ctx: &KernelCtx, kernel: K) -> K::Output { - match ctx.target() { - Target::Baseline => kernel.run(), - #[cfg(target_arch = "x86_64")] - Target::X86_64V3 => { - debug_assert!(Target::X86_64V3.is_available()); - // SAFETY: a `KernelCtx` only holds a target that `Target::is_available` - // confirmed on this CPU (`KernelCtx::new`/`with_target` are its only - // constructors), so every feature `unsafe_run_v3` enables is present. - unsafe { unsafe_run_v3(kernel) } - } - #[cfg(target_arch = "x86_64")] - Target::X86_64V4 => { - debug_assert!(Target::X86_64V4.is_available()); - // SAFETY: as above, for the x86-64-v4 feature set. - unsafe { unsafe_run_v4(kernel) } +pub(crate) fn run(dispatch: &D, kernel: K) -> K::Output { + dispatch.run_kernel(kernel) +} + +/// The build baseline only: no `#[target_feature]` clone is instantiated, and +/// no scalar-operand loop, so a kernel reached only through [`Baseline`] +/// compiles one loop instead of nine. +impl Run for Baseline { + const SCALAR_LOOPS: bool = false; + + #[inline] + fn run_kernel(&self, kernel: K) -> K::Output { + kernel.run() + } +} + +/// The context's target, detected at run time. +impl Run for KernelCtx { + const SCALAR_LOOPS: bool = true; + + #[inline] + fn run_kernel(&self, kernel: K) -> K::Output { + match self.target() { + Target::Baseline => kernel.run(), + #[cfg(target_arch = "x86_64")] + Target::X86_64V3 => { + debug_assert!(Target::X86_64V3.is_available()); + // SAFETY: a `KernelCtx` only holds a target that `Target::is_available` + // confirmed on this CPU (`KernelCtx::new`/`with_target` are its only + // constructors), so every feature `unsafe_run_v3` enables is present. + unsafe { unsafe_run_v3(kernel) } + } + #[cfg(target_arch = "x86_64")] + Target::X86_64V4 => { + debug_assert!(Target::X86_64V4.is_available()); + // SAFETY: as above, for the x86-64-v4 feature set. + unsafe { unsafe_run_v4(kernel) } + } + // Non-x86 CPUs never report the x86 targets available, so no context + // holds them; run the portable code regardless. + #[cfg(not(target_arch = "x86_64"))] + Target::X86_64V3 | Target::X86_64V4 => kernel.run(), } - // Non-x86 CPUs never report the x86 targets available, so no context - // holds them; run the portable code regardless. - #[cfg(not(target_arch = "x86_64"))] - Target::X86_64V3 | Target::X86_64V4 => kernel.run(), } } diff --git a/crates/krishiv-optimizer/CLAUDE.md b/crates/krishiv-optimizer/CLAUDE.md index b25c08985..f5f0c4789 100644 --- a/crates/krishiv-optimizer/CLAUDE.md +++ b/crates/krishiv-optimizer/CLAUDE.md @@ -25,6 +25,10 @@ Paths are relative to this crate. rewrites a shared subtree once (`dag::Rewriter`), subquery plans included; never copy a shared subtree. - Only deterministic predicates move; folding never changes what a query returns or raises (no overflow, no division, no time-zone-dependent cast; a raising call stays in the plan). +- `SUM(x + c)` of a narrow integral column becomes `SUM(x) + c * COUNT(x)` (`sum_rewrite.rs`, one pass after the + rewrite batch) only where the type range proves no per-row overflow and `|x|, |c| <= 2^16`; floating point and + decimals are never rewritten. Conditions and the one residual assumption (fewer than 2^46 rows per aggregate) + are in the module docs; the executor differential test is `krishiv-exec` `tests/planner/sum_rewrite.rs`. - Join ordering re-plans each inner-join tree (through deterministic filters and column selections) from `Statistics`; it never adds a cross product, places each conjunct at the lowest join that has its inputs (subquery conjuncts as filters), and restores column order only for positional consumers. Inputs are diff --git a/crates/krishiv-optimizer/Cargo.toml b/crates/krishiv-optimizer/Cargo.toml index ed5ebecde..fbb40db8d 100644 --- a/crates/krishiv-optimizer/Cargo.toml +++ b/crates/krishiv-optimizer/Cargo.toml @@ -12,6 +12,7 @@ publish = false arrow-array.workspace = true arrow-schema.workspace = true krishiv-common = { path = "../krishiv-common" } +krishiv-functions = { path = "../krishiv-functions" } krishiv-kernels = { path = "../krishiv-kernels" } krishiv-plan = { path = "../krishiv-plan" } krishiv-types = { path = "../krishiv-types" } diff --git a/crates/krishiv-optimizer/src/lib.rs b/crates/krishiv-optimizer/src/lib.rs index f42b46cf6..02c5fa12e 100644 --- a/crates/krishiv-optimizer/src/lib.rs +++ b/crates/krishiv-optimizer/src/lib.rs @@ -13,6 +13,8 @@ //! outer joins inner where a filter rejects their NULL rows), join //! conditions into the side they read, projection collapse and removal, //! limit pushdown. +//! **Algebraic sum**, once: `SUM(x + c)` over a narrow integral column +//! becomes `SUM(x) + c * COUNT(x)` (`sum_rewrite`). //! 2. **Restrict**, then alternating with join order until neither //! changes the plan: an aggregate below a join that drops its unmatched //! groups groups only the input rows whose keys the join's other side @@ -47,6 +49,7 @@ mod prune; mod pushdown; mod restrict; mod stats; +mod sum_rewrite; use std::sync::Arc; @@ -193,6 +196,9 @@ fn run( }) })?; let root = batch(root, "Rewrite", &mut t)?; + let root = t.once("AlgebraicSum", &root, |r| { + sum_rewrite::rewrite(Arc::clone(r)) + })?; // Restriction and join ordering alternate until neither changes // the plan: ordering sees the restricted estimates, and restriction // sees every join the ordering forms (which side an aggregate joins diff --git a/crates/krishiv-optimizer/src/restrict.rs b/crates/krishiv-optimizer/src/restrict.rs index 9bb705423..39628795f 100644 --- a/crates/krishiv-optimizer/src/restrict.rs +++ b/crates/krishiv-optimizer/src/restrict.rs @@ -82,7 +82,7 @@ const LOPSIDED: f64 = 2.0; const DESCEND: f64 = 2.0; /// The largest attribute id a plan may hold (as the analyzer allows). -const MAX_ID: u64 = 1 << 62; +pub(crate) const MAX_ID: u64 = 1 << 62; /// Restricts the aggregates below joins in `root` (see the module docs). pub(crate) fn restrict( @@ -603,7 +603,7 @@ fn shift(e: &Arc, offset: u64) -> Arc { /// The largest attribute id `p` holds: outputs, references and subquery /// plans, each shift at its offset. -fn max_id(p: &Arc, memo: &mut HashMap<*const LogicalPlan, u64>) -> u64 { +pub(crate) fn max_id(p: &Arc, memo: &mut HashMap<*const LogicalPlan, u64>) -> u64 { if let Some(m) = memo.get(&Arc::as_ptr(p)) { return *m; } diff --git a/crates/krishiv-optimizer/src/sum_rewrite.rs b/crates/krishiv-optimizer/src/sum_rewrite.rs new file mode 100644 index 000000000..01f828e80 --- /dev/null +++ b/crates/krishiv-optimizer/src/sum_rewrite.rs @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: Apache-2.0 +//! `SUM(x + c)` as `SUM(x) + c * COUNT(x)` (and `x - c`, `c - x`). +//! +//! Many sums of one column shifted by different constants (ClickBench's +//! 30th query computes ninety) become one `SUM` and one `COUNT` of the +//! column, and a projection above the aggregate that adds the constants. +//! DuckDB has a rewrite of this shape (`SumRewriteRule` in +//! `src/optimizer/aggregate_function_rewriter.cpp`, formerly its sum +//! rewriter); it matches integer `x + C` without grouping and widens the +//! result. This one is stricter, because Spark evaluates `x + c` per row +//! and an overflow there is an error (ANSI) or a wrap (legacy) that +//! `SUM(x) + c * COUNT(x)` would not reproduce. +//! +//! # When it applies +//! +//! All of the following, else the aggregate is left alone: +//! +//! 1. The item is exactly `sum(e) AS a` (not `DISTINCT`, no `FILTER`), `e` +//! is a call of `+` or `-` of an integral column expression `x` and an +//! integral literal `c`, and the call has the type of `x` and `c`. +//! Floating point is excluded: IEEE addition is not associative, so +//! `SUM(x + c)` and `SUM(x) + c * COUNT(x)` differ in the last bits, +//! and the result must be identical. Decimals are excluded: their +//! result precision and scale follow the operands and the rewrite would +//! have to reproduce each rounding. +//! 2. **No per-row overflow.** The type of `x` bounds it +//! ([`bounds`]: a column's type, through casts that cannot fail) and +//! every value `x + c` can take fits the type of the addition. For +//! `SMALLINT` and `TINYINT` columns promoted to `INT` or `BIGINT` (what +//! Spark's coercion makes of `smallint_col + 1`) this always holds. For +//! an `INT` column and `+ 1` it does not (`INT_MAX + 1` overflows), so +//! that is left alone. +//! 3. **No overflow in the accumulation either.** `SUM` of an integral type +//! accumulates in `BIGINT` (an error under ANSI, a wrap in legacy +//! mode); the rewrite accumulates `SUM(x)` and `c * COUNT(x)` there. +//! Legacy mode wraps modulo 2^64, which is associative, so both agree +//! for any input. Under ANSI, an error is raised when a partial sum +//! leaves the `BIGINT` range. With `|x| <= 2^16` and `|c| <= 2^16` +//! ([`MAX_MAGNITUDE`]) every row adds less than 2^17 in magnitude, so +//! neither form can leave the range before 2^46 rows; the two can differ +//! only on aggregates over more than 2^46 (7e13) rows. +//! 4. NULL: `SUM` skips NULL values of `x + c`, which are those of `x`; +//! `COUNT(x)` counts the same rows, so the result is NULL exactly when +//! `SUM(x)` is, and `NULL + c * 0` is NULL. +//! +//! The result type is `BIGINT`, as the sum's was, and the output attribute +//! (id, name, nullability) is the aggregate item's own, now computed by a +//! projection over the aggregate. + +use std::sync::Arc; + +use krishiv_common::error::KrishivError; +use krishiv_functions::registry::{Lookup, builtins}; +use krishiv_functions::signature::SparkProfile; +use krishiv_plan::{ + AttrId, BoundColumn, Builtin, Expr, ExprNode, FunctionId, FunctionKind, Literal, LogicalPlan, + PlanNode, ResolvedExpr, ResolvedFunction, +}; +use krishiv_types::DataType; + +use crate::dag; +use crate::expr::{ + call, column, data_type, has_aggregate, has_outer_reference, has_subquery, is_deterministic, + output_of, same, +}; +use crate::restrict::{MAX_ID, max_id}; + +/// The largest magnitude of the column and of the constant (2^16): see the +/// module documentation, condition 3. +pub(crate) const MAX_MAGNITUDE: i128 = 1 << 16; + +/// Rewrites the sums of shifted columns in every aggregate of `root`. +/// +/// # Errors +/// As [`dag::rewrite_up`]. +pub(crate) fn rewrite(root: Arc) -> Result, KrishivError> { + let mut next = max_id(&root, &mut std::collections::HashMap::new()).saturating_add(1); + dag::rewrite_up(root, &mut |p| Ok(rewrite_aggregate(p, &mut next))) +} + +/// One `sum(x ± c)` item, taken apart. +struct Shifted<'a> { + /// The column expression. + x: &'a Arc, + /// The constant, with the sign it has in the sum: `+c` or `-c`, and + /// whether the sum is `c - x` (the column is subtracted). + c: i128, + negated: bool, + /// The `sum` call. + sum: &'a ResolvedFunction, +} + +fn rewrite_aggregate(p: Arc, next: &mut u64) -> Arc { + let PlanNode::Aggregate { + input, + grouping, + aggregates, + } = &p.node + else { + return p; + }; + let shifted: Vec>> = aggregates.iter().map(shifted).collect(); + if shifted.iter().all(Option::is_none) { + return p; + } + // Every item must be a column or an alias to be passed up unchanged. + let outputs: Option> = aggregates.iter().map(|e| output_of(e)).collect(); + let Some(outputs) = outputs else { + return p; + }; + let mut kept: Vec> = Vec::new(); + let mut project: Vec> = Vec::new(); + // The `sum(x)` and `count(x)` attributes of each distinct `x`. + let mut made: Vec<(Arc, BoundColumn, BoundColumn)> = Vec::new(); + let mut fresh = |name: &str, data_type: DataType, nullable: bool| -> Option { + let id = *next; + if id > MAX_ID { + return None; + } + *next += 1; + Some(BoundColumn { + id: AttrId(id), + name: name.to_owned(), + data_type, + nullable, + }) + }; + let count_id = count_function(); + let mut extra: Vec> = Vec::new(); + for ((item, shift), out) in aggregates.iter().zip(&shifted).zip(&outputs) { + let Some(s) = shift else { + kept.push(Arc::clone(item)); + project.push(column(out)); + continue; + }; + let Some(count_id) = count_id.clone() else { + return p; + }; + let (sum_col, count_col) = match made.iter().find(|(x, _, _)| same(x, s.x)) { + Some((_, a, b)) => (a.clone(), b.clone()), + None => { + // An existing `sum(x)` item of the aggregate is reused. + let plain = plain_sum(aggregates, s.x); + let (Some(sum_col), Some(count_col)) = ( + match plain { + Some(c) => Some(c.clone()), + None => fresh("sum", DataType::Long, true), + }, + fresh("count", DataType::Long, false), + ) else { + return p; + }; + if plain.is_none() { + extra.push(alias( + sum_call(s.sum, vec![Arc::clone(s.x)]), + sum_col.clone(), + )); + } + extra.push(alias( + count_call(count_id, vec![Arc::clone(s.x)]), + count_col.clone(), + )); + made.push((Arc::clone(s.x), sum_col.clone(), count_col.clone())); + (sum_col, count_col) + } + }; + // `c * COUNT(x)`, then added to or subtracted from `SUM(x)`. + let Ok(c) = i64::try_from(s.c.abs()) else { + return p; + }; + let scaled = call( + Builtin::Multiply, + vec![ + Arc::new(Expr::literal(Literal::Long(c))), + column(&count_col), + ], + DataType::Long, + ); + let total = match (s.c < 0, s.negated) { + // c - SUM(x), with c >= 0 or c < 0 (then -(|c| COUNT) - SUM). + (false, true) => call( + Builtin::Subtract, + vec![scaled, column(&sum_col)], + DataType::Long, + ), + (true, true) => call( + Builtin::Subtract, + vec![ + call(Builtin::Negative, vec![scaled], DataType::Long), + column(&sum_col), + ], + DataType::Long, + ), + (false, false) => call(Builtin::Add, vec![column(&sum_col), scaled], DataType::Long), + (true, false) => call( + Builtin::Subtract, + vec![column(&sum_col), scaled], + DataType::Long, + ), + }; + project.push(alias(total, (*out).clone())); + } + // A `sum(x)` item that was reused stays in `kept` (it was not a shifted + // sum); the new aggregates follow it. + kept.extend(extra); + let aggregate = Arc::new(LogicalPlan::new(PlanNode::Aggregate { + input: Arc::clone(input), + grouping: grouping.clone(), + aggregates: kept, + })); + let mut out = LogicalPlan::new(PlanNode::Project { + input: aggregate, + exprs: project, + }); + out.origin = p.origin; + Arc::new(out) +} + +/// `e` as `sum(x ± c)`, when the module's conditions hold. +fn shifted(e: &Arc) -> Option> { + let ExprNode::Resolved(ResolvedExpr::Alias { expr, .. }) = &e.node else { + return None; + }; + let ExprNode::Resolved(ResolvedExpr::Function(sum)) = &expr.node else { + return None; + }; + if sum.id.name() != "sum" + || sum.kind != FunctionKind::Aggregate + || sum.distinct + || sum.filter.is_some() + || sum.data_type != DataType::Long + { + return None; + } + let [arg] = sum.args.as_slice() else { + return None; + }; + let ExprNode::Resolved(ResolvedExpr::Function(add)) = &arg.node else { + return None; + }; + let FunctionId::Builtin(op @ (Builtin::Add | Builtin::Subtract)) = add.id else { + return None; + }; + let [l, r] = add.args.as_slice() else { + return None; + }; + // Which operand is the constant. + let (x, c, constant_first) = match (literal_value(l), literal_value(r)) { + (None, Some(c)) => (l, c, false), + (Some(c), None) => (r, c, true), + _ => return None, + }; + let t = add.data_type.clone(); + if !integral(&t) + || data_type(x).as_ref() != Some(&t) + || data_type(l).as_ref() != Some(&t) + || data_type(r).as_ref() != Some(&t) + || !is_deterministic(x) + || has_subquery(x) + || has_outer_reference(x) + || has_aggregate(x) + || c.abs() > MAX_MAGNITUDE + { + return None; + } + // The signed constant of `x + k`: `+c`, `-c` for `x - c`; `c - x` is + // `c` with the column negated. + let (k, negated) = match (op, constant_first) { + (Builtin::Add, _) => (c, false), + (_, false) => (-c, false), + (_, true) => (c, true), + }; + let (lo, hi) = bounds(x)?; + if lo < -MAX_MAGNITUDE || hi > MAX_MAGNITUDE { + return None; + } + // The values of the addition, per row, fit its type. + let (v_lo, v_hi) = if negated { + (k - hi, k - lo) + } else { + (lo + k, hi + k) + }; + let (t_lo, t_hi) = type_range(&t)?; + if v_lo < t_lo || v_hi > t_hi { + return None; + } + Some(Shifted { + x, + c: k, + negated, + sum, + }) +} + +fn integral(t: &DataType) -> bool { + matches!( + t, + DataType::Byte | DataType::Short | DataType::Integer | DataType::Long + ) +} + +/// The range of an integral type. +fn type_range(t: &DataType) -> Option<(i128, i128)> { + Some(match t { + DataType::Byte => (i128::from(i8::MIN), i128::from(i8::MAX)), + DataType::Short => (i128::from(i16::MIN), i128::from(i16::MAX)), + DataType::Integer => (i128::from(i32::MIN), i128::from(i32::MAX)), + DataType::Long => (i128::from(i64::MIN), i128::from(i64::MAX)), + _ => return None, + }) +} + +fn literal_value(e: &Expr) -> Option { + match &e.node { + ExprNode::Literal(Literal::Byte(v)) => Some(i128::from(*v)), + ExprNode::Literal(Literal::Short(v)) => Some(i128::from(*v)), + ExprNode::Literal(Literal::Integer(v)) => Some(i128::from(*v)), + ExprNode::Literal(Literal::Long(v)) => Some(i128::from(*v)), + _ => None, + } +} + +/// The values an integral expression can take, from the types of its +/// columns: a column's type range, through casts to a type that holds +/// that range (so the cast neither fails nor wraps). +fn bounds(e: &Expr) -> Option<(i128, i128)> { + match &e.node { + ExprNode::Resolved(ResolvedExpr::Column(c)) => type_range(&c.data_type), + ExprNode::Cast { expr, to, .. } => { + let (lo, hi) = bounds(expr)?; + let (t_lo, t_hi) = type_range(to)?; + (t_lo <= lo && hi <= t_hi).then_some((lo, hi)) + } + _ => None, + } +} + +/// The output attribute of an item `sum(x) AS a` already in `aggregates`. +fn plain_sum<'a>(aggregates: &'a [Arc], x: &Arc) -> Option<&'a BoundColumn> { + aggregates.iter().find_map(|e| { + let ExprNode::Resolved(ResolvedExpr::Alias { expr, output }) = &e.node else { + return None; + }; + let ExprNode::Resolved(ResolvedExpr::Function(f)) = &expr.node else { + return None; + }; + let plain = f.id.name() == "sum" + && f.kind == FunctionKind::Aggregate + && !f.distinct + && f.filter.is_none() + && f.data_type == DataType::Long + && matches!(f.args.as_slice(), [a] if same(a, x)); + plain.then_some(output) + }) +} + +fn alias(expr: Arc, output: BoundColumn) -> Arc { + Arc::new(Expr::new(ExprNode::Resolved(ResolvedExpr::Alias { + expr, + output, + }))) +} + +fn sum_call(like: &ResolvedFunction, args: Vec>) -> Arc { + Arc::new(Expr::new(ExprNode::Resolved(ResolvedExpr::Function( + ResolvedFunction { + args, + ..like.clone() + }, + )))) +} + +fn count_call(id: FunctionId, args: Vec>) -> Arc { + Arc::new(Expr::new(ExprNode::Resolved(ResolvedExpr::Function( + ResolvedFunction { + id, + kind: FunctionKind::Aggregate, + args, + distinct: false, + filter: None, + data_type: DataType::Long, + nullable: false, + deterministic: true, + }, + )))) +} + +/// The registry's `count`. +fn count_function() -> Option { + let profile = SparkProfile::ALL.into_iter().max()?; + match builtins().lookup("count", profile) { + Lookup::Found(def) => Some(FunctionId::Registry { + name: def.name.to_owned(), + id: def.id, + }), + _ => None, + } +} diff --git a/crates/krishiv-optimizer/tests/it/main.rs b/crates/krishiv-optimizer/tests/it/main.rs index adc073934..e1191d70e 100644 --- a/crates/krishiv-optimizer/tests/it/main.rs +++ b/crates/krishiv-optimizer/tests/it/main.rs @@ -11,5 +11,6 @@ mod join_order; mod props; mod rules; +mod sum_rewrite; mod support; mod tpch; diff --git a/crates/krishiv-optimizer/tests/it/sum_rewrite.rs b/crates/krishiv-optimizer/tests/it/sum_rewrite.rs new file mode 100644 index 000000000..18c9fbc99 --- /dev/null +++ b/crates/krishiv-optimizer/tests/it/sum_rewrite.rs @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: Apache-2.0 +//! `SUM(x + c)` as `SUM(x) + c * COUNT(x)`: the shapes it applies to and +//! each condition that keeps it away (see `sum_rewrite.rs`). The values are +//! checked against the unrewritten plan on the executor, in +//! `krishiv-exec`'s planner tests. + +use krishiv_optimizer::optimize; +use krishiv_plan::analyzer::{MemoryCatalog, TableColumn}; + +use crate::support; + +/// `s(ti tinyint, si smallint, i int, l bigint, f double, d decimal(10,2), g int)`. +fn catalog() -> MemoryCatalog { + let col = |name: &str, t: &str| TableColumn { + name: name.to_owned(), + data_type: krishiv_types::parse_data_type(t).unwrap(), + nullable: true, + }; + MemoryCatalog::new("spark_catalog").with_table( + &["default"], + "s", + vec![ + col("ti", "tinyint"), + col("si", "smallint"), + col("i", "int"), + col("l", "bigint"), + col("f", "double"), + col("d", "decimal(10,2)"), + col("g", "int"), + ], + None, + ) +} + +/// The optimised plan of `sql`, as text. +fn plan(sql: &str) -> String { + let ctx = support::ctx_over(catalog()); + let resolved = support::resolve(sql, &ctx); + let optimized = optimize(&resolved).unwrap(); + assert_eq!( + optimized.root().resolved_output(), + resolved.root().resolved_output(), + "{sql}: the output keeps its attributes (id, name, type, nullability)" + ); + let again = optimize(&optimized).unwrap(); + assert!( + again.structurally_eq(&optimized), + "{sql}: a fixed point\n{}", + again.root() + ); + optimized.root().to_string() +} + +/// The line of the plan that prints the aggregate's computations. +fn aggregate_line(text: &str) -> &str { + text.lines() + .find(|l| { + l.trim_start_matches(['+', '-', ' ']) + .starts_with("Aggregate") + }) + .unwrap_or_else(|| panic!("no aggregate in\n{text}")) +} + +fn rewritten(sql: &str) -> bool { + let text = plan(sql); + let has_count = text.contains("count("); + // A rewritten aggregate computes the shifted sums from one sum and one + // count; the originals are gone. + assert!( + has_count || !text.contains("1L *"), + "{sql}: no count without a product\n{text}" + ); + has_count +} + +#[test] +fn narrow_columns_with_a_small_constant_are_rewritten() { + // Spark types `smallint + 1` as an `int` addition over a cast column. + let text = plan("SELECT SUM(si + 1) FROM s"); + assert!(text.contains("sum(CAST(si#1 AS INT))"), "{text}"); + assert!(text.contains("count(CAST(si#1 AS INT))"), "{text}"); + assert!(!text.contains("(CAST(si#1 AS INT) + 1)"), "{text}"); + for sql in [ + "SELECT SUM(si + 1) FROM s", + "SELECT SUM(1 + si) FROM s", + "SELECT SUM(si - 2) FROM s", + "SELECT SUM(2 - si) FROM s", + "SELECT SUM(ti + 100) FROM s", + "SELECT SUM(si + -5) FROM s", + "SELECT SUM(si - -5) FROM s", + "SELECT SUM(5 - si) FROM s", + "SELECT SUM(si + 65536) FROM s", + "SELECT SUM(si - 65536) FROM s", + "SELECT SUM(si + 0) FROM s", + "SELECT SUM(CAST(si AS BIGINT) + 1) FROM s", + "SELECT SUM(CAST(ti AS INT) + 7) FROM s", + "SELECT g, SUM(si + 1) FROM s GROUP BY g", + "SELECT g, SUM(si + 1) FROM s GROUP BY g HAVING SUM(si + 1) > 3 ORDER BY g", + ] { + assert!(rewritten(sql), "{sql}\n{}", plan(sql)); + } +} + +#[test] +fn many_shifted_sums_share_one_sum_and_one_count() { + let items: Vec = (0..90).map(|k| format!("SUM(si + {k})")).collect(); + let sql = format!("SELECT SUM(si), {} FROM s", items.join(", ")); + let text = plan(&sql); + // The aggregate computes `sum(si)`, and for the 90 shifted sums one + // `sum` and one `count` of the column. + let aggregate = aggregate_line(&text); + assert_eq!( + aggregate.matches("count(CAST(si#1 AS INT))").count(), + 1, + "{text}" + ); + assert_eq!( + aggregate.matches("sum(CAST(si#1 AS INT))").count(), + 1, + "{text}" + ); + assert_eq!(aggregate.matches("sum(si#1)").count(), 1, "{text}"); +} + +#[test] +fn a_sum_of_the_column_already_there_is_reused() { + let text = plan("SELECT SUM(CAST(si AS INT)), SUM(si + 1) FROM s"); + // The aggregate's own `sum` serves both items. + assert_eq!( + aggregate_line(&text) + .matches("sum(CAST(si#1 AS INT))") + .count(), + 1, + "{text}" + ); + assert!(text.contains("count(CAST(si#1 AS INT))"), "{text}"); +} + +#[test] +fn conditions_that_keep_the_sum_as_it_is() { + for (sql, why) in [ + // `INT_MAX + 1` overflows per row: Spark raises or wraps. + ("SELECT SUM(i + 1) FROM s", "an int column can overflow"), + ("SELECT SUM(i - 1) FROM s", "an int column can overflow"), + ("SELECT SUM(l + 1) FROM s", "a bigint column can overflow"), + // A `TINYINT` stays a `TINYINT`: `127 + 1Y` overflows per row, as + // `32767 + 1S` does for a `SMALLINT`. + ( + "SELECT SUM(ti + 1Y) FROM s", + "a tinyint addition can overflow per row", + ), + ( + "SELECT SUM(ti - -1Y) FROM s", + "a tinyint addition can overflow per row", + ), + ( + "SELECT SUM(1Y - ti) FROM s", + "a tinyint subtraction can overflow per row", + ), + ( + "SELECT SUM(si + 1S) FROM s", + "a smallint addition can overflow per row", + ), + ( + "SELECT SUM(si + 65537) FROM s", + "the constant is past the bound", + ), + ( + "SELECT SUM(si + 100000) FROM s", + "the constant is past the bound", + ), + ( + "SELECT SUM(CAST(i AS BIGINT) + 1) FROM s", + "an int column's accumulation bound is too wide", + ), + ( + "SELECT SUM(f + 1.5) FROM s", + "floating-point sums are not associative", + ), + ("SELECT SUM(si + 0.5) FROM s", "a decimal addition"), + ("SELECT SUM(d + 1) FROM s", "a decimal addition"), + ( + "SELECT SUM(DISTINCT si + 1) FROM s", + "DISTINCT counts each value once", + ), + ( + "SELECT SUM(si + 1) FILTER (WHERE g > 1) FROM s", + "FILTER restricts both sides", + ), + ("SELECT SUM(si + ti) FROM s", "no constant"), + ("SELECT SUM(si * 2) FROM s", "not an addition"), + ("SELECT SUM(si + si) FROM s", "no constant"), + ("SELECT SUM(si + g) FROM s", "no constant"), + ("SELECT SUM(si) FROM s", "nothing added"), + ( + "SELECT SUM(g + 1) FROM (SELECT g FROM s)", + "an int column can overflow", + ), + ( + "SELECT AVG(si + 1) FROM s", + "only SUM is rewritten (AVG would follow SUM and COUNT)", + ), + ] { + assert!(!rewritten(sql), "{sql} ({why})\n{}", plan(sql)); + } +} + +#[test] +fn an_expression_over_the_sum_is_left_as_it_is() { + // The item is `sum(..) * 2`, not a plain sum. + let text = plan("SELECT SUM(si + 1) * 2 FROM s"); + assert!(!text.contains("count("), "{text}"); +} + +#[test] +fn aggregates_in_subqueries_are_rewritten_too() { + let text = plan("SELECT g FROM s WHERE g > (SELECT SUM(si + 1) FROM s)"); + assert!(text.contains("count(CAST(si"), "{text}"); +} diff --git a/crates/krishiv-plan/CLAUDE.md b/crates/krishiv-plan/CLAUDE.md index 8797166fd..6e709c1cc 100644 --- a/crates/krishiv-plan/CLAUDE.md +++ b/crates/krishiv-plan/CLAUDE.md @@ -50,7 +50,17 @@ Paths are relative to this crate. `PlanNode::Window`s (Spark's `ExtractWindowExpressions`); a `HAVING` over an aggregate with windows filters below them. Window goldens: `tests/scripts/gen_window_goldens.py` → `tests/fixtures/spark-4.2.0/window-goldens.json`. - Analyzer goldens come from a real Spark run: `tests/scripts/gen_analyzer_goldens.py` → - `tests/fixtures/spark-4.2.0/analyzer-goldens.json`. + `tests/fixtures/spark-4.2.0/analyzer-goldens.json`; the constant-folding and ORDER BY-over-aggregate cases are a + separate fixture (`--section folding --views`, safe on the shared oracle) `analyzer-folding-goldens.json`. +- Constant arguments (`round`'s scale, `date_part`'s field, `LIMIT`): `analyzer/fold.rs` folds what Spark's + `foldable` allows through the kernels the executor runs (`fold_ops.rs`, on `krishiv_kernels::Baseline`: one loop per + kernel instead of nine, which keeps the binary small) and raises what folding raises, at the + argument. A function is folded only if it is deterministic and in the argument-pure families + (`krishiv_functions::scalar::is_argument_pure`: string, math, arithmetic; datetime/session/hash read session + state). `first`/`last` match a boolean `Literal` and do not fold (`CallTypes::is_literal`). +- Over an aggregate, `ORDER BY`/`HAVING` expressions are matched to grouping and output expressions by + `semantic_key` (Spark's `semanticEquals`: commutative operands sorted, `a > b` as `b < a`); a memo keyed by + address must never see an expression that is dropped (`group_substitute` keys probes with a fresh memo). - `#![forbid(unsafe_code)]`. - No `unwrap`/`expect`/`panic` in library code; errors carry a Spark error class + SQLSTATE. diff --git a/crates/krishiv-plan/src/analyzer/coerce.rs b/crates/krishiv-plan/src/analyzer/coerce.rs index f0d0d372c..e7bb2c9dd 100644 --- a/crates/krishiv-plan/src/analyzer/coerce.rs +++ b/crates/krishiv-plan/src/analyzer/coerce.rs @@ -669,12 +669,47 @@ pub(super) fn inputs( operator_types(builtin, args, call.ansi(), call.decimal_loss()).map(|t| t.casts) } _ => match inputs.expected(call) { - Some(types) => declared(&types, args), + Some(types) => { + let casts = declared(&types, args)?; + legacy_string_counts(&types, args, call)?; + Ok(casts) + } None => Ok(vec![None; args.len()]), }, } } +/// Without ANSI, a string takes the place of a day count (`date_add(d, +/// '1')`, the collection `INT`, `SMALLINT`, `TINYINT`) only when it is +/// foldable: `date_add(d, s)` over a column is `UNEXPECTED_INPUT_TYPE` +/// (checked against a Spark 4.2 run, with `'1' || '2'` and `upper('1')` +/// accepted). +fn legacy_string_counts( + types: &[InputType], + args: &[Arg<'_>], + call: &CallTypes<'_>, +) -> Result<(), Mismatch> { + if call.ansi() { + return Ok(()); + } + for (i, a) in args.iter().enumerate() { + let want = types.get(i).or(types.last()).unwrap_or(&InputType::Any); + let days = matches!( + want, + InputType::OneOf(t) if t == &[DataType::Integer, DataType::Short, DataType::Byte] + ); + if days && a.ty == Some(&DataType::String) && call.constant(i).is_none() { + return Err(Mismatch::Unexpected { + arg: i, + param: i, + ty: a.ty.cloned(), + required: want.sql(), + }); + } + } + Ok(()) +} + /// The casts of `args` to the type all of `meet` (which includes `args`) /// share. fn common_casts( diff --git a/crates/krishiv-plan/src/analyzer/exprs.rs b/crates/krishiv-plan/src/analyzer/exprs.rs index 045f9b344..07ae55f6b 100644 --- a/crates/krishiv-plan/src/analyzer/exprs.rs +++ b/crates/krishiv-plan/src/analyzer/exprs.rs @@ -546,13 +546,14 @@ impl Resolver<'_> { deterministic: entry.deterministic, }; let expr = rebuilt(ExprNode::Resolved(ResolvedExpr::Function(call))); + let shown = self.call_shown(&f.name, &expr, kids, &call_kids); Bound { agg: if entry.kind == FunctionKind::Aggregate && !window_fn { Some(e.origin) } else { agg }, - shown: shown_call(&expr, kids, &call_kids), + shown, expr, ..keep(ty) } @@ -680,14 +681,16 @@ impl Resolver<'_> { } let constants: Vec> = kids .iter() - .map(|k| fold::constant(&k.expr, self.ctx.conf.ansi)) + .map(|k| self.fold(&k.expr, self.ctx.conf.ansi)) .collect(); + let literals: Vec = kids.iter().map(|k| fold::is_literal(&k.expr)).collect(); // Rendered only if a rule's error quotes an argument. let sql = |i: usize| kids.get(i).map(|k| pretty(&k.shown())); let given: Vec = kids.iter().map(|k| k.ty.clone()).collect(); let ansi = self.ctx.conf.ansi; let loss = self.ctx.conf.decimal_precision_loss; let call = CallTypes::new(&given, &constants) + .with_literals(&literals) .with_sql(&sql) .with_ansi(ansi) .with_decimal_loss(loss); @@ -703,11 +706,91 @@ impl Resolver<'_> { .collect(); let types: Vec = call_kids.iter().map(|k| k.ty.clone()).collect(); let call = CallTypes::new(&types, &constants) + .with_literals(&literals) .with_sql(&sql) .with_ansi(ansi) .with_decimal_loss(loss); - let ty = (entry.result)(&call).map_err(|err| AnalysisError::new(err, e.origin))?; - Ok((call_kids, ty)) + let ty = (entry.result)(&call).map_err(|err| { + // An error folding an argument is Spark's, cited at the argument. + let origin = constants + .iter() + .zip(kids) + .find_map(|(c, k)| match c { + Some(Constant::Error(folded)) if *folded == err => Some(k.expr.origin), + _ => None, + }) + .unwrap_or(e.origin); + AnalysisError::new(err, origin) + })?; + Ok((Self::folded_ntile(entry, &constants, call_kids), ty)) + } + + /// `ntile`'s bucket count as the literal it folds to (`ntile(1 + 1)`): + /// the window operator reads a literal. The rule above checked it is an + /// `int` constant. + #[inline(never)] + fn folded_ntile( + entry: &FunctionEntry, + constants: &[Option], + mut kids: Vec, + ) -> Vec { + if entry.id.name() == "ntile" + && let (Some(Some(Constant::Integral(n))), Some(k)) = + (constants.first(), kids.first_mut()) + && let Ok(n) = i32::try_from(*n) + { + k.expr = Arc::new( + Expr::new(ExprNode::Literal(Literal::Integer(n))).with_origin(k.expr.origin), + ); + } + kids + } + + /// The shown form of the call `expr` (see [`shown_call`]); `date_add(d, + /// ' 12 ')` and `date_add(d, '1' || '2')` without ANSI show the day count + /// as an integer (`date_add(d, 12)`): Spark folds the string it casts to + /// `INT`. Out of line: it is on the path of every call. + #[inline(never)] + fn call_shown( + &self, + name: &str, + expr: &Expr, + kids: &[Bound], + cast: &[Bound], + ) -> Option> { + let days = self.legacy_day_count(name, kids); + shown_call(expr, days.as_deref().unwrap_or(kids), cast) + } + + /// The value of `e` as a constant (`fold::constant`) under this + /// session's settings, with `ansi` for the arithmetic: shared with + /// every other fold of the pass. + pub(super) fn fold(&self, e: &Arc, ansi: bool) -> Option { + let conf = fold::Conf::new(ansi, self.ctx.conf.decimal_precision_loss, self.ctx.profile); + fold::constant(e, conf, &mut self.folds.borrow_mut()) + } + + fn legacy_day_count(&self, name: &str, kids: &[Bound]) -> Option> { + if self.ctx.conf.ansi + || !["date_add", "dateadd", "date_sub"] + .iter() + .any(|n| name.eq_ignore_ascii_case(n)) + { + return None; + } + let kid = kids.get(1)?; + if kid.ty.data_type != Some(DataType::String) { + return None; + } + let Some(Constant::String(text)) = self.fold(&kid.expr, false) else { + return None; + }; + let days = krishiv_functions::registry::legacy_day_count(&text)?; + let mut shown = kids.to_vec(); + shown[1].shown = Some(Arc::new(Expr::new(ExprNode::Literal(Literal::String( + days.to_string(), + ))))); + Some(shown) } pub(super) fn implicit_cast(&self, b: &Bound, to: Option) -> Bound { @@ -1520,7 +1603,9 @@ fn pretty_node(x: &Expr, k: &[&str]) -> String { } ExprNode::Star(_) => "*".to_owned(), ExprNode::Window(w) => pretty_window(w, k), - ExprNode::Function(FunctionCall { name, distinct, .. }) => call(name, None, *distinct, k), + ExprNode::Function(FunctionCall { name, distinct, .. }) => { + call(name, Builtin::from_name(name), *distinct, k) + } ExprNode::Resolved(ResolvedExpr::Function(f)) => { let op = match &f.id { FunctionId::Builtin(b) => Some(*b), @@ -1691,8 +1776,42 @@ fn pretty_literal(v: &Literal) -> String { } } +/// How Spark's canonicalisation (`Expression.canonicalized`) orders a call's +/// operands. +#[derive(Clone, Copy, PartialEq, Eq)] +enum Canon { + /// Operands in order. + Ordered, + /// `+ * AND OR`: nested calls of the same operator are flattened and + /// the operands sorted (`greatest`/`least` and `= <=>` sort too, with + /// nothing to flatten for the latter). + Commutative { flatten: bool }, + /// `a > b` is `b < a`, `a >= b` is `b <= a`: the call is renamed and + /// its operands swapped. + Flipped(Builtin), +} + +fn canon(f: &ResolvedFunction) -> Canon { + match &f.id { + FunctionId::Builtin(Builtin::Add | Builtin::Multiply | Builtin::And | Builtin::Or) => { + Canon::Commutative { flatten: true } + } + FunctionId::Builtin(Builtin::Eq | Builtin::EqNullSafe) => { + Canon::Commutative { flatten: false } + } + FunctionId::Builtin(Builtin::Gt) => Canon::Flipped(Builtin::Lt), + FunctionId::Builtin(Builtin::GtEq) => Canon::Flipped(Builtin::LtEq), + FunctionId::Registry { name, .. } if matches!(name.as_str(), "greatest" | "least") => { + Canon::Commutative { flatten: false } + } + _ => Canon::Ordered, + } +} + /// A semantic key: equal for expressions that compute the same value, -/// whatever their origins, column spellings or (top-level) alias. +/// whatever their origins, column spellings or (top-level) alias, and +/// canonicalised as Spark's `semanticEquals` is (commutative operands +/// sorted, `a > b` as `b < a`). pub(super) fn semantic_key(e: &Expr, memo: &mut HashMap) -> u128 { let e = match &e.node { ExprNode::Resolved(ResolvedExpr::Alias { expr, .. }) => &**expr, @@ -1710,11 +1829,19 @@ pub(super) fn semantic_key(e: &Expr, memo: &mut HashMap) -> u128 { stack.extend(kids.into_iter().map(|c| (c, false))); continue; } + let mut name = None; + let mut order = Canon::Ordered; let mut b = match &x.node { ExprNode::Resolved(ResolvedExpr::Column(c)) => format!("c{}", c.id.0), ExprNode::Resolved(ResolvedExpr::OuterColumn(c)) => format!("o{}", c.id.0), ExprNode::Resolved(ResolvedExpr::Function(f)) => { - format!("f{}:{:?}:{}", f.id.name(), f.kind, f.distinct) + order = canon(f); + let id = match order { + Canon::Flipped(to) => to.name(), + _ => f.id.name(), + }; + name = Some(f); + format!("f{id}:{:?}:{}", f.kind, f.distinct) } ExprNode::Resolved(ResolvedExpr::Alias { output, .. }) => format!("a{}", output.id.0), ExprNode::Literal(v) => format!("l{v:?}"), @@ -1741,14 +1868,80 @@ pub(super) fn semantic_key(e: &Expr, memo: &mut HashMap) -> u128 { other => format!("u{other:?}"), } .into_bytes(); - for c in kids { - b.extend_from_slice(&memo.get(&addr(c)).copied().unwrap_or(0).to_le_bytes()); + let mut hashes: Vec = Vec::new(); + match (order, name) { + (Canon::Commutative { flatten }, Some(f)) => { + // Flattening reads a nested operator's operands again for each + // way it is shared, so it stops at a bound; past it the + // operands are the call's own (equal expressions written the + // same way still match). + let mut budget = FLATTEN_BUDGET; + if !(flatten && collect_operands(x, f, memo, &mut hashes, &mut budget)) { + hashes.clear(); + hashes.extend( + kids.iter() + .map(|c| memo.get(&addr(*c)).copied().unwrap_or(0)), + ); + } + hashes.sort_unstable(); + } + (Canon::Flipped(_), _) => { + hashes.extend( + kids.iter() + .rev() + .map(|c| memo.get(&addr(*c)).copied().unwrap_or(0)), + ); + } + _ => hashes.extend( + kids.iter() + .map(|c| memo.get(&addr(*c)).copied().unwrap_or(0)), + ), + } + for h in hashes { + b.extend_from_slice(&h.to_le_bytes()); } memo.insert(addr(x), XxHash3_128::oneshot(&b)); } memo.get(&addr(e)).copied().unwrap_or(0) } +/// The most nodes [`collect_operands`] reads for one call. +const FLATTEN_BUDGET: usize = 64; + +/// Adds the operand hashes of `x`, a call of `f`, to `out`: those of nested +/// calls of the same operator and result type are gathered too (Spark's +/// `gatherCommutative`). `false` when `budget` nodes were not enough, which +/// keeps a shared operand (a DAG that is exponentially large as a tree) from +/// being read once per path. +fn collect_operands( + x: &Expr, + f: &ResolvedFunction, + memo: &HashMap, + out: &mut Vec, + budget: &mut usize, +) -> bool { + let mut done = true; + x.for_each_child(&mut |c| { + if !done { + return; + } + let Some(left) = budget.checked_sub(1) else { + done = false; + return; + }; + *budget = left; + if let ExprNode::Resolved(ResolvedExpr::Function(g)) = &c.node + && g.id == f.id + && g.data_type == f.data_type + { + done = collect_operands(c, g, memo, out, budget); + } else { + out.push(memo.get(&addr(&**c)).copied().unwrap_or(0)); + } + }); + done +} + /// A frame bound's kind, for [`semantic_key`] (an offset's value is a /// child). const fn frame_shape(b: &crate::FrameBound) -> u8 { diff --git a/crates/krishiv-plan/src/analyzer/fold.rs b/crates/krishiv-plan/src/analyzer/fold.rs index 25c0289ce..e456069b9 100644 --- a/crates/krishiv-plan/src/analyzer/fold.rs +++ b/crates/krishiv-plan/src/analyzer/fold.rs @@ -1,41 +1,149 @@ // SPDX-License-Identifier: Apache-2.0 //! The value of a constant argument, for the functions whose typing reads -//! it (`round`'s scale, `extract`'s field). +//! it (`round`'s scale, `extract`'s field, a `LIMIT`). //! //! Spark folds a foldable argument before it types the call, so -//! `round(x, CAST(1.5 AS FLOAT))` has scale 1. Literals and casts of -//! literals to a number fold here, through the same cast kernels that -//! evaluate them (so overflow, malformed input and ANSI/legacy behaviour -//! are the kernels'). A cast that fails folds to [`Constant::Error`]: the -//! function that reads the value raises it, any other ignores it, so an -//! unselected branch never raises. +//! `round(x, CAST(1.5 AS FLOAT))` has scale 1 and so does +//! `round(x, 0.5 + 0.5)`. Foldable here means what Spark's `foldable` means +//! for the expressions this folder evaluates: literals (dates included); +//! casts of foldable values to a number, a string or a date; `+ - * / % div` +//! and unary `-`; comparisons, `AND`/`OR`/`NOT`, `IS [NOT] NULL`; +//! `CASE`/`if`/`coalesce`; `concat`; the deterministic string, math and +//! arithmetic functions (`abs`, `length`, `upper`, ...) of foldable +//! arguments; and the day and field datetime functions (`date_add`, `year`, +//! `extract`, ...) of foldable date arguments. Anything else (a column, a +//! nondeterministic call, a datetime function over a timestamp, which reads +//! the session time zone, or the clock and session functions, which read +//! the query start or the user) is not a constant. +//! +//! A folded date has no [`Constant`]: it is not a value the typing rules +//! read, so it stays unfolded to them (not an error), while the calls that +//! read a folded date (`year`, `date_add`, a `LIMIT` over one) still +//! evaluate. Datetime functions over timestamps stay unfolded too: the +//! folder has no session time zone, so a timestamp result could differ from +//! the executor's. +//! +//! Evaluation runs through the same kernels the executor uses (so overflow, +//! division by zero, malformed input and ANSI/legacy behaviour are the +//! kernels'). A call that fails folds to [`Constant::Error`]: the function +//! that reads the value raises it, any other ignores it, so an unselected +//! branch never raises. `CASE`, `if` and `coalesce` evaluate lazily, as +//! Spark's do. +use std::collections::HashMap; use std::sync::Arc; use arrow_array::cast::AsArray; use arrow_array::types::{Int8Type, Int16Type, Int32Type, Int64Type}; use arrow_array::{ - Array, ArrayRef, BooleanArray, Decimal128Array, Float32Array, Float64Array, Int8Array, - Int16Array, Int32Array, Int64Array, StringArray, new_null_array, + Array, ArrayRef, BooleanArray, Date32Array, Decimal128Array, Float32Array, Float64Array, + Int8Array, Int16Array, Int32Array, Int64Array, StringArray, new_null_array, }; use arrow_schema::DataType as ArrowType; use krishiv_common::error::{ErrorClass, KrishivError}; +use krishiv_common::stack::{STEP, on_big_stack}; +use krishiv_functions::scalar::{Arg, BindArg, BindOptions, bind_scalar, is_argument_pure}; +use krishiv_functions::signature::FunctionKind; use krishiv_kernels::cast::{CastMode as KernelMode, CastOptions, FixedOffset, cast}; +use krishiv_kernels::{KernelCtx, SparkVersion}; use krishiv_types::DataType; -use super::Constant; -use crate::{CastMode, Expr, ExprNode, Literal}; +use super::fold_ops; +use super::{Constant, SparkProfile}; +use crate::{ + Builtin, CastMode, Expr, ExprNode, FunctionId, Literal, ResolvedExpr, ResolvedFunction, +}; -/// The value of `e` as a constant, when it is a literal or a cast of one. -pub(super) fn constant(e: &Expr, ansi: bool) -> Option { - let folded = match &e.node { +/// The session settings folding reads. +#[derive(Debug, Clone, Copy)] +pub(super) struct Conf { + /// `spark.sql.ansi.enabled`. + pub ansi: bool, + /// `spark.sql.decimalOperations.allowPrecisionLoss`. + pub decimal_loss: bool, + /// The kernels' context: the session's Spark line, whose error classes + /// and messages the kernels raise. + pub kernel: KernelCtx, +} + +impl Conf { + /// The settings of a session on `profile`. + pub(super) fn new(ansi: bool, decimal_loss: bool, profile: SparkProfile) -> Self { + // The kernels model 4.0 as their oldest line; 3.5 behaves as it. + let version = match profile { + SparkProfile::V3_5 | SparkProfile::V4_0 => SparkVersion::V4_0, + SparkProfile::V4_1 => SparkVersion::V4_1, + _ => SparkVersion::V4_2, + }; + Self { + ansi, + decimal_loss, + kernel: KernelCtx::new().with_spark_version(version), + } + } +} + +/// One folded subexpression: `None` when it is not foldable, else its +/// one-row value or the error evaluating it raises. +type Folded = Option>; + +/// What a folded node's value depends on besides the node: its address +/// and the settings it was folded under. +type Key = (usize, bool, bool, SparkVersion); + +/// The values of the expressions folded so far in one resolver pass, by +/// node address. Folding a call folds its arguments, and `Resolver::expr` +/// shares subtrees, so without a memo `e = f(e', e')` folds `e'` twice at +/// every level (exponential in the depth), and each enclosing call folds +/// its arguments again. Each entry keeps its node alive, so an address is +/// never reused for another node while the memo lives. +#[derive(Debug, Default)] +pub(super) struct Memo { + map: HashMap, Folded)>, + depth: usize, +} + +/// Whether `e` is a plain literal (what `first(x, true)` requires of its +/// flag, where Spark matches `Literal` and does not fold). +pub(super) const fn is_literal(e: &Expr) -> bool { + matches!(e.node, ExprNode::Literal(_)) +} + +/// The value of `e` as a constant, when it is foldable. A folded date (or +/// timestamp, which never folds here) has no [`Constant`]: it is not a +/// value the typing rules read, so it is not a constant rather than an +/// error, while the calls evaluated from it still fold. +pub(super) fn constant(e: &Arc, conf: Conf, memo: &mut Memo) -> Option { + match &e.node { ExprNode::Literal(Literal::Null(_)) => return Some(Constant::Null), ExprNode::Literal(Literal::Boolean(v)) => return Some(Constant::Boolean(*v)), ExprNode::Literal(Literal::String(v)) => return Some(Constant::String(v.clone())), - ExprNode::Literal(_) | ExprNode::Cast { .. } => fold(e, ansi)?, - _ => return None, + _ => {} + } + let folded = fold(e, conf, memo)?; + let array = match folded { + Err(e) => return Some(Constant::Error(e)), + Ok(a) => a, }; - Some(match folded.and_then(|a| value(&a, ansi)) { + if array.null_count() > 0 || array.data_type() == &ArrowType::Null { + return Some(Constant::Null); + } + if !matches!( + array.data_type(), + ArrowType::Null + | ArrowType::Boolean + | ArrowType::Int8 + | ArrowType::Int16 + | ArrowType::Int32 + | ArrowType::Int64 + | ArrowType::Utf8 + | ArrowType::Float32 + | ArrowType::Float64 + | ArrowType::Decimal128(..) + ) { + return None; + } + Some(match value(&array, conf.ansi) { Ok(c) => c, Err(e) => Constant::Error(e), }) @@ -53,6 +161,7 @@ fn value(a: &ArrayRef, ansi: bool) -> Result { ArrowType::Int16 => Constant::Integral(i64::from(a.as_primitive::().value(0))), ArrowType::Int32 => Constant::Integral(i64::from(a.as_primitive::().value(0))), ArrowType::Int64 => Constant::Integral(a.as_primitive::().value(0)), + ArrowType::Utf8 => Constant::String(a.as_string::().value(0).to_owned()), ArrowType::Float32 | ArrowType::Float64 | ArrowType::Decimal128(..) => { let int = cast( a.as_ref(), @@ -92,51 +201,314 @@ fn unsupported() -> KrishivError { .into() } -/// `e` as a one-row array: `None` when it is not a literal, a cast of one -/// to a number, or a cast the kernels do not implement. -fn fold(e: &Expr, ansi: bool) -> Option> { - match &e.node { - ExprNode::Literal(l) => literal(l).map(Ok), - ExprNode::Cast { expr, to, mode: m } => { - if !matches!( - to, - DataType::Byte - | DataType::Short - | DataType::Integer - | DataType::Long - | DataType::Float - | DataType::Double - | DataType::Decimal(_) - ) { - return None; +/// `e` as a one-row array: `None` when it is not foldable here. Every +/// `STEP` levels run on a fresh stack (see `Resolver::rel`). +fn fold(e: &Arc, conf: Conf, memo: &mut Memo) -> Folded { + memo.depth += 1; + let r = if memo.depth.is_multiple_of(STEP) { + on_big_stack(|| fold_on_stack(e, conf, memo)).unwrap_or(None) + } else { + fold_on_stack(e, conf, memo) + }; + memo.depth -= 1; + r +} + +fn fold_on_stack(e: &Arc, conf: Conf, memo: &mut Memo) -> Folded { + if let ExprNode::Literal(l) = &e.node { + return literal(l).map(Ok); + } + let key = ( + Arc::as_ptr(e) as usize, + conf.ansi, + conf.decimal_loss, + conf.kernel.spark_version(), + ); + if let Some((_, hit)) = memo.map.get(&key) { + return hit.clone(); + } + let folded = match &e.node { + ExprNode::Cast { expr, to, mode: m } => fold_cast(expr, to, *m, conf, memo), + ExprNode::Resolved(ResolvedExpr::Function(f)) => call(f, conf, memo), + _ => None, + }; + memo.map.insert(key, (Arc::clone(e), folded.clone())); + folded +} + +fn fold_cast(expr: &Arc, to: &DataType, m: CastMode, conf: Conf, memo: &mut Memo) -> Folded { + let inner = match fold(expr, conf, memo)? { + // The executor reads strings through their `Utf8` carrier too. + Ok(a) => normalized(a), + Err(e) => return Some(Err(e)), + }; + // A NULL of any type casts to a NULL of the target type. + if inner.null_count() > 0 || inner.data_type() == &ArrowType::Null { + return Some(Ok(new_null_array(&to.to_arrow(), 1))); + } + // The kernels' targets: numbers, strings and dates (no timestamp: it + // reads the session time zone, so a cast to one stays unfolded). + if !matches!( + to, + DataType::Byte + | DataType::Short + | DataType::Integer + | DataType::Long + | DataType::Float + | DataType::Double + | DataType::Decimal(_) + | DataType::String + | DataType::Date + ) { + return None; + } + let kernel_mode = match m { + CastMode::Try => KernelMode::Try, + CastMode::Legacy => KernelMode::Legacy, + CastMode::Ansi => KernelMode::Ansi, + _ => mode(conf.ansi), + }; + // The kernels' string carrier is `Utf8`: what the executor maps + // `Utf8View` to around the same call. The result stays `Utf8`, which + // the value reader and the function bindings both take as a string. + let target = to.to_arrow(); + let kernel_target = match &target { + ArrowType::Utf8View => ArrowType::Utf8, + _ => target, + }; + match cast( + inner.as_ref(), + &kernel_target, + &options(kernel_mode, &FixedOffset(0)), + ) { + Ok(a) => Some(Ok(a)), + Err(err) => { + let err = KrishivError::from(err); + (err.error_class() != ErrorClass::KrishivUnsupportedFeature).then_some(Err(err)) + } + } +} + +/// Every child of a call, folded; `None` when any is not foldable (a call +/// is foldable only if all its arguments are, whichever it evaluates). +fn kids( + f: &ResolvedFunction, + conf: Conf, + memo: &mut Memo, +) -> Option>> { + // Stops at the first argument that is not foldable (a column), so a + // deep non-constant tree costs one descent, not an evaluation. + f.args.iter().map(|a| fold(a, conf, memo)).collect() +} + +fn call(f: &ResolvedFunction, conf: Conf, memo: &mut Memo) -> Folded { + if !f.deterministic || f.distinct || f.filter.is_some() || f.kind != FunctionKind::Scalar { + return None; + } + let kids = kids(f, conf, memo)?; + match &f.id { + FunctionId::Builtin(b) => operator(*b, f, kids, conf), + FunctionId::Registry { name, .. } => registry(name, f, kids, conf), + } +} + +/// Splits the children into values, or the first error (evaluation order). +fn values(kids: Vec>) -> Result, KrishivError> { + kids.into_iter().collect() +} + +fn operator( + op: Builtin, + f: &ResolvedFunction, + kids: Vec>, + conf: Conf, +) -> Folded { + match op { + Builtin::And | Builtin::Or => return logic(op == Builtin::And, kids), + Builtin::When => return when(f, kids), + _ => {} + } + let args = match values(kids) { + Ok(a) => a, + Err(e) => return Some(Err(e)), + }; + let out = f.data_type.to_arrow(); + match (op, args.as_slice()) { + ( + Builtin::Add + | Builtin::Subtract + | Builtin::Multiply + | Builtin::Divide + | Builtin::Remainder, + [l, r], + ) => fold_ops::arithmetic(op, l, r, &out, conf.ansi, &conf.kernel.baseline()), + (Builtin::IntegralDivide, [l, r]) => { + fold_ops::integral_divide(l, r, conf.ansi, &conf.kernel.baseline()) + } + (Builtin::Negative, [a]) => fold_ops::negate(a, conf.ansi, &conf.kernel.baseline()), + (Builtin::Eq | Builtin::Lt | Builtin::LtEq | Builtin::Gt | Builtin::GtEq, [l, r]) => { + if fold_ops::is_null(l) || fold_ops::is_null(r) { + return Some(Ok(fold_ops::bool_array(None))); } - let inner = match fold(expr, ansi)? { - Ok(a) => a, - Err(e) => return Some(Err(e)), - }; - // A NULL of any type casts to a NULL of the target type. - if inner.null_count() > 0 || inner.data_type() == &ArrowType::Null { - return Some(Ok(new_null_array(&to.to_arrow(), 1))); + fold_ops::comparison(op, l, r, &conf.kernel.baseline()) + } + (Builtin::Not, [a]) => { + let v = fold_ops::boolean(a)?; + Some(Ok(fold_ops::bool_array(v.map(|b| !b)))) + } + (Builtin::IsNull, [a]) => Some(Ok(fold_ops::bool_array(Some(fold_ops::is_null(a))))), + (Builtin::IsNotNull, [a]) => Some(Ok(fold_ops::bool_array(Some(!fold_ops::is_null(a))))), + (Builtin::Concat, parts) => { + if parts.iter().any(|p| p.data_type() == &ArrowType::Null) { + return Some(Ok(new_null_array(&ArrowType::Utf8, 1))); } - let kernel_mode = match m { - CastMode::Try => KernelMode::Try, - CastMode::Legacy => KernelMode::Legacy, - CastMode::Ansi => KernelMode::Ansi, - _ => mode(ansi), - }; - match cast( - inner.as_ref(), - &to.to_arrow(), - &options(kernel_mode, &FixedOffset(0)), - ) { - Ok(a) => Some(Ok(a)), - Err(err) => { - let err = KrishivError::from(err); - (err.error_class() != ErrorClass::KrishivUnsupportedFeature).then_some(Err(err)) + fold_ops::concat(parts) + } + _ => None, + } +} + +/// Kleene `AND`/`OR`, left operand first: a decided left operand skips the +/// right one (its error is not raised). +fn logic(and: bool, kids: Vec>) -> Folded { + let [l, r] = <[_; 2]>::try_from(kids).ok()?; + let l = match l { + Ok(l) => fold_ops::boolean(&l)?, + Err(e) => return Some(Err(e)), + }; + // `false AND x` and `true OR x` are decided by the left operand. + if l == Some(!and) { + return Some(Ok(fold_ops::bool_array(l))); + } + let r = match r { + Ok(r) => fold_ops::boolean(&r)?, + Err(e) => return Some(Err(e)), + }; + let v = match (l, r) { + (_, d) if d == Some(!and) => d, + (None, _) | (_, None) => None, + _ => Some(and), + }; + Some(Ok(fold_ops::bool_array(v))) +} + +/// `CASE WHEN c1 THEN v1 ... [ELSE e]`: the first true condition's value. +fn when(f: &ResolvedFunction, kids: Vec>) -> Folded { + let mut it = kids.into_iter(); + loop { + let Some(c) = it.next() else { + return Some(Ok(new_null_array(&f.data_type.to_arrow(), 1))); + }; + let Some(v) = it.next() else { + return Some(c); + }; + let c = match c { + Ok(c) => fold_ops::boolean(&c)?, + Err(e) => return Some(Err(e)), + }; + if c == Some(true) { + return Some(v); + } + } +} + +/// The datetime functions the folder evaluates: the day arithmetic, the +/// field functions and `extract`/`date_part`. Their results over dates +/// never read the session time zone; over timestamps they do, so those +/// stay unfolded (checked at the call). The clock and session functions +/// (`current_date`, `current_timestamp`, `localtimestamp`, `current_user`, +/// ...) read the query start or the user and never fold here: the folder +/// has neither, so Spark's foldable call stays unfolded for the executor. +fn is_foldable_datetime(name: &str) -> bool { + matches!( + name.to_ascii_lowercase().as_str(), + "date_add" + | "dateadd" + | "date_sub" + | "datediff" + | "date_diff" + | "year" + | "month" + | "day" + | "dayofmonth" + | "extract" + | "date_part" + ) +} + +fn registry( + name: &str, + f: &ResolvedFunction, + kids: Vec>, + conf: Conf, +) -> Folded { + match name { + "coalesce" | "ifnull" | "nvl" => { + for k in kids { + match k { + Ok(a) if fold_ops::is_null(&a) => {} + other => return Some(other), } } + return Some(Ok(new_null_array(&f.data_type.to_arrow(), 1))); } - _ => None, + "if" => { + let [c, a, b] = <[_; 3]>::try_from(kids).ok()?; + return match c.map(|c| fold_ops::boolean(&c)) { + Ok(Some(Some(true))) => Some(a), + Ok(Some(_)) => Some(b), + Ok(None) => None, + Err(e) => Some(Err(e)), + }; + } + _ => {} + } + if !is_argument_pure(name) && !is_foldable_datetime(name) { + return None; + } + let args = match values(kids) { + Ok(a) => a, + Err(e) => return Some(Err(e)), + }; + // The folder has no session time zone, so a datetime function over a + // timestamp does not fold here (dates never read the zone). It stays + // unfolded, for the executor to evaluate once. + if is_foldable_datetime(name) + && args + .iter() + .any(|a| matches!(a.data_type(), ArrowType::Timestamp(..))) + { + return None; + } + let opts = BindOptions::new() + .with_kernel(conf.kernel) + .with_ansi(conf.ansi) + .with_decimal_precision_loss(conf.decimal_loss); + let bind: Vec = args.iter().cloned().map(BindArg::Literal).collect(); + let run = bind_scalar(name, &bind, &opts).and_then(|func| { + let call: Vec = args.into_iter().map(Arg::Scalar).collect(); + func.invoke(&call, 1) + }); + match run { + Ok(a) => Some(Ok(normalized(a))), + // A binding the kernels lack is not a constant here, not an error. + Err(e) if e.error_class() == ErrorClass::KrishivUnsupportedFeature => None, + Err(e) => Some(Err(e)), + } +} + +/// Strings as `Utf8`, the carrier folding works on. +fn normalized(a: ArrayRef) -> ArrayRef { + match a.data_type() { + ArrowType::Utf8View => { + let v = a.as_string_view(); + Arc::new(StringArray::from_iter(v.iter())) + } + ArrowType::LargeUtf8 => { + let v = a.as_string::(); + Arc::new(StringArray::from_iter(v.iter())) + } + _ => a, } } @@ -164,6 +536,7 @@ fn literal(l: &Literal) -> Option { .ok()?, ), Literal::String(v) => Arc::new(StringArray::from(vec![v.as_str()])), + Literal::Date(v) => Arc::new(Date32Array::from(vec![*v])), _ => return None, }) } @@ -175,6 +548,14 @@ mod tests { use super::*; + fn constant(e: &Expr, ansi: bool) -> Option { + super::constant( + &Arc::new(e.clone()), + Conf::new(ansi, true, SparkProfile::V4_2), + &mut Memo::default(), + ) + } + fn lit(v: Literal) -> Expr { Expr::new(ExprNode::Literal(v)) } @@ -329,14 +710,62 @@ mod tests { ); } - /// What is not a literal or a cast of one to a number is not folded. + /// Casts to `STRING` and `DATE` fold through the cast kernels: a number + /// or a date has a string, a well-formed string has a date. A folded + /// date is not a value the typing rules read, but the calls reading it + /// still fold. #[test] - fn other_expressions_are_not_constants() { - let ansi = true; + fn casts_to_string_and_date_fold() { + assert_eq!( + constant(&cast(Literal::Date(0), DataType::String), true), + string("1970-01-01") + ); assert_eq!( - constant(&cast(Literal::Integer(1), DataType::String), ansi), + constant( + &cast(Literal::String("2024-01-01".to_owned()), DataType::Date), + true + ), None ); + assert_eq!( + constant( + &named( + "year", + vec![cast( + Literal::String("2024-01-01".to_owned()), + DataType::Date + )], + DataType::Integer + ), + true + ), + Some(Constant::Integral(2024)) + ); + assert_eq!( + constant( + &named( + "length", + vec![cast(Literal::Integer(12), DataType::String)], + DataType::Integer + ), + true + ), + Some(Constant::Integral(2)) + ); + // Malformed input fails as the cast kernels fail it. + assert_eq!( + class(constant( + &cast(Literal::String("x".to_owned()), DataType::Date), + true + )), + Some(ErrorClass::CastInvalidInput) + ); + } + + /// What is neither foldable nor a literal is not a constant. + #[test] + fn other_expressions_are_not_constants() { + let ansi = true; let col = Expr::new(ExprNode::Column(crate::ColumnRef { name: vec!["a".to_owned()], plan_id: None, @@ -344,4 +773,486 @@ mod tests { assert_eq!(constant(&col, ansi), None); assert_eq!(constant(&cast_of(col, DataType::Float), ansi), None); } + + fn call(id: FunctionId, args: Vec, data_type: DataType) -> Expr { + Expr::new(ExprNode::Resolved(ResolvedExpr::Function( + ResolvedFunction { + id, + kind: FunctionKind::Scalar, + args: args.into_iter().map(Arc::new).collect(), + distinct: false, + filter: None, + data_type, + nullable: true, + deterministic: true, + }, + ))) + } + + fn op(b: Builtin, args: Vec, data_type: DataType) -> Expr { + call(FunctionId::Builtin(b), args, data_type) + } + + fn named(name: &str, args: Vec, data_type: DataType) -> Expr { + call( + FunctionId::Registry { + name: name.to_owned(), + id: 0, + }, + args, + data_type, + ) + } + + fn int(v: i32) -> Expr { + lit(Literal::Integer(v)) + } + + fn text(v: &str) -> Expr { + lit(Literal::String(v.to_owned())) + } + + fn truth(v: bool) -> Expr { + lit(Literal::Boolean(v)) + } + + fn string(v: &str) -> Option { + Some(Constant::String(v.to_owned())) + } + + /// An expression whose folding raises under ANSI: `1 / 0` over doubles. + fn failing() -> Expr { + op( + Builtin::Divide, + vec![lit(Literal::Double(1.0)), lit(Literal::Double(0.0))], + DataType::Double, + ) + } + + /// `e_n = e_(n-1) + e_(n-1)` over one shared node each: 2^n evaluations + /// without a memo, one per node with it, and a second fold of the same + /// expression (an enclosing call's) evaluates nothing again. + #[test] + fn a_shared_subtree_folds_once() { + let long = || lit(Literal::Long(1)); + let mut e = Arc::new(op(Builtin::Add, vec![long(), long()], DataType::Long)); + let depth = 200; + for _ in 0..depth { + e = Arc::new(Expr::new(ExprNode::Resolved(ResolvedExpr::Function( + ResolvedFunction { + id: FunctionId::Builtin(Builtin::Add), + kind: FunctionKind::Scalar, + args: vec![Arc::clone(&e), Arc::clone(&e)], + distinct: false, + filter: None, + data_type: DataType::Long, + nullable: false, + deterministic: true, + }, + )))); + } + let conf = Conf::new(false, true, SparkProfile::V4_2); + let mut memo = Memo::default(); + // 2 * 2^200 wraps to 0 in legacy mode: the value is the kernels'. + let first = super::constant(&e, conf, &mut memo); + assert!(first.is_some()); + assert_eq!(memo.map.len(), depth + 1, "one entry per distinct node"); + assert_eq!(super::constant(&e, conf, &mut memo), first); + assert_eq!(memo.map.len(), depth + 1); + // Another setting folds under its own entries. + let ansi = Conf::new(true, true, SparkProfile::V4_2); + let _ = super::constant(&e, ansi, &mut memo); + assert_eq!(memo.map.len(), 2 * (depth + 1)); + } + + /// The kernels raise the session's Spark line's error: `%` by zero is + /// `DIVIDE_BY_ZERO` before 4.1 and `REMAINDER_BY_ZERO` after it. + #[test] + fn folding_follows_the_session_spark_line() { + let rem = Arc::new(op( + Builtin::Remainder, + vec![int(1), int(0)], + DataType::Integer, + )); + let class = |profile| match super::constant( + &rem, + Conf::new(true, true, profile), + &mut Memo::default(), + ) { + Some(Constant::Error(e)) => e.error_class(), + other => panic!("{other:?}"), + }; + assert_eq!(class(SparkProfile::V4_0), ErrorClass::DivideByZero); + assert_eq!(class(SparkProfile::V3_5), ErrorClass::DivideByZero); + assert_eq!(class(SparkProfile::V4_1), ErrorClass::RemainderByZero); + assert_eq!(class(SparkProfile::V4_2), ErrorClass::RemainderByZero); + } + + #[test] + fn arithmetic_folds_through_the_kernels() { + let sum = |a, b| op(Builtin::Add, vec![int(a), int(b)], DataType::Integer); + let n = |v: i64| Some(Constant::Integral(v)); + assert_eq!(constant(&sum(1, 2), true), n(3)); + let nested = op( + Builtin::Multiply, + vec![sum(1, 2), int(3)], + DataType::Integer, + ); + assert_eq!(constant(&nested, true), n(9)); + // Overflow raises under ANSI and wraps in legacy mode. + assert_eq!( + class(constant(&sum(i32::MAX, 1), true)), + Some(ErrorClass::ArithmeticOverflow) + ); + assert_eq!(constant(&sum(i32::MAX, 1), false), n(i64::from(i32::MIN))); + let sub = op(Builtin::Subtract, vec![int(1), int(5)], DataType::Integer); + assert_eq!(constant(&sub, true), n(-4)); + let neg = op(Builtin::Negative, vec![int(5)], DataType::Integer); + assert_eq!(constant(&neg, true), n(-5)); + let rem = op(Builtin::Remainder, vec![int(7), int(4)], DataType::Integer); + assert_eq!(constant(&rem, true), n(3)); + let long = |v: i64| lit(Literal::Long(v)); + let div = op( + Builtin::IntegralDivide, + vec![long(7), long(2)], + DataType::Long, + ); + assert_eq!(constant(&div, true), n(3)); + // Division by zero: an error, or NULL. + assert_eq!( + class(constant(&failing(), true)), + Some(ErrorClass::DivideByZero) + ); + assert_eq!(constant(&failing(), false), Some(Constant::Null)); + // A double is the integer it truncates to. + let half = op( + Builtin::Add, + vec![lit(Literal::Double(1.5)), lit(Literal::Double(1.5))], + DataType::Double, + ); + assert_eq!(constant(&half, true), Some(Constant::Fractional(3))); + // NULL operands give NULL. + let null = op( + Builtin::Add, + vec![cast(Literal::Null(None), DataType::Integer), int(1)], + DataType::Integer, + ); + assert_eq!(constant(&null, true), Some(Constant::Null)); + let mixed = op( + Builtin::Add, + vec![int(1), lit(Literal::Long(1))], + DataType::Long, + ); + assert_eq!(constant(&mixed, true), None); + } + + #[test] + fn comparisons_and_logic_fold() { + let b = |v: bool| Some(Constant::Boolean(v)); + let lt = |x, y| op(Builtin::Lt, vec![int(x), int(y)], DataType::Boolean); + assert_eq!(constant(<(1, 2), true), b(true)); + assert_eq!(constant(<(2, 1), true), b(false)); + let with_null = op( + Builtin::Eq, + vec![lit(Literal::Null(None)), int(1)], + DataType::Boolean, + ); + assert_eq!(constant(&with_null, true), Some(Constant::Null)); + assert_eq!( + constant( + &op(Builtin::Not, vec![truth(true)], DataType::Boolean), + true + ), + b(false) + ); + assert_eq!( + constant(&op(Builtin::IsNull, vec![int(1)], DataType::Boolean), true), + b(false) + ); + assert_eq!( + constant( + &op( + Builtin::IsNotNull, + vec![lit(Literal::Null(None))], + DataType::Boolean + ), + true + ), + b(false) + ); + let null = || lit(Literal::Null(Some(DataType::Boolean))); + let and = |x, y| op(Builtin::And, vec![x, y], DataType::Boolean); + let or = |x, y| op(Builtin::Or, vec![x, y], DataType::Boolean); + assert_eq!(constant(&and(truth(true), truth(true)), true), b(true)); + assert_eq!(constant(&and(truth(true), truth(false)), true), b(false)); + assert_eq!( + constant(&and(truth(true), null()), true), + Some(Constant::Null) + ); + assert_eq!(constant(&and(null(), truth(false)), true), b(false)); + assert_eq!(constant(&or(truth(false), truth(false)), true), b(false)); + assert_eq!(constant(&or(null(), truth(true)), true), b(true)); + assert_eq!( + constant(&or(truth(false), null()), true), + Some(Constant::Null) + ); + // The left operand decides, as in Spark: its error is raised, and + // a decided left operand hides the right one's. + let boom = || { + op( + Builtin::Eq, + vec![failing(), lit(Literal::Double(0.0))], + DataType::Boolean, + ) + }; + assert_eq!(constant(&and(truth(false), boom()), true), b(false)); + assert_eq!(constant(&or(truth(true), boom()), true), b(true)); + assert_eq!( + class(constant(&and(boom(), truth(false)), true)), + Some(ErrorClass::DivideByZero) + ); + assert_eq!( + class(constant(&and(truth(true), boom()), true)), + Some(ErrorClass::DivideByZero) + ); + } + + #[test] + fn conditionals_evaluate_lazily() { + let n = |v: i64| Some(Constant::Integral(v)); + let boom = || op(Builtin::Add, vec![int(i32::MAX), int(1)], DataType::Integer); + let when = |args| op(Builtin::When, args, DataType::Integer); + assert_eq!( + constant(&when(vec![truth(true), int(1), boom()]), true), + n(1) + ); + assert_eq!( + constant(&when(vec![truth(false), boom(), int(2)]), true), + n(2) + ); + assert_eq!( + constant(&when(vec![truth(false), int(1), truth(true), int(3)]), true), + n(3) + ); + // No branch taken and no ELSE: NULL. + assert_eq!( + constant(&when(vec![truth(false), int(1)]), true), + Some(Constant::Null) + ); + // The taken branch's error is raised. + assert_eq!( + class(constant(&when(vec![truth(true), boom(), int(1)]), true)), + Some(ErrorClass::ArithmeticOverflow) + ); + let coalesce = |args| named("coalesce", args, DataType::Integer); + assert_eq!( + constant( + &coalesce(vec![lit(Literal::Null(None)), int(2), boom()]), + true + ), + n(2) + ); + assert_eq!( + constant(&coalesce(vec![lit(Literal::Null(None))]), true), + Some(Constant::Null) + ); + let iff = |c, a, b| named("if", vec![c, a, b], DataType::Integer); + assert_eq!(constant(&iff(truth(true), int(1), boom()), true), n(1)); + assert_eq!(constant(&iff(truth(false), boom(), int(2)), true), n(2)); + assert_eq!( + constant(&iff(lit(Literal::Null(None)), boom(), int(2)), true), + n(2) + ); + // One argument that is not foldable keeps the call from folding. + let col = Expr::new(ExprNode::Column(crate::ColumnRef { + name: vec!["a".to_owned()], + plan_id: None, + })); + assert_eq!(constant(&iff(truth(true), int(1), col), true), None); + } + + #[test] + fn strings_and_registry_functions_fold() { + let concat = |parts: Vec| op(Builtin::Concat, parts, DataType::String); + assert_eq!( + constant(&concat(vec![text("a"), text("b")]), true), + string("ab") + ); + let null = lit(Literal::Null(None)); + assert_eq!( + constant(&concat(vec![text("a"), null]), true), + Some(Constant::Null) + ); + assert_eq!( + constant( + &concat(vec![text("a"), lit(Literal::String(String::new()))]), + true + ), + string("a") + ); + let cmp = op(Builtin::Lt, vec![text("a"), text("b")], DataType::Boolean); + assert_eq!(constant(&cmp, true), Some(Constant::Boolean(true))); + // Casts to a string fold through the cast kernels, so `concat` of + // mixed literals folds too. + assert_eq!( + constant(&cast(Literal::Integer(12), DataType::String), true), + string("12") + ); + let mixed = |parts: Vec| op(Builtin::Concat, parts, DataType::String); + assert_eq!( + constant( + &named( + "length", + vec![mixed(vec![ + text("a"), + cast(Literal::Integer(1), DataType::String) + ])], + DataType::Integer + ), + true + ), + Some(Constant::Integral(2)) + ); + // Deterministic string, math and arithmetic functions. + assert_eq!( + constant(&named("upper", vec![text("ab")], DataType::String), true), + string("AB") + ); + assert_eq!( + constant(&named("length", vec![text("abc")], DataType::Integer), true), + Some(Constant::Integral(3)) + ); + let abs = named("abs", vec![int(-2)], DataType::Integer); + assert_eq!(constant(&abs, true), Some(Constant::Integral(2))); + // The day and field datetime functions fold over dates; a folded + // date has no constant (the typing rules do not read dates), so + // `date_add` of literals is still not a constant, while `year` of + // one is. Clock, session and unknown functions never fold. + let date = lit(Literal::Date(0)); + assert_eq!( + constant(&named("date_add", vec![date, int(1)], DataType::Date), true), + None + ); + assert_eq!( + constant( + &named("year", vec![lit(Literal::Date(0))], DataType::Integer), + true + ), + Some(Constant::Integral(1970)) + ); + assert_eq!( + constant( + &named( + "datediff", + vec![lit(Literal::Date(1)), lit(Literal::Date(0))], + DataType::Integer + ), + true + ), + Some(Constant::Integral(1)) + ); + // Over timestamps the same functions read the session time zone, + // which the folder has not: they stay unfolded. + assert_eq!( + constant( + &named( + "year", + vec![cast( + Literal::String("2024-01-01".to_owned()), + DataType::Timestamp + )], + DataType::Integer + ), + true + ), + None + ); + for clock in ["current_date", "current_timestamp", "localtimestamp"] { + assert_eq!( + constant(&named(clock, vec![], DataType::Date), true), + None, + "{clock}" + ); + } + assert_eq!( + constant(&named("nosuchfn", vec![int(1)], DataType::Integer), true), + None + ); + // A function the kernels lack for the argument types is not folded. + assert_eq!( + constant(&named("abs", vec![text("x")], DataType::Integer), true), + None + ); + // Nondeterministic, `DISTINCT` and filtered calls are not constants. + let mut f = ResolvedFunction { + id: FunctionId::Registry { + name: "abs".to_owned(), + id: 0, + }, + kind: FunctionKind::Scalar, + args: vec![Arc::new(int(1))], + distinct: false, + filter: None, + data_type: DataType::Integer, + nullable: false, + deterministic: false, + }; + let expr = + |f: &ResolvedFunction| Expr::new(ExprNode::Resolved(ResolvedExpr::Function(f.clone()))); + assert_eq!(constant(&expr(&f), true), None); + f.deterministic = true; + assert_eq!(constant(&expr(&f), true), Some(Constant::Integral(1))); + f.distinct = true; + assert_eq!(constant(&expr(&f), true), None); + f.distinct = false; + f.filter = Some(Arc::new(truth(true))); + assert_eq!(constant(&expr(&f), true), None); + f.filter = None; + f.kind = FunctionKind::Aggregate; + assert_eq!(constant(&expr(&f), true), None); + } + + #[test] + fn a_literal_is_not_a_folded_expression() { + assert!(is_literal(&truth(true))); + assert!(!is_literal(&op( + Builtin::Not, + vec![truth(false)], + DataType::Boolean + ))); + assert!(!is_literal(&cast(Literal::Integer(1), DataType::Long))); + // `constant` folds the second; the flag of `first` needs the first. + assert_eq!( + constant( + &op(Builtin::Not, vec![truth(false)], DataType::Boolean), + true + ), + Some(Constant::Boolean(true)) + ); + } + + /// A foldable expression near [`crate::MAX_DEPTH`] folds on a 2 MiB + /// thread: every `STEP` levels hop to a fresh stack, so without the hop + /// this overflows the thread's stack. + #[test] + fn deep_foldable_expression_survives_small_stack() { + let mut e = int(0); + for _ in 0..crate::MAX_DEPTH - 1 { + e = op(Builtin::Add, vec![e, int(1)], DataType::Integer); + } + let e = Arc::new(e); + std::thread::Builder::new() + .stack_size(2 << 20) + .spawn(move || { + let conf = Conf::new(false, true, SparkProfile::V4_2); + let mut memo = Memo::default(); + assert_eq!( + super::constant(&e, conf, &mut memo), + Some(Constant::Integral(crate::MAX_DEPTH as i64 - 1)) + ); + }) + .unwrap() + .join() + .unwrap(); + } } diff --git a/crates/krishiv-plan/src/analyzer/fold_ops.rs b/crates/krishiv-plan/src/analyzer/fold_ops.rs new file mode 100644 index 000000000..e13a07025 --- /dev/null +++ b/crates/krishiv-plan/src/analyzer/fold_ops.rs @@ -0,0 +1,612 @@ +// SPDX-License-Identifier: Apache-2.0 +//! The operators a foldable expression may contain, evaluated on one-row +//! arrays through the same kernels the executor runs (so overflow, +//! division by zero and ANSI/legacy behaviour are the kernels'), on their +//! build-baseline code only ([`Baseline`]): one row gains nothing from the +//! per-CPU clones, and each instantiation here would add three. +//! +//! Every function answers `None` for an operand shape it does not +//! evaluate: the expression is then not folded (a constant-only argument +//! site reports it as non-foldable, see `fold.rs`). + +use std::sync::Arc; + +use arrow_array::cast::AsArray; +use arrow_array::types::{ + Decimal128Type, Float32Type, Float64Type, Int8Type, Int16Type, Int32Type, Int64Type, +}; +use arrow_array::{Array, ArrayRef, BooleanArray, StringArray}; +use arrow_schema::DataType as ArrowType; +use krishiv_common::error::KrishivError; +use krishiv_kernels::compare::{self, Equal, Greater, GreaterEq, Less, LessEq}; +use krishiv_kernels::decimal::{ + DecimalOp, DecimalPlan, decimal_arith, decimal_integral_divide, decimal_unary, +}; +use krishiv_kernels::integer::{self, SparkIntegral, UnaryOp}; +use krishiv_kernels::{ + Add, AnsiError, ArithOp, Baseline, JavaWrap, KernelError, Mul, NullOnOverflow, Operand, Sub, + float, +}; + +use crate::Builtin; + +/// An evaluation: `None` when the shape is not evaluated here. +pub(super) type Eval = Option>; + +fn done(r: Result) -> Eval { + Some( + r.map(|a| Arc::new(a) as ArrayRef) + .map_err(KrishivError::from), + ) +} + +fn operand(a: &ArrayRef) -> Operand<'_, T> { + Operand::Array(a.as_primitive::()) +} + +/// `l op r` for `+ - * / %` over operands of the result type `out`. +pub(super) fn arithmetic( + op: Builtin, + l: &ArrayRef, + r: &ArrayRef, + out: &ArrowType, + ansi: bool, + ctx: &Baseline, +) -> Eval { + if let ( + ArrowType::Decimal128(lp, ls), + ArrowType::Decimal128(rp, rs), + ArrowType::Decimal128(p, s), + ) = (l.data_type(), r.data_type(), out) + { + let dop = match op { + Builtin::Add => DecimalOp::Add, + Builtin::Subtract => DecimalOp::Subtract, + Builtin::Multiply => DecimalOp::Multiply, + Builtin::Divide => DecimalOp::Divide, + Builtin::Remainder => DecimalOp::Remainder, + _ => return None, + }; + let plan = match DecimalPlan::new(dop, (*lp, *ls), (*rp, *rs), (*p, *s)) { + Ok(plan) => plan, + Err(e) => return Some(Err(e.into())), + }; + let (a, b) = (operand::(l), operand::(r)); + return if ansi { + done(decimal_arith::(a, b, &plan, ctx)) + } else { + done(decimal_arith::(a, b, &plan, ctx)) + }; + } + if l.data_type() != out || r.data_type() != out { + return None; + } + match out { + ArrowType::Int8 => integral::(op, l, r, ansi, ctx), + ArrowType::Int16 => integral::(op, l, r, ansi, ctx), + ArrowType::Int32 => integral::(op, l, r, ansi, ctx), + ArrowType::Int64 => integral::(op, l, r, ansi, ctx), + ArrowType::Float32 => floating::(op, l, r, ansi, ctx), + ArrowType::Float64 => floating::(op, l, r, ansi, ctx), + _ => None, + } +} + +/// Integral `+ - * %` (`/` of integrals is typed `double` by the analyzer). +fn integral( + op: Builtin, + l: &ArrayRef, + r: &ArrayRef, + ansi: bool, + ctx: &Baseline, +) -> Eval { + let (a, b) = (operand::(l), operand::(r)); + macro_rules! run { + ($p:ty) => { + match op { + Builtin::Add => done(integer::binary::(a, b, ctx)), + Builtin::Subtract => done(integer::binary::(a, b, ctx)), + Builtin::Multiply => done(integer::binary::(a, b, ctx)), + Builtin::Remainder => done(integer::remainder::(a, b, ctx)), + _ => None, + } + }; + } + if ansi { + run!(AnsiError) + } else { + run!(JavaWrap) + } +} + +fn floating(op: Builtin, l: &ArrayRef, r: &ArrayRef, ansi: bool, ctx: &Baseline) -> Eval +where + T: arrow_array::ArrowPrimitiveType, +{ + let (a, b) = (operand::(l), operand::(r)); + match (op, ansi) { + (Builtin::Add, _) => done(float::binary(ArithOp::Add, a, b, ctx)), + (Builtin::Subtract, _) => done(float::binary(ArithOp::Subtract, a, b, ctx)), + (Builtin::Multiply, _) => done(float::binary(ArithOp::Multiply, a, b, ctx)), + (Builtin::Divide, true) => done(float::divide::(a, b, ctx)), + (Builtin::Divide, false) => done(float::divide::(a, b, ctx)), + (Builtin::Remainder, true) => done(float::remainder::(a, b, ctx)), + (Builtin::Remainder, false) => done(float::remainder::(a, b, ctx)), + _ => None, + } +} + +/// `l div r` over `bigint`s or decimals. +pub(super) fn integral_divide(l: &ArrayRef, r: &ArrayRef, ansi: bool, ctx: &Baseline) -> Eval { + match (l.data_type(), r.data_type()) { + (ArrowType::Int64, ArrowType::Int64) => { + let (a, b) = (operand::(l), operand::(r)); + if ansi { + done(integer::integral_divide::(a, b, ctx)) + } else { + done(integer::integral_divide::(a, b, ctx)) + } + } + (ArrowType::Decimal128(lp, ls), ArrowType::Decimal128(rp, rs)) => { + let (lt, rt) = ((*lp, *ls), (*rp, *rs)); + let (a, b) = (operand::(l), operand::(r)); + if ansi { + done(decimal_integral_divide::(a, b, lt, rt, ctx)) + } else { + done(decimal_integral_divide::(a, b, lt, rt, ctx)) + } + } + _ => None, + } +} + +/// Unary `-`. +pub(super) fn negate(a: &ArrayRef, ansi: bool, ctx: &Baseline) -> Eval { + macro_rules! int { + ($t:ty) => { + if ansi { + done(integer::unary::<$t, AnsiError>( + UnaryOp::Negate, + a.as_primitive::<$t>(), + ctx, + )) + } else { + done(integer::unary::<$t, JavaWrap>( + UnaryOp::Negate, + a.as_primitive::<$t>(), + ctx, + )) + } + }; + } + match a.data_type() { + ArrowType::Int8 => int!(Int8Type), + ArrowType::Int16 => int!(Int16Type), + ArrowType::Int32 => int!(Int32Type), + ArrowType::Int64 => int!(Int64Type), + ArrowType::Float32 => done(float::unary( + UnaryOp::Negate, + a.as_primitive::(), + )), + ArrowType::Float64 => done(float::unary( + UnaryOp::Negate, + a.as_primitive::(), + )), + ArrowType::Decimal128(..) => done(decimal_unary( + UnaryOp::Negate, + a.as_primitive::(), + )), + _ => None, + } +} + +/// `l op r` for `= < <= > >=` over two operands of one numeric type, or +/// two strings (compared by bytes, as Spark's `UTF8String` is). +pub(super) fn comparison(op: Builtin, l: &ArrayRef, r: &ArrayRef, ctx: &Baseline) -> Eval { + if l.data_type() != r.data_type() { + return None; + } + macro_rules! prim { + ($t:ty) => {{ + let (a, b) = (operand::<$t>(l), operand::<$t>(r)); + match op { + Builtin::Eq => done(compare::compare::<$t, Equal>(a, b, ctx)), + Builtin::Lt => done(compare::compare::<$t, Less>(a, b, ctx)), + Builtin::LtEq => done(compare::compare::<$t, LessEq>(a, b, ctx)), + Builtin::Gt => done(compare::compare::<$t, Greater>(a, b, ctx)), + Builtin::GtEq => done(compare::compare::<$t, GreaterEq>(a, b, ctx)), + _ => None, + } + }}; + } + match l.data_type() { + ArrowType::Int8 => prim!(Int8Type), + ArrowType::Int16 => prim!(Int16Type), + ArrowType::Int32 => prim!(Int32Type), + ArrowType::Int64 => prim!(Int64Type), + ArrowType::Float32 => prim!(Float32Type), + ArrowType::Float64 => prim!(Float64Type), + ArrowType::Decimal128(..) => prim!(Decimal128Type), + ArrowType::Utf8 => { + let (a, b) = (l.as_string::(), r.as_string::()); + let ord = (a.is_valid(0) && b.is_valid(0)) + .then(|| a.value(0).as_bytes().cmp(b.value(0).as_bytes())); + let holds = |o: std::cmp::Ordering| match op { + Builtin::Eq => Some(o.is_eq()), + Builtin::Lt => Some(o.is_lt()), + Builtin::LtEq => Some(o.is_le()), + Builtin::Gt => Some(o.is_gt()), + Builtin::GtEq => Some(o.is_ge()), + _ => None, + }; + let v = match ord { + Some(o) => Some(holds(o)?), + None => None, + }; + Some(Ok(Arc::new(BooleanArray::from(vec![v])) as ArrayRef)) + } + _ => None, + } +} + +/// The boolean value of a one-row array: `Some(None)` for NULL. +pub(super) fn boolean(a: &ArrayRef) -> Option> { + if a.data_type() == &ArrowType::Null { + return Some(None); + } + let b = a.as_boolean_opt()?; + Some(b.is_valid(0).then(|| b.value(0))) +} + +/// A one-row boolean array. +pub(super) fn bool_array(v: Option) -> ArrayRef { + Arc::new(BooleanArray::from(vec![v])) +} + +/// `concat` of strings: NULL when an argument is. +pub(super) fn concat(parts: &[ArrayRef]) -> Eval { + let mut out = String::new(); + let mut null = false; + for p in parts { + let s = p.as_string_opt::()?; + if s.is_valid(0) { + out.push_str(s.value(0)); + } else { + null = true; + } + } + let v: Option<&str> = (!null).then_some(out.as_str()); + Some(Ok(Arc::new(StringArray::from(vec![v])) as ArrayRef)) +} + +/// A one-row array is NULL. +pub(super) fn is_null(a: &ArrayRef) -> bool { + a.data_type() == &ArrowType::Null || a.null_count() > 0 +} + +#[cfg(test)] +mod tests { + use arrow_array::{ + Decimal128Array, Float64Array, Int8Array, Int16Array, Int32Array, Int64Array, NullArray, + }; + use krishiv_common::error::ErrorClass; + + use krishiv_kernels::KernelCtx; + + use super::*; + + // The session's current Spark line, as the tests that do not choose + // one use it. + fn arithmetic(op: Builtin, l: &ArrayRef, r: &ArrayRef, out: &ArrowType, ansi: bool) -> Eval { + super::arithmetic(op, l, r, out, ansi, &KernelCtx::new().baseline()) + } + + fn integral_divide(l: &ArrayRef, r: &ArrayRef, ansi: bool) -> Eval { + super::integral_divide(l, r, ansi, &KernelCtx::new().baseline()) + } + + fn negate(a: &ArrayRef, ansi: bool) -> Eval { + super::negate(a, ansi, &KernelCtx::new().baseline()) + } + + fn comparison(op: Builtin, l: &ArrayRef, r: &ArrayRef) -> Eval { + super::comparison(op, l, r, &KernelCtx::new().baseline()) + } + + fn i32s(v: Option) -> ArrayRef { + Arc::new(Int32Array::from(vec![v])) + } + + fn i64s(v: Option) -> ArrayRef { + Arc::new(Int64Array::from(vec![v])) + } + + fn f64s(v: Option) -> ArrayRef { + Arc::new(Float64Array::from(vec![v])) + } + + fn dec(v: Option, p: u8, s: i8) -> ArrayRef { + Arc::new( + Decimal128Array::from(vec![v]) + .with_precision_and_scale(p, s) + .unwrap(), + ) + } + + fn strs(v: Option<&str>) -> ArrayRef { + Arc::new(StringArray::from(vec![v])) + } + + fn ok(e: Eval) -> ArrayRef { + e.expect("evaluated").expect("no error") + } + + fn err(e: Eval) -> ErrorClass { + e.expect("evaluated").expect_err("an error").error_class() + } + + #[test] + fn integral_arithmetic_follows_the_overflow_mode() { + let int = ArrowType::Int32; + let sum = |a, b, ansi| arithmetic(Builtin::Add, &i32s(a), &i32s(b), &int, ansi); + assert_eq!( + ok(sum(Some(2), Some(3), true)) + .as_primitive::() + .value(0), + 5 + ); + assert_eq!( + err(sum(Some(i32::MAX), Some(1), true)), + ErrorClass::ArithmeticOverflow + ); + // Legacy mode wraps. + let wrapped = ok(sum(Some(i32::MAX), Some(1), false)); + assert_eq!(wrapped.as_primitive::().value(0), i32::MIN); + // NULL propagates. + assert!(ok(sum(None, Some(1), true)).is_null(0)); + let sub = arithmetic( + Builtin::Subtract, + &i32s(Some(1)), + &i32s(Some(5)), + &int, + true, + ); + assert_eq!(ok(sub).as_primitive::().value(0), -4); + let mul = arithmetic( + Builtin::Multiply, + &i32s(Some(6)), + &i32s(Some(7)), + &int, + true, + ); + assert_eq!(ok(mul).as_primitive::().value(0), 42); + let rem = |b, ansi| { + arithmetic( + Builtin::Remainder, + &i32s(Some(7)), + &i32s(Some(b)), + &int, + ansi, + ) + }; + assert_eq!(ok(rem(4, true)).as_primitive::().value(0), 3); + assert_eq!(err(rem(0, true)), ErrorClass::RemainderByZero); + assert!(ok(rem(0, false)).is_null(0)); + // Every integral width. + for (a, t) in [ + ( + Arc::new(Int8Array::from(vec![1_i8])) as ArrayRef, + ArrowType::Int8, + ), + (Arc::new(Int16Array::from(vec![1_i16])), ArrowType::Int16), + (i64s(Some(1)), ArrowType::Int64), + ] { + let r = ok(arithmetic(Builtin::Add, &a, &a, &t, true)); + assert_eq!(r.data_type(), &t); + } + } + + #[test] + fn arithmetic_shapes_it_does_not_evaluate_are_none() { + let int = ArrowType::Int32; + // `/` of integrals (the analyzer types it `double`), another + // operator, operands of the wrong type. + assert!(arithmetic(Builtin::Divide, &i32s(Some(1)), &i32s(Some(1)), &int, true).is_none()); + assert!(arithmetic(Builtin::Eq, &i32s(Some(1)), &i32s(Some(1)), &int, true).is_none()); + assert!(arithmetic(Builtin::Add, &i32s(Some(1)), &i64s(Some(1)), &int, true).is_none()); + let s = strs(Some("1")); + assert!(arithmetic(Builtin::Add, &s, &s, &ArrowType::Utf8, true).is_none()); + let d = dec(Some(1), 5, 0); + let dt = ArrowType::Decimal128(6, 0); + assert!(arithmetic(Builtin::Eq, &d, &d, &dt, true).is_none()); + } + + #[test] + fn floating_arithmetic() { + let t = ArrowType::Float64; + let run = |op, a, b, ansi| arithmetic(op, &f64s(Some(a)), &f64s(Some(b)), &t, ansi); + let v = |e: Eval| ok(e).as_primitive::().value(0); + assert!((v(run(Builtin::Add, 1.5, 2.0, true)) - 3.5).abs() < f64::EPSILON); + assert!((v(run(Builtin::Subtract, 1.5, 2.0, true)) + 0.5).abs() < f64::EPSILON); + assert!((v(run(Builtin::Multiply, 1.5, 2.0, true)) - 3.0).abs() < f64::EPSILON); + assert!((v(run(Builtin::Divide, 3.0, 2.0, true)) - 1.5).abs() < f64::EPSILON); + assert!((v(run(Builtin::Remainder, 5.5, 2.0, false)) - 1.5).abs() < f64::EPSILON); + assert_eq!( + err(run(Builtin::Divide, 1.0, 0.0, true)), + ErrorClass::DivideByZero + ); + assert!(ok(run(Builtin::Divide, 1.0, 0.0, false)).is_null(0)); + assert_eq!( + err(run(Builtin::Remainder, 1.0, 0.0, true)), + ErrorClass::RemainderByZero + ); + assert!(ok(run(Builtin::Remainder, 1.0, 0.0, false)).is_null(0)); + let f32s: ArrayRef = Arc::new(arrow_array::Float32Array::from(vec![1.5_f32])); + let r = arithmetic(Builtin::Add, &f32s, &f32s, &ArrowType::Float32, true); + assert_eq!(ok(r).as_primitive::().value(0), 3.0); + // `div` is not floating-point arithmetic. + assert!(run(Builtin::IntegralDivide, 1.0, 1.0, true).is_none()); + } + + #[test] + fn the_session_spark_version_reaches_the_kernels() { + use krishiv_kernels::SparkVersion; + let int = ArrowType::Int32; + let rem = |ctx: &Baseline| { + super::arithmetic( + Builtin::Remainder, + &i32s(Some(1)), + &i32s(Some(0)), + &int, + true, + ctx, + ) + }; + let v40 = KernelCtx::new().with_spark_version(SparkVersion::V4_0); + assert_eq!(err(rem(&v40.baseline())), ErrorClass::DivideByZero); + assert_eq!( + err(rem(&KernelCtx::new().baseline())), + ErrorClass::RemainderByZero + ); + } + + #[test] + fn decimal_arithmetic() { + let out = ArrowType::Decimal128(7, 2); + let a = dec(Some(150), 5, 2); + let b = dec(Some(25), 5, 2); + let run = |op, ansi| arithmetic(op, &a, &b, &out, ansi); + let v = |e: Eval| ok(e).as_primitive::().value(0); + assert_eq!(v(run(Builtin::Add, true)), 175); + assert_eq!(v(run(Builtin::Subtract, false)), 125); + // Overflow of the result type: an error, or NULL in legacy mode. + let tight = ArrowType::Decimal128(3, 2); + let big = dec(Some(999), 3, 2); + let over = arithmetic(Builtin::Add, &big, &big, &tight, true); + assert!(over.expect("evaluated").is_err()); + let wrapped = arithmetic(Builtin::Add, &big, &big, &tight, false); + assert!(ok(wrapped).is_null(0)); + // A plan the kernels refuse is the kernels' error, not a panic. + let bad = arithmetic( + Builtin::Add, + &dec(Some(1), 5, 2), + &dec(Some(1), 5, 2), + &ArrowType::Decimal128(38, 38), + true, + ); + assert!(matches!(bad, Some(Err(_))), "{bad:?}"); + } + + #[test] + fn integral_division() { + let q = |a: i64, b: i64, ansi| integral_divide(&i64s(Some(a)), &i64s(Some(b)), ansi); + assert_eq!(ok(q(7, 2, true)).as_primitive::().value(0), 3); + assert_eq!(err(q(1, 0, true)), ErrorClass::DivideByZero); + assert!(ok(q(1, 0, false)).is_null(0)); + let d = |ansi| integral_divide(&dec(Some(750), 5, 2), &dec(Some(200), 5, 2), ansi); + assert_eq!(ok(d(true)).as_primitive::().value(0), 3); + assert_eq!(ok(d(false)).as_primitive::().value(0), 3); + assert!(integral_divide(&i32s(Some(1)), &i32s(Some(1)), true).is_none()); + } + + #[test] + fn negation() { + let n = |a: &ArrayRef, ansi| negate(a, ansi); + assert_eq!( + ok(n(&i32s(Some(5)), true)) + .as_primitive::() + .value(0), + -5 + ); + assert_eq!( + err(n(&i32s(Some(i32::MIN)), true)), + ErrorClass::ArithmeticOverflow + ); + let wrapped = ok(n(&i32s(Some(i32::MIN)), false)); + assert_eq!(wrapped.as_primitive::().value(0), i32::MIN); + for a in [ + Arc::new(Int8Array::from(vec![1_i8])) as ArrayRef, + Arc::new(Int16Array::from(vec![1_i16])), + i64s(Some(1)), + f64s(Some(1.5)), + Arc::new(arrow_array::Float32Array::from(vec![1.5_f32])), + dec(Some(15), 3, 1), + ] { + assert_eq!(ok(n(&a, true)).data_type(), a.data_type()); + } + assert!(n(&strs(Some("x")), true).is_none()); + } + + #[test] + fn comparisons() { + let t = |e: Eval| ok(e).as_boolean().value(0); + assert!(t(comparison(Builtin::Lt, &i32s(Some(1)), &i32s(Some(2))))); + assert!(t(comparison(Builtin::LtEq, &i32s(Some(2)), &i32s(Some(2))))); + assert!(t(comparison(Builtin::Eq, &i64s(Some(2)), &i64s(Some(2))))); + assert!(t(comparison( + Builtin::Gt, + &f64s(Some(2.5)), + &f64s(Some(2.0)) + ))); + assert!(!t(comparison( + Builtin::GtEq, + &dec(Some(1), 3, 1), + &dec(Some(2), 3, 1) + ))); + assert!(t(comparison( + Builtin::Lt, + &strs(Some("a")), + &strs(Some("b")) + ))); + assert!(t(comparison( + Builtin::GtEq, + &strs(Some("b")), + &strs(Some("b")) + ))); + assert!(t(comparison( + Builtin::Gt, + &strs(Some("b")), + &strs(Some("a")) + ))); + assert!(t(comparison( + Builtin::LtEq, + &strs(Some("a")), + &strs(Some("a")) + ))); + assert!(t(comparison( + Builtin::Eq, + &strs(Some("a")), + &strs(Some("a")) + ))); + // A NULL string compares to NULL. + let null = comparison(Builtin::Eq, &strs(None), &strs(Some("a"))); + assert!(ok(null).is_null(0)); + // Another operator, another type, mismatched types. + assert!(comparison(Builtin::Add, &strs(Some("a")), &strs(Some("a"))).is_none()); + assert!(comparison(Builtin::Add, &i32s(Some(1)), &i32s(Some(1))).is_none()); + assert!(comparison(Builtin::Eq, &i32s(Some(1)), &i64s(Some(1))).is_none()); + let b: ArrayRef = bool_array(Some(true)); + assert!(comparison(Builtin::Eq, &b, &b).is_none()); + for t in [ArrowType::Int8, ArrowType::Int16] { + let a = arrow_array::new_null_array(&t, 1); + assert!(comparison(Builtin::Eq, &a, &a).is_some()); + } + } + + #[test] + fn booleans_nulls_and_concat() { + assert_eq!(boolean(&bool_array(Some(true))), Some(Some(true))); + assert_eq!(boolean(&bool_array(None)), Some(None)); + let null: ArrayRef = Arc::new(NullArray::new(1)); + assert_eq!(boolean(&null), Some(None)); + assert_eq!(boolean(&i32s(Some(1))), None); + assert!(is_null(&null)); + assert!(is_null(&i32s(None))); + assert!(!is_null(&i32s(Some(1)))); + let joined = ok(concat(&[strs(Some("a")), strs(Some("b"))])); + assert_eq!(joined.as_string::().value(0), "ab"); + let with_null = ok(concat(&[strs(Some("a")), strs(None)])); + assert!(with_null.is_null(0)); + assert!(concat(&[strs(Some("a")), i32s(Some(1))]).is_none()); + } +} diff --git a/crates/krishiv-plan/src/analyzer/mod.rs b/crates/krishiv-plan/src/analyzer/mod.rs index 52bc4fe1c..01aa3969e 100644 --- a/crates/krishiv-plan/src/analyzer/mod.rs +++ b/crates/krishiv-plan/src/analyzer/mod.rs @@ -68,6 +68,7 @@ mod catalog; mod coerce; mod exprs; mod fold; +mod fold_ops; mod hints; mod ops; mod resolve; diff --git a/crates/krishiv-plan/src/analyzer/ops.rs b/crates/krishiv-plan/src/analyzer/ops.rs index 8ac401696..a16b31216 100644 --- a/crates/krishiv-plan/src/analyzer/ops.rs +++ b/crates/krishiv-plan/src/analyzer/ops.rs @@ -8,11 +8,10 @@ use std::sync::Arc; use krishiv_common::error::{ AmbiguousReference, AssignmentArityMismatch, DatatypeMismatchFilterNotBoolean, FailedToParseTooComplex, GroupByAggregate, GroupByPosAggregate, GroupByPosOutOfRange, - InvalidLimitLikeExpressionDataType, InvalidLimitLikeExpressionIsNegative, - InvalidLimitLikeExpressionIsNull, InvalidLimitLikeExpressionIsUnfoldable, - InvalidWhereCondition, JoinConditionIsNotBooleanType, MissingAggregation, MissingGroupBy, - OrderByPosOutOfRange, StarGroupByPos, SumOfLimitAndOffsetExceedsMaxInt, TableOrViewNotFound, - UnresolvedUsingColumnForJoin, UnsupportedFeatureLateralColumnAliasInAggregateFunc, + InvalidLimitLikeExpressionDataType, InvalidWhereCondition, JoinConditionIsNotBooleanType, + MissingAggregation, MissingGroupBy, OrderByPosOutOfRange, StarGroupByPos, + SumOfLimitAndOffsetExceedsMaxInt, TableOrViewNotFound, UnresolvedUsingColumnForJoin, + UnsupportedFeatureLateralColumnAliasInAggregateFunc, UnsupportedFeatureLateralColumnAliasInGroupBy, }; @@ -21,13 +20,27 @@ use super::catalog::quoted; use super::coerce::quoted_type; use super::exprs::{Bound, Cx, WindowUse, names, pretty, semantic_key}; use super::resolve::{AggInfo, Attr, Env, Rel, Resolver, Widen}; -use super::{AnalysisError, ArgType, Constant, TableKind}; +use super::{AnalysisError, ArgType, TableKind}; use crate::{ AttrId, BoundColumn, CteRef, Expr, ExprNode, FunctionCall, FunctionKind, Grouping, JoinCondition, JoinKind, Literal, LogicalPlan, Origin, PlanNode, ReadSource, ResolvedExpr, ResolvedFunction, Scan, SortOrder, }; +/// What [`Resolver::group_substitute`] reads and grows: the aggregate, the +/// attributes it shows, and the output it adds for grouping expressions the +/// select list does not name. +struct Grouped<'a> { + info: &'a AggInfo, + env: &'a Arc, + op: &'static str, + visible: &'a HashSet, + memo: &'a mut HashMap, + known: &'a mut Vec<(u128, Attr)>, + grown: &'a mut AggInfo, + pass: &'a mut Vec, +} + /// The two attributes of a `USING` column. type Keys = (Attr, Attr); @@ -562,6 +575,44 @@ impl Resolver<'_> { Ok((bounds, self.widened(c, &missing)?)) } + /// The aggregate under `c`'s filters, sorts and limits (`HAVING`), and + /// those layers, top first; `None` when `c` is not such a stack. A + /// `HAVING` that had to grow the aggregate left a projection over its + /// filter (`restore`), and that is not such a stack: Spark does not + /// resolve a sort through it (`GROUP BY x + 1 HAVING sum(l) > 1 ORDER BY + /// x + 1` is UNRESOLVED_COLUMN, checked against 4.2.0). + fn through_to_agg(c: &Rel) -> Option<(Vec, Rel)> { + let mut layers = Vec::new(); + let mut cur = c.clone(); + loop { + if cur.agg.is_some() { + return Some((layers, cur)); + } + let child = match cur.widen.as_deref() { + Some(Widen::Through { child }) => child.clone(), + _ => return None, + }; + layers.push(cur); + cur = child; + } + } + + /// `layers` (from [`Self::through_to_agg`]) rebuilt over `inner`, a + /// grown version of the aggregate they were over. + fn rewrapped(&self, layers: &[Rel], inner: Rel) -> Rel { + let mut built = inner; + for rel in layers.iter().rev() { + let child = built; + let plan = Arc::clone(&rel.plan) + .map_children(|_| Ok::<_, Infallible>(Arc::clone(&child.plan))) + .unwrap_or_else(|never| match never {}); + let mut wide = self.wrap(plan, rel.plan.origin.plan_id, child.out.to_vec(), &[&child]); + wide.widen = Some(Arc::new(Widen::Through { child })); + built = wide; + } + built + } + /// Binds each of `exprs` in `cx`. fn bind_all(&mut self, exprs: &[Arc], cx: &Cx<'_>) -> Result, AnalysisError> { exprs.iter().map(|e| self.bind(e, cx)).collect() @@ -688,10 +739,6 @@ impl Resolver<'_> { if op == "Filter" { cx.windows = WindowUse::Having; } - let mut bounds = Vec::new(); - for e in exprs { - bounds.push(self.bind(e, &cx)?); - } let mut memo = HashMap::new(); let mut known: Vec<(u128, Attr)> = info .aggregates @@ -703,6 +750,39 @@ impl Resolver<'_> { let mut grown = (*info).clone(); // What the aggregate adds to the output it shows. let mut pass: Vec = Vec::new(); + let mut bounds = Vec::new(); + for e in exprs { + match self.bind(e, &cx) { + Ok(b) => bounds.push(b), + // A grouping expression written out in full (`GROUP BY x + 1 + // ORDER BY x + 1`) is the aggregate's output, wherever it + // appears in the expression; names it does not cover stay + // unresolved, as in Spark. + Err(err) + if err + .error + .error_class() + .name() + .starts_with("UNRESOLVED_COLUMN") => + { + let mut st = Grouped { + info: &info, + env, + op, + visible: &visible, + memo: &mut memo, + known: &mut known, + grown: &mut grown, + pass: &mut pass, + }; + let Some(sub) = self.group_substitute(e, &mut st) else { + return Err(err); + }; + bounds.push(self.bind(&sub, &cx).map_err(|_| err)?); + } + Err(err) => return Err(err), + } + } for b in &mut bounds { b.expr = Arc::clone(&b.expr).transform_down(&mut |x: Arc| match &x.node { ExprNode::Resolved(ResolvedExpr::Function(f)) @@ -742,6 +822,12 @@ impl Resolver<'_> { if !visible.contains(&c.id) && !pass.iter().any(|a| a.col.id == c.id) => { if let Some(k) = info.keys.iter().find(|k| k.col.id == c.id) { + // An output that already computes the key (`x AS + // m`) stands for it, as in Spark: nothing grows. + let key = semantic_key(&x, &mut memo); + if let Some((_, a)) = known.iter().find(|(kk, _)| *kk == key) { + return Ok(col_expr(&a.col, x.origin)); + } if !grown.out.iter().any(|o| o.col.id == c.id) { grown.aggregates.push(col_expr(&k.col, Origin::UNKNOWN)); grown.out.push(k.clone()); @@ -778,6 +864,89 @@ impl Resolver<'_> { Ok((bounds, r, true)) } + /// `e` with every subexpression that is one of the aggregate's grouping + /// expressions or output expressions (equal after canonicalisation, as Spark's + /// `semanticEquals`) replaced by the attribute the aggregate computes + /// it as, added to the aggregate when it does not output it. `None` + /// when nothing matches, or `e` holds a subquery. + #[inline(never)] + fn group_substitute(&mut self, e: &Arc, st: &mut Grouped<'_>) -> Option> { + let info = st.info; + let rels = [&info.input]; + let probe = Self::cx(&info.input.out, &rels, st.env, st.op); + let grouping: HashSet = info + .grouping + .iter() + .map(|g| semantic_key(g, st.memo)) + .collect(); + let mut subquery = false; + let _ = crate::walk::visit_distinct(crate::walk::Node::Expr(e), |n| { + if let crate::walk::Node::Expr(x) = n + && matches!(x.node, ExprNode::Subquery { .. }) + { + subquery = true; + } + std::ops::ControlFlow::Continue(()) + }); + if subquery { + return None; + } + let mut changed = false; + let out = Arc::clone(e) + .transform_down(&mut |x: Arc| -> Result, Infallible> { + // Leaves resolve by name; aggregate calls and the rest of + // the output are bound by the caller. + if matches!( + x.node, + ExprNode::Column(_) | ExprNode::Literal(_) | ExprNode::Star(_) + ) { + return Ok(x); + } + let Ok(b) = self.expr(&x, &probe) else { + return Ok(x); + }; + if b.agg.is_some() || b.outer.is_some() || !b.lateral.is_empty() { + return Ok(x); + } + // The probe's expressions are dropped on return: their + // addresses must not outlive them in a memo. + let key = semantic_key(&b.expr, &mut HashMap::new()); + if !grouping.contains(&key) && !st.known.iter().any(|(k, _)| *k == key) { + return Ok(x); + } + let a = match st.known.iter().find(|(k, _)| *k == key) { + Some((_, a)) => a.clone(), + None => { + let output = self.attr(&pretty(&b.expr), &b.ty); + st.grown + .aggregates + .push(Arc::new(Expr::new(ExprNode::Resolved( + ResolvedExpr::Alias { + expr: Arc::clone(&b.expr), + output: output.clone(), + }, + )))); + let a = Attr { + col: output, + qual: no_qual(), + source: None, + }; + st.grown.out.push(a.clone()); + st.known.push((key, a.clone())); + a + } + }; + if !st.visible.contains(&a.col.id) && !st.pass.iter().any(|p| p.col.id == a.col.id) + { + st.pass.push(a.clone()); + } + changed = true; + Ok(col_expr(&a.col, x.origin)) + }) + .unwrap_or_else(|never| match never {}); + changed.then_some(out) + } + /// The aggregate of `info`, under its `HAVING` (with windows), its /// windows and the projections of its lateral aliases if it has any; /// `pass` (attributes of the aggregate) are output after the select @@ -1480,44 +1649,22 @@ impl Resolver<'_> { if name == "limit" { "Limit" } else { "Offset" }, ); let b = self.bind(e, &cx)?; - let shown = || format!("\"{}\"", pretty(&b.shown())); - if not_constant(&b.expr) { - return Err(AnalysisError::new( - InvalidLimitLikeExpressionIsUnfoldable { - expr: shown(), - name: name.to_owned(), - }, - e.origin, - )); - } - if b.ty.data_type != Some(krishiv_types::DataType::Integer) { + // Spark's order: foldable, then the type, then the value. + let unfoldable = not_constant(&b.expr); + if !unfoldable && b.ty.data_type != Some(krishiv_types::DataType::Integer) { return Err(AnalysisError::new( InvalidLimitLikeExpressionDataType { - expr: shown(), + expr: format!("\"{}\"", pretty(&b.shown())), name: name.to_owned(), data_type: quoted_type(b.ty.data_type.as_ref()), }, e.origin, )); } - match super::fold::constant(&b.expr, self.ctx.conf.ansi) { - Some(Constant::Null) => Err(AnalysisError::new( - InvalidLimitLikeExpressionIsNull { - expr: shown(), - name: name.to_owned(), - }, - e.origin, - )), - Some(Constant::Integral(v)) if v < 0 => Err(AnalysisError::new( - InvalidLimitLikeExpressionIsNegative { - expr: shown(), - name: name.to_owned(), - v: v.to_string(), - }, - e.origin, - )), + let folded = self.check_limit(&b, name, unfoldable, e.origin, input.plan.origin)?; + match folded { // `CAST('3' AS INT)` and the like: the planner reads a literal. - Some(Constant::Integral(v)) if !matches!(b.expr.node, ExprNode::Literal(_)) => { + Some(v) if !matches!(b.expr.node, ExprNode::Literal(_)) => { let v = i32::try_from(v) .map_err(|_| unsupported("a LIMIT or OFFSET out of range", e.origin))?; Ok(Arc::new(Expr::literal(Literal::Integer(v)))) @@ -1571,9 +1718,40 @@ impl Resolver<'_> { } else { // A name the select list outputs twice is looked up below it, // as Spark does. - let (bounds, wide) = self.bind_missing(&c, &exprs, env, "Sort", true)?; - let extended = wide.out.len() > c.out.len(); - (bounds, wide, extended) + match self.bind_missing(&c, &exprs, env, "Sort", true) { + Ok((bounds, wide)) => { + let extended = wide.out.len() > c.out.len(); + (bounds, wide, extended) + } + // `HAVING ... ORDER BY`: the sort reads the aggregate below + // the filter, which grows what the sort needs. + Err(e) + if e.error + .error_class() + .name() + .starts_with("UNRESOLVED_COLUMN") => + { + let Some((layers, inner)) = Self::through_to_agg(&c) else { + return Err(e); + }; + // Over windows, Spark's `ORDER BY` reads the select list + // only: nothing resolves through them to the aggregate. + if inner.agg.as_ref().is_some_and(|i| i.has_windows()) { + return Err(e); + } + let Ok((bounds, grown, extended)) = self.over_agg(&inner, &exprs, env, "Sort") + else { + return Err(e); + }; + let top = if extended { + self.rewrapped(&layers, grown) + } else { + c.clone() + }; + (bounds, top, extended) + } + Err(e) => return Err(e), + } }; let node = PlanNode::Sort { input: Arc::clone(&below.plan), diff --git a/crates/krishiv-plan/src/analyzer/resolve.rs b/crates/krishiv-plan/src/analyzer/resolve.rs index d8dcaf437..1b31c2435 100644 --- a/crates/krishiv-plan/src/analyzer/resolve.rs +++ b/crates/krishiv-plan/src/analyzer/resolve.rs @@ -130,6 +130,8 @@ pub(super) struct Resolver<'a> { depth: usize, op_outer: Option, root_env: Option>, + /// Constant folding's values over this pass (see `fold::Memo`). + pub(super) folds: std::cell::RefCell, } type Resolved = ( @@ -156,6 +158,7 @@ pub(super) fn resolve( depth: 0, op_outer: None, root_env: None, + folds: std::cell::RefCell::default(), }; // Fresh ids start past every id the input already holds (a plan that // is resolved in part, or re-analysed). @@ -454,6 +457,90 @@ impl Resolver<'_> { } } + /// Spark's checks of a `LIMIT` or `OFFSET` (`name`) value: it must be + /// foldable (`IS_UNFOLDABLE` when it is not: a column, a nondeterministic + /// call, a subquery), to a value that is not NULL and not negative + /// (cited at the expression, `at`); what folding raises (`2147483647 + 1` + /// under ANSI) is raised as is. `unfoldable` reports the first check + /// without folding. A foldable expression this folder cannot evaluate + /// (a cast or call the kernels lack here) is not an error: it passes + /// through for the executor to evaluate once at run time, as before. + /// The folded value, when it is an integral. + #[inline(never)] + pub(super) fn check_limit( + &self, + b: &super::exprs::Bound, + name: &str, + unfoldable: bool, + at: Origin, + operator: Origin, + ) -> Result, AnalysisError> { + use krishiv_common::error::{ + InvalidLimitLikeExpressionIsNegative, InvalidLimitLikeExpressionIsNull, + InvalidLimitLikeExpressionIsUnfoldable, + }; + // A nondeterministic expression is pulled out of the operator into + // an attribute of this name before Spark checks it. + let nondeterministic = { + let mut found = false; + let _ = crate::walk::visit_distinct(crate::walk::Node::Expr(&b.expr), |n| { + if let crate::walk::Node::Expr(x) = n + && let ExprNode::Resolved(crate::ResolvedExpr::Function(f)) = &x.node + && !f.deterministic + { + found = true; + } + std::ops::ControlFlow::Continue(()) + }); + found + }; + let text = if nondeterministic { + "\"_nondeterministic\"".to_owned() + } else { + format!("\"{}\"", super::exprs::pretty(&b.shown())) + }; + let name = name.to_owned(); + let folded = if unfoldable { + None + } else { + self.fold(&b.expr, self.ctx.conf.ansi) + }; + match folded { + // An attribute carries no position of its own: Spark cites the + // input there, the expression otherwise. + // Not foldable to Spark either: `IS_UNFOLDABLE` without folding. + None if unfoldable => Err(AnalysisError::new( + InvalidLimitLikeExpressionIsUnfoldable { expr: text, name }, + if matches!( + b.expr.node, + ExprNode::Resolved(crate::ResolvedExpr::Column(_)) + ) { + operator + } else { + b.expr.origin + }, + )), + Some(super::Constant::Error(e)) => Err(AnalysisError::new(e, b.expr.origin)), + Some(super::Constant::Null) => Err(AnalysisError::new( + InvalidLimitLikeExpressionIsNull { expr: text, name }, + at, + )), + Some(super::Constant::Integral(v)) if v < 0 => Err(AnalysisError::new( + InvalidLimitLikeExpressionIsNegative { + expr: text, + name, + v: v.to_string(), + }, + at, + )), + Some(super::Constant::Integral(v)) => Ok(Some(v)), + // Foldable, but not evaluated here (or not an integral): pass + // the expression through for the downstream folders and the + // executor to read at run time. + None | Some(_) => Ok(None), + } + } + /// Binds a top-level expression of the current operator. pub(super) fn bind(&mut self, e: &Arc, cx: &Cx<'_>) -> Result { let b = self.expr(e, cx)?; diff --git a/crates/krishiv-plan/src/tests/analyzer.rs b/crates/krishiv-plan/src/tests/analyzer.rs index d24192d99..c06d46cc7 100644 --- a/crates/krishiv-plan/src/tests/analyzer.rs +++ b/crates/krishiv-plan/src/tests/analyzer.rs @@ -1911,6 +1911,57 @@ fn try_arithmetic_casts_its_arguments_in_try_mode() { assert!(try_add.output[0].nullable); } +/// Built-in functions plus `rand`, a nondeterministic `DOUBLE` function as +/// in Spark (the engine does not implement it yet; `sqrt`'s signature +/// stands in for its typing). +struct WithRand(crate::analyzer::BuiltinFunctions); + +impl crate::analyzer::FunctionRegistry for WithRand { + fn lookup(&self, name: &[String], profile: SparkProfile) -> crate::analyzer::FunctionLookup { + use crate::analyzer::FunctionLookup; + if name.len() == 1 && name[0].eq_ignore_ascii_case("rand") { + return match self.0.lookup(&["sqrt".to_owned()], profile) { + FunctionLookup::Found(mut e) => { + e.deterministic = false; + FunctionLookup::Found(e) + } + other => other, + }; + } + self.0.lookup(name, profile) + } + + fn version(&self) -> u64 { + self.0.version() + } +} + +/// `OFFSET rand(1)` is `IS_UNFOLDABLE` (cited as `_nondeterministic`), not +/// `DATA_TYPE` for its `DOUBLE`: Spark checks foldability first (Spark 4.2.0 +/// raises the same for `OFFSET rand()`). +#[test] +fn a_nondeterministic_count_is_unfoldable_before_its_type() { + let mut cx = ctx(); + cx.functions = Arc::new(WithRand(crate::analyzer::BuiltinFunctions::new())); + let rand = || Expr::function("rand", vec![Expr::from(Literal::Integer(1))]); + for (plan, name) in [ + (LogicalPlan::table(["t"]).offset(rand()), "offset"), + (LogicalPlan::table(["t"]).limit(rand()), "limit"), + ] { + let e = run(plan, &cx).unwrap_err(); + assert_eq!( + e.error.error_class(), + ErrorClass::InvalidLimitLikeExpressionIsUnfoldable, + "{e:?}" + ); + let msg = e.error.to_string(); + assert!( + msg.contains("\"_nondeterministic\"") && msg.contains(name), + "{msg}" + ); + } +} + /// An unused CTE is not resolved: its column errors never fail the query. /// Spark's golden `cte` case 50 keeps an unused `cte3` whose projection /// over the duplicate-case columns of `cte2` would be ambiguous. diff --git a/crates/krishiv-session/tests/offset_regexp.rs b/crates/krishiv-session/tests/offset_regexp.rs index aeabfc3ef..e6cd6552b 100644 --- a/crates/krishiv-session/tests/offset_regexp.rs +++ b/crates/krishiv-session/tests/offset_regexp.rs @@ -88,6 +88,15 @@ fn offset_skips_then_limit_keeps() { ints(&s, "SELECT id FROM t ORDER BY id DESC LIMIT 20 OFFSET 7"), [3, 2, 1] ); + // A foldable count folds to a literal the planner reads (Spark 4.2.0: + // two rows). + assert_eq!( + ints( + &s, + "SELECT id FROM t ORDER BY id LIMIT length('ab') OFFSET 1 + 1" + ), + [3, 4] + ); // Offset 0 is a no-op; a limit of 0 returns nothing whatever the offset. assert_eq!(ints(&s, "SELECT id FROM t ORDER BY id OFFSET 0").len(), 10); assert!(ints(&s, "SELECT id FROM t ORDER BY id LIMIT 0 OFFSET 3").is_empty()); @@ -267,11 +276,14 @@ fn regexp_replace_position_is_checked_before_any_row() { one("SELECT regexp_replace(CAST(NULL AS STRING), 'a', 'b', CAST(NULL AS INT))"), None ); - // Known divergence: Spark folds `1 + 1`; the analyzer only folds - // literals and casts of them (as for the scale of `round`). + // A foldable position folds, as in Spark 4.2.0: `1 + 1` is 2. assert_eq!( - fails(&s, "SELECT regexp_replace('a', 'a', 'b', 1 + 1)").error_class(), - ErrorClass::DatatypeMismatchNonFoldableInput + one("SELECT regexp_replace('a', 'a', 'b', 1 + 1)").as_deref(), + Some("a") + ); + assert_eq!( + one("SELECT regexp_replace('abc', 'b', 'x', 1 + 1)").as_deref(), + Some("axc") ); assert_eq!( one("SELECT regexp_replace('abc', 'b', 'x', CAST(2 AS BIGINT))").as_deref(), @@ -279,6 +291,35 @@ fn regexp_replace_position_is_checked_before_any_row() { ); } +/// Spark checks a count is foldable before its type, and bounds the sum of +/// folded counts (error classes and messages from Spark 4.2.0). +#[test] +fn limit_like_checks_follow_spark_order() { + let s = session(); + let unfoldable = ErrorClass::InvalidLimitLikeExpressionIsUnfoldable; + // A STRING column is not foldable: that, not its type, is the error. + let e = fails( + &s, + "SELECT s FROM (SELECT CAST(id AS STRING) AS s FROM t) LIMIT s", + ); + assert_eq!(e.error_class(), unfoldable, "{e}"); + assert!(e.to_string().contains("\"s\""), "{e}"); + // `OFFSET rand()` (Spark: `IS_UNFOLDABLE` with `"_nondeterministic"`) + // is pinned in the analyzer's tests: `rand` is not implemented yet. + for sql in [ + "SELECT id FROM t LIMIT 2147483647 OFFSET 1 + 0", + "SELECT id FROM t LIMIT 2147483646 + 1 OFFSET 1", + ] { + let e = fails(&s, sql); + assert_eq!( + e.error_class(), + ErrorClass::SumOfLimitAndOffsetExceedsMaxInt, + "{sql}: {e}" + ); + assert!(e.to_string().contains("2147483647"), "{sql}: {e}"); + } +} + /// Results and error classes of Spark 4.2.0 (local session, same data) for /// the edge cases of `OFFSET`. #[test] diff --git a/crates/krishiv-session/tests/window_goldens.rs b/crates/krishiv-session/tests/window_goldens.rs index 02d60f48e..eba6cba02 100644 --- a/crates/krishiv-session/tests/window_goldens.rs +++ b/crates/krishiv-session/tests/window_goldens.rs @@ -29,12 +29,6 @@ use serde_json::Value; /// `KRISHIV_UNSUPPORTED_FEATURE` until then. const PENDING: [&str; 3] = ["rows_sliding", "range_offset", "rows_current_to_end"]; -/// Known gaps outside window functions, with the error they give until -/// fixed: constant arguments fold from literals and casts only, so -/// `ntile(1 + 1)` is not foldable yet (the analyzer's general constant -/// folding of operators is separate P2b work). -const GAPS: [(&str, &str); 1] = [("ntile_folded", "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT")]; - fn fixture() -> Value { let path = Path::new(env!("CARGO_MANIFEST_DIR")) .join("../../tests/fixtures/spark-4.2.0/window-goldens.json"); @@ -231,15 +225,6 @@ fn check(s: &Session, tables: &[&str], case: &Value) -> String { conf.unset(k).unwrap(); } let id = case["id"].as_str().unwrap(); - if let Some((_, class)) = GAPS.iter().find(|(g, _)| *g == id) { - match result { - Err(e) if e.error_class().name() == *class => {} - other => { - let _ = writeln!(out, "{id}: known gap changed (update GAPS): {other:?}"); - } - } - return out; - } if PENDING.contains(&id) { match result { Err(e) if e.error_class().name() == "KRISHIV_UNSUPPORTED_FEATURE" => {} diff --git a/crates/krishiv-sql/tests/analyzer.rs b/crates/krishiv-sql/tests/analyzer.rs index 6f35b4010..74b960ce2 100644 --- a/crates/krishiv-sql/tests/analyzer.rs +++ b/crates/krishiv-sql/tests/analyzer.rs @@ -20,8 +20,8 @@ use krishiv_plan::analyzer::{ ResolutionConf, TableColumn, }; use krishiv_plan::{ - AttrId, Builtin, Expr, ExprNode, FunctionId, JoinCondition, JoinKind, LogicalPlan, PlanNode, - ResolvedExpr, SourceId, + AttrId, Builtin, Expr, ExprNode, FunctionId, JoinCondition, JoinKind, LogicalPlan, + NullOrdering, PlanNode, ResolvedExpr, SortDirection, SourceId, }; use krishiv_sql::{ParserOptions, parse_and_lower, redact_sql}; use serde_json::Value; @@ -31,7 +31,11 @@ fn root() -> &'static Path { } fn goldens() -> Value { - let path = root().join("tests/fixtures/spark-4.2.0/analyzer-goldens.json"); + fixture("analyzer-goldens.json") +} + +fn fixture(name: &str) -> Value { + let path = root().join("tests/fixtures/spark-4.2.0").join(name); serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap() } @@ -382,6 +386,245 @@ fn resolution_corpus_matches_spark() { } } +/// The columns a `Sort` or `Filter` of `plan` reads that its input does +/// not output: a plan like that analyzes but cannot be planned. +fn dangling(plan: &Arc, out: &mut Vec) { + fn reads(e: &Arc, ids: &mut BTreeSet) { + if let ExprNode::Resolved(ResolvedExpr::Column(c)) = &e.node { + ids.insert(c.id); + } + e.for_each_child(&mut |k| reads(k, ids)); + } + if let PlanNode::Sort { input, .. } | PlanNode::Filter { input, .. } = &plan.node { + let have: BTreeSet = input + .resolved_output() + .unwrap() + .iter() + .map(|c| c.id) + .collect(); + let mut used = BTreeSet::new(); + plan.for_each_expr(&mut |e| reads(e, &mut used)); + for id in used.difference(&have) { + out.push(format!("{id:?} in\n{plan}")); + } + } + plan.for_each_child(&mut |c| dangling(c, out)); +} + +/// Every `Sort` of `plan`, in walk order: its keys' direction and null +/// ordering, and whether it is global (`ORDER BY`) or not (`SORT BY`). +fn sorts_of(plan: &Arc, out: &mut Vec<(Vec<(SortDirection, NullOrdering)>, bool)>) { + fn exprs(e: &Arc, out: &mut Vec<(Vec<(SortDirection, NullOrdering)>, bool)>) { + if let ExprNode::Subquery { plan, .. } = &e.node { + sorts_of(plan, out); + } + e.for_each_child(&mut |k| exprs(k, out)); + } + if let PlanNode::Sort { order, global, .. } = &plan.node { + out.push(( + order.iter().map(|o| (o.direction, o.nulls)).collect(), + *global, + )); + } + plan.for_each_child(&mut |c| sorts_of(c, out)); + plan.for_each_expr(&mut |e| exprs(e, out)); +} + +/// Sort keys of `plan` that are not bound: unresolved, reading an outer +/// query, or naming no attribute of the sort's input. +fn unbound_sorts(plan: &Arc, out: &mut Vec) { + if let PlanNode::Sort { order, input, .. } = &plan.node { + let have: BTreeSet = input + .resolved_output() + .unwrap() + .iter() + .map(|c| c.id) + .collect(); + for o in order { + if !o.expr.is_resolved() { + out.push(format!("unresolved sort key in\n{plan}")); + } + let mut stack = vec![&o.expr]; + while let Some(e) = stack.pop() { + match &e.node { + ExprNode::Resolved(ResolvedExpr::Column(c)) => { + if !have.contains(&c.id) { + out.push(format!("unbound sort key {c:?} in\n{plan}")); + } + } + ExprNode::Resolved(ResolvedExpr::OuterColumn(c)) => { + out.push(format!("outer sort key {c:?} in\n{plan}")); + } + ExprNode::Column(_) + | ExprNode::Star(_) + | ExprNode::Function(_) + | ExprNode::Alias { .. } => { + out.push(format!("unresolved sort key in\n{plan}")); + } + _ => {} + } + e.for_each_child(&mut |k| stack.push(k)); + } + } + } + plan.for_each_child(&mut |c| unbound_sorts(c, out)); + plan.for_each_expr(&mut |e| { + if let ExprNode::Subquery { plan, .. } = &e.node { + unbound_sorts(plan, out); + } + }); +} + +/// The sort keys of the single `Sort` of a resolved plan: the column each +/// key reads when it is one, else its display. +fn top_sort_keys(plan: &Arc) -> Vec<(String, SortDirection, NullOrdering)> { + let mut stack = vec![Arc::clone(plan)]; + let mut found = None; + while let Some(p) = stack.pop() { + if let PlanNode::Sort { order, .. } = &p.node { + found = Some(order.clone()); + break; + } + p.for_each_child(&mut |c| stack.push(Arc::clone(c))); + } + let order = found.unwrap(); + order + .iter() + .map(|o| (key_name(&o.expr), o.direction, o.nulls)) + .collect() +} + +fn key_name(e: &Arc) -> String { + match &e.node { + ExprNode::Resolved(ResolvedExpr::Column(c)) => c.name.clone(), + _ => format!("{e}"), + } +} + +/// Constant folding of the arguments that need a constant (`round`'s and +/// `ceil`'s scale, `date_part`'s field, `LIMIT`), ORDER BY and HAVING over +/// grouping expressions: Spark's outcome for each statement +/// (`analyzer-folding-goldens.json`, generated with +/// `gen_analyzer_goldens.py --section folding`). +#[test] +fn folding_and_grouped_ordering_match_spark() { + let g = fixture("analyzer-folding-goldens.json"); + let mut failures = Vec::new(); + let mut raised = BTreeSet::new(); + for case in g["corpus"].as_array().unwrap() { + let sql = case["sql"].as_str().unwrap(); + let got = analyze(&g, sql, conf(&case["conf"])); + if let Some(diff) = compare(sql, &got, case) { + failures.push(format!("{sql} {}: {diff}", case["conf"])); + } + match &got { + Ok(a) => { + let mut bad = Vec::new(); + dangling(a.plan.root(), &mut bad); + failures.extend(bad.into_iter().map(|b| format!("{sql}: dangling {b}"))); + // Grouped ordering keeps the lowered sorts: the same sorts, + // keys, directions and null ordering, all bound. + let lowered = parse_and_lower(sql, &ParserOptions::default(), SourceId(0)) + .expect("a passing case lowers"); + let mut low = Vec::new(); + sorts_of(lowered.root(), &mut low); + let mut high = Vec::new(); + sorts_of(a.plan.root(), &mut high); + if low.len() != high.len() { + failures.push(format!( + "{sql}: {} lowered sorts, {} resolved", + low.len(), + high.len() + )); + } else { + for (i, (l, h)) in low.iter().zip(&high).enumerate() { + if l.0.len() != h.0.len() { + failures.push(format!( + "{sql}: sort {i} has {} keys lowered, {} resolved", + l.0.len(), + h.0.len() + )); + } + if l.0 != h.0 { + failures.push(format!( + "{sql}: sort {i} directions/nulls {l:?} lowered, {h:?} resolved" + )); + } + if l.1 != h.1 { + failures.push(format!( + "{sql}: sort {i} global {} lowered, {} resolved", + l.1, h.1 + )); + } + } + } + let mut unbound = Vec::new(); + unbound_sorts(a.plan.root(), &mut unbound); + failures.extend(unbound.into_iter().map(|b| format!("{sql}: {b}"))); + } + Err(e) => { + raised.insert(e.error.error_class().name()); + } + } + } + // Representative grouped orderings resolve to their grouping or + // aggregate attributes, with direction and nulls kept. + for (sql, want) in [ + ( + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1", + vec![( + "m".to_owned(), + SortDirection::Ascending, + NullOrdering::NullsFirst, + )], + ), + ( + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1 DESC, c", + vec![ + ( + "m".to_owned(), + SortDirection::Descending, + NullOrdering::NullsLast, + ), + ( + "c".to_owned(), + SortDirection::Ascending, + NullOrdering::NullsFirst, + ), + ], + ), + ( + "SELECT x m, count(*) c FROM g GROUP BY x HAVING count(*) > 3 ORDER BY sum(l)", + vec![( + "sum(l)".to_owned(), + SortDirection::Ascending, + NullOrdering::NullsFirst, + )], + ), + ] { + let got = analyze(&g, sql, ResolutionConf::default()).expect("representative resolves"); + assert_eq!(top_sort_keys(got.plan.root()), want, "{sql}"); + } + assert!( + failures.is_empty(), + "{} failures:\n{}", + failures.len(), + failures.join("\n") + ); + for class in [ + "ARITHMETIC_OVERFLOW", + "DIVIDE_BY_ZERO", + "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "NON_FOLDABLE_ARGUMENT", + "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "INVALID_LIMIT_LIKE_EXPRESSION.IS_NULL", + "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE", + ] { + assert!(raised.contains(class), "{class} not raised"); + } +} + /// SQL text inside a plan resolves through the front end, which keeps it /// redacted; its parse errors keep their span and never echo a secret. #[test] @@ -477,15 +720,6 @@ fn window_goldens_resolve_to_a_fixed_point() { let plan = parse_and_lower(sql, &ParserOptions::default(), SourceId(0)).unwrap(); let a = match block_on(DefaultAnalyzer.analyze(&plan, &ctx)) { Ok(a) => a, - // A known gap outside windows (`krishiv-session`'s - // `window_goldens` lists it): constant arguments fold from - // literals and casts only, so `ntile(1 + 1)` is not foldable yet. - Err(e) - if case["id"] == "ntile_folded" - && e.error.error_class().name() == "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT" => - { - continue; - } // Frames with value bounds are a later part of P2-T055. Err(e) if e.error.error_class().name() == "KRISHIV_UNSUPPORTED_FEATURE" => { pending.push(case["id"].as_str().unwrap()); @@ -523,6 +757,68 @@ fn window_goldens_resolve_to_a_fixed_point() { } } assert_eq!(pending, ["rows_sliding", "range_offset"]); - assert_eq!(resolved, 66); + assert_eq!(resolved, 67); assert!(failures.is_empty(), "{}", failures.join("\n")); } + +/// Foldable expressions the analyzer evaluates for typing: casts to string +/// and date, datetime functions of literals and function-form `concat`. +/// Spark folds them at analysis time, so a `LIMIT`, a legacy day count and +/// a `round` scale read them; only what Spark itself calls not foldable (a +/// column, a nondeterministic call) stays `IS_UNFOLDABLE`. +#[test] +fn foldable_limits_day_counts_and_scales_match_spark() { + let g = goldens(); + let ansi = ResolutionConf::default(); + let legacy = conf(&serde_json::json!({ "spark.sql.ansi.enabled": "false" })); + // A `LIMIT` over a foldable expression resolves, whatever the analyzer + // evaluates it to (Spark returns rows for both). + for sql in [ + "SELECT * FROM t LIMIT length(CAST(12 AS STRING))", + "SELECT * FROM t LIMIT year(DATE'2024-01-01') - 2020", + "SELECT * FROM t LIMIT length(concat('a', 'b'))", + ] { + assert!( + analyze(&g, sql, ansi).is_ok(), + "{sql}: Spark returns rows, the analyzer must resolve it" + ); + } + // A column in a `LIMIT` is what Spark calls not foldable. + let err = analyze(&g, "SELECT * FROM t LIMIT a", ansi).unwrap_err(); + assert_eq!( + err.error.error_class().name(), + "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE" + ); + // Foldable but beyond what the folder evaluates: Spark folds them, so + // they resolve here and the downstream folders read them + // (`current_date` is deterministic to Spark, so foldable, but the + // folder has no query clock; `md5` is deterministic too, but outside + // the folder's pure families). + for sql in [ + "SELECT * FROM t LIMIT year(current_date)", + "SELECT * FROM t LIMIT length(md5('a'))", + ] { + assert!( + analyze(&g, sql, ansi).is_ok(), + "{sql}: Spark folds it, so it must resolve" + ); + } + // The legacy day count reads through a cast to string, shown as the + // integer Spark's `StringLiteralCoercion` folds it to. + let a = analyze(&g, "SELECT date_add(dt, CAST(1 AS STRING)) FROM n", legacy) + .expect("Spark folds the legacy day count"); + assert_eq!(a.output[0].name, "date_add(dt, 1)"); + assert_eq!(a.output[0].data_type.simple_string(), "date"); + // `round` reads its scale through function-form `concat`. + let a = analyze(&g, "SELECT round(dc, length(concat('a','b'))) FROM n", ansi) + .expect("Spark folds the round scale"); + assert_eq!(a.output[0].data_type.simple_string(), "decimal(11,2)"); + // A `concat` argument that needs its own cast folds through it too. + let a = analyze( + &g, + "SELECT round(dc, length(concat('a', CAST(1 AS STRING)))) FROM n", + ansi, + ) + .expect("Spark folds the round scale through the cast"); + assert_eq!(a.output[0].data_type.simple_string(), "decimal(11,2)"); +} diff --git a/tests/fixtures/spark-4.2.0/analyzer-folding-goldens.json b/tests/fixtures/spark-4.2.0/analyzer-folding-goldens.json new file mode 100644 index 000000000..cfdaba83a --- /dev/null +++ b/tests/fixtures/spark-4.2.0/analyzer-folding-goldens.json @@ -0,0 +1,6801 @@ +{ + "format_version": 1, + "spark_version": "4.2.0", + "generator": "tests/scripts/gen_analyzer_goldens.py", + "notes": "Output columns or error (condition, SQLSTATE, message parameters, query context) of Spark's analyzer per case, over empty parquet tables in spark_catalog.default whose schemas are `tables`.", + "tables": { + "part": [ + { + "name": "p_partkey", + "type": "bigint", + "nullable": true + }, + { + "name": "p_name", + "type": "string", + "nullable": true + }, + { + "name": "p_mfgr", + "type": "string", + "nullable": true + }, + { + "name": "p_brand", + "type": "string", + "nullable": true + }, + { + "name": "p_type", + "type": "string", + "nullable": true + }, + { + "name": "p_size", + "type": "int", + "nullable": true + }, + { + "name": "p_container", + "type": "string", + "nullable": true + }, + { + "name": "p_retailprice", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "p_comment", + "type": "string", + "nullable": true + } + ], + "supplier": [ + { + "name": "s_suppkey", + "type": "bigint", + "nullable": true + }, + { + "name": "s_name", + "type": "string", + "nullable": true + }, + { + "name": "s_address", + "type": "string", + "nullable": true + }, + { + "name": "s_nationkey", + "type": "bigint", + "nullable": true + }, + { + "name": "s_phone", + "type": "string", + "nullable": true + }, + { + "name": "s_acctbal", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "s_comment", + "type": "string", + "nullable": true + } + ], + "partsupp": [ + { + "name": "ps_partkey", + "type": "bigint", + "nullable": true + }, + { + "name": "ps_suppkey", + "type": "bigint", + "nullable": true + }, + { + "name": "ps_availqty", + "type": "int", + "nullable": true + }, + { + "name": "ps_supplycost", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "ps_comment", + "type": "string", + "nullable": true + } + ], + "customer": [ + { + "name": "c_custkey", + "type": "bigint", + "nullable": true + }, + { + "name": "c_name", + "type": "string", + "nullable": true + }, + { + "name": "c_address", + "type": "string", + "nullable": true + }, + { + "name": "c_nationkey", + "type": "bigint", + "nullable": true + }, + { + "name": "c_phone", + "type": "string", + "nullable": true + }, + { + "name": "c_acctbal", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "c_mktsegment", + "type": "string", + "nullable": true + }, + { + "name": "c_comment", + "type": "string", + "nullable": true + } + ], + "orders": [ + { + "name": "o_orderkey", + "type": "bigint", + "nullable": true + }, + { + "name": "o_custkey", + "type": "bigint", + "nullable": true + }, + { + "name": "o_orderstatus", + "type": "string", + "nullable": true + }, + { + "name": "o_totalprice", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "o_orderdate", + "type": "date", + "nullable": true + }, + { + "name": "o_orderpriority", + "type": "string", + "nullable": true + }, + { + "name": "o_clerk", + "type": "string", + "nullable": true + }, + { + "name": "o_shippriority", + "type": "int", + "nullable": true + }, + { + "name": "o_comment", + "type": "string", + "nullable": true + } + ], + "lineitem": [ + { + "name": "l_orderkey", + "type": "bigint", + "nullable": true + }, + { + "name": "l_partkey", + "type": "bigint", + "nullable": true + }, + { + "name": "l_suppkey", + "type": "bigint", + "nullable": true + }, + { + "name": "l_linenumber", + "type": "int", + "nullable": true + }, + { + "name": "l_quantity", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "l_extendedprice", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "l_discount", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "l_tax", + "type": "decimal(15,2)", + "nullable": true + }, + { + "name": "l_returnflag", + "type": "string", + "nullable": true + }, + { + "name": "l_linestatus", + "type": "string", + "nullable": true + }, + { + "name": "l_shipdate", + "type": "date", + "nullable": true + }, + { + "name": "l_commitdate", + "type": "date", + "nullable": true + }, + { + "name": "l_receiptdate", + "type": "date", + "nullable": true + }, + { + "name": "l_shipinstruct", + "type": "string", + "nullable": true + }, + { + "name": "l_shipmode", + "type": "string", + "nullable": true + }, + { + "name": "l_comment", + "type": "string", + "nullable": true + } + ], + "nation": [ + { + "name": "n_nationkey", + "type": "bigint", + "nullable": true + }, + { + "name": "n_name", + "type": "string", + "nullable": true + }, + { + "name": "n_regionkey", + "type": "bigint", + "nullable": true + }, + { + "name": "n_comment", + "type": "string", + "nullable": true + } + ], + "region": [ + { + "name": "r_regionkey", + "type": "bigint", + "nullable": true + }, + { + "name": "r_name", + "type": "string", + "nullable": true + }, + { + "name": "r_comment", + "type": "string", + "nullable": true + } + ], + "t": [ + { + "name": "a", + "type": "int", + "nullable": true + }, + { + "name": "b", + "type": "string", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": true + } + ], + "u": [ + { + "name": "a", + "type": "int", + "nullable": true + }, + { + "name": "d", + "type": "string", + "nullable": true + } + ], + "wide": [ + { + "name": "col1", + "type": "int", + "nullable": true + }, + { + "name": "col2", + "type": "int", + "nullable": true + }, + { + "name": "col3", + "type": "int", + "nullable": true + }, + { + "name": "col4", + "type": "int", + "nullable": true + }, + { + "name": "col5", + "type": "int", + "nullable": true + }, + { + "name": "col6", + "type": "int", + "nullable": true + }, + { + "name": "col7", + "type": "int", + "nullable": true + }, + { + "name": "colx", + "type": "int", + "nullable": true + } + ], + "MixedCase": [ + { + "name": "Id", + "type": "int", + "nullable": true + }, + { + "name": "Name", + "type": "string", + "nullable": true + } + ], + "g": [ + { + "name": "x", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + } + ], + "n": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + "tpch": [], + "corpus": [ + { + "sql": "SELECT round(dc, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, i) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"i\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"round(dc, i)\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "round(dc, i)" + } + }, + { + "sql": "SELECT round(dc, i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"i\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"round(dc, i)\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "round(dc, i)" + } + }, + { + "sql": "SELECT round(dc, 1+i) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"(1 + i)\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 + i))\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "round(dc, 1+i)" + } + }, + { + "sql": "SELECT round(dc, 1+i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"(1 + i)\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 + i))\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "round(dc, 1+i)" + } + }, + { + "sql": "SELECT round(dc, 2147483647+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "ARITHMETIC_OVERFLOW", + "sql_state": "22003", + "message_parameters": { + "alternative": " Use 'try_add' to tolerate overflow and return NULL instead.", + "config": "\"spark.sql.ansi.enabled\"", + "message": "overflow" + }, + "context": { + "start": 17, + "stop": 28, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT round(dc, 2147483647+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (2147483647 + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (CAST(1 AS BIGINT) + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (CAST(1 AS BIGINT) + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, -(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, -(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5/2) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (5 / 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5/2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (5 / 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5 div 2) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (5 div 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5 div 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (5 div 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5 % 3) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 5 % 3) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1/0) FROM n", + "conf": {}, + "ok": false, + "error_class": "DIVIDE_BY_ZERO", + "sql_state": "22012", + "message_parameters": { + "config": "\"spark.sql.ansi.enabled\"" + }, + "context": { + "start": 17, + "stop": 19, + "fragment": "1/0" + } + }, + { + "sql": "SELECT round(dc, 1/0) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (1 / 0))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, if(true,1,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, if(true,1,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, coalesce(NULL,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, coalesce(NULL,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, abs(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, abs(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, length('abc')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, length('abc')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1.5+1.5) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (1.5 + 1.5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1.5+1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (1.5 + 1.5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1.5D+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (1.5 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1.5D+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (1.5 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, NULL+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (NULL + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, NULL+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (NULL + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 3+5L) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (3 + 5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 3+5L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (3 + 5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 2L) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, 2)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 2L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, 2)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CAST(2 AS INT)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CAST(2 AS INT)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 = 1)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 = 1))\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "round(dc, 1=1)" + } + }, + { + "sql": "SELECT round(dc, 1=1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 = 1)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 = 1))\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "round(dc, 1=1)" + } + }, + { + "sql": "SELECT round(dc, '1'||'1') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, concat(1, 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, '1'||'1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, concat(1, 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, upper('2')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, upper(2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, upper('2')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, upper(2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, (1+1) * (2-1)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, (1+1) * (2-1)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, 1 < 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 < 2)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 < 2))\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "round(dc, 1 < 2)" + } + }, + { + "sql": "SELECT round(dc, 1 < 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 < 2)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (1 < 2))\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "round(dc, 1 < 2)" + } + }, + { + "sql": "SELECT round(dc, NOT TRUE) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(NOT true)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (NOT true))\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "round(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT round(dc, NOT TRUE) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(NOT true)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"round(dc, (NOT true))\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "round(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT round(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, CASE WHEN (1 = 2) THEN (1 / 0) ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, CASE WHEN (1 = 2) THEN (1 / 0) ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, if(1=1, 2, 1/0)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "round(dc, (IF((1 = 1), 2, (1 / 0))))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT round(dc, if(1=1, 2, 1/0)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "round(dc, (IF((1 = 1), 2, (1 / 0))))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, i) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"i\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"bround(dc, i)\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "bround(dc, i)" + } + }, + { + "sql": "SELECT bround(dc, i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"i\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"bround(dc, i)\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "bround(dc, i)" + } + }, + { + "sql": "SELECT bround(dc, 1+i) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"(1 + i)\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 + i))\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "bround(dc, 1+i)" + } + }, + { + "sql": "SELECT bround(dc, 1+i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.NON_FOLDABLE_INPUT", + "sql_state": "42K09", + "message_parameters": { + "inputExpr": "\"(1 + i)\"", + "inputName": "`scale`", + "inputType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 + i))\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "bround(dc, 1+i)" + } + }, + { + "sql": "SELECT bround(dc, 2147483647+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "ARITHMETIC_OVERFLOW", + "sql_state": "22003", + "message_parameters": { + "alternative": " Use 'try_add' to tolerate overflow and return NULL instead.", + "config": "\"spark.sql.ansi.enabled\"", + "message": "overflow" + }, + "context": { + "start": 18, + "stop": 29, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT bround(dc, 2147483647+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (2147483647 + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (CAST(1 AS BIGINT) + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (CAST(1 AS BIGINT) + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, -(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, -(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5/2) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 / 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5/2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 / 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5 div 2) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 div 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5 div 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 div 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5 % 3) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 5 % 3) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1/0) FROM n", + "conf": {}, + "ok": false, + "error_class": "DIVIDE_BY_ZERO", + "sql_state": "22012", + "message_parameters": { + "config": "\"spark.sql.ansi.enabled\"" + }, + "context": { + "start": 18, + "stop": 20, + "fragment": "1/0" + } + }, + { + "sql": "SELECT bround(dc, 1/0) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (1 / 0))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, if(true,1,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, if(true,1,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, coalesce(NULL,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, coalesce(NULL,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, abs(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, abs(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, length('abc')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, length('abc')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1.5+1.5) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (1.5 + 1.5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1.5+1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (1.5 + 1.5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1.5D+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (1.5 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1.5D+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (1.5 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, NULL+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (NULL + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, NULL+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (NULL + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 3+5L) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (3 + 5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 3+5L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (3 + 5))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 2L) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, 2)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 2L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, 2)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CAST(2 AS INT)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CAST(2 AS INT)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 = 1)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 = 1))\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "bround(dc, 1=1)" + } + }, + { + "sql": "SELECT bround(dc, 1=1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 = 1)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 = 1))\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "bround(dc, 1=1)" + } + }, + { + "sql": "SELECT bround(dc, '1'||'1') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, concat(1, 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, '1'||'1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, concat(1, 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, upper('2')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, upper(2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, upper('2')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, upper(2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, (1+1) * (2-1)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, (1+1) * (2-1)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, 1 < 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 < 2)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 < 2))\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "bround(dc, 1 < 2)" + } + }, + { + "sql": "SELECT bround(dc, 1 < 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(1 < 2)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (1 < 2))\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "bround(dc, 1 < 2)" + } + }, + { + "sql": "SELECT bround(dc, NOT TRUE) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(NOT true)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (NOT true))\"" + }, + "context": { + "start": 7, + "stop": 26, + "fragment": "bround(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT bround(dc, NOT TRUE) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"(NOT true)\"", + "inputType": "\"BOOLEAN\"", + "paramIndex": "second", + "requiredType": "\"INT\"", + "sqlExpr": "\"bround(dc, (NOT true))\"" + }, + "context": { + "start": 7, + "stop": 26, + "fragment": "bround(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT bround(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, CASE WHEN (1 = 2) THEN (1 / 0) ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, CASE WHEN (1 = 2) THEN (1 / 0) ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, if(1=1, 2, 1/0)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "bround(dc, (IF((1 = 1), 2, (1 / 0))))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT bround(dc, if(1=1, 2, 1/0)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "bround(dc, (IF((1 = 1), 2, (1 / 0))))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, i) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 17, + "fragment": "ceil(dc, i)" + } + }, + { + "sql": "SELECT ceil(dc, i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 17, + "fragment": "ceil(dc, i)" + } + }, + { + "sql": "SELECT ceil(dc, 1+i) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1+i)" + } + }, + { + "sql": "SELECT ceil(dc, 1+i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1+i)" + } + }, + { + "sql": "SELECT ceil(dc, 2147483647+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "ARITHMETIC_OVERFLOW", + "sql_state": "22003", + "message_parameters": { + "alternative": " Use 'try_add' to tolerate overflow and return NULL instead.", + "config": "\"spark.sql.ansi.enabled\"", + "message": "overflow" + }, + "context": { + "start": 16, + "stop": 27, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT ceil(dc, 2147483647+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, (2147483647 + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 35, + "fragment": "ceil(dc, CAST(1 AS BIGINT)+1)" + } + }, + { + "sql": "SELECT ceil(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 35, + "fragment": "ceil(dc, CAST(1 AS BIGINT)+1)" + } + }, + { + "sql": "SELECT ceil(dc, -(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, -(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 5/2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 5/2)" + } + }, + { + "sql": "SELECT ceil(dc, 5/2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 5/2)" + } + }, + { + "sql": "SELECT ceil(dc, 5 div 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "ceil(dc, 5 div 2)" + } + }, + { + "sql": "SELECT ceil(dc, 5 div 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "ceil(dc, 5 div 2)" + } + }, + { + "sql": "SELECT ceil(dc, 5 % 3) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 5 % 3) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1/0) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1/0)" + } + }, + { + "sql": "SELECT ceil(dc, 1/0) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1/0)" + } + }, + { + "sql": "SELECT ceil(dc, if(true,1,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, if(true,1,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, coalesce(NULL,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, coalesce(NULL,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, abs(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, abs(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, length('abc')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, length('abc')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1.5+1.5) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "ceil(dc, 1.5+1.5)" + } + }, + { + "sql": "SELECT ceil(dc, 1.5+1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "ceil(dc, 1.5+1.5)" + } + }, + { + "sql": "SELECT ceil(dc, 1.5D+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "ceil(dc, 1.5D+1)" + } + }, + { + "sql": "SELECT ceil(dc, 1.5D+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "ceil(dc, 1.5D+1)" + } + }, + { + "sql": "SELECT ceil(dc, NULL+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "ceil(dc, NULL+1)" + } + }, + { + "sql": "SELECT ceil(dc, NULL+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "ceil(dc, NULL+1)" + } + }, + { + "sql": "SELECT ceil(dc, 3+5L) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "ceil(dc, 3+5L)" + } + }, + { + "sql": "SELECT ceil(dc, 3+5L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "ceil(dc, 3+5L)" + } + }, + { + "sql": "SELECT ceil(dc, 2L) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "ceil(dc, 2L)" + } + }, + { + "sql": "SELECT ceil(dc, 2L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "ceil(dc, 2L)" + } + }, + { + "sql": "SELECT ceil(dc, CAST(2 AS INT)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, CAST(2 AS INT)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1=1)" + } + }, + { + "sql": "SELECT ceil(dc, 1=1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "ceil(dc, 1=1)" + } + }, + { + "sql": "SELECT ceil(dc, '1'||'1') FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "ceil(dc, '1'||'1')" + } + }, + { + "sql": "SELECT ceil(dc, '1'||'1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "ceil(dc, '1'||'1')" + } + }, + { + "sql": "SELECT ceil(dc, upper('2')) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 26, + "fragment": "ceil(dc, upper('2'))" + } + }, + { + "sql": "SELECT ceil(dc, upper('2')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 26, + "fragment": "ceil(dc, upper('2'))" + } + }, + { + "sql": "SELECT ceil(dc, (1+1) * (2-1)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ceil(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, (1+1) * (2-1)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ceil(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT ceil(dc, 1 < 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "ceil(dc, 1 < 2)" + } + }, + { + "sql": "SELECT ceil(dc, 1 < 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "ceil(dc, 1 < 2)" + } + }, + { + "sql": "SELECT ceil(dc, NOT TRUE) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "ceil(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT ceil(dc, NOT TRUE) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "ceil(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT ceil(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 49, + "fragment": "ceil(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END)" + } + }, + { + "sql": "SELECT ceil(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 49, + "fragment": "ceil(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END)" + } + }, + { + "sql": "SELECT ceil(dc, if(1=1, 2, 1/0)) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 31, + "fragment": "ceil(dc, if(1=1, 2, 1/0))" + } + }, + { + "sql": "SELECT ceil(dc, if(1=1, 2, 1/0)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`ceil`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 31, + "fragment": "ceil(dc, if(1=1, 2, 1/0))" + } + }, + { + "sql": "SELECT floor(dc, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, (1 + 1))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, i) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "floor(dc, i)" + } + }, + { + "sql": "SELECT floor(dc, i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "floor(dc, i)" + } + }, + { + "sql": "SELECT floor(dc, 1+i) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1+i)" + } + }, + { + "sql": "SELECT floor(dc, 1+i) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1+i)" + } + }, + { + "sql": "SELECT floor(dc, 2147483647+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "ARITHMETIC_OVERFLOW", + "sql_state": "22003", + "message_parameters": { + "alternative": " Use 'try_add' to tolerate overflow and return NULL instead.", + "config": "\"spark.sql.ansi.enabled\"", + "message": "overflow" + }, + "context": { + "start": 17, + "stop": 28, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT floor(dc, 2147483647+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, (2147483647 + 1))", + "type": "decimal(9,0)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 36, + "fragment": "floor(dc, CAST(1 AS BIGINT)+1)" + } + }, + { + "sql": "SELECT floor(dc, CAST(1 AS BIGINT)+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 36, + "fragment": "floor(dc, CAST(1 AS BIGINT)+1)" + } + }, + { + "sql": "SELECT floor(dc, -(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, -(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, (- -2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 5/2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 5/2)" + } + }, + { + "sql": "SELECT floor(dc, 5/2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 5/2)" + } + }, + { + "sql": "SELECT floor(dc, 5 div 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "floor(dc, 5 div 2)" + } + }, + { + "sql": "SELECT floor(dc, 5 div 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "floor(dc, 5 div 2)" + } + }, + { + "sql": "SELECT floor(dc, 5 % 3) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 5 % 3) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, (5 % 3))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 1/0) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1/0)" + } + }, + { + "sql": "SELECT floor(dc, 1/0) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1/0)" + } + }, + { + "sql": "SELECT floor(dc, if(true,1,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, if(true,1,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, (IF(true, 1, 2)))", + "type": "decimal(10,1)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, CASE WHEN 1=1 THEN 3 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, CASE WHEN (1 = 1) THEN 3 ELSE 2 END)", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, coalesce(NULL,2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, coalesce(NULL,2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, coalesce(NULL, 2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, abs(-2)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, abs(-2)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, abs(-2))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, length('abc')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, length('abc')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, length(abc))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 1.5+1.5) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "floor(dc, 1.5+1.5)" + } + }, + { + "sql": "SELECT floor(dc, 1.5+1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "floor(dc, 1.5+1.5)" + } + }, + { + "sql": "SELECT floor(dc, 1.5D+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "floor(dc, 1.5D+1)" + } + }, + { + "sql": "SELECT floor(dc, 1.5D+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "floor(dc, 1.5D+1)" + } + }, + { + "sql": "SELECT floor(dc, NULL+1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "floor(dc, NULL+1)" + } + }, + { + "sql": "SELECT floor(dc, NULL+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "floor(dc, NULL+1)" + } + }, + { + "sql": "SELECT floor(dc, 3+5L) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "floor(dc, 3+5L)" + } + }, + { + "sql": "SELECT floor(dc, 3+5L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "floor(dc, 3+5L)" + } + }, + { + "sql": "SELECT floor(dc, 2L) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "floor(dc, 2L)" + } + }, + { + "sql": "SELECT floor(dc, 2L) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "floor(dc, 2L)" + } + }, + { + "sql": "SELECT floor(dc, CAST(2 AS INT)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, CAST(2 AS INT)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, CAST(2 AS INT))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1=1)" + } + }, + { + "sql": "SELECT floor(dc, 1=1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "floor(dc, 1=1)" + } + }, + { + "sql": "SELECT floor(dc, '1'||'1') FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "floor(dc, '1'||'1')" + } + }, + { + "sql": "SELECT floor(dc, '1'||'1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "floor(dc, '1'||'1')" + } + }, + { + "sql": "SELECT floor(dc, upper('2')) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 27, + "fragment": "floor(dc, upper('2'))" + } + }, + { + "sql": "SELECT floor(dc, upper('2')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 27, + "fragment": "floor(dc, upper('2'))" + } + }, + { + "sql": "SELECT floor(dc, (1+1) * (2-1)) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "floor(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, (1+1) * (2-1)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "floor(dc, ((1 + 1) * (2 - 1)))", + "type": "decimal(11,2)", + "nullable": true + } + ] + }, + { + "sql": "SELECT floor(dc, 1 < 2) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "floor(dc, 1 < 2)" + } + }, + { + "sql": "SELECT floor(dc, 1 < 2) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "floor(dc, 1 < 2)" + } + }, + { + "sql": "SELECT floor(dc, NOT TRUE) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "floor(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT floor(dc, NOT TRUE) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "floor(dc, NOT TRUE)" + } + }, + { + "sql": "SELECT floor(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 50, + "fragment": "floor(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END)" + } + }, + { + "sql": "SELECT floor(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 50, + "fragment": "floor(dc, CASE WHEN 1=2 THEN 1/0 ELSE 2 END)" + } + }, + { + "sql": "SELECT floor(dc, if(1=1, 2, 1/0)) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 32, + "fragment": "floor(dc, if(1=1, 2, 1/0))" + } + }, + { + "sql": "SELECT floor(dc, if(1=1, 2, 1/0)) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`floor`", + "paramName": "`scale`", + "paramType": "\"INT\"" + }, + "context": { + "start": 7, + "stop": 32, + "fragment": "floor(dc, if(1=1, 2, 1/0))" + } + }, + { + "sql": "SELECT date_part('y'||'ear', dt) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_part(concat(y, ear), dt)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part('y'||'ear', dt) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_part(concat(y, ear), dt)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part(s, dt) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`date_part`", + "paramName": "`field`", + "paramType": "\"STRING\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "date_part(s, dt)" + } + }, + { + "sql": "SELECT date_part(s, dt) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`date_part`", + "paramName": "`field`", + "paramType": "\"STRING\"" + }, + "context": { + "start": 7, + "stop": 22, + "fragment": "date_part(s, dt)" + } + }, + { + "sql": "SELECT date_part(CAST(NULL AS STRING), dt) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_part(CAST(NULL AS STRING), dt)", + "type": "double", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part(CAST(NULL AS STRING), dt) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_part(CAST(NULL AS STRING), dt)", + "type": "double", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part(upper('year'), dt) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_part(upper(year), dt)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part(upper('year'), dt) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_part(upper(year), dt)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_part(1+1, dt) FROM n", + "conf": {}, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`date_part`", + "paramName": "`field`", + "paramType": "\"STRING\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "date_part(1+1, dt)" + } + }, + { + "sql": "SELECT date_part(1+1, dt) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "NON_FOLDABLE_ARGUMENT", + "sql_state": "42K08", + "message_parameters": { + "funcName": "`date_part`", + "paramName": "`field`", + "paramType": "\"STRING\"" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "date_part(1+1, dt)" + } + }, + { + "sql": "SELECT first(i, true) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "first(i)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT first(i, false) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "first(i)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT first(i, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "first(i, 1=1)" + } + }, + { + "sql": "SELECT first(i, true AND true) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 29, + "fragment": "first(i, true AND true)" + } + }, + { + "sql": "SELECT first(i, i > 1) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "first(i, i > 1)" + } + }, + { + "sql": "SELECT first(i, NOT FALSE) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 25, + "fragment": "first(i, NOT FALSE)" + } + }, + { + "sql": "SELECT first(i, NULL) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "first(i, NULL)" + } + }, + { + "sql": "SELECT first(i, CAST(true AS BOOLEAN)) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "first" + }, + "context": { + "start": 7, + "stop": 37, + "fragment": "first(i, CAST(true AS BOOLEAN))" + } + }, + { + "sql": "SELECT last(i, true) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "last(i)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT last(i, false) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "last(i)", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT last(i, 1=1) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 18, + "fragment": "last(i, 1=1)" + } + }, + { + "sql": "SELECT last(i, true AND true) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 28, + "fragment": "last(i, true AND true)" + } + }, + { + "sql": "SELECT last(i, i > 1) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 20, + "fragment": "last(i, i > 1)" + } + }, + { + "sql": "SELECT last(i, NOT FALSE) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 24, + "fragment": "last(i, NOT FALSE)" + } + }, + { + "sql": "SELECT last(i, NULL) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 19, + "fragment": "last(i, NULL)" + } + }, + { + "sql": "SELECT last(i, CAST(true AS BOOLEAN)) FROM n", + "conf": {}, + "ok": false, + "error_class": "_LEGACY_ERROR_TEMP_1210", + "sql_state": null, + "message_parameters": { + "funcName": "last" + }, + "context": { + "start": 7, + "stop": 36, + "fragment": "last(i, CAST(true AS BOOLEAN))" + } + }, + { + "sql": "SELECT date_add(dt, '1'||'2') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, concat(1, 2))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1'||'2') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 12)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1'||'.5') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, concat(1, .5))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1'||'.5') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, upper('1')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, upper(1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, upper('1')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 1)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, (1 + 1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, (1 + 1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, 'a') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, a)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, 'a') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, s) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_add(dt, s)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, s) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"s\"", + "inputType": "\"STRING\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_add(dt, s)\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "date_add(dt, s)" + } + }, + { + "sql": "SELECT date_add(dt, 1.5) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"1.5\"", + "inputType": "\"DECIMAL(2,1)\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_add(dt, 1.5)\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "date_add(dt, 1.5)" + } + }, + { + "sql": "SELECT date_add(dt, 1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"1.5\"", + "inputType": "\"DECIMAL(2,1)\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_add(dt, 1.5)\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "date_add(dt, 1.5)" + } + }, + { + "sql": "SELECT date_sub(dt, '1'||'2') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, concat(1, 2))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, '1'||'2') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_sub(dt, 12)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, '1'||'.5') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, concat(1, .5))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, '1'||'.5') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_sub" + } + }, + { + "sql": "SELECT date_sub(dt, upper('1')) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, upper(1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, upper('1')) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_sub(dt, 1)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, 1+1) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, (1 + 1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, 1+1) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_sub(dt, (1 + 1))", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, 'a') FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, a)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, 'a') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_sub" + } + }, + { + "sql": "SELECT date_sub(dt, s) FROM n", + "conf": {}, + "ok": true, + "output": [ + { + "name": "date_sub(dt, s)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_sub(dt, s) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"s\"", + "inputType": "\"STRING\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_sub(dt, s)\"" + }, + "context": { + "start": 7, + "stop": 21, + "fragment": "date_sub(dt, s)" + } + }, + { + "sql": "SELECT date_sub(dt, 1.5) FROM n", + "conf": {}, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"1.5\"", + "inputType": "\"DECIMAL(2,1)\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_sub(dt, 1.5)\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "date_sub(dt, 1.5)" + } + }, + { + "sql": "SELECT date_sub(dt, 1.5) FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE", + "sql_state": "42K09", + "message_parameters": { + "inputSql": "\"1.5\"", + "inputType": "\"DECIMAL(2,1)\"", + "paramIndex": "second", + "requiredType": "(\"INT\" or \"SMALLINT\" or \"TINYINT\")", + "sqlExpr": "\"date_sub(dt, 1.5)\"" + }, + "context": { + "start": 7, + "stop": 23, + "fragment": "date_sub(dt, 1.5)" + } + }, + { + "sql": "SELECT date_add(dt, '1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 1)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1.5') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, ' 12 ') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 12)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '+3') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 3)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1.') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '.5') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '1e2') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '0x1') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '2147483648') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '-0') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "date_add(dt, 0)", + "type": "date", + "nullable": true + } + ] + }, + { + "sql": "SELECT date_add(dt, '1.0') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, 'abc') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, ' ') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT date_add(dt, '1 2') FROM n", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER", + "sql_state": "22023", + "message_parameters": { + "functionName": "date_add" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1+1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT 1+1", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT i", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"i\"", + "name": "limit" + }, + "context": { + "start": 0, + "stop": 14, + "fragment": "SELECT * FROM n" + } + }, + { + "sql": "SELECT * FROM n LIMIT i", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"i\"", + "name": "limit" + }, + "context": { + "start": 0, + "stop": 14, + "fragment": "SELECT * FROM n" + } + }, + { + "sql": "SELECT * FROM n LIMIT 2147483647+1", + "conf": {}, + "ok": false, + "error_class": "ARITHMETIC_OVERFLOW", + "sql_state": "22003", + "message_parameters": { + "alternative": " Use 'try_add' to tolerate overflow and return NULL instead.", + "config": "\"spark.sql.ansi.enabled\"", + "message": "overflow" + }, + "context": { + "start": 22, + "stop": 33, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT * FROM n LIMIT 2147483647+1", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"(2147483647 + 1)\"", + "name": "limit", + "v": "-2147483648" + }, + "context": { + "start": 22, + "stop": 33, + "fragment": "2147483647+1" + } + }, + { + "sql": "SELECT * FROM n LIMIT length('ab')", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT length('ab')", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT CAST(NULL AS INT)", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NULL", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"CAST(NULL AS INT)\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 38, + "fragment": "CAST(NULL AS INT)" + } + }, + { + "sql": "SELECT * FROM n LIMIT CAST(NULL AS INT)", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NULL", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"CAST(NULL AS INT)\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 38, + "fragment": "CAST(NULL AS INT)" + } + }, + { + "sql": "SELECT * FROM n LIMIT -1", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"-1\"", + "name": "limit", + "v": "-1" + }, + "context": { + "start": 22, + "stop": 23, + "fragment": "-1" + } + }, + { + "sql": "SELECT * FROM n LIMIT -1", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"-1\"", + "name": "limit", + "v": "-1" + }, + "context": { + "start": 22, + "stop": 23, + "fragment": "-1" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1+(-2)", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"(1 + -2)\"", + "name": "limit", + "v": "-1" + }, + "context": { + "start": 22, + "stop": 27, + "fragment": "1+(-2)" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1+(-2)", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_NEGATIVE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"(1 + -2)\"", + "name": "limit", + "v": "-1" + }, + "context": { + "start": 22, + "stop": 27, + "fragment": "1+(-2)" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1L", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"BIGINT\"", + "expr": "\"1\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 23, + "fragment": "1L" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1L", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"BIGINT\"", + "expr": "\"1\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 23, + "fragment": "1L" + } + }, + { + "sql": "SELECT * FROM n LIMIT '1'", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"STRING\"", + "expr": "\"1\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 24, + "fragment": "'1'" + } + }, + { + "sql": "SELECT * FROM n LIMIT '1'", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"STRING\"", + "expr": "\"1\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 24, + "fragment": "'1'" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1.5", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"DECIMAL(2,1)\"", + "expr": "\"1.5\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 24, + "fragment": "1.5" + } + }, + { + "sql": "SELECT * FROM n LIMIT 1.5", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.DATA_TYPE", + "sql_state": "42K0E", + "message_parameters": { + "dataType": "\"DECIMAL(2,1)\"", + "expr": "\"1.5\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 24, + "fragment": "1.5" + } + }, + { + "sql": "SELECT * FROM n LIMIT CASE WHEN 1=1 THEN 5 ELSE 6 END", + "conf": {}, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT CASE WHEN 1=1 THEN 5 ELSE 6 END", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": true, + "output": [ + { + "name": "ti", + "type": "tinyint", + "nullable": true + }, + { + "name": "si", + "type": "smallint", + "nullable": true + }, + { + "name": "i", + "type": "int", + "nullable": true + }, + { + "name": "l", + "type": "bigint", + "nullable": true + }, + { + "name": "f", + "type": "float", + "nullable": true + }, + { + "name": "d", + "type": "double", + "nullable": true + }, + { + "name": "dc", + "type": "decimal(10,2)", + "nullable": true + }, + { + "name": "dw", + "type": "decimal(38,10)", + "nullable": true + }, + { + "name": "s", + "type": "string", + "nullable": true + }, + { + "name": "bo", + "type": "boolean", + "nullable": true + }, + { + "name": "dt", + "type": "date", + "nullable": true + }, + { + "name": "ts", + "type": "timestamp", + "nullable": true + }, + { + "name": "tn", + "type": "timestamp_ntz", + "nullable": true + }, + { + "name": "bi", + "type": "binary", + "nullable": true + } + ] + }, + { + "sql": "SELECT * FROM n LIMIT (SELECT 1)", + "conf": {}, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"scalarsubquery()\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 31, + "fragment": "(SELECT 1)" + } + }, + { + "sql": "SELECT * FROM n LIMIT (SELECT 1)", + "conf": { + "spark.sql.ansi.enabled": "false" + }, + "ok": false, + "error_class": "INVALID_LIMIT_LIKE_EXPRESSION.IS_UNFOLDABLE", + "sql_state": "42K0E", + "message_parameters": { + "expr": "\"scalarsubquery()\"", + "name": "limit" + }, + "context": { + "start": 22, + "stop": 31, + "fragment": "(SELECT 1)" + } + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 2", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 58, + "stop": 58, + "fragment": "x" + } + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY 1 + x", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY m + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 58, + "stop": 58, + "fragment": "x" + } + }, + { + "sql": "SELECT x m, count(*) c FROM g GROUP BY x ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY abs(x + 1)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY (x + 1) * count(*)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY sum(x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY sum(x + 1)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 2 > 3", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 56, + "stop": 56, + "fragment": "x" + } + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3", + "conf": {}, + "ok": true, + "output": [ + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`" + }, + "context": { + "start": 66, + "stop": 66, + "fragment": "x" + } + }, + { + "sql": "SELECT sum(l) FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1 DESC", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`sum(l)`" + }, + "context": { + "start": 62, + "stop": 62, + "fragment": "x" + } + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 2", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`" + }, + "context": { + "start": 66, + "stop": 66, + "fragment": "x" + } + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x HAVING sum(l) > 1 ORDER BY sum(l)", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`" + }, + "context": { + "start": 67, + "stop": 67, + "fragment": "l" + } + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x HAVING sum(l) > 1 ORDER BY c", + "conf": {}, + "ok": true, + "output": [ + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 HAVING sum(l) > 1 ORDER BY x + 1", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`" + }, + "context": { + "start": 67, + "stop": 67, + "fragment": "x" + } + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x HAVING x > 1 ORDER BY sum(l)", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`" + }, + "context": { + "start": 62, + "stop": 62, + "fragment": "l" + } + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x HAVING count(*) > 0 ORDER BY sum(l)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 0 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY m ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT DISTINCT x + 1 FROM g ORDER BY x + 1", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`(x + 1)`" + }, + "context": { + "start": 38, + "stop": 38, + "fragment": "x" + } + }, + { + "sql": "SELECT DISTINCT x + 1 m FROM g ORDER BY x + 2", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`m`" + }, + "context": { + "start": 40, + "stop": 40, + "fragment": "x" + } + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1 DESC, c", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT abs(x) m FROM g GROUP BY abs(x) ORDER BY abs(x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT X + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY X + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT g.x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY g.x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY g.x + 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT sum(x) + 1 m FROM g GROUP BY x + 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + } + ] + }, + { + "sql": "SELECT sum(x) s FROM g GROUP BY x + 1 ORDER BY x + 1, s", + "conf": {}, + "ok": true, + "output": [ + { + "name": "s", + "type": "bigint", + "nullable": true + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1 + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT cast(x as string) m, count(*) c FROM g GROUP BY cast(x as string) ORDER BY cast(x as string)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "string", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY (SELECT 1) + x + 1", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`x`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 71, + "stop": 71, + "fragment": "x" + } + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY CASE WHEN x + 1 > 1 THEN 1 ELSE 2 END", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x + 1) * 2 m FROM g GROUP BY x + 1 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT (x + 1) * 2 m FROM g GROUP BY x + 1 ORDER BY (x + 1) * 2", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT x + l m, count(*) c FROM g GROUP BY x + l ORDER BY l + x", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x * l m, count(*) c FROM g GROUP BY x * l ORDER BY l * x", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x = 1 AND l = 2) m, count(*) c FROM g GROUP BY (x = 1 AND l = 2) ORDER BY (l = 2 AND x = 1)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x = 1 OR l = 2) m, count(*) c FROM g GROUP BY (x = 1 OR l = 2) ORDER BY (l = 2 OR x = 1)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x = l) m, count(*) c FROM g GROUP BY (x = l) ORDER BY (l = x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x <=> l) m, count(*) c FROM g GROUP BY (x <=> l) ORDER BY (l <=> x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": false + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x < l) m, count(*) c FROM g GROUP BY (x < l) ORDER BY (l > x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT (x <= l) m, count(*) c FROM g GROUP BY (x <= l) ORDER BY (l >= x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "boolean", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT greatest(x, l) m, count(*) c FROM g GROUP BY greatest(x, l) ORDER BY greatest(l, x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT least(x, l) m, count(*) c FROM g GROUP BY least(x, l) ORDER BY least(l, x)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x - l m, count(*) c FROM g GROUP BY x - l ORDER BY l - x", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 58, + "stop": 58, + "fragment": "l" + } + }, + { + "sql": "SELECT concat(cast(x as string), cast(l as string)) m, count(*) c FROM g GROUP BY concat(cast(x as string), cast(l as string)) ORDER BY concat(cast(l as string), cast(x as string))", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 148, + "stop": 148, + "fragment": "l" + } + }, + { + "sql": "SELECT coalesce(x, l) m, count(*) c FROM g GROUP BY coalesce(x, l) ORDER BY coalesce(l, x)", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 85, + "stop": 85, + "fragment": "l" + } + }, + { + "sql": "SELECT (x + 1) + 2 m, count(*) c FROM g GROUP BY (x + 1) + 2 ORDER BY x + (1 + 2)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 + l m, count(*) c FROM g GROUP BY x + 1 + l ORDER BY l + 1 + x", + "conf": {}, + "ok": false, + "error_class": "UNRESOLVED_COLUMN.WITH_SUGGESTION", + "sql_state": "42703", + "message_parameters": { + "objectName": "`l`", + "proposal": "`c`, `m`" + }, + "context": { + "start": 66, + "stop": 66, + "fragment": "l" + } + }, + { + "sql": "SELECT x + l m, count(*) c FROM g GROUP BY l + x ORDER BY x + l", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT l - l % 60 m, count(*) c FROM g WHERE x = 62 GROUP BY l - l % 60 ORDER BY l - l % 60 LIMIT 10", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "bigint", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x m, count(*) c FROM g GROUP BY x HAVING x > 3 ORDER BY x", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x m, count(*) c FROM g GROUP BY x HAVING x > 3 ORDER BY sum(l)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x m, count(*) c FROM g GROUP BY x HAVING count(*) > 3 ORDER BY sum(l)", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x m FROM g GROUP BY x HAVING count(*) > 3 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 3 ORDER BY x + 1", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + }, + { + "sql": "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 3 ORDER BY m", + "conf": {}, + "ok": true, + "output": [ + { + "name": "m", + "type": "int", + "nullable": true + }, + { + "name": "c", + "type": "bigint", + "nullable": false + } + ] + } + ], + "plan_ids": [] +} diff --git a/tests/scripts/gen_analyzer_goldens.py b/tests/scripts/gen_analyzer_goldens.py index 6e2dcebbe..fb564ddb8 100644 --- a/tests/scripts/gen_analyzer_goldens.py +++ b/tests/scripts/gen_analyzer_goldens.py @@ -52,6 +52,7 @@ "u": "a INT, d STRING", "wide": "col1 INT, col2 INT, col3 INT, col4 INT, col5 INT, col6 INT, col7 INT, colx INT", "MixedCase": "Id INT, Name STRING", + "g": "x INT, l BIGINT", "n": "ti TINYINT, si SMALLINT, i INT, l BIGINT, f FLOAT, d DOUBLE, dc DECIMAL(10,2), dw DECIMAL(38,10), " "s STRING, bo BOOLEAN, dt DATE, ts TIMESTAMP, tn TIMESTAMP_NTZ, bi BINARY", } @@ -519,6 +520,173 @@ ] ] +# Constant folding of arguments that need a constant, and ORDER BY / HAVING over a grouping expression +# (`--section folding`, written to its own fixture). Spark folds any foldable expression for these +# arguments (`round`'s scale, `ceil`/`floor`'s scale, `date_part`'s field, `LIMIT`) and raises what +# folding raises; `first`/`last` match a boolean `Literal` and fold nothing. +FOLD_SCALES = [ + "1+1", + "i", + "1+i", + "2147483647+1", + "CAST(1 AS BIGINT)+1", + "-(-2)", + "5/2", + "5 div 2", + "5 % 3", + "1/0", + "if(true,1,2)", + "CASE WHEN 1=1 THEN 3 ELSE 2 END", + "coalesce(NULL,2)", + "abs(-2)", + "length('abc')", + "1.5+1.5", + "1.5D+1", + "NULL+1", + "3+5L", + "2L", + "CAST(2 AS INT)", + "1=1", + "'1'||'1'", + "upper('2')", + "(1+1) * (2-1)", + "1 < 2", + "NOT TRUE", + "CASE WHEN 1=2 THEN 1/0 ELSE 2 END", + "if(1=1, 2, 1/0)", +] +FOLDING = ( + [ + (f"SELECT {fn}(dc, {x}) FROM n", conf) + for fn in ["round", "bround", "ceil", "floor"] + for x in FOLD_SCALES + for conf in [{}, NO_ANSI] + ] + + [ + (f"SELECT date_part({x}, dt) FROM n", conf) + for x in ["'y'||'ear'", "s", "CAST(NULL AS STRING)", "upper('year')", "1+1"] + for conf in [{}, NO_ANSI] + ] + + [ + (f"SELECT {fn}(i, {x}) FROM n", {}) + for fn in ["first", "last"] + for x in ["true", "false", "1=1", "true AND true", "i > 1", "NOT FALSE", "NULL", "CAST(true AS BOOLEAN)"] + ] + + [ + (f"SELECT {fn}(dt, {x}) FROM n", conf) + for fn in ["date_add", "date_sub"] + for x in ["'1'||'2'", "'1'||'.5'", "upper('1')", "1+1", "'a'", "s", "1.5"] + for conf in [{}, NO_ANSI] + ] + + [ + (f"SELECT date_add(dt, {x}) FROM n", NO_ANSI) + for x in [ + "'1'", + "'1.5'", + "' 12 '", + "'+3'", + "'1.'", + "'.5'", + "'1e2'", + "'0x1'", + "'2147483648'", + "'-0'", + "'1.0'", + "'abc'", + "''", + "' '", + "'1 2'", + ] + ] + + [ + (f"SELECT * FROM n LIMIT {x}", conf) + for x in [ + "1+1", + "i", + "2147483647+1", + "length('ab')", + "CAST(NULL AS INT)", + "-1", + "1+(-2)", + "1L", + "'1'", + "1.5", + "CASE WHEN 1=1 THEN 5 ELSE 6 END", + "(SELECT 1)", + ] + for conf in [{}, NO_ANSI] + ] +) +ORDER_BY_GROUPED = [ + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 2", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY 1 + x", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY m + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x", + "SELECT x m, count(*) c FROM g GROUP BY x ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY abs(x + 1)", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY (x + 1) * count(*)", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY sum(x)", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY sum(x + 1)", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 2 > 3", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3", + "SELECT count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1", + "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3", + "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1", + "SELECT sum(l) FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 1 DESC", + "SELECT count(*) c FROM g GROUP BY x + 1 HAVING x + 1 > 3 ORDER BY x + 2", + # A HAVING that grows the aggregate leaves a projection over it: a sort cannot grow it again + "SELECT count(*) c FROM g GROUP BY x HAVING sum(l) > 1 ORDER BY sum(l)", + "SELECT count(*) c FROM g GROUP BY x HAVING sum(l) > 1 ORDER BY c", + "SELECT count(*) c FROM g GROUP BY x + 1 HAVING sum(l) > 1 ORDER BY x + 1", + "SELECT count(*) c FROM g GROUP BY x HAVING x > 1 ORDER BY sum(l)", + "SELECT count(*) c FROM g GROUP BY x HAVING count(*) > 0 ORDER BY sum(l)", + "SELECT count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 0 ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY m ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY 1 ORDER BY x + 1", + "SELECT DISTINCT x + 1 FROM g ORDER BY x + 1", + "SELECT DISTINCT x + 1 m FROM g ORDER BY x + 2", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1 DESC, c", + "SELECT abs(x) m FROM g GROUP BY abs(x) ORDER BY abs(x)", + "SELECT X + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY X + 1", + "SELECT g.x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY g.x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY g.x + 1 ORDER BY x + 1", + "SELECT sum(x) + 1 m FROM g GROUP BY x + 1 ORDER BY x + 1", + "SELECT sum(x) s FROM g GROUP BY x + 1 ORDER BY x + 1, s", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY x + 1 + 1", + "SELECT cast(x as string) m, count(*) c FROM g GROUP BY cast(x as string) ORDER BY cast(x as string)", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY (SELECT 1) + x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 ORDER BY CASE WHEN x + 1 > 1 THEN 1 ELSE 2 END", + "SELECT (x + 1) * 2 m FROM g GROUP BY x + 1 ORDER BY x + 1", + "SELECT (x + 1) * 2 m FROM g GROUP BY x + 1 ORDER BY (x + 1) * 2", + "SELECT x + l m, count(*) c FROM g GROUP BY x + l ORDER BY l + x", + "SELECT x * l m, count(*) c FROM g GROUP BY x * l ORDER BY l * x", + "SELECT (x = 1 AND l = 2) m, count(*) c FROM g GROUP BY (x = 1 AND l = 2) ORDER BY (l = 2 AND x = 1)", + "SELECT (x = 1 OR l = 2) m, count(*) c FROM g GROUP BY (x = 1 OR l = 2) ORDER BY (l = 2 OR x = 1)", + "SELECT (x = l) m, count(*) c FROM g GROUP BY (x = l) ORDER BY (l = x)", + "SELECT (x <=> l) m, count(*) c FROM g GROUP BY (x <=> l) ORDER BY (l <=> x)", + "SELECT (x < l) m, count(*) c FROM g GROUP BY (x < l) ORDER BY (l > x)", + "SELECT (x <= l) m, count(*) c FROM g GROUP BY (x <= l) ORDER BY (l >= x)", + "SELECT greatest(x, l) m, count(*) c FROM g GROUP BY greatest(x, l) ORDER BY greatest(l, x)", + "SELECT least(x, l) m, count(*) c FROM g GROUP BY least(x, l) ORDER BY least(l, x)", + "SELECT x - l m, count(*) c FROM g GROUP BY x - l ORDER BY l - x", + "SELECT concat(cast(x as string), cast(l as string)) m, count(*) c FROM g GROUP BY concat(cast(x as string), " + "cast(l as string)) ORDER BY concat(cast(l as string), cast(x as string))", + "SELECT coalesce(x, l) m, count(*) c FROM g GROUP BY coalesce(x, l) ORDER BY coalesce(l, x)", + "SELECT (x + 1) + 2 m, count(*) c FROM g GROUP BY (x + 1) + 2 ORDER BY x + (1 + 2)", + "SELECT x + 1 + l m, count(*) c FROM g GROUP BY x + 1 + l ORDER BY l + 1 + x", + "SELECT x + l m, count(*) c FROM g GROUP BY l + x ORDER BY x + l", + "SELECT l - l % 60 m, count(*) c FROM g WHERE x = 62 GROUP BY l - l % 60 ORDER BY l - l % 60 LIMIT 10", + "SELECT x m, count(*) c FROM g GROUP BY x HAVING x > 3 ORDER BY x", + "SELECT x m, count(*) c FROM g GROUP BY x HAVING x > 3 ORDER BY sum(l)", + "SELECT x m, count(*) c FROM g GROUP BY x HAVING count(*) > 3 ORDER BY sum(l)", + "SELECT x m FROM g GROUP BY x HAVING count(*) > 3 ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 3 ORDER BY x + 1", + "SELECT x + 1 m, count(*) c FROM g GROUP BY x + 1 HAVING count(*) > 3 ORDER BY m", +] +FOLDING += [(sql, conf) for sql in ORDER_BY_GROUPED for conf in [{}]] + TPCH_DIR = Path(__file__).resolve().parents[2] / "bench" / "queries" / "tpch" @@ -620,21 +788,55 @@ def analyze(thunk) -> dict: } +def view_query(cols: str) -> str: + """`SELECT CAST(NULL AS ) AS , ... WHERE false` for a DDL column list.""" + parts, depth, cur = [], 0, "" + for ch in cols: + depth += (ch == "(") - (ch == ")") + if ch == "," and depth == 0: + parts.append(cur.strip()) + cur = "" + else: + cur += ch + parts.append(cur.strip()) + items = [] + for part in parts: + name, type_ = part.split(" ", 1) + items.append(f"CAST(NULL AS {type_}) AS {name}") + return f"SELECT {', '.join(items)} WHERE false" + + def main() -> None: from pyspark.sql import SparkSession ap = argparse.ArgumentParser() ap.add_argument("--remote", default="sc://localhost:15002") ap.add_argument("--out", default="tests/fixtures/spark-4.2.0/analyzer-goldens.json") + ap.add_argument( + "--section", + choices=["all", "folding"], + default="all", + help="`folding` writes only the constant-folding and ORDER BY-over-aggregate cases " + "(tests/fixtures/spark-4.2.0/analyzer-folding-goldens.json)", + ) + ap.add_argument( + "--views", + action="store_true", + help="create the tables as temporary views over empty relations (no catalog writes: for a shared server)", + ) args = ap.parse_args() spark = SparkSession.builder.remote(args.remote).getOrCreate() if spark.version != "4.2.0": raise SystemExit(f"expected Spark 4.2.0, found {spark.version}") - spark.sql("CREATE DATABASE IF NOT EXISTS default") - for name, cols in TABLES.items(): - spark.sql(f"DROP TABLE IF EXISTS {name}") - spark.sql(f"CREATE TABLE {name} ({cols}) USING parquet") + if args.views: + for name, cols in TABLES.items(): + spark.sql(f"CREATE OR REPLACE TEMPORARY VIEW {name} AS {view_query(cols)}") + else: + spark.sql("CREATE DATABASE IF NOT EXISTS default") + for name, cols in TABLES.items(): + spark.sql(f"DROP TABLE IF EXISTS {name}") + spark.sql(f"CREATE TABLE {name} ({cols}) USING parquet") tables = { name: [ {"name": f.name, "type": f.dataType.simpleString(), "nullable": f.nullable} @@ -653,15 +855,19 @@ def run_sql(sql: str, conf: dict) -> dict: spark.conf.unset(k) tpch = [] - for path in sorted(TPCH_DIR.glob("q*.sql")): - sql = path.read_text(encoding="utf-8").strip().rstrip(";") - tpch.append({"id": path.stem, **run_sql(sql, {})}) - corpus = [ - {"sql": sql, "conf": conf, **run_sql(sql, conf)} for sql, conf in CORPUS + MATRIX + CASTS + ANALYZER_FIXES - ] - plan_ids = [{"id": i, "dataframe": d, **analyze(f)} for i, d, f in plan_id_cases(spark)] + plan_ids = [] + if args.section == "folding": + corpus = [{"sql": sql, "conf": conf, **run_sql(sql, conf)} for sql, conf in FOLDING] + else: + for path in sorted(TPCH_DIR.glob("q*.sql")): + sql = path.read_text(encoding="utf-8").strip().rstrip(";") + tpch.append({"id": path.stem, **run_sql(sql, {})}) + corpus = [ + {"sql": sql, "conf": conf, **run_sql(sql, conf)} for sql, conf in CORPUS + MATRIX + CASTS + ANALYZER_FIXES + ] + plan_ids = [{"id": i, "dataframe": d, **analyze(f)} for i, d, f in plan_id_cases(spark)] for name in TABLES: - spark.sql(f"DROP TABLE IF EXISTS {name}") + spark.sql(f"DROP VIEW IF EXISTS {name}" if args.views else f"DROP TABLE IF EXISTS {name}") doc = { "format_version": FORMAT_VERSION,