@@ -1054,6 +1054,126 @@ mod tests {
10541054 assert ! ( s. contains( "p__amount" ) , "Should contain column reference" ) ;
10551055 }
10561056
1057+ #[ test]
1058+ fn test_value_expr_function_tolower ( ) {
1059+ let expr = ValueExpression :: Function {
1060+ name : "toLower" . into ( ) ,
1061+ args : vec ! [ ValueExpression :: Property ( PropertyRef {
1062+ variable: "p" . into( ) ,
1063+ property: "name" . into( ) ,
1064+ } ) ] ,
1065+ } ;
1066+
1067+ let df_expr = to_df_value_expr ( & expr) ;
1068+ let s = format ! ( "{:?}" , df_expr) ;
1069+ // Should be a ScalarFunction with lower
1070+ assert ! (
1071+ s. contains( "lower" ) || s. contains( "Lower" ) ,
1072+ "Should use lower function, got: {}" ,
1073+ s
1074+ ) ;
1075+ assert ! ( s. contains( "p__name" ) , "Should contain column reference" ) ;
1076+ }
1077+
1078+ #[ test]
1079+ fn test_value_expr_function_toupper ( ) {
1080+ let expr = ValueExpression :: Function {
1081+ name : "toUpper" . into ( ) ,
1082+ args : vec ! [ ValueExpression :: Property ( PropertyRef {
1083+ variable: "p" . into( ) ,
1084+ property: "name" . into( ) ,
1085+ } ) ] ,
1086+ } ;
1087+
1088+ let df_expr = to_df_value_expr ( & expr) ;
1089+ let s = format ! ( "{:?}" , df_expr) ;
1090+ // Should be a ScalarFunction with upper
1091+ assert ! (
1092+ s. contains( "upper" ) || s. contains( "Upper" ) ,
1093+ "Should use upper function, got: {}" ,
1094+ s
1095+ ) ;
1096+ assert ! ( s. contains( "p__name" ) , "Should contain column reference" ) ;
1097+ }
1098+
1099+ #[ test]
1100+ fn test_value_expr_function_lower_alias ( ) {
1101+ // Test that 'lower' also works (SQL-style alias)
1102+ let expr = ValueExpression :: Function {
1103+ name : "lower" . into ( ) ,
1104+ args : vec ! [ ValueExpression :: Property ( PropertyRef {
1105+ variable: "p" . into( ) ,
1106+ property: "name" . into( ) ,
1107+ } ) ] ,
1108+ } ;
1109+
1110+ let df_expr = to_df_value_expr ( & expr) ;
1111+ let s = format ! ( "{:?}" , df_expr) ;
1112+ assert ! (
1113+ s. contains( "lower" ) || s. contains( "Lower" ) ,
1114+ "Should use lower function, got: {}" ,
1115+ s
1116+ ) ;
1117+ }
1118+
1119+ #[ test]
1120+ fn test_value_expr_function_upper_alias ( ) {
1121+ // Test that 'upper' also works (SQL-style alias)
1122+ let expr = ValueExpression :: Function {
1123+ name : "upper" . into ( ) ,
1124+ args : vec ! [ ValueExpression :: Property ( PropertyRef {
1125+ variable: "p" . into( ) ,
1126+ property: "name" . into( ) ,
1127+ } ) ] ,
1128+ } ;
1129+
1130+ let df_expr = to_df_value_expr ( & expr) ;
1131+ let s = format ! ( "{:?}" , df_expr) ;
1132+ assert ! (
1133+ s. contains( "upper" ) || s. contains( "Upper" ) ,
1134+ "Should use upper function, got: {}" ,
1135+ s
1136+ ) ;
1137+ }
1138+
1139+ #[ test]
1140+ fn test_tolower_with_contains_produces_valid_like ( ) {
1141+ // This is the bug scenario: toLower(s.name) CONTAINS 'offer'
1142+ // Previously returned lit(0) which caused type coercion error
1143+ let tolower_expr = ValueExpression :: Function {
1144+ name : "toLower" . into ( ) ,
1145+ args : vec ! [ ValueExpression :: Property ( PropertyRef {
1146+ variable: "s" . into( ) ,
1147+ property: "name" . into( ) ,
1148+ } ) ] ,
1149+ } ;
1150+
1151+ let contains_expr = BooleanExpression :: Contains {
1152+ expression : tolower_expr,
1153+ substring : "offer" . into ( ) ,
1154+ } ;
1155+
1156+ let df_expr = to_df_boolean_expr ( & contains_expr) ;
1157+ let s = format ! ( "{:?}" , df_expr) ;
1158+
1159+ // Should be a Like expression with lower() on the column, not lit(0)
1160+ assert ! (
1161+ s. contains( "Like" ) ,
1162+ "Should be a LIKE expression, got: {}" ,
1163+ s
1164+ ) ;
1165+ assert ! (
1166+ s. contains( "lower" ) || s. contains( "Lower" ) ,
1167+ "Should contain lower function, got: {}" ,
1168+ s
1169+ ) ;
1170+ assert ! (
1171+ !s. contains( "Int32(0)" ) && !s. contains( "Int64(0)" ) && !s. contains( "Utf8(\" \" )" ) ,
1172+ "Should NOT contain literal 0 or empty string (placeholder bugs), got: {}" ,
1173+ s
1174+ ) ;
1175+ }
1176+
10571177 // ========================================================================
10581178 // Unit tests for contains_aggregate()
10591179 // ========================================================================
@@ -1277,124 +1397,4 @@ mod tests {
12771397 let name = to_cypher_column_name ( & expr) ;
12781398 assert_eq ! ( name, "expr" , "Arithmetic should use generic name" ) ;
12791399 }
1280-
1281- #[ test]
1282- fn test_value_expr_function_tolower ( ) {
1283- let expr = ValueExpression :: Function {
1284- name : "toLower" . into ( ) ,
1285- args : vec ! [ ValueExpression :: Property ( PropertyRef {
1286- variable: "p" . into( ) ,
1287- property: "name" . into( ) ,
1288- } ) ] ,
1289- } ;
1290-
1291- let df_expr = to_df_value_expr ( & expr) ;
1292- let s = format ! ( "{:?}" , df_expr) ;
1293- // Should be a ScalarFunction with lower
1294- assert ! (
1295- s. contains( "lower" ) || s. contains( "Lower" ) ,
1296- "Should use lower function, got: {}" ,
1297- s
1298- ) ;
1299- assert ! ( s. contains( "p__name" ) , "Should contain column reference" ) ;
1300- }
1301-
1302- #[ test]
1303- fn test_value_expr_function_toupper ( ) {
1304- let expr = ValueExpression :: Function {
1305- name : "toUpper" . into ( ) ,
1306- args : vec ! [ ValueExpression :: Property ( PropertyRef {
1307- variable: "p" . into( ) ,
1308- property: "name" . into( ) ,
1309- } ) ] ,
1310- } ;
1311-
1312- let df_expr = to_df_value_expr ( & expr) ;
1313- let s = format ! ( "{:?}" , df_expr) ;
1314- // Should be a ScalarFunction with upper
1315- assert ! (
1316- s. contains( "upper" ) || s. contains( "Upper" ) ,
1317- "Should use upper function, got: {}" ,
1318- s
1319- ) ;
1320- assert ! ( s. contains( "p__name" ) , "Should contain column reference" ) ;
1321- }
1322-
1323- #[ test]
1324- fn test_value_expr_function_lower_alias ( ) {
1325- // Test that 'lower' also works (SQL-style alias)
1326- let expr = ValueExpression :: Function {
1327- name : "lower" . into ( ) ,
1328- args : vec ! [ ValueExpression :: Property ( PropertyRef {
1329- variable: "p" . into( ) ,
1330- property: "name" . into( ) ,
1331- } ) ] ,
1332- } ;
1333-
1334- let df_expr = to_df_value_expr ( & expr) ;
1335- let s = format ! ( "{:?}" , df_expr) ;
1336- assert ! (
1337- s. contains( "lower" ) || s. contains( "Lower" ) ,
1338- "Should use lower function, got: {}" ,
1339- s
1340- ) ;
1341- }
1342-
1343- #[ test]
1344- fn test_value_expr_function_upper_alias ( ) {
1345- // Test that 'upper' also works (SQL-style alias)
1346- let expr = ValueExpression :: Function {
1347- name : "upper" . into ( ) ,
1348- args : vec ! [ ValueExpression :: Property ( PropertyRef {
1349- variable: "p" . into( ) ,
1350- property: "name" . into( ) ,
1351- } ) ] ,
1352- } ;
1353-
1354- let df_expr = to_df_value_expr ( & expr) ;
1355- let s = format ! ( "{:?}" , df_expr) ;
1356- assert ! (
1357- s. contains( "upper" ) || s. contains( "Upper" ) ,
1358- "Should use upper function, got: {}" ,
1359- s
1360- ) ;
1361- }
1362-
1363- #[ test]
1364- fn test_tolower_with_contains_produces_valid_like ( ) {
1365- // This is the bug scenario: toLower(s.name) CONTAINS 'offer'
1366- // Previously returned lit(0) which caused type coercion error
1367- let tolower_expr = ValueExpression :: Function {
1368- name : "toLower" . into ( ) ,
1369- args : vec ! [ ValueExpression :: Property ( PropertyRef {
1370- variable: "s" . into( ) ,
1371- property: "name" . into( ) ,
1372- } ) ] ,
1373- } ;
1374-
1375- let contains_expr = BooleanExpression :: Contains {
1376- expression : tolower_expr,
1377- substring : "offer" . into ( ) ,
1378- } ;
1379-
1380- let df_expr = to_df_boolean_expr ( & contains_expr) ;
1381- let s = format ! ( "{:?}" , df_expr) ;
1382-
1383- // Should be a Like expression with lower() on the column, not lit(0)
1384- assert ! (
1385- s. contains( "Like" ) ,
1386- "Should be a LIKE expression, got: {}" ,
1387- s
1388- ) ;
1389- assert ! (
1390- s. contains( "lower" ) || s. contains( "Lower" ) ,
1391- "Should contain lower function, got: {}" ,
1392- s
1393- ) ;
1394- assert ! (
1395- !s. contains( "Int32(0)" ) && !s. contains( "Int64(0)" ) && !s. contains( "Utf8(\" \" )" ) ,
1396- "Should NOT contain literal 0 or empty string (placeholder bugs), got: {}" ,
1397- s
1398- ) ;
1399- }
14001400}
0 commit comments