@@ -52,6 +52,8 @@ module PEP249 {
5252 result in [ "sql" , "statement" , "operation" , "query" , "query_string" , "sql_script" ]
5353 }
5454
55+ private string getExecuteMethodName ( ) { result in [ "execute" , "executemany" , "executescript" ] }
56+
5557 /**
5658 * A call to an execute method on a database cursor or a connection, such as `execute`
5759 * or `executemany`.
@@ -68,7 +70,7 @@ module PEP249 {
6870 exists ( API:: Node start |
6971 start instanceof DatabaseCursor or start instanceof DatabaseConnection
7072 |
71- this = start .getMember ( [ "execute" , "executemany" , "executescript" ] ) .getACall ( )
73+ this = start .getMember ( getExecuteMethodName ( ) ) .getACall ( )
7274 )
7375 }
7476
@@ -77,6 +79,82 @@ module PEP249 {
7779 }
7880 }
7981
82+ // ---------------------------------------------------------------------------
83+ // asyncio implementations
84+ // ---------------------------------------------------------------------------
85+ //
86+ // we differentiate between normal and asyncio implementations, since we model the
87+ // `execute` call differently -- as a SqlExecution vs SqlConstruction, since the SQL
88+ // is only executed in asyncio after being awaited (which might happen in something
89+ // like `asyncio.gather`)
90+ /**
91+ * An API graph node representing a module that implements PEP 249 using asyncio.
92+ */
93+ abstract class AsyncPEP249ModuleApiNode extends API:: Node {
94+ /** Gets a string representation of this element. */
95+ override string toString ( ) { result = this .( API:: Node ) .toString ( ) }
96+ }
97+
98+ /**
99+ * An API graph node representing a asyncio database connection (after being awaited).
100+ */
101+ abstract class AsyncDatabaseConnection extends API:: Node {
102+ /** Gets a string representation of this element. */
103+ override string toString ( ) { result = this .( API:: Node ) .toString ( ) }
104+ }
105+
106+ private class DefaultAsyncDatabaseConnection extends AsyncDatabaseConnection {
107+ DefaultAsyncDatabaseConnection ( ) {
108+ this = any ( AsyncPEP249ModuleApiNode mod ) .getMember ( "connect" ) .getReturn ( ) .getAwaited ( )
109+ }
110+ }
111+
112+ /**
113+ * An API graph node representing a asyncio database cursor (after being awaited).
114+ */
115+ abstract class AsyncDatabaseCursor extends API:: Node {
116+ /** Gets a string representation of this element. */
117+ override string toString ( ) { result = this .( API:: Node ) .toString ( ) }
118+ }
119+
120+ private class DefaultAsyncDatabaseCursor extends AsyncDatabaseCursor {
121+ DefaultAsyncDatabaseCursor ( ) {
122+ this = any ( AsyncDatabaseConnection conn ) .getMember ( "cursor" ) .getReturn ( ) .getAwaited ( )
123+ }
124+ }
125+
126+ /**
127+ * A call to an execute method on an asyncio database cursor or an asyncio connection,
128+ * such as `execute` or `executemany`.
129+ *
130+ * (This is not an SqlExecution, since that only happens when the coroutine is
131+ * awaited)
132+ *
133+ * See ExecuteMethodCall for more details.
134+ */
135+ private class AsyncExecuteMethodCall extends SqlConstruction:: Range , API:: CallNode {
136+ AsyncExecuteMethodCall ( ) {
137+ exists ( API:: Node start |
138+ start instanceof AsyncDatabaseCursor or start instanceof AsyncDatabaseConnection
139+ |
140+ this = start .getMember ( getExecuteMethodName ( ) ) .getACall ( )
141+ )
142+ }
143+
144+ override DataFlow:: Node getSql ( ) {
145+ result in [ this .getArg ( 0 ) , this .getArgByName ( getSqlKwargName ( ) ) , ]
146+ }
147+ }
148+
149+ /** Actual execution of the AsyncExecuteMethodCall coroutine. */
150+ private class AwaitedAsyncExecuteMethodCall extends SqlExecution:: Range {
151+ AsyncExecuteMethodCall execute ;
152+
153+ AwaitedAsyncExecuteMethodCall ( ) { this = execute .getReturn ( ) .getAwaited ( ) .asSource ( ) }
154+
155+ override DataFlow:: Node getSql ( ) { result = execute .getSql ( ) }
156+ }
157+
80158 // ---------------------------------------------------------------------------
81159 // old impl
82160 // ---------------------------------------------------------------------------
0 commit comments