I have a module that will construct an SQL query given the following...
I took a similar approach in DBIx::SQLEngine, which accepts a very flexible set of arguments and can both generate SQL or optionally execute it for you.
When working at this higher level, the OP may find that they don't need as many subroutines -- for example, rather than having subroutines for each version of a select query based on which columns you need, your get_person_companies() subroutine could take a list of additional columns to include in the results.