in reply to DBI do() SQL injection

I think there is something of a misunderstanding here. Although do() can use placeholders, many statements cannot use placeholders.

This means that there is a possible SQL injection vector where placeholders cannot be used. For example, in PostgreSQL, utility statements such as CREATE USER, CREATE TABLE, DROP TABLE, etc. have no query plan associated with them and therefore cannot be parameterized. In these cases, you have to properly use quote_identifier and quote methods to properly escape your variables.

There are some things you can do to allow these to be parameterized from the Perl side such as wrapping in user-defined functions and then calling with SELECT queries, but this pushes into the function definition level on the SQL side.

It's important to understand and think through how SQL Injection happens to assess it. In Postgres, for example, parameterized queries come in with the placeholder-including text and the parameters supplied separately. This means that the parsing of the query happens the parameters are not considered and the parameters are fed into the parse tree after the query is parsed but before it is planned. In this regard, there is no room for sql injection at all on this level. But anywhere you have to have string interpolation, you get the parsing happening once the variables are interpolated in, so this can affect the output parse tree. Once that happens, you have to use other measures to prevent that. In queries that are not planned, in Postgres this means that all utility statements are problems.