Improved row processing performance for "binary" datatypes by making the
"bytes" handler conditional on a per driver basis. As a result, the
"bytes" result handler has been disabled for nearly all drivers other than
psycopg2, all of which in modern forms support returning Python "bytes"
directly. Pull request courtesy J. Nick Koston.
Fixes: #9680
Closes: #9681
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/9681
Pull-request-sha:
4f2fd88bd9af54c54438a3b72a2f30384b0f8898
Change-Id: I394bdcbebaab272e63b13cc02f60813b7aa76839
--- /dev/null
+.. change::
+ :tags: performance, sql
+ :tickets: 9680
+
+ Improved row processing performance for "binary" datatypes by making the
+ "bytes" handler conditional on a per driver basis. As a result, the
+ "bytes" result handler has been disabled for nearly all drivers other than
+ psycopg2, all of which in modern forms support returning Python "bytes"
+ directly. Pull request courtesy J. Nick Koston.
if self.convert_int:
def process(value):
- value = super_(value)
+ if super_:
+ value = super_(value)
if value is not None:
# https://stackoverflow.com/a/30403242/34549
value = int(codecs.encode(value, "hex"), 16)
supports_empty_insert = False
favor_returning_over_lastrowid = True
+ returns_native_bytes = True
+
supports_comments = True
supports_default_metavalue = False
"""dialect supports INSERT... VALUES (DEFAULT) syntax -
supports_native_enum = True
+ returns_native_bytes = True
+
supports_sequences = False # default for MySQL ...
# ... may be updated to True for MariaDB 10.3+ in initialize()
supports_simple_order_by_label = False
cte_follows_insert = True
+ returns_native_bytes = True
supports_sequences = True
sequences_optional = False
postfetch_lastrowid = False
use_insertmanyvalues = True
+ returns_native_bytes = True
+
insertmanyvalues_implicit_sentinel = (
InsertmanyvaluesSentinelOpts.ANY_AUTOINCREMENT
| InsertmanyvaluesSentinelOpts.USE_INSERT_FROM_SELECT
psycopg2_version = (0, 0)
use_insertmanyvalues_wo_returning = True
+ returns_native_bytes = False
+
_has_native_hstore = True
colspecs = util.update_copy(
class SQLiteDialect_pysqlite(SQLiteDialect):
default_paramstyle = "qmark"
supports_statement_cache = True
+ returns_native_bytes = True
colspecs = util.update_copy(
SQLiteDialect.colspecs,
supports_native_enum = False
supports_native_boolean = False
supports_native_uuid = False
+ returns_native_bytes = False
+
non_native_boolean_check_constraint = True
supports_simple_order_by_label = True
"""
+ returns_native_bytes: bool
+ """indicates if Python bytes() objects are returned natively by the
+ driver for SQL "binary" datatypes.
+
+ .. versionadded:: 2.0.11
+
+ """
+
construct_arguments: Optional[
List[Tuple[Type[Union[SchemaItem, ClauseElement]], Mapping[str, Any]]]
] = None
# both sqlite3 and pg8000 seem to return it,
# psycopg2 as of 2.5 returns 'memoryview'
def result_processor(self, dialect, coltype):
+ if dialect.returns_native_bytes:
+ return None
+
def process(value):
if value is not None:
value = bytes(value)
class BinaryTest(_LiteralRoundTripFixture, fixtures.TablesTest):
- __requires__ = ("binary_literals",)
__backend__ = True
@classmethod
Column("pickle_data", PickleType),
)
- def test_binary_roundtrip(self, connection):
+ @testing.combinations(b"this is binary", b"7\xe7\x9f", argnames="data")
+ def test_binary_roundtrip(self, connection, data):
binary_table = self.tables.binary_table
connection.execute(
- binary_table.insert(), {"id": 1, "binary_data": b"this is binary"}
+ binary_table.insert(), {"id": 1, "binary_data": data}
)
row = connection.execute(select(binary_table.c.binary_data)).first()
- eq_(row, (b"this is binary",))
+ eq_(row, (data,))
def test_pickle_roundtrip(self, connection):
binary_table = self.tables.binary_table