1919import pytest
2020from datafusion import SessionContext
2121from datafusion import substrait as ss
22- from substrait import plan_pb2
23- from google .protobuf import json_format
22+
2423
2524@pytest .fixture
2625def ctx ():
@@ -77,23 +76,74 @@ def test_substrait_file_serialization(ctx, tmp_path, path_to_str):
7776 assert str (expected_logical_plan ) == str (expected_actual_plan )
7877
7978
80- def test_plan_json_stability_and_validator_compatibility (ctx ):
81- sql = "SELECT * FROM (VALUES (1, 4), (2, 5), (3, 6)) AS t(a, b)"
82-
83- expected_binary_plan = ss .Serde .serialize_bytes (sql , ctx )
84- actual_plan = ss .Serde .serialize_to_plan (sql , ctx )
85-
86- json_str = actual_plan .to_json ()
87- reconstructed_plan = ss .Plan .parse_json (json_str )
88-
89- expected_logical_plan = ss .Consumer .from_substrait_plan (ctx , actual_plan )
90- actual_logical_plan = ss .Consumer .from_substrait_plan (ctx , reconstructed_plan )
91-
92- assert str (expected_logical_plan ) == str (actual_logical_plan )
93-
94- # Verify that the JSON can be parsed by the Substrait protobuf library
95- proto_plan = plan_pb2 .Plan ()
96- json_format .Parse (json_str , proto_plan )
97- actual_binary_plan = proto_plan .SerializeToString ()
79+ def test_json_processing_round_trip (ctx : SessionContext ):
80+ ctx .register_record_batches ("t" , [[pa .record_batch ({"a" : [1 ]})]])
81+ original_logical_plan = ctx .sql ("SELECT * FROM t" ).logical_plan ()
82+
83+ substrait_plan = ss .Producer .to_substrait_plan (original_logical_plan , ctx )
84+ json_plan = substrait_plan .to_json ()
85+
86+ expected = """\
87+ "relations": [
88+ {
89+ "root": {
90+ "input": {
91+ "project": {
92+ "common": {
93+ "emit": {
94+ "outputMapping": [
95+ 1
96+ ]
97+ }
98+ },
99+ "input": {
100+ "read": {
101+ "baseSchema": {
102+ "names": [
103+ "a"
104+ ],
105+ "struct": {
106+ "types": [
107+ {
108+ "i64": {
109+ "nullability": "NULLABILITY_NULLABLE"
110+ }
111+ }
112+ ],
113+ "nullability": "NULLABILITY_REQUIRED"
114+ }
115+ },
116+ "namedTable": {
117+ "names": [
118+ "t"
119+ ]
120+ }
121+ }
122+ },
123+ "expressions": [
124+ {
125+ "selection": {
126+ "directReference": {
127+ "structField": {}
128+ },
129+ "rootReference": {}
130+ }
131+ }
132+ ]
133+ }
134+ },
135+ "names": [
136+ "a"
137+ ]
138+ }
139+ }
140+ ]"""
141+
142+ assert expected in json_plan
143+
144+ round_trip_substrait_plan = ss .Plan .from_json (json_plan )
145+ round_trip_logical_plan = ss .Consumer .from_substrait_plan (
146+ ctx , round_trip_substrait_plan
147+ )
98148
99- assert expected_binary_plan == actual_binary_plan
149+ assert round_trip_logical_plan == original_logical_plan
0 commit comments