Deep Typechecking and Refactoring Zachary Tatlock, Chris Tucker, David Shuffleton, Ranjit Jhala,...

79
Deep Typechecking and Refactoring Zachary Tatlock, Chris Tucker, David Shuffleton, Ranjit Jhala, Sorin Lerner 1 University of California, San Diego

Transcript of Deep Typechecking and Refactoring Zachary Tatlock, Chris Tucker, David Shuffleton, Ranjit Jhala,...

1

Deep Typecheckingand Refactoring

Zachary Tatlock, Chris Tucker, David Shuffleton, Ranjit Jhala, Sorin Lerner

University of California, San Diego

3

Communicating with Databases

String based queries are prevalent:JPA, Hibernate, TopLink

JAVA DBStrings

4

Example: Using JPA to query DB

“SELECT w FROM Weblog w WHERE w.id = ?1 AND w.link.id = ?2”

Query in JPA Query Language:

Mapping Java Classes to DB Tables: Expressed in Object Relational Mapping (ORM)

Java syntax in query String

5

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

6

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

7

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

2. Create query

8

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

2. Create query

3. Set parameters

9

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

2. Create query

3. Set parameters

10

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

2. Create query

3. Set parameters

4. Execute query

11

Example: Using JPA to query DBString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Build query string

2. Create query

3. Set parameters

4. Execute query

• Efficient• Flexible

Unsafe

12

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

13

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); // q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

14

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); // q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

15

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

16

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, new Weblog()); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

17

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

18

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Warranty w = (Warranty) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

19

Uncaught ErrorsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

Java compiler does not reason about the query strings; cannot typecheck.

20

Refactor: Weblog.id Weblog.nameString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

21

Refactor: Weblog.id Weblog.nameString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

Refactor

Don’t Refactor

Need to know type of w and w.link to

refactor safely.

22

Refactor: Weblog.id Weblog.nameString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

4. Refactoring difficult

23

String Based Query ChallengesString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

4. Refactoring difficult

24

Contributions

Deep Typechecking: All parameters set Parameters correctly set Results safely downcast

Deep Refactoring: Builds on Deep Typechecking Enables class and field renaming

1. Unset parameter

2. Unsafe param type

3. Unsafe downcast

4. Refactoring difficult

25

Outline

1. Introduction and Motivation2. Deep Typechecking and Refactoring

Straight Line Code Control Flow Multiple Methods

3. Experimental Results4. Related Work and Conclusion

26

Deep Typechecking ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Query safety:

• All params set

• Params safely set

• Result safely downcast

Is this query exec safe?

Need to know:

1. query string

2. param types

27

Deep Typechecking ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Bound Query:• query string• param types

query : “SELECT … ?1 … ?2 … ?3 …”?1 : String?2 : Weblog?3 : unknown

Example :

At each program point map each var to a set of BQs.

28

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

29

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

30

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

31

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

32

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

query : “SELECT …”?1 : unknown?2 : unknown

33

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

query : “SELECT …”?1 : unknown?2 : unknown

query : “SELECT …”?1 : String?2 : unknown

34

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

qStr = “SELECT … ?2”

query : “SELECT …”?1 : unknown?2 : unknown

query : “SELECT …”?1 : String?2 : unknown

query : “SELECT …”?1 : String?2 : int

35

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Checking param types:

1. Parse query string

2. Check all params set

3. Check param types

Bound Queries:

query : “SELECT …”?1 : String?2 : int

36

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Checking result type:

1. Infer result type

2. Propagate result type

3. Check downcasts

Bound Queries:

query : “SELECT …”?1 : String?2 : int

query : “SELECT …”?1 : String?2 : intresult : Weblog

37

Bound Query AnalysisString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

If a query passes Deep Typechecking, then it will not cause an error at runtime.

Therefore, Bound Query Analysis has no silent failures.

39

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

40

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Refactor Weblog field:

id name

41

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Refactor Weblog field:

id name

42

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

Refactor Weblog field:

id name

43

Deep Refactoring ExampleRefactor Weblog field:

id name

String getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

query :

SELECT w FROM Weblog w WHERE w.id = ?1 AND w.link.id = ?2?1 : String?2 : int

44

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

query :

SELECT w FROM Weblog w WHERE w.id = ?1 AND w.link.id = ?2?1 : String?2 : int

Refactor Weblog field:

id name

1. Refactor full query

45

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

query :

SELECT w FROM Weblog w WHERE w.name = ?1 AND w.link.id = ?2?1 : String?2 : int

Refactor Weblog field:

id name

1. Refactor full query

46

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

query :

SELECT w FROM Weblog w WHERE w.name = ?1 AND w.link.id = ?2?1 : String?2 : int

Refactor Weblog field:

id name

1. Refactor full query

2. Propagate changes

47

Deep Refactoring ExampleString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.name = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

query :

SELECT w FROM Weblog w WHERE w.name = ?1 AND w.link.id = ?2?1 : String?2 : int

Refactor Weblog field:

id name

1. Refactor full query

2. Propagate changes

48

Outline

1. Introduction and Motivation2. Deep Typechecking and Refactoring

Straight Line Code Control Flow Multiple Methods

3. Experimental Results4. Related Work and Conclusion

49

Flow SensitivityString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “AND w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

50

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery(); return w.text;}

51

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery(); return w.text;}

52

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else {

}

Weblog w = (Weblog) q.execQuery(); return w.text;}

53

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

54

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

55

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

qStr = “SELECT … ?2”

56

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?2”

57

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?1”

qStr = “SELECT … ?2”

58

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?1”

qStr = “SELECT … ?2”

59

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?1”

qStr = “SELECT … ?2”

60

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

qStr = “SELECT … ?1”

query : “SEL … ?1”?1 : String

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?2”

61

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

query : “SEL … ?1”?1 : String

“SEL … ?2”?1 : String?2 : int

“SEL … ?1”?1 : String

query : “SEL … ?2”?1 : String?2 : int

qStr = “SELECT … ?1”

qStr = “SELECT … ?2”

62

Flow SensitivityString getText(String id, Link link) { String qStr; Query q; qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

if(link != null) { qStr += “AND w.link.id = ?2”; q = createQuery(qStr); q.setParam(1, id); q.setParam(2, link.id); } else { q = createQuery(qStr); q.setParam(1, id); }

Weblog w = (Weblog) q.execQuery(); return w.text;}

“SEL … ?2”?1 : String?2 : int

“SEL … ?1”?1 : String

As before, for each bound query:

1. Check param types

2. Check result type

In general, we express Bound Query Analysis as a dataflow analysis.

64

LoopsString getText(String id, Link link) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “OR w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

65

LoopsString getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “OR w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

66

LoopsString getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”; qStr += “OR w.link.id = ?2”;

q = createQuery(qStr);

q.setParam(1, id); q.setParam(2, link.id);

Weblog w = (Weblog) q.execQuery();

return w.text;}

67

LoopsString getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

for(int i = 0; i < links.size(); i++) { qStr += “ OR w.link.id = ?” + i; }

q = createQuery(qStr);

...}

68

String getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

for(int i = 0; i < links.size(); i++) { qStr += “ OR w.link.id = ?” + i; }

q = createQuery(qStr);

...}

Loops

qStr = ???qStr = “SELECT … w.id = ?1” ( “ OR w.link.id = ?#” )*

69

String getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

for(int i = 0; i < links.size(); i++) { qStr += “ OR w.link.id = ?” + i; }

q = createQuery(qStr);

...}

Loops

qStr = “SELECT … w.id = ?1” ( “ OR w.link.id = ?#” )*

70

String getText(String id, List<Link> links) { String qStr; Query q;

qStr = “SELECT w FROM Weblog w ”; qStr += “WHERE w.id = ?1 ”;

for(int i = 0; i < links.size(); i++) { qStr += “ OR w.link.id = ?” + i; }

q = createQuery(qStr);

...}

Loops

qStr = “SELECT … w.id = ?1” ( “ OR w.link.id = ?#” )*

Deep Refactoring:• know query structure• know fragment locs• refactor across loops

Deep Typechecking:• unknown # of params• do not check params• can still check result

71

Outline

1. Introduction and Motivation2. Deep Typechecking and Refactoring

Straight Line Code Control Flow Multiple Methods

3. Experimental Results4. Related Work and Conclusion

72

Multiple MethodsString mainQueryStr() { return “SELECT ... ?1”;}

Object getMain() { String qStr = mainQueryStr();

Query q = createQuery(qStr);

q.setParam(1, “main”);

return q.execQuery();}

String mainId() { return ((Weblog) getMain()).id;}

String Analysis : • interprocedural• compute regexps

Bound Query Analysis : • intraprocedural• no complex aliasing

Result Analysis :• interprocedural• propagate result type

73

Outline

1. Introduction and Motivation2. Deep Typechecking and Refactoring

Straight Line Code Control Flow Multiple Methods

3. Experimental Results4. Related Work and Conclusion

74

Results Implementation: Quail

5700 lines of Java in Eclipse plugin

Benchmarks:Application LOC DescriptionRoller 82,900 Blogging frameworkPlanet 14,500 News aggregatorPetStore 5,440 Example JPA applicationCaveatEmptor 3,370 Online auction systemTotal 106,000

Create Query Set Param Exec Query163 199 136

JPA Calls:

Tested,Stable,

Deployed

75

Deep Typechecking ExperimentCheck for all query execution sites:

All parameters set Parameters safely set Query results safely downcast

Show 84% of query executions are safe

Remaining 16% due to imprecision: Queries built with loops or data structures Path sensitivity Reflection

76

Deep Refactoring Experiment Rename 16 most frequently appearing classes / fields Correctly refactor 98% of refactorable locations Remaining 2% from heap based strings in query

String[] blacklist = getBlacklist();

String qStr = “SELECT w FROM Weblog w WHERE w.id = ?1 ”;

for(int i = 0; i < blacklist.length; i++) {

qStr += “AND w.id != ” + blacklist[i] + “ ”;

}

...

77

Results

Typechecking and Refactoring Experiments: No silent failures Show user exactly where to check 2% vs 16% imprecision:

Refactoring does not depend on parameter types

78

Outline

1. Introduction and Motivation2. Deep Typechecking and Refactoring

Straight Line Code Control Flow Mutliple Methods

3. Experimental Results4. Related Work and Conclusion

79

Related Work

Query Extraction [Wiedermann, Ibrahim, Cook 08] Infer query from Java code that uses DB root object Not applicable to legacy code

Static Query Checking [Gould, Su, Devanbu 04] Typechecks JDBC queries against DB schema Not applied to source language type system

80

Related Work

Language Based [Matthes 95, Schmidt 94] Syntax extension for queries Not applicable to legacy code

Orthogonal Persistence [Atkinson 96, Liskov 96] Map DB to collection of persisted objects Must express queries in non-query language

81

Conclusion

String based queries can be safe and flexible.

Deep Typechecking ensures: All parameters are set Parameters are set to correct type Query results are safely downcast

Deep Refactoring enables: Class and field renaming

82

Thank You