Skip to content

Commit c1577f9

Browse files
Wizzy-woozsergiimk
andauthored
Feature/306 use arrow schema instead of parquet schema in gql and cli (#555)
* Use Arrow schema instead of Parquet schema in GQL and CLI #306: draft * Use Arrow schema instead of Parquet schema in GQL and CLI #306: formatting * Use Arrow schema instead of Parquet schema in GQL and CLI #306 * Use Arrow schema instead of Parquet schema in GQL and CLI #306: updated Cargo.lock * Use Arrow schema instead of Parquet schema in GQL and CLI #306: updated Cargo.lock + corrections * Use Arrow schema instead of Parquet schema in GQL and CLI #306: removed unused dependency * Use Arrow schema instead of Parquet schema in GQL and CLI #306: changes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: changes after running clippy and tests * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes for tests * Use Arrow schema instead of Parquet schema in GQL and CLI #306: updated test group * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixing cargo files * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixing cargo files part 2 * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixing cargo files part 3 * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixing cargo files part 4 * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixing cargo files part 5 * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Use Arrow schema instead of Parquet schema in GQL and CLI #306: fixes after code review * Final tweaks * Restore schema default format to parquet-json, speed up block iteration --------- Co-authored-by: Sergii Mikhtoniuk <mikhtoniuk@gmail.com>
1 parent 5fb3fb4 commit c1577f9

21 files changed

Lines changed: 498 additions & 110 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## Unreleased
8+
### Added
9+
- Support `ArrowJson` schema output format in QGL API and CLI commands
10+
711
## [0.170.0] - 2024-03-29
812
### Added
913
- Added GrapqQL Dataset Endpoints object

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/cli-reference.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,9 @@ Shows the dataset schema
392392

393393
* `-o`, `--output-format <FMT>` — Format of an output
394394

395-
Possible values: `ddl`, `parquet`, `json`
395+
Possible values: `ddl`, `parquet`, `parquet-json`, `arrow-json`
396396

397+
* `--from-data-file`
397398

398399
Displays the schema of the dataset. Note that dataset schemas can evolve over time and by default the latest schema will be shown.
399400

resources/schema.gql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ type DataSchema {
228228
enum DataSchemaFormat {
229229
PARQUET
230230
PARQUET_JSON
231+
ARROW_JSON
231232
}
232233

233234
type DataSlice {

src/adapter/graphql/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ async-graphql = { version = "6", features = ["chrono", "url", "apollo_tracing"]
3636
async-trait = { version = "0.1", default-features = false }
3737
cron = { version = "0.12.0", default-features = false }
3838
chrono = "0.4"
39-
datafusion = { version = "36", default-features = false } # TODO: Currently needed for type conversions but ideally should be encapsulated by kamu-core
39+
datafusion = { version = "36", default-features = false, features = ["serde"] } # TODO: Currently needed for type conversions but ideally should be encapsulated by kamu-core
4040
dill = "0.8"
4141
futures = "0.3"
42-
serde = "1"
42+
serde = {version = "1", default-features = false }
4343
serde_json = "1"
4444
tokio = { version = "1", default-features = false, features = [] }
4545
tokio-stream = { version = "0.1", default-features = false }

src/adapter/graphql/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(crate) mod mutations;
1818
pub(crate) mod prelude;
1919
pub(crate) mod queries;
2020
mod root;
21-
pub(crate) mod scalars;
21+
pub mod scalars;
2222
pub(crate) mod utils;
2323

2424
pub use root::*;

src/adapter/graphql/src/queries/datasets/dataset_metadata.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,22 @@ impl DatasetMetadata {
7676
ctx: &Context<'_>,
7777
format: Option<DataSchemaFormat>,
7878
) -> Result<Option<DataSchema>> {
79+
// TODO: Default to Arrow eventually
7980
let format = format.unwrap_or(DataSchemaFormat::Parquet);
8081

8182
let query_svc = from_catalog::<dyn domain::QueryService>(ctx).unwrap();
82-
let res_schema = query_svc
83+
84+
if let Some(schema) = query_svc
8385
.get_schema(&self.dataset_handle.as_local_ref())
8486
.await
85-
.int_err()?;
86-
87-
match res_schema {
88-
Some(schema) => Ok(Some(DataSchema::from_parquet_schema(&schema, format)?)),
89-
None => Ok(None),
87+
.int_err()?
88+
{
89+
Ok(Option::from(DataSchema::from_arrow_schema(
90+
schema.as_ref(),
91+
format,
92+
)))
93+
} else {
94+
Ok(None)
9095
}
9196
}
9297

src/adapter/graphql/src/queries/datasets/metadata_chain.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// the Business Source License, use of this software will be governed
88
// by the Apache License, Version 2.0.
99

10-
use futures::TryStreamExt;
10+
use futures::{StreamExt, TryStreamExt};
1111
use kamu_core::{self as domain, MetadataChainExt};
1212
use opendatafabric as odf;
1313

@@ -111,7 +111,6 @@ impl MetadataChain {
111111

112112
// TODO: Add ref parameter (defaulting to "head")
113113
// TODO: Support before/after style iteration
114-
// TODO: PERF: Avoid traversing entire chain
115114
/// Iterates all metadata blocks in the reverse chronological order
116115
#[tracing::instrument(level = "info", skip_all)]
117116
async fn blocks(
@@ -120,32 +119,30 @@ impl MetadataChain {
120119
page: Option<usize>,
121120
per_page: Option<usize>,
122121
) -> Result<MetadataBlockConnection> {
123-
let dataset = self.get_dataset(ctx).await?;
124-
125122
let page = page.unwrap_or(0);
126123
let per_page = per_page.unwrap_or(Self::DEFAULT_BLOCKS_PER_PAGE);
127124

128-
let blocks: Vec<_> = dataset
129-
.as_metadata_chain()
130-
.iter_blocks()
131-
.try_collect()
132-
.await
133-
.int_err()?;
125+
let dataset = self.get_dataset(ctx).await?;
126+
let chain = dataset.as_metadata_chain();
134127

135-
let total_count = blocks.len();
128+
let head = chain.resolve_ref(&domain::BlockRef::Head).await.int_err()?;
129+
let total_count =
130+
usize::try_from(chain.get_block(&head).await.int_err()?.sequence_number).unwrap() + 1;
136131

137-
let nodes: Vec<_> = blocks
138-
.into_iter()
132+
let mut block_stream = chain
133+
.iter_blocks_interval(&head, None, false)
139134
.skip(page * per_page)
140-
.take(per_page)
141-
.map(|(hash, block)| {
142-
MetadataBlockExtended::new(
143-
hash,
144-
block,
145-
Account::from_dataset_alias(ctx, &self.dataset_handle.alias),
146-
)
147-
})
148-
.collect();
135+
.take(per_page);
136+
137+
let mut nodes = Vec::new();
138+
while let Some((hash, block)) = block_stream.try_next().await.int_err()? {
139+
let block = MetadataBlockExtended::new(
140+
hash,
141+
block,
142+
Account::from_dataset_alias(ctx, &self.dataset_handle.alias),
143+
);
144+
nodes.push(block);
145+
}
149146

150147
Ok(MetadataBlockConnection::new(
151148
nodes,

0 commit comments

Comments
 (0)