Skip to content

Commit e63c4be

Browse files
committed
fix create_table
1 parent dab8e51 commit e63c4be

File tree

2 files changed

+149
-17
lines changed

2 files changed

+149
-17
lines changed

crates/catalog/s3tables/src/catalog.rs

Lines changed: 146 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,18 @@ impl S3TablesCatalog {
6262

6363
#[async_trait]
6464
impl Catalog for S3TablesCatalog {
65+
/// List namespaces from s3tables catalog.
66+
///
67+
/// S3Tables doesn't support nested namespaces. If parent is provided, it will
68+
/// return an empty list.
6569
async fn list_namespaces(
6670
&self,
6771
parent: Option<&NamespaceIdent>,
6872
) -> Result<Vec<NamespaceIdent>> {
73+
if parent.is_some() {
74+
return Ok(vec![]);
75+
}
76+
6977
let mut result = Vec::new();
7078
let mut continuation_token = None;
7179
loop {
@@ -91,6 +99,22 @@ impl Catalog for S3TablesCatalog {
9199
Ok(result)
92100
}
93101

102+
/// Creates a new namespace with the given identifier and properties.
103+
///
104+
/// Attempts to create a namespace defined by the `namespace`. The `properties`
105+
/// parameter is ignored.
106+
///
107+
/// The following naming rules apply to namespaces:
108+
///
109+
/// - Names must be between 3 (min) and 63 (max) characters long.
110+
/// - Names can consist only of lowercase letters, numbers, and underscores (_).
111+
/// - Names must begin and end with a letter or number.
112+
/// - Names must not contain hyphens (-) or periods (.).
113+
///
114+
/// This function can return an error in the following situations:
115+
///
116+
/// - Errors from the underlying database creation process, converted using
117+
/// `from_aws_sdk_error`.
94118
async fn create_namespace(
95119
&self,
96120
namespace: &NamespaceIdent,
@@ -108,6 +132,15 @@ impl Catalog for S3TablesCatalog {
108132
))
109133
}
110134

135+
/// Retrieves a namespace by its identifier.
136+
///
137+
/// Validates the given namespace identifier and then queries the
138+
/// underlying database client to fetch the corresponding namespace data.
139+
/// Constructs a `Namespace` object with the retrieved data and returns it.
140+
///
141+
/// This function can return an error in any of the following situations:
142+
/// - If there is an error querying the database, returned by
143+
/// `from_aws_sdk_error`.
111144
async fn get_namespace(&self, namespace: &NamespaceIdent) -> Result<Namespace> {
112145
let req = self
113146
.s3tables_client
@@ -122,6 +155,18 @@ impl Catalog for S3TablesCatalog {
122155
))
123156
}
124157

158+
/// Checks if a namespace exists within the s3tables catalog.
159+
///
160+
/// Validates the namespace identifier by querying the s3tables catalog
161+
/// to determine if the specified namespace exists.
162+
///
163+
/// # Returns
164+
/// A `Result<bool>` indicating the outcome of the check:
165+
/// - `Ok(true)` if the namespace exists.
166+
/// - `Ok(false)` if the namespace does not exist, identified by a specific
167+
/// `IsNotFoundException` variant.
168+
/// - `Err(...)` if an error occurs during validation or the s3tables catalog
169+
/// query, with the error encapsulating the issue.
125170
async fn namespace_exists(&self, namespace: &NamespaceIdent) -> Result<bool> {
126171
let req = self
127172
.s3tables_client
@@ -140,17 +185,29 @@ impl Catalog for S3TablesCatalog {
140185
}
141186
}
142187

188+
/// Updates the properties of an existing namespace.
189+
///
190+
/// S3Tables doesn't support updating namespace properties, so this function
191+
/// will always return an error.
143192
async fn update_namespace(
144193
&self,
145-
namespace: &NamespaceIdent,
146-
properties: HashMap<String, String>,
194+
_namespace: &NamespaceIdent,
195+
_properties: HashMap<String, String>,
147196
) -> Result<()> {
148197
Err(Error::new(
149198
ErrorKind::FeatureUnsupported,
150199
"Update namespace is not supported for s3tables catalog",
151200
))
152201
}
153202

203+
/// Drops an existing namespace from the s3tables catalog.
204+
///
205+
/// Validates the namespace identifier and then deletes the corresponding
206+
/// namespace from the s3tables catalog.
207+
///
208+
/// This function can return an error in the following situations:
209+
/// - Errors from the underlying database deletion process, converted using
210+
/// `from_aws_sdk_error`.
154211
async fn drop_namespace(&self, namespace: &NamespaceIdent) -> Result<()> {
155212
let req = self
156213
.s3tables_client
@@ -161,6 +218,14 @@ impl Catalog for S3TablesCatalog {
161218
Ok(())
162219
}
163220

221+
/// Lists all tables within a given namespace.
222+
///
223+
/// Retrieves all tables associated with the specified namespace and returns
224+
/// their identifiers.
225+
///
226+
/// This function can return an error in the following situations:
227+
/// - Errors from the underlying database query process, converted using
228+
/// `from_aws_sdk_error`.
164229
async fn list_tables(&self, namespace: &NamespaceIdent) -> Result<Vec<TableIdent>> {
165230
let mut result = Vec::new();
166231
let mut continuation_token = None;
@@ -188,37 +253,65 @@ impl Catalog for S3TablesCatalog {
188253
Ok(result)
189254
}
190255

256+
/// Creates a new table within a specified namespace.
257+
///
258+
/// Attempts to create a table defined by the `creation` parameter. The metadata
259+
/// location is generated by the s3tables catalog, looks like:
260+
///
261+
/// s3://{RANDOM WAREHOUSE LOCATION}/metadata/{VERSION}-{UUID}.metadata.json
262+
///
263+
/// We have to get this random warehouse location after the table is created.
264+
///
265+
/// This function can return an error in the following situations:
266+
/// - Errors from the underlying database creation process, converted using
267+
/// `from_aws_sdk_error`.
191268
async fn create_table(
192269
&self,
193270
namespace: &NamespaceIdent,
194271
creation: TableCreation,
195272
) -> Result<Table> {
196273
let table_ident = TableIdent::new(namespace.clone(), creation.name.clone());
197274

275+
// create table
276+
let create_resp: CreateTableOutput = self
277+
.s3tables_client
278+
.create_table()
279+
.table_bucket_arn(self.config.table_bucket_arn.clone())
280+
.namespace(namespace.to_url_string())
281+
.name(table_ident.name())
282+
.send()
283+
.await
284+
.map_err(from_aws_sdk_error)?;
285+
286+
// get warehouse location
287+
let get_resp: GetTableOutput = self
288+
.s3tables_client
289+
.get_table()
290+
.table_bucket_arn(self.config.table_bucket_arn.clone())
291+
.namespace(namespace.to_url_string())
292+
.name(table_ident.name())
293+
.send()
294+
.await
295+
.map_err(from_aws_sdk_error)?;
296+
297+
// write metadata to file
198298
let metadata = TableMetadataBuilder::from_table_creation(creation)?
199299
.build()?
200300
.metadata;
201-
let metadata_location =
202-
create_metadata_location(namespace.to_url_string(), table_ident.name(), 0)?;
301+
let metadata_location = create_metadata_location(get_resp.warehouse_location(), 0)?;
203302
self.file_io
204303
.new_output(&metadata_location)?
205304
.write(serde_json::to_vec(&metadata)?.into())
206305
.await?;
207306

208-
self.s3tables_client
209-
.create_table()
210-
.table_bucket_arn(self.config.table_bucket_arn.clone())
211-
.namespace(namespace.to_url_string())
212-
.name(table_ident.name())
213-
.send()
214-
.await
215-
.map_err(from_aws_sdk_error)?;
307+
// update metadata location
216308
self.s3tables_client
217309
.update_table_metadata_location()
218310
.table_bucket_arn(self.config.table_bucket_arn.clone())
219311
.namespace(namespace.to_url_string())
220312
.name(table_ident.name())
221313
.metadata_location(metadata_location.clone())
314+
.version_token(create_resp.version_token())
222315
.send()
223316
.await
224317
.map_err(from_aws_sdk_error)?;
@@ -232,6 +325,16 @@ impl Catalog for S3TablesCatalog {
232325
Ok(table)
233326
}
234327

328+
/// Loads an existing table from the s3tables catalog.
329+
///
330+
/// Retrieves the metadata location of the specified table and constructs a
331+
/// `Table` object with the retrieved metadata.
332+
///
333+
/// This function can return an error in the following situations:
334+
/// - If the table does not have a metadata location, identified by a specific
335+
/// `Unexpected` variant.
336+
/// - Errors from the underlying database query process, converted using
337+
/// `from_aws_sdk_error`.
235338
async fn load_table(&self, table_ident: &TableIdent) -> Result<Table> {
236339
let req = self
237340
.s3tables_client
@@ -263,6 +366,14 @@ impl Catalog for S3TablesCatalog {
263366
Ok(table)
264367
}
265368

369+
/// Drops an existing table from the s3tables catalog.
370+
///
371+
/// Validates the table identifier and then deletes the corresponding
372+
/// table from the s3tables catalog.
373+
///
374+
/// This function can return an error in the following situations:
375+
/// - Errors from the underlying database deletion process, converted using
376+
/// `from_aws_sdk_error`.
266377
async fn drop_table(&self, table: &TableIdent) -> Result<()> {
267378
let req = self
268379
.s3tables_client
@@ -274,6 +385,18 @@ impl Catalog for S3TablesCatalog {
274385
Ok(())
275386
}
276387

388+
/// Checks if a table exists within the s3tables catalog.
389+
///
390+
/// Validates the table identifier by querying the s3tables catalog
391+
/// to determine if the specified table exists.
392+
///
393+
/// # Returns
394+
/// A `Result<bool>` indicating the outcome of the check:
395+
/// - `Ok(true)` if the table exists.
396+
/// - `Ok(false)` if the table does not exist, identified by a specific
397+
/// `IsNotFoundException` variant.
398+
/// - `Err(...)` if an error occurs during validation or the s3tables catalog
399+
/// query, with the error encapsulating the issue.
277400
async fn table_exists(&self, table_ident: &TableIdent) -> Result<bool> {
278401
let req = self
279402
.s3tables_client
@@ -293,6 +416,14 @@ impl Catalog for S3TablesCatalog {
293416
}
294417
}
295418

419+
/// Renames an existing table within the s3tables catalog.
420+
///
421+
/// Validates the source and destination table identifiers and then renames
422+
/// the source table to the destination table.
423+
///
424+
/// This function can return an error in the following situations:
425+
/// - Errors from the underlying database renaming process, converted using
426+
/// `from_aws_sdk_error`.
296427
async fn rename_table(&self, src: &TableIdent, dest: &TableIdent) -> Result<()> {
297428
let req = self
298429
.s3tables_client
@@ -306,6 +437,9 @@ impl Catalog for S3TablesCatalog {
306437
Ok(())
307438
}
308439

440+
/// Updates an existing table within the s3tables catalog.
441+
///
442+
/// This function is still in development and will always return an error.
309443
async fn update_table(&self, commit: TableCommit) -> Result<Table> {
310444
Err(Error::new(
311445
ErrorKind::FeatureUnsupported,

crates/catalog/s3tables/src/utils.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ pub(crate) async fn create_sdk_config(
5757

5858
/// Create metadata location from `location` and `version`
5959
pub(crate) fn create_metadata_location(
60-
namespace: impl AsRef<str>,
61-
table_name: impl AsRef<str>,
60+
warehouse_location: impl AsRef<str>,
6261
version: i32,
6362
) -> Result<String> {
6463
if version < 0 {
@@ -74,9 +73,8 @@ pub(crate) fn create_metadata_location(
7473
let version = format!("{:0>5}", version);
7574
let id = Uuid::new_v4();
7675
let metadata_location = format!(
77-
"{}/{}/metadata/{}-{}.metadata.json",
78-
namespace.as_ref(),
79-
table_name.as_ref(),
76+
"{}/metadata/{}-{}.metadata.json",
77+
warehouse_location.as_ref(),
8078
version,
8179
id
8280
);

0 commit comments

Comments
 (0)