forked from getredash/redash
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Schema Viewer Drawer (getredash#3291)
* Process extra column metadata for a few sql-based data sources. * Add Table and Column metadata tables. * Periodically update table and column schema tables in a celery task. * Fetching schema returns data from table and column metadata tables. * Add tests for backend changes. * Front-end shows extra table metadata and uses new schema response. * Delete datasource schema data when deleting a data source. * Process and store data source schema when a data source is first created or after a migration. * Tables should have a unique name per datasource. * Addressing review comments. * Update migration file for mixins. * Appease PEP8 * Upgrade migration file for rebase. * Cascade delete. * Adding org_id * Remove redundant column and table prefixes. * Non-existing tables and columns should be filtered out on the server side not client side. * Fetching table samples should be optional and should happen in a separate task per table. * Allow users to force a schema refresh. * Use updated_at to help prune old schema metadata periodically. * Using settings.SCHEMAS_REFRESH_QUEUE * fix for getredash#2426 test * more stable test_interactive_new * Closes #927, #928: Schema refresh improvements. * Closes #934, #935: Remove type from schema browser and don't show empty example column in schema drawer (#936) * Speed up schema fetch requests with fewer postgres queries. * Add column metadata to Athena glue processing. * Fix bug assuming 'metadata' exists for every table. * Closes #939: Persisted, existing table metadata should be updated. * Sample processing should be rate-limited. * Add cli command for refreshing data samples. * Schema refreshes should not overwrite column 'example' field. * refresh_samples() should filter tables_to_sample on the datasource's id being sampled * Correctly wrap long text in schema drawer. Co-authored-by: Alison <[email protected]>
- Loading branch information
Showing
28 changed files
with
1,191 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { react2angular } from 'react2angular'; | ||
import Drawer from 'antd/lib/drawer'; | ||
import Table from 'antd/lib/table'; | ||
|
||
import { DataSourceMetadata } from '@/components/proptypes'; | ||
|
||
function textWrapRenderer(text) { | ||
return ( | ||
<div style={{ wordWrap: 'break-word', wordBreak: 'break-all' }}> | ||
{text} | ||
</div> | ||
); | ||
} | ||
|
||
class SchemaData extends React.PureComponent { | ||
static propTypes = { | ||
show: PropTypes.bool.isRequired, | ||
onClose: PropTypes.func.isRequired, | ||
tableName: PropTypes.string, | ||
tableMetadata: PropTypes.arrayOf(DataSourceMetadata), | ||
}; | ||
|
||
static defaultProps = { | ||
tableName: '', | ||
tableMetadata: [], | ||
}; | ||
|
||
render() { | ||
const columns = [{ | ||
title: 'Column Name', | ||
dataIndex: 'name', | ||
width: 400, | ||
key: 'name', | ||
render: textWrapRenderer, | ||
}, { | ||
title: 'Column Type', | ||
dataIndex: 'type', | ||
width: 400, | ||
key: 'type', | ||
render: textWrapRenderer, | ||
}]; | ||
|
||
const hasExample = | ||
this.props.tableMetadata.some(columnMetadata => columnMetadata.example); | ||
|
||
if (hasExample) { | ||
columns.push({ | ||
title: 'Example', | ||
dataIndex: 'example', | ||
width: 400, | ||
key: 'example', | ||
render: textWrapRenderer, | ||
}); | ||
} | ||
|
||
return ( | ||
<Drawer | ||
title={this.props.tableName} | ||
closable={false} | ||
placement="bottom" | ||
height={500} | ||
onClose={this.props.onClose} | ||
visible={this.props.show} | ||
> | ||
<Table | ||
dataSource={this.props.tableMetadata} | ||
pagination={false} | ||
scroll={{ y: 350 }} | ||
size="small" | ||
columns={columns} | ||
/> | ||
</Drawer> | ||
); | ||
} | ||
} | ||
|
||
export default function init(ngModule) { | ||
ngModule.component('schemaData', react2angular(SchemaData, null, [])); | ||
} | ||
|
||
init.init = true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
"""Add column metadata and table metadata | ||
Revision ID: 280daa582976 | ||
Revises: b8a479422596 | ||
Create Date: 2019-01-24 18:23:53.040608 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = '280daa582976' | ||
down_revision = 'b8a479422596' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.create_table( | ||
'table_metadata', | ||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), | ||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), | ||
sa.Column('id', sa.Integer(), nullable=False), | ||
sa.Column('org_id', sa.Integer(), nullable=False), | ||
sa.Column('data_source_id', sa.Integer(), nullable=False), | ||
sa.Column('exists', sa.Boolean(), nullable=False), | ||
sa.Column('name', sa.String(length=255), nullable=False), | ||
sa.Column('description', sa.String(length=4096), nullable=True), | ||
sa.Column('column_metadata', sa.Boolean(), nullable=False), | ||
sa.Column('sample_query', sa.Text(), nullable=True), | ||
sa.ForeignKeyConstraint(['data_source_id'], ['data_sources.id'], ondelete="CASCADE"), | ||
sa.ForeignKeyConstraint(['org_id'], ['organizations.id']), | ||
sa.PrimaryKeyConstraint('id') | ||
) | ||
op.create_table( | ||
'column_metadata', | ||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), | ||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), | ||
sa.Column('id', sa.Integer(), nullable=False), | ||
sa.Column('org_id', sa.Integer(), nullable=False), | ||
sa.Column('table_id', sa.Integer(), nullable=False), | ||
sa.Column('name', sa.String(length=255), nullable=False), | ||
sa.Column('type', sa.String(length=255), nullable=True), | ||
sa.Column('example', sa.String(length=4096), nullable=True), | ||
sa.Column('exists', sa.Boolean(), nullable=False), | ||
sa.ForeignKeyConstraint(['table_id'], ['table_metadata.id'], ondelete="CASCADE"), | ||
sa.ForeignKeyConstraint(['org_id'], ['organizations.id']), | ||
sa.PrimaryKeyConstraint('id') | ||
) | ||
|
||
|
||
def downgrade(): | ||
op.drop_table('column_metadata') | ||
op.drop_table('table_metadata') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
"""Add sample_updated_at column to table_metadata | ||
Revision ID: 6adb92e75691 | ||
Revises: 280daa582976 | ||
Create Date: 2019-04-10 20:13:13.714589 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = '6adb92e75691' | ||
down_revision = '280daa582976' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.add_column('table_metadata', sa.Column( | ||
'sample_updated_at', sa.DateTime(timezone=True), nullable=True)) | ||
|
||
|
||
def downgrade(): | ||
op.drop_column('table_metadata', 'sample_updated_at') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.