Skip to content

Commit f4f7d88

Browse files
committed
[Storage] Extend UCDeltaClient with table-loading ops + exceptions
- loadTable / createStagingTable / createTable now take TableIdentifier; createTable takes AbstractMetadata + AbstractProtocol (mirrors commit()). - TableInfo realigned with StagingTableInfo (tableId field + ordering). - New typed exceptions: CredentialFetchFailedException, NoSuchTableException, UnsupportedTableFormatException. - build.sbt: conditional unitycatalog-hadoop dep gated on UC version >= 0.5.0 via a small isAtLeastVersion helper. Signed-off-by: Yi Li <yi.li@databricks.com>
1 parent 98a0d51 commit f4f7d88

8 files changed

Lines changed: 497 additions & 35 deletions

File tree

build.sbt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,23 @@ val unityCatalogVersion: String = sys.props.getOrElse(
791791
if (useDefaultUnityCatalogReleaseVersion) defaultUnityCatalogReleaseVersion
792792
else unityCatalogReleaseVersion.getOrElse(pinnedUnityCatalogVersion))
793793

794+
/**
795+
* Returns true when `current` is at least `target`. Numeric segments only; suffix after
796+
* the first `-` (e.g. `-SNAPSHOT-abc1234`) is stripped before comparison.
797+
*/
798+
def isAtLeastVersion(current: String, target: String): Boolean = {
799+
def parts(v: String): Seq[Int] =
800+
v.takeWhile(_ != '-').split('.').iterator
801+
.map(p => scala.util.Try(p.toInt).getOrElse(0)).toSeq
802+
val cur = parts(current)
803+
val tgt = parts(target)
804+
val n = math.max(cur.length, tgt.length)
805+
(0 until n).iterator
806+
.map(i => (cur.lift(i).getOrElse(0), tgt.lift(i).getOrElse(0)))
807+
.find { case (a, b) => a != b }
808+
.forall { case (a, b) => a >= b }
809+
}
810+
794811
val sparkUnityCatalogJacksonVersion = "2.15.4" // We are using Spark 4.0's Jackson version 2.15.x, to override Unity Catalog 0.3.0's version 2.18.x
795812

796813
// Publishes the pinned UC jars to ~/.ivy2/local if they're not already cached there. Hooked
@@ -1217,6 +1234,19 @@ lazy val storage = (project in file("storage"))
12171234
"org.scalatest" %% "scalatest" % scalaTestVersion % "test",
12181235
// Jackson datatype module needed for UC SDK tests (excluded from main compile scope)
12191236
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.15.4" % "test",
1237+
) ++ (
1238+
// unitycatalog-hadoop ships from UC 0.5.0 onward; older versions don't publish the
1239+
// artifact, so resolving it would fail. Used by UCDeltaTokenBasedRestClient for
1240+
// credential vending via UCCredentialHadoopConfs.
1241+
if (isAtLeastVersion(unityCatalogVersion, "0.5.0")) {
1242+
Seq("io.unitycatalog" % "unitycatalog-hadoop" % unityCatalogVersion excludeAll(
1243+
ExclusionRule(organization = "org.openapitools"),
1244+
ExclusionRule(organization = "com.fasterxml.jackson.core"),
1245+
ExclusionRule(organization = "com.fasterxml.jackson.module"),
1246+
ExclusionRule(organization = "com.fasterxml.jackson.datatype"),
1247+
ExclusionRule(organization = "com.fasterxml.jackson.dataformat")
1248+
))
1249+
} else Nil
12201250
),
12211251

12221252
// Publish the pinned UC jars before sbt tries to resolve them. storage is the transitive

storage/src/main/java/io/delta/storage/commit/uccommitcoordinator/UCDeltaClient.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
package io.delta.storage.commit.uccommitcoordinator;
1818

19+
import io.delta.storage.commit.TableIdentifier;
1920
import io.delta.storage.commit.actions.AbstractMetadata;
2021
import io.delta.storage.commit.uccommitcoordinator.UCDeltaModels.StagingTableInfo;
22+
import io.delta.storage.commit.uccommitcoordinator.UCDeltaModels.TableInfo;
2123
import java.io.IOException;
2224
import java.util.List;
2325
import java.util.Map;
@@ -31,13 +33,12 @@ public interface UCDeltaClient extends UCClient {
3133
/**
3234
* Loads a table's metadata from Unity Catalog.
3335
*
34-
* @param catalog the catalog name
35-
* @param schema the schema name
36-
* @param table the table name
37-
* @return the table's {@link AbstractMetadata}
36+
* @param tableIdentifier catalog + schema namespace and table name
37+
* @return the table's {@link TableInfo}, carrying the catalog-supplied storage location and
38+
* metadata
3839
* @throws IOException on network or API errors
3940
*/
40-
AbstractMetadata loadTable(String catalog, String schema, String table) throws IOException;
41+
TableInfo loadTable(TableIdentifier tableIdentifier) throws IOException;
4142

4243
/**
4344
* Reserves a staging slot for a new Delta table. The returned response contains the table ID,

storage/src/main/java/io/delta/storage/commit/uccommitcoordinator/UCDeltaModels.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@
1616

1717
package io.delta.storage.commit.uccommitcoordinator;
1818

19+
import io.delta.storage.commit.actions.AbstractMetadata;
1920
import io.delta.storage.commit.actions.AbstractProtocol;
2021
import java.util.Collection;
2122
import java.util.Collections;
2223
import java.util.HashSet;
2324
import java.util.Map;
2425
import java.util.Objects;
2526
import java.util.Set;
27+
import java.util.UUID;
2628

2729
/**
28-
* Delta-owned models for the UC Delta REST Catalog API. These decouple the {@link UCDeltaClient}
30+
* Delta-owned models for the UC Delta REST API. These decouple the {@link UCDeltaClient}
2931
* interface from any generated SDK types.
3032
*/
3133
public final class UCDeltaModels {
@@ -101,9 +103,54 @@ public int hashCode() {
101103
}
102104
}
103105

106+
/** Result of {@link UCDeltaClient#loadTable}. */
107+
public static final class TableInfo {
108+
109+
private final UUID tableId;
110+
private final TableType tableType;
111+
private final String location;
112+
private final AbstractMetadata metadata;
113+
private final Map<String, String> storageProperties;
114+
115+
public TableInfo(
116+
UUID tableId,
117+
TableType tableType,
118+
String location,
119+
AbstractMetadata metadata,
120+
Map<String, String> storageProperties) {
121+
this.tableId = tableId;
122+
this.tableType = tableType;
123+
this.location = location;
124+
this.metadata = metadata;
125+
this.storageProperties = storageProperties;
126+
}
127+
128+
/** UC's {@code table_uuid}; distinct from {@link AbstractMetadata#getId()} (the Delta id). */
129+
public UUID getTableId() {
130+
return tableId;
131+
}
132+
133+
public TableType getTableType() {
134+
return tableType;
135+
}
136+
137+
public String getLocation() {
138+
return location;
139+
}
140+
141+
public AbstractMetadata getMetadata() {
142+
return metadata;
143+
}
144+
145+
/** Hadoop-style storage options (e.g. catalog-vended credentials). */
146+
public Map<String, String> getStorageProperties() {
147+
return storageProperties == null ? Collections.emptyMap() : storageProperties;
148+
}
149+
}
150+
104151
public static final class StagingTableInfo {
105152

106-
private final String tableId;
153+
private final UUID tableId;
107154
private final TableType tableType;
108155
private final String location;
109156
private final DeltaProtocol requiredProtocol;
@@ -112,7 +159,7 @@ public static final class StagingTableInfo {
112159
private final Map<String, String> suggestedProperties;
113160

114161
public StagingTableInfo(
115-
String tableId,
162+
UUID tableId,
116163
TableType tableType,
117164
String location,
118165
DeltaProtocol requiredProtocol,
@@ -128,7 +175,7 @@ public StagingTableInfo(
128175
this.suggestedProperties = suggestedProperties;
129176
}
130177

131-
public String getTableId() {
178+
public UUID getTableId() {
132179
return tableId;
133180
}
134181

0 commit comments

Comments
 (0)