Some people believe that security problems and other severe bugs are inevitable. Some of these people believe that conscientious design and clear thinking about how languages and APIs work is irrelevant; bad code is possible in every language.
Bad code is possible in any language and wrong code is possible with any API. Even so, it's possible to create languages and APIs which make the right thing so much easier than the wrong thing that only the most incompetent (or dangerously malicious) write bad code.
Imagine, for example, a database access layer which forbids the use of raw strings to create SQL queries. You might have to write:
my $sth = $dbh->select( @tables )->join( %relations )->where( %conditions );
That's not necessarily a beautiful interface dashed off after a moment of thinking, but it has an important security property: it avoids the interpolation of untrusted user input. All data sent to the database may go through a quoting or untainting process without the user having to remember to do so.
A similar library could help avoid malicious user input from interfering with the display or operation of a web site, for example. These are both specific cases of a general principle: replace unstructured string data with structured data. In both cases, the structure of the data makes the intent of the data clear, which allows the library to ensure as much safety as possible.
This principle has other implications as well; more on that next time.
But DBI already provides a middle ground, you can use the ? character to indicate user input and it will be escaped properly.
C# goes further and uses LINQ to allow the language to parse and statically type SQL queries:
http://www.hookedonlinq.com/LINQtoSQL5MinuteOverview.ashx
http://msdn.microsoft.com/en-us/library/bb425822.aspx
So not only is it structured as you suggest, but it is statically typed so you won't run into type problems unless by coercion.
Encoding grammars like states as you suggest seems fine too, but recognize that if you interpret strings it isn't always awful.
Yes, just imagine.
Yes, Fey exists and DBI supports placeholders, but the most obvious and straightforward approach is building up a big string and sending that to the database. Novices usually take what they perceive to be the path of least resistance.
This sounds like the discussion about programs being manipulated in a textual representation vs. a parse tree representation handled by a special-purpose programming editor. There are advantages and disadvantages to both choices, but in general, I am very much in favor of the unix approach of reducing structure to text.