sql_values.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "sql_values.h"
  2. #include "sql_group_by.h"
  3. #include "sql_query.h"
  4. #include "sql_select.h"
  5. #include "sql_expression.h"
  6. #include "source.h"
  7. namespace NSQLTranslationV1 {
  8. using namespace NSQLv1Generated;
  9. TSourcePtr TSqlValues::Build(const TRule_values_stmt& node, TPosition& valuesPos, const TVector<TString>& derivedColumns, TPosition derivedColumnsPos) {
  10. Token(node.GetToken1());
  11. valuesPos = Ctx.Pos();
  12. TVector<TVector<TNodePtr>> rows;
  13. const auto& rowList = node.GetRule_values_source_row_list2();
  14. if (!BuildRows(rowList, rows)) {
  15. return nullptr;
  16. }
  17. YQL_ENSURE(!rows.empty());
  18. const size_t columnsCount = rows.back().size();
  19. if (derivedColumns.size() > columnsCount) {
  20. Ctx.Error(derivedColumnsPos) << "Derived column list size exceeds column count in VALUES";
  21. return nullptr;
  22. }
  23. auto columns = derivedColumns;
  24. if (Ctx.WarnUnnamedColumns && columns.size() < columnsCount) {
  25. Ctx.Warning(valuesPos, TIssuesIds::YQL_UNNAMED_COLUMN)
  26. << "Autogenerated column names column" << columns.size() << "...column" << columnsCount - 1 << " will be used here";
  27. }
  28. while (columns.size() < columnsCount) {
  29. columns.push_back(TStringBuilder() << "column" << columns.size());
  30. }
  31. TVector<TNodePtr> labels;
  32. for (size_t i = 0; i < columnsCount; ++i) {
  33. labels.push_back(BuildQuotedAtom(derivedColumnsPos, columns[i]));
  34. }
  35. TVector<TNodePtr> items;
  36. for (auto& row : rows) {
  37. YQL_ENSURE(!row.empty());
  38. YQL_ENSURE(row.size() == columnsCount);
  39. items.push_back(BuildOrderedStructure(row.front()->GetPos(), row, labels));
  40. }
  41. auto list = new TCallNodeImpl(valuesPos, "AsListMayWarn", items);
  42. list = new TCallNodeImpl(valuesPos, "PersistableRepr", { list });
  43. list = new TCallNodeImpl(valuesPos, "AssumeColumnOrder", { list, BuildTuple(valuesPos, labels) });
  44. auto result = BuildNodeSource(valuesPos, list, false);
  45. result->AllColumns();
  46. return result;
  47. }
  48. bool TSqlValues::BuildRows(const TRule_values_source_row_list& node, TVector<TVector<TNodePtr>>& rows) {
  49. rows = TVector<TVector<TNodePtr>> {{}};
  50. if (!BuildRow(node.GetRule_values_source_row1(), rows.back())) {
  51. return false;
  52. }
  53. const size_t rowSize = rows.back().size();
  54. for (const auto& valuesSourceRow: node.GetBlock2()) {
  55. rows.push_back({});
  56. if (!BuildRow(valuesSourceRow.GetRule_values_source_row2(), rows.back())) {
  57. return false;
  58. }
  59. if (rows.back().size() != rowSize) {
  60. Token(valuesSourceRow.GetRule_values_source_row2().GetToken1());
  61. Error() << "All VALUES items should have same size: expecting " << rowSize << ", got " << rows.back().size();
  62. return false;
  63. }
  64. }
  65. return true;
  66. }
  67. bool TSqlValues::BuildRow(const TRule_values_source_row& inRow, TVector<TNodePtr>& outRow) {
  68. TSqlExpression sqlExpr(Ctx, Mode);
  69. return ExprList(sqlExpr, outRow, inRow.GetRule_expr_list2());
  70. }
  71. TSourcePtr TSqlValues::ValuesSource(const TRule_values_source& node, const TVector<TString>& columnsHint,
  72. const TString& operationName)
  73. {
  74. Ctx.IncrementMonCounter("sql_features", "ValuesSource");
  75. TPosition pos(Ctx.Pos());
  76. switch (node.Alt_case()) {
  77. case TRule_values_source::kAltValuesSource1: {
  78. TVector<TVector<TNodePtr>> rows {{}};
  79. const auto& rowList = node.GetAlt_values_source1().GetRule_values_stmt1().GetRule_values_source_row_list2();
  80. if (!BuildRows(rowList, rows)) {
  81. return nullptr;
  82. }
  83. return BuildWriteValues(pos, operationName, columnsHint, rows);
  84. }
  85. case TRule_values_source::kAltValuesSource2: {
  86. TSqlSelect select(Ctx, Mode);
  87. TPosition selectPos;
  88. auto source = select.Build(node.GetAlt_values_source2().GetRule_select_stmt1(), selectPos);
  89. if (!source) {
  90. return nullptr;
  91. }
  92. return BuildWriteValues(pos, "UPDATE", columnsHint, std::move(source));
  93. }
  94. default:
  95. Ctx.IncrementMonCounter("sql_errors", "UnknownValuesSource");
  96. AltNotImplemented("values_source", node);
  97. return nullptr;
  98. }
  99. }
  100. TSourcePtr TSqlIntoValues::Build(const TRule_into_values_source& node, const TString& operationName) {
  101. switch (node.Alt_case()) {
  102. case TRule_into_values_source::kAltIntoValuesSource1: {
  103. auto alt = node.GetAlt_into_values_source1();
  104. TVector<TString> columnsHint;
  105. if (alt.HasBlock1()) {
  106. PureColumnListStr(alt.GetBlock1().GetRule_pure_column_list1(), *this, columnsHint);
  107. }
  108. return ValuesSource(alt.GetRule_values_source2(), columnsHint, operationName);
  109. }
  110. default:
  111. Ctx.IncrementMonCounter("sql_errors", "DefaultValuesOrOther");
  112. AltNotImplemented("into_values_source", node);
  113. return nullptr;
  114. }
  115. }
  116. TSourcePtr TSqlAsValues::Build(const TRule_values_source& node, const TString& operationName) {
  117. switch (node.Alt_case()) {
  118. case TRule_values_source::kAltValuesSource1: {
  119. Ctx.IncrementMonCounter("sql_errors", "UnknownValuesSource");
  120. Error() << "AS VALUES statement is not supported for " << operationName << ".";
  121. return nullptr;
  122. }
  123. case TRule_values_source::kAltValuesSource2: {
  124. return ValuesSource(node, {}, operationName);
  125. }
  126. default:
  127. Ctx.IncrementMonCounter("sql_errors", "UnknownValuesSource");
  128. AltNotImplemented("values_source", node);
  129. return nullptr;
  130. }
  131. }
  132. } // namespace NSQLTranslationV1