From f3e0405c12d431c09df3994619ee895e767990df Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Mon, 14 Apr 2025 18:43:52 +0900 Subject: [PATCH 1/2] [SPARK-51793] Support `ddlParse` and `jsonToDdl` in `SparkConnectClient` --- Sources/SparkConnect/SparkConnectClient.swift | 42 +++++++++++++++++++ .../SparkConnectClientTests.swift | 18 ++++++++ 2 files changed, 60 insertions(+) diff --git a/Sources/SparkConnect/SparkConnectClient.swift b/Sources/SparkConnect/SparkConnectClient.swift index d11c4d9..1e8087c 100644 --- a/Sources/SparkConnect/SparkConnectClient.swift +++ b/Sources/SparkConnect/SparkConnectClient.swift @@ -438,4 +438,46 @@ public actor SparkConnectClient { public func clearTags() { tags.removeAll() } + + /// Parse a DDL string to ``Spark_Connect_DataType`` instance. + /// - Parameter ddlString: A string to parse. + /// - Returns: A ``Spark_Connect_DataType`` instance. + func ddlParse(_ ddlString: String) async throws -> Spark_Connect_DataType { + try await withGRPCClient( + transport: .http2NIOPosix( + target: .dns(host: self.host, port: self.port), + transportSecurity: .plaintext + ) + ) { client in + let service = SparkConnectService.Client(wrapping: client) + let request = analyze(self.sessionID!, { + var ddlParse = AnalyzePlanRequest.DDLParse() + ddlParse.ddlString = ddlString + return OneOf_Analyze.ddlParse(ddlParse) + }) + let response = try await service.analyzePlan(request) + return response.ddlParse.parsed + } + } + + /// Convert an JSON string to a DDL string. + /// - Parameter jsonString: A JSON string. + /// - Returns: A DDL string. + func jsonToDdl(_ jsonString: String) async throws -> String { + try await withGRPCClient( + transport: .http2NIOPosix( + target: .dns(host: self.host, port: self.port), + transportSecurity: .plaintext + ) + ) { client in + let service = SparkConnectService.Client(wrapping: client) + let request = analyze(self.sessionID!, { + var jsonToDDL = AnalyzePlanRequest.JsonToDDL() + jsonToDDL.jsonString = jsonString + return OneOf_Analyze.jsonToDdl(jsonToDDL) + }) + let response = try await service.analyzePlan(request) + return response.jsonToDdl.ddlString + } + } } diff --git a/Tests/SparkConnectTests/SparkConnectClientTests.swift b/Tests/SparkConnectTests/SparkConnectClientTests.swift index 965fb53..365d11a 100644 --- a/Tests/SparkConnectTests/SparkConnectClientTests.swift +++ b/Tests/SparkConnectTests/SparkConnectClientTests.swift @@ -62,4 +62,22 @@ struct SparkConnectClientTests { #expect(await client.getExecutePlanRequest(plan).tags.isEmpty) await client.stop() } + + @Test + func ddlParse() async throws { + let client = SparkConnectClient(remote: "sc://localhost", user: "test") + let _ = try await client.connect(UUID().uuidString) + #expect(try await client.ddlParse("a int").simpleString == "struct") + await client.stop() + } + + @Test + func jsonToDdl() async throws { + let client = SparkConnectClient(remote: "sc://localhost", user: "test") + let _ = try await client.connect(UUID().uuidString) + let json = + #"{"type":"struct","fields":[{"name":"id","type":"long","nullable":false,"metadata":{}}]}"# + #expect(try await client.jsonToDdl(json) == "id BIGINT NOT NULL") + await client.stop() + } } From a56777492fb1eb75b0acf079f2beb0ab7fdec50d Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Mon, 14 Apr 2025 21:03:23 +0900 Subject: [PATCH 2/2] Disable test on Spark 4.0.0-preview2 --- Tests/SparkConnectTests/SparkConnectClientTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/SparkConnectTests/SparkConnectClientTests.swift b/Tests/SparkConnectTests/SparkConnectClientTests.swift index 365d11a..13dbf4d 100644 --- a/Tests/SparkConnectTests/SparkConnectClientTests.swift +++ b/Tests/SparkConnectTests/SparkConnectClientTests.swift @@ -71,6 +71,7 @@ struct SparkConnectClientTests { await client.stop() } +#if !os(Linux) // TODO: Enable this with the offical Spark 4 docker image @Test func jsonToDdl() async throws { let client = SparkConnectClient(remote: "sc://localhost", user: "test") @@ -80,4 +81,5 @@ struct SparkConnectClientTests { #expect(try await client.jsonToDdl(json) == "id BIGINT NOT NULL") await client.stop() } +#endif }