10 ms·
So when the Query is sent to the database MySQL actually receives a Query object and then parses that Query object? ...oh wait, right before it is sent to mysq
by x1 14y ago
So when the Query is sent to the database MySQL actually receives a Query object and then parses that Query object?
...oh wait, right before it is sent to mysql it is turned back into a string again.
My point is that static typing doesn't help you do anything other than verify that the objects being passed are of a particular type. I'm not saying static typing is bad or good I'm just saying that type checking itself is NEARLY USELESS unless you include some sort of validation.
Query q = new Query("select * from users where id = (id)");
QueryParam qp = new QueryParam("(id)",25);
q.addParam(qp);
ResultSet rs = q.execute();
public class Query {
public ResultSet execute() {
for(QueryParam qp : this.getQueryParams()) {
this.getSql().replace(qp.getId(),qp.getValue());
}
super.execute(sql);
}
}
That's all type safe. So it should be good right?
- gaius 14y agoInterestingly Wikipaedia lists SQL injection as being mitigated by strong typing (no I did not just edit it!) http://en.wikipedia.org/wiki/SQL_injection http://en.wikipedia.org/wiki/SQL_injection
- zopa 14y agoYes, you can write a Query type that is vulnerable to SQL injection, if you want to. But if you write a secure version, you only have to write it once. You only have to maintain it in one place. You only need to test it in one place. And if you forget to use your secure Query type, anywhere else in your code, the compiler will yell at you. It's a significant advantage. This is easier to see in a language with a rich, flexible and expressive type system than it is in Java. The writer of the original article used Haskell for a reason.
- x1 14y ago> But if you write a secure version, you only have to write it once. > You only have to maintain it in one place. > You only need to test it in one place. Again, so this cannot be done in a dynamic language? If it can be done, why bring them up? > And if you forget to use your secure Query type, anywhere else in your code, the compiler will yell at you. It's a significant advantage. The only thing the compiler will yell at you is if you passed a type that is not of a Query type. The compiler will not yell at you for getting the current session directly or creating your own jdbc driver for that matter.
- zopa 14y ago> "The only thing the compiler will yell at you is if you passed a type that is not of a Query type. The compiler will not yell at you for getting the current session directly or creating your own jdbc driver for that matter." In Haskell, I'd have a module, Database, that held all my db code. That module would export functions something like query :: Query -> DBResult update :: Query -> DBAction -> DBResult (read those as "query is a function that takes a Query and returns a DBResult.") In the rest of my program, those functions would be the only way to talk to the database. There's your guarantee. Could I, rather than using my nice database module, instead drop into IO and write code to do something vicious? Surely. But now we've moved beyond bugs and into active malice. > "Again, so this cannot be done in a dynamic language? If it can be done, why bring them up?" It's harder. With duck typing, if it looks like a Query it is a Query, no? Even if it drops your table. I'm no expert on dynamic languages, and I'd believe that there are sophisticated object hierarchies that can do these things (at runtime...), but the original article is empirical evidence that real projects get this wrong. Really, though, try a language with a modern type system and see for yourself. I know we Haskell users sound like zealots, but the difference between the Java and Haskell type systems truly is night and day.
- x1 14y ago> In the rest of my program, those functions would be the only way to talk to the database. There's your guarantee. Honest question. Take these pseudo sql calls: //Bad Person username = "lastname'; drop table user--" //Good Programmer query = "select * from users where name like %[username]%"; input = {"username":"frank"}; result = execute(query,input); //Bad Programmer query = "select * from users where name like '%"+username+"%'"; result = execute(query, {}); vs //Bad Person String username = "lastname'; drop table user--" //Good Programmer Query q = new Query("select * from users where name like %[username]%"); Input input = new Input(username); q.addInput(input); Result r = q.execute(); //Bad Programmer Query q = new Query("select * from users where name like '%"+username+"%'"); Result r = q.execute(); Could you solve this better using a static system? Right now I see no difference between the good and bad