ClickHouse / ClickHouse/clickhouse-rs

Support specifying independent names for the serialization and deserialization of a field

Open
#360 1 comment 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.