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)