mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
sql lab localStorage config (#6257)
This commit is contained in:
441
superset/assets/src/SqlLab/actions/sqlLab.js
Normal file
441
superset/assets/src/SqlLab/actions/sqlLab.js
Normal file
@@ -0,0 +1,441 @@
|
||||
import shortid from 'shortid';
|
||||
import JSONbig from 'json-bigint';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { SupersetClient } from '@superset-ui/connection';
|
||||
|
||||
import { now } from '../../modules/dates';
|
||||
import {
|
||||
addSuccessToast as addSuccessToastAction,
|
||||
addDangerToast as addDangerToastAction,
|
||||
addInfoToast as addInfoToastAction,
|
||||
} from '../../messageToasts/actions/index';
|
||||
import getClientErrorObject from '../../utils/getClientErrorObject';
|
||||
import COMMON_ERR_MESSAGES from '../../utils/errorMessages';
|
||||
|
||||
export const RESET_STATE = 'RESET_STATE';
|
||||
export const ADD_QUERY_EDITOR = 'ADD_QUERY_EDITOR';
|
||||
export const CLONE_QUERY_TO_NEW_TAB = 'CLONE_QUERY_TO_NEW_TAB';
|
||||
export const REMOVE_QUERY_EDITOR = 'REMOVE_QUERY_EDITOR';
|
||||
export const MERGE_TABLE = 'MERGE_TABLE';
|
||||
export const REMOVE_TABLE = 'REMOVE_TABLE';
|
||||
export const END_QUERY = 'END_QUERY';
|
||||
export const REMOVE_QUERY = 'REMOVE_QUERY';
|
||||
export const EXPAND_TABLE = 'EXPAND_TABLE';
|
||||
export const COLLAPSE_TABLE = 'COLLAPSE_TABLE';
|
||||
export const QUERY_EDITOR_SETDB = 'QUERY_EDITOR_SETDB';
|
||||
export const QUERY_EDITOR_SET_SCHEMA = 'QUERY_EDITOR_SET_SCHEMA';
|
||||
export const QUERY_EDITOR_SET_TITLE = 'QUERY_EDITOR_SET_TITLE';
|
||||
export const QUERY_EDITOR_SET_AUTORUN = 'QUERY_EDITOR_SET_AUTORUN';
|
||||
export const QUERY_EDITOR_SET_SQL = 'QUERY_EDITOR_SET_SQL';
|
||||
export const QUERY_EDITOR_SET_TEMPLATE_PARAMS = 'QUERY_EDITOR_SET_TEMPLATE_PARAMS';
|
||||
export const QUERY_EDITOR_SET_SELECTED_TEXT = 'QUERY_EDITOR_SET_SELECTED_TEXT';
|
||||
export const QUERY_EDITOR_PERSIST_HEIGHT = 'QUERY_EDITOR_PERSIST_HEIGHT';
|
||||
|
||||
export const SET_DATABASES = 'SET_DATABASES';
|
||||
export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR';
|
||||
export const SET_ACTIVE_SOUTHPANE_TAB = 'SET_ACTIVE_SOUTHPANE_TAB';
|
||||
export const REFRESH_QUERIES = 'REFRESH_QUERIES';
|
||||
export const SET_USER_OFFLINE = 'SET_USER_OFFLINE';
|
||||
export const RUN_QUERY = 'RUN_QUERY';
|
||||
export const START_QUERY = 'START_QUERY';
|
||||
export const STOP_QUERY = 'STOP_QUERY';
|
||||
export const REQUEST_QUERY_RESULTS = 'REQUEST_QUERY_RESULTS';
|
||||
export const QUERY_SUCCESS = 'QUERY_SUCCESS';
|
||||
export const QUERY_FAILED = 'QUERY_FAILED';
|
||||
export const CLEAR_QUERY_RESULTS = 'CLEAR_QUERY_RESULTS';
|
||||
export const REMOVE_DATA_PREVIEW = 'REMOVE_DATA_PREVIEW';
|
||||
export const CHANGE_DATA_PREVIEW_ID = 'CHANGE_DATA_PREVIEW_ID';
|
||||
|
||||
export const CREATE_DATASOURCE_STARTED = 'CREATE_DATASOURCE_STARTED';
|
||||
export const CREATE_DATASOURCE_SUCCESS = 'CREATE_DATASOURCE_SUCCESS';
|
||||
export const CREATE_DATASOURCE_FAILED = 'CREATE_DATASOURCE_FAILED';
|
||||
|
||||
export const addInfoToast = addInfoToastAction;
|
||||
export const addSuccessToast = addSuccessToastAction;
|
||||
export const addDangerToast = addDangerToastAction;
|
||||
|
||||
export function resetState() {
|
||||
return { type: RESET_STATE };
|
||||
}
|
||||
|
||||
export function saveQuery(query) {
|
||||
return dispatch =>
|
||||
SupersetClient.post({
|
||||
endpoint: '/savedqueryviewapi/api/create',
|
||||
postPayload: query,
|
||||
stringify: false,
|
||||
})
|
||||
.then(() => dispatch(addSuccessToast(t('Your query was saved'))))
|
||||
.catch(() => dispatch(addDangerToast(t('Your query could not be saved'))));
|
||||
}
|
||||
|
||||
export function startQuery(query) {
|
||||
Object.assign(query, {
|
||||
id: query.id ? query.id : shortid.generate(),
|
||||
progress: 0,
|
||||
startDttm: now(),
|
||||
state: query.runAsync ? 'pending' : 'running',
|
||||
cached: false,
|
||||
});
|
||||
return { type: START_QUERY, query };
|
||||
}
|
||||
|
||||
export function querySuccess(query, results) {
|
||||
return { type: QUERY_SUCCESS, query, results };
|
||||
}
|
||||
|
||||
export function queryFailed(query, msg, link) {
|
||||
return { type: QUERY_FAILED, query, msg, link };
|
||||
}
|
||||
|
||||
export function stopQuery(query) {
|
||||
return { type: STOP_QUERY, query };
|
||||
}
|
||||
|
||||
export function clearQueryResults(query) {
|
||||
return { type: CLEAR_QUERY_RESULTS, query };
|
||||
}
|
||||
|
||||
export function removeDataPreview(table) {
|
||||
return { type: REMOVE_DATA_PREVIEW, table };
|
||||
}
|
||||
|
||||
export function requestQueryResults(query) {
|
||||
return { type: REQUEST_QUERY_RESULTS, query };
|
||||
}
|
||||
|
||||
export function fetchQueryResults(query) {
|
||||
return function (dispatch) {
|
||||
dispatch(requestQueryResults(query));
|
||||
|
||||
return SupersetClient.get({
|
||||
endpoint: `/superset/results/${query.resultsKey}/`,
|
||||
parseMethod: 'text',
|
||||
})
|
||||
.then(({ text = '{}' }) => {
|
||||
const bigIntJson = JSONbig.parse(text);
|
||||
dispatch(querySuccess(query, bigIntJson));
|
||||
})
|
||||
.catch(response =>
|
||||
getClientErrorObject(response).then((error) => {
|
||||
const message = error.error || error.statusText || t('Failed at retrieving results');
|
||||
|
||||
return dispatch(queryFailed(query, message, error.link));
|
||||
}),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function runQuery(query) {
|
||||
return function (dispatch) {
|
||||
dispatch(startQuery(query));
|
||||
const postPayload = {
|
||||
client_id: query.id,
|
||||
database_id: query.dbId,
|
||||
json: true,
|
||||
runAsync: query.runAsync,
|
||||
schema: query.schema,
|
||||
sql: query.sql,
|
||||
sql_editor_id: query.sqlEditorId,
|
||||
tab: query.tab,
|
||||
tmp_table_name: query.tempTableName,
|
||||
select_as_cta: query.ctas,
|
||||
templateParams: query.templateParams,
|
||||
};
|
||||
|
||||
return SupersetClient.post({
|
||||
endpoint: `/superset/sql_json/${window.location.search}`,
|
||||
postPayload,
|
||||
stringify: false,
|
||||
})
|
||||
.then(({ json }) => {
|
||||
if (!query.runAsync) {
|
||||
dispatch(querySuccess(query, json));
|
||||
}
|
||||
})
|
||||
.catch(response =>
|
||||
getClientErrorObject(response).then((error) => {
|
||||
let message = error.error || error.statusText || t('Unknown error');
|
||||
if (message.includes('CSRF token')) {
|
||||
message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
|
||||
}
|
||||
dispatch(queryFailed(query, message, error.link));
|
||||
}),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function postStopQuery(query) {
|
||||
return function (dispatch) {
|
||||
return SupersetClient.post({
|
||||
endpoint: '/superset/stop_query/',
|
||||
postPayload: { client_id: query.id },
|
||||
stringify: false,
|
||||
})
|
||||
.then(() => dispatch(stopQuery(query)))
|
||||
.then(() => dispatch(addSuccessToast(t('Query was stopped.'))))
|
||||
.catch(() => dispatch(addDangerToast(t('Failed at stopping query. ') + `'${query.id}'`)));
|
||||
};
|
||||
}
|
||||
|
||||
export function setDatabases(databases) {
|
||||
return { type: SET_DATABASES, databases };
|
||||
}
|
||||
|
||||
export function addQueryEditor(queryEditor) {
|
||||
const newQueryEditor = {
|
||||
...queryEditor,
|
||||
id: shortid.generate(),
|
||||
};
|
||||
return { type: ADD_QUERY_EDITOR, queryEditor: newQueryEditor };
|
||||
}
|
||||
|
||||
export function cloneQueryToNewTab(query) {
|
||||
return { type: CLONE_QUERY_TO_NEW_TAB, query };
|
||||
}
|
||||
|
||||
export function setActiveQueryEditor(queryEditor) {
|
||||
return { type: SET_ACTIVE_QUERY_EDITOR, queryEditor };
|
||||
}
|
||||
|
||||
export function setActiveSouthPaneTab(tabId) {
|
||||
return { type: SET_ACTIVE_SOUTHPANE_TAB, tabId };
|
||||
}
|
||||
|
||||
export function removeQueryEditor(queryEditor) {
|
||||
return { type: REMOVE_QUERY_EDITOR, queryEditor };
|
||||
}
|
||||
|
||||
export function removeQuery(query) {
|
||||
return { type: REMOVE_QUERY, query };
|
||||
}
|
||||
|
||||
export function queryEditorSetDb(queryEditor, dbId) {
|
||||
return { type: QUERY_EDITOR_SETDB, queryEditor, dbId };
|
||||
}
|
||||
|
||||
export function queryEditorSetSchema(queryEditor, schema) {
|
||||
return { type: QUERY_EDITOR_SET_SCHEMA, queryEditor, schema };
|
||||
}
|
||||
|
||||
export function queryEditorSetAutorun(queryEditor, autorun) {
|
||||
return { type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun };
|
||||
}
|
||||
|
||||
export function queryEditorSetTitle(queryEditor, title) {
|
||||
return { type: QUERY_EDITOR_SET_TITLE, queryEditor, title };
|
||||
}
|
||||
|
||||
export function queryEditorSetSql(queryEditor, sql) {
|
||||
return { type: QUERY_EDITOR_SET_SQL, queryEditor, sql };
|
||||
}
|
||||
|
||||
export function queryEditorSetTemplateParams(queryEditor, templateParams) {
|
||||
return { type: QUERY_EDITOR_SET_TEMPLATE_PARAMS, queryEditor, templateParams };
|
||||
}
|
||||
|
||||
export function queryEditorSetSelectedText(queryEditor, sql) {
|
||||
return { type: QUERY_EDITOR_SET_SELECTED_TEXT, queryEditor, sql };
|
||||
}
|
||||
|
||||
export function mergeTable(table, query) {
|
||||
return { type: MERGE_TABLE, table, query };
|
||||
}
|
||||
|
||||
export function addTable(query, tableName, schemaName) {
|
||||
return function (dispatch) {
|
||||
const table = {
|
||||
dbId: query.dbId,
|
||||
queryEditorId: query.id,
|
||||
schema: schemaName,
|
||||
name: tableName,
|
||||
};
|
||||
dispatch(
|
||||
mergeTable({
|
||||
...table,
|
||||
isMetadataLoading: true,
|
||||
isExtraMetadataLoading: true,
|
||||
expanded: false,
|
||||
}),
|
||||
);
|
||||
|
||||
SupersetClient.get({ endpoint: `/superset/table/${query.dbId}/${tableName}/${schemaName}/` })
|
||||
.then(({ json }) => {
|
||||
const dataPreviewQuery = {
|
||||
id: shortid.generate(),
|
||||
dbId: query.dbId,
|
||||
sql: json.selectStar,
|
||||
tableName,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: false,
|
||||
ctas: false,
|
||||
};
|
||||
const newTable = {
|
||||
...table,
|
||||
...json,
|
||||
expanded: true,
|
||||
isMetadataLoading: false,
|
||||
};
|
||||
|
||||
return Promise.all([
|
||||
dispatch(mergeTable(newTable, dataPreviewQuery)), // Merge table to tables in state
|
||||
dispatch(runQuery(dataPreviewQuery)), // Run query to get preview data for table
|
||||
]);
|
||||
})
|
||||
.catch(() =>
|
||||
Promise.all([
|
||||
dispatch(
|
||||
mergeTable({
|
||||
...table,
|
||||
isMetadataLoading: false,
|
||||
}),
|
||||
),
|
||||
dispatch(addDangerToast(t('An error occurred while fetching table metadata'))),
|
||||
]),
|
||||
);
|
||||
|
||||
SupersetClient.get({
|
||||
endpoint: `/superset/extra_table_metadata/${query.dbId}/${tableName}/${schemaName}/`,
|
||||
})
|
||||
.then(({ json }) =>
|
||||
dispatch(mergeTable({ ...table, ...json, isExtraMetadataLoading: false })),
|
||||
)
|
||||
.catch(() =>
|
||||
Promise.all([
|
||||
dispatch(mergeTable({ ...table, isExtraMetadataLoading: false })),
|
||||
dispatch(addDangerToast(t('An error occurred while fetching table metadata'))),
|
||||
]),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function changeDataPreviewId(oldQueryId, newQuery) {
|
||||
return { type: CHANGE_DATA_PREVIEW_ID, oldQueryId, newQuery };
|
||||
}
|
||||
|
||||
export function reFetchQueryResults(query) {
|
||||
return function (dispatch) {
|
||||
const newQuery = {
|
||||
id: shortid.generate(),
|
||||
dbId: query.dbId,
|
||||
sql: query.sql,
|
||||
tableName: query.tableName,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: false,
|
||||
ctas: false,
|
||||
};
|
||||
dispatch(runQuery(newQuery));
|
||||
dispatch(changeDataPreviewId(query.id, newQuery));
|
||||
};
|
||||
}
|
||||
|
||||
export function expandTable(table) {
|
||||
return { type: EXPAND_TABLE, table };
|
||||
}
|
||||
|
||||
export function collapseTable(table) {
|
||||
return { type: COLLAPSE_TABLE, table };
|
||||
}
|
||||
|
||||
export function removeTable(table) {
|
||||
return { type: REMOVE_TABLE, table };
|
||||
}
|
||||
|
||||
export function refreshQueries(alteredQueries) {
|
||||
return { type: REFRESH_QUERIES, alteredQueries };
|
||||
}
|
||||
|
||||
export function setUserOffline(offline) {
|
||||
return { type: SET_USER_OFFLINE, offline };
|
||||
}
|
||||
|
||||
export function persistEditorHeight(queryEditor, currentHeight) {
|
||||
return { type: QUERY_EDITOR_PERSIST_HEIGHT, queryEditor, currentHeight };
|
||||
}
|
||||
|
||||
export function popStoredQuery(urlId) {
|
||||
return function (dispatch) {
|
||||
return SupersetClient.get({ endpoint: `/kv/${urlId}` })
|
||||
.then(({ json }) =>
|
||||
dispatch(
|
||||
addQueryEditor({
|
||||
title: json.title ? json.title : t('Sjsonhared query'),
|
||||
dbId: json.dbId ? parseInt(json.dbId, 10) : null,
|
||||
schema: json.schema ? json.schema : null,
|
||||
autorun: json.autorun ? json.autorun : false,
|
||||
sql: json.sql ? json.sql : 'SELECT ...',
|
||||
}),
|
||||
),
|
||||
)
|
||||
.catch(() => dispatch(addDangerToast(t("The query couldn't be loaded"))));
|
||||
};
|
||||
}
|
||||
export function popSavedQuery(saveQueryId) {
|
||||
return function (dispatch) {
|
||||
return SupersetClient.get({ endpoint: `/savedqueryviewapi/api/get/${saveQueryId}` })
|
||||
.then(({ json }) => {
|
||||
const { result } = json;
|
||||
const queryEditorProps = {
|
||||
title: result.label,
|
||||
dbId: result.db_id ? parseInt(result.db_id, 10) : null,
|
||||
schema: result.schema,
|
||||
autorun: false,
|
||||
sql: result.sql,
|
||||
};
|
||||
return dispatch(addQueryEditor(queryEditorProps));
|
||||
})
|
||||
.catch(() => dispatch(addDangerToast(t("The query couldn't be loaded"))));
|
||||
};
|
||||
}
|
||||
export function popDatasourceQuery(datasourceKey, sql) {
|
||||
return function (dispatch) {
|
||||
return SupersetClient.get({
|
||||
endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${datasourceKey}`,
|
||||
})
|
||||
.then(({ json }) =>
|
||||
dispatch(
|
||||
addQueryEditor({
|
||||
title: 'Query ' + json.name,
|
||||
dbId: json.database.id,
|
||||
schema: json.schema,
|
||||
autorun: sql !== undefined,
|
||||
sql: sql || json.select_star,
|
||||
}),
|
||||
),
|
||||
)
|
||||
.catch(() => dispatch(addDangerToast(t("The datasource couldn't be loaded"))));
|
||||
};
|
||||
}
|
||||
export function createDatasourceStarted() {
|
||||
return { type: CREATE_DATASOURCE_STARTED };
|
||||
}
|
||||
export function createDatasourceSuccess(data) {
|
||||
const datasource = `${data.table_id}__table`;
|
||||
return { type: CREATE_DATASOURCE_SUCCESS, datasource };
|
||||
}
|
||||
export function createDatasourceFailed(err) {
|
||||
return { type: CREATE_DATASOURCE_FAILED, err };
|
||||
}
|
||||
|
||||
export function createDatasource(vizOptions) {
|
||||
return (dispatch) => {
|
||||
dispatch(createDatasourceStarted());
|
||||
return SupersetClient.post({
|
||||
endpoint: '/superset/sqllab_viz/',
|
||||
postPayload: { data: vizOptions },
|
||||
})
|
||||
.then(({ json }) => {
|
||||
const data = JSON.parse(json);
|
||||
dispatch(createDatasourceSuccess(data));
|
||||
|
||||
return Promise.resolve(data);
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch(createDatasourceFailed(t('An error occurred while creating the data source')));
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user