sql_expression.cpp 98 KB

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