ClickHouse / ClickHouse/clickhouse-rs
Support specifying independent names for the serialization and deserialization of a field
- Dominant language
- Rust
- Stars
- 559
- Forks
- 172
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 3
Description
### Use case
> Note: Only after upgrading to 0.14.0+ will it be affected.(with RowBinaryWithNamesAndTypes open)
If we have a struct like:
```Rust
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Row)]
pub struct FooBar {
#[serde(rename(deserialize = "foobar"))]
pub foo: i32,
pub bar: i32,
}
```
ddl like:
```sql
CREATE TABLE IF NOT EXISTS dummy_table (
foo Int32,
bar Int32
) ENGINE = MergeTree
ORDER BY foo;
```
then i can get it from clickhouse by using alias clause
```sql
SELECT foo AS foobar, bar FROM dummy_table order by foo
```
Now, clickhouse-rs(0.14.0+) will panic directly in this situation(with RowBinaryWithNamesAndTypes format enabled).
```
thread 'tests::fetch_with_rename' (7401293) panicked at src/lib.rs:77:14:
called `Result::unwrap()` on an `Err` value: SchemaMismatch("While processing struct FooBar: database schema has a column foobar: Int32 that was not found in the struct definition.\n#### All struct fields:\n- foo\n- bar\n#### All schema columns:\n- foobar: Int32\n- bar: Int32")
```
Using the RowBinary format, this problem is not an issue.
### Describe the solution you'd like
Support `#[serde(rename(serialize = "ser_name"))]`, `#[serde(rename(deserialize = "de_name"))]` and `#[serde(rename(serialize = "ser_name", deserialize = "de_name"))]`
### Describe the alternatives you've considered
nothing here
### Additional context
This is useful when you want to use the same field names in the database as in the DDL, but need to use different field names in the query you write.
And in some cases, using the alias clause is necessary:
```
SELECT
date,
broker_id,
broker_key,
account_id,
argMax(timestamp, timestamp) AS timestamp,
argMax(vwap, timestamp) AS vwap,
argMax(vwap_profit, timestamp) AS vwap_profit,
argMax(vwap_bp, timestamp) AS vwap_bp,
argMax(progress_rate, timestamp) AS progress_rate
FROM ufas_account_serial_hist
FINAL
WHERE date = today()
GROUP BY
date,
broker_id,
broker_key,
account_id
```
will lead to:
```text
Code: 184. DB::Exception: Received from localhost:9147. DB::Exception: Aggregate function argMax(timestamp, timestamp) is found inside another aggregate function in query: While processing argMax(timestamp, timestamp) AS timestamp. (ILLEGAL_AGGREGATION)
```
then you can use `argMax(timestamp, timestamp) AS ts` to fix that
Contributor guide
Research direction
Start at the RowBinaryWithNamesAndTypes handling involved in the fetch_with_rename failure reported at src/lib.rs:77:14, and review how serde field names are matched to database schema columns. Reproduce the alias query with the shown FooBar struct, then verify that serialize-only, deserialize-only, and combined serde rename attributes avoid SchemaMismatch while RowBinary behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, sql
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100