sql_expression.cpp 99 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331
  1. #include "sql_expression.h"
  2. #include "sql_call_expr.h"
  3. #include "sql_select.h"
  4. #include "sql_values.h"
  5. #include <yql/essentials/parser/proto_ast/gen/v1/SQLv1Lexer.h>
  6. #include <yql/essentials/parser/proto_ast/gen/v1_antlr4/SQLv1Antlr4Lexer.h>
  7. #include <yql/essentials/utils/utf8.h>
  8. #include <util/charset/wide.h>
  9. #include <util/string/ascii.h>
  10. #include <util/string/hex.h>
  11. namespace NSQLTranslationV1 {
  12. using NALPDefault::SQLv1LexerTokens;
  13. using NALPDefaultAntlr4::SQLv1Antlr4Lexer;
  14. using namespace NSQLv1Generated;
  15. TNodePtr TSqlExpression::Build(const TRule_expr& node) {
  16. // expr:
  17. // or_subexpr (OR or_subexpr)*
  18. // | type_name_composite
  19. switch (node.Alt_case()) {
  20. case TRule_expr::kAltExpr1: {
  21. auto getNode = [](const TRule_expr_TAlt1_TBlock2& b) -> const TRule_or_subexpr& { return b.GetRule_or_subexpr2(); };
  22. return BinOper("Or", node.GetAlt_expr1().GetRule_or_subexpr1(), getNode,
  23. node.GetAlt_expr1().GetBlock2().begin(), node.GetAlt_expr1().GetBlock2().end(), {});
  24. }
  25. case TRule_expr::kAltExpr2: {
  26. return TypeNode(node.GetAlt_expr2().GetRule_type_name_composite1());
  27. }
  28. case TRule_expr::ALT_NOT_SET:
  29. Y_ABORT("You should change implementation according to grammar changes");
  30. }
  31. }
  32. TNodePtr TSqlExpression::Build(const TRule_lambda_or_parameter& node) {
  33. // lambda_or_parameter:
  34. // lambda
  35. // | bind_parameter
  36. switch (node.Alt_case()) {
  37. case TRule_lambda_or_parameter::kAltLambdaOrParameter1: {
  38. return LambdaRule(node.alt_lambda_or_parameter1().GetRule_lambda1());
  39. }
  40. case TRule_lambda_or_parameter::kAltLambdaOrParameter2: {
  41. TString named;
  42. if (!NamedNodeImpl(node.GetAlt_lambda_or_parameter2().GetRule_bind_parameter1(), named, *this)) {
  43. return nullptr;
  44. }
  45. auto namedNode = GetNamedNode(named);
  46. if (!namedNode) {
  47. return nullptr;
  48. }
  49. return namedNode;
  50. }
  51. case TRule_lambda_or_parameter::ALT_NOT_SET:
  52. Y_ABORT("You should change implementation according to grammar changes");
  53. }
  54. }
  55. TNodePtr TSqlExpression::SubExpr(const TRule_mul_subexpr& node, const TTrailingQuestions& tail) {
  56. // mul_subexpr: con_subexpr (DOUBLE_PIPE con_subexpr)*;
  57. auto getNode = [](const TRule_mul_subexpr::TBlock2& b) -> const TRule_con_subexpr& { return b.GetRule_con_subexpr2(); };
  58. return BinOper("Concat", node.GetRule_con_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  59. }
  60. TNodePtr TSqlExpression::SubExpr(const TRule_add_subexpr& node, const TTrailingQuestions& tail) {
  61. // add_subexpr: mul_subexpr ((ASTERISK | SLASH | PERCENT) mul_subexpr)*;
  62. auto getNode = [](const TRule_add_subexpr::TBlock2& b) -> const TRule_mul_subexpr& { return b.GetRule_mul_subexpr2(); };
  63. return BinOpList(node.GetRule_mul_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  64. }
  65. TNodePtr TSqlExpression::SubExpr(const TRule_bit_subexpr& node, const TTrailingQuestions& tail) {
  66. // bit_subexpr: add_subexpr ((PLUS | MINUS) add_subexpr)*;
  67. auto getNode = [](const TRule_bit_subexpr::TBlock2& b) -> const TRule_add_subexpr& { return b.GetRule_add_subexpr2(); };
  68. return BinOpList(node.GetRule_add_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  69. }
  70. TNodePtr TSqlExpression::SubExpr(const TRule_neq_subexpr& node, const TTrailingQuestions& tailExternal) {
  71. //neq_subexpr: bit_subexpr ((SHIFT_LEFT | shift_right | ROT_LEFT | rot_right | AMPERSAND | PIPE | CARET) bit_subexpr)*
  72. // // trailing QUESTIONS are used in optional simple types (String?) and optional lambda args: ($x, $y?) -> ($x)
  73. // ((double_question neq_subexpr) => double_question neq_subexpr | QUESTION+)?;
  74. YQL_ENSURE(tailExternal.Count == 0);
  75. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && !node.HasBlock3();
  76. TTrailingQuestions tail;
  77. if (node.HasBlock3() && node.GetBlock3().Alt_case() == TRule_neq_subexpr::TBlock3::kAlt2) {
  78. auto& questions = node.GetBlock3().GetAlt2();
  79. tail.Count = questions.GetBlock1().size();
  80. tail.Pos = Ctx.TokenPosition(questions.GetBlock1().begin()->GetToken1());
  81. YQL_ENSURE(tail.Count > 0);
  82. }
  83. auto getNode = [](const TRule_neq_subexpr::TBlock2& b) -> const TRule_bit_subexpr& { return b.GetRule_bit_subexpr2(); };
  84. auto result = BinOpList(node.GetRule_bit_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  85. if (!result) {
  86. return {};
  87. }
  88. if (node.HasBlock3()) {
  89. auto& block = node.GetBlock3();
  90. if (block.Alt_case() == TRule_neq_subexpr::TBlock3::kAlt1) {
  91. TSqlExpression altExpr(Ctx, Mode);
  92. auto altResult = SubExpr(block.GetAlt1().GetRule_neq_subexpr2(), {});
  93. if (!altResult) {
  94. return {};
  95. }
  96. const TVector<TNodePtr> args({result, altResult});
  97. Token(block.GetAlt1().GetRule_double_question1().GetToken1());
  98. result = BuildBuiltinFunc(Ctx, Ctx.Pos(), "Coalesce", args);
  99. }
  100. }
  101. return result;
  102. }
  103. TNodePtr TSqlExpression::SubExpr(const TRule_eq_subexpr& node, const TTrailingQuestions& tail) {
  104. // eq_subexpr: neq_subexpr ((LESS | LESS_OR_EQ | GREATER | GREATER_OR_EQ) neq_subexpr)*;
  105. auto getNode = [](const TRule_eq_subexpr::TBlock2& b) -> const TRule_neq_subexpr& { return b.GetRule_neq_subexpr2(); };
  106. return BinOpList(node.GetRule_neq_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  107. }
  108. TNodePtr TSqlExpression::SubExpr(const TRule_or_subexpr& node, const TTrailingQuestions& tail) {
  109. // or_subexpr: and_subexpr (AND and_subexpr)*;
  110. auto getNode = [](const TRule_or_subexpr::TBlock2& b) -> const TRule_and_subexpr& { return b.GetRule_and_subexpr2(); };
  111. return BinOper("And", node.GetRule_and_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  112. }
  113. TNodePtr TSqlExpression::SubExpr(const TRule_and_subexpr& node, const TTrailingQuestions& tail) {
  114. // and_subexpr: xor_subexpr (XOR xor_subexpr)*;
  115. auto getNode = [](const TRule_and_subexpr::TBlock2& b) -> const TRule_xor_subexpr& { return b.GetRule_xor_subexpr2(); };
  116. return BinOper("Xor", node.GetRule_xor_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail);
  117. }
  118. bool ChangefeedSettingsEntry(const TRule_changefeed_settings_entry& node, TSqlExpression& ctx, TChangefeedSettings& settings, bool alter) {
  119. const auto id = IdEx(node.GetRule_an_id1(), ctx);
  120. if (alter) {
  121. // currently we don't support alter settings
  122. ctx.Error() << to_upper(id.Name) << " alter is not supported";
  123. return false;
  124. }
  125. const auto& setting = node.GetRule_changefeed_setting_value3();
  126. auto exprNode = ctx.Build(setting.GetRule_expr1());
  127. if (!exprNode) {
  128. ctx.Context().Error(id.Pos) << "Invalid changefeed setting: " << id.Name;
  129. return false;
  130. }
  131. if (to_lower(id.Name) == "sink_type") {
  132. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "String") {
  133. ctx.Context().Error() << "Literal of String type is expected for " << id.Name;
  134. return false;
  135. }
  136. const auto value = exprNode->GetLiteralValue();
  137. if (to_lower(value) == "local") {
  138. settings.SinkSettings = TChangefeedSettings::TLocalSinkSettings();
  139. } else {
  140. ctx.Context().Error() << "Unknown changefeed sink type: " << value;
  141. return false;
  142. }
  143. } else if (to_lower(id.Name) == "mode") {
  144. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "String") {
  145. ctx.Context().Error() << "Literal of String type is expected for " << id.Name;
  146. return false;
  147. }
  148. settings.Mode = exprNode;
  149. } else if (to_lower(id.Name) == "format") {
  150. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "String") {
  151. ctx.Context().Error() << "Literal of String type is expected for " << id.Name;
  152. return false;
  153. }
  154. settings.Format = exprNode;
  155. } else if (to_lower(id.Name) == "initial_scan") {
  156. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "Bool") {
  157. ctx.Context().Error() << "Literal of Bool type is expected for " << id.Name;
  158. return false;
  159. }
  160. settings.InitialScan = exprNode;
  161. } else if (to_lower(id.Name) == "virtual_timestamps") {
  162. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "Bool") {
  163. ctx.Context().Error() << "Literal of Bool type is expected for " << id.Name;
  164. return false;
  165. }
  166. settings.VirtualTimestamps = exprNode;
  167. } else if (to_lower(id.Name) == "barriers_interval" || to_lower(id.Name) == "resolved_timestamps") {
  168. if (exprNode->GetOpName() != "Interval") {
  169. ctx.Context().Error() << "Literal of Interval type is expected for " << id.Name;
  170. return false;
  171. }
  172. settings.BarriersInterval = exprNode;
  173. } else if (to_lower(id.Name) == "retention_period") {
  174. if (exprNode->GetOpName() != "Interval") {
  175. ctx.Context().Error() << "Literal of Interval type is expected for " << id.Name;
  176. return false;
  177. }
  178. settings.RetentionPeriod = exprNode;
  179. } else if (to_lower(id.Name) == "topic_auto_partitioning") {
  180. auto v = to_lower(exprNode->GetLiteralValue());
  181. if (v != "enabled" && v != "disabled") {
  182. ctx.Context().Error() << "Literal of Interval type is expected for " << id.Name;
  183. }
  184. settings.TopicAutoPartitioning = exprNode;
  185. } else if (to_lower(id.Name) == "topic_max_active_partitions") {
  186. if (!exprNode->IsIntegerLiteral()) {
  187. ctx.Context().Error() << "Literal of integer type is expected for " << id.Name;
  188. return false;
  189. }
  190. settings.TopicMaxActivePartitions = exprNode;
  191. } else if (to_lower(id.Name) == "topic_min_active_partitions") {
  192. if (!exprNode->IsIntegerLiteral()) {
  193. ctx.Context().Error() << "Literal of integer type is expected for " << id.Name;
  194. return false;
  195. }
  196. settings.TopicPartitions = exprNode;
  197. } else if (to_lower(id.Name) == "aws_region") {
  198. if (!exprNode->IsLiteral() || exprNode->GetLiteralType() != "String") {
  199. ctx.Context().Error() << "Literal of String type is expected for " << id.Name;
  200. return false;
  201. }
  202. settings.AwsRegion = exprNode;
  203. } else {
  204. ctx.Context().Error(id.Pos) << "Unknown changefeed setting: " << id.Name;
  205. return false;
  206. }
  207. return true;
  208. }
  209. bool ChangefeedSettings(const TRule_changefeed_settings& node, TSqlExpression& ctx, TChangefeedSettings& settings, bool alter) {
  210. if (!ChangefeedSettingsEntry(node.GetRule_changefeed_settings_entry1(), ctx, settings, alter)) {
  211. return false;
  212. }
  213. for (auto& block : node.GetBlock2()) {
  214. if (!ChangefeedSettingsEntry(block.GetRule_changefeed_settings_entry2(), ctx, settings, alter)) {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. bool CreateChangefeed(const TRule_changefeed& node, TSqlExpression& ctx, TVector<TChangefeedDescription>& changefeeds) {
  221. changefeeds.emplace_back(IdEx(node.GetRule_an_id2(), ctx));
  222. if (!ChangefeedSettings(node.GetRule_changefeed_settings5(), ctx, changefeeds.back().Settings, false)) {
  223. return false;
  224. }
  225. return true;
  226. }
  227. namespace {
  228. bool WithoutAlpha(const std::string_view &literal) {
  229. return literal.cend() == std::find_if(literal.cbegin(), literal.cend(), [](char c) { return std::isalpha(c) || (c & '\x80'); });
  230. }
  231. }
  232. bool Expr(TSqlExpression& sqlExpr, TVector<TNodePtr>& exprNodes, const TRule_expr& node) {
  233. TNodePtr exprNode = sqlExpr.Build(node);
  234. if (!exprNode) {
  235. return false;
  236. }
  237. exprNodes.push_back(exprNode);
  238. return true;
  239. }
  240. bool ExprList(TSqlExpression& sqlExpr, TVector<TNodePtr>& exprNodes, const TRule_expr_list& node) {
  241. if (!Expr(sqlExpr, exprNodes, node.GetRule_expr1())) {
  242. return false;
  243. }
  244. for (auto b: node.GetBlock2()) {
  245. sqlExpr.Token(b.GetToken1());
  246. if (!Expr(sqlExpr, exprNodes, b.GetRule_expr2())) {
  247. return false;
  248. }
  249. }
  250. return true;
  251. }
  252. bool ParseNumbers(TContext& ctx, const TString& strOrig, ui64& value, TString& suffix) {
  253. const auto str = to_lower(strOrig);
  254. const auto strLen = str.size();
  255. ui64 base = 10;
  256. if (strLen > 2 && str[0] == '0') {
  257. const auto formatChar = str[1];
  258. if (formatChar == 'x') {
  259. base = 16;
  260. } else if (formatChar == 'o') {
  261. base = 8;
  262. } else if (formatChar == 'b') {
  263. base = 2;
  264. }
  265. }
  266. if (strLen > 1) {
  267. auto iter = str.cend() - 1;
  268. if (*iter == 'l' || *iter == 's' || *iter == 't' || *iter == 's' || *iter == 'i' || *iter == 'b' || *iter == 'n') {
  269. --iter;
  270. }
  271. if (*iter == 'u' || *iter == 'p') {
  272. --iter;
  273. }
  274. suffix = TString(++iter, str.cend());
  275. }
  276. value = 0;
  277. const TString digString(str.begin() + (base == 10 ? 0 : 2), str.end() - suffix.size());
  278. for (const char& cur: digString) {
  279. const ui64 curDigit = Char2DigitTable[static_cast<int>(cur)];
  280. if (curDigit >= base) {
  281. ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << strOrig << ", char: '" << cur <<
  282. "' is out of base: " << base;
  283. return false;
  284. }
  285. ui64 curValue = value;
  286. value *= base;
  287. bool overflow = ((value / base) != curValue);
  288. if (!overflow) {
  289. curValue = value;
  290. value += curDigit;
  291. overflow = value < curValue;
  292. }
  293. if (overflow) {
  294. ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << strOrig << ", number limit overflow";
  295. return false;
  296. }
  297. }
  298. return true;
  299. }
  300. TNodePtr LiteralNumber(TContext& ctx, const TRule_integer& node) {
  301. const TString intergerString = ctx.Token(node.GetToken1());
  302. if (to_lower(intergerString).EndsWith("pn")) {
  303. // TODO: add validation
  304. return new TLiteralNode(ctx.Pos(), "PgNumeric", intergerString.substr(0, intergerString.size() - 2));
  305. }
  306. ui64 value;
  307. TString suffix;
  308. if (!ParseNumbers(ctx, intergerString, value, suffix)) {
  309. return {};
  310. }
  311. const bool noSpaceForInt32 = value >> 31;
  312. const bool noSpaceForInt64 = value >> 63;
  313. if (suffix == "") {
  314. bool implicitType = true;
  315. if (noSpaceForInt64) {
  316. return new TLiteralNumberNode<ui64>(ctx.Pos(), "Uint64", ToString(value), implicitType);
  317. } else if (noSpaceForInt32) {
  318. return new TLiteralNumberNode<i64>(ctx.Pos(), "Int64", ToString(value), implicitType);
  319. }
  320. return new TLiteralNumberNode<i32>(ctx.Pos(), "Int32", ToString(value), implicitType);
  321. } else if (suffix == "p") {
  322. bool implicitType = true;
  323. if (noSpaceForInt64) {
  324. ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << intergerString << ", 64 bit signed integer overflow";
  325. return {};
  326. } else if (noSpaceForInt32) {
  327. return new TLiteralNumberNode<i64>(ctx.Pos(), "PgInt8", ToString(value), implicitType);
  328. }
  329. return new TLiteralNumberNode<i32>(ctx.Pos(), "PgInt4", ToString(value), implicitType);
  330. } else if (suffix == "u") {
  331. return new TLiteralNumberNode<ui32>(ctx.Pos(), "Uint32", ToString(value));
  332. } else if (suffix == "ul") {
  333. return new TLiteralNumberNode<ui64>(ctx.Pos(), "Uint64", ToString(value));
  334. } else if (suffix == "ut") {
  335. return new TLiteralNumberNode<ui8>(ctx.Pos(), "Uint8", ToString(value));
  336. } else if (suffix == "t") {
  337. return new TLiteralNumberNode<i8>(ctx.Pos(), "Int8", ToString(value));
  338. } else if (suffix == "l") {
  339. return new TLiteralNumberNode<i64>(ctx.Pos(), "Int64", ToString(value));
  340. } else if (suffix == "us") {
  341. return new TLiteralNumberNode<ui16>(ctx.Pos(), "Uint16", ToString(value));
  342. } else if (suffix == "s") {
  343. return new TLiteralNumberNode<i16>(ctx.Pos(), "Int16", ToString(value));
  344. } else if (suffix == "ps") {
  345. return new TLiteralNumberNode<i16>(ctx.Pos(), "PgInt2", ToString(value));
  346. } else if (suffix == "pi") {
  347. return new TLiteralNumberNode<i32>(ctx.Pos(), "PgInt4", ToString(value));
  348. } else if (suffix == "pb") {
  349. return new TLiteralNumberNode<i64>(ctx.Pos(), "PgInt8", ToString(value));
  350. } else {
  351. ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << intergerString << ", invalid suffix: " << suffix;
  352. return {};
  353. }
  354. }
  355. TNodePtr LiteralReal(TContext& ctx, const TRule_real& node) {
  356. const TString value(ctx.Token(node.GetToken1()));
  357. YQL_ENSURE(!value.empty());
  358. auto lower = to_lower(value);
  359. if (lower.EndsWith("f")) {
  360. return new TLiteralNumberNode<float>(ctx.Pos(), "Float", value.substr(0, value.size()-1));
  361. } else if (lower.EndsWith("p")) {
  362. return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size()-1));
  363. } else if (lower.EndsWith("pf4")) {
  364. return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat4", value.substr(0, value.size()-3));
  365. } else if (lower.EndsWith("pf8")) {
  366. return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size()-3));
  367. } else if (lower.EndsWith("pn")) {
  368. return new TLiteralNode(ctx.Pos(), "PgNumeric", value.substr(0, value.size()-2));
  369. } else {
  370. return new TLiteralNumberNode<double>(ctx.Pos(), "Double", value);
  371. }
  372. }
  373. TMaybe<TExprOrIdent> TSqlExpression::LiteralExpr(const TRule_literal_value& node) {
  374. TExprOrIdent result;
  375. switch (node.Alt_case()) {
  376. case TRule_literal_value::kAltLiteralValue1: {
  377. result.Expr = LiteralNumber(Ctx, node.GetAlt_literal_value1().GetRule_integer1());
  378. break;
  379. }
  380. case TRule_literal_value::kAltLiteralValue2: {
  381. result.Expr = LiteralReal(Ctx, node.GetAlt_literal_value2().GetRule_real1());
  382. break;
  383. }
  384. case TRule_literal_value::kAltLiteralValue3: {
  385. const TString value(Token(node.GetAlt_literal_value3().GetToken1()));
  386. return BuildLiteralTypedSmartStringOrId(Ctx, value);
  387. }
  388. case TRule_literal_value::kAltLiteralValue5: {
  389. Token(node.GetAlt_literal_value5().GetToken1());
  390. result.Expr = BuildLiteralNull(Ctx.Pos());
  391. break;
  392. }
  393. case TRule_literal_value::kAltLiteralValue9: {
  394. const TString value(to_lower(Token(node.GetAlt_literal_value9().GetRule_bool_value1().GetToken1())));
  395. result.Expr = BuildLiteralBool(Ctx.Pos(), FromString<bool>(value));
  396. break;
  397. }
  398. case TRule_literal_value::kAltLiteralValue10: {
  399. result.Expr = BuildEmptyAction(Ctx.Pos());
  400. break;
  401. }
  402. case TRule_literal_value::kAltLiteralValue4:
  403. case TRule_literal_value::kAltLiteralValue6:
  404. case TRule_literal_value::kAltLiteralValue7:
  405. case TRule_literal_value::kAltLiteralValue8:
  406. case TRule_literal_value::ALT_NOT_SET:
  407. AltNotImplemented("literal_value", node);
  408. }
  409. if (!result.Expr) {
  410. return {};
  411. }
  412. return result;
  413. }
  414. template<typename TUnarySubExprType>
  415. TNodePtr TSqlExpression::UnaryExpr(const TUnarySubExprType& node, const TTrailingQuestions& tail) {
  416. if constexpr (std::is_same_v<TUnarySubExprType, TRule_unary_subexpr>) {
  417. if (node.Alt_case() == TRule_unary_subexpr::kAltUnarySubexpr1) {
  418. return UnaryCasualExpr(node.GetAlt_unary_subexpr1().GetRule_unary_casual_subexpr1(), tail);
  419. } else if (tail.Count) {
  420. UnexpectedQuestionToken(tail);
  421. return {};
  422. } else {
  423. MaybeUnnamedSmartParenOnTop = false;
  424. return JsonApiExpr(node.GetAlt_unary_subexpr2().GetRule_json_api_expr1());
  425. }
  426. } else {
  427. MaybeUnnamedSmartParenOnTop = false;
  428. if (node.Alt_case() == TRule_in_unary_subexpr::kAltInUnarySubexpr1) {
  429. return UnaryCasualExpr(node.GetAlt_in_unary_subexpr1().GetRule_in_unary_casual_subexpr1(), tail);
  430. } else if (tail.Count) {
  431. UnexpectedQuestionToken(tail);
  432. return {};
  433. } else {
  434. return JsonApiExpr(node.GetAlt_in_unary_subexpr2().GetRule_json_api_expr1());
  435. }
  436. }
  437. }
  438. TNodePtr TSqlExpression::JsonPathSpecification(const TRule_jsonpath_spec& node) {
  439. /*
  440. jsonpath_spec: STRING_VALUE;
  441. */
  442. TString value = Token(node.GetToken1());
  443. TPosition pos = Ctx.Pos();
  444. auto parsed = StringContent(Ctx, pos, value);
  445. if (!parsed) {
  446. return nullptr;
  447. }
  448. return new TCallNodeImpl(pos, "Utf8", {BuildQuotedAtom(pos, parsed->Content, parsed->Flags)});
  449. }
  450. TNodePtr TSqlExpression::JsonReturningTypeRule(const TRule_type_name_simple& node) {
  451. /*
  452. (RETURNING type_name_simple)?
  453. */
  454. return TypeSimple(node, /* onlyDataAllowed */ true);
  455. }
  456. TNodePtr TSqlExpression::JsonInputArg(const TRule_json_common_args& node) {
  457. /*
  458. json_common_args: expr COMMA jsonpath_spec (PASSING json_variables)?;
  459. */
  460. TNodePtr jsonExpr = Build(node.GetRule_expr1());
  461. if (!jsonExpr || jsonExpr->IsNull()) {
  462. jsonExpr = new TCallNodeImpl(Ctx.Pos(), "Nothing", {
  463. new TCallNodeImpl(Ctx.Pos(), "OptionalType", {BuildDataType(Ctx.Pos(), "Json")})
  464. });
  465. }
  466. return jsonExpr;
  467. }
  468. void TSqlExpression::AddJsonVariable(const TRule_json_variable& node, TVector<TNodePtr>& children) {
  469. /*
  470. json_variable: expr AS json_variable_name;
  471. */
  472. TNodePtr expr;
  473. TString rawName;
  474. TPosition namePos = Ctx.Pos();
  475. ui32 nameFlags = 0;
  476. expr = Build(node.GetRule_expr1());
  477. const auto& nameRule = node.GetRule_json_variable_name3();
  478. switch (nameRule.GetAltCase()) {
  479. case TRule_json_variable_name::kAltJsonVariableName1:
  480. rawName = Id(nameRule.GetAlt_json_variable_name1().GetRule_id_expr1(), *this);
  481. nameFlags = TNodeFlags::ArbitraryContent;
  482. break;
  483. case TRule_json_variable_name::kAltJsonVariableName2: {
  484. const auto& token = nameRule.GetAlt_json_variable_name2().GetToken1();
  485. namePos = GetPos(token);
  486. auto parsed = StringContentOrIdContent(Ctx, namePos, token.GetValue());
  487. if (!parsed) {
  488. return;
  489. }
  490. rawName = parsed->Content;
  491. nameFlags = parsed->Flags;
  492. break;
  493. }
  494. case TRule_json_variable_name::ALT_NOT_SET:
  495. Y_ABORT("You should change implementation according to grammar changes");
  496. }
  497. TNodePtr nameExpr = BuildQuotedAtom(namePos, rawName, nameFlags);
  498. children.push_back(BuildTuple(namePos, {nameExpr, expr}));
  499. }
  500. void TSqlExpression::AddJsonVariables(const TRule_json_variables& node, TVector<TNodePtr>& children) {
  501. /*
  502. json_variables: json_variable (COMMA json_variable)*;
  503. */
  504. AddJsonVariable(node.GetRule_json_variable1(), children);
  505. for (size_t i = 0; i < node.Block2Size(); i++) {
  506. AddJsonVariable(node.GetBlock2(i).GetRule_json_variable2(), children);
  507. }
  508. }
  509. TNodePtr TSqlExpression::JsonVariables(const TRule_json_common_args& node) {
  510. /*
  511. json_common_args: expr COMMA jsonpath_spec (PASSING json_variables)?;
  512. */
  513. TVector<TNodePtr> variables;
  514. TPosition pos = Ctx.Pos();
  515. if (node.HasBlock4()) {
  516. const auto& block = node.GetBlock4();
  517. pos = GetPos(block.GetToken1());
  518. AddJsonVariables(block.GetRule_json_variables2(), variables);
  519. }
  520. return new TCallNodeImpl(pos, "JsonVariables", variables);
  521. }
  522. void TSqlExpression::AddJsonCommonArgs(const TRule_json_common_args& node, TVector<TNodePtr>& children) {
  523. /*
  524. json_common_args: expr COMMA jsonpath_spec (PASSING json_variables)?;
  525. */
  526. TNodePtr jsonExpr = JsonInputArg(node);
  527. TNodePtr jsonPath = JsonPathSpecification(node.GetRule_jsonpath_spec3());
  528. TNodePtr variables = JsonVariables(node);
  529. children.push_back(jsonExpr);
  530. children.push_back(jsonPath);
  531. children.push_back(variables);
  532. }
  533. TNodePtr TSqlExpression::JsonValueCaseHandler(const TRule_json_case_handler& node, EJsonValueHandlerMode& mode) {
  534. /*
  535. json_case_handler: ERROR | NULL | (DEFAULT expr);
  536. */
  537. switch (node.GetAltCase()) {
  538. case TRule_json_case_handler::kAltJsonCaseHandler1: {
  539. const auto pos = GetPos(node.GetAlt_json_case_handler1().GetToken1());
  540. mode = EJsonValueHandlerMode::Error;
  541. return new TCallNodeImpl(pos, "Null", {});
  542. }
  543. case TRule_json_case_handler::kAltJsonCaseHandler2: {
  544. const auto pos = GetPos(node.GetAlt_json_case_handler2().GetToken1());
  545. mode = EJsonValueHandlerMode::DefaultValue;
  546. return new TCallNodeImpl(pos, "Null", {});
  547. }
  548. case TRule_json_case_handler::kAltJsonCaseHandler3:
  549. mode = EJsonValueHandlerMode::DefaultValue;
  550. return Build(node.GetAlt_json_case_handler3().GetRule_expr2());
  551. case TRule_json_case_handler::ALT_NOT_SET:
  552. Y_ABORT("You should change implementation according to grammar changes");
  553. }
  554. }
  555. void TSqlExpression::AddJsonValueCaseHandlers(const TRule_json_value& node, TVector<TNodePtr>& children) {
  556. /*
  557. json_case_handler*
  558. */
  559. if (node.Block5Size() > 2) {
  560. Ctx.Error() << "Only 1 ON EMPTY and/or 1 ON ERROR clause is expected";
  561. Ctx.IncrementMonCounter("sql_errors", "JsonValueTooManyHandleClauses");
  562. return;
  563. }
  564. TNodePtr onEmpty;
  565. EJsonValueHandlerMode onEmptyMode = EJsonValueHandlerMode::DefaultValue;
  566. TNodePtr onError;
  567. EJsonValueHandlerMode onErrorMode = EJsonValueHandlerMode::DefaultValue;
  568. for (size_t i = 0; i < node.Block5Size(); i++) {
  569. const auto block = node.GetBlock5(i);
  570. const bool isEmptyClause = to_lower(block.GetToken3().GetValue()) == "empty";
  571. if (isEmptyClause && onEmpty != nullptr) {
  572. Ctx.Error() << "Only 1 ON EMPTY clause is expected";
  573. Ctx.IncrementMonCounter("sql_errors", "JsonValueMultipleOnEmptyClauses");
  574. return;
  575. }
  576. if (!isEmptyClause && onError != nullptr) {
  577. Ctx.Error() << "Only 1 ON ERROR clause is expected";
  578. Ctx.IncrementMonCounter("sql_errors", "JsonValueMultipleOnErrorClauses");
  579. return;
  580. }
  581. if (isEmptyClause && onError != nullptr) {
  582. Ctx.Error() << "ON EMPTY clause must be before ON ERROR clause";
  583. Ctx.IncrementMonCounter("sql_errors", "JsonValueOnEmptyAfterOnError");
  584. return;
  585. }
  586. EJsonValueHandlerMode currentMode;
  587. TNodePtr currentHandler = JsonValueCaseHandler(block.GetRule_json_case_handler1(), currentMode);
  588. if (isEmptyClause) {
  589. onEmpty = currentHandler;
  590. onEmptyMode = currentMode;
  591. } else {
  592. onError = currentHandler;
  593. onErrorMode = currentMode;
  594. }
  595. }
  596. if (onEmpty == nullptr) {
  597. onEmpty = new TCallNodeImpl(Ctx.Pos(), "Null", {});
  598. }
  599. if (onError == nullptr) {
  600. onError = new TCallNodeImpl(Ctx.Pos(), "Null", {});
  601. }
  602. children.push_back(BuildQuotedAtom(Ctx.Pos(), ToString(onEmptyMode), TNodeFlags::Default));
  603. children.push_back(onEmpty);
  604. children.push_back(BuildQuotedAtom(Ctx.Pos(), ToString(onErrorMode), TNodeFlags::Default));
  605. children.push_back(onError);
  606. }
  607. TNodePtr TSqlExpression::JsonValueExpr(const TRule_json_value& node) {
  608. /*
  609. json_value: JSON_VALUE LPAREN
  610. json_common_args
  611. (RETURNING type_name_simple)?
  612. (json_case_handler ON (EMPTY | ERROR))*
  613. RPAREN;
  614. */
  615. TVector<TNodePtr> children;
  616. AddJsonCommonArgs(node.GetRule_json_common_args3(), children);
  617. AddJsonValueCaseHandlers(node, children);
  618. if (node.HasBlock4()) {
  619. auto returningType = JsonReturningTypeRule(node.GetBlock4().GetRule_type_name_simple2());
  620. if (!returningType) {
  621. return {};
  622. }
  623. children.push_back(returningType);
  624. }
  625. return new TCallNodeImpl(GetPos(node.GetToken1()), "JsonValue", children);
  626. }
  627. void TSqlExpression::AddJsonExistsHandler(const TRule_json_exists& node, TVector<TNodePtr>& children) {
  628. /*
  629. json_exists: JSON_EXISTS LPAREN
  630. json_common_args
  631. json_exists_handler?
  632. RPAREN;
  633. */
  634. auto buildJustBool = [&](const TPosition& pos, bool value) {
  635. return new TCallNodeImpl(pos, "Just", {BuildLiteralBool(pos, value)});
  636. };
  637. if (!node.HasBlock4()) {
  638. children.push_back(buildJustBool(Ctx.Pos(), false));
  639. return;
  640. }
  641. const auto& handlerRule = node.GetBlock4().GetRule_json_exists_handler1();
  642. const auto& token = handlerRule.GetToken1();
  643. const auto pos = GetPos(token);
  644. const auto mode = to_lower(token.GetValue());
  645. if (mode == "unknown") {
  646. const auto nothingNode = new TCallNodeImpl(pos, "Nothing", {
  647. new TCallNodeImpl(pos, "OptionalType", {BuildDataType(pos, "Bool")})
  648. });
  649. children.push_back(nothingNode);
  650. } else if (mode != "error") {
  651. children.push_back(buildJustBool(pos, FromString<bool>(mode)));
  652. }
  653. }
  654. TNodePtr TSqlExpression::JsonExistsExpr(const TRule_json_exists& node) {
  655. /*
  656. json_exists: JSON_EXISTS LPAREN
  657. json_common_args
  658. json_exists_handler?
  659. RPAREN;
  660. */
  661. TVector<TNodePtr> children;
  662. AddJsonCommonArgs(node.GetRule_json_common_args3(), children);
  663. AddJsonExistsHandler(node, children);
  664. return new TCallNodeImpl(GetPos(node.GetToken1()), "JsonExists", children);
  665. }
  666. EJsonQueryWrap TSqlExpression::JsonQueryWrapper(const TRule_json_query& node) {
  667. /*
  668. json_query: JSON_QUERY LPAREN
  669. json_common_args
  670. (json_query_wrapper WRAPPER)?
  671. (json_query_handler ON EMPTY)?
  672. (json_query_handler ON ERROR)?
  673. RPAREN;
  674. */
  675. // default behaviour - no wrapping
  676. if (!node.HasBlock4()) {
  677. return EJsonQueryWrap::NoWrap;
  678. }
  679. // WITHOUT ARRAY? - no wrapping
  680. const auto& wrapperRule = node.GetBlock4().GetRule_json_query_wrapper1();
  681. if (wrapperRule.GetAltCase() == TRule_json_query_wrapper::kAltJsonQueryWrapper1) {
  682. return EJsonQueryWrap::NoWrap;
  683. }
  684. // WITH (CONDITIONAL | UNCONDITIONAL)? ARRAY? - wrapping depends on 2nd token. Default is UNCONDITIONAL
  685. const auto& withWrapperRule = wrapperRule.GetAlt_json_query_wrapper2();
  686. if (!withWrapperRule.HasBlock2()) {
  687. return EJsonQueryWrap::Wrap;
  688. }
  689. const auto& token = withWrapperRule.GetBlock2().GetToken1();
  690. if (to_lower(token.GetValue()) == "conditional") {
  691. return EJsonQueryWrap::ConditionalWrap;
  692. } else {
  693. return EJsonQueryWrap::Wrap;
  694. }
  695. }
  696. EJsonQueryHandler TSqlExpression::JsonQueryHandler(const TRule_json_query_handler& node) {
  697. /*
  698. json_query_handler: ERROR | NULL | (EMPTY ARRAY) | (EMPTY OBJECT);
  699. */
  700. switch (node.GetAltCase()) {
  701. case TRule_json_query_handler::kAltJsonQueryHandler1:
  702. return EJsonQueryHandler::Error;
  703. case TRule_json_query_handler::kAltJsonQueryHandler2:
  704. return EJsonQueryHandler::Null;
  705. case TRule_json_query_handler::kAltJsonQueryHandler3:
  706. return EJsonQueryHandler::EmptyArray;
  707. case TRule_json_query_handler::kAltJsonQueryHandler4:
  708. return EJsonQueryHandler::EmptyObject;
  709. case TRule_json_query_handler::ALT_NOT_SET:
  710. Y_ABORT("You should change implementation according to grammar changes");
  711. }
  712. }
  713. TNodePtr TSqlExpression::JsonQueryExpr(const TRule_json_query& node) {
  714. /*
  715. json_query: JSON_QUERY LPAREN
  716. json_common_args
  717. (json_query_wrapper WRAPPER)?
  718. (json_query_handler ON EMPTY)?
  719. (json_query_handler ON ERROR)?
  720. RPAREN;
  721. */
  722. TVector<TNodePtr> children;
  723. AddJsonCommonArgs(node.GetRule_json_common_args3(), children);
  724. auto addChild = [&](TPosition pos, const TString& content) {
  725. children.push_back(BuildQuotedAtom(pos, content, TNodeFlags::Default));
  726. };
  727. const auto wrapMode = JsonQueryWrapper(node);
  728. addChild(Ctx.Pos(), ToString(wrapMode));
  729. auto onEmpty = EJsonQueryHandler::Null;
  730. if (node.HasBlock5()) {
  731. if (wrapMode != EJsonQueryWrap::NoWrap) {
  732. Ctx.Error() << "ON EMPTY is prohibited because WRAPPER clause is specified";
  733. Ctx.IncrementMonCounter("sql_errors", "JsonQueryOnEmptyWithWrapper");
  734. return nullptr;
  735. }
  736. onEmpty = JsonQueryHandler(node.GetBlock5().GetRule_json_query_handler1());
  737. }
  738. addChild(Ctx.Pos(), ToString(onEmpty));
  739. auto onError = EJsonQueryHandler::Null;
  740. if (node.HasBlock6()) {
  741. onError = JsonQueryHandler(node.GetBlock6().GetRule_json_query_handler1());
  742. }
  743. addChild(Ctx.Pos(), ToString(onError));
  744. return new TCallNodeImpl(GetPos(node.GetToken1()), "JsonQuery", children);
  745. }
  746. TNodePtr TSqlExpression::JsonApiExpr(const TRule_json_api_expr& node) {
  747. /*
  748. json_api_expr: json_value | json_exists | json_query;
  749. */
  750. TPosition pos = Ctx.Pos();
  751. TNodePtr result = nullptr;
  752. switch (node.GetAltCase()) {
  753. case TRule_json_api_expr::kAltJsonApiExpr1: {
  754. const auto& jsonValue = node.GetAlt_json_api_expr1().GetRule_json_value1();
  755. pos = GetPos(jsonValue.GetToken1());
  756. result = JsonValueExpr(jsonValue);
  757. break;
  758. }
  759. case TRule_json_api_expr::kAltJsonApiExpr2: {
  760. const auto& jsonExists = node.GetAlt_json_api_expr2().GetRule_json_exists1();
  761. pos = GetPos(jsonExists.GetToken1());
  762. result = JsonExistsExpr(jsonExists);
  763. break;
  764. }
  765. case TRule_json_api_expr::kAltJsonApiExpr3: {
  766. const auto& jsonQuery = node.GetAlt_json_api_expr3().GetRule_json_query1();
  767. pos = GetPos(jsonQuery.GetToken1());
  768. result = JsonQueryExpr(jsonQuery);
  769. break;
  770. }
  771. case TRule_json_api_expr::ALT_NOT_SET:
  772. Y_ABORT("You should change implementation according to grammar changes");
  773. }
  774. return result;
  775. }
  776. TNodePtr TSqlExpression::RowPatternVarAccess(TString var, const TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2 block) {
  777. switch (block.GetAltCase()) {
  778. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt1:
  779. break;
  780. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt2:
  781. break;
  782. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt3:
  783. switch (block.GetAlt3().GetRule_an_id_or_type1().GetAltCase()) {
  784. case TRule_an_id_or_type::kAltAnIdOrType1: {
  785. const auto &idOrType = block.GetAlt3().GetRule_an_id_or_type1().GetAlt_an_id_or_type1().GetRule_id_or_type1();
  786. switch(idOrType.GetAltCase()) {
  787. case TRule_id_or_type::kAltIdOrType1: {
  788. const auto column = Id(idOrType.GetAlt_id_or_type1().GetRule_id1(), *this);
  789. return BuildMatchRecognizeColumnAccess(Ctx.Pos(), std::move(var), std::move(column));
  790. }
  791. case TRule_id_or_type::kAltIdOrType2:
  792. break;
  793. case TRule_id_or_type::ALT_NOT_SET:
  794. break;
  795. }
  796. break;
  797. }
  798. case TRule_an_id_or_type::kAltAnIdOrType2:
  799. break;
  800. case TRule_an_id_or_type::ALT_NOT_SET:
  801. break;
  802. }
  803. break;
  804. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::ALT_NOT_SET:
  805. Y_ABORT("You should change implementation according to grammar changes");
  806. }
  807. return {};
  808. }
  809. template<typename TUnaryCasualExprRule>
  810. TNodePtr TSqlExpression::UnaryCasualExpr(const TUnaryCasualExprRule& node, const TTrailingQuestions& tail) {
  811. // unary_casual_subexpr: (id_expr | atom_expr) unary_subexpr_suffix;
  812. // OR
  813. // in_unary_casual_subexpr: (id_expr_in | in_atom_expr) unary_subexpr_suffix;
  814. // where
  815. // unary_subexpr_suffix: (key_expr | invoke_expr |(DOT (bind_parameter | DIGITS | id)))* (COLLATE id)?;
  816. const auto& suffix = node.GetRule_unary_subexpr_suffix2();
  817. const bool suffixIsEmpty = suffix.GetBlock1().empty() && !suffix.HasBlock2();
  818. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && suffixIsEmpty;
  819. TString name;
  820. TNodePtr expr;
  821. bool typePossible = false;
  822. auto& block = node.GetBlock1();
  823. switch (block.Alt_case()) {
  824. case TUnaryCasualExprRule::TBlock1::kAlt1: {
  825. MaybeUnnamedSmartParenOnTop = false;
  826. auto& alt = block.GetAlt1();
  827. if constexpr (std::is_same_v<TUnaryCasualExprRule, TRule_unary_casual_subexpr>) {
  828. name = Id(alt.GetRule_id_expr1(), *this);
  829. typePossible = !IsQuotedId(alt.GetRule_id_expr1(), *this);
  830. } else {
  831. // type was never possible here
  832. name = Id(alt.GetRule_id_expr_in1(), *this);
  833. }
  834. break;
  835. }
  836. case TUnaryCasualExprRule::TBlock1::kAlt2: {
  837. auto& alt = block.GetAlt2();
  838. TMaybe<TExprOrIdent> exprOrId;
  839. if constexpr (std::is_same_v<TUnaryCasualExprRule, TRule_unary_casual_subexpr>) {
  840. exprOrId = AtomExpr(alt.GetRule_atom_expr1(), suffixIsEmpty ? tail : TTrailingQuestions{});
  841. } else {
  842. MaybeUnnamedSmartParenOnTop = false;
  843. exprOrId = InAtomExpr(alt.GetRule_in_atom_expr1(), suffixIsEmpty ? tail : TTrailingQuestions{});
  844. }
  845. if (!exprOrId) {
  846. Ctx.IncrementMonCounter("sql_errors", "BadAtomExpr");
  847. return nullptr;
  848. }
  849. if (!exprOrId->Expr) {
  850. name = exprOrId->Ident;
  851. } else {
  852. expr = exprOrId->Expr;
  853. }
  854. break;
  855. }
  856. case TUnaryCasualExprRule::TBlock1::ALT_NOT_SET:
  857. Y_ABORT("You should change implementation according to grammar changes");
  858. }
  859. // bool onlyDots = true;
  860. bool isColumnRef = !expr;
  861. bool isFirstElem = true;
  862. for (auto& _b : suffix.GetBlock1()) {
  863. auto& b = _b.GetBlock1();
  864. switch (b.Alt_case()) {
  865. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: {
  866. // key_expr
  867. // onlyDots = false;
  868. break;
  869. }
  870. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: {
  871. // invoke_expr - cannot be a column, function name
  872. if (isFirstElem) {
  873. isColumnRef = false;
  874. }
  875. // onlyDots = false;
  876. break;
  877. }
  878. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: {
  879. // In case of MATCH_RECOGNIZE lambdas
  880. // X.Y is treated as Var.Column access
  881. if (isColumnRef && (
  882. EColumnRefState::MatchRecognizeMeasures == Ctx.GetColumnReferenceState() ||
  883. EColumnRefState::MatchRecognizeDefine == Ctx.GetColumnReferenceState() ||
  884. EColumnRefState::MatchRecognizeDefineAggregate == Ctx.GetColumnReferenceState()
  885. )) {
  886. return RowPatternVarAccess(std::move(name), b.GetAlt3().GetBlock2());
  887. }
  888. break;
  889. }
  890. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET:
  891. AltNotImplemented("unary_subexpr_suffix", b);
  892. return nullptr;
  893. }
  894. isFirstElem = false;
  895. }
  896. isFirstElem = true;
  897. TVector<INode::TIdPart> ids;
  898. INode::TPtr lastExpr;
  899. if (!isColumnRef) {
  900. lastExpr = expr;
  901. } else {
  902. const bool flexibleTypes = Ctx.FlexibleTypes;
  903. bool columnOrType = false;
  904. auto columnRefsState = Ctx.GetColumnReferenceState();
  905. bool explicitPgType = columnRefsState == EColumnRefState::AsPgType;
  906. if (explicitPgType && typePossible && suffixIsEmpty) {
  907. auto pgType = BuildSimpleType(Ctx, Ctx.Pos(), name, false);
  908. if (pgType && tail.Count) {
  909. Ctx.Error() << "Optional types are not supported in this context";
  910. return {};
  911. }
  912. return pgType;
  913. }
  914. if (auto simpleType = LookupSimpleType(name, flexibleTypes, false); simpleType && typePossible && suffixIsEmpty) {
  915. if (tail.Count > 0 || columnRefsState == EColumnRefState::Deny || !flexibleTypes) {
  916. // a type
  917. return AddOptionals(BuildSimpleType(Ctx, Ctx.Pos(), name, false), tail.Count);
  918. }
  919. // type or column: ambiguity will be resolved on type annotation stage
  920. columnOrType = columnRefsState == EColumnRefState::Allow;
  921. }
  922. if (tail.Count) {
  923. UnexpectedQuestionToken(tail);
  924. return {};
  925. }
  926. if (!Ctx.CheckColumnReference(Ctx.Pos(), name)) {
  927. return nullptr;
  928. }
  929. ids.push_back(columnOrType ? BuildColumnOrType(Ctx.Pos()) : BuildColumn(Ctx.Pos()));
  930. ids.push_back(name);
  931. }
  932. TPosition pos(Ctx.Pos());
  933. for (auto& _b : suffix.GetBlock1()) {
  934. auto& b = _b.GetBlock1();
  935. switch (b.Alt_case()) {
  936. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: {
  937. // key_expr
  938. auto keyExpr = KeyExpr(b.GetAlt1().GetRule_key_expr1());
  939. if (!keyExpr) {
  940. Ctx.IncrementMonCounter("sql_errors", "BadKeyExpr");
  941. return nullptr;
  942. }
  943. if (!lastExpr) {
  944. lastExpr = BuildAccess(pos, ids, false);
  945. ids.clear();
  946. }
  947. ids.push_back(lastExpr);
  948. ids.push_back(keyExpr);
  949. lastExpr = BuildAccess(pos, ids, true);
  950. ids.clear();
  951. break;
  952. }
  953. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: {
  954. // invoke_expr - cannot be a column, function name
  955. TSqlCallExpr call(Ctx, Mode);
  956. if (isFirstElem && !name.empty()) {
  957. call.AllowDistinct();
  958. call.InitName(name);
  959. } else {
  960. call.InitExpr(lastExpr);
  961. }
  962. bool initRet = call.Init(b.GetAlt2().GetRule_invoke_expr1());
  963. if (initRet) {
  964. call.IncCounters();
  965. }
  966. if (!initRet) {
  967. return nullptr;
  968. }
  969. lastExpr = call.BuildCall();
  970. if (!lastExpr) {
  971. return nullptr;
  972. }
  973. break;
  974. }
  975. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: {
  976. // dot
  977. if (lastExpr) {
  978. ids.push_back(lastExpr);
  979. }
  980. auto bb = b.GetAlt3().GetBlock2();
  981. switch (bb.Alt_case()) {
  982. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt1: {
  983. TString named;
  984. if (!NamedNodeImpl(bb.GetAlt1().GetRule_bind_parameter1(), named, *this)) {
  985. return nullptr;
  986. }
  987. auto namedNode = GetNamedNode(named);
  988. if (!namedNode) {
  989. return nullptr;
  990. }
  991. ids.push_back(named);
  992. ids.back().Expr = namedNode;
  993. break;
  994. }
  995. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt2: {
  996. const TString str(Token(bb.GetAlt2().GetToken1()));
  997. ids.push_back(str);
  998. break;
  999. }
  1000. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt3: {
  1001. ids.push_back(Id(bb.GetAlt3().GetRule_an_id_or_type1(), *this));
  1002. break;
  1003. }
  1004. case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::ALT_NOT_SET:
  1005. Y_ABORT("You should change implementation according to grammar changes");
  1006. }
  1007. if (lastExpr) {
  1008. lastExpr = BuildAccess(pos, ids, false);
  1009. ids.clear();
  1010. }
  1011. break;
  1012. }
  1013. case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET:
  1014. AltNotImplemented("unary_subexpr_suffix", b);
  1015. return nullptr;
  1016. }
  1017. isFirstElem = false;
  1018. }
  1019. if (!lastExpr) {
  1020. lastExpr = BuildAccess(pos, ids, false);
  1021. ids.clear();
  1022. }
  1023. if (suffix.HasBlock2()) {
  1024. Ctx.IncrementMonCounter("sql_errors", "CollateUnarySubexpr");
  1025. Error() << "unary_subexpr: COLLATE is not implemented yet";
  1026. }
  1027. return lastExpr;
  1028. }
  1029. TNodePtr TSqlExpression::BindParameterRule(const TRule_bind_parameter& rule, const TTrailingQuestions& tail) {
  1030. TString namedArg;
  1031. if (!NamedNodeImpl(rule, namedArg, *this)) {
  1032. return {};
  1033. }
  1034. if (SmartParenthesisMode == ESmartParenthesis::SqlLambdaParams) {
  1035. Ctx.IncrementMonCounter("sql_features", "LambdaArgument");
  1036. if (tail.Count > 1) {
  1037. Ctx.Error(tail.Pos) << "Expecting at most one '?' token here (for optional lambda parameters), but got " << tail.Count;
  1038. return {};
  1039. }
  1040. return BuildAtom(Ctx.Pos(), namedArg, NYql::TNodeFlags::ArbitraryContent, tail.Count != 0);
  1041. }
  1042. if (tail.Count) {
  1043. UnexpectedQuestionToken(tail);
  1044. return {};
  1045. }
  1046. Ctx.IncrementMonCounter("sql_features", "NamedNodeUseAtom");
  1047. auto ret = GetNamedNode(namedArg);
  1048. if (ret) {
  1049. ret->SetRefPos(Ctx.Pos());
  1050. }
  1051. return ret;
  1052. }
  1053. TNodePtr TSqlExpression::LambdaRule(const TRule_lambda& rule) {
  1054. const auto& alt = rule;
  1055. const bool isSqlLambda = alt.HasBlock2();
  1056. if (!isSqlLambda) {
  1057. return SmartParenthesis(alt.GetRule_smart_parenthesis1());
  1058. }
  1059. MaybeUnnamedSmartParenOnTop = false;
  1060. TNodePtr parenthesis;
  1061. {
  1062. // we allow column reference here to postpone error and report it with better description in SqlLambdaParams
  1063. TColumnRefScope scope(Ctx, EColumnRefState::Allow);
  1064. TSqlExpression expr(Ctx, Mode);
  1065. expr.SetSmartParenthesisMode(ESmartParenthesis::SqlLambdaParams);
  1066. parenthesis = expr.SmartParenthesis(alt.GetRule_smart_parenthesis1());
  1067. }
  1068. if (!parenthesis) {
  1069. return {};
  1070. }
  1071. ui32 optionalArgumentsCount = 0;
  1072. TVector<TSymbolNameWithPos> args;
  1073. if (!SqlLambdaParams(parenthesis, args, optionalArgumentsCount)) {
  1074. return {};
  1075. }
  1076. auto bodyBlock = alt.GetBlock2();
  1077. Token(bodyBlock.GetToken1());
  1078. TPosition pos(Ctx.Pos());
  1079. TVector<TNodePtr> exprSeq;
  1080. for (auto& arg: args) {
  1081. arg.Name = PushNamedAtom(arg.Pos, arg.Name);
  1082. }
  1083. bool ret = false;
  1084. TColumnRefScope scope(Ctx, EColumnRefState::Deny);
  1085. scope.SetNoColumnErrContext("in lambda function");
  1086. if (bodyBlock.GetBlock2().HasAlt1()) {
  1087. ret = SqlLambdaExprBody(Ctx, bodyBlock.GetBlock2().GetAlt1().GetRule_expr2(), exprSeq);
  1088. } else {
  1089. ret = SqlLambdaExprBody(Ctx, bodyBlock.GetBlock2().GetAlt2().GetRule_lambda_body2(), exprSeq);
  1090. }
  1091. TVector<TString> argNames;
  1092. for (const auto& arg : args) {
  1093. argNames.push_back(arg.Name);
  1094. PopNamedNode(arg.Name);
  1095. }
  1096. if (!ret) {
  1097. return {};
  1098. }
  1099. auto lambdaNode = BuildSqlLambda(pos, std::move(argNames), std::move(exprSeq));
  1100. if (optionalArgumentsCount > 0) {
  1101. lambdaNode = new TCallNodeImpl(pos, "WithOptionalArgs", {
  1102. lambdaNode,
  1103. BuildQuotedAtom(pos, ToString(optionalArgumentsCount), TNodeFlags::Default)
  1104. });
  1105. }
  1106. return lambdaNode;
  1107. }
  1108. TNodePtr TSqlExpression::CastRule(const TRule_cast_expr& rule) {
  1109. Ctx.IncrementMonCounter("sql_features", "Cast");
  1110. const auto& alt = rule;
  1111. Token(alt.GetToken1());
  1112. TPosition pos(Ctx.Pos());
  1113. TSqlExpression expr(Ctx, Mode);
  1114. auto exprNode = expr.Build(rule.GetRule_expr3());
  1115. if (!exprNode) {
  1116. return {};
  1117. }
  1118. auto type = TypeNodeOrBind(rule.GetRule_type_name_or_bind5());
  1119. if (!type) {
  1120. return {};
  1121. }
  1122. return new TCallNodeImpl(pos, "SafeCast", {exprNode, type});
  1123. }
  1124. TNodePtr TSqlExpression::BitCastRule(const TRule_bitcast_expr& rule) {
  1125. Ctx.IncrementMonCounter("sql_features", "BitCast");
  1126. const auto& alt = rule;
  1127. Token(alt.GetToken1());
  1128. TPosition pos(Ctx.Pos());
  1129. TSqlExpression expr(Ctx, Mode);
  1130. auto exprNode = expr.Build(rule.GetRule_expr3());
  1131. if (!exprNode) {
  1132. return {};
  1133. }
  1134. auto type = TypeSimple(rule.GetRule_type_name_simple5(), true);
  1135. if (!type) {
  1136. return {};
  1137. }
  1138. return new TCallNodeImpl(pos, "BitCast", {exprNode, type});
  1139. }
  1140. TNodePtr TSqlExpression::ExistsRule(const TRule_exists_expr& rule) {
  1141. Ctx.IncrementMonCounter("sql_features", "Exists");
  1142. TPosition pos;
  1143. TSourcePtr source;
  1144. Token(rule.GetToken2());
  1145. switch (rule.GetBlock3().Alt_case()) {
  1146. case TRule_exists_expr::TBlock3::kAlt1: {
  1147. const auto& alt = rule.GetBlock3().GetAlt1().GetRule_select_stmt1();
  1148. TSqlSelect select(Ctx, Mode);
  1149. source = select.Build(alt, pos);
  1150. break;
  1151. }
  1152. case TRule_exists_expr::TBlock3::kAlt2: {
  1153. const auto& alt = rule.GetBlock3().GetAlt2().GetRule_values_stmt1();
  1154. TSqlValues values(Ctx, Mode);
  1155. source = values.Build(alt, pos);
  1156. break;
  1157. }
  1158. case TRule_exists_expr::TBlock3::ALT_NOT_SET:
  1159. AltNotImplemented("exists_expr", rule.GetBlock3());
  1160. }
  1161. if (!source) {
  1162. Ctx.IncrementMonCounter("sql_errors", "BadSource");
  1163. return nullptr;
  1164. }
  1165. const bool checkExist = true;
  1166. auto select = BuildSourceNode(Ctx.Pos(), source, checkExist);
  1167. if (Ctx.Settings.EmitReadsForExists) {
  1168. TTableList tableList;
  1169. source->GetInputTables(tableList);
  1170. TNodePtr inputTables(BuildInputTables(Ctx.Pos(), tableList, false, Ctx.Scoped));
  1171. if (!inputTables->Init(Ctx, source.Get())) {
  1172. return nullptr;
  1173. }
  1174. auto node = inputTables;
  1175. node = node->L(node, node->Y("return", select));
  1176. select = node->Y("block", node->Q(node));
  1177. }
  1178. return BuildBuiltinFunc(Ctx, Ctx.Pos(), "ListHasItems", {select});
  1179. }
  1180. TNodePtr TSqlExpression::CaseRule(const TRule_case_expr& rule) {
  1181. // case_expr: CASE expr? when_expr+ (ELSE expr)? END;
  1182. // when_expr: WHEN expr THEN expr;
  1183. Ctx.IncrementMonCounter("sql_features", "Case");
  1184. const auto& alt = rule;
  1185. Token(alt.GetToken1());
  1186. TNodePtr elseExpr;
  1187. if (alt.HasBlock4()) {
  1188. Token(alt.GetBlock4().GetToken1());
  1189. TSqlExpression expr(Ctx, Mode);
  1190. elseExpr = expr.Build(alt.GetBlock4().GetRule_expr2());
  1191. } else {
  1192. Ctx.IncrementMonCounter("sql_errors", "ElseIsRequired");
  1193. Error() << "ELSE is required";
  1194. return {};
  1195. }
  1196. TNodePtr caseExpr;
  1197. if (alt.HasBlock2()) {
  1198. TSqlExpression expr(Ctx, Mode);
  1199. caseExpr = expr.Build(alt.GetBlock2().GetRule_expr1());
  1200. if (!caseExpr) {
  1201. return {};
  1202. }
  1203. }
  1204. TVector<TCaseBranch> branches;
  1205. for (size_t i = 0; i < alt.Block3Size(); ++i) {
  1206. branches.emplace_back();
  1207. const auto& block = alt.GetBlock3(i).GetRule_when_expr1();
  1208. Token(block.GetToken1());
  1209. TSqlExpression condExpr(Ctx, Mode);
  1210. branches.back().Pred = condExpr.Build(block.GetRule_expr2());
  1211. if (caseExpr) {
  1212. branches.back().Pred = BuildBinaryOp(Ctx, Ctx.Pos(), "==", caseExpr->Clone(), branches.back().Pred);
  1213. }
  1214. if (!branches.back().Pred) {
  1215. return {};
  1216. }
  1217. Token(block.GetToken3());
  1218. TSqlExpression thenExpr(Ctx, Mode);
  1219. branches.back().Value = thenExpr.Build(block.GetRule_expr4());
  1220. if (!branches.back().Value) {
  1221. return {};
  1222. }
  1223. }
  1224. auto final = ReduceCaseBranches(branches.begin(), branches.end());
  1225. return BuildBuiltinFunc(Ctx, Ctx.Pos(), "If", { final.Pred, final.Value, elseExpr });
  1226. }
  1227. TMaybe<TExprOrIdent> TSqlExpression::AtomExpr(const TRule_atom_expr& node, const TTrailingQuestions& tail) {
  1228. // atom_expr:
  1229. // literal_value
  1230. // | bind_parameter
  1231. // | lambda
  1232. // | cast_expr
  1233. // | exists_expr
  1234. // | case_expr
  1235. // | an_id_or_type NAMESPACE (id_or_type | STRING_VALUE)
  1236. // | value_constructor
  1237. // | bitcast_expr
  1238. // | list_literal
  1239. // | dict_literal
  1240. // | struct_literal
  1241. // ;
  1242. if (node.Alt_case() != TRule_atom_expr::kAltAtomExpr2 && tail.Count) {
  1243. UnexpectedQuestionToken(tail);
  1244. return {};
  1245. }
  1246. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && (node.Alt_case() == TRule_atom_expr::kAltAtomExpr3);
  1247. TExprOrIdent result;
  1248. switch (node.Alt_case()) {
  1249. case TRule_atom_expr::kAltAtomExpr1:
  1250. Ctx.IncrementMonCounter("sql_features", "LiteralExpr");
  1251. return LiteralExpr(node.GetAlt_atom_expr1().GetRule_literal_value1());
  1252. case TRule_atom_expr::kAltAtomExpr2:
  1253. result.Expr = BindParameterRule(node.GetAlt_atom_expr2().GetRule_bind_parameter1(), tail);
  1254. break;
  1255. case TRule_atom_expr::kAltAtomExpr3:
  1256. result.Expr = LambdaRule(node.GetAlt_atom_expr3().GetRule_lambda1());
  1257. break;
  1258. case TRule_atom_expr::kAltAtomExpr4:
  1259. result.Expr = CastRule(node.GetAlt_atom_expr4().GetRule_cast_expr1());
  1260. break;
  1261. case TRule_atom_expr::kAltAtomExpr5:
  1262. result.Expr = ExistsRule(node.GetAlt_atom_expr5().GetRule_exists_expr1());
  1263. break;
  1264. case TRule_atom_expr::kAltAtomExpr6:
  1265. result.Expr = CaseRule(node.GetAlt_atom_expr6().GetRule_case_expr1());
  1266. break;
  1267. case TRule_atom_expr::kAltAtomExpr7: {
  1268. const auto& alt = node.GetAlt_atom_expr7();
  1269. TString module(Id(alt.GetRule_an_id_or_type1(), *this));
  1270. TPosition pos(Ctx.Pos());
  1271. TString name;
  1272. switch (alt.GetBlock3().Alt_case()) {
  1273. case TRule_atom_expr::TAlt7::TBlock3::kAlt1:
  1274. name = Id(alt.GetBlock3().GetAlt1().GetRule_id_or_type1(), *this);
  1275. break;
  1276. case TRule_atom_expr::TAlt7::TBlock3::kAlt2: {
  1277. name = Token(alt.GetBlock3().GetAlt2().GetToken1());
  1278. if (Ctx.AnsiQuotedIdentifiers && name.StartsWith('"')) {
  1279. // same as previous case
  1280. name = IdContentFromString(Ctx, name);
  1281. } else {
  1282. module = "@" + module;
  1283. }
  1284. break;
  1285. }
  1286. case TRule_atom_expr::TAlt7::TBlock3::ALT_NOT_SET:
  1287. Y_ABORT("Unsigned number: you should change implementation according to grammar changes");
  1288. }
  1289. result.Expr = BuildCallable(pos, module, name, {});
  1290. break;
  1291. }
  1292. case TRule_atom_expr::kAltAtomExpr8: {
  1293. result.Expr = ValueConstructor(node.GetAlt_atom_expr8().GetRule_value_constructor1());
  1294. break;
  1295. }
  1296. case TRule_atom_expr::kAltAtomExpr9:
  1297. result.Expr = BitCastRule(node.GetAlt_atom_expr9().GetRule_bitcast_expr1());
  1298. break;
  1299. case TRule_atom_expr::kAltAtomExpr10:
  1300. result.Expr = ListLiteral(node.GetAlt_atom_expr10().GetRule_list_literal1());
  1301. break;
  1302. case TRule_atom_expr::kAltAtomExpr11:
  1303. result.Expr = DictLiteral(node.GetAlt_atom_expr11().GetRule_dict_literal1());
  1304. break;
  1305. case TRule_atom_expr::kAltAtomExpr12:
  1306. result.Expr = StructLiteral(node.GetAlt_atom_expr12().GetRule_struct_literal1());
  1307. break;
  1308. case TRule_atom_expr::ALT_NOT_SET:
  1309. AltNotImplemented("atom_expr", node);
  1310. }
  1311. if (!result.Expr) {
  1312. return {};
  1313. }
  1314. return result;
  1315. }
  1316. TMaybe<TExprOrIdent> TSqlExpression::InAtomExpr(const TRule_in_atom_expr& node, const TTrailingQuestions& tail) {
  1317. // in_atom_expr:
  1318. // literal_value
  1319. // | bind_parameter
  1320. // | lambda
  1321. // | cast_expr
  1322. // | case_expr
  1323. // | an_id_or_type NAMESPACE (id_or_type | STRING_VALUE)
  1324. // | LPAREN select_stmt RPAREN
  1325. // | value_constructor
  1326. // | bitcast_expr
  1327. // | list_literal
  1328. // | dict_literal
  1329. // | struct_literal
  1330. // ;
  1331. if (node.Alt_case() != TRule_in_atom_expr::kAltInAtomExpr2 && tail.Count) {
  1332. UnexpectedQuestionToken(tail);
  1333. return {};
  1334. }
  1335. TExprOrIdent result;
  1336. switch (node.Alt_case()) {
  1337. case TRule_in_atom_expr::kAltInAtomExpr1:
  1338. Ctx.IncrementMonCounter("sql_features", "LiteralExpr");
  1339. return LiteralExpr(node.GetAlt_in_atom_expr1().GetRule_literal_value1());
  1340. case TRule_in_atom_expr::kAltInAtomExpr2:
  1341. result.Expr = BindParameterRule(node.GetAlt_in_atom_expr2().GetRule_bind_parameter1(), tail);
  1342. break;
  1343. case TRule_in_atom_expr::kAltInAtomExpr3:
  1344. result.Expr = LambdaRule(node.GetAlt_in_atom_expr3().GetRule_lambda1());
  1345. break;
  1346. case TRule_in_atom_expr::kAltInAtomExpr4:
  1347. result.Expr = CastRule(node.GetAlt_in_atom_expr4().GetRule_cast_expr1());
  1348. break;
  1349. case TRule_in_atom_expr::kAltInAtomExpr5:
  1350. result.Expr = CaseRule(node.GetAlt_in_atom_expr5().GetRule_case_expr1());
  1351. break;
  1352. case TRule_in_atom_expr::kAltInAtomExpr6: {
  1353. const auto& alt = node.GetAlt_in_atom_expr6();
  1354. TString module(Id(alt.GetRule_an_id_or_type1(), *this));
  1355. TPosition pos(Ctx.Pos());
  1356. TString name;
  1357. switch (alt.GetBlock3().Alt_case()) {
  1358. case TRule_in_atom_expr::TAlt6::TBlock3::kAlt1:
  1359. name = Id(alt.GetBlock3().GetAlt1().GetRule_id_or_type1(), *this);
  1360. break;
  1361. case TRule_in_atom_expr::TAlt6::TBlock3::kAlt2: {
  1362. name = Token(alt.GetBlock3().GetAlt2().GetToken1());
  1363. if (Ctx.AnsiQuotedIdentifiers && name.StartsWith('"')) {
  1364. // same as previous case
  1365. name = IdContentFromString(Ctx, name);
  1366. } else {
  1367. module = "@" + module;
  1368. }
  1369. break;
  1370. }
  1371. case TRule_in_atom_expr::TAlt6::TBlock3::ALT_NOT_SET:
  1372. Y_ABORT("You should change implementation according to grammar changes");
  1373. }
  1374. result.Expr = BuildCallable(pos, module, name, {});
  1375. break;
  1376. }
  1377. case TRule_in_atom_expr::kAltInAtomExpr7: {
  1378. Token(node.GetAlt_in_atom_expr7().GetToken1());
  1379. // reset column reference scope (select will reenable it where needed)
  1380. TColumnRefScope scope(Ctx, EColumnRefState::Deny);
  1381. TSqlSelect select(Ctx, Mode);
  1382. TPosition pos;
  1383. auto source = select.Build(node.GetAlt_in_atom_expr7().GetRule_select_stmt2(), pos);
  1384. if (!source) {
  1385. Ctx.IncrementMonCounter("sql_errors", "BadSource");
  1386. return {};
  1387. }
  1388. Ctx.IncrementMonCounter("sql_features", "InSubquery");
  1389. const auto alias = Ctx.MakeName("subquerynode");
  1390. const auto ref = Ctx.MakeName("subquery");
  1391. auto& blocks = Ctx.GetCurrentBlocks();
  1392. blocks.push_back(BuildSubquery(std::move(source), alias, Mode == NSQLTranslation::ESqlMode::SUBQUERY, -1, Ctx.Scoped));
  1393. blocks.back()->SetLabel(ref);
  1394. result.Expr = BuildSubqueryRef(blocks.back(), ref, -1);
  1395. break;
  1396. }
  1397. case TRule_in_atom_expr::kAltInAtomExpr8: {
  1398. result.Expr = ValueConstructor(node.GetAlt_in_atom_expr8().GetRule_value_constructor1());
  1399. break;
  1400. }
  1401. case TRule_in_atom_expr::kAltInAtomExpr9:
  1402. result.Expr = BitCastRule(node.GetAlt_in_atom_expr9().GetRule_bitcast_expr1());
  1403. break;
  1404. case TRule_in_atom_expr::kAltInAtomExpr10:
  1405. result.Expr = ListLiteral(node.GetAlt_in_atom_expr10().GetRule_list_literal1());
  1406. break;
  1407. case TRule_in_atom_expr::kAltInAtomExpr11:
  1408. result.Expr = DictLiteral(node.GetAlt_in_atom_expr11().GetRule_dict_literal1());
  1409. break;
  1410. case TRule_in_atom_expr::kAltInAtomExpr12:
  1411. result.Expr = StructLiteral(node.GetAlt_in_atom_expr12().GetRule_struct_literal1());
  1412. break;
  1413. case TRule_in_atom_expr::ALT_NOT_SET:
  1414. AltNotImplemented("in_atom_expr", node);
  1415. }
  1416. if (!result.Expr) {
  1417. return {};
  1418. }
  1419. return result;
  1420. }
  1421. bool TSqlExpression::SqlLambdaParams(const TNodePtr& node, TVector<TSymbolNameWithPos>& args, ui32& optionalArgumentsCount) {
  1422. args.clear();
  1423. optionalArgumentsCount = 0;
  1424. auto errMsg = TStringBuf("Invalid lambda arguments syntax. Lambda arguments should start with '$' as named value.");
  1425. auto tupleNodePtr = node->GetTupleNode();;
  1426. if (!tupleNodePtr) {
  1427. Ctx.Error(node->GetPos()) << errMsg;
  1428. return false;
  1429. }
  1430. THashSet<TString> dupArgsChecker;
  1431. for (const auto& argPtr: tupleNodePtr->Elements()) {
  1432. auto contentPtr = argPtr->GetAtomContent();
  1433. if (!contentPtr || !contentPtr->StartsWith("$")) {
  1434. Ctx.Error(argPtr->GetPos()) << errMsg;
  1435. return false;
  1436. }
  1437. if (argPtr->IsOptionalArg()) {
  1438. ++optionalArgumentsCount;
  1439. } else if (optionalArgumentsCount > 0) {
  1440. Ctx.Error(argPtr->GetPos()) << "Non-optional argument can not follow optional one";
  1441. return false;
  1442. }
  1443. if (!IsAnonymousName(*contentPtr) && !dupArgsChecker.insert(*contentPtr).second) {
  1444. Ctx.Error(argPtr->GetPos()) << "Duplicate lambda argument parametr: '" << *contentPtr << "'.";
  1445. return false;
  1446. }
  1447. args.push_back(TSymbolNameWithPos{*contentPtr, argPtr->GetPos()});
  1448. }
  1449. return true;
  1450. }
  1451. bool TSqlExpression::SqlLambdaExprBody(TContext& ctx, const TRule_expr& node, TVector<TNodePtr>& exprSeq) {
  1452. TSqlExpression expr(ctx, ctx.Settings.Mode);
  1453. TNodePtr nodeExpr = expr.Build(node);
  1454. if (!nodeExpr) {
  1455. return false;
  1456. }
  1457. exprSeq.push_back(nodeExpr);
  1458. return true;
  1459. }
  1460. bool TSqlExpression::SqlLambdaExprBody(TContext& ctx, const TRule_lambda_body& node, TVector<TNodePtr>& exprSeq) {
  1461. TSqlExpression expr(ctx, ctx.Settings.Mode);
  1462. TVector<TString> localNames;
  1463. bool hasError = false;
  1464. for (auto& block: node.GetBlock2()) {
  1465. const auto& rule = block.GetRule_lambda_stmt1();
  1466. switch (rule.Alt_case()) {
  1467. case TRule_lambda_stmt::kAltLambdaStmt1: {
  1468. TVector<TSymbolNameWithPos> names;
  1469. auto nodeExpr = NamedNode(rule.GetAlt_lambda_stmt1().GetRule_named_nodes_stmt1(), names);
  1470. if (!nodeExpr) {
  1471. hasError = true;
  1472. continue;
  1473. } else if (nodeExpr->GetSource()) {
  1474. ctx.Error() << "SELECT is not supported inside lambda body";
  1475. hasError = true;
  1476. continue;
  1477. }
  1478. if (names.size() > 1) {
  1479. auto ref = ctx.MakeName("tie");
  1480. exprSeq.push_back(nodeExpr->Y("EnsureTupleSize", nodeExpr, nodeExpr->Q(ToString(names.size()))));
  1481. exprSeq.back()->SetLabel(ref);
  1482. for (size_t i = 0; i < names.size(); ++i) {
  1483. TNodePtr nthExpr = nodeExpr->Y("Nth", ref, nodeExpr->Q(ToString(i)));
  1484. names[i].Name = PushNamedAtom(names[i].Pos, names[i].Name);
  1485. nthExpr->SetLabel(names[i].Name);
  1486. localNames.push_back(names[i].Name);
  1487. exprSeq.push_back(nthExpr);
  1488. }
  1489. } else {
  1490. auto& symbol = names.front();
  1491. symbol.Name = PushNamedAtom(symbol.Pos, symbol.Name);
  1492. nodeExpr->SetLabel(symbol.Name);
  1493. localNames.push_back(symbol.Name);
  1494. exprSeq.push_back(nodeExpr);
  1495. }
  1496. break;
  1497. }
  1498. case TRule_lambda_stmt::kAltLambdaStmt2: {
  1499. if (!ImportStatement(rule.GetAlt_lambda_stmt2().GetRule_import_stmt1(), &localNames)) {
  1500. hasError = true;
  1501. }
  1502. break;
  1503. }
  1504. case TRule_lambda_stmt::ALT_NOT_SET:
  1505. Y_ABORT("SampleClause: does not correspond to grammar changes");
  1506. }
  1507. }
  1508. TNodePtr nodeExpr;
  1509. if (!hasError) {
  1510. nodeExpr = expr.Build(node.GetRule_expr4());
  1511. }
  1512. for (const auto& name : localNames) {
  1513. PopNamedNode(name);
  1514. }
  1515. if (!nodeExpr) {
  1516. return false;
  1517. }
  1518. exprSeq.push_back(nodeExpr);
  1519. return true;
  1520. }
  1521. TNodePtr TSqlExpression::SubExpr(const TRule_con_subexpr& node, const TTrailingQuestions& tail) {
  1522. // con_subexpr: unary_subexpr | unary_op unary_subexpr;
  1523. switch (node.Alt_case()) {
  1524. case TRule_con_subexpr::kAltConSubexpr1:
  1525. return UnaryExpr(node.GetAlt_con_subexpr1().GetRule_unary_subexpr1(), tail);
  1526. case TRule_con_subexpr::kAltConSubexpr2: {
  1527. MaybeUnnamedSmartParenOnTop = false;
  1528. Ctx.IncrementMonCounter("sql_features", "UnaryOperation");
  1529. TString opName;
  1530. auto token = node.GetAlt_con_subexpr2().GetRule_unary_op1().GetToken1();
  1531. Token(token);
  1532. TPosition pos(Ctx.Pos());
  1533. auto tokenId = token.GetId();
  1534. if (IS_TOKEN(tokenId, NOT)) {
  1535. opName = "Not";
  1536. } else if (IS_TOKEN(tokenId, PLUS)) {
  1537. opName = "Plus";
  1538. } else if (IS_TOKEN(tokenId, MINUS)) {
  1539. opName = Ctx.Scoped->PragmaCheckedOps ? "CheckedMinus" : "Minus";
  1540. } else if (IS_TOKEN(tokenId, TILDA)) {
  1541. opName = "BitNot";
  1542. } else {
  1543. Ctx.IncrementMonCounter("sql_errors", "UnsupportedUnaryOperation");
  1544. Error() << "Unsupported unary operation: " << token.GetValue();
  1545. return nullptr;
  1546. }
  1547. Ctx.IncrementMonCounter("sql_unary_operations", opName);
  1548. auto expr = UnaryExpr(node.GetAlt_con_subexpr2().GetRule_unary_subexpr2(), tail);
  1549. return expr ? expr->ApplyUnaryOp(Ctx, pos, opName) : expr;
  1550. }
  1551. case TRule_con_subexpr::ALT_NOT_SET:
  1552. Y_ABORT("You should change implementation according to grammar changes");
  1553. }
  1554. return nullptr;
  1555. }
  1556. TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQuestions& tail) {
  1557. // xor_subexpr: eq_subexpr cond_expr?;
  1558. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && !node.HasBlock2();
  1559. TNodePtr res(SubExpr(node.GetRule_eq_subexpr1(), node.HasBlock2() ? TTrailingQuestions{} : tail));
  1560. if (!res) {
  1561. return {};
  1562. }
  1563. TPosition pos(Ctx.Pos());
  1564. if (node.HasBlock2()) {
  1565. auto cond = node.GetBlock2().GetRule_cond_expr1();
  1566. switch (cond.Alt_case()) {
  1567. case TRule_cond_expr::kAltCondExpr1: {
  1568. const auto& matchOp = cond.GetAlt_cond_expr1();
  1569. const bool notMatch = matchOp.HasBlock1();
  1570. const TCiString& opName = Token(matchOp.GetRule_match_op2().GetToken1());
  1571. const auto& pattern = SubExpr(cond.GetAlt_cond_expr1().GetRule_eq_subexpr3(), matchOp.HasBlock4() ? TTrailingQuestions{} : tail);
  1572. if (!pattern) {
  1573. return {};
  1574. }
  1575. TNodePtr isMatch;
  1576. if (opName == "like" || opName == "ilike") {
  1577. const TString* escapeLiteral = nullptr;
  1578. TNodePtr escapeNode;
  1579. const auto& escaper = BuildUdf(Ctx, pos, "Re2", "PatternFromLike", {});
  1580. TVector<TNodePtr> escaperArgs({ escaper, pattern });
  1581. if (matchOp.HasBlock4()) {
  1582. const auto& escapeBlock = matchOp.GetBlock4();
  1583. TNodePtr escapeExpr = SubExpr(escapeBlock.GetRule_eq_subexpr2(), tail);
  1584. if (!escapeExpr) {
  1585. return {};
  1586. }
  1587. escapeLiteral = escapeExpr->GetLiteral("String");
  1588. escapeNode = escapeExpr;
  1589. if (escapeLiteral) {
  1590. Ctx.IncrementMonCounter("sql_features", "LikeEscape");
  1591. if (escapeLiteral->size() != 1) {
  1592. Ctx.IncrementMonCounter("sql_errors", "LikeMultiCharEscape");
  1593. Error() << "ESCAPE clause requires single character argument";
  1594. return nullptr;
  1595. }
  1596. if (escapeLiteral[0] == "%" || escapeLiteral[0] == "_" || escapeLiteral[0] == "\\") {
  1597. Ctx.IncrementMonCounter("sql_errors", "LikeUnsupportedEscapeChar");
  1598. Error() << "'%', '_' and '\\' are currently not supported in ESCAPE clause, ";
  1599. Error() << "please choose any other character";
  1600. return nullptr;
  1601. }
  1602. if (!IsAscii(escapeLiteral->front())) {
  1603. Ctx.IncrementMonCounter("sql_errors", "LikeUnsupportedEscapeChar");
  1604. Error() << "Non-ASCII symbols are not supported in ESCAPE clause, ";
  1605. Error() << "please choose ASCII character";
  1606. return nullptr;
  1607. }
  1608. escaperArgs.push_back(BuildLiteralRawString(pos, *escapeLiteral));
  1609. } else {
  1610. Ctx.IncrementMonCounter("sql_errors", "LikeNotLiteralEscape");
  1611. Error() << "ESCAPE clause requires String literal argument";
  1612. return nullptr;
  1613. }
  1614. }
  1615. auto re2options = BuildUdf(Ctx, pos, "Re2", "Options", {});
  1616. if (opName == "ilike") {
  1617. Ctx.IncrementMonCounter("sql_features", "CaseInsensitiveLike");
  1618. }
  1619. auto csModeLiteral = BuildLiteralBool(pos, opName != "ilike");
  1620. csModeLiteral->SetLabel("CaseSensitive");
  1621. auto csOption = BuildStructure(pos, { csModeLiteral });
  1622. auto optionsApply = new TCallNodeImpl(pos, "NamedApply", { re2options, BuildTuple(pos, {}), csOption });
  1623. const TNodePtr escapedPattern = new TCallNodeImpl(pos, "Apply", { escaperArgs });
  1624. auto list = new TAstListNodeImpl(pos, { escapedPattern, optionsApply });
  1625. auto runConfig = new TAstListNodeImpl(pos, { new TAstAtomNodeImpl(pos, "quote", 0), list });
  1626. const TNodePtr matcher = new TCallNodeImpl(pos, "AssumeStrict", { BuildUdf(Ctx, pos, "Re2", "Match", { runConfig }) });
  1627. isMatch = new TCallNodeImpl(pos, "Apply", { matcher, res });
  1628. bool isUtf8 = false;
  1629. const TString* literalPattern = pattern->GetLiteral("String");
  1630. if (!literalPattern) {
  1631. literalPattern = pattern->GetLiteral("Utf8");
  1632. isUtf8 = literalPattern != nullptr;
  1633. }
  1634. if (literalPattern) {
  1635. bool inEscape = false;
  1636. TMaybe<char> escape;
  1637. if (escapeLiteral) {
  1638. escape = escapeLiteral->front();
  1639. }
  1640. bool mayIgnoreCase;
  1641. TVector<TPatternComponent<char>> components;
  1642. if (isUtf8) {
  1643. auto splitResult = SplitPattern(UTF8ToUTF32<false>(*literalPattern), escape, inEscape);
  1644. for (const auto& component : splitResult) {
  1645. TPatternComponent<char> converted;
  1646. converted.IsSimple = component.IsSimple;
  1647. converted.Prefix = WideToUTF8(component.Prefix);
  1648. converted.Suffix = WideToUTF8(component.Suffix);
  1649. components.push_back(std::move(converted));
  1650. }
  1651. mayIgnoreCase = ToLowerUTF8(*literalPattern) == ToUpperUTF8(*literalPattern);
  1652. } else {
  1653. components = SplitPattern(*literalPattern, escape, inEscape);
  1654. mayIgnoreCase = WithoutAlpha(*literalPattern);
  1655. }
  1656. if (inEscape) {
  1657. Ctx.IncrementMonCounter("sql_errors", "LikeEscapeSymbolEnd");
  1658. Error() << "LIKE pattern should not end with escape symbol";
  1659. return nullptr;
  1660. }
  1661. if (opName == "like" || mayIgnoreCase) {
  1662. // TODO: expand LIKE in optimizers - we can analyze argument types there
  1663. YQL_ENSURE(!components.empty());
  1664. const auto& first = components.front();
  1665. if (components.size() == 1 && first.IsSimple) {
  1666. // no '%'s and '_'s in pattern
  1667. YQL_ENSURE(first.Prefix == first.Suffix);
  1668. isMatch = BuildBinaryOp(Ctx, pos, "==", res, BuildLiteralRawString(pos, first.Suffix, isUtf8));
  1669. } else if (!first.Prefix.empty()) {
  1670. const TString& prefix = first.Prefix;
  1671. TNodePtr prefixMatch;
  1672. if (Ctx.EmitStartsWith) {
  1673. prefixMatch = BuildBinaryOp(Ctx, pos, "StartsWith", res, BuildLiteralRawString(pos, prefix, isUtf8));
  1674. } else {
  1675. prefixMatch = BuildBinaryOp(Ctx, pos, ">=", res, BuildLiteralRawString(pos, prefix, isUtf8));
  1676. auto upperBound = isUtf8 ? NextValidUtf8(prefix) : NextLexicographicString(prefix);
  1677. if (upperBound) {
  1678. prefixMatch = BuildBinaryOp(
  1679. Ctx,
  1680. pos,
  1681. "And",
  1682. prefixMatch,
  1683. BuildBinaryOp(Ctx, pos, "<", res, BuildLiteralRawString(pos, TString(*upperBound), isUtf8))
  1684. );
  1685. }
  1686. }
  1687. if (Ctx.AnsiLike && first.IsSimple && components.size() == 2 && components.back().IsSimple) {
  1688. const TString& suffix = components.back().Suffix;
  1689. // 'prefix%suffix'
  1690. if (suffix.empty()) {
  1691. isMatch = prefixMatch;
  1692. } else {
  1693. // len(str) >= len(prefix) + len(suffix) && StartsWith(str, prefix) && EndsWith(str, suffix)
  1694. TNodePtr sizePred = BuildBinaryOp(Ctx, pos, ">=",
  1695. TNodePtr(new TCallNodeImpl(pos, "Size", { res })),
  1696. TNodePtr(new TLiteralNumberNode<ui32>(pos, "Uint32", ToString(prefix.size() + suffix.size()))));
  1697. TNodePtr suffixMatch = BuildBinaryOp(Ctx, pos, "EndsWith", res, BuildLiteralRawString(pos, suffix, isUtf8));
  1698. isMatch = new TCallNodeImpl(pos, "And", {
  1699. sizePred,
  1700. prefixMatch,
  1701. suffixMatch
  1702. });
  1703. }
  1704. } else {
  1705. isMatch = BuildBinaryOp(Ctx, pos, "And", prefixMatch, isMatch);
  1706. }
  1707. } else if (Ctx.AnsiLike && AllOf(components, [](const auto& comp) { return comp.IsSimple; })) {
  1708. YQL_ENSURE(first.Prefix.empty());
  1709. if (components.size() == 3 && components.back().Prefix.empty()) {
  1710. // '%foo%'
  1711. YQL_ENSURE(!components[1].Prefix.empty());
  1712. isMatch = BuildBinaryOp(Ctx, pos, "StringContains", res, BuildLiteralRawString(pos, components[1].Prefix, isUtf8));
  1713. } else if (components.size() == 2) {
  1714. // '%foo'
  1715. isMatch = BuildBinaryOp(Ctx, pos, "EndsWith", res, BuildLiteralRawString(pos, components[1].Prefix, isUtf8));
  1716. }
  1717. } else if (Ctx.AnsiLike && !components.back().Suffix.empty()) {
  1718. const TString& suffix = components.back().Suffix;
  1719. TNodePtr suffixMatch = BuildBinaryOp(Ctx, pos, "EndsWith", res, BuildLiteralRawString(pos, suffix, isUtf8));
  1720. isMatch = BuildBinaryOp(Ctx, pos, "And", suffixMatch, isMatch);
  1721. }
  1722. // TODO: more StringContains/StartsWith/EndsWith cases?
  1723. }
  1724. }
  1725. Ctx.IncrementMonCounter("sql_features", notMatch ? "NotLike" : "Like");
  1726. } else if (opName == "regexp" || opName == "rlike" || opName == "match") {
  1727. if (matchOp.HasBlock4()) {
  1728. Ctx.IncrementMonCounter("sql_errors", "RegexpEscape");
  1729. TString opNameUpper(opName);
  1730. opNameUpper.to_upper();
  1731. Error() << opName << " and ESCAPE clauses should not be used together";
  1732. return nullptr;
  1733. }
  1734. if (!Ctx.PragmaRegexUseRe2) {
  1735. Ctx.Warning(pos, TIssuesIds::CORE_LEGACY_REGEX_ENGINE) << "Legacy regex engine works incorrectly with unicode. Use PRAGMA RegexUseRe2='true';";
  1736. }
  1737. const auto& matcher = Ctx.PragmaRegexUseRe2 ?
  1738. BuildUdf(Ctx, pos, "Re2", opName == "match" ? "Match" : "Grep", {BuildTuple(pos, {pattern, BuildLiteralNull(pos)})}):
  1739. BuildUdf(Ctx, pos, "Pcre", opName == "match" ? "BacktrackingMatch" : "BacktrackingGrep", { pattern });
  1740. isMatch = new TCallNodeImpl(pos, "Apply", { matcher, res });
  1741. if (opName != "match") {
  1742. Ctx.IncrementMonCounter("sql_features", notMatch ? "NotRegexp" : "Regexp");
  1743. } else {
  1744. Ctx.IncrementMonCounter("sql_features", notMatch ? "NotMatch" : "Match");
  1745. }
  1746. } else {
  1747. Ctx.IncrementMonCounter("sql_errors", "UnknownMatchOp");
  1748. AltNotImplemented("match_op", cond);
  1749. return nullptr;
  1750. }
  1751. return (notMatch && isMatch) ? isMatch->ApplyUnaryOp(Ctx, pos, "Not") : isMatch;
  1752. }
  1753. case TRule_cond_expr::kAltCondExpr2: {
  1754. // | NOT? IN COMPACT? in_expr
  1755. auto altInExpr = cond.GetAlt_cond_expr2();
  1756. const bool notIn = altInExpr.HasBlock1();
  1757. auto hints = BuildTuple(pos, {});
  1758. bool isCompact = altInExpr.HasBlock3();
  1759. if (!isCompact) {
  1760. auto sqlHints = Ctx.PullHintForToken(Ctx.TokenPosition(altInExpr.GetToken2()));
  1761. isCompact = AnyOf(sqlHints, [](const NSQLTranslation::TSQLHint& hint) { return to_lower(hint.Name) == "compact"; });
  1762. }
  1763. if (isCompact) {
  1764. Ctx.IncrementMonCounter("sql_features", "IsCompactHint");
  1765. auto sizeHint = BuildTuple(pos, { BuildQuotedAtom(pos, "isCompact", NYql::TNodeFlags::Default) });
  1766. hints = BuildTuple(pos, { sizeHint });
  1767. }
  1768. TSqlExpression inSubexpr(Ctx, Mode);
  1769. auto inRight = inSubexpr.SqlInExpr(altInExpr.GetRule_in_expr4(), tail);
  1770. auto isIn = BuildBuiltinFunc(Ctx, pos, "In", {res, inRight, hints});
  1771. Ctx.IncrementMonCounter("sql_features", notIn ? "NotIn" : "In");
  1772. return (notIn && isIn) ? isIn->ApplyUnaryOp(Ctx, pos, "Not") : isIn;
  1773. }
  1774. case TRule_cond_expr::kAltCondExpr3: {
  1775. if (tail.Count) {
  1776. UnexpectedQuestionToken(tail);
  1777. return {};
  1778. }
  1779. auto altCase = cond.GetAlt_cond_expr3().GetBlock1().Alt_case();
  1780. const bool notNoll =
  1781. altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt2 ||
  1782. altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt4
  1783. ;
  1784. if (altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt4 &&
  1785. !cond.GetAlt_cond_expr3().GetBlock1().GetAlt4().HasBlock1())
  1786. {
  1787. Ctx.Warning(Ctx.Pos(), TIssuesIds::YQL_MISSING_IS_BEFORE_NOT_NULL) << "Missing IS keyword before NOT NULL";
  1788. }
  1789. auto isNull = BuildIsNullOp(pos, res);
  1790. Ctx.IncrementMonCounter("sql_features", notNoll ? "NotNull" : "Null");
  1791. return (notNoll && isNull) ? isNull->ApplyUnaryOp(Ctx, pos, "Not") : isNull;
  1792. }
  1793. case TRule_cond_expr::kAltCondExpr4: {
  1794. auto alt = cond.GetAlt_cond_expr4();
  1795. const bool symmetric = alt.HasBlock3() && IS_TOKEN(alt.GetBlock3().GetToken1().GetId(), SYMMETRIC);
  1796. const bool negation = alt.HasBlock1();
  1797. TNodePtr left = SubExpr(alt.GetRule_eq_subexpr4(), {});
  1798. TNodePtr right = SubExpr(alt.GetRule_eq_subexpr6(), tail);
  1799. if (!left || !right) {
  1800. return {};
  1801. }
  1802. const bool bothArgNull = left->IsNull() && right->IsNull();
  1803. const bool oneArgNull = left->IsNull() || right->IsNull();
  1804. if (res->IsNull() || bothArgNull || (symmetric && oneArgNull)) {
  1805. Ctx.Warning(pos, TIssuesIds::YQL_OPERATION_WILL_RETURN_NULL)
  1806. << "BETWEEN operation will return NULL here";
  1807. }
  1808. auto buildSubexpr = [&](const TNodePtr& left, const TNodePtr& right) {
  1809. if (negation) {
  1810. return BuildBinaryOpRaw(
  1811. pos,
  1812. "Or",
  1813. BuildBinaryOpRaw(pos, "<", res, left),
  1814. BuildBinaryOpRaw(pos, ">", res, right)
  1815. );
  1816. } else {
  1817. return BuildBinaryOpRaw(
  1818. pos,
  1819. "And",
  1820. BuildBinaryOpRaw(pos, ">=", res, left),
  1821. BuildBinaryOpRaw(pos, "<=", res, right)
  1822. );
  1823. }
  1824. };
  1825. if (symmetric) {
  1826. Ctx.IncrementMonCounter("sql_features", negation? "NotBetweenSymmetric" : "BetweenSymmetric");
  1827. return BuildBinaryOpRaw(
  1828. pos,
  1829. negation? "And" : "Or",
  1830. buildSubexpr(left, right),
  1831. buildSubexpr(right, left)
  1832. );
  1833. } else {
  1834. Ctx.IncrementMonCounter("sql_features", negation? "NotBetween" : "Between");
  1835. return buildSubexpr(left, right);
  1836. }
  1837. }
  1838. case TRule_cond_expr::kAltCondExpr5: {
  1839. auto alt = cond.GetAlt_cond_expr5();
  1840. auto getNode = [](const TRule_cond_expr::TAlt5::TBlock1& b) -> const TRule_eq_subexpr& { return b.GetRule_eq_subexpr2(); };
  1841. return BinOpList(node.GetRule_eq_subexpr1(), getNode, alt.GetBlock1().begin(), alt.GetBlock1().end(), tail);
  1842. }
  1843. case TRule_cond_expr::ALT_NOT_SET:
  1844. Ctx.IncrementMonCounter("sql_errors", "UnknownConditionExpr");
  1845. AltNotImplemented("cond_expr", cond);
  1846. return nullptr;
  1847. }
  1848. }
  1849. return res;
  1850. }
  1851. TNodePtr TSqlExpression::BinOperList(const TString& opName, TVector<TNodePtr>::const_iterator begin, TVector<TNodePtr>::const_iterator end) const {
  1852. TPosition pos(Ctx.Pos());
  1853. const size_t opCount = end - begin;
  1854. Y_DEBUG_ABORT_UNLESS(opCount >= 2);
  1855. if (opCount == 2) {
  1856. return BuildBinaryOp(Ctx, pos, opName, *begin, *(begin+1));
  1857. } if (opCount == 3) {
  1858. return BuildBinaryOp(Ctx, pos, opName, BuildBinaryOp(Ctx, pos, opName, *begin, *(begin+1)), *(begin+2));
  1859. } else {
  1860. auto mid = begin + opCount / 2;
  1861. return BuildBinaryOp(Ctx, pos, opName, BinOperList(opName, begin, mid), BinOperList(opName, mid, end));
  1862. }
  1863. }
  1864. TSqlExpression::TCaseBranch TSqlExpression::ReduceCaseBranches(TVector<TCaseBranch>::const_iterator begin, TVector<TCaseBranch>::const_iterator end) const {
  1865. YQL_ENSURE(begin < end);
  1866. const size_t branchCount = end - begin;
  1867. if (branchCount == 1) {
  1868. return *begin;
  1869. }
  1870. auto mid = begin + branchCount / 2;
  1871. auto left = ReduceCaseBranches(begin, mid);
  1872. auto right = ReduceCaseBranches(mid, end);
  1873. TVector<TNodePtr> preds;
  1874. preds.reserve(branchCount);
  1875. for (auto it = begin; it != end; ++it) {
  1876. preds.push_back(it->Pred);
  1877. }
  1878. TCaseBranch result;
  1879. result.Pred = new TCallNodeImpl(Ctx.Pos(), "Or", CloneContainer(preds));
  1880. result.Value = BuildBuiltinFunc(Ctx, Ctx.Pos(), "If", { left.Pred, left.Value, right.Value });
  1881. return result;
  1882. }
  1883. template <typename TNode, typename TGetNode, typename TIter>
  1884. TNodePtr TSqlExpression::BinOper(const TString& opName, const TNode& node, TGetNode getNode, TIter begin, TIter end, const TTrailingQuestions& tail) {
  1885. if (begin == end) {
  1886. return SubExpr(node, tail);
  1887. }
  1888. // can't have top level smart_parenthesis node if any binary operation is present
  1889. MaybeUnnamedSmartParenOnTop = false;
  1890. Ctx.IncrementMonCounter("sql_binary_operations", opName);
  1891. const size_t listSize = end - begin;
  1892. TVector<TNodePtr> nodes;
  1893. nodes.reserve(1 + listSize);
  1894. nodes.push_back(SubExpr(node, {}));
  1895. for (; begin != end; ++begin) {
  1896. nodes.push_back(SubExpr(getNode(*begin), (begin + 1 == end) ? tail : TTrailingQuestions{}));
  1897. }
  1898. return BinOperList(opName, nodes.begin(), nodes.end());
  1899. }
  1900. template <typename TNode, typename TGetNode, typename TIter>
  1901. TNodePtr TSqlExpression::BinOpList(const TNode& node, TGetNode getNode, TIter begin, TIter end, const TTrailingQuestions& tail) {
  1902. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && (begin == end);
  1903. TNodePtr partialResult = SubExpr(node, (begin == end) ? tail : TTrailingQuestions{});
  1904. while (begin != end) {
  1905. Ctx.IncrementMonCounter("sql_features", "BinaryOperation");
  1906. Token(begin->GetToken1());
  1907. TPosition pos(Ctx.Pos());
  1908. TString opName;
  1909. auto tokenId = begin->GetToken1().GetId();
  1910. if (IS_TOKEN(tokenId, LESS)) {
  1911. opName = "<";
  1912. Ctx.IncrementMonCounter("sql_binary_operations", "Less");
  1913. } else if (IS_TOKEN(tokenId, LESS_OR_EQ)) {
  1914. opName = "<=";
  1915. Ctx.IncrementMonCounter("sql_binary_operations", "LessOrEq");
  1916. } else if (IS_TOKEN(tokenId, GREATER)) {
  1917. opName = ">";
  1918. Ctx.IncrementMonCounter("sql_binary_operations", "Greater");
  1919. } else if (IS_TOKEN(tokenId, GREATER_OR_EQ)) {
  1920. opName = ">=";
  1921. Ctx.IncrementMonCounter("sql_binary_operations", "GreaterOrEq");
  1922. } else if (IS_TOKEN(tokenId, PLUS)) {
  1923. opName = Ctx.Scoped->PragmaCheckedOps ? "CheckedAdd" : "+MayWarn";
  1924. Ctx.IncrementMonCounter("sql_binary_operations", "Plus");
  1925. } else if (IS_TOKEN(tokenId, MINUS)) {
  1926. opName = Ctx.Scoped->PragmaCheckedOps ? "CheckedSub" : "-MayWarn";
  1927. Ctx.IncrementMonCounter("sql_binary_operations", "Minus");
  1928. } else if (IS_TOKEN(tokenId, ASTERISK)) {
  1929. opName = Ctx.Scoped->PragmaCheckedOps ? "CheckedMul" : "*MayWarn";
  1930. Ctx.IncrementMonCounter("sql_binary_operations", "Multiply");
  1931. } else if (IS_TOKEN(tokenId, SLASH)) {
  1932. opName = "/MayWarn";
  1933. Ctx.IncrementMonCounter("sql_binary_operations", "Divide");
  1934. if (!Ctx.Scoped->PragmaClassicDivision && partialResult) {
  1935. partialResult = new TCallNodeImpl(pos, "SafeCast", {std::move(partialResult), BuildDataType(pos, "Double")});
  1936. } else if (Ctx.Scoped->PragmaCheckedOps) {
  1937. opName = "CheckedDiv";
  1938. }
  1939. } else if (IS_TOKEN(tokenId, PERCENT)) {
  1940. opName = Ctx.Scoped->PragmaCheckedOps ? "CheckedMod" : "%MayWarn";
  1941. Ctx.IncrementMonCounter("sql_binary_operations", "Mod");
  1942. } else {
  1943. Ctx.IncrementMonCounter("sql_errors", "UnsupportedBinaryOperation");
  1944. Error() << "Unsupported binary operation token: " << tokenId;
  1945. return nullptr;
  1946. }
  1947. partialResult = BuildBinaryOp(Ctx, pos, opName, partialResult, SubExpr(getNode(*begin), (begin + 1 == end) ? tail : TTrailingQuestions{}));
  1948. ++begin;
  1949. }
  1950. return partialResult;
  1951. }
  1952. template <typename TGetNode, typename TIter>
  1953. TNodePtr TSqlExpression::BinOpList(const TRule_bit_subexpr& node, TGetNode getNode, TIter begin, TIter end, const TTrailingQuestions& tail) {
  1954. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && (begin == end);
  1955. TNodePtr partialResult = SubExpr(node, (begin == end) ? tail : TTrailingQuestions{});
  1956. while (begin != end) {
  1957. Ctx.IncrementMonCounter("sql_features", "BinaryOperation");
  1958. TString opName;
  1959. switch (begin->GetBlock1().Alt_case()) {
  1960. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt1: {
  1961. Token(begin->GetBlock1().GetAlt1().GetToken1());
  1962. auto tokenId = begin->GetBlock1().GetAlt1().GetToken1().GetId();
  1963. if (!IS_TOKEN(tokenId, SHIFT_LEFT)) {
  1964. Error() << "Unsupported binary operation token: " << tokenId;
  1965. return {};
  1966. }
  1967. opName = "ShiftLeft";
  1968. Ctx.IncrementMonCounter("sql_binary_operations", "ShiftLeft");
  1969. break;
  1970. }
  1971. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt2: {
  1972. opName = "ShiftRight";
  1973. Ctx.IncrementMonCounter("sql_binary_operations", "ShiftRight");
  1974. break;
  1975. }
  1976. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt3: {
  1977. Token(begin->GetBlock1().GetAlt3().GetToken1());
  1978. auto tokenId = begin->GetBlock1().GetAlt3().GetToken1().GetId();
  1979. if (!IS_TOKEN(tokenId, ROT_LEFT)) {
  1980. Error() << "Unsupported binary operation token: " << tokenId;
  1981. return {};
  1982. }
  1983. opName = "RotLeft";
  1984. Ctx.IncrementMonCounter("sql_binary_operations", "RotLeft");
  1985. break;
  1986. }
  1987. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt4: {
  1988. opName = "RotRight";
  1989. Ctx.IncrementMonCounter("sql_binary_operations", "RotRight");
  1990. break;
  1991. }
  1992. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt5: {
  1993. Token(begin->GetBlock1().GetAlt5().GetToken1());
  1994. auto tokenId = begin->GetBlock1().GetAlt5().GetToken1().GetId();
  1995. if (!IS_TOKEN(tokenId, AMPERSAND)) {
  1996. Error() << "Unsupported binary operation token: " << tokenId;
  1997. return {};
  1998. }
  1999. opName = "BitAnd";
  2000. Ctx.IncrementMonCounter("sql_binary_operations", "BitAnd");
  2001. break;
  2002. }
  2003. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt6: {
  2004. Token(begin->GetBlock1().GetAlt6().GetToken1());
  2005. auto tokenId = begin->GetBlock1().GetAlt6().GetToken1().GetId();
  2006. if (!IS_TOKEN(tokenId, PIPE)) {
  2007. Error() << "Unsupported binary operation token: " << tokenId;
  2008. return {};
  2009. }
  2010. opName = "BitOr";
  2011. Ctx.IncrementMonCounter("sql_binary_operations", "BitOr");
  2012. break;
  2013. }
  2014. case TRule_neq_subexpr_TBlock2_TBlock1::kAlt7: {
  2015. Token(begin->GetBlock1().GetAlt7().GetToken1());
  2016. auto tokenId = begin->GetBlock1().GetAlt7().GetToken1().GetId();
  2017. if (!IS_TOKEN(tokenId, CARET)) {
  2018. Error() << "Unsupported binary operation token: " << tokenId;
  2019. return {};
  2020. }
  2021. opName = "BitXor";
  2022. Ctx.IncrementMonCounter("sql_binary_operations", "BitXor");
  2023. break;
  2024. }
  2025. case TRule_neq_subexpr_TBlock2_TBlock1::ALT_NOT_SET:
  2026. Y_ABORT("You should change implementation according to grammar changes");
  2027. }
  2028. partialResult = BuildBinaryOp(Ctx, Ctx.Pos(), opName, partialResult, SubExpr(getNode(*begin), (begin + 1 == end) ? tail : TTrailingQuestions{}));
  2029. ++begin;
  2030. }
  2031. return partialResult;
  2032. }
  2033. template <typename TGetNode, typename TIter>
  2034. TNodePtr TSqlExpression::BinOpList(const TRule_eq_subexpr& node, TGetNode getNode, TIter begin, TIter end, const TTrailingQuestions& tail) {
  2035. MaybeUnnamedSmartParenOnTop = MaybeUnnamedSmartParenOnTop && (begin == end);
  2036. TNodePtr partialResult = SubExpr(node, (begin == end) ? tail : TTrailingQuestions{});
  2037. while (begin != end) {
  2038. Ctx.IncrementMonCounter("sql_features", "BinaryOperation");
  2039. TString opName;
  2040. switch (begin->GetBlock1().Alt_case()) {
  2041. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::kAlt1: {
  2042. Token(begin->GetBlock1().GetAlt1().GetToken1());
  2043. auto tokenId = begin->GetBlock1().GetAlt1().GetToken1().GetId();
  2044. if (!IS_TOKEN(tokenId, EQUALS)) {
  2045. Error() << "Unsupported binary operation token: " << tokenId;
  2046. return {};
  2047. }
  2048. Ctx.IncrementMonCounter("sql_binary_operations", "Equals");
  2049. opName = "==";
  2050. break;
  2051. }
  2052. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::kAlt2: {
  2053. Token(begin->GetBlock1().GetAlt2().GetToken1());
  2054. auto tokenId = begin->GetBlock1().GetAlt2().GetToken1().GetId();
  2055. if (!IS_TOKEN(tokenId, EQUALS2)) {
  2056. Error() << "Unsupported binary operation token: " << tokenId;
  2057. return {};
  2058. }
  2059. Ctx.IncrementMonCounter("sql_binary_operations", "Equals2");
  2060. opName = "==";
  2061. break;
  2062. }
  2063. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::kAlt3: {
  2064. Token(begin->GetBlock1().GetAlt3().GetToken1());
  2065. auto tokenId = begin->GetBlock1().GetAlt3().GetToken1().GetId();
  2066. if (!IS_TOKEN(tokenId, NOT_EQUALS)) {
  2067. Error() << "Unsupported binary operation token: " << tokenId;
  2068. return {};
  2069. }
  2070. Ctx.IncrementMonCounter("sql_binary_operations", "NotEquals");
  2071. opName = "!=";
  2072. break;
  2073. }
  2074. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::kAlt4: {
  2075. Token(begin->GetBlock1().GetAlt4().GetToken1());
  2076. auto tokenId = begin->GetBlock1().GetAlt4().GetToken1().GetId();
  2077. if (!IS_TOKEN(tokenId, NOT_EQUALS2)) {
  2078. Error() << "Unsupported binary operation token: " << tokenId;
  2079. return {};
  2080. }
  2081. Ctx.IncrementMonCounter("sql_binary_operations", "NotEquals2");
  2082. opName = "!=";
  2083. break;
  2084. }
  2085. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::kAlt5: {
  2086. Token(begin->GetBlock1().GetAlt5().GetRule_distinct_from_op1().GetToken1());
  2087. opName = begin->GetBlock1().GetAlt5().GetRule_distinct_from_op1().HasBlock2() ? "IsNotDistinctFrom" : "IsDistinctFrom";
  2088. Ctx.IncrementMonCounter("sql_binary_operations", opName);
  2089. break;
  2090. }
  2091. case TRule_cond_expr::TAlt5::TBlock1::TBlock1::ALT_NOT_SET:
  2092. Y_ABORT("You should change implementation according to grammar changes");
  2093. }
  2094. partialResult = BuildBinaryOp(Ctx, Ctx.Pos(), opName, partialResult, SubExpr(getNode(*begin), (begin + 1 == end) ? tail : TTrailingQuestions{}));
  2095. ++begin;
  2096. }
  2097. return partialResult;
  2098. }
  2099. TNodePtr TSqlExpression::SqlInExpr(const TRule_in_expr& node, const TTrailingQuestions& tail) {
  2100. TSqlExpression expr(Ctx, Mode);
  2101. expr.SetSmartParenthesisMode(TSqlExpression::ESmartParenthesis::InStatement);
  2102. auto result = expr.UnaryExpr(node.GetRule_in_unary_subexpr1(), tail);
  2103. return result;
  2104. }
  2105. TNodePtr TSqlExpression::SmartParenthesis(const TRule_smart_parenthesis& node) {
  2106. TVector<TNodePtr> exprs;
  2107. Token(node.GetToken1());
  2108. const TPosition pos(Ctx.Pos());
  2109. const bool isTuple = node.HasBlock3();
  2110. bool expectTuple = SmartParenthesisMode == ESmartParenthesis::InStatement;
  2111. EExpr mode = EExpr::Regular;
  2112. if (SmartParenthesisMode == ESmartParenthesis::SqlLambdaParams) {
  2113. mode = EExpr::SqlLambdaParams;
  2114. expectTuple = true;
  2115. }
  2116. if (node.HasBlock2() && !NamedExprList(node.GetBlock2().GetRule_named_expr_list1(), exprs, mode)) {
  2117. return {};
  2118. }
  2119. bool topLevelGroupBy = MaybeUnnamedSmartParenOnTop && SmartParenthesisMode == ESmartParenthesis::GroupBy;
  2120. bool hasAliases = false;
  2121. bool hasUnnamed = false;
  2122. for (const auto& expr: exprs) {
  2123. if (expr->GetLabel()) {
  2124. hasAliases = true;
  2125. } else {
  2126. hasUnnamed = true;
  2127. }
  2128. if (hasAliases && hasUnnamed && !topLevelGroupBy) {
  2129. Ctx.IncrementMonCounter("sql_errors", "AnonymousStructMembers");
  2130. Ctx.Error(pos) << "Structure does not allow anonymous members";
  2131. return nullptr;
  2132. }
  2133. }
  2134. if (exprs.size() == 1 && hasUnnamed && !isTuple && !expectTuple) {
  2135. return exprs.back();
  2136. }
  2137. if (topLevelGroupBy) {
  2138. if (isTuple) {
  2139. Ctx.IncrementMonCounter("sql_errors", "SimpleTupleInGroupBy");
  2140. Token(node.GetBlock3().GetToken1());
  2141. Ctx.Error() << "Unexpected trailing comma in grouping elements list";
  2142. return nullptr;
  2143. }
  2144. Ctx.IncrementMonCounter("sql_features", "ListOfNamedNode");
  2145. return BuildListOfNamedNodes(pos, std::move(exprs));
  2146. }
  2147. Ctx.IncrementMonCounter("sql_features", hasUnnamed ? "SimpleTuple" : "SimpleStruct");
  2148. return (hasUnnamed || expectTuple || exprs.size() == 0) ? BuildTuple(pos, exprs) : BuildStructure(pos, exprs);
  2149. }
  2150. } // namespace NSQLTranslationV1