I don't know Postgres, but in databases I've used, DDL statements are indifferent to transactions and can't be rolled back. Not sure that will be an issue.
But in general, using transactions to validate SQL is not a bad idea. I have an application that does something similar.
If you're having data values interpreted as placeholders, it sounds like your SQL text may not actually be in a form that's valid for an individual statement. I don't know the COPY statement so I may be out of my league here.