60918 {
60919
60921 result += "(";
60922 if (entry.children.size()) {
60923
60924 int distincts = entry.distinct ? 0 : 1;
60925 result +=
StringUtil::Join(entry.children, entry.children.size(),
", ", [&](
const unique_ptr<BASE> &child) {
60926 return (distincts++ ? "" : "DISTINCT ") + child->ToString();
60927 });
60928 }
60929
60930 if (entry.offset_expr.get()) {
60931 result += ", ";
60932 result += entry.offset_expr->ToString();
60933 }
60934 if (entry.default_expr.get()) {
60935 result += ", ";
60936 result += entry.default_expr->ToString();
60937 }
60938
60939 if (!entry.arg_orders.empty()) {
60940 result += " ORDER BY ";
60941 result +=
StringUtil::Join(entry.arg_orders, entry.arg_orders.size(),
", ",
60942 [](const ORDER_NODE &order) { return order.ToString(); });
60943 }
60944
60945
60946 if (entry.ignore_nulls) {
60947 result += " IGNORE NULLS";
60948 }
60949
60950 if (entry.filter_expr) {
60951 result += ") FILTER (WHERE " + entry.filter_expr->ToString();
60952 }
60953
60954
60955 result += ") OVER (";
60956 string sep;
60957
60958
60959 if (!entry.partitions.empty()) {
60960 result += "PARTITION BY ";
60961 result +=
StringUtil::Join(entry.partitions, entry.partitions.size(),
", ",
60962 [](const unique_ptr<BASE> &partition) { return partition->ToString(); });
60963 sep = " ";
60964 }
60965
60966
60967 if (!entry.orders.empty()) {
60968 result += sep;
60969 result += "ORDER BY ";
60971 [](const ORDER_NODE &order) { return order.ToString(); });
60972 sep = " ";
60973 }
60974
60975
60976 string units = "ROWS";
60977 string from;
60978 switch (entry.start) {
60979 case WindowBoundary::CURRENT_ROW_RANGE:
60980 case WindowBoundary::CURRENT_ROW_ROWS:
60981 case WindowBoundary::CURRENT_ROW_GROUPS:
60982 from = "CURRENT ROW";
60983 units = ToUnits(entry.start, WindowBoundary::CURRENT_ROW_ROWS, WindowBoundary::CURRENT_ROW_RANGE,
60984 WindowBoundary::CURRENT_ROW_GROUPS);
60985 break;
60986 case WindowBoundary::UNBOUNDED_PRECEDING:
60987 if (entry.end != WindowBoundary::CURRENT_ROW_RANGE) {
60988 from = "UNBOUNDED PRECEDING";
60989 }
60990 break;
60991 case WindowBoundary::EXPR_PRECEDING_ROWS:
60992 case WindowBoundary::EXPR_PRECEDING_RANGE:
60993 case WindowBoundary::EXPR_PRECEDING_GROUPS:
60994 from = entry.start_expr->ToString() + " PRECEDING";
60995 units = ToUnits(entry.start, WindowBoundary::EXPR_PRECEDING_ROWS, WindowBoundary::EXPR_PRECEDING_RANGE,
60996 WindowBoundary::EXPR_PRECEDING_GROUPS);
60997 break;
60998 case WindowBoundary::EXPR_FOLLOWING_ROWS:
60999 case WindowBoundary::EXPR_FOLLOWING_RANGE:
61000 case WindowBoundary::EXPR_FOLLOWING_GROUPS:
61001 from = entry.start_expr->ToString() + " FOLLOWING";
61002 units = ToUnits(entry.start, WindowBoundary::EXPR_FOLLOWING_ROWS, WindowBoundary::EXPR_FOLLOWING_RANGE,
61003 WindowBoundary::EXPR_FOLLOWING_GROUPS);
61004 break;
61005 case WindowBoundary::UNBOUNDED_FOLLOWING:
61006 case WindowBoundary::INVALID:
61007 throw InternalException("Unrecognized FROM in WindowExpression");
61008 }
61009
61010 string to;
61011 switch (entry.end) {
61012 case WindowBoundary::CURRENT_ROW_RANGE:
61013 if (entry.start != WindowBoundary::UNBOUNDED_PRECEDING) {
61014 to = "CURRENT ROW";
61015 units = "RANGE";
61016 }
61017 break;
61018 case WindowBoundary::CURRENT_ROW_ROWS:
61019 case WindowBoundary::CURRENT_ROW_GROUPS:
61020 to = "CURRENT ROW";
61021 units = ToUnits(entry.end, WindowBoundary::CURRENT_ROW_ROWS, WindowBoundary::CURRENT_ROW_RANGE,
61022 WindowBoundary::CURRENT_ROW_GROUPS);
61023 break;
61024 case WindowBoundary::UNBOUNDED_PRECEDING:
61025 to = "UNBOUNDED PRECEDING";
61026 break;
61027 case WindowBoundary::UNBOUNDED_FOLLOWING:
61028 to = "UNBOUNDED FOLLOWING";
61029 break;
61030 case WindowBoundary::EXPR_PRECEDING_ROWS:
61031 case WindowBoundary::EXPR_PRECEDING_RANGE:
61032 case WindowBoundary::EXPR_PRECEDING_GROUPS:
61033 to = entry.end_expr->ToString() + " PRECEDING";
61034 units = ToUnits(entry.end, WindowBoundary::EXPR_PRECEDING_ROWS, WindowBoundary::EXPR_PRECEDING_RANGE,
61035 WindowBoundary::EXPR_PRECEDING_GROUPS);
61036 break;
61037 case WindowBoundary::EXPR_FOLLOWING_ROWS:
61038 case WindowBoundary::EXPR_FOLLOWING_RANGE:
61039 case WindowBoundary::EXPR_FOLLOWING_GROUPS:
61040 to = entry.end_expr->ToString() + " FOLLOWING";
61041 units = ToUnits(entry.end, WindowBoundary::EXPR_FOLLOWING_ROWS, WindowBoundary::EXPR_FOLLOWING_RANGE,
61042 WindowBoundary::EXPR_FOLLOWING_GROUPS);
61043 break;
61044 case WindowBoundary::INVALID:
61045 throw InternalException("Unrecognized TO in WindowExpression");
61046 }
61047 if (entry.exclude_clause != WindowExcludeMode::NO_OTHER) {
61048
61049 if (from.empty()) {
61050 from = "UNBOUNDED PRECEDING";
61051 }
61052 if (to.empty()) {
61053 to = "CURRENT ROW";
61054 units = "RANGE";
61055 }
61056 }
61057
61058 if (!from.empty() || !to.empty()) {
61059 result += sep + units;
61060 }
61061 if (!from.empty() && !to.empty()) {
61062 result += " BETWEEN ";
61063 result += from;
61064 result += " AND ";
61065 result += to;
61066 } else if (!from.empty()) {
61067 result += " ";
61068 result += from;
61069 } else if (!to.empty()) {
61070 result += " ";
61071 result += to;
61072 }
61073
61074 if (entry.exclude_clause != WindowExcludeMode::NO_OTHER) {
61075 result += " EXCLUDE ";
61076 }
61077 switch (entry.exclude_clause) {
61078 case WindowExcludeMode::CURRENT_ROW:
61079 result += "CURRENT ROW";
61080 break;
61081 case WindowExcludeMode::GROUP:
61082 result += "GROUP";
61083 break;
61084 case WindowExcludeMode::TIES:
61085 result += "TIES";
61086 break;
61087 default:
61088 break;
61089 }
61090
61091 result += ")";
61092
61093 return result;
61094 }
static DUCKDB_API string Join(const vector< string > &input, const string &separator)
Join multiple strings into one string. Components are concatenated by the given separator.
string function_name
Name of the aggregate function.
Definition duckdb.cpp:60855
string schema
Schema of the aggregate function.
Definition duckdb.cpp:60853