<#3493 perf: :zap: Speed up function `to_jsonschem...
# meltano-repo-activity
g
#3493 perf: :zap: Speed up function `to_jsonschema_type` by 463% Pull request opened by codeflash-ai[bot] on <!date^1771369544^{date_short}|2026-02-17T23:05:44Z> 📄 463% (4.63x) speedup for
tojsonschematype
in
singersdk/typing.py
⏱️ Runtime :
41.6 milliseconds
→
7.39 milliseconds
(best of
58
runs) 📝 Explanation and details This optimization achieves a 462% speedup (from 41.6ms to 7.39ms) by eliminating redundant work in the
to_jsonschema_type
function, which converts SQL type names to JSON Schema type dictionaries. Key Optimizations 1. Module-level lookup table (primary improvement) • Moved
sqltype_lookup
from being recreated inside the function on every call to a module-level constant • Changed from
dict[str, dict]
to
list[tuple[str, type]]
, storing type classes rather than pre-computed dictionaries • The original code reconstructed the entire lookup dictionary (with 13 entries accessing
.type_dict
properties) on every invocation 2. Lazy dictionary generation • Instead of calling
.type_dict
upfront for all 13 type mappings, the optimized version only calls
getattr(class, "type_dict")
for the matched type • This preserves the original behavior of returning fresh dictionary objects per call (important since callers may mutate these dicts) • Reduces wasted computation when only one type mapping is needed per call 3. Micro-optimizations • Computed
type_name.lower()
once and stored in
tl
variable instead of calling
.lower()
repeatedly in the generator expression • Cached
sqltype_lookup
and
"type_dict"
string as local variables to avoid repeated global lookups • Changed from generator expression with
next()
to explicit loop for slightly better performance Runtime Impact The test results show consistent 2-5x speedups across all test cases: • Simple type lookups: ~200-400% faster (e.g.,
"int"
→ 218% faster,
"VARCHAR"
→ 191% faster) • Large-scale iterations (1000 calls): 443-537% faster, demonstrating the benefit compounds with repeated calls • SQLAlchemy type instances/classes: 165-221% faster Workload Relevance Based on
function_references
, this function is called from
sql.connector.SQLConnector.to_jsonschema_type()
, which is part of the SQL type introspection pipeline. This suggests: • Schema discovery operations that iterate over many table columns will see substantial improvements • Streaming/ETL workloads performing type conversions for each record field will benefit significantly • The optimization is particularly valuable in hot paths where schemas are frequently translated (e.g., dynamic schema generation, bulk data processing) The deprecated status of the function means new code uses
SQLToJSONSchema
, but legacy code paths still calling this function will see immediate performance benefits without any changes required. ✅ Correctness verification report: | Test | Status | | ----------------------------- | --------------- | | ⚙️ Existing Unit Tests | ✅ 8 Passed | | 🌀 Generated Regression Tests | ✅ 6145 Passed | | ⏪ Replay Tests | 🔘 None Found | | 🔎 Concolic Coverage Tests | 🔘 None Found | | 📊 Tests Coverage | 100.0% | ⚙️ Click to see Existing Unit Tests | Test File::Test Function | Original ⏱️ | Optimized ⏱️ | Speedup | | ------------------------------------------------------------ | ----------- | ------------ | ------- | | sql/test_typing.py::test_convert_sql_type_to_jsonschema_type | 70.4μs | 22.9μs | 208%✅ | 🌀 Click to see Generated Regression Tests from future import annotations import pytest # used for our unit tests import sqlalchemy.types # used to provide real SQLAlchemy TypeEngine classes from singer_sdk.typing import ( DateTimeType, IntegerType, NumberType, StringType, to_jsonschema_type, ) def test_string_input_matches_integer_type_by_substring(): # A string containing 'int' (case-insensitive) should map to IntegerType.type_dict codeflash_output = to_jsonschema_type("INT") result = codeflash_output # 14.7μs -> 4.62μs (218% faster) def test_sqlalchemy_instance_integer_maps_to_integer_type(): # An instance of sqlalchemy.types.Integer should map to IntegerType.type_dict int_instance = sqlalchemy.types.Integer() # real SQLAlchemy TypeEngine instance codeflash_output = to_jsonschema_type(int_instance) result = codeflash_output # 11.4μs -> 4.00μs (185% faster) def test_sqlalchemy_class_integer_maps_to_integer_type(): # Passing the TypeEngine class itself should also resolve to IntegerType.type_dict codeflash_output = to_jsonschema_type(sqlalchemy.types.Integer) result = codeflash_output # 11.0μs -> 3.88μs (185% faster) def test_varchar_string_matches_string_type(): # 'VARCHAR' contains the substring 'char' which should map to the StringType.type_dict codeflash_output = to_jsonschema_type("VARCHAR") result = codeflash_output # 11.3μs -> 3.88μs (191% faster) def test_unknown_string_defaults_to_string_type(): # Unknown/unsupported SQL type strings should safely fall back to string mapping codeflash_output = to_jsonschema_type("some_custom_sql_type") result = codeflash_output # 11.9μs -> 4.21μs (183% faster) def test_sqlalchemy_class_datetime_maps_to_datetime_type(): # The SQLAlchemy DateTime class should map to DateTimeType.type_dict codeflash_output = to_jsonschema_type(sqlalchemy.types.DateTime) result = codeflash_output # 10.9μs -> 4.04μs (169% faster) def test_sqlalchemy_instance_date_maps_to_date_type(): # The SQLAlchemy Date instance should map to DateType.type_dict codeflash_output = to_jsonschema_type(sqlalchemy.types.Date()) result = codeflash_output # 11.3μs -> 4.08μs (176% faster) def test_boolean_sqlalchemy_type_maps_to_boolean_type(): # The SQLAlchemy Boolean class should map to BooleanType.type_dict codeflash_output = to_jsonschema_type(sqlalchemy.types.Boolean) result = codeflash_output # 11.6μs -> 3.92μs (196% faster) def test_double_and_float_string_map_to_number_type(): # Strings containing 'double' or 'float' should map to NumberType.type_dict codeflash_output = to_jsonschema_type( "DOUBLE PRECISION" ) # 11.0μs -> 4.62μs (139% faster) codeflash_output = to_jsonschema_type( "MyFloatCol" ) # 7.88μs -> 2.04μs (286% faster) def test_timestamp_precedence_over_datetime(): # If a name contains both 'timestamp' and 'datetime' (artificial case), 'timestamp' # appears earlier in the mapping and should take precedence, mapping to DateTimeType. mixed = "MyTimeStampAndDatetimeColumn" codeflash_output = to_jsonschema_type(mixed) result = codeflash_output # 10.9μs -> 3.71μs (193% faster) def test_none_raises_typeerror_due_to_issubclass_check(): # Passing None is neither a str nor a TypeEngine instance nor a class; the function's # issubclass check will raise a TypeError (not the ValueError described in the docstring). with pytest.raises(TypeError): to_jsonschema_type(None) # 10.6μs -> 2.96μs (258% faster) def test_unrelated_builtin_class_raises_valueerror(): # Passing a plain Python class (which is not a SQLAlchemy TypeEngine subclass) should # reach the final else branch and raise ValueError per the implementation. with pytest.raises(ValueError): to_jsonschema_type(dict) # 10.8μs -> 2.79μs (285% faster) def test_unrelated_instance_int_raises_typeerror(): # Passing an unrelated instance (like an int) will cause issubclass() to be called # with a non-class argument and thus raise TypeError. with pytest.raises(TypeError): to_jsonschema_type(12345) # 10.3μs -> 2.62μs (294% faster) def test_case_insensitive_matching_for_mixed_case_strings(): # Matching sh… meltano/sdk