excludedTableFullNames;
+ /**
+ * Who to alert when anomaly detection finds unhealthy tables in this schema. Applicable to
+ * `schema` monitors only. This is the same schema alert you manage from **Manage alerts** in the
+ * Data Quality Monitoring UI, so a change made in either place shows in both.
+ *
+ * Set the recipients in `on_unhealthy_table`; `on_failure` is not supported here. Only
+ * `destination_ids` and `destination_user_ids` are supported.
+ *
+ *
On update, an update mask of `*`, `anomaly_detection_config`, or
+ * `anomaly_detection_config.notification_settings` replaces the alert's recipients with the ones
+ * in the request; omitting the field, or leaving both recipient lists empty, removes the alert.
+ * Other masks leave the alert unchanged.
+ */
+ @JsonProperty("notification_settings")
+ private NotificationSettings notificationSettings;
+
public AnomalyDetectionConfig setExcludedTableFullNames(
Collection excludedTableFullNames) {
this.excludedTableFullNames = excludedTableFullNames;
@@ -25,23 +41,34 @@ public Collection getExcludedTableFullNames() {
return excludedTableFullNames;
}
+ public AnomalyDetectionConfig setNotificationSettings(NotificationSettings notificationSettings) {
+ this.notificationSettings = notificationSettings;
+ return this;
+ }
+
+ public NotificationSettings getNotificationSettings() {
+ return notificationSettings;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AnomalyDetectionConfig that = (AnomalyDetectionConfig) o;
- return Objects.equals(excludedTableFullNames, that.excludedTableFullNames);
+ return Objects.equals(excludedTableFullNames, that.excludedTableFullNames)
+ && Objects.equals(notificationSettings, that.notificationSettings);
}
@Override
public int hashCode() {
- return Objects.hash(excludedTableFullNames);
+ return Objects.hash(excludedTableFullNames, notificationSettings);
}
@Override
public String toString() {
return new ToStringer(AnomalyDetectionConfig.class)
.add("excludedTableFullNames", excludedTableFullNames)
+ .add("notificationSettings", notificationSettings)
.toString();
}
}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationDestination.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationDestination.java
index 5a5a920aa..e776a88af 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationDestination.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationDestination.java
@@ -11,6 +11,22 @@
/** Destination of the data quality monitoring notification. */
@Generated
public class NotificationDestination {
+ /**
+ * The notification-destination IDs (Slack / Teams / webhook) to send the notification to. The
+ * destinations must already exist in the workspace; a workspace admin creates them. A maximum of
+ * 25 destination IDs is supported. Only supported on schema monitors, via
+ * `anomaly_detection_config`; rejected on table monitors.
+ */
+ @JsonProperty("destination_ids")
+ private Collection destinationIds;
+
+ /**
+ * The IDs of the workspace users to notify by email. A maximum of 25 user IDs is supported. Only
+ * supported on schema monitors, via `anomaly_detection_config`; rejected on table monitors.
+ */
+ @JsonProperty("destination_user_ids")
+ private Collection destinationUserIds;
+
/**
* The list of email addresses to send the notification to. A maximum of 5 email addresses is
* supported.
@@ -18,6 +34,24 @@ public class NotificationDestination {
@JsonProperty("email_addresses")
private Collection emailAddresses;
+ public NotificationDestination setDestinationIds(Collection destinationIds) {
+ this.destinationIds = destinationIds;
+ return this;
+ }
+
+ public Collection getDestinationIds() {
+ return destinationIds;
+ }
+
+ public NotificationDestination setDestinationUserIds(Collection destinationUserIds) {
+ this.destinationUserIds = destinationUserIds;
+ return this;
+ }
+
+ public Collection getDestinationUserIds() {
+ return destinationUserIds;
+ }
+
public NotificationDestination setEmailAddresses(Collection emailAddresses) {
this.emailAddresses = emailAddresses;
return this;
@@ -32,17 +66,21 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NotificationDestination that = (NotificationDestination) o;
- return Objects.equals(emailAddresses, that.emailAddresses);
+ return Objects.equals(destinationIds, that.destinationIds)
+ && Objects.equals(destinationUserIds, that.destinationUserIds)
+ && Objects.equals(emailAddresses, that.emailAddresses);
}
@Override
public int hashCode() {
- return Objects.hash(emailAddresses);
+ return Objects.hash(destinationIds, destinationUserIds, emailAddresses);
}
@Override
public String toString() {
return new ToStringer(NotificationDestination.class)
+ .add("destinationIds", destinationIds)
+ .add("destinationUserIds", destinationUserIds)
.add("emailAddresses", emailAddresses)
.toString();
}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationSettings.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationSettings.java
index 6f3b950b5..fc28153ef 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationSettings.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/dataquality/NotificationSettings.java
@@ -14,6 +14,14 @@ public class NotificationSettings {
@JsonProperty("on_failure")
private NotificationDestination onFailure;
+ /**
+ * Recipients to notify when anomaly detection finds unhealthy tables in the schema. Each
+ * recipient gets one notification per important unhealthy table. Only supported on schema
+ * monitors, via `anomaly_detection_config`.
+ */
+ @JsonProperty("on_unhealthy_table")
+ private NotificationDestination onUnhealthyTable;
+
public NotificationSettings setOnFailure(NotificationDestination onFailure) {
this.onFailure = onFailure;
return this;
@@ -23,21 +31,34 @@ public NotificationDestination getOnFailure() {
return onFailure;
}
+ public NotificationSettings setOnUnhealthyTable(NotificationDestination onUnhealthyTable) {
+ this.onUnhealthyTable = onUnhealthyTable;
+ return this;
+ }
+
+ public NotificationDestination getOnUnhealthyTable() {
+ return onUnhealthyTable;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NotificationSettings that = (NotificationSettings) o;
- return Objects.equals(onFailure, that.onFailure);
+ return Objects.equals(onFailure, that.onFailure)
+ && Objects.equals(onUnhealthyTable, that.onUnhealthyTable);
}
@Override
public int hashCode() {
- return Objects.hash(onFailure);
+ return Objects.hash(onFailure, onUnhealthyTable);
}
@Override
public String toString() {
- return new ToStringer(NotificationSettings.class).add("onFailure", onFailure).toString();
+ return new ToStringer(NotificationSettings.class)
+ .add("onFailure", onFailure)
+ .add("onUnhealthyTable", onUnhealthyTable)
+ .toString();
}
}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlOutput.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlOutput.java
index 0ce85de12..ba1fd2461 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlOutput.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlOutput.java
@@ -17,6 +17,10 @@ public class SqlOutput {
@JsonProperty("dashboard_output")
private SqlDashboardOutput dashboardOutput;
+ /** The output of a SQL file task, if available. */
+ @JsonProperty("file_output")
+ private SqlTaskSqlFileOutput fileOutput;
+
/** The output of a SQL query task, if available. */
@JsonProperty("query_output")
private SqlQueryOutput queryOutput;
@@ -39,6 +43,15 @@ public SqlDashboardOutput getDashboardOutput() {
return dashboardOutput;
}
+ public SqlOutput setFileOutput(SqlTaskSqlFileOutput fileOutput) {
+ this.fileOutput = fileOutput;
+ return this;
+ }
+
+ public SqlTaskSqlFileOutput getFileOutput() {
+ return fileOutput;
+ }
+
public SqlOutput setQueryOutput(SqlQueryOutput queryOutput) {
this.queryOutput = queryOutput;
return this;
@@ -55,12 +68,13 @@ public boolean equals(Object o) {
SqlOutput that = (SqlOutput) o;
return Objects.equals(alertOutput, that.alertOutput)
&& Objects.equals(dashboardOutput, that.dashboardOutput)
+ && Objects.equals(fileOutput, that.fileOutput)
&& Objects.equals(queryOutput, that.queryOutput);
}
@Override
public int hashCode() {
- return Objects.hash(alertOutput, dashboardOutput, queryOutput);
+ return Objects.hash(alertOutput, dashboardOutput, fileOutput, queryOutput);
}
@Override
@@ -68,6 +82,7 @@ public String toString() {
return new ToStringer(SqlOutput.class)
.add("alertOutput", alertOutput)
.add("dashboardOutput", dashboardOutput)
+ .add("fileOutput", fileOutput)
.add("queryOutput", queryOutput)
.toString();
}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlQueryOutput.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlQueryOutput.java
index d540662e4..7401dfe8d 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlQueryOutput.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlQueryOutput.java
@@ -14,7 +14,7 @@ public class SqlQueryOutput {
@JsonProperty("endpoint_id")
private String endpointId;
- /** The link to find the output results. */
+ /** Deprecated. The link to find the output results, which are only accessible from the UI. */
@JsonProperty("output_link")
private String outputLink;
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResult.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResult.java
new file mode 100644
index 000000000..edf16a0e4
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResult.java
@@ -0,0 +1,75 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.jobs;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+@Generated
+public class SqlStatementQueryResult {
+ /** The metadata for each column in the result set. */
+ @JsonProperty("columns")
+ private Collection columns;
+
+ /** The rows returned by the query. */
+ @JsonProperty("rows")
+ private Collection rows;
+
+ /** Whether the result set was truncated. */
+ @JsonProperty("truncated")
+ private Boolean truncated;
+
+ public SqlStatementQueryResult setColumns(Collection columns) {
+ this.columns = columns;
+ return this;
+ }
+
+ public Collection getColumns() {
+ return columns;
+ }
+
+ public SqlStatementQueryResult setRows(Collection rows) {
+ this.rows = rows;
+ return this;
+ }
+
+ public Collection getRows() {
+ return rows;
+ }
+
+ public SqlStatementQueryResult setTruncated(Boolean truncated) {
+ this.truncated = truncated;
+ return this;
+ }
+
+ public Boolean getTruncated() {
+ return truncated;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SqlStatementQueryResult that = (SqlStatementQueryResult) o;
+ return Objects.equals(columns, that.columns)
+ && Objects.equals(rows, that.rows)
+ && Objects.equals(truncated, that.truncated);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(columns, rows, truncated);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SqlStatementQueryResult.class)
+ .add("columns", columns)
+ .add("rows", rows)
+ .add("truncated", truncated)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultColumn.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultColumn.java
new file mode 100644
index 000000000..efefc4d44
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultColumn.java
@@ -0,0 +1,42 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.jobs;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+
+@Generated
+public class SqlStatementQueryResultColumn {
+ /** The name of the column. */
+ @JsonProperty("name")
+ private String name;
+
+ public SqlStatementQueryResultColumn setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SqlStatementQueryResultColumn that = (SqlStatementQueryResultColumn) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SqlStatementQueryResultColumn.class).add("name", name).toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRow.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRow.java
new file mode 100644
index 000000000..61418d6da
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRow.java
@@ -0,0 +1,44 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.jobs;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+@Generated
+public class SqlStatementQueryResultRow {
+ /** The values in the row, ordered to match the columns. */
+ @JsonProperty("values")
+ private Collection values;
+
+ public SqlStatementQueryResultRow setValues(
+ Collection values) {
+ this.values = values;
+ return this;
+ }
+
+ public Collection getValues() {
+ return values;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SqlStatementQueryResultRow that = (SqlStatementQueryResultRow) o;
+ return Objects.equals(values, that.values);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(values);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SqlStatementQueryResultRow.class).add("values", values).toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRowRowValue.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRowRowValue.java
new file mode 100644
index 000000000..ca1154bf6
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlStatementQueryResultRowRowValue.java
@@ -0,0 +1,44 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.jobs;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+
+@Generated
+public class SqlStatementQueryResultRowRowValue {
+ /** The value rendered as a string. */
+ @JsonProperty("string_value")
+ private String stringValue;
+
+ public SqlStatementQueryResultRowRowValue setStringValue(String stringValue) {
+ this.stringValue = stringValue;
+ return this;
+ }
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SqlStatementQueryResultRowRowValue that = (SqlStatementQueryResultRowRowValue) o;
+ return Objects.equals(stringValue, that.stringValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(stringValue);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SqlStatementQueryResultRowRowValue.class)
+ .add("stringValue", stringValue)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlTaskSqlFileOutput.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlTaskSqlFileOutput.java
new file mode 100644
index 000000000..c4d03bfdc
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SqlTaskSqlFileOutput.java
@@ -0,0 +1,90 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.jobs;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+@Generated
+public class SqlTaskSqlFileOutput {
+ /** The result of the executed SQL statement, if available. */
+ @JsonProperty("query_result")
+ private SqlStatementQueryResult queryResult;
+
+ /** The text of the SQL query. */
+ @JsonProperty("query_text")
+ private String queryText;
+
+ /** Information about SQL statements executed in the run. */
+ @JsonProperty("sql_statements")
+ private Collection sqlStatements;
+
+ /** The canonical identifier of the SQL warehouse. */
+ @JsonProperty("warehouse_id")
+ private String warehouseId;
+
+ public SqlTaskSqlFileOutput setQueryResult(SqlStatementQueryResult queryResult) {
+ this.queryResult = queryResult;
+ return this;
+ }
+
+ public SqlStatementQueryResult getQueryResult() {
+ return queryResult;
+ }
+
+ public SqlTaskSqlFileOutput setQueryText(String queryText) {
+ this.queryText = queryText;
+ return this;
+ }
+
+ public String getQueryText() {
+ return queryText;
+ }
+
+ public SqlTaskSqlFileOutput setSqlStatements(Collection sqlStatements) {
+ this.sqlStatements = sqlStatements;
+ return this;
+ }
+
+ public Collection getSqlStatements() {
+ return sqlStatements;
+ }
+
+ public SqlTaskSqlFileOutput setWarehouseId(String warehouseId) {
+ this.warehouseId = warehouseId;
+ return this;
+ }
+
+ public String getWarehouseId() {
+ return warehouseId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SqlTaskSqlFileOutput that = (SqlTaskSqlFileOutput) o;
+ return Objects.equals(queryResult, that.queryResult)
+ && Objects.equals(queryText, that.queryText)
+ && Objects.equals(sqlStatements, that.sqlStatements)
+ && Objects.equals(warehouseId, that.warehouseId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(queryResult, queryText, sqlStatements, warehouseId);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SqlTaskSqlFileOutput.class)
+ .add("queryResult", queryResult)
+ .add("queryText", queryText)
+ .add("sqlStatements", sqlStatements)
+ .add("warehouseId", warehouseId)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetOperation.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetOperation.java
new file mode 100644
index 000000000..bd70d3fa9
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetOperation.java
@@ -0,0 +1,164 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.core.DatabricksException;
+import com.databricks.sdk.core.logging.Logger;
+import com.databricks.sdk.core.logging.LoggerFactory;
+import com.databricks.sdk.core.utils.SerDeUtils;
+import com.databricks.sdk.service.common.lro.LroOptions;
+import com.databricks.sdk.support.Generated;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Duration;
+import java.util.Optional;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Wrapper for interacting with a long-running createMaterializationSet operation. Provides methods
+ * to wait for completion, check status, cancel, and access metadata.
+ */
+@Generated
+public class CreateMaterializationSetOperation {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(CreateMaterializationSetOperation.class);
+
+ private final FeatureEngineeringService impl;
+ private Operation operation;
+ private final ObjectMapper objectMapper;
+
+ public CreateMaterializationSetOperation(FeatureEngineeringService impl, Operation operation) {
+ this.impl = impl;
+ this.operation = operation;
+ this.objectMapper = SerDeUtils.createMapper();
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting MaterializationSet. Waits
+ * indefinitely if no timeout is specified.
+ *
+ * @return the created MaterializationSet
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public MaterializationSet waitForCompletion() throws TimeoutException {
+ return waitForCompletion(Optional.empty());
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting MaterializationSet.
+ *
+ * @param options the options for configuring the wait behavior, can be empty for defaults
+ * @return the created MaterializationSet
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public MaterializationSet waitForCompletion(Optional options)
+ throws TimeoutException {
+ Optional timeout = options.flatMap(LroOptions::getTimeout);
+ long deadline =
+ timeout.isPresent()
+ ? System.currentTimeMillis() + timeout.get().toMillis()
+ : Long.MAX_VALUE;
+ String statusMessage = "polling operation...";
+ int attempt = 1;
+
+ while (System.currentTimeMillis() < deadline) {
+ // Refresh the operation state
+ refreshOperation();
+
+ if (operation.getDone() != null && operation.getDone()) {
+ // Operation completed, check for success or failure
+ if (operation.getError() != null) {
+ String errorMsg = "unknown error";
+ if (operation.getError().getMessage() != null
+ && !operation.getError().getMessage().isEmpty()) {
+ errorMsg = operation.getError().getMessage();
+ }
+
+ if (operation.getError().getErrorCode() != null) {
+ errorMsg = String.format("[%s] %s", operation.getError().getErrorCode(), errorMsg);
+ }
+
+ throw new DatabricksException("Operation failed: " + errorMsg);
+ }
+
+ // Operation completed successfully, unmarshal response
+ if (operation.getResponse() == null) {
+ throw new DatabricksException("Operation completed but no response available");
+ }
+
+ try {
+ JsonNode responseJson = objectMapper.valueToTree(operation.getResponse());
+ return objectMapper.treeToValue(responseJson, MaterializationSet.class);
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException(
+ "Failed to unmarshal materializationSet response: " + e.getMessage(), e);
+ }
+ }
+
+ // Operation still in progress, wait before polling again
+ String prefix = String.format("operation=%s", operation.getName());
+ int sleep = Math.min(attempt, 10); // sleep 10s max per attempt
+ LOG.info("{}: operation in progress (sleeping ~{}s)", prefix, sleep);
+
+ try {
+ Thread.sleep((long) (sleep * 1000L + Math.random() * 1000));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new DatabricksException("Current thread was interrupted", e);
+ }
+ attempt++;
+ }
+
+ String timeoutMessage =
+ timeout.isPresent()
+ ? String.format("Operation timed out after %s: %s", timeout.get(), statusMessage)
+ : String.format("Operation timed out: %s", statusMessage);
+ throw new TimeoutException(timeoutMessage);
+ }
+
+ /**
+ * Get the operation name.
+ *
+ * @return the operation name
+ */
+ public String getName() {
+ return operation.getName();
+ }
+
+ /**
+ * Get the operation metadata.
+ *
+ * @return the operation metadata, or null if not available
+ * @throws DatabricksException if the metadata cannot be deserialized
+ */
+ public MaterializationSetOperationMetadata getMetadata() {
+ if (operation.getMetadata() == null) {
+ return null;
+ }
+
+ try {
+ JsonNode metadataJson = objectMapper.valueToTree(operation.getMetadata());
+ return objectMapper.treeToValue(metadataJson, MaterializationSetOperationMetadata.class);
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException("Failed to unmarshal operation metadata: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Check if the operation is done. This method refreshes the operation state before checking.
+ *
+ * @return true if the operation is complete, false otherwise
+ * @throws DatabricksException if the status check fails
+ */
+ public boolean isDone() {
+ refreshOperation();
+ return operation.getDone() != null && operation.getDone();
+ }
+
+ /** Refresh the operation state by polling the server. */
+ private void refreshOperation() {
+ operation = impl.getOperation(new GetOperationRequest().setName(operation.getName()));
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetRequest.java
new file mode 100644
index 000000000..b213b768c
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/CreateMaterializationSetRequest.java
@@ -0,0 +1,72 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.QueryParam;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+
+@Generated
+public class CreateMaterializationSetRequest {
+ /**
+ * The materialization set to create. Supply materialization_set_id to choose the identifier;
+ * leave it unset to have one assigned.
+ */
+ @JsonProperty("materialization_set")
+ private MaterializationSet materializationSet;
+
+ /**
+ * Idempotency token for the request. A second request carrying a token that has already been used
+ * returns the operation the first one created, whatever state it reached, and creates no second
+ * set. The token is not checked against the rest of the request, so reusing one for a different
+ * set returns the original operation rather than an error. Omit it and each request creates its
+ * own set.
+ */
+ @JsonIgnore
+ @QueryParam("request_id")
+ private String requestId;
+
+ public CreateMaterializationSetRequest setMaterializationSet(
+ MaterializationSet materializationSet) {
+ this.materializationSet = materializationSet;
+ return this;
+ }
+
+ public MaterializationSet getMaterializationSet() {
+ return materializationSet;
+ }
+
+ public CreateMaterializationSetRequest setRequestId(String requestId) {
+ this.requestId = requestId;
+ return this;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CreateMaterializationSetRequest that = (CreateMaterializationSetRequest) o;
+ return Objects.equals(materializationSet, that.materializationSet)
+ && Objects.equals(requestId, that.requestId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(materializationSet, requestId);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(CreateMaterializationSetRequest.class)
+ .add("materializationSet", materializationSet)
+ .add("requestId", requestId)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetOperation.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetOperation.java
new file mode 100644
index 000000000..f02903997
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetOperation.java
@@ -0,0 +1,163 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.core.DatabricksException;
+import com.databricks.sdk.core.logging.Logger;
+import com.databricks.sdk.core.logging.LoggerFactory;
+import com.databricks.sdk.core.utils.SerDeUtils;
+import com.databricks.sdk.service.common.lro.LroOptions;
+import com.databricks.sdk.support.Generated;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Duration;
+import java.util.Optional;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Wrapper for interacting with a long-running deleteMaterializationSet operation. Provides methods
+ * to wait for completion, check status, cancel, and access metadata.
+ */
+@Generated
+public class DeleteMaterializationSetOperation {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(DeleteMaterializationSetOperation.class);
+
+ private final FeatureEngineeringService impl;
+ private Operation operation;
+ private final ObjectMapper objectMapper;
+
+ public DeleteMaterializationSetOperation(FeatureEngineeringService impl, Operation operation) {
+ this.impl = impl;
+ this.operation = operation;
+ this.objectMapper = SerDeUtils.createMapper();
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting . Waits indefinitely if no timeout
+ * is specified.
+ *
+ * @return the created
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public void waitForCompletion() throws TimeoutException {
+ waitForCompletion(Optional.empty());
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting .
+ *
+ * @param options the options for configuring the wait behavior, can be empty for defaults
+ * @return the created
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public void waitForCompletion(Optional options) throws TimeoutException {
+ Optional timeout = options.flatMap(LroOptions::getTimeout);
+ long deadline =
+ timeout.isPresent()
+ ? System.currentTimeMillis() + timeout.get().toMillis()
+ : Long.MAX_VALUE;
+ String statusMessage = "polling operation...";
+ int attempt = 1;
+
+ while (System.currentTimeMillis() < deadline) {
+ // Refresh the operation state
+ refreshOperation();
+
+ if (operation.getDone() != null && operation.getDone()) {
+ // Operation completed, check for success or failure
+ if (operation.getError() != null) {
+ String errorMsg = "unknown error";
+ if (operation.getError().getMessage() != null
+ && !operation.getError().getMessage().isEmpty()) {
+ errorMsg = operation.getError().getMessage();
+ }
+
+ if (operation.getError().getErrorCode() != null) {
+ errorMsg = String.format("[%s] %s", operation.getError().getErrorCode(), errorMsg);
+ }
+
+ throw new DatabricksException("Operation failed: " + errorMsg);
+ }
+
+ // Operation completed successfully, unmarshal response
+ if (operation.getResponse() == null) {
+ throw new DatabricksException("Operation completed but no response available");
+ }
+
+ try {
+ JsonNode responseJson = objectMapper.valueToTree(operation.getResponse());
+ objectMapper.treeToValue(responseJson, Void.class);
+ return;
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException("Failed to unmarshal response: " + e.getMessage(), e);
+ }
+ }
+
+ // Operation still in progress, wait before polling again
+ String prefix = String.format("operation=%s", operation.getName());
+ int sleep = Math.min(attempt, 10); // sleep 10s max per attempt
+ LOG.info("{}: operation in progress (sleeping ~{}s)", prefix, sleep);
+
+ try {
+ Thread.sleep((long) (sleep * 1000L + Math.random() * 1000));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new DatabricksException("Current thread was interrupted", e);
+ }
+ attempt++;
+ }
+
+ String timeoutMessage =
+ timeout.isPresent()
+ ? String.format("Operation timed out after %s: %s", timeout.get(), statusMessage)
+ : String.format("Operation timed out: %s", statusMessage);
+ throw new TimeoutException(timeoutMessage);
+ }
+
+ /**
+ * Get the operation name.
+ *
+ * @return the operation name
+ */
+ public String getName() {
+ return operation.getName();
+ }
+
+ /**
+ * Get the operation metadata.
+ *
+ * @return the operation metadata, or null if not available
+ * @throws DatabricksException if the metadata cannot be deserialized
+ */
+ public MaterializationSetOperationMetadata getMetadata() {
+ if (operation.getMetadata() == null) {
+ return null;
+ }
+
+ try {
+ JsonNode metadataJson = objectMapper.valueToTree(operation.getMetadata());
+ return objectMapper.treeToValue(metadataJson, MaterializationSetOperationMetadata.class);
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException("Failed to unmarshal operation metadata: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Check if the operation is done. This method refreshes the operation state before checking.
+ *
+ * @return true if the operation is complete, false otherwise
+ * @throws DatabricksException if the status check fails
+ */
+ public boolean isDone() {
+ refreshOperation();
+ return operation.getDone() != null && operation.getDone();
+ }
+
+ /** Refresh the operation state by polling the server. */
+ private void refreshOperation() {
+ operation = impl.getOperation(new GetOperationRequest().setName(operation.getName()));
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetRequest.java
new file mode 100644
index 000000000..f23bac4a5
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/DeleteMaterializationSetRequest.java
@@ -0,0 +1,84 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.QueryParam;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Objects;
+
+@Generated
+public class DeleteMaterializationSetRequest {
+ /**
+ * Return success instead of NOT_FOUND when the set does not exist, so a repeated destroy is
+ * idempotent.
+ */
+ @JsonIgnore
+ @QueryParam("allow_missing")
+ private Boolean allowMissing;
+
+ /** The ID of the materialization set to delete. */
+ @JsonIgnore private String materializationSetId;
+
+ /**
+ * Idempotency token for the request. A second request carrying a token that has already been used
+ * returns the operation the first one created, whatever state it reached, and deletes nothing
+ * further. The token is not checked against the rest of the request. Omit it and each request
+ * deletes independently.
+ */
+ @JsonIgnore
+ @QueryParam("request_id")
+ private String requestId;
+
+ public DeleteMaterializationSetRequest setAllowMissing(Boolean allowMissing) {
+ this.allowMissing = allowMissing;
+ return this;
+ }
+
+ public Boolean getAllowMissing() {
+ return allowMissing;
+ }
+
+ public DeleteMaterializationSetRequest setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
+ public DeleteMaterializationSetRequest setRequestId(String requestId) {
+ this.requestId = requestId;
+ return this;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DeleteMaterializationSetRequest that = (DeleteMaterializationSetRequest) o;
+ return Objects.equals(allowMissing, that.allowMissing)
+ && Objects.equals(materializationSetId, that.materializationSetId)
+ && Objects.equals(requestId, that.requestId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(allowMissing, materializationSetId, requestId);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(DeleteMaterializationSetRequest.class)
+ .add("allowMissing", allowMissing)
+ .add("materializationSetId", materializationSetId)
+ .add("requestId", requestId)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java
index 1f4aec813..85be19eea 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java
@@ -54,6 +54,13 @@ public KafkaConfig createKafkaConfig(CreateKafkaConfigRequest request) {
return impl.createKafkaConfig(request);
}
+ /** Create a materialization set. */
+ public CreateMaterializationSetOperation createMaterializationSet(
+ CreateMaterializationSetRequest request) {
+ Operation operation = impl.createMaterializationSet(request);
+ return new CreateMaterializationSetOperation(impl, operation);
+ }
+
/** Create a materialized feature. */
public MaterializedFeature createMaterializedFeature(CreateMaterializedFeatureRequest request) {
return impl.createMaterializedFeature(request);
@@ -85,6 +92,21 @@ public void deleteKafkaConfig(DeleteKafkaConfigRequest request) {
impl.deleteKafkaConfig(request);
}
+ public DeleteMaterializationSetOperation deleteMaterializationSet(String materializationSetId) {
+ return deleteMaterializationSet(
+ new DeleteMaterializationSetRequest().setMaterializationSetId(materializationSetId));
+ }
+
+ /**
+ * Delete a materialization set and every materialized feature in it. The set is gone afterwards,
+ * so a later read returns NOT_FOUND and the set id is free to use again.
+ */
+ public DeleteMaterializationSetOperation deleteMaterializationSet(
+ DeleteMaterializationSetRequest request) {
+ Operation operation = impl.deleteMaterializationSet(request);
+ return new DeleteMaterializationSetOperation(impl, operation);
+ }
+
public void deleteMaterializedFeature(String materializedFeatureId) {
deleteMaterializedFeature(
new DeleteMaterializedFeatureRequest().setMaterializedFeatureId(materializedFeatureId));
@@ -125,6 +147,19 @@ public KafkaConfig getKafkaConfig(GetKafkaConfigRequest request) {
return impl.getKafkaConfig(request);
}
+ public MaterializationSet getMaterializationSet(String materializationSetId) {
+ return getMaterializationSet(
+ new GetMaterializationSetRequest().setMaterializationSetId(materializationSetId));
+ }
+
+ /**
+ * Get a materialization set and the materialized features in it. A set whose materialized feature
+ * members have all been deleted is returned with an empty member list.
+ */
+ public MaterializationSet getMaterializationSet(GetMaterializationSetRequest request) {
+ return impl.getMaterializationSet(request);
+ }
+
public MaterializedFeature getMaterializedFeature(String materializedFeatureId) {
return getMaterializedFeature(
new GetMaterializedFeatureRequest().setMaterializedFeatureId(materializedFeatureId));
@@ -241,6 +276,17 @@ public KafkaConfig updateKafkaConfig(UpdateKafkaConfigRequest request) {
return impl.updateKafkaConfig(request);
}
+ /**
+ * Update the materialization set's state to match the supplied materialization set. Changes are
+ * applied member by member and are not atomic: when one member fails, the error reports which
+ * members were already changed.
+ */
+ public UpdateMaterializationSetOperation updateMaterializationSet(
+ UpdateMaterializationSetRequest request) {
+ Operation operation = impl.updateMaterializationSet(request);
+ return new UpdateMaterializationSetOperation(impl, operation);
+ }
+
/** Update a materialized feature (pause/resume). */
public MaterializedFeature updateMaterializedFeature(UpdateMaterializedFeatureRequest request) {
return impl.updateMaterializedFeature(request);
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java
index 6cc228e38..30974318a 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java
@@ -111,6 +111,27 @@ public KafkaConfig createKafkaConfig(CreateKafkaConfigRequest request) {
}
}
+ @Override
+ public Operation createMaterializationSet(CreateMaterializationSetRequest request) {
+ String path = "/api/2.0/feature-engineering/materialization-sets";
+ try {
+ Request req = new Request("POST", path, apiClient.serialize(request.getMaterializationSet()));
+
+ if (request.getRequestId() == null || request.getRequestId().isEmpty()) {
+ request.setRequestId(UUID.randomUUID().toString());
+ }
+ ApiClient.setQuery(req, request);
+ req.withHeader("Accept", "application/json");
+ req.withHeader("Content-Type", "application/json");
+ if (apiClient.workspaceId() != null) {
+ req.withHeader("X-Databricks-Workspace-Id", apiClient.workspaceId());
+ }
+ return apiClient.execute(req, Operation.class);
+ } catch (IOException e) {
+ throw new DatabricksException("IO error: " + e.getMessage(), e);
+ }
+ }
+
@Override
public MaterializedFeature createMaterializedFeature(CreateMaterializedFeatureRequest request) {
String path = "/api/2.0/feature-engineering/materialized-features";
@@ -183,6 +204,29 @@ public void deleteKafkaConfig(DeleteKafkaConfigRequest request) {
}
}
+ @Override
+ public Operation deleteMaterializationSet(DeleteMaterializationSetRequest request) {
+ String path =
+ String.format(
+ "/api/2.0/feature-engineering/materialization-sets/%s",
+ request.getMaterializationSetId());
+ try {
+ Request req = new Request("DELETE", path);
+
+ if (request.getRequestId() == null || request.getRequestId().isEmpty()) {
+ request.setRequestId(UUID.randomUUID().toString());
+ }
+ ApiClient.setQuery(req, request);
+ req.withHeader("Accept", "application/json");
+ if (apiClient.workspaceId() != null) {
+ req.withHeader("X-Databricks-Workspace-Id", apiClient.workspaceId());
+ }
+ return apiClient.execute(req, Operation.class);
+ } catch (IOException e) {
+ throw new DatabricksException("IO error: " + e.getMessage(), e);
+ }
+ }
+
@Override
public void deleteMaterializedFeature(DeleteMaterializedFeatureRequest request) {
String path =
@@ -255,6 +299,26 @@ public KafkaConfig getKafkaConfig(GetKafkaConfigRequest request) {
}
}
+ @Override
+ public MaterializationSet getMaterializationSet(GetMaterializationSetRequest request) {
+ String path =
+ String.format(
+ "/api/2.0/feature-engineering/materialization-sets/%s",
+ request.getMaterializationSetId());
+ try {
+ Request req = new Request("GET", path);
+
+ ApiClient.setQuery(req, request);
+ req.withHeader("Accept", "application/json");
+ if (apiClient.workspaceId() != null) {
+ req.withHeader("X-Databricks-Workspace-Id", apiClient.workspaceId());
+ }
+ return apiClient.execute(req, MaterializationSet.class);
+ } catch (IOException e) {
+ throw new DatabricksException("IO error: " + e.getMessage(), e);
+ }
+ }
+
@Override
public MaterializedFeature getMaterializedFeature(GetMaterializedFeatureRequest request) {
String path =
@@ -436,6 +500,31 @@ public KafkaConfig updateKafkaConfig(UpdateKafkaConfigRequest request) {
}
}
+ @Override
+ public Operation updateMaterializationSet(UpdateMaterializationSetRequest request) {
+ String path =
+ String.format(
+ "/api/2.0/feature-engineering/materialization-sets/%s",
+ request.getMaterializationSetId());
+ try {
+ Request req =
+ new Request("PATCH", path, apiClient.serialize(request.getMaterializationSet()));
+
+ if (request.getRequestId() == null || request.getRequestId().isEmpty()) {
+ request.setRequestId(UUID.randomUUID().toString());
+ }
+ ApiClient.setQuery(req, request);
+ req.withHeader("Accept", "application/json");
+ req.withHeader("Content-Type", "application/json");
+ if (apiClient.workspaceId() != null) {
+ req.withHeader("X-Databricks-Workspace-Id", apiClient.workspaceId());
+ }
+ return apiClient.execute(req, Operation.class);
+ } catch (IOException e) {
+ throw new DatabricksException("IO error: " + e.getMessage(), e);
+ }
+ }
+
@Override
public MaterializedFeature updateMaterializedFeature(UpdateMaterializedFeatureRequest request) {
String path =
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java
index 4b3af192e..4705e823e 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java
@@ -31,6 +31,10 @@ BatchCreateMaterializedFeaturesResponse batchCreateMaterializedFeatures(
*/
KafkaConfig createKafkaConfig(CreateKafkaConfigRequest createKafkaConfigRequest);
+ /** Create a materialization set. */
+ Operation createMaterializationSet(
+ CreateMaterializationSetRequest createMaterializationSetRequest);
+
/** Create a materialized feature. */
MaterializedFeature createMaterializedFeature(
CreateMaterializedFeatureRequest createMaterializedFeatureRequest);
@@ -47,6 +51,13 @@ MaterializedFeature createMaterializedFeature(
*/
void deleteKafkaConfig(DeleteKafkaConfigRequest deleteKafkaConfigRequest);
+ /**
+ * Delete a materialization set and every materialized feature in it. The set is gone afterwards,
+ * so a later read returns NOT_FOUND and the set id is free to use again.
+ */
+ Operation deleteMaterializationSet(
+ DeleteMaterializationSetRequest deleteMaterializationSetRequest);
+
/** Delete a materialized feature. */
void deleteMaterializedFeature(DeleteMaterializedFeatureRequest deleteMaterializedFeatureRequest);
@@ -62,6 +73,13 @@ MaterializedFeature createMaterializedFeature(
*/
KafkaConfig getKafkaConfig(GetKafkaConfigRequest getKafkaConfigRequest);
+ /**
+ * Get a materialization set and the materialized features in it. A set whose materialized feature
+ * members have all been deleted is returned with an empty member list.
+ */
+ MaterializationSet getMaterializationSet(
+ GetMaterializationSetRequest getMaterializationSetRequest);
+
/** Get a materialized feature. */
MaterializedFeature getMaterializedFeature(
GetMaterializedFeatureRequest getMaterializedFeatureRequest);
@@ -100,6 +118,14 @@ ListMaterializedFeaturesResponse listMaterializedFeatures(
*/
KafkaConfig updateKafkaConfig(UpdateKafkaConfigRequest updateKafkaConfigRequest);
+ /**
+ * Update the materialization set's state to match the supplied materialization set. Changes are
+ * applied member by member and are not atomic: when one member fails, the error reports which
+ * members were already changed.
+ */
+ Operation updateMaterializationSet(
+ UpdateMaterializationSetRequest updateMaterializationSetRequest);
+
/** Update a materialized feature (pause/resume). */
MaterializedFeature updateMaterializedFeature(
UpdateMaterializedFeatureRequest updateMaterializedFeatureRequest);
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/GetMaterializationSetRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/GetMaterializationSetRequest.java
new file mode 100644
index 000000000..aea6966b5
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/GetMaterializationSetRequest.java
@@ -0,0 +1,43 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Objects;
+
+@Generated
+public class GetMaterializationSetRequest {
+ /** The ID of the materialization set. */
+ @JsonIgnore private String materializationSetId;
+
+ public GetMaterializationSetRequest setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ GetMaterializationSetRequest that = (GetMaterializationSetRequest) o;
+ return Objects.equals(materializationSetId, that.materializationSetId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(materializationSetId);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(GetMaterializationSetRequest.class)
+ .add("materializationSetId", materializationSetId)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSet.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSet.java
new file mode 100644
index 000000000..9cafdecd7
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSet.java
@@ -0,0 +1,65 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+/** A group of materialized features created and managed as a single unit. */
+@Generated
+public class MaterializationSet {
+ /** Server-assigned unique identifier for the materialization set. */
+ @JsonProperty("materialization_set_id")
+ private String materializationSetId;
+
+ /**
+ * The materialized features in this set. Order is not significant. Updating the set with a
+ * materialized feature removed from this set will cause it to be deleted.
+ */
+ @JsonProperty("materialized_features")
+ private Collection materializedFeatures;
+
+ public MaterializationSet setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
+ public MaterializationSet setMaterializedFeatures(
+ Collection materializedFeatures) {
+ this.materializedFeatures = materializedFeatures;
+ return this;
+ }
+
+ public Collection getMaterializedFeatures() {
+ return materializedFeatures;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MaterializationSet that = (MaterializationSet) o;
+ return Objects.equals(materializationSetId, that.materializationSetId)
+ && Objects.equals(materializedFeatures, that.materializedFeatures);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(materializationSetId, materializedFeatures);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(MaterializationSet.class)
+ .add("materializationSetId", materializationSetId)
+ .add("materializedFeatures", materializedFeatures)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetDeletionProgress.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetDeletionProgress.java
new file mode 100644
index 000000000..2604c9453
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetDeletionProgress.java
@@ -0,0 +1,67 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * What a partly failed DeleteMaterializationSet got through, attached to the error so a caller can
+ * tell which materialized feature members are gone and which ones still need attention. The set
+ * itself is left in place whenever any member failed, so a retry can still find the members.
+ */
+@Generated
+public class MaterializationSetDeletionProgress {
+ /** Members that are no longer materialized, including any that were already gone. */
+ @JsonProperty("deleted_materialized_feature_ids")
+ private Collection deletedMaterializedFeatureIds;
+
+ /** Members that could not be deleted, one entry each. */
+ @JsonProperty("failed_materialized_features")
+ private Collection failedMaterializedFeatures;
+
+ public MaterializationSetDeletionProgress setDeletedMaterializedFeatureIds(
+ Collection deletedMaterializedFeatureIds) {
+ this.deletedMaterializedFeatureIds = deletedMaterializedFeatureIds;
+ return this;
+ }
+
+ public Collection getDeletedMaterializedFeatureIds() {
+ return deletedMaterializedFeatureIds;
+ }
+
+ public MaterializationSetDeletionProgress setFailedMaterializedFeatures(
+ Collection failedMaterializedFeatures) {
+ this.failedMaterializedFeatures = failedMaterializedFeatures;
+ return this;
+ }
+
+ public Collection getFailedMaterializedFeatures() {
+ return failedMaterializedFeatures;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MaterializationSetDeletionProgress that = (MaterializationSetDeletionProgress) o;
+ return Objects.equals(deletedMaterializedFeatureIds, that.deletedMaterializedFeatureIds)
+ && Objects.equals(failedMaterializedFeatures, that.failedMaterializedFeatures);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deletedMaterializedFeatureIds, failedMaterializedFeatures);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(MaterializationSetDeletionProgress.class)
+ .add("deletedMaterializedFeatureIds", deletedMaterializedFeatureIds)
+ .add("failedMaterializedFeatures", failedMaterializedFeatures)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadata.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadata.java
new file mode 100644
index 000000000..cc0737ce3
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadata.java
@@ -0,0 +1,135 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.protobuf.Timestamp;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Progress of a materialization set operation. Shared by create, update and delete, because
+ * databricks.longrunning freezes a method's metadata type once it ships.
+ */
+@Generated
+public class MaterializationSetOperationMetadata {
+ /** Time at which the operation was requested. */
+ @JsonProperty("create_time")
+ private Timestamp createTime;
+
+ /** Set by a DeleteMaterializationSet operation. */
+ @JsonProperty("deletion_progress")
+ private MaterializationSetDeletionProgress deletionProgress;
+
+ /** Full names of the features the set materializes, one entry per feature. */
+ @JsonProperty("feature_full_names")
+ private Collection featureFullNames;
+
+ /** ID of the materialization set the operation targets. */
+ @JsonProperty("materialization_set_id")
+ private String materializationSetId;
+
+ /** Current state of the operation. */
+ @JsonProperty("state")
+ private MaterializationSetOperationMetadataState state;
+
+ /** Set by an UpdateMaterializationSet operation. */
+ @JsonProperty("update_progress")
+ private MaterializationSetUpdateProgress updateProgress;
+
+ public MaterializationSetOperationMetadata setCreateTime(Timestamp createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public Timestamp getCreateTime() {
+ return createTime;
+ }
+
+ public MaterializationSetOperationMetadata setDeletionProgress(
+ MaterializationSetDeletionProgress deletionProgress) {
+ this.deletionProgress = deletionProgress;
+ return this;
+ }
+
+ public MaterializationSetDeletionProgress getDeletionProgress() {
+ return deletionProgress;
+ }
+
+ public MaterializationSetOperationMetadata setFeatureFullNames(
+ Collection featureFullNames) {
+ this.featureFullNames = featureFullNames;
+ return this;
+ }
+
+ public Collection getFeatureFullNames() {
+ return featureFullNames;
+ }
+
+ public MaterializationSetOperationMetadata setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
+ public MaterializationSetOperationMetadata setState(
+ MaterializationSetOperationMetadataState state) {
+ this.state = state;
+ return this;
+ }
+
+ public MaterializationSetOperationMetadataState getState() {
+ return state;
+ }
+
+ public MaterializationSetOperationMetadata setUpdateProgress(
+ MaterializationSetUpdateProgress updateProgress) {
+ this.updateProgress = updateProgress;
+ return this;
+ }
+
+ public MaterializationSetUpdateProgress getUpdateProgress() {
+ return updateProgress;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MaterializationSetOperationMetadata that = (MaterializationSetOperationMetadata) o;
+ return Objects.equals(createTime, that.createTime)
+ && Objects.equals(deletionProgress, that.deletionProgress)
+ && Objects.equals(featureFullNames, that.featureFullNames)
+ && Objects.equals(materializationSetId, that.materializationSetId)
+ && Objects.equals(state, that.state)
+ && Objects.equals(updateProgress, that.updateProgress);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ createTime,
+ deletionProgress,
+ featureFullNames,
+ materializationSetId,
+ state,
+ updateProgress);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(MaterializationSetOperationMetadata.class)
+ .add("createTime", createTime)
+ .add("deletionProgress", deletionProgress)
+ .add("featureFullNames", featureFullNames)
+ .add("materializationSetId", materializationSetId)
+ .add("state", state)
+ .add("updateProgress", updateProgress)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadataState.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadataState.java
new file mode 100644
index 000000000..83a6902f5
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetOperationMetadataState.java
@@ -0,0 +1,15 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+
+/** Lifecycle state of a materialization set operation. */
+@Generated
+public enum MaterializationSetOperationMetadataState {
+ CANCELLED,
+ FAILED,
+ PENDING,
+ RUNNING,
+ SUCCEEDED,
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetUpdateProgress.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetUpdateProgress.java
new file mode 100644
index 000000000..c46d194f9
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializationSetUpdateProgress.java
@@ -0,0 +1,83 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * What a partly failed UpdateMaterializationSet got through, attached to the error so a caller can
+ * tell which materialized feature members already changed and which ones did not and why it failed.
+ */
+@Generated
+public class MaterializationSetUpdateProgress {
+ /** Materialized feature members that were deleted from the materialization set. */
+ @JsonProperty("deleted_materialized_feature_ids")
+ private Collection deletedMaterializedFeatureIds;
+
+ /** Materialized feature members that could not be updated, one entry each. */
+ @JsonProperty("failed_materialized_features")
+ private Collection failedMaterializedFeatures;
+
+ /** Materialized feature members whose mutable state was updated. */
+ @JsonProperty("updated_materialized_feature_ids")
+ private Collection updatedMaterializedFeatureIds;
+
+ public MaterializationSetUpdateProgress setDeletedMaterializedFeatureIds(
+ Collection deletedMaterializedFeatureIds) {
+ this.deletedMaterializedFeatureIds = deletedMaterializedFeatureIds;
+ return this;
+ }
+
+ public Collection getDeletedMaterializedFeatureIds() {
+ return deletedMaterializedFeatureIds;
+ }
+
+ public MaterializationSetUpdateProgress setFailedMaterializedFeatures(
+ Collection failedMaterializedFeatures) {
+ this.failedMaterializedFeatures = failedMaterializedFeatures;
+ return this;
+ }
+
+ public Collection getFailedMaterializedFeatures() {
+ return failedMaterializedFeatures;
+ }
+
+ public MaterializationSetUpdateProgress setUpdatedMaterializedFeatureIds(
+ Collection updatedMaterializedFeatureIds) {
+ this.updatedMaterializedFeatureIds = updatedMaterializedFeatureIds;
+ return this;
+ }
+
+ public Collection getUpdatedMaterializedFeatureIds() {
+ return updatedMaterializedFeatureIds;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MaterializationSetUpdateProgress that = (MaterializationSetUpdateProgress) o;
+ return Objects.equals(deletedMaterializedFeatureIds, that.deletedMaterializedFeatureIds)
+ && Objects.equals(failedMaterializedFeatures, that.failedMaterializedFeatures)
+ && Objects.equals(updatedMaterializedFeatureIds, that.updatedMaterializedFeatureIds);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ deletedMaterializedFeatureIds, failedMaterializedFeatures, updatedMaterializedFeatureIds);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(MaterializationSetUpdateProgress.class)
+ .add("deletedMaterializedFeatureIds", deletedMaterializedFeatureIds)
+ .add("failedMaterializedFeatures", failedMaterializedFeatures)
+ .add("updatedMaterializedFeatureIds", updatedMaterializedFeatureIds)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java
index fbd5d2439..3da02e9e1 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java
@@ -57,6 +57,13 @@ public class MaterializedFeature {
@JsonProperty("latest_backfill_operation")
private String latestBackfillOperation;
+ /**
+ * The materialization set this materialized feature was created for, through DABs or
+ * direct-engine creation. Unset for a materialized feature that was not created as part of a set.
+ */
+ @JsonProperty("materialization_set_id")
+ private String materializationSetId;
+
/** Server-assigned unique identifier for the materialized feature. */
@JsonProperty("materialized_feature_id")
private String materializedFeatureId;
@@ -200,6 +207,15 @@ public String getLatestBackfillOperation() {
return latestBackfillOperation;
}
+ public MaterializedFeature setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
public MaterializedFeature setMaterializedFeatureId(String materializedFeatureId) {
this.materializedFeatureId = materializedFeatureId;
return this;
@@ -304,6 +320,7 @@ public boolean equals(Object o) {
&& Objects.equals(jobId, that.jobId)
&& Objects.equals(lastMaterializationTime, that.lastMaterializationTime)
&& Objects.equals(latestBackfillOperation, that.latestBackfillOperation)
+ && Objects.equals(materializationSetId, that.materializationSetId)
&& Objects.equals(materializedFeatureId, that.materializedFeatureId)
&& Objects.equals(notifications, that.notifications)
&& Objects.equals(offlineStoreConfig, that.offlineStoreConfig)
@@ -327,6 +344,7 @@ public int hashCode() {
jobId,
lastMaterializationTime,
latestBackfillOperation,
+ materializationSetId,
materializedFeatureId,
notifications,
offlineStoreConfig,
@@ -350,6 +368,7 @@ public String toString() {
.add("jobId", jobId)
.add("lastMaterializationTime", lastMaterializationTime)
.add("latestBackfillOperation", latestBackfillOperation)
+ .add("materializationSetId", materializationSetId)
.add("materializedFeatureId", materializedFeatureId)
.add("notifications", notifications)
.add("offlineStoreConfig", offlineStoreConfig)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeatureChangeFailure.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeatureChangeFailure.java
new file mode 100644
index 000000000..1526ae4b1
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeatureChangeFailure.java
@@ -0,0 +1,75 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+
+/** Why one materialization set member could not be changed. */
+@Generated
+public class MaterializedFeatureChangeFailure {
+ /** Databricks error code name of the failure, for example "RESOURCE_CONFLICT". */
+ @JsonProperty("error_code")
+ private String errorCode;
+
+ /** The member that could not be changed. */
+ @JsonProperty("materialized_feature_id")
+ private String materializedFeatureId;
+
+ /** The failure's message. */
+ @JsonProperty("message")
+ private String message;
+
+ public MaterializedFeatureChangeFailure setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ return this;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public MaterializedFeatureChangeFailure setMaterializedFeatureId(String materializedFeatureId) {
+ this.materializedFeatureId = materializedFeatureId;
+ return this;
+ }
+
+ public String getMaterializedFeatureId() {
+ return materializedFeatureId;
+ }
+
+ public MaterializedFeatureChangeFailure setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MaterializedFeatureChangeFailure that = (MaterializedFeatureChangeFailure) o;
+ return Objects.equals(errorCode, that.errorCode)
+ && Objects.equals(materializedFeatureId, that.materializedFeatureId)
+ && Objects.equals(message, that.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(errorCode, materializedFeatureId, message);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(MaterializedFeatureChangeFailure.class)
+ .add("errorCode", errorCode)
+ .add("materializedFeatureId", materializedFeatureId)
+ .add("message", message)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java
index d92822847..910884049 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java
@@ -16,6 +16,10 @@ public class PurgeFeatureEntitiesMetadata {
@JsonProperty("create_time")
private Timestamp createTime;
+ /** Whether this purge deletes matching rows instead of setting feature values to null. */
+ @JsonProperty("delete_rows")
+ private Boolean deleteRows;
+
/** Fully qualified name of the Unity Catalog Delta table containing the entity keys to purge. */
@JsonProperty("entities_table")
private String entitiesTable;
@@ -45,6 +49,15 @@ public Timestamp getCreateTime() {
return createTime;
}
+ public PurgeFeatureEntitiesMetadata setDeleteRows(Boolean deleteRows) {
+ this.deleteRows = deleteRows;
+ return this;
+ }
+
+ public Boolean getDeleteRows() {
+ return deleteRows;
+ }
+
public PurgeFeatureEntitiesMetadata setEntitiesTable(String entitiesTable) {
this.entitiesTable = entitiesTable;
return this;
@@ -96,6 +109,7 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
PurgeFeatureEntitiesMetadata that = (PurgeFeatureEntitiesMetadata) o;
return Objects.equals(createTime, that.createTime)
+ && Objects.equals(deleteRows, that.deleteRows)
&& Objects.equals(entitiesTable, that.entitiesTable)
&& Objects.equals(entitiesTableVersion, that.entitiesTableVersion)
&& Objects.equals(features, that.features)
@@ -105,13 +119,15 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- return Objects.hash(createTime, entitiesTable, entitiesTableVersion, features, jobId, state);
+ return Objects.hash(
+ createTime, deleteRows, entitiesTable, entitiesTableVersion, features, jobId, state);
}
@Override
public String toString() {
return new ToStringer(PurgeFeatureEntitiesMetadata.class)
.add("createTime", createTime)
+ .add("deleteRows", deleteRows)
.add("entitiesTable", entitiesTable)
.add("entitiesTableVersion", entitiesTableVersion)
.add("features", features)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java
index 0d2f53743..75c3b24c8 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java
@@ -21,6 +21,16 @@ public class PurgeFeatureEntitiesRequest {
@JsonProperty("budget_policy_id")
private String budgetPolicyId;
+ /**
+ * If false feature values are set to null on purge but rows are not deleted. If true then the
+ * full rows containing entities are deleted. Defaults to false. When true, the request must
+ * include every feature which shares the same `table_name` property in their MaterializedFeature.
+ * Features from multiple tables may be included if all features materialized in each table are
+ * included.
+ */
+ @JsonProperty("delete_rows")
+ private Boolean deleteRows;
+
/**
* Fully qualified name of the Unity Catalog Delta table containing the entity keys to purge. The
* table may contain a subset of each feature's entity-key columns. A partial key match deletes
@@ -32,7 +42,7 @@ public class PurgeFeatureEntitiesRequest {
/**
* Fully qualified names of the features to purge. At least one nonempty feature name is required.
- * A request may contain at most 10000 features; submit additional features in separate requests.
+ * A request may contain at most 500 features; submit additional features in separate requests.
* Duplicate features are rejected.
*/
@JsonProperty("features")
@@ -62,6 +72,15 @@ public String getBudgetPolicyId() {
return budgetPolicyId;
}
+ public PurgeFeatureEntitiesRequest setDeleteRows(Boolean deleteRows) {
+ this.deleteRows = deleteRows;
+ return this;
+ }
+
+ public Boolean getDeleteRows() {
+ return deleteRows;
+ }
+
public PurgeFeatureEntitiesRequest setEntitiesTable(String entitiesTable) {
this.entitiesTable = entitiesTable;
return this;
@@ -104,6 +123,7 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
PurgeFeatureEntitiesRequest that = (PurgeFeatureEntitiesRequest) o;
return Objects.equals(budgetPolicyId, that.budgetPolicyId)
+ && Objects.equals(deleteRows, that.deleteRows)
&& Objects.equals(entitiesTable, that.entitiesTable)
&& Objects.equals(features, that.features)
&& Objects.equals(requestId, that.requestId)
@@ -112,13 +132,14 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- return Objects.hash(budgetPolicyId, entitiesTable, features, requestId, tags);
+ return Objects.hash(budgetPolicyId, deleteRows, entitiesTable, features, requestId, tags);
}
@Override
public String toString() {
return new ToStringer(PurgeFeatureEntitiesRequest.class)
.add("budgetPolicyId", budgetPolicyId)
+ .add("deleteRows", deleteRows)
.add("entitiesTable", entitiesTable)
.add("features", features)
.add("requestId", requestId)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/SdpSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/SdpSource.java
index 2c61359c1..ac494d69a 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/SdpSource.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/SdpSource.java
@@ -29,8 +29,8 @@ public class SdpSource {
/**
* The full three-part names of the tables the pipeline reads from. Required to materialize this
* feature with a TableTrigger, which starts a run when these tables update. Each table must exist
- * when the feature is created. After the pipeline runs, Feature Store checks that it reads from
- * these tables, and the run fails if it doesn't. At most 100 tables.
+ * when the feature is created. Feature Store doesn't confirm that the pipeline reads from these
+ * tables. At most 100 tables.
*/
@JsonProperty("input_tables")
private Collection inputTables;
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetOperation.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetOperation.java
new file mode 100644
index 000000000..c15e6b3cf
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetOperation.java
@@ -0,0 +1,164 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.core.DatabricksException;
+import com.databricks.sdk.core.logging.Logger;
+import com.databricks.sdk.core.logging.LoggerFactory;
+import com.databricks.sdk.core.utils.SerDeUtils;
+import com.databricks.sdk.service.common.lro.LroOptions;
+import com.databricks.sdk.support.Generated;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Duration;
+import java.util.Optional;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Wrapper for interacting with a long-running updateMaterializationSet operation. Provides methods
+ * to wait for completion, check status, cancel, and access metadata.
+ */
+@Generated
+public class UpdateMaterializationSetOperation {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(UpdateMaterializationSetOperation.class);
+
+ private final FeatureEngineeringService impl;
+ private Operation operation;
+ private final ObjectMapper objectMapper;
+
+ public UpdateMaterializationSetOperation(FeatureEngineeringService impl, Operation operation) {
+ this.impl = impl;
+ this.operation = operation;
+ this.objectMapper = SerDeUtils.createMapper();
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting MaterializationSet. Waits
+ * indefinitely if no timeout is specified.
+ *
+ * @return the created MaterializationSet
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public MaterializationSet waitForCompletion() throws TimeoutException {
+ return waitForCompletion(Optional.empty());
+ }
+
+ /**
+ * Wait for the operation to complete and return the resulting MaterializationSet.
+ *
+ * @param options the options for configuring the wait behavior, can be empty for defaults
+ * @return the created MaterializationSet
+ * @throws TimeoutException if the operation doesn't complete within the timeout
+ * @throws DatabricksException if the operation fails
+ */
+ public MaterializationSet waitForCompletion(Optional options)
+ throws TimeoutException {
+ Optional timeout = options.flatMap(LroOptions::getTimeout);
+ long deadline =
+ timeout.isPresent()
+ ? System.currentTimeMillis() + timeout.get().toMillis()
+ : Long.MAX_VALUE;
+ String statusMessage = "polling operation...";
+ int attempt = 1;
+
+ while (System.currentTimeMillis() < deadline) {
+ // Refresh the operation state
+ refreshOperation();
+
+ if (operation.getDone() != null && operation.getDone()) {
+ // Operation completed, check for success or failure
+ if (operation.getError() != null) {
+ String errorMsg = "unknown error";
+ if (operation.getError().getMessage() != null
+ && !operation.getError().getMessage().isEmpty()) {
+ errorMsg = operation.getError().getMessage();
+ }
+
+ if (operation.getError().getErrorCode() != null) {
+ errorMsg = String.format("[%s] %s", operation.getError().getErrorCode(), errorMsg);
+ }
+
+ throw new DatabricksException("Operation failed: " + errorMsg);
+ }
+
+ // Operation completed successfully, unmarshal response
+ if (operation.getResponse() == null) {
+ throw new DatabricksException("Operation completed but no response available");
+ }
+
+ try {
+ JsonNode responseJson = objectMapper.valueToTree(operation.getResponse());
+ return objectMapper.treeToValue(responseJson, MaterializationSet.class);
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException(
+ "Failed to unmarshal materializationSet response: " + e.getMessage(), e);
+ }
+ }
+
+ // Operation still in progress, wait before polling again
+ String prefix = String.format("operation=%s", operation.getName());
+ int sleep = Math.min(attempt, 10); // sleep 10s max per attempt
+ LOG.info("{}: operation in progress (sleeping ~{}s)", prefix, sleep);
+
+ try {
+ Thread.sleep((long) (sleep * 1000L + Math.random() * 1000));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new DatabricksException("Current thread was interrupted", e);
+ }
+ attempt++;
+ }
+
+ String timeoutMessage =
+ timeout.isPresent()
+ ? String.format("Operation timed out after %s: %s", timeout.get(), statusMessage)
+ : String.format("Operation timed out: %s", statusMessage);
+ throw new TimeoutException(timeoutMessage);
+ }
+
+ /**
+ * Get the operation name.
+ *
+ * @return the operation name
+ */
+ public String getName() {
+ return operation.getName();
+ }
+
+ /**
+ * Get the operation metadata.
+ *
+ * @return the operation metadata, or null if not available
+ * @throws DatabricksException if the metadata cannot be deserialized
+ */
+ public MaterializationSetOperationMetadata getMetadata() {
+ if (operation.getMetadata() == null) {
+ return null;
+ }
+
+ try {
+ JsonNode metadataJson = objectMapper.valueToTree(operation.getMetadata());
+ return objectMapper.treeToValue(metadataJson, MaterializationSetOperationMetadata.class);
+ } catch (JsonProcessingException e) {
+ throw new DatabricksException("Failed to unmarshal operation metadata: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Check if the operation is done. This method refreshes the operation state before checking.
+ *
+ * @return true if the operation is complete, false otherwise
+ * @throws DatabricksException if the status check fails
+ */
+ public boolean isDone() {
+ refreshOperation();
+ return operation.getDone() != null && operation.getDone();
+ }
+
+ /** Refresh the operation state by polling the server. */
+ private void refreshOperation() {
+ operation = impl.getOperation(new GetOperationRequest().setName(operation.getName()));
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetRequest.java
new file mode 100644
index 000000000..d293f96e6
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/UpdateMaterializationSetRequest.java
@@ -0,0 +1,101 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.ml;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.QueryParam;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.protobuf.FieldMask;
+import java.util.Objects;
+
+@Generated
+public class UpdateMaterializationSetRequest {
+ /**
+ * The desired state of the updated materialization set. materialization_set_id selects the set.
+ */
+ @JsonProperty("materialization_set")
+ private MaterializationSet materializationSet;
+
+ /** Server-assigned unique identifier for the materialization set. */
+ @JsonIgnore private String materializationSetId;
+
+ /**
+ * Idempotency token for the request. A second request carrying a token that has already been used
+ * returns the operation the first one created, whatever state it reached, and changes nothing
+ * further. The token is not checked against the rest of the request. Omit it and each request
+ * updates independently.
+ */
+ @JsonIgnore
+ @QueryParam("request_id")
+ private String requestId;
+
+ /** The fields to update. Only 'materialized_features' is supported. */
+ @JsonIgnore
+ @QueryParam("update_mask")
+ private FieldMask updateMask;
+
+ public UpdateMaterializationSetRequest setMaterializationSet(
+ MaterializationSet materializationSet) {
+ this.materializationSet = materializationSet;
+ return this;
+ }
+
+ public MaterializationSet getMaterializationSet() {
+ return materializationSet;
+ }
+
+ public UpdateMaterializationSetRequest setMaterializationSetId(String materializationSetId) {
+ this.materializationSetId = materializationSetId;
+ return this;
+ }
+
+ public String getMaterializationSetId() {
+ return materializationSetId;
+ }
+
+ public UpdateMaterializationSetRequest setRequestId(String requestId) {
+ this.requestId = requestId;
+ return this;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public UpdateMaterializationSetRequest setUpdateMask(FieldMask updateMask) {
+ this.updateMask = updateMask;
+ return this;
+ }
+
+ public FieldMask getUpdateMask() {
+ return updateMask;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ UpdateMaterializationSetRequest that = (UpdateMaterializationSetRequest) o;
+ return Objects.equals(materializationSet, that.materializationSet)
+ && Objects.equals(materializationSetId, that.materializationSetId)
+ && Objects.equals(requestId, that.requestId)
+ && Objects.equals(updateMask, that.updateMask);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(materializationSet, materializationSetId, requestId, updateMask);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(UpdateMaterializationSetRequest.class)
+ .add("materializationSet", materializationSet)
+ .add("materializationSetId", materializationSetId)
+ .add("requestId", requestId)
+ .add("updateMask", updateMask)
+ .toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/StartUpdate.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/StartUpdate.java
index 63ef82f38..ee5c31f9d 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/StartUpdate.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/StartUpdate.java
@@ -36,6 +36,10 @@ public class StartUpdate {
@JsonProperty("full_refresh_selection")
private Collection fullRefreshSelection;
+ /** A list of file paths that identify the tables to update with a full refresh. */
+ @JsonProperty("full_refresh_selection_by_path")
+ private Collection fullRefreshSelectionByPath;
+
/** Key/value map of parameters to pass to the pipeline execution */
@JsonProperty("parameters")
private Map parameters;
@@ -51,6 +55,10 @@ public class StartUpdate {
@JsonProperty("refresh_selection")
private Collection refreshSelection;
+ /** A list of file paths that identify the tables to update. */
+ @JsonProperty("refresh_selection_by_path")
+ private Collection refreshSelectionByPath;
+
/**
* A list of predicate overrides for replace_where flows in this update. Only replace_where flows
* may be specified. Flows not listed use their original predicate.
@@ -116,6 +124,15 @@ public Collection getFullRefreshSelection() {
return fullRefreshSelection;
}
+ public StartUpdate setFullRefreshSelectionByPath(Collection fullRefreshSelectionByPath) {
+ this.fullRefreshSelectionByPath = fullRefreshSelectionByPath;
+ return this;
+ }
+
+ public Collection getFullRefreshSelectionByPath() {
+ return fullRefreshSelectionByPath;
+ }
+
public StartUpdate setParameters(Map parameters) {
this.parameters = parameters;
return this;
@@ -143,6 +160,15 @@ public Collection getRefreshSelection() {
return refreshSelection;
}
+ public StartUpdate setRefreshSelectionByPath(Collection refreshSelectionByPath) {
+ this.refreshSelectionByPath = refreshSelectionByPath;
+ return this;
+ }
+
+ public Collection getRefreshSelectionByPath() {
+ return refreshSelectionByPath;
+ }
+
public StartUpdate setReplaceWhereOverrides(
Collection replaceWhereOverrides) {
this.replaceWhereOverrides = replaceWhereOverrides;
@@ -189,9 +215,11 @@ public boolean equals(Object o) {
&& Objects.equals(development, that.development)
&& Objects.equals(fullRefresh, that.fullRefresh)
&& Objects.equals(fullRefreshSelection, that.fullRefreshSelection)
+ && Objects.equals(fullRefreshSelectionByPath, that.fullRefreshSelectionByPath)
&& Objects.equals(parameters, that.parameters)
&& Objects.equals(pipelineId, that.pipelineId)
&& Objects.equals(refreshSelection, that.refreshSelection)
+ && Objects.equals(refreshSelectionByPath, that.refreshSelectionByPath)
&& Objects.equals(replaceWhereOverrides, that.replaceWhereOverrides)
&& Objects.equals(resetCheckpointSelection, that.resetCheckpointSelection)
&& Objects.equals(rewindSpec, that.rewindSpec)
@@ -205,9 +233,11 @@ public int hashCode() {
development,
fullRefresh,
fullRefreshSelection,
+ fullRefreshSelectionByPath,
parameters,
pipelineId,
refreshSelection,
+ refreshSelectionByPath,
replaceWhereOverrides,
resetCheckpointSelection,
rewindSpec,
@@ -221,9 +251,11 @@ public String toString() {
.add("development", development)
.add("fullRefresh", fullRefresh)
.add("fullRefreshSelection", fullRefreshSelection)
+ .add("fullRefreshSelectionByPath", fullRefreshSelectionByPath)
.add("parameters", parameters)
.add("pipelineId", pipelineId)
.add("refreshSelection", refreshSelection)
+ .add("refreshSelectionByPath", refreshSelectionByPath)
.add("replaceWhereOverrides", replaceWhereOverrides)
.add("resetCheckpointSelection", resetCheckpointSelection)
.add("rewindSpec", rewindSpec)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java
index 9f67fdcf1..114442e2a 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java
@@ -42,6 +42,10 @@ public class UpdateInfo {
@JsonProperty("full_refresh_selection")
private Collection fullRefreshSelection;
+ /** A list of file paths that identify the tables to update with a full refresh. */
+ @JsonProperty("full_refresh_selection_by_path")
+ private Collection fullRefreshSelectionByPath;
+
/**
* Indicates whether the update is either part of a continuous job run, or running in legacy
* continuous pipeline mode. Returned only for GetUpdate; not populated in ListUpdates responses.
@@ -65,6 +69,10 @@ public class UpdateInfo {
@JsonProperty("refresh_selection")
private Collection refreshSelection;
+ /** A list of file paths that identify the tables to update. */
+ @JsonProperty("refresh_selection_by_path")
+ private Collection refreshSelectionByPath;
+
/** The update state. */
@JsonProperty("state")
private UpdateInfoState state;
@@ -134,6 +142,15 @@ public Collection getFullRefreshSelection() {
return fullRefreshSelection;
}
+ public UpdateInfo setFullRefreshSelectionByPath(Collection fullRefreshSelectionByPath) {
+ this.fullRefreshSelectionByPath = fullRefreshSelectionByPath;
+ return this;
+ }
+
+ public Collection getFullRefreshSelectionByPath() {
+ return fullRefreshSelectionByPath;
+ }
+
public UpdateInfo setMode(UpdateMode mode) {
this.mode = mode;
return this;
@@ -170,6 +187,15 @@ public Collection getRefreshSelection() {
return refreshSelection;
}
+ public UpdateInfo setRefreshSelectionByPath(Collection refreshSelectionByPath) {
+ this.refreshSelectionByPath = refreshSelectionByPath;
+ return this;
+ }
+
+ public Collection getRefreshSelectionByPath() {
+ return refreshSelectionByPath;
+ }
+
public UpdateInfo setState(UpdateInfoState state) {
this.state = state;
return this;
@@ -208,10 +234,12 @@ public boolean equals(Object o) {
&& Objects.equals(creationTime, that.creationTime)
&& Objects.equals(fullRefresh, that.fullRefresh)
&& Objects.equals(fullRefreshSelection, that.fullRefreshSelection)
+ && Objects.equals(fullRefreshSelectionByPath, that.fullRefreshSelectionByPath)
&& Objects.equals(mode, that.mode)
&& Objects.equals(parameters, that.parameters)
&& Objects.equals(pipelineId, that.pipelineId)
&& Objects.equals(refreshSelection, that.refreshSelection)
+ && Objects.equals(refreshSelectionByPath, that.refreshSelectionByPath)
&& Objects.equals(state, that.state)
&& Objects.equals(updateId, that.updateId)
&& Objects.equals(validateOnly, that.validateOnly);
@@ -226,10 +254,12 @@ public int hashCode() {
creationTime,
fullRefresh,
fullRefreshSelection,
+ fullRefreshSelectionByPath,
mode,
parameters,
pipelineId,
refreshSelection,
+ refreshSelectionByPath,
state,
updateId,
validateOnly);
@@ -244,10 +274,12 @@ public String toString() {
.add("creationTime", creationTime)
.add("fullRefresh", fullRefresh)
.add("fullRefreshSelection", fullRefreshSelection)
+ .add("fullRefreshSelectionByPath", fullRefreshSelectionByPath)
.add("mode", mode)
.add("parameters", parameters)
.add("pipelineId", pipelineId)
.add("refreshSelection", refreshSelection)
+ .add("refreshSelectionByPath", refreshSelectionByPath)
.add("state", state)
.add("updateId", updateId)
.add("validateOnly", validateOnly)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/Sandbox.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/Sandbox.java
index 1df20fab0..b02dfce34 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/Sandbox.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/Sandbox.java
@@ -19,6 +19,10 @@ public class Sandbox {
@JsonProperty("display_name")
private String displayName;
+ /** Metadata associated with the sandbox. */
+ @JsonProperty("metadata")
+ private SandboxMetadata metadata;
+
/**
* The sandbox resource name, in the form `sandboxes/{sandbox_id}`. Derived from `sandbox_id`; any
* value supplied in a create or update request body is ignored.
@@ -56,6 +60,15 @@ public String getDisplayName() {
return displayName;
}
+ public Sandbox setMetadata(SandboxMetadata metadata) {
+ this.metadata = metadata;
+ return this;
+ }
+
+ public SandboxMetadata getMetadata() {
+ return metadata;
+ }
+
public Sandbox setName(String name) {
this.name = name;
return this;
@@ -99,6 +112,7 @@ public boolean equals(Object o) {
Sandbox that = (Sandbox) o;
return Objects.equals(createTime, that.createTime)
&& Objects.equals(displayName, that.displayName)
+ && Objects.equals(metadata, that.metadata)
&& Objects.equals(name, that.name)
&& Objects.equals(spec, that.spec)
&& Objects.equals(status, that.status)
@@ -107,7 +121,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- return Objects.hash(createTime, displayName, name, spec, status, updateTime);
+ return Objects.hash(createTime, displayName, metadata, name, spec, status, updateTime);
}
@Override
@@ -115,6 +129,7 @@ public String toString() {
return new ToStringer(Sandbox.class)
.add("createTime", createTime)
.add("displayName", displayName)
+ .add("metadata", metadata)
.add("name", name)
.add("spec", spec)
.add("status", status)
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/SandboxMetadata.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/SandboxMetadata.java
new file mode 100644
index 000000000..866566507
--- /dev/null
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sandbox/SandboxMetadata.java
@@ -0,0 +1,47 @@
+// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
+
+package com.databricks.sdk.service.sandbox;
+
+import com.databricks.sdk.support.Generated;
+import com.databricks.sdk.support.ToStringer;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import java.util.Objects;
+
+/** Metadata associated with a sandbox. */
+@Generated
+public class SandboxMetadata {
+ /**
+ * Key-value tags associated with the sandbox. Supports up to 54 tags. Keys must be between 1 and
+ * 512 characters, and values must not exceed 256 characters.
+ */
+ @JsonProperty("custom_tags")
+ private Map customTags;
+
+ public SandboxMetadata setCustomTags(Map customTags) {
+ this.customTags = customTags;
+ return this;
+ }
+
+ public Map getCustomTags() {
+ return customTags;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SandboxMetadata that = (SandboxMetadata) o;
+ return Objects.equals(customTags, that.customTags);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(customTags);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringer(SandboxMetadata.class).add("customTags", customTags).toString();
+ }
+}
diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sharing/SharedDataObject.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sharing/SharedDataObject.java
index 071f11697..4d1d1452b 100644
--- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sharing/SharedDataObject.java
+++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/sharing/SharedDataObject.java
@@ -104,7 +104,8 @@ public class SharedDataObject {
* A user-provided alias name for non-table data objects within the share.
*
* Use this field for non-table objects (for example: VOLUME, MODEL, NOTEBOOK_FILE, FUNCTION).
- * For table-like objects (for example: TABLE, VIEW, MATERIALIZED_VIEW, STREAMING_TABLE,
+ *
+ *
For table-like objects (for example: TABLE, VIEW, MATERIALIZED_VIEW, STREAMING_TABLE,
* FOREIGN_TABLE), use `shared_as` instead.
*
*
Important: For table-like objects, this field must be omitted entirely.
@@ -113,9 +114,10 @@ public class SharedDataObject {
* "data_schema.ml_models") - For FUNCTION: Must be a 2-part name `.`
* (e.g., "udf_schema.calculate_tax") - For MODEL: Must be a 2-part name
* `.` (e.g., "models.prediction_model") - For NOTEBOOK_FILE: Should be
- * the notebook file name (e.g., "analysis_notebook.py") - All names must contain only
- * alphanumeric characters and underscores - No periods, spaces, forward slashes, or control
- * characters are allowed within each part
+ * the notebook file name (e.g., "analysis_notebook.py")
+ *
+ * - All names must contain only alphanumeric characters and underscores - No periods, spaces,
+ * forward slashes, or control characters are allowed within each part
*
*
Behavior: - If not provided, the service automatically generates the alias from the object's
* original name - If you don't want to specify this field, omit it entirely from the request (do
@@ -123,8 +125,10 @@ public class SharedDataObject {
* type within the share
*
*
Examples: - Valid for VOLUME: "data_schema.training_data" - Valid for FUNCTION:
- * "analytics.calculate_revenue" - Invalid: "catalog.data_schema.training_data" (3 parts not
- * allowed for volumes) - Invalid: "data-schema.training-data" (hyphens not allowed)
+ * "analytics.calculate_revenue"
+ *
+ *
- Invalid: "catalog.data_schema.training_data" (3 parts not allowed for volumes) - Invalid:
+ * "data-schema.training-data" (hyphens not allowed)
*/
@JsonProperty("string_shared_as")
private String stringSharedAs;
diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/GoogleAuthCompatibilityTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/GoogleAuthCompatibilityTest.java
new file mode 100644
index 000000000..740d93c3b
--- /dev/null
+++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/GoogleAuthCompatibilityTest.java
@@ -0,0 +1,248 @@
+package com.databricks.sdk.core;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.auth.oauth2.AccessToken;
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.auth.oauth2.ServiceAccountCredentials;
+import com.google.auth.oauth2.UserCredentials;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Signature;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class GoogleAuthCompatibilityTest {
+ private HttpServer tokenServer;
+ private URI tokenServerUri;
+ private final AtomicReference requestBody = new AtomicReference<>();
+ private volatile int responseCode = 200;
+ private volatile String responseBody =
+ "{\"access_token\":\"refreshed-token\",\"expires_in\":3600,\"token_type\":\"Bearer\","
+ + "\"issued_token_type\":\"urn:ietf:params:oauth:token-type:access_token\"}";
+
+ @BeforeEach
+ void startTokenServer() throws IOException {
+ tokenServer = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
+ tokenServer.createContext("/token", this::respondToTokenRequest);
+ tokenServer.createContext(
+ "/subject",
+ exchange -> {
+ byte[] subjectToken = "external-subject-token".getBytes(StandardCharsets.UTF_8);
+ exchange.sendResponseHeaders(200, subjectToken.length);
+ try {
+ exchange.getResponseBody().write(subjectToken);
+ } finally {
+ exchange.close();
+ }
+ });
+ tokenServer.start();
+ tokenServerUri =
+ URI.create("http://127.0.0.1:" + tokenServer.getAddress().getPort() + "/token");
+ }
+
+ @AfterEach
+ void stopTokenServer() {
+ if (tokenServer != null) {
+ tokenServer.stop(0);
+ }
+ }
+
+ @Test
+ void addsBearerTokenToRequestMetadata() throws IOException {
+ GoogleCredentials credentials =
+ GoogleCredentials.create(
+ new AccessToken("test-token", new Date(System.currentTimeMillis() + 3600000)));
+
+ assertEquals(
+ Collections.singletonList("Bearer test-token"),
+ credentials
+ .getRequestMetadata(URI.create("https://storage.googleapis.com/"))
+ .get("Authorization"));
+ }
+
+ @Test
+ void parsesUserCredentialsWithPinnedHttpDependencies() throws IOException {
+ String credentialJson =
+ "{\"type\":\"authorized_user\",\"client_id\":\"test-client\","
+ + "\"client_secret\":\"test-secret\",\"refresh_token\":\"test-refresh\"}";
+
+ try (ByteArrayInputStream input =
+ new ByteArrayInputStream(credentialJson.getBytes(StandardCharsets.UTF_8))) {
+ UserCredentials credentials = UserCredentials.fromStream(input);
+
+ assertEquals("test-client", credentials.getClientId());
+ assertEquals("test-secret", credentials.getClientSecret());
+ assertEquals("test-refresh", credentials.getRefreshToken());
+ }
+ }
+
+ @Test
+ void refreshesUserCredentialsWithPinnedHttpDependencies() throws IOException {
+ UserCredentials credentials =
+ UserCredentials.newBuilder()
+ .setClientId("test-client")
+ .setClientSecret("test-secret")
+ .setRefreshToken("test-refresh")
+ .setTokenServerUri(tokenServerUri)
+ .build();
+
+ credentials.refresh();
+
+ assertRefreshedToken(credentials);
+ Map form = requestForm();
+ assertEquals("refresh_token", form.get("grant_type"));
+ assertEquals("test-client", form.get("client_id"));
+ assertEquals("test-secret", form.get("client_secret"));
+ assertEquals("test-refresh", form.get("refresh_token"));
+ }
+
+ @Test
+ void refreshesServiceAccountWithPinnedHttpDependencies() throws Exception {
+ KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
+ keyGenerator.initialize(2048);
+ KeyPair keyPair = keyGenerator.generateKeyPair();
+ ServiceAccountCredentials credentials =
+ ServiceAccountCredentials.newBuilder()
+ .setClientEmail("test-account@example.com")
+ .setPrivateKey(keyPair.getPrivate())
+ .setPrivateKeyId("test-key")
+ .setScopes(Collections.singletonList("https://www.googleapis.com/auth/cloud-platform"))
+ .setTokenServerUri(tokenServerUri)
+ .build();
+
+ credentials.refresh();
+
+ assertRefreshedToken(credentials);
+ Map form = requestForm();
+ assertEquals("urn:ietf:params:oauth:grant-type:jwt-bearer", form.get("grant_type"));
+ String[] assertion = form.get("assertion").split("\\.");
+ JsonNode claims = new ObjectMapper().readTree(Base64.getUrlDecoder().decode(assertion[1]));
+ assertEquals("test-account@example.com", claims.get("iss").asText());
+ assertEquals("https://oauth2.googleapis.com/token", claims.get("aud").asText());
+ assertEquals("https://www.googleapis.com/auth/cloud-platform", claims.get("scope").asText());
+ Signature verifier = Signature.getInstance("SHA256withRSA");
+ verifier.initVerify(keyPair.getPublic());
+ verifier.update((assertion[0] + "." + assertion[1]).getBytes(StandardCharsets.UTF_8));
+ assertTrue(verifier.verify(Base64.getUrlDecoder().decode(assertion[2])));
+ }
+
+ @Test
+ void exchangesExternalAccountTokenWithPinnedHttpDependencies() throws IOException {
+ String audience =
+ "//iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/test/providers/test";
+ String credentialJson =
+ "{\"type\":\"external_account\",\"audience\":\""
+ + audience
+ + "\",\"subject_token_type\":\"urn:ietf:params:oauth:token-type:jwt\",\"token_url\":\""
+ + "https://sts.googleapis.com/v1/token"
+ + "\",\"credential_source\":{\"url\":\""
+ + tokenServerUri.resolve("/subject")
+ + "\"}}";
+ GoogleCredentials credentials;
+ try (ByteArrayInputStream input =
+ new ByteArrayInputStream(credentialJson.getBytes(StandardCharsets.UTF_8))) {
+ NetHttpTransport transport =
+ new NetHttpTransport.Builder()
+ .setConnectionFactory(
+ url -> {
+ URI localUri =
+ url.getHost().equals("sts.googleapis.com")
+ ? tokenServerUri
+ : tokenServerUri.resolve("/subject");
+ return (HttpURLConnection) localUri.toURL().openConnection();
+ })
+ .build();
+ credentials =
+ GoogleCredentials.fromStream(input, () -> transport)
+ .createScoped(
+ Collections.singletonList("https://www.googleapis.com/auth/cloud-platform"));
+ }
+
+ credentials.refresh();
+
+ assertRefreshedToken(credentials);
+ Map form = requestForm();
+ assertEquals("urn:ietf:params:oauth:grant-type:token-exchange", form.get("grant_type"));
+ assertEquals("external-subject-token", form.get("subject_token"));
+ assertEquals(audience, form.get("audience"));
+ assertEquals("urn:ietf:params:oauth:token-type:jwt", form.get("subject_token_type"));
+ }
+
+ @Test
+ void propagatesTokenEndpointErrorsWithPinnedHttpDependencies() {
+ responseCode = 400;
+ responseBody = "{\"error\":\"invalid_grant\",\"error_description\":\"Refresh token revoked\"}";
+ UserCredentials credentials =
+ UserCredentials.newBuilder()
+ .setClientId("test-client")
+ .setClientSecret("test-secret")
+ .setRefreshToken("revoked-refresh")
+ .setTokenServerUri(tokenServerUri)
+ .build();
+
+ IOException failure = assertThrows(IOException.class, credentials::refresh);
+
+ assertTrue(failure.getMessage().contains("invalid_grant"));
+ }
+
+ private void assertRefreshedToken(GoogleCredentials credentials) throws IOException {
+ assertEquals("refreshed-token", credentials.getAccessToken().getTokenValue());
+ assertTrue(credentials.getAccessToken().getExpirationTime().after(new Date()));
+ assertEquals(
+ Collections.singletonList("Bearer refreshed-token"),
+ credentials
+ .getRequestMetadata(URI.create("https://storage.googleapis.com/"))
+ .get("Authorization"));
+ }
+
+ private Map requestForm() throws IOException {
+ Map form = new HashMap<>();
+ for (String field : requestBody.get().split("&")) {
+ String[] pair = field.split("=", 2);
+ form.put(URLDecoder.decode(pair[0], "UTF-8"), URLDecoder.decode(pair[1], "UTF-8"));
+ }
+ return form;
+ }
+
+ private void respondToTokenRequest(HttpExchange exchange) throws IOException {
+ try (InputStream input = exchange.getRequestBody();
+ ByteArrayOutputStream body = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = input.read(buffer)) != -1) {
+ body.write(buffer, 0, length);
+ }
+ requestBody.set(new String(body.toByteArray(), StandardCharsets.UTF_8));
+ byte[] content = responseBody.getBytes(StandardCharsets.UTF_8);
+ exchange.getResponseHeaders().set("Content-Type", "application/json");
+ exchange.sendResponseHeaders(responseCode, content.length);
+ exchange.getResponseBody().write(content);
+ } finally {
+ exchange.close();
+ }
+ }
+}
diff --git a/examples/docs/pom.xml b/examples/docs/pom.xml
index 780c9e084..fed6fdb4f 100644
--- a/examples/docs/pom.xml
+++ b/examples/docs/pom.xml
@@ -24,7 +24,7 @@
com.databricks
databricks-sdk-java
- 0.170.0
+ 0.171.0
diff --git a/examples/spring-boot-oauth-u2m-demo/pom.xml b/examples/spring-boot-oauth-u2m-demo/pom.xml
index 082d91eea..e05f0662d 100644
--- a/examples/spring-boot-oauth-u2m-demo/pom.xml
+++ b/examples/spring-boot-oauth-u2m-demo/pom.xml
@@ -40,7 +40,7 @@
com.databricks
databricks-sdk-java
- 0.170.0
+ 0.171.0
diff --git a/lockfile.json b/lockfile.json
index 032d01367..3fa5db068 100644
--- a/lockfile.json
+++ b/lockfile.json
@@ -1,15 +1,15 @@
{
"artifactId": "databricks-sdk-parent",
"groupId": "com.databricks",
- "version": "0.170.0",
+ "version": "0.171.0",
"lockFileVersion": 1,
"dependencies": [],
"mavenPlugins": [],
"metaData": {
"environment": {
- "osName": "Mac OS X",
- "mavenVersion": "3.9.14",
- "javaVersion": "11.0.12"
+ "osName": "Linux",
+ "mavenVersion": "3.9.9",
+ "javaVersion": "17.0.3"
},
"config": {
"includeMavenPlugins": false,
diff --git a/pom.xml b/pom.xml
index a778682c4..b46b8ed23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.databricks
databricks-sdk-parent
- 0.170.0
+ 0.171.0
pom
Databricks SDK for Java
The Databricks SDK for Java includes functionality to accelerate development with Java for
@@ -65,7 +65,7 @@
com.google.auto.value
auto-value
- 1.10.4
+ 1.11.1
diff --git a/shaded/pom.xml b/shaded/pom.xml
index 7b05b9806..15c21067f 100644
--- a/shaded/pom.xml
+++ b/shaded/pom.xml
@@ -4,7 +4,7 @@
4.0.0
- 0.170.0
+ 0.171.0
com.databricks