mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-08 13:07:45 +01:00
iceberg: support views (#10069)
* s3tables: tag table entries and exclude views from table listings * s3tables: add view CRUD operations * iceberg: support view create, load, exists, drop, and list * iceberg: support view update * iceberg: test view error classification and metadata round-trip * iceberg: pre-check existence and write view metadata only after create * iceberg: map view namespace-not-found to 404 * iceberg: test view create namespace-404 and duplicate no-clobber * s3tables: tag view metadata and entry type atomically CreateView wrote ExtendedKeyMetadata and ExtendedKeyEntryType in two UpdateEntry calls, so a partial failure could leave a view directory untagged. Add setExtendedAttributes to set both in one UpdateEntry. * iceberg: roll back view registration when metadata write fails The metadata file is written after the catalog registers the view. If that write fails, drop the just-created view so it doesn't linger pointing at a missing metadata.json. Reuse the DeleteView path via a shared dropView helper.
This commit is contained in:
1 parent
1ca628d3e9
commit
0403e47ef6
13 files changed
+1815
-3
No files matched your search
@@ -26,6 +26,12 @@ const (
|
||||
ExtendedKeyMetadataVersion = "s3tables.metadataVersion"
|
||||
ExtendedKeyPolicy = "s3tables.policy"
|
||||
ExtendedKeyTags = "s3tables.tags"
|
||||
ExtendedKeyEntryType = "s3tables.entryType"
|
||||
|
||||
// Entry-type marker values for ExtendedKeyEntryType. Absent or "table" means
|
||||
// a table; views are stored like tables but tagged "view".
|
||||
EntryTypeTable = "table"
|
||||
EntryTypeView = "view"
|
||||
|
||||
// Maximum request body size (10MB)
|
||||
maxRequestBodySize = 10 * 1024 * 1024
|
||||
@@ -153,6 +159,18 @@ func (h *S3TablesHandler) HandleRequest(w http.ResponseWriter, r *http.Request,
|
||||
case "DeleteTable":
|
||||
err = h.handleDeleteTable(w, r, filerClient)
|
||||
|
||||
// View operations
|
||||
case "CreateView":
|
||||
err = h.handleCreateView(w, r, filerClient)
|
||||
case "GetView":
|
||||
err = h.handleGetView(w, r, filerClient)
|
||||
case "ListViews":
|
||||
err = h.handleListViews(w, r, filerClient)
|
||||
case "UpdateView":
|
||||
err = h.handleUpdateView(w, r, filerClient)
|
||||
case "DeleteView":
|
||||
err = h.handleDeleteView(w, r, filerClient)
|
||||
|
||||
// Table Policy operations
|
||||
case "PutTablePolicy":
|
||||
err = h.handlePutTablePolicy(w, r, filerClient)
|
||||
@@ -363,6 +381,10 @@ func (h *S3TablesHandler) generateTableARN(ownerAccountID, bucketName, tableID s
|
||||
return fmt.Sprintf("arn:aws:s3tables:%s:%s:bucket/%s/table/%s", h.region, ownerAccountID, bucketName, tableID)
|
||||
}
|
||||
|
||||
func (h *S3TablesHandler) generateViewARN(ownerAccountID, bucketName, viewID string) string {
|
||||
return fmt.Sprintf("arn:aws:s3tables:%s:%s:bucket/%s/view/%s", h.region, ownerAccountID, bucketName, viewID)
|
||||
}
|
||||
|
||||
func isAuthError(err error) bool {
|
||||
var authErr *AuthError
|
||||
return errors.As(err, &authErr) || errors.Is(err, ErrAccessDenied)
|
||||
|
||||
Reference in new issue
Block a user