Skip to content

Conversation

papparapa
Copy link
Contributor

#5981

This PR adds BAR function like ClickHouse's BAR function.

It draws unicode-art bar chart and is useful for instant visualization of numerical data in CLI.

Cited from ClickHouse's documentation

bar(x, min, max, width) draws a band with a width proportional to (x - min) and equal to width characters when x = max.

Arguments

  • x — Size to display.
  • min, max — Integer constants. The value must fit in Int64.
  • width — Constant, positive integer, can be fractional.

The band is drawn with accuracy to one eighth of a symbol.

e.g.

D select x * x as y, bar(y, 0, 100) from range(0, 11) _(x);
┌───────┬──────────────────────────────────────────────────────────────────────────────────┐
│   y   │                                  bar(y, 0, 100)                                  │
│ int64 │                                     varchar                                      │
├───────┼──────────────────────────────────────────────────────────────────────────────────┤
│     0 │                                                                                  │
│     1 │ ▊                                                                                │
│     4 │ ███▏                                                                             │
│     9 │ ███████▏                                                                         │
│    16 │ ████████████▊                                                                    │
│    25 │ ████████████████████                                                             │
│    36 │ ████████████████████████████▊                                                    │
│    49 │ ███████████████████████████████████████▏                                         │
│    64 │ ███████████████████████████████████████████████████▏                             │
│    81 │ ████████████████████████████████████████████████████████████████▊                │
│   100 │ ████████████████████████████████████████████████████████████████████████████████ │
├───────┴──────────────────────────────────────────────────────────────────────────────────┤
│ 11 rows                                                                        2 columns │
└──────────────────────────────────────────────────────────────────────────────────────────┘

Two overloads are included.

BAR(x: double, min: double, max: double)
BAR(x: double, min: double, max: double, width: double)

In the former overload, width is set to 80 implicitly.

Copy link
Collaborator

@Mytherin Mytherin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Looks good. Some comments below:

@papparapa
Copy link
Contributor Author

Also fixed a bug in GenericExecutor.
Constant vector check in GenericExecutor::ExecuteTernaryInternal and GenericExecutor::ExecuteQuaternaryInternal missed vectors except for the first and second ones.

Copy link
Collaborator

@Mytherin Mytherin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes! Looks good - some more minor comments:

static const char *FULL_BLOCK = UnicodeBar::FullBlock();
static const char *const *PARTIAL_BLOCKS = UnicodeBar::PartialBlocks();
static const idx_t PARTIAL_BLOCKS_COUNT = UnicodeBar::PartialBlocksCount();
static const idx_t UNICODE_BLOCK_CHAR_SIZE = strlen(FULL_BLOCK);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work for the space character, no? As it is only a single byte.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed UNICODE_BLOCK_CHAR_SIZE

int32_t width_as_int = static_cast<int32_t>(width * PARTIAL_BLOCKS_COUNT);
idx_t full_blocks_count = (width_as_int / PARTIAL_BLOCKS_COUNT);
for (idx_t i = 0; i < full_blocks_count; i++) {
result.insert(result.end(), FULL_BLOCK, FULL_BLOCK + UNICODE_BLOCK_CHAR_SIZE);
Copy link
Collaborator

@Mytherin Mytherin Jan 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this to be a vector<char>? Can this not be a std::string instead? It seems like that would simplify the code, as we could then just use string appends (e.g. result += FULL_BLOCK;). Then we wouldn't need UNICODE_BLOCK_CHAR_SIZE either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right.
Fixed to use string

@Mytherin Mytherin merged commit e2cacf2 into duckdb:master Feb 2, 2023
@Mytherin
Copy link
Collaborator

Mytherin commented Feb 2, 2023

Thanks for the changes! Looks good.

@papparapa papparapa deleted the add-bar-function branch February 3, 2023 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants