Skip to content

Commit 76fa34c

Browse files
committed
script to generate type cast chart
1 parent dca6a83 commit 76fa34c

File tree

3 files changed

+101
-25
lines changed

3 files changed

+101
-25
lines changed

documentation/reference/sql/cast.md

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -91,32 +91,10 @@ smallest possible type so that no data is lost.
9191
## Casting table
9292

9393
The below chart illustrates the explicit and implicit cast available in QuestDB:
94+
<!-- the image can be regenerated via the script at scripts/generate_type_cast_chart.py -->
95+
96+
![Table showing the different possibilities the cast function supports, those are defined by an input and output types](/images/docs/castmap.jpg)
9497

95-
| From \ To | String | Boolean | Char | Byte | Short | Int | Long | Long256 | Float | Double | Decimal | Date | Timestamp | Symbol | Binary |
96-
| --------- | ------ | ------- | ----- | ----- | ----- | ----- | ----- | ------- | ----- | ------ | ------- | ----- | --------- | ------ | ------ |
97-
| String | | `E` | `E*` | `E` | `E` | `I` | `I` | `I` | `I` | `I` | `E` | `I` | `I` | `I` | `N/A` |
98-
| Boolean | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` | `I` | `I` | `I` | `N/A` |
99-
| Char | `I` | `N/A` | | `E*` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` | `I` | `I` | `I` | `N/A` |
100-
| Byte | `I` | `E*` | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` |
101-
| Short | `I` | `E*` | `E*` | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` |
102-
| Int | `E` | `E*` | `E*` | `E*` | `E*` | | `I` | `I` | `I*` | `I` | `I` | `I` | `I` | `I` | `N/A` |
103-
| Long | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | | `I` | `E*` | `I*` | `I` | `I` | `I` | `E` | `N/A` |
104-
| Long256 | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `E*` | | `E*` | `E*` | `N/A` | `E*` | `E*` | `E*` | `N/A` |
105-
| Float | `E` | `N/A` | `E*` | `E*` | `E*` | `I*` | `I*` | `I*` | | `I` | `E*` | `I*` | `I*` | `I` | `N/A` |
106-
| Double | `E` | `N/A` | `E*` | `E*` | `E*` | `E*` | `I*` | `I*` | `E*` | | `E*` | `I*` | `I*` | `E` | `N/A` |
107-
| Decimal | `E` | `N/A` | `N/A` | `E!` | `E!` | `E!` | `E!` | `N/A` | `E*` | `E*` | | `N/A` | `N/A` | `N/A` | `N/A` |
108-
| Date | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `I` | `I` | `E*` | `I*` | `N/A` | | `I` | `E` | `N/A` |
109-
| Timestamp | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `I` | `I` | `E*` | `I*` | `N/A` | `I*` | | `E` | `N/A` |
110-
| Symbol | `I` | `E` | `E` | `E` | `E` | `E` | `I` | `I` | `E` | `I` | `N/A` | `I` | `I` | | `N/A` |
111-
| Binary | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` |
112-
113-
#### Legend
114-
115-
- `E`: Explicit cast (using the `cast` function or `::` operator)
116-
- `I`: Implicit cast
117-
- `*`: The cast operation might lead to precision loss
118-
- `!`: The cast operation throws an error when if it would lead to precision
119-
loss
12098

12199
```questdb-sql title="Queries"
122100
SELECT
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import matplotlib.pyplot as plt
2+
import matplotlib.patches as mpatches
3+
4+
5+
markdown_table = """
6+
| From \\ To | String | Boolean | Char | Byte | Short | Int | Long | Long256 | Float | Double | Decimal | Date | Timestamp | Symbol | Binary |
7+
| --------- | ------ | ------- | ----- | ----- | ----- | ----- | ----- | ------- | ----- | ------ | ------- | ----- | --------- | ------ | ------ |
8+
| String | | `E` | `E*` | `E` | `E` | `I` | `I` | `I` | `I` | `I` | `E` | `I` | `I` | `I` | `N/A` |
9+
| Boolean | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` | `I` | `I` | `I` | `N/A` |
10+
| Char | `I` | `N/A` | | `E*` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` | `I` | `I` | `I` | `N/A` |
11+
| Byte | `I` | `E*` | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` |
12+
| Short | `I` | `E*` | `E*` | `I` | | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `I` | `N/A` |
13+
| Int | `E` | `E*` | `E*` | `E*` | `E*` | | `I` | `I` | `I*` | `I` | `I` | `I` | `I` | `I` | `N/A` |
14+
| Long | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | | `I` | `E*` | `I*` | `I` | `I` | `I` | `E` | `N/A` |
15+
| Long256 | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `E*` | | `E*` | `E*` | `N/A` | `E*` | `E*` | `E*` | `N/A` |
16+
| Float | `E` | `N/A` | `E*` | `E*` | `E*` | `I*` | `I*` | `I*` | | `I` | `E*` | `I*` | `I*` | `I` | `N/A` |
17+
| Double | `E` | `N/A` | `E*` | `E*` | `E*` | `E*` | `I*` | `I*` | `E*` | | `E*` | `I*` | `I*` | `E` | `N/A` |
18+
| Decimal | `E` | `N/A` | `N/A` | `E!` | `E!` | `E!` | `E!` | `N/A` | `E*` | `E*` | | `N/A` | `N/A` | `N/A` | `N/A` |
19+
| Date | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `I` | `I` | `E*` | `I*` | `N/A` | | `I` | `E` | `N/A` |
20+
| Timestamp | `E` | `E*` | `E*` | `E*` | `E*` | `E*` | `I` | `I` | `E*` | `I*` | `N/A` | `I*` | | `E` | `N/A` |
21+
| Symbol | `I` | `E` | `E` | `E` | `E` | `E` | `I` | `I` | `E` | `I` | `N/A` | `I` | `I` | | `N/A` |
22+
| Binary | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` | `N/A` |
23+
"""
24+
25+
# --- Parse Markdown into matrix ---
26+
lines = [line.strip() for line in markdown_table.strip().split("\n") if line.strip()]
27+
header = [h.strip() for h in lines[0].split("|")[1:-1]] # remove leading/trailing pipe
28+
rows = []
29+
30+
matrix = {}
31+
for line in lines[2:]: # skip header + separator
32+
parts = [p.strip().strip("`") for p in line.split("|")[1:-1]]
33+
row_name, values = parts[0], parts[1:]
34+
matrix[row_name] = dict(zip(header[1:], values)) # map To-cols to values
35+
rows.append(row_name)
36+
37+
cols = header[1:]
38+
39+
# --- Color mapping ---
40+
color_map = {
41+
"": "white",
42+
"I": "#a6d96a", # implicit
43+
"E": "#fdae61", # explicit
44+
"I*": "#313695", # implicit precision loss
45+
"E*": "#d73027", # explicit precision loss
46+
"E!": "#e08214", # explicit warning
47+
"N/A": "#7f7f7f" # grey
48+
}
49+
50+
# --- Plot ---
51+
fig, ax = plt.subplots(figsize=(5, 4))
52+
53+
for i, row in enumerate(rows):
54+
for j, col in enumerate(cols):
55+
val = matrix[row].get(col, "")
56+
ax.add_patch(plt.Rectangle(
57+
(j, i), 1, 1,
58+
facecolor=color_map.get(val, "white"),
59+
edgecolor="black", linewidth=0.5
60+
))
61+
62+
# Configure ticks
63+
ax.set_xticks([i + 0.5 for i in range(len(cols))])
64+
ax.set_yticks([i + 0.5 for i in range(len(rows))])
65+
ax.set_xticklabels(cols, rotation=90)
66+
ax.set_yticklabels(rows)
67+
68+
# Put X axis labels at the top
69+
ax.xaxis.tick_top()
70+
71+
ax.set_xlim(0, len(cols))
72+
ax.set_ylim(0, len(rows))
73+
ax.invert_yaxis()
74+
ax.set_aspect("equal")
75+
76+
# Axis labels
77+
ax.set_xlabel("TO", labelpad=20)
78+
ax.xaxis.set_label_position("top")
79+
80+
ax.set_ylabel("FROM", labelpad=20)
81+
ax.yaxis.set_label_position("left")
82+
83+
# Legend centered at bottom
84+
legend_elements = [
85+
mpatches.Patch(facecolor="#a6d96a", edgecolor="black", label="Implicit"),
86+
mpatches.Patch(facecolor="#fdae61", edgecolor="black", label="Explicit"),
87+
mpatches.Patch(facecolor="#313695", edgecolor="black", label="Implicit (precision loss)"),
88+
mpatches.Patch(facecolor="#d73027", edgecolor="black", label="Explicit (precision loss)"),
89+
mpatches.Patch(facecolor="#7f7f7f", edgecolor="black", label="N/A")
90+
]
91+
ax.legend(handles=legend_elements,
92+
bbox_to_anchor=(0.5, -0.05), loc="upper center", ncol=3, frameon=False)
93+
94+
# Save directly to file
95+
path = "../static/images/docs/castmap.jpg"
96+
plt.savefig(path, dpi=300, bbox_inches="tight")
97+
plt.close()
98+
print("file written to: " + path)

static/images/docs/castmap.jpg

136 KB
Loading

0 commit comments

Comments
 (0)