diff --git a/src/backend/regex/regcomp.c b/src/backend/regex/regcomp.c index cc589b0930101da518ab8e117070d2d71df51a30..20670491de2120c85430ae93b56cf110fdaef83e 100644 --- a/src/backend/regex/regcomp.c +++ b/src/backend/regex/regcomp.c @@ -1154,7 +1154,10 @@ parseqatom(struct vars * v, /* rest of branch can be strung starting from atom->end */ s2 = atom->end; } - else if (m == 1 && n == 1) + else if (m == 1 && n == 1 && + (qprefer == 0 || + (atom->flags & (LONGER | SHORTER | MIXED)) == 0 || + qprefer == (atom->flags & (LONGER | SHORTER | MIXED)))) { /* no/vacuous quantifier: done */ EMPTYARC(s, atom->begin); /* empty prefix */ diff --git a/src/test/regress/expected/regex.out b/src/test/regress/expected/regex.out index af097193c52dee740033f31db4e8a76b79af8a55..2fb24ba5f6142f5f21fd5e27a36593aafc740ac0 100644 --- a/src/test/regress/expected/regex.out +++ b/src/test/regress/expected/regex.out @@ -464,6 +464,55 @@ select regexp_matches('foo/bar/baz', {foo,bar,baz} (1 row) +-- Test that greediness can be overridden by outer quantifier +select regexp_matches('llmmmfff', '^(l*)(.*)(f*)$'); + regexp_matches +---------------- + {ll,mmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*){1,1}(.*)(f*)$'); + regexp_matches +---------------- + {ll,mmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*){1,1}?(.*)(f*)$'); + regexp_matches +------------------ + {"",llmmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*){1,1}?(.*){1,1}?(f*)$'); + regexp_matches +---------------- + {"",llmmm,fff} +(1 row) + +select regexp_matches('llmmmfff', '^(l*?)(.*)(f*)$'); + regexp_matches +------------------ + {"",llmmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*?){1,1}(.*)(f*)$'); + regexp_matches +---------------- + {ll,mmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*?){1,1}?(.*)(f*)$'); + regexp_matches +------------------ + {"",llmmmfff,""} +(1 row) + +select regexp_matches('llmmmfff', '^(l*?){1,1}?(.*){1,1}?(f*)$'); + regexp_matches +---------------- + {"",llmmm,fff} +(1 row) + -- Test for infinite loop in cfindloop with zero-length possible match -- but no actual match (can only happen in the presence of backrefs) select 'a' ~ '$()|^\1'; diff --git a/src/test/regress/sql/regex.sql b/src/test/regress/sql/regex.sql index 1028ca6dcdcd0e8cae17c13ce4281af678c45708..31dfa1c461ded116e12b357867e136d1987474a9 100644 --- a/src/test/regress/sql/regex.sql +++ b/src/test/regress/sql/regex.sql @@ -111,6 +111,16 @@ select regexp_matches('Programmer', '(\w)(.*?\1)', 'g'); select regexp_matches('foo/bar/baz', '^([^/]+?)(?:/([^/]+?))(?:/([^/]+?))?$', ''); +-- Test that greediness can be overridden by outer quantifier +select regexp_matches('llmmmfff', '^(l*)(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*){1,1}(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*){1,1}?(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*){1,1}?(.*){1,1}?(f*)$'); +select regexp_matches('llmmmfff', '^(l*?)(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*?){1,1}(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*?){1,1}?(.*)(f*)$'); +select regexp_matches('llmmmfff', '^(l*?){1,1}?(.*){1,1}?(f*)$'); + -- Test for infinite loop in cfindloop with zero-length possible match -- but no actual match (can only happen in the presence of backrefs) select 'a' ~ '$()|^\1';