Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Visualize complex Hive column types v2 #1091

Merged
merged 1 commit into from
Jan 10, 2023

Conversation

baumandm
Copy link
Contributor

@baumandm baumandm commented Dec 1, 2022

This is an alternate version of #1072, replacing the JSON viewer with a more natural-looking nested type drilldown. I've also addressed some issues with the original version.

Compared to #1072, the parser is more consistent and does a better job of handling certain types than before. To support the nesting, it always creates nodes with optional children. Now array<> and uniontype<> types will create placeholder <element> nodes underneath them, and map<> types create placeholder <key> and <value> nodes.

Complex type parsing is case-insensitive (e.g. struct vs STRUCT) but otherwise case is preserved.

There are three main features:

  1. Columns with complex types can be expanded directly in the TablePanelView to see a nested representation (initially collapsed).

Screen Shot 2022-12-01 at 4 55 50 PM Screen Shot 2022-12-01 at 4 56 10 PM

  1. The type displayed on the ColumnPanelView is pretty-printed with simple line breaks/indents.

Screen Shot 2022-12-01 at 4 56 35 PM

  1. The DataTableColumnCard shows a similar nested visualization after expanding a column (initially collapsed).

Screen Shot 2022-12-01 at 4 58 06 PM

@baumandm
Copy link
Contributor Author

baumandm commented Dec 2, 2022

I've extended the length of DataTableColumn's type column to 1024 characters, since we were running into a number of truncated columns.

In the event that a column type is still longer than the new limit, everything degrades gracefully and the partial type string will be short as before.

Copy link
Collaborator

@jczhong84 jczhong84 left a comment

Choose a reason for hiding this comment

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

Looks good to me overall, thanks for the update!

Also could you update the version in package.json?

Comment on lines +35 to +39
if (!matches || matches.length < 3) {
return { key, type };
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this to handle the truncated case?

  1. could you add a test case for it?
  2. what if the truncated type also matches the regex? like struct<date:struct<hour:int>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a case for non-matching truncated, and the 2nd scenario where the truncated type matches the regex accidentally. I've addressed this by checking the depth field to ensure we've closed all <> pairs

}
*/
export function parseType(key: string, type: string): ComplexType {
const regex = /(struct|array|map|uniontype)<(.*)>/i;
Copy link
Collaborator

Choose a reason for hiding this comment

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

does it need to handle spaces? like struct <...>, struct<year : int, day : int>?

also should it match the start and end /^ ... $/?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I left spaces out intentionally as I haven't seen that in the wild. If needed it probably wouldn't be too hard, but didn't want to add unnecessary complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added start/end to the regex.

if (char === '<') {
prettyString += '<\n';
depth += 1;
prettyString += ' '.repeat(depth);
Copy link
Collaborator

Choose a reason for hiding this comment

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

could you use a variable for the 2 spaces ' '?

Comment on lines 124 to 126
{complexType.type}
</StyledText>
<AccentText weight="extra">{complexType.key}</AccentText>
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of displaying it as type key, I'd prefer to have it same as the ColumnRow, which is key type, which I think is more reasonable.

@baumandm baumandm force-pushed the external/struct-types-v2 branch 2 times, most recently from 645b79f to a030692 Compare January 5, 2023 15:59
jczhong84
jczhong84 previously approved these changes Jan 6, 2023
@@ -24,6 +26,7 @@ export const DataTableColumnCard: React.FunctionComponent<IProps> = ({
updateDataColumnDescription,
}) => {
const [expanded, setExpanded] = React.useState(false);
const parsedType = parseType('', column.type);
Copy link
Collaborator

Choose a reason for hiding this comment

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

memo this?

@@ -71,3 +81,57 @@ export const DataTableColumnCard: React.FunctionComponent<IProps> = ({
</div>
);
};

interface IDataTableColumnCardNestedTypeProps {
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you separate this into another file?

IDataTableColumnCardNestedTypeProps
> = ({ complexType }) => {
const hasChildren = complexType.children?.length > 0;
const [expanded, setExpanded] = React.useState(false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

you can use useToggleState then you don't need () => setExpanded(!expanded)

const hasChildren = complexType.children?.length > 0;
const [expanded, setExpanded] = React.useState(false);

const rowProps = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

const rowProps: React.HTMLAttributes = {}

</div>
{hasChildren &&
expanded &&
complexType.children?.map((child) => (
Copy link
Collaborator

Choose a reason for hiding this comment

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

.map is sufficient

'struct<ids:array<string>,data:uniontype<int,float,string>>'
)
).toEqual(`struct<
ids:array<
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we add a space after : to make it easier to read?

@@ -53,6 +56,7 @@ export const TablePanelView: React.FunctionComponent<ITablePanelViewProps> = ({
onClick={onColumnRowClick.bind(null, col.id)}
name={col.name}
type={col.type}
typeChildren={parseType('', col.type).children}
Copy link
Collaborator

Choose a reason for hiding this comment

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

memo this?

actually, the parsing can be down in ColumnRow since col.type is passed as a prop

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ColumnRow takes typeChildren because it only parses once, then recursively output nested rows. I've moved the parseType call down and inside useMemo, where it returns either the passed typeChildren or calculates it.

czgu
czgu previously approved these changes Jan 9, 2023
@baumandm
Copy link
Contributor Author

Rebased to resolve conflicts / squashed the commits.

@czgu czgu merged commit 05de0ca into pinterest:master Jan 10, 2023
rohan-sh1 pushed a commit to CAI-TECHNOLOGIES/cai-ext-db-explorer that referenced this pull request Feb 28, 2023
@baumandm baumandm deleted the external/struct-types-v2 branch September 21, 2023 16:55
aidenprice pushed a commit to arrowtail-precision/querybook that referenced this pull request Jan 3, 2024
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.

3 participants