mirror of
https://github.com/apache/superset.git
synced 2026-05-10 02:15:50 +00:00
feat(sqllab): Add a configuration option to disable data preview (#19104)
This commit is contained in:
@@ -1018,28 +1018,13 @@ function getTableMetadata(table, query, dispatch) {
|
||||
),
|
||||
})
|
||||
.then(({ json }) => {
|
||||
const dataPreviewQuery = {
|
||||
id: shortid.generate(),
|
||||
dbId: query.dbId,
|
||||
sql: json.selectStar,
|
||||
tableName: table.name,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: false,
|
||||
ctas: false,
|
||||
isDataPreview: true,
|
||||
};
|
||||
const newTable = {
|
||||
...table,
|
||||
...json,
|
||||
expanded: true,
|
||||
isMetadataLoading: false,
|
||||
dataPreviewQueryId: dataPreviewQuery.id,
|
||||
};
|
||||
Promise.all([
|
||||
dispatch(mergeTable(newTable, dataPreviewQuery)), // Merge table to tables in state
|
||||
dispatch(runQuery(dataPreviewQuery)), // Run query to get preview data for table
|
||||
]);
|
||||
dispatch(mergeTable(newTable)); // Merge table to tables in state
|
||||
return newTable;
|
||||
})
|
||||
.catch(() =>
|
||||
@@ -1082,7 +1067,7 @@ function getTableExtendedMetadata(table, query, dispatch) {
|
||||
);
|
||||
}
|
||||
|
||||
export function addTable(query, tableName, schemaName) {
|
||||
export function addTable(query, database, tableName, schemaName) {
|
||||
return function (dispatch) {
|
||||
const table = {
|
||||
dbId: query.dbId,
|
||||
@@ -1110,6 +1095,32 @@ export function addTable(query, tableName, schemaName) {
|
||||
})
|
||||
: Promise.resolve({ json: { id: shortid.generate() } });
|
||||
|
||||
if (!database.disable_data_preview && database.id === query.dbId) {
|
||||
const dataPreviewQuery = {
|
||||
id: shortid.generate(),
|
||||
dbId: query.dbId,
|
||||
sql: newTable.selectStar,
|
||||
tableName: table.name,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: database.allow_run_async,
|
||||
ctas: false,
|
||||
isDataPreview: true,
|
||||
};
|
||||
Promise.all([
|
||||
dispatch(
|
||||
mergeTable(
|
||||
{
|
||||
...newTable,
|
||||
dataPreviewQueryId: dataPreviewQuery.id,
|
||||
},
|
||||
dataPreviewQuery,
|
||||
),
|
||||
),
|
||||
dispatch(runQuery(dataPreviewQuery)),
|
||||
]);
|
||||
}
|
||||
|
||||
return sync
|
||||
.then(({ json: resultJson }) =>
|
||||
dispatch(mergeTable({ ...table, id: resultJson.id })),
|
||||
|
||||
@@ -727,28 +727,18 @@ describe('async actions', () => {
|
||||
it('updates the table schema state in the backend', () => {
|
||||
expect.assertions(5);
|
||||
|
||||
const results = {
|
||||
data: mockBigNumber,
|
||||
query: { sqlEditorId: 'null' },
|
||||
query_id: 'efgh',
|
||||
};
|
||||
fetchMock.post(runQueryEndpoint, JSON.stringify(results), {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
|
||||
const database = { disable_data_preview: true };
|
||||
const tableName = 'table';
|
||||
const schemaName = 'schema';
|
||||
const store = mockStore({});
|
||||
const expectedActionTypes = [
|
||||
actions.MERGE_TABLE, // addTable
|
||||
actions.MERGE_TABLE, // getTableMetadata
|
||||
actions.START_QUERY, // runQuery (data preview)
|
||||
actions.MERGE_TABLE, // getTableExtendedMetadata
|
||||
actions.QUERY_SUCCESS, // querySuccess
|
||||
actions.MERGE_TABLE, // addTable
|
||||
];
|
||||
return store
|
||||
.dispatch(actions.addTable(query, tableName, schemaName))
|
||||
.dispatch(actions.addTable(query, database, tableName, schemaName))
|
||||
.then(() => {
|
||||
expect(store.getActions().map(a => a.type)).toEqual(
|
||||
expectedActionTypes,
|
||||
@@ -759,6 +749,47 @@ describe('async actions', () => {
|
||||
1,
|
||||
);
|
||||
|
||||
// tab state is not updated, since no query was run
|
||||
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('updates and runs data preview query when configured', () => {
|
||||
expect.assertions(5);
|
||||
|
||||
const results = {
|
||||
data: mockBigNumber,
|
||||
query: { sqlEditorId: 'null', dbId: 1 },
|
||||
query_id: 'efgh',
|
||||
};
|
||||
fetchMock.post(runQueryEndpoint, JSON.stringify(results), {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
|
||||
const database = { disable_data_preview: false, id: 1 };
|
||||
const tableName = 'table';
|
||||
const schemaName = 'schema';
|
||||
const store = mockStore({});
|
||||
const expectedActionTypes = [
|
||||
actions.MERGE_TABLE, // addTable
|
||||
actions.MERGE_TABLE, // getTableMetadata
|
||||
actions.MERGE_TABLE, // getTableExtendedMetadata
|
||||
actions.MERGE_TABLE, // addTable (data preview)
|
||||
actions.START_QUERY, // runQuery (data preview)
|
||||
actions.MERGE_TABLE, // addTable
|
||||
actions.QUERY_SUCCESS, // querySuccess
|
||||
];
|
||||
return store
|
||||
.dispatch(actions.addTable(query, database, tableName, schemaName))
|
||||
.then(() => {
|
||||
expect(store.getActions().map(a => a.type)).toEqual(
|
||||
expectedActionTypes,
|
||||
);
|
||||
expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
|
||||
expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1);
|
||||
expect(fetchMock.calls(getExtraTableMetadataEndpoint)).toHaveLength(
|
||||
1,
|
||||
);
|
||||
// tab state is not updated, since the query is a data preview
|
||||
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(0);
|
||||
});
|
||||
|
||||
@@ -43,11 +43,17 @@ interface Props {
|
||||
actions: {
|
||||
queryEditorSetSelectedText: (edit: any, text: null | string) => void;
|
||||
queryEditorSetFunctionNames: (queryEditor: object, dbId: number) => void;
|
||||
addTable: (queryEditor: any, value: any, schema: any) => void;
|
||||
addTable: (
|
||||
queryEditor: any,
|
||||
database: any,
|
||||
value: any,
|
||||
schema: any,
|
||||
) => void;
|
||||
};
|
||||
autocomplete: boolean;
|
||||
onBlur: (sql: string) => void;
|
||||
sql: string;
|
||||
database: any;
|
||||
schemas: any[];
|
||||
tables: any[];
|
||||
functionNames: string[];
|
||||
@@ -210,6 +216,7 @@ class AceEditorWrapper extends React.PureComponent<Props, State> {
|
||||
if (data.meta === 'table') {
|
||||
this.props.actions.addTable(
|
||||
this.props.queryEditor,
|
||||
this.props.database,
|
||||
data.value,
|
||||
this.props.queryEditor.schema,
|
||||
);
|
||||
|
||||
@@ -514,6 +514,7 @@ class SqlEditor extends React.PureComponent {
|
||||
onChange={this.onSqlChanged}
|
||||
queryEditor={this.props.queryEditor}
|
||||
sql={this.props.queryEditor.sql}
|
||||
database={this.props.database}
|
||||
schemas={this.props.queryEditor.schemaOptions}
|
||||
tables={this.props.queryEditor.tableOptions}
|
||||
functionNames={this.props.queryEditor.functionNames}
|
||||
|
||||
@@ -36,7 +36,7 @@ interface actionsTypes {
|
||||
queryEditorSetFunctionNames: (queryEditor: QueryEditor, dbId: number) => void;
|
||||
collapseTable: (table: Table) => void;
|
||||
expandTable: (table: Table) => void;
|
||||
addTable: (queryEditor: any, value: any, schema: any) => void;
|
||||
addTable: (queryEditor: any, database: any, value: any, schema: any) => void;
|
||||
setDatabases: (arg0: any) => {};
|
||||
addDangerToast: (msg: string) => void;
|
||||
queryEditorSetSchema: (queryEditor: QueryEditor, schema?: string) => void;
|
||||
@@ -103,7 +103,7 @@ export default function SqlEditorLeftBar({
|
||||
|
||||
const onTableChange = (tableName: string, schemaName: string) => {
|
||||
if (tableName && schemaName) {
|
||||
actions.addTable(queryEditor, tableName, schemaName);
|
||||
actions.addTable(queryEditor, database, tableName, schemaName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ beforeEach(() => {
|
||||
allows_cost_estimate: 'Allows Cost Estimate',
|
||||
allows_subquery: 'Allows Subquery',
|
||||
allows_virtual_table_explore: 'Allows Virtual Table Explore',
|
||||
disable_data_preview: 'Disables SQL Lab Data Preview',
|
||||
backend: 'Backend',
|
||||
changed_on: 'Changed On',
|
||||
changed_on_delta_humanized: 'Changed On Delta Humanized',
|
||||
@@ -97,6 +98,7 @@ beforeEach(() => {
|
||||
'allows_cost_estimate',
|
||||
'allows_subquery',
|
||||
'allows_virtual_table_explore',
|
||||
'disable_data_preview',
|
||||
'backend',
|
||||
'changed_on',
|
||||
'changed_on_delta_humanized',
|
||||
@@ -130,6 +132,7 @@ beforeEach(() => {
|
||||
allows_cost_estimate: null,
|
||||
allows_subquery: true,
|
||||
allows_virtual_table_explore: true,
|
||||
disable_data_preview: false,
|
||||
backend: 'postgresql',
|
||||
changed_on: '2021-03-09T19:02:07.141095',
|
||||
changed_on_delta_humanized: 'a day ago',
|
||||
@@ -150,6 +153,7 @@ beforeEach(() => {
|
||||
allows_cost_estimate: null,
|
||||
allows_subquery: true,
|
||||
allows_virtual_table_explore: true,
|
||||
disable_data_preview: false,
|
||||
backend: 'mysql',
|
||||
changed_on: '2021-03-09T19:02:07.141095',
|
||||
changed_on_delta_humanized: 'a day ago',
|
||||
|
||||
@@ -182,7 +182,7 @@ const ExtraOptions = ({
|
||||
/>
|
||||
</div>
|
||||
</StyledInputContainer>
|
||||
<StyledInputContainer>
|
||||
<StyledInputContainer css={no_margin_bottom}>
|
||||
<div className="input-container">
|
||||
<IndeterminateCheckbox
|
||||
id="allows_virtual_table_explore"
|
||||
@@ -198,6 +198,24 @@ const ExtraOptions = ({
|
||||
/>
|
||||
</div>
|
||||
</StyledInputContainer>
|
||||
<StyledInputContainer>
|
||||
<div className="input-container">
|
||||
<IndeterminateCheckbox
|
||||
id="disable_data_preview"
|
||||
indeterminate={false}
|
||||
checked={!!db?.extra_json?.disable_data_preview}
|
||||
onChange={onExtraInputChange}
|
||||
labelText={t('Disable SQL Lab data preview queries')}
|
||||
/>
|
||||
<InfoTooltip
|
||||
tooltip={t(
|
||||
'Disable data preview when fetching table metadata in SQL Lab. ' +
|
||||
' Useful to avoid browser performance issues when using ' +
|
||||
' databases with very wide tables.',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</StyledInputContainer>
|
||||
</StyledExpandableForm>
|
||||
</StyledInputContainer>
|
||||
</Collapse.Panel>
|
||||
|
||||
@@ -591,6 +591,15 @@ describe('DatabaseModal', () => {
|
||||
const allowDbExplorationText = screen.getByText(
|
||||
/allow this database to be explored/i,
|
||||
);
|
||||
const disableSQLLabDataPreviewQueriesCheckbox = screen.getByRole(
|
||||
'checkbox',
|
||||
{
|
||||
name: /Disable SQL Lab data preview queries/i,
|
||||
},
|
||||
);
|
||||
const disableSQLLabDataPreviewQueriesText = screen.getByText(
|
||||
/Disable SQL Lab data preview queries/i,
|
||||
);
|
||||
|
||||
// ---------- Assertions ----------
|
||||
const visibleComponents = [
|
||||
@@ -610,6 +619,7 @@ describe('DatabaseModal', () => {
|
||||
checkboxOffSVGs[4],
|
||||
checkboxOffSVGs[5],
|
||||
checkboxOffSVGs[6],
|
||||
checkboxOffSVGs[7],
|
||||
tooltipIcons[0],
|
||||
tooltipIcons[1],
|
||||
tooltipIcons[2],
|
||||
@@ -617,6 +627,7 @@ describe('DatabaseModal', () => {
|
||||
tooltipIcons[4],
|
||||
tooltipIcons[5],
|
||||
tooltipIcons[6],
|
||||
tooltipIcons[7],
|
||||
exposeInSQLLabText,
|
||||
allowCTASText,
|
||||
allowCVASText,
|
||||
@@ -627,6 +638,7 @@ describe('DatabaseModal', () => {
|
||||
allowMultiSchemaMDFetchText,
|
||||
enableQueryCostEstimationText,
|
||||
allowDbExplorationText,
|
||||
disableSQLLabDataPreviewQueriesText,
|
||||
];
|
||||
// These components exist in the DOM but are not visible
|
||||
const invisibleComponents = [
|
||||
@@ -637,6 +649,7 @@ describe('DatabaseModal', () => {
|
||||
allowMultiSchemaMDFetchCheckbox,
|
||||
enableQueryCostEstimationCheckbox,
|
||||
allowDbExplorationCheckbox,
|
||||
disableSQLLabDataPreviewQueriesCheckbox,
|
||||
];
|
||||
|
||||
visibleComponents.forEach(component => {
|
||||
@@ -645,8 +658,8 @@ describe('DatabaseModal', () => {
|
||||
invisibleComponents.forEach(component => {
|
||||
expect(component).not.toBeVisible();
|
||||
});
|
||||
expect(checkboxOffSVGs).toHaveLength(7);
|
||||
expect(tooltipIcons).toHaveLength(7);
|
||||
expect(checkboxOffSVGs).toHaveLength(8);
|
||||
expect(tooltipIcons).toHaveLength(8);
|
||||
});
|
||||
|
||||
it('renders the "Advanced" - PERFORMANCE tab correctly', async () => {
|
||||
|
||||
@@ -92,6 +92,7 @@ export type DatabaseObject = {
|
||||
|
||||
version?: string;
|
||||
cost_estimate_enabled?: boolean; // in SQL Lab
|
||||
disable_data_preview?: boolean; // in SQL Lab
|
||||
};
|
||||
|
||||
// Temporary storage
|
||||
|
||||
Reference in New Issue
Block a user