Filter Safely on Hostile Names
Support escalated a ticket this morning: the customer-search feature crashes the moment someone looks up O'Brien & Sons. Last week it was worse — a search containing a | quietly matched customers it should never have matched. The root cause is the same in both cases: user-typed text is being pasted straight into a record filter, and filter strings are a little query language of their own.
Your job is a search codeunit that treats user input as data, not as filter syntax.
Requirements
Create a codeunit named "Customer Name Search" with two public procedures:
procedure CountExactName(NameToFind: Text): Integer
procedure CountNamesContaining(Fragment: Text): IntegerRules:
CountExactNamereturns how manyCustomerrecords have aNameequal toNameToFind, every character taken literally — apostrophes,&,|,*,?,.., parentheses and the rest included. Two customers sharing that exact name count as 2. Near misses (a name that merely starts the same way, or that a wildcard would catch) must not count.CountNamesContainingreturns how manyCustomerrecords containFragmentanywhere in theirName, ignoring case — searching foro'brien & sonsfinds a customer namedO'Brien & Sons Ltd.Fragmentis never empty and never contains*or?. Everything else is fair game: apostrophes,&,|,(,),=.- Neither procedure may raise an error, whatever the input contains. A search that finds nothing returns 0.
What the tests check
The grading tests seed customers with names like O'Brien & Sons, Import|Export, Star* Retail, Hans?n Shipping and 10..20 Storage, next to near-miss decoys such as Starfish Retail and Hansen Shipping, and assert exact counts — an implementation that over-matches, under-matches, or dies with a filter syntax error fails the corresponding test. One test gives two customers the identical name and expects 2; others search for a name or fragment that no customer has and expect 0. The contains tests place the fragment at the start, in the middle and at the end of the name — and one fragment is the entire name. The tests run in a real company, so extra customers exist — the seeded names carry unique markers, and your counts must be driven purely by the name matching described above.