sql.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #include "sql.h"
  2. #include "sql_query.h"
  3. #include <yql/essentials/parser/proto_ast/collect_issues/collect_issues.h>
  4. #include <yql/essentials/sql/v1/lexer/lexer.h>
  5. #include <yql/essentials/sql/v1/proto_parser/proto_parser.h>
  6. namespace NSQLTranslationV1 {
  7. using namespace NSQLv1Generated;
  8. TAstNode* SqlASTToYql(const google::protobuf::Message& protoAst, TContext& ctx) {
  9. const google::protobuf::Descriptor* d = protoAst.GetDescriptor();
  10. if (d && d->name() != "TSQLv1ParserAST") {
  11. ctx.Error() << "Invalid AST structure: " << d->name() << ", expected TSQLv1ParserAST";
  12. return nullptr;
  13. }
  14. TSqlQuery query(ctx, ctx.Settings.Mode, true);
  15. TNodePtr node(query.Build(static_cast<const TSQLv1ParserAST&>(protoAst)));
  16. try {
  17. if (node && node->Init(ctx, nullptr)) {
  18. return node->Translate(ctx);
  19. }
  20. } catch (const NProtoAST::TTooManyErrors&) {
  21. // do not add error issue, no room for it
  22. }
  23. return nullptr;
  24. }
  25. TAstNode* SqlASTsToYqls(const std::vector<::NSQLv1Generated::TRule_sql_stmt_core>& ast, TContext& ctx) {
  26. TSqlQuery query(ctx, ctx.Settings.Mode, true);
  27. TNodePtr node(query.Build(ast));
  28. try {
  29. if (node && node->Init(ctx, nullptr)) {
  30. return node->Translate(ctx);
  31. }
  32. } catch (const NProtoAST::TTooManyErrors&) {
  33. // do not add error issue, no room for it
  34. }
  35. return nullptr;
  36. }
  37. void SqlASTToYqlImpl(NYql::TAstParseResult& res, const google::protobuf::Message& protoAst,
  38. TContext& ctx) {
  39. YQL_ENSURE(!ctx.Issues.Size());
  40. res.Root = SqlASTToYql(protoAst, ctx);
  41. res.Pool = std::move(ctx.Pool);
  42. if (!res.Root) {
  43. if (ctx.Issues.Size()) {
  44. ctx.IncrementMonCounter("sql_errors", "AstToYqlError");
  45. } else {
  46. ctx.IncrementMonCounter("sql_errors", "AstToYqlSilentError");
  47. ctx.Error() << "Error occurred on parse SQL query, but no error is collected" <<
  48. ", please send this request over bug report into YQL interface or write on yql@ maillist";
  49. }
  50. } else {
  51. ctx.WarnUnusedHints();
  52. }
  53. }
  54. void SqlASTsToYqlsImpl(NYql::TAstParseResult& res, const std::vector<::NSQLv1Generated::TRule_sql_stmt_core>& ast, TContext& ctx) {
  55. res.Root = SqlASTsToYqls(ast, ctx);
  56. res.Pool = std::move(ctx.Pool);
  57. if (!res.Root) {
  58. if (ctx.Issues.Size()) {
  59. ctx.IncrementMonCounter("sql_errors", "AstToYqlError");
  60. } else {
  61. ctx.IncrementMonCounter("sql_errors", "AstToYqlSilentError");
  62. ctx.Error() << "Error occurred on parse SQL query, but no error is collected" <<
  63. ", please send this request over bug report into YQL interface or write on yql@ maillist";
  64. }
  65. } else {
  66. ctx.WarnUnusedHints();
  67. }
  68. }
  69. NYql::TAstParseResult SqlASTToYql(const TLexers& lexers, const TParsers& parsers,
  70. const TString& query,
  71. const google::protobuf::Message& protoAst,
  72. const NSQLTranslation::TSQLHints& hints,
  73. const NSQLTranslation::TTranslationSettings& settings)
  74. {
  75. YQL_ENSURE(IsQueryMode(settings.Mode));
  76. TAstParseResult res;
  77. TContext ctx(lexers, parsers, settings, hints, res.Issues, query);
  78. SqlASTToYqlImpl(res, protoAst, ctx);
  79. res.ActualSyntaxType = NYql::ESyntaxType::YQLv1;
  80. return res;
  81. }
  82. NYql::TAstParseResult SqlASTToYql(const TString& query,
  83. const google::protobuf::Message& protoAst,
  84. const NSQLTranslation::TSQLHints& hints,
  85. const NSQLTranslation::TTranslationSettings& settings)
  86. {
  87. return SqlASTToYql(MakeAllLexers(), MakeAllParsers(), query, protoAst, hints, settings);
  88. }
  89. NYql::TAstParseResult SqlToYql(const TLexers& lexers, const TParsers& parsers, const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules)
  90. {
  91. TAstParseResult res;
  92. const TString queryName = settings.File;
  93. NSQLTranslation::TSQLHints hints;
  94. auto lexer = MakeLexer(lexers, settings.AnsiLexer, settings.Antlr4Parser);
  95. YQL_ENSURE(lexer);
  96. if (!CollectSqlHints(*lexer, query, queryName, settings.File, hints, res.Issues, settings.MaxErrors, settings.Antlr4Parser)) {
  97. return res;
  98. }
  99. TContext ctx(lexers, parsers, settings, hints, res.Issues, query);
  100. NSQLTranslation::TErrorCollectorOverIssues collector(res.Issues, settings.MaxErrors, settings.File);
  101. google::protobuf::Message* ast(SqlAST(parsers, query, queryName, collector, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena));
  102. if (ast) {
  103. SqlASTToYqlImpl(res, *ast, ctx);
  104. } else {
  105. ctx.IncrementMonCounter("sql_errors", "AstError");
  106. }
  107. if (warningRules) {
  108. *warningRules = ctx.WarningPolicy.GetRules();
  109. ctx.WarningPolicy.Clear();
  110. }
  111. res.ActualSyntaxType = NYql::ESyntaxType::YQLv1;
  112. return res;
  113. }
  114. NYql::TAstParseResult SqlToYql(const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules) {
  115. return SqlToYql(MakeAllLexers(), MakeAllParsers(), query, settings, warningRules);
  116. }
  117. bool NeedUseForAllStatements(const TRule_sql_stmt_core::AltCase& subquery) {
  118. switch (subquery) {
  119. case TRule_sql_stmt_core::kAltSqlStmtCore1: // pragma
  120. case TRule_sql_stmt_core::kAltSqlStmtCore3: // named nodes
  121. case TRule_sql_stmt_core::kAltSqlStmtCore6: // use
  122. case TRule_sql_stmt_core::kAltSqlStmtCore12: // declare
  123. case TRule_sql_stmt_core::kAltSqlStmtCore13: // import
  124. case TRule_sql_stmt_core::kAltSqlStmtCore14: // export
  125. case TRule_sql_stmt_core::kAltSqlStmtCore18: // define action or subquery
  126. return true;
  127. case TRule_sql_stmt_core::ALT_NOT_SET:
  128. case TRule_sql_stmt_core::kAltSqlStmtCore2: // select
  129. case TRule_sql_stmt_core::kAltSqlStmtCore4: // create table
  130. case TRule_sql_stmt_core::kAltSqlStmtCore5: // drop table
  131. case TRule_sql_stmt_core::kAltSqlStmtCore7: // into table
  132. case TRule_sql_stmt_core::kAltSqlStmtCore8: // commit
  133. case TRule_sql_stmt_core::kAltSqlStmtCore9: // update
  134. case TRule_sql_stmt_core::kAltSqlStmtCore10: // delete
  135. case TRule_sql_stmt_core::kAltSqlStmtCore11: // rollback
  136. case TRule_sql_stmt_core::kAltSqlStmtCore15: // alter table
  137. case TRule_sql_stmt_core::kAltSqlStmtCore16: // alter external table
  138. case TRule_sql_stmt_core::kAltSqlStmtCore17: // do
  139. case TRule_sql_stmt_core::kAltSqlStmtCore19: // if
  140. case TRule_sql_stmt_core::kAltSqlStmtCore20: // for
  141. case TRule_sql_stmt_core::kAltSqlStmtCore21: // values
  142. case TRule_sql_stmt_core::kAltSqlStmtCore22: // create user
  143. case TRule_sql_stmt_core::kAltSqlStmtCore23: // alter user
  144. case TRule_sql_stmt_core::kAltSqlStmtCore24: // create group
  145. case TRule_sql_stmt_core::kAltSqlStmtCore25: // alter group
  146. case TRule_sql_stmt_core::kAltSqlStmtCore26: // drop role
  147. case TRule_sql_stmt_core::kAltSqlStmtCore27: // create object
  148. case TRule_sql_stmt_core::kAltSqlStmtCore28: // alter object
  149. case TRule_sql_stmt_core::kAltSqlStmtCore29: // drop object
  150. case TRule_sql_stmt_core::kAltSqlStmtCore30: // create external data source
  151. case TRule_sql_stmt_core::kAltSqlStmtCore31: // alter external data source
  152. case TRule_sql_stmt_core::kAltSqlStmtCore32: // drop external data source
  153. case TRule_sql_stmt_core::kAltSqlStmtCore33: // create replication
  154. case TRule_sql_stmt_core::kAltSqlStmtCore34: // drop replication
  155. case TRule_sql_stmt_core::kAltSqlStmtCore35: // create topic
  156. case TRule_sql_stmt_core::kAltSqlStmtCore36: // alter topic
  157. case TRule_sql_stmt_core::kAltSqlStmtCore37: // drop topic
  158. case TRule_sql_stmt_core::kAltSqlStmtCore38: // grant permissions
  159. case TRule_sql_stmt_core::kAltSqlStmtCore39: // revoke permissions
  160. case TRule_sql_stmt_core::kAltSqlStmtCore40: // alter table store
  161. case TRule_sql_stmt_core::kAltSqlStmtCore41: // upsert object
  162. case TRule_sql_stmt_core::kAltSqlStmtCore42: // create view
  163. case TRule_sql_stmt_core::kAltSqlStmtCore43: // drop view
  164. case TRule_sql_stmt_core::kAltSqlStmtCore44: // alter replication
  165. case TRule_sql_stmt_core::kAltSqlStmtCore45: // create resource pool
  166. case TRule_sql_stmt_core::kAltSqlStmtCore46: // alter resource pool
  167. case TRule_sql_stmt_core::kAltSqlStmtCore47: // drop resource pool
  168. case TRule_sql_stmt_core::kAltSqlStmtCore48: // create backup collection
  169. case TRule_sql_stmt_core::kAltSqlStmtCore49: // alter backup collection
  170. case TRule_sql_stmt_core::kAltSqlStmtCore50: // drop backup collection
  171. case TRule_sql_stmt_core::kAltSqlStmtCore51: // analyze
  172. case TRule_sql_stmt_core::kAltSqlStmtCore52: // create resource pool classifier
  173. case TRule_sql_stmt_core::kAltSqlStmtCore53: // alter resource pool classifier
  174. case TRule_sql_stmt_core::kAltSqlStmtCore54: // drop resource pool classifier
  175. case TRule_sql_stmt_core::kAltSqlStmtCore55: // backup
  176. case TRule_sql_stmt_core::kAltSqlStmtCore56: // restore
  177. case TRule_sql_stmt_core::kAltSqlStmtCore57: // alter sequence
  178. case TRule_sql_stmt_core::kAltSqlStmtCore58: // create transfer
  179. case TRule_sql_stmt_core::kAltSqlStmtCore59: // alter transfer
  180. case TRule_sql_stmt_core::kAltSqlStmtCore60: // drop transfer
  181. case TRule_sql_stmt_core::kAltSqlStmtCore61: // alter database
  182. case TRule_sql_stmt_core::kAltSqlStmtCore62: // show create table
  183. return false;
  184. }
  185. }
  186. TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const TParsers& parsers, const TString& queryText, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules,
  187. TVector<NYql::TStmtParseInfo>* stmtParseInfo)
  188. {
  189. TVector<TAstParseResult> result;
  190. const TString queryName = settings.File;
  191. TIssues issues;
  192. NSQLTranslation::TSQLHints hints;
  193. auto lexer = MakeLexer(lexers, settings.AnsiLexer, settings.Antlr4Parser);
  194. YQL_ENSURE(lexer);
  195. if (!CollectSqlHints(*lexer, queryText, queryName, settings.File, hints, issues, settings.MaxErrors, settings.Antlr4Parser)) {
  196. return result;
  197. }
  198. TContext ctx(lexers, parsers, settings, hints, issues, queryText);
  199. NSQLTranslation::TErrorCollectorOverIssues collector(issues, settings.MaxErrors, settings.File);
  200. google::protobuf::Message* astProto(SqlAST(parsers, queryText, queryName, collector, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena));
  201. if (astProto) {
  202. auto ast = static_cast<const TSQLv1ParserAST&>(*astProto);
  203. const auto& query = ast.GetRule_sql_query();
  204. if (query.Alt_case() == NSQLv1Generated::TRule_sql_query::kAltSqlQuery1) {
  205. std::vector<::NSQLv1Generated::TRule_sql_stmt_core> commonStates;
  206. std::vector<::NSQLv1Generated::TRule_sql_stmt_core> statementResult;
  207. const auto& statements = query.GetAlt_sql_query1().GetRule_sql_stmt_list1();
  208. if (NeedUseForAllStatements(statements.GetRule_sql_stmt2().GetRule_sql_stmt_core2().Alt_case())) {
  209. commonStates.push_back(statements.GetRule_sql_stmt2().GetRule_sql_stmt_core2());
  210. } else {
  211. TContext ctx(lexers, parsers, settings, hints, issues, queryText);
  212. result.emplace_back();
  213. if (stmtParseInfo) {
  214. stmtParseInfo->push_back({});
  215. }
  216. SqlASTsToYqlsImpl(result.back(), {statements.GetRule_sql_stmt2().GetRule_sql_stmt_core2()}, ctx);
  217. result.back().Issues = std::move(issues);
  218. issues.Clear();
  219. }
  220. for (auto block: statements.GetBlock3()) {
  221. if (NeedUseForAllStatements(block.GetRule_sql_stmt2().GetRule_sql_stmt_core2().Alt_case())) {
  222. commonStates.push_back(block.GetRule_sql_stmt2().GetRule_sql_stmt_core2());
  223. continue;
  224. }
  225. TContext ctx(lexers, parsers, settings, hints, issues, queryText);
  226. result.emplace_back();
  227. if (stmtParseInfo) {
  228. stmtParseInfo->push_back({});
  229. }
  230. statementResult = commonStates;
  231. statementResult.push_back(block.GetRule_sql_stmt2().GetRule_sql_stmt_core2());
  232. SqlASTsToYqlsImpl(result.back(), statementResult, ctx);
  233. result.back().Issues = std::move(issues);
  234. issues.Clear();
  235. }
  236. }
  237. } else {
  238. ctx.IncrementMonCounter("sql_errors", "AstError");
  239. }
  240. if (warningRules) {
  241. *warningRules = ctx.WarningPolicy.GetRules();
  242. ctx.WarningPolicy.Clear();
  243. }
  244. return result;
  245. }
  246. TVector<NYql::TAstParseResult> SqlToAstStatements(const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo) {
  247. return SqlToAstStatements(MakeAllLexers(), MakeAllParsers(), query, settings, warningRules, stmtParseInfo);
  248. }
  249. bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, TVector<TString>& statements, NYql::TIssues& issues,
  250. const NSQLTranslation::TTranslationSettings& settings) {
  251. auto lexer = NSQLTranslationV1::MakeLexer(lexers, settings.AnsiLexer, settings.Antlr4Parser);
  252. TVector<TString> parts;
  253. if (!SplitQueryToStatements(query, lexer, parts, issues)) {
  254. return false;
  255. }
  256. for (auto& currentQuery : parts) {
  257. NYql::TIssues parserIssues;
  258. auto message = NSQLTranslationV1::SqlAST(parsers, currentQuery, settings.File, parserIssues, NSQLTranslation::SQL_MAX_PARSER_ERRORS,
  259. settings.AnsiLexer, settings.Antlr4Parser, settings.Arena);
  260. if (!message) {
  261. // Skip empty statements
  262. continue;
  263. }
  264. statements.push_back(std::move(currentQuery));
  265. }
  266. return true;
  267. }
  268. bool SplitQueryToStatements(const TString& query, TVector<TString>& statements, NYql::TIssues& issues,
  269. const NSQLTranslation::TTranslationSettings& settings) {
  270. return SplitQueryToStatements(MakeAllLexers(), MakeAllParsers(), query, statements, issues, settings);
  271. }
  272. class TTranslator : public NSQLTranslation::ITranslator {
  273. public:
  274. TTranslator(const TLexers& lexers, const TParsers& parsers)
  275. : Lexers_(lexers)
  276. , Parsers_(parsers)
  277. {
  278. }
  279. NSQLTranslation::ILexer::TPtr MakeLexer(const NSQLTranslation::TTranslationSettings& settings) final {
  280. return NSQLTranslationV1::MakeLexer(Lexers_, settings.AnsiLexer, settings.Antlr4Parser);
  281. }
  282. NYql::TAstParseResult TextToAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings,
  283. NYql::TWarningRules* warningRules, NYql::TStmtParseInfo* stmtParseInfo) final {
  284. Y_UNUSED(stmtParseInfo);
  285. return SqlToYql(Lexers_, Parsers_, query, settings, warningRules);
  286. }
  287. google::protobuf::Message* TextToMessage(const TString& query, const TString& queryName,
  288. NYql::TIssues& issues, size_t maxErrors, const NSQLTranslation::TTranslationSettings& settings) final {
  289. return SqlAST(Parsers_, query, queryName, issues, maxErrors, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena);
  290. }
  291. NYql::TAstParseResult TextAndMessageToAst(const TString& query, const google::protobuf::Message& protoAst,
  292. const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings) final {
  293. return SqlASTToYql(Lexers_, Parsers_, query, protoAst, hints, settings);
  294. }
  295. TVector<NYql::TAstParseResult> TextToManyAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings,
  296. NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo) final {
  297. return SqlToAstStatements(Lexers_, Parsers_, query, settings, warningRules, stmtParseInfo);
  298. }
  299. private:
  300. const TLexers Lexers_;
  301. const TParsers Parsers_;
  302. };
  303. NSQLTranslation::TTranslatorPtr MakeTranslator() {
  304. return MakeIntrusive<TTranslator>(MakeAllLexers(), MakeAllParsers());
  305. }
  306. NSQLTranslation::TTranslatorPtr MakeTranslator(const TLexers& lexers, const TParsers& parsers) {
  307. return MakeIntrusive<TTranslator>(lexers, parsers);
  308. }
  309. } // namespace NSQLTranslationV1