@@ -669,6 +669,18 @@ def test_regexp_extract():
669669 'regexp_extract(a, "(a)(b)|(c)(d)", 4)' ),
670670 conf = _regexp_conf )
671671
672+ def test_regexp_extract_case_insensitive_inline_flag ():
673+ gen = mk_str_gen ('[abcABC]{1,3}[0-9]{1,2}[abcABC]{1,3}' )
674+ assert_gpu_and_cpu_are_equal_collect (
675+ lambda spark : unary_op_df (spark , gen ).selectExpr (
676+ # (?i) folds the capture-group contents but does not change group numbering
677+ 'regexp_extract(a, "(?i)([a-c]+)([0-9]+)", 1)' ,
678+ 'regexp_extract(a, "(?i)([a-c]+)([0-9]+)", 2)' ,
679+ # the flag turns on partway through, so only group 2 is case-insensitive
680+ 'regexp_extract(a, "([a-c]+)(?i)([a-c]+)", 2)' ,
681+ 'regexp_extract(a, "(?i)(abc)", 1)' ),
682+ conf = _regexp_conf )
683+
672684def test_regexp_extract_no_match ():
673685 gen = mk_str_gen ('[abcd]{1,3}[0-9]{1,3}[abcd]{1,3}' )
674686 assert_gpu_and_cpu_are_equal_collect (
@@ -1120,6 +1132,69 @@ def test_rlike_fallback_lookarounds_independent_named():
11201132 'RLike' ,
11211133 conf = _regexp_conf )
11221134
1135+ def test_rlike_case_insensitive_inline_flag ():
1136+ gen = mk_str_gen ('[a-dA-D]{1,4}' )
1137+ assert_gpu_and_cpu_are_equal_collect (
1138+ lambda spark : unary_op_df (spark , gen ).selectExpr (
1139+ 'a rlike "(?i)abc"' ,
1140+ 'a rlike "(?i)[a-c]"' ,
1141+ 'a rlike "a(?i)b"' ,
1142+ 'a rlike "(?i)a(?-i)b"' ,
1143+ 'a rlike "a|(?i)b"' ,
1144+ 'a rlike "(?i)(a|b)c"' ,
1145+ 'a rlike "(?i:abc)"' ,
1146+ 'a rlike "(?i:a|b)"' ,
1147+ 'a rlike "(?-i:a)b"' ,
1148+ # nested scoped-flags groups
1149+ 'a rlike "(?i:(?-i:a)b)"' ,
1150+ 'a rlike "(?-i:a(?i:b)c)"' ,
1151+ 'a rlike "(?i:a(?-i:b(?i:c))d)"' ,
1152+ # a bare inline flag inside a scoped-flags group
1153+ 'a rlike "(?i:a(?-i)b)"' ,
1154+ 'a rlike "(?-i:a(?i)b)"' ,
1155+ # a negated non-case-insensitive flag is a no-op (mode off by default)
1156+ 'a rlike "(?-s:abc)"' ,
1157+ 'a rlike "(?i-s:abc)"' ),
1158+ conf = _regexp_conf )
1159+
1160+ def test_regexp_replace_case_insensitive_inline_flag ():
1161+ from pyspark .sql .functions import regexp_replace , col
1162+ gen = mk_str_gen ('[a-cA-C]{0,4}' )
1163+ # case folding must also work in replace mode, including a backref into a case-insensitive
1164+ # capture group (uses the DataFrame API so Spark SQL does not expand ${...} first)
1165+ assert_gpu_and_cpu_are_equal_collect (
1166+ lambda spark : unary_op_df (spark , gen ).select (
1167+ regexp_replace (col ('a' ), '(?i)abc' , 'X' ),
1168+ regexp_replace (col ('a' ), '(?i:abc)' , 'Y' ),
1169+ regexp_replace (col ('a' ), '(?i)a(?-i)b' , 'Z' ),
1170+ regexp_replace (col ('a' ), '(?i)(abc)' , '[${1}]' )),
1171+ conf = _regexp_conf )
1172+
1173+ @allow_non_gpu ('ProjectExec' , 'RLike' )
1174+ def test_rlike_fallback_unsupported_inline_flags ():
1175+ gen = mk_str_gen ('[abcd]{1,3}' )
1176+ # (?m)/(?s) are unsupported (positive) flags; (?i) that precedes a choice alternative cannot
1177+ # be folded (in Java `a(?i)b|c` makes both `b` and `c` case-insensitive); scoped groups with a
1178+ # positive non-case-insensitive flag are likewise unsupported
1179+ for pattern in ['(?m)a' , '(?s)a' , '(?i)a|b' , '(?i)a|b|c' , 'a(?i)b|c' , '(?m:a)' , '(?is:a)' ]:
1180+ assert_gpu_fallback_collect (
1181+ lambda spark , pattern = pattern : unary_op_df (spark , gen ).selectExpr (
1182+ f'a rlike "{ pattern } "' ),
1183+ 'RLike' ,
1184+ conf = _regexp_conf )
1185+
1186+ @allow_non_gpu ('ProjectExec' , 'RLike' )
1187+ def test_rlike_fallback_inline_flags_with_anchors ():
1188+ gen = mk_str_gen ('[abcd]{1,3}' )
1189+ # a zero-width (?i) must not let an otherwise-unsupported anchor context (\n$, $^, ^$, or an
1190+ # anchors-only sequence) reach the GPU; these all fall back like their flag-free forms
1191+ for pattern in ['$(?i)^' , '^(?i)$' , '^(?i)' , '(?i)$' ]:
1192+ assert_gpu_fallback_collect (
1193+ lambda spark , pattern = pattern : unary_op_df (spark , gen ).selectExpr (
1194+ f'a rlike "{ pattern } "' ),
1195+ 'RLike' ,
1196+ conf = _regexp_conf )
1197+
11231198def test_regexp_extract_all_idx_zero ():
11241199 gen = mk_str_gen ('[abcd]{0,3}[0-9]{0,3}-[0-9]{0,3}[abcd]{1,3}' )
11251200 assert_gpu_and_cpu_are_equal_collect (
0 commit comments