Skip to content

Commit f89fae3

Browse files
authored
Merge pull request #20276 from github/tausbn/python-model-psycopg2-connection-pools
Python: Add support for Psycopg2 database connection pools
2 parents 7c5b04a + 1008ca9 commit f89fae3

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
- The modelling of Psycopg2 now supports the use of `psycopg2.pool` connection pools for handling database connections.

python/ql/lib/semmle/python/frameworks/Psycopg2.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,17 @@ private module Psycopg2 {
2929
class Psycopg2 extends PEP249::PEP249ModuleApiNode {
3030
Psycopg2() { this = API::moduleImport("psycopg2") }
3131
}
32+
33+
/** A database connection obtained from a psycopg2 connection pool. */
34+
class Psycopg2ConnectionPoolMember extends PEP249::DatabaseConnection {
35+
Psycopg2ConnectionPoolMember() {
36+
this =
37+
any(Psycopg2 p)
38+
.getMember("pool")
39+
.getMember(["SimpleConnectionPool", "ThreadedConnectionPool", "AbstractConnectionPool"])
40+
.getAnInstance()
41+
.getMember("getconn")
42+
.getReturn()
43+
}
44+
}
3245
}

python/ql/test/library-tests/frameworks/psycopg2/ConceptsTest.expected

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import python
2+
import experimental.meta.ConceptsTest
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Examples using psycopg2 connection pools.
2+
3+
import psycopg2
4+
from psycopg2.pool import SimpleConnectionPool, AbstractConnectionPool
5+
6+
7+
DSN = "dbname=test user=test password=test host=localhost port=5432"
8+
9+
10+
def run_simple_pool_query():
11+
pool = SimpleConnectionPool(1, 4, dsn=DSN)
12+
try:
13+
conn = pool.getconn()
14+
try:
15+
cur = conn.cursor()
16+
try:
17+
# Simple, parameterless query
18+
cur.execute("SELECT 1") # $ getSql="SELECT 1"
19+
_ = cur.fetchall() if hasattr(cur, "fetchall") else None # $ threatModelSource[database]=cur.fetchall()
20+
finally:
21+
cur.close()
22+
finally:
23+
pool.putconn(conn)
24+
finally:
25+
pool.closeall()
26+
27+
28+
class LocalPool(AbstractConnectionPool):
29+
pass
30+
31+
32+
def run_custom_pool_query():
33+
pool = LocalPool(1, 3, dsn=DSN)
34+
try:
35+
conn = pool.getconn()
36+
try:
37+
cur = conn.cursor()
38+
try:
39+
cur.execute("SELECT 2") # $ getSql="SELECT 2"
40+
_ = cur.fetchone() if hasattr(cur, "fetchone") else None # $ threatModelSource[database]=cur.fetchone()
41+
finally:
42+
cur.close()
43+
finally:
44+
pool.putconn(conn)
45+
finally:
46+
pool.closeall()

0 commit comments

Comments
 (0)