-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(driver): support parsing to struct (#190)
* refactor: split crates * feat(driver): support parsing to struct
- Loading branch information
Showing
19 changed files
with
402 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
[package] | ||
name = "bindings-nodejs" | ||
name = "databend-nodejs" | ||
publish = false | ||
|
||
version = { workspace = true } | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "databend-driver-macros" | ||
description = "Macros for Databend Driver" | ||
categories = ["database"] | ||
keywords = ["databend", "database", "macros"] | ||
|
||
version = { workspace = true } | ||
edition = { workspace = true } | ||
license = { workspace = true } | ||
authors = { workspace = true } | ||
repository = { workspace = true } | ||
|
||
[lib] | ||
proc-macro = true | ||
|
||
[dependencies] | ||
proc-macro2 = "1.0" | ||
quote = "1.0" | ||
syn = "2.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright 2021 Datafuse Labs | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use proc_macro::TokenStream; | ||
use quote::{quote, quote_spanned}; | ||
use syn::{spanned::Spanned, DeriveInput}; | ||
|
||
/// #[derive(TryFromRow)] derives TryFromRow for struct | ||
pub fn from_row_derive(tokens_input: TokenStream) -> TokenStream { | ||
let item = syn::parse::<DeriveInput>(tokens_input).expect("No DeriveInput"); | ||
let struct_fields = crate::parser::parse_named_fields(&item, "TryFromRow"); | ||
|
||
let struct_name = &item.ident; | ||
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl(); | ||
|
||
let set_fields_code = struct_fields.named.iter().map(|field| { | ||
let field_name = &field.ident; | ||
let field_type = &field.ty; | ||
|
||
quote_spanned! {field.span() => | ||
#field_name: { | ||
let (col_ix, col_value) = vals_iter | ||
.next() | ||
.unwrap(); // vals_iter size is checked before this code is reached, so | ||
// it is safe to unwrap | ||
let t = col_value.get_type(); | ||
|
||
<#field_type>::try_from(col_value) | ||
.map_err(|_| Error::InvalidResponse(format!("failed converting column {} from type({:?}) to type({})", col_ix, t, std::any::type_name::<#field_type>())))? | ||
}, | ||
} | ||
}); | ||
|
||
let fields_count = struct_fields.named.len(); | ||
let generated = quote! { | ||
use databend_sql::rows::Row; | ||
use databend_sql::error::{Error, Result}; | ||
|
||
impl #impl_generics TryFrom<Row> for #struct_name #ty_generics #where_clause { | ||
type Error = Error; | ||
fn try_from(row: Row) -> Result<Self> { | ||
if #fields_count != row.len() { | ||
return Err(Error::InvalidResponse(format!("row size mismatch: expected {} columns, got {}", #fields_count, row.len()))); | ||
} | ||
let mut vals_iter = row.into_iter().enumerate(); | ||
|
||
Ok(#struct_name { | ||
#(#set_fields_code)* | ||
}) | ||
} | ||
} | ||
}; | ||
|
||
TokenStream::from(generated) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2021 Datafuse Labs | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use proc_macro::TokenStream; | ||
|
||
mod from_row; | ||
mod parser; | ||
|
||
#[proc_macro_derive(TryFromRow)] | ||
pub fn from_row_derive(tokens_input: TokenStream) -> TokenStream { | ||
from_row::from_row_derive(tokens_input) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2021 Datafuse Labs | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use syn::{Data, DeriveInput, Fields, FieldsNamed}; | ||
|
||
/// Parses the tokens_input to a DeriveInput and returns the struct name from which it derives and | ||
/// the named fields | ||
pub(crate) fn parse_named_fields<'a>( | ||
input: &'a DeriveInput, | ||
current_derive: &str, | ||
) -> &'a FieldsNamed { | ||
match &input.data { | ||
Data::Struct(data) => match &data.fields { | ||
Fields::Named(named_fields) => named_fields, | ||
_ => panic!( | ||
"derive({}) works only for structs with named fields. Tuples don't need derive.", | ||
current_derive | ||
), | ||
}, | ||
_ => panic!("derive({}) works only on structs!", current_derive), | ||
} | ||
} |
Oops, something went wrong.