Skip to content

Commit ecdb963

Browse files
Migrate from psycopg2 to psycopg3
psycopg3 is mostly built as a drop-in upgrade from psycopg2. Differences are detailed here: https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html A few highlights: * Cancelling running queries One major DX improvement is that Ctrl-C can now cancel a running query. With psycopg2, the python process can be killed but a running query usually could not be killed (without knowing the PID and running `pg_cancel_backend(pid)` from a separate connection), to the immediate regret of all we who sometimes accidentally execute an unfortunately large query. See https://www.psycopg.org/psycopg3/docs/advanced/async.html#interrupting-async-operations * Breaking changes to parameterization A few parameterization patterns that worked with psycopg2 no longer work with psycopg3. They are detailed on the migration guide linked above, but these in particular should be highlighted: ** You can no longer use `IN %s` with a tuple This would work with psycopg2 but will not work with psycopg3: `conn.execute("SELECT * FROM foo WHERE id IN %s", parameters=[(10,20,30)])` Instead, this format is advised: `conn.execute("SELECT * FROM foo WHERE id = ANY(%s)", parameters=[[10,20,30]])` ** You can no longer use `IS %s` This would work with psycopg2 but will not work with psycopg3: `conn.execute("SELECT * FROM foo WHERE field IS %s", [None])` Instead, `IS NOT DISTINCT FROM %s` should be used `conn.execute("SELECT * FROM foo WHERE field IS NOT DISTINCT FROM %s", [None])` * Breaking changes to psycopg2 `copy` methods `copy` methods are refactored and consolidated in psycopg3. See the migration guide for details.
1 parent 9da2ebc commit ecdb963

File tree

3 files changed

+11
-9
lines changed

3 files changed

+11
-9
lines changed

parsons/databases/redshift/redshift.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
from parsons.databases.alchemy import Alchemy
99
from parsons.utilities import files, sql_helpers
1010
from parsons.databases.database_connector import DatabaseConnector
11-
import psycopg2
12-
import psycopg2.extras
11+
import psycopg
1312
import os
1413
import logging
1514
import json
@@ -128,11 +127,14 @@ def connection(self):
128127
``with rs.connection() as conn:``
129128
130129
`Returns:`
131-
Psycopg2 ``connection`` object
130+
Psycopg ``connection`` object
132131
"""
132+
# Redshift unicode encoding doesn't work out of the box with psycopg3
133+
# See https://github.com/psycopg/psycopg/issues/122#issuecomment-1272352650
134+
os.environ["PGCLIENTENCODING"] = "utf-8"
133135

134-
# Create a psycopg2 connection and cursor
135-
conn = psycopg2.connect(
136+
# Create a psycopg connection and cursor
137+
conn = psycopg.connect(
136138
user=self.username,
137139
password=self.password,
138140
host=self.host,
@@ -149,7 +151,7 @@ def connection(self):
149151

150152
@contextmanager
151153
def cursor(self, connection):
152-
cur = connection.cursor(cursor_factory=psycopg2.extras.DictCursor)
154+
cur = connection.cursor(row_factory=psycopg.rows.dict_row)
153155
try:
154156
yield cur
155157
finally:

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ boto3>=1.17.98
44
boxsdk==2.10.0
55
civis==1.16.0
66
slackclient==1.3.0
7-
psycopg2-binary==2.9.3
7+
psycopg[c]==3.1.18
88
xmltodict==0.11.0
99
gspread==3.7.0
1010
oauth2client==4.1.3

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ def main():
4444
"newmode": ["newmode"],
4545
"ngpvan": ["suds-py3"],
4646
"mobilecommons": ["bs4"],
47-
"postgres": ["psycopg2-binary", "SQLAlchemy"],
48-
"redshift": ["boto3", "psycopg2-binary", "SQLAlchemy"],
47+
"postgres": ["psycopg[c]", "SQLAlchemy"],
48+
"redshift": ["boto3", "psycopg[c]", "SQLAlchemy"],
4949
"s3": ["boto3"],
5050
"salesforce": ["simple-salesforce"],
5151
"sftp": ["paramiko"],

0 commit comments

Comments
 (0)