@@ -83,7 +83,9 @@ def test_normative_catalog_compiles_for_every_sql_family() -> None:
8383 [
8484 ("mysql" , "8.4.6" , True ), ("mysql" , "9.7.0" , True ),
8585 ("mysql" , "8.0.44" , False ),
86- ("dolt" , "2.2.2" , True ), ("dolt" , "2.2.3" , False ),
86+ ("dolt" , "2.2.2" , True ), ("dolt" , " 2.2.2 " , True ),
87+ ("dolt" , "2.2.3" , False ), ("dolt" , "2.2.2-rc1" , False ),
88+ ("dolt" , "2.2.2+build.1" , False ), ("dolt" , "garbage" , False ),
8789 ("mariadb" , "11.4.8-MariaDB" , True ),
8890 ("mariadb" , "11.8.3-MariaDB" , True ),
8991 ("mariadb" , "12.3.1-MariaDB" , True ),
@@ -223,6 +225,25 @@ def test_dolt_comment_requires_a_nonempty_product_version(monkeypatch) -> None:
223225 active_connection ("mysql+pymysql://user@host/database" )
224226
225227
228+ @pytest .mark .parametrize (
229+ "product_version" ,
230+ ["2.2.2-rc1" , "2.2.2+build.1" , "v2.2.2" , "garbage" ],
231+ )
232+ def test_dolt_identity_rejects_nonexact_product_versions (
233+ monkeypatch , product_version ,
234+ ) -> None :
235+ connection = _mock_mysql_probes (
236+ monkeypatch , ** {"select DOLT_VERSION()" : product_version },
237+ )
238+
239+ with pytest .raises (UnsupportedOperationError , match = "exactly 2.2.2" ):
240+ active_connection ("mysql+pymysql://user@host/database" )
241+
242+ assert connection .calls == [
243+ "select @@version" , "select @@version_comment" , "select DOLT_VERSION()" ,
244+ ]
245+
246+
226247def test_unknown_mysql_wire_product_fails_closed_without_dolt_probe (monkeypatch ) -> None :
227248 connection = _mock_mysql_probes (
228249 monkeypatch ,
@@ -268,6 +289,7 @@ def test_effective_profile_selects_dolt_without_changing_url_profile(monkeypatch
268289 assert profile .name == "dolt"
269290 assert profile .url_schemes == ()
270291 assert profile .max_physical_variables == 305
292+ assert profile .max_text_value_bytes == 65_504
271293 assert profile .max_row_bytes == 65_504
272294 assert observed is active
273295
@@ -281,22 +303,32 @@ def test_dolt_declaration_labels_conservative_envelopes() -> None:
281303 assert declaration ["ci_tested_server_versions" ] == ["Dolt 2.2.2" ]
282304 assert declaration ["proposed_adapter_limits" ]["maximum_physical_columns" ] == 306
283305 assert declaration ["proposed_adapter_limits" ]["maximum_source_variables" ] == 305
306+ assert declaration ["proposed_adapter_limits" ]["maximum_value_bytes" ] == 65_504
284307 assert declaration ["proposed_adapter_limits" ]["maximum_row_bytes" ] == 65_504
308+ assert declaration ["theoretical_limits" ]["maximum_value_bytes" ] == 4_294_967_295
285309 assert declaration ["observed_limits" ]["minimum_observed_physical_columns" ] == 307
286310 assert declaration ["observed_limits" ]["identifier_limit" ]["value" ] == 64
287311 assert declaration ["observed_limits" ]["rejected_identifier_bytes" ] == 65
288312 assert set (declaration ["proposed_adapter_limits" ]) == {
289- "maximum_physical_columns" , "maximum_source_variables" , "maximum_row_bytes" ,
313+ "maximum_physical_columns" , "maximum_source_variables" ,
314+ "maximum_value_bytes" , "maximum_row_bytes" ,
290315 }
291316 assert declaration ["limit_bases" ]["maximum_physical_columns" ] == "proposed_adapter_envelope"
292317 assert declaration ["limit_bases" ]["identifier_limit" ] == "observed_exact_version"
318+ assert declaration ["limit_bases" ]["maximum_value_bytes" ] == "observed_exact_version"
293319 assert declaration ["limit_bases" ]["maximum_statement_bytes" ] == "active_connection_observation"
294320 assert declaration ["effective_limits" ] is None
295321 assert declaration ["text_type" ] == "LONGTEXT"
296322 assert capabilities .profile_declarations ()["mysql" ]["text_type" ] == "LONGTEXT"
297323 assert capabilities .profile_declarations ()["mariadb" ]["text_type" ] == "LONGTEXT"
298324 assert declaration ["ddl_atomic" ] is False
299325 assert declaration ["failure_cleanup" ] == "compensating_cleanup"
326+ assert declaration ["numeric_value_policy" ] == {
327+ "finite_binary64" : "supported" ,
328+ "nan" : "rejected_before_ddl" ,
329+ "positive_infinity" : "rejected_before_ddl" ,
330+ "negative_infinity" : "rejected_before_ddl" ,
331+ }
300332 assert declaration ["storage_evidence" ]["binary64" ]["maximum_finite_round_trip_exact" ] is True
301333 assert declaration ["storage_evidence" ]["binary64" ]["source" ]
302334 assert declaration ["storage_evidence" ]["binary64" ]["version" ] == "2.2.2"
@@ -320,13 +352,30 @@ def test_dolt_uses_longtext_without_changing_mysql_storage() -> None:
320352def test_dolt_row_preflight_counts_utf8_values_against_adapter_envelope () -> None :
321353 variables = [{
322354 "ordinal" : 1 , "source_name" : "value" , "physical_name" : "value" ,
323- "storage_kind" : "string" , "string_width" : 65_496 ,
355+ "storage_kind" : "string" , "string_width" : 65_504 ,
324356 }]
325- preflight (DOLT , variables , rows = [{"value" : "x" * 65_496 }])
357+ preflight (DOLT , variables , rows = [{"value" : "x" * 65_504 }])
326358
327359 with pytest .raises (UnsupportedOperationError ) as error :
328- preflight (DOLT , variables , rows = [{"value" : "x" * 65_497 }])
329- assert error .value .details ["reason" ] == "row_size_limit"
360+ preflight (DOLT , variables , rows = [{"value" : "x" * 65_505 }])
361+ assert error .value .details ["reason" ] == "text_value_limit"
362+
363+
364+ @pytest .mark .parametrize ("value" , [float ("nan" ), float ("inf" ), float ("-inf" )])
365+ def test_dolt_numeric_preflight_rejects_nonfinite_values (value ) -> None :
366+ variables = [{
367+ "ordinal" : 1 , "source_name" : "value" , "physical_name" : "value" ,
368+ "storage_kind" : "numeric" , "string_width" : None ,
369+ }]
370+
371+ with pytest .raises (UnsupportedOperationError ) as error :
372+ preflight (DOLT , variables , rows = [{"value" : value }])
373+
374+ assert error .value .details == {
375+ "reason" : "nonfinite_numeric_value" ,
376+ "row_ordinal" : 1 ,
377+ "source_name" : "value" ,
378+ }
330379
331380
332381def test_validate_identity_failure_happens_before_catalog_access (monkeypatch ) -> None :
0 commit comments