Original file line numberDiff line numberDiff line change@@ -7,6 +7,10 @@
77# future enhancements, you should normally quote any identifier that
88# is an English language word, even if you do not have to."
9910+11+fromcontextlibimportcontextmanager
12+13+1014def_quote_name(name):
1115return'"{0}"'.format(name.replace('"', '""'))
1216@@ -15,6 +19,24 @@ def _quote_value(value):
1519return"'{0}'".format(value.replace("'", "''"))
1620172122+def_force_decode(bs, *args, **kwargs):
23+# gh-108590: Don't fail if the database contains invalid Unicode data.
24+try:
25+returnbs.decode(*args, **kwargs)
26+exceptUnicodeDecodeError:
27+return"".join([chr(c) forcinbs])
28+29+30+@contextmanager
31+def_text_factory(con, factory):
32+saved_factory=con.text_factory
33+con.text_factory=factory
34+try:
35+yield
36+finally:
37+con.text_factory=saved_factory
38+39+1840def_iterdump(connection):
1941"""
2042 Returns an iterator to the dump of the database in an SQL text format.
@@ -74,8 +96,9 @@ def _iterdump(connection):
7496 )
7597 )
7698query_res=cu.execute(q)
77-forrowinquery_res:
78-yield("{0};".format(row[0]))
99+with_text_factory(connection, bytes):
100+forrowinquery_res:
101+yield("{0};".format(_force_decode(row[0])))
7910280103# Now when the type is 'index', 'trigger', or 'view'
81104q="""