@@ -41,6 +41,7 @@ private module Aiopg {
4141 result = connection ( ) .getMember ( "cursor" ) .getReturn ( ) .getAwaited ( )
4242 }
4343
44+ /** Calling `execute` on a `Cursor` constructs a query. */
4445 class CursorExecuteCall extends SqlConstruction:: Range , DataFlow:: CallCfgNode {
4546 CursorExecuteCall ( ) { this = cursor ( ) .getMember ( "execute" ) .getACall ( ) }
4647
@@ -71,4 +72,49 @@ private module Aiopg {
7172
7273 override DataFlow:: Node getSql ( ) { result = sql }
7374 }
75+
76+ /** An `Engine` is created when the result of calling `aiopg.sa.create_engine` is awaited. */
77+ API:: Node engine ( ) {
78+ result =
79+ API:: moduleImport ( "aiopg" ) .getMember ( "sa" ) .getMember ( "create_engine" ) .getReturn ( ) .getAwaited ( )
80+ }
81+
82+ /**
83+ * A `SAConnection` is created when the result of calling `aquire` on an `Engine` is awaited.
84+ */
85+ API:: Node saConnection ( ) { result = engine ( ) .getMember ( "acquire" ) .getReturn ( ) .getAwaited ( ) }
86+
87+ /** Calling `execute` on a `SAConnection` constructs a query. */
88+ class SAConnectionExecuteCall extends SqlConstruction:: Range , DataFlow:: CallCfgNode {
89+ SAConnectionExecuteCall ( ) { this = saConnection ( ) .getMember ( "execute" ) .getACall ( ) }
90+
91+ override DataFlow:: Node getSql ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "query" ) ] }
92+ }
93+
94+ /**
95+ * This is only needed to connect the argument to the execute call with the subsequnt awaiting.
96+ * It should be obsolete once we have `API::CallNode` available.
97+ */
98+ private DataFlow:: TypeTrackingNode saConnectionExecuteCall (
99+ DataFlow:: TypeTracker t , DataFlow:: Node sql
100+ ) {
101+ // saConnection created from engine
102+ t .start ( ) and
103+ sql = result .( SAConnectionExecuteCall ) .getSql ( )
104+ or
105+ exists ( DataFlow:: TypeTracker t2 | result = saConnectionExecuteCall ( t2 , sql ) .track ( t2 , t ) )
106+ }
107+
108+ DataFlow:: Node saConnectionExecuteCall ( DataFlow:: Node sql ) {
109+ saConnectionExecuteCall ( DataFlow:: TypeTracker:: end ( ) , sql ) .flowsTo ( result )
110+ }
111+
112+ /** Awaiting the result of calling `execute` executes the query. */
113+ class AwaitedSAConnectionExecuteCall extends SqlExecution:: Range {
114+ DataFlow:: Node sql ;
115+
116+ AwaitedSAConnectionExecuteCall ( ) { this = awaited ( saConnectionExecuteCall ( sql ) ) }
117+
118+ override DataFlow:: Node getSql ( ) { result = sql }
119+ }
74120}
0 commit comments