|
1 | 1 | use cubeclient::models::V1LoadRequestQuery; |
2 | 2 | use datafusion::physical_plan::displayable; |
3 | 3 | use pretty_assertions::assert_eq; |
| 4 | +use regex::Regex; |
4 | 5 | use serde_json::json; |
5 | 6 | use std::sync::Arc; |
6 | 7 |
|
@@ -1147,6 +1148,88 @@ async fn test_case_wrapper_escaping() { |
1147 | 1148 | .contains("\\\\\\\\\\\\`")); |
1148 | 1149 | } |
1149 | 1150 |
|
| 1151 | +/// Test aliases for grouped CubeScan in wrapper |
| 1152 | +/// qualifiers from join should get remapped to single from alias |
| 1153 | +/// long generated aliases from Datafusion should get shortened |
| 1154 | +#[tokio::test] |
| 1155 | +async fn test_join_wrapper_cubescan_aliasing() { |
| 1156 | + if !Rewriter::sql_push_down_enabled() { |
| 1157 | + return; |
| 1158 | + } |
| 1159 | + init_testing_logger(); |
| 1160 | + |
| 1161 | + let query_plan = convert_select_to_query_plan( |
| 1162 | + // language=PostgreSQL |
| 1163 | + r#" |
| 1164 | +WITH |
| 1165 | +-- This subquery should be represented as CubeScan(ungrouped=false) inside CubeScanWrapper |
| 1166 | +cube_scan_subq AS ( |
| 1167 | + SELECT |
| 1168 | + logs_alias.content logs_content, |
| 1169 | + DATE_TRUNC('month', kibana_alias.last_mod) last_mod_month, |
| 1170 | + CASE |
| 1171 | + WHEN sum(kibana_alias."sumPrice") IS NOT NULL |
| 1172 | + THEN sum(kibana_alias."sumPrice") |
| 1173 | + ELSE 0 |
| 1174 | + END sum_price |
| 1175 | + FROM KibanaSampleDataEcommerce kibana_alias |
| 1176 | + JOIN Logs logs_alias |
| 1177 | + ON kibana_alias.__cubeJoinField = logs_alias.__cubeJoinField |
| 1178 | + GROUP BY |
| 1179 | + logs_content, |
| 1180 | + last_mod_month |
| 1181 | +), |
| 1182 | +filter_subq AS ( |
| 1183 | + SELECT |
| 1184 | + Logs.content logs_content_filter |
| 1185 | + FROM Logs |
| 1186 | + GROUP BY |
| 1187 | + logs_content_filter |
| 1188 | +) |
| 1189 | +SELECT |
| 1190 | + logs_content |
| 1191 | +FROM cube_scan_subq |
| 1192 | +WHERE |
| 1193 | + -- This subquery filter should trigger wrapping of whole query |
| 1194 | + logs_content IN ( |
| 1195 | + SELECT |
| 1196 | + logs_content_filter |
| 1197 | + FROM filter_subq |
| 1198 | + ) |
| 1199 | +; |
| 1200 | +"# |
| 1201 | + .to_string(), |
| 1202 | + DatabaseProtocol::PostgreSQL, |
| 1203 | + ) |
| 1204 | + .await; |
| 1205 | + |
| 1206 | + let physical_plan = query_plan.as_physical_plan().await.unwrap(); |
| 1207 | + println!( |
| 1208 | + "Physical plan: {}", |
| 1209 | + displayable(physical_plan.as_ref()).indent() |
| 1210 | + ); |
| 1211 | + |
| 1212 | + let logical_plan = query_plan.as_logical_plan(); |
| 1213 | + let sql = logical_plan |
| 1214 | + .find_cube_scan_wrapper() |
| 1215 | + .wrapped_sql |
| 1216 | + .unwrap() |
| 1217 | + .sql; |
| 1218 | + |
| 1219 | + // Check that all aliases from different tables have same qualifier, and that names are simple and short |
| 1220 | + // logs_content => logs_alias.content |
| 1221 | + // last_mod_month => DATE_TRUNC('month', kibana_alias.last_mod), |
| 1222 | + // sum_price => CASE WHEN sum(kibana_alias."sumPrice") ... END |
| 1223 | + let content_re = Regex::new(r#""logs_alias"."[a-zA-Z0-9_]{1,16}" "logs_content""#).unwrap(); |
| 1224 | + assert!(content_re.is_match(&sql)); |
| 1225 | + let last_mod_month_re = |
| 1226 | + Regex::new(r#""logs_alias"."[a-zA-Z0-9_]{1,16}" "last_mod_month""#).unwrap(); |
| 1227 | + assert!(last_mod_month_re.is_match(&sql)); |
| 1228 | + let sum_price_re = Regex::new(r#"CASE WHEN "logs_alias"."[a-zA-Z0-9_]{1,16}" IS NOT NULL THEN "logs_alias"."[a-zA-Z0-9_]{1,16}" ELSE 0 END "sum_price""#) |
| 1229 | + .unwrap(); |
| 1230 | + assert!(sum_price_re.is_match(&sql)); |
| 1231 | +} |
| 1232 | + |
1150 | 1233 | /// Test that WrappedSelect(... limit=Some(0) ...) will render it correctly |
1151 | 1234 | #[tokio::test] |
1152 | 1235 | async fn test_wrapper_limit_zero() { |
|
0 commit comments