diff --git a/docs/static/resources/openapi.json b/docs/static/resources/openapi.json index 86d07ad8264c5..1e8c6129f1d44 100644 --- a/docs/static/resources/openapi.json +++ b/docs/static/resources/openapi.json @@ -2248,6 +2248,9 @@ "allows_virtual_table_explore": { "type": "boolean" }, + "disable_data_preview": { + "type": "boolean" + }, "backend": { "type": "string" }, @@ -2472,6 +2475,9 @@ "allows_virtual_table_explore": { "readOnly": true }, + "disable_data_preview": { + "readOnly": true + }, "backend": { "readOnly": true }, @@ -2571,7 +2577,7 @@ "type": "boolean" }, "extra": { - "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown.

", + "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown
6. The disable_data_preview field is a boolean specifying whether or not data preview queries will be run when fetching table metadata in SQL Lab.

", "type": "string" }, "force_ctas_schema": { @@ -2663,7 +2669,7 @@ "type": "boolean" }, "extra": { - "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown.

", + "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown
6. The disable_data_preview field is a boolean specifying whether or not data preview queries will be run when fetching table metadata in SQL Lab.

", "type": "string" }, "force_ctas_schema": { @@ -2720,7 +2726,7 @@ "type": "string" }, "extra": { - "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown.

", + "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown
6. The disable_data_preview field is a boolean specifying whether or not data preview queries will be run when fetching table metadata in SQL Lab.

", "type": "string" }, "impersonate_user": { @@ -2768,7 +2774,7 @@ "type": "string" }, "extra": { - "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown.

", + "description": "

JSON string containing extra configuration elements.
1. The engine_params object gets unpacked into the sqlalchemy.create_engine call, while the metadata_params gets unpacked into the sqlalchemy.MetaData call.
2. The metadata_cache_timeout is a cache timeout setting in seconds for metadata fetch of this database. Specify it as \"metadata_cache_timeout\": {\"schema_cache_timeout\": 600, \"table_cache_timeout\": 600}. If unset, cache will not be enabled for the functionality. A timeout of 0 indicates that the cache never expires.
3. The schemas_allowed_for_csv_upload is a comma separated list of schemas that CSVs are allowed to upload to. Specify it as \"schemas_allowed_for_csv_upload\": [\"public\", \"csv_upload\"]. If database flavor does not support schema or any schema is allowed to be accessed, just leave the list empty
4. the version field is a string specifying the this db's version. This should be used with Presto DBs so that the syntax is correct
5. The allows_virtual_table_explore field is a boolean specifying whether or not the Explore button in SQL Lab results is shown
6. The disable_data_preview field is a boolean specifying whether or not data preview queries will be run when fetching table metadata in SQL Lab.

", "type": "string" }, "impersonate_user": { diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index f89a6a8535df7..e13e4263a36cd 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -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 })), diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.test.js b/superset-frontend/src/SqlLab/actions/sqlLab.test.js index d04d8b90ab1a8..789ae986bfbe7 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.test.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.test.js @@ -727,28 +727,60 @@ describe('async actions', () => { it('updates the table schema state in the backend', () => { expect.assertions(5); + 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.MERGE_TABLE, // getTableExtendedMetadata + actions.MERGE_TABLE, // addTable + ]; + 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 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' }, + 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.START_QUERY, // runQuery (data preview) actions.MERGE_TABLE, // getTableExtendedMetadata - actions.QUERY_SUCCESS, // querySuccess + 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, tableName, schemaName)) + .dispatch(actions.addTable(query, database, tableName, schemaName)) .then(() => { expect(store.getActions().map(a => a.type)).toEqual( expectedActionTypes, @@ -758,7 +790,6 @@ describe('async actions', () => { expect(fetchMock.calls(getExtraTableMetadataEndpoint)).toHaveLength( 1, ); - // tab state is not updated, since the query is a data preview expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(0); }); diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx index 8807ccdacc7f4..25da49137ad60 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx @@ -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 { if (data.meta === 'table') { this.props.actions.addTable( this.props.queryEditor, + this.props.database, data.value, this.props.queryEditor.schema, ); diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx index 168a53d52b1a0..7899cbf71908a 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx @@ -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} diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx index 0988fd9680371..f9e8c2da9f98f 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx @@ -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); } }; diff --git a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx index d8d4e23eb1651..2387c2e2517fe 100644 --- a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx +++ b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx @@ -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', diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/ExtraOptions.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/ExtraOptions.tsx index 3d28a4a434252..12a712fa35b52 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/ExtraOptions.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/ExtraOptions.tsx @@ -182,7 +182,7 @@ const ExtraOptions = ({ /> - +
+ +
+ + +
+
diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx index 6fcbfdad43848..9db2333573dfa 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx @@ -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 () => { diff --git a/superset-frontend/src/views/CRUD/data/database/types.ts b/superset-frontend/src/views/CRUD/data/database/types.ts index 4ffb69535cbe2..c03891689e90b 100644 --- a/superset-frontend/src/views/CRUD/data/database/types.ts +++ b/superset-frontend/src/views/CRUD/data/database/types.ts @@ -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 diff --git a/superset/dashboards/schemas.py b/superset/dashboards/schemas.py index d2f55d2e15ba8..b1831fdcbbe70 100644 --- a/superset/dashboards/schemas.py +++ b/superset/dashboards/schemas.py @@ -175,6 +175,7 @@ class DatabaseSchema(Schema): allows_subquery = fields.Bool() allows_cost_estimate = fields.Bool() allows_virtual_table_explore = fields.Bool() + disable_data_preview = fields.Bool() explore_database_id = fields.Int() diff --git a/superset/databases/api.py b/superset/databases/api.py index 1b8b408c1ca91..83cdf2571a60e 100644 --- a/superset/databases/api.py +++ b/superset/databases/api.py @@ -145,6 +145,7 @@ class DatabaseRestApi(BaseSupersetModelRestApi): "extra", "force_ctas_schema", "id", + "disable_data_preview", ] add_columns = [ "database_name", diff --git a/superset/databases/schemas.py b/superset/databases/schemas.py index e030a7e06add8..4483b051f1be0 100644 --- a/superset/databases/schemas.py +++ b/superset/databases/schemas.py @@ -115,10 +115,12 @@ '["public", "csv_upload"]**. ' "If database flavor does not support schema or any schema is allowed " "to be accessed, just leave the list empty
" - "4. the ``version`` field is a string specifying the this db's version. " + "4. The ``version`` field is a string specifying the this db's version. " "This should be used with Presto DBs so that the syntax is correct
" "5. The ``allows_virtual_table_explore`` field is a boolean specifying " - "whether or not the Explore button in SQL Lab results is shown.", + "whether or not the Explore button in SQL Lab results is shown.
" + "6. The ``disable_data_preview`` field is a boolean specifying whether or not data " + "preview queries will be run when fetching table metadata in SQL Lab.", True, ) get_export_ids_schema = {"type": "array", "items": {"type": "integer"}} diff --git a/superset/models/core.py b/superset/models/core.py index 7798ddf05930d..51f0731009950 100755 --- a/superset/models/core.py +++ b/superset/models/core.py @@ -212,6 +212,13 @@ def allows_virtual_table_explore(self) -> bool: def explore_database_id(self) -> int: return self.get_extra().get("explore_database_id", self.id) + @property + def disable_data_preview(self) -> bool: + # this will prevent any 'trash value' strings from going through + if self.get_extra().get("disable_data_preview", False) is not True: + return False + return True + @property def data(self) -> Dict[str, Any]: return { @@ -225,6 +232,7 @@ def data(self) -> Dict[str, Any]: "allows_virtual_table_explore": self.allows_virtual_table_explore, "explore_database_id": self.explore_database_id, "parameters": self.parameters, + "disable_data_preview": self.disable_data_preview, "parameters_schema": self.parameters_schema, } diff --git a/superset/views/core.py b/superset/views/core.py index 32844807b60c7..f2f4ab31ddf72 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -182,6 +182,7 @@ "expose_in_sqllab", "force_ctas_schema", "id", + "disable_data_preview", ] DATASOURCE_MISSING_ERR = __("The data source seems to have been deleted") diff --git a/superset/views/database/mixins.py b/superset/views/database/mixins.py index 5382181d2a3ff..d5a5157ef4f7b 100644 --- a/superset/views/database/mixins.py +++ b/superset/views/database/mixins.py @@ -145,7 +145,10 @@ class DatabaseMixin: "4. the ``version`` field is a string specifying the this db's version. " "This should be used with Presto DBs so that the syntax is correct
" "5. The ``allows_virtual_table_explore`` field is a boolean specifying " - "whether or not the Explore button in SQL Lab results is shown.", + "whether or not the Explore button in SQL Lab results is shown
" + "6. The ``disable_data_preview`` field is a boolean specifying whether or" + "not data preview queries will be run when fetching table metadata in" + "SQL Lab.", True, ), "encrypted_extra": utils.markdown( diff --git a/tests/integration_tests/core_tests.py b/tests/integration_tests/core_tests.py index 337becbe48387..26674054ae394 100644 --- a/tests/integration_tests/core_tests.py +++ b/tests/integration_tests/core_tests.py @@ -1517,6 +1517,29 @@ def test_virtual_table_explore_visibility(self): database.extra = json.dumps(extra) self.assertEqual(database.allows_virtual_table_explore, True) + def test_data_preview_visibility(self): + # test that default visibility is allowed + database = utils.get_example_database() + self.assertEqual(database.disable_data_preview, False) + + # test that visibility is disabled when extra is set to true + extra = database.get_extra() + extra["disable_data_preview"] = True + database.extra = json.dumps(extra) + self.assertEqual(database.disable_data_preview, True) + + # test that visibility is enabled when extra is set to false + extra = database.get_extra() + extra["disable_data_preview"] = False + database.extra = json.dumps(extra) + self.assertEqual(database.disable_data_preview, False) + + # test that visibility is not broken with bad values + extra = database.get_extra() + extra["disable_data_preview"] = "trash value" + database.extra = json.dumps(extra) + self.assertEqual(database.disable_data_preview, False) + def test_explore_database_id(self): database = superset.utils.database.get_example_database() explore_database = superset.utils.database.get_example_database() diff --git a/tests/integration_tests/databases/api_tests.py b/tests/integration_tests/databases/api_tests.py index 78d7285e010e7..928f3d595730d 100644 --- a/tests/integration_tests/databases/api_tests.py +++ b/tests/integration_tests/databases/api_tests.py @@ -179,12 +179,14 @@ def test_get_items(self): "changed_on_delta_humanized", "created_by", "database_name", + "disable_data_preview", "explore_database_id", "expose_in_sqllab", "extra", "force_ctas_schema", "id", ] + self.assertGreater(response["count"], 0) self.assertEqual(list(response["result"][0].keys()), expected_columns)