hotdata 0.7.0

Powerful data platform API for datasets, queries, and analytics.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
/*
 * Hotdata API
 *
 * Powerful data platform API for managed databases, queries, and analytics.
 *
 * The version of the OpenAPI document: 1.0.0
 * Contact: developers@hotdata.dev
 * Generated by: https://openapi-generator.tech
 */

use super::{configuration, ContentType, Error};
use crate::{apis::ResponseContent, models};
use reqwest;
use serde::{de::Error as _, Deserialize, Serialize};
use tokio::fs::File as TokioFile;
use tokio_util::codec::{BytesCodec, FramedRead};

/// struct for typed errors of method [`create_upload_session_handler`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CreateUploadSessionHandlerError {
    Status400(models::ApiErrorResponse),
    Status501(models::ApiErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`create_upload_sessions_batch_handler`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CreateUploadSessionsBatchHandlerError {
    Status400(models::ApiErrorResponse),
    Status501(models::ApiErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`finalize_upload_handler`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FinalizeUploadHandlerError {
    Status400(models::ApiErrorResponse),
    Status404(models::ApiErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`list_uploads`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListUploadsError {
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`mint_upload_parts_handler`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MintUploadPartsHandlerError {
    Status400(models::ApiErrorResponse),
    Status404(models::ApiErrorResponse),
    Status501(models::ApiErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`upload_file`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UploadFileError {
    Status400(models::ApiErrorResponse),
    UnknownValue(serde_json::Value),
}

/// Create an upload session for a file you will send directly to storage. The response is one of three shapes. For a small file (`mode: single`) it contains a short-lived `url` to `PUT` the whole file to. For a large file with a known size (`mode: multipart`) it contains `part_urls` and `part_size`: split the file into `part_size`-byte chunks (the last is the remainder) and `PUT` chunk *i* (1-based) to `part_urls[i - 1]`, keeping each response's `ETag`. Slice by `part_size`, not by an even division across `part_urls.len()` (which can make a non-final part too small). For a file whose size you do not know up front, omit `declared_size_bytes`: the response is `mode: multipart` with a `part_size` but NO `part_urls`. As you stream, call `POST /v1/uploads/{upload_id}/parts` with a batch of `part_numbers` to mint per-part `PUT` URLs, `PUT` each part and keep its `ETag`, then finalize as for any multipart upload. In all cases the response also includes a one-time `finalize_token`. After uploading, call the finalize endpoint with the token (and, for multipart, the `{part_number, e_tag}` list) to make the upload usable as managed-table contents. The returned upload ID can then be passed to the managed-table load endpoint.  You may hint a preferred part size with `part_size`; the service clamps it to the allowed range and ignores it for single-`PUT` uploads.  If the response status is `501` with error code `PRESIGN_UNSUPPORTED`, the configured storage backend cannot issue upload URLs; send the file to the `POST /v1/files` endpoint instead.
pub async fn create_upload_session_handler(
    configuration: &configuration::Configuration,
    create_upload_request: models::CreateUploadRequest,
) -> Result<models::UploadSessionResponse, Error<CreateUploadSessionHandlerError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_create_upload_request = create_upload_request;

    let uri_str = format!("{}/v1/uploads", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };
    req_builder = req_builder.json(&p_body_create_upload_request);

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UploadSessionResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UploadSessionResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<CreateUploadSessionHandlerError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Create upload sessions for several files in one request. Each file is planned independently and the response returns one session per requested file, in the same order. Each session is finalized separately via the finalize endpoint, so you can upload and finalize files at your own pace.  If the response status is `501` with error code `PRESIGN_UNSUPPORTED`, the configured storage backend cannot issue upload URLs; send each file to the `POST /v1/files` endpoint instead.
pub async fn create_upload_sessions_batch_handler(
    configuration: &configuration::Configuration,
    batch_create_upload_request: models::BatchCreateUploadRequest,
) -> Result<models::BatchCreateUploadResponse, Error<CreateUploadSessionsBatchHandlerError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_batch_create_upload_request = batch_create_upload_request;

    let uri_str = format!("{}/v1/uploads/batch", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };
    req_builder = req_builder.json(&p_body_batch_create_upload_request);

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::BatchCreateUploadResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::BatchCreateUploadResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<CreateUploadSessionsBatchHandlerError> =
            serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Confirm that a file has been uploaded to storage and make it usable as managed-table contents. Supply the `finalize_token` returned when the session was created, in the `X-Upload-Finalize-Token` header. When you declared a size at create time, the uploaded file's size is validated against it and a mismatch is rejected. An upload created without a declared size is finalized from its uploaded parts; it must be non-empty and is rejected if it exceeds the server's maximum upload size. Finalize is exactly-once: a second finalize of the same upload is rejected.
pub async fn finalize_upload_handler(
    configuration: &configuration::Configuration,
    upload_id: &str,
    x_upload_finalize_token: &str,
    finalize_upload_request: Option<models::FinalizeUploadRequest>,
) -> Result<models::FinalizeUploadResponse, Error<FinalizeUploadHandlerError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_upload_id = upload_id;
    let p_header_x_upload_finalize_token = x_upload_finalize_token;
    let p_body_finalize_upload_request = finalize_upload_request;

    let uri_str = format!(
        "{}/v1/uploads/{upload_id}/finalize",
        configuration.base_path,
        upload_id = crate::apis::urlencode(p_path_upload_id)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    req_builder = req_builder.header(
        "X-Upload-Finalize-Token",
        p_header_x_upload_finalize_token.to_string(),
    );
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };
    req_builder = req_builder.json(&p_body_finalize_upload_request);

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FinalizeUploadResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FinalizeUploadResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<FinalizeUploadHandlerError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

pub async fn list_uploads(
    configuration: &configuration::Configuration,
    status: Option<&str>,
) -> Result<models::ListUploadsResponse, Error<ListUploadsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_status = status;

    let uri_str = format!("{}/v1/files", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_status {
        req_builder = req_builder.query(&[("status", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ListUploadsResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ListUploadsResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<ListUploadsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Mint short-lived presigned URLs for specific parts of a multi-part upload. This is required for a streaming (unknown-size) upload — created by omitting the declared size — which mints no part URLs up front. It also works for a known-size multi-part upload: use it to re-mint a part whose URL expired before you uploaded that part. Supply the `finalize_token` returned when the session was created, in the `X-Upload-Finalize-Token` header, and the 1-based `part_numbers` you want URLs for. `PUT` each part's bytes to its URL, keep each response's `ETag`, then pass the `{part_number, e_tag}` list to finalize. You may mint parts in batches as you upload, and re-mint a part number whose URL expired before you finished uploading it.
pub async fn mint_upload_parts_handler(
    configuration: &configuration::Configuration,
    upload_id: &str,
    x_upload_finalize_token: &str,
    mint_upload_parts_request: models::MintUploadPartsRequest,
) -> Result<models::MintUploadPartsResponse, Error<MintUploadPartsHandlerError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_upload_id = upload_id;
    let p_header_x_upload_finalize_token = x_upload_finalize_token;
    let p_body_mint_upload_parts_request = mint_upload_parts_request;

    let uri_str = format!(
        "{}/v1/uploads/{upload_id}/parts",
        configuration.base_path,
        upload_id = crate::apis::urlencode(p_path_upload_id)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    req_builder = req_builder.header(
        "X-Upload-Finalize-Token",
        p_header_x_upload_finalize_token.to_string(),
    );
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };
    req_builder = req_builder.json(&p_body_mint_upload_parts_request);

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::MintUploadPartsResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::MintUploadPartsResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<MintUploadPartsHandlerError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Upload a Parquet file to publish as the contents of a managed table. Send the raw file bytes as the request body with an appropriate Content-Type header (e.g., `application/parquet`). The body is streamed to disk, so files up to 20GB are supported. The returned upload ID can be passed to the managed-table load endpoint.
pub async fn upload_file(
    configuration: &configuration::Configuration,
    body: std::path::PathBuf,
) -> Result<models::UploadResponse, Error<UploadFileError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_body = body;

    let uri_str = format!("{}/v1/files", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(apikey) = configuration.api_keys.get("X-Workspace-Id") {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Workspace-Id", value);
    };
    if let Some(token) = configuration.resolve_bearer_token().await {
        req_builder = req_builder.bearer_auth(token);
    };
    let file = TokioFile::open(p_body_body).await?;
    let stream = FramedRead::new(file, BytesCodec::new());
    req_builder = req_builder.body(reqwest::Body::wrap_stream(stream));

    let req = req_builder.build()?;
    crate::http_log::log_request(&req);
    // Route through the shared retry helper so HTTP 429 (OVERLOADED admission
    // shedding) is retried per `configuration.retry` on every generated op, not
    // just the hand-written query path. See crate::http::execute_retrying.
    let resp =
        crate::http::execute_retrying(&configuration.client, req, &configuration.retry).await?;

    let status = resp.status();
    crate::http_log::log_response_status(status);
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UploadResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UploadResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        crate::http_log::log_response_body(&content);
        let entity: Option<UploadFileError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}