Skip to content

Commit

Permalink
chore(sqllab): Relocate get bootstrap data logic (#24936)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpark authored Aug 11, 2023
1 parent ed0d288 commit a44c998
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 76 deletions.
9 changes: 2 additions & 7 deletions superset-frontend/src/SqlLab/actions/sqlLab.js
Original file line number Diff line number Diff line change
Expand Up @@ -570,15 +570,10 @@ export function addQueryEditor(queryEditor) {
export function addNewQueryEditor() {
return function (dispatch, getState) {
const {
sqlLab: {
queryEditors,
tabHistory,
unsavedQueryEditor,
defaultDbId,
databases,
},
sqlLab: { queryEditors, tabHistory, unsavedQueryEditor, databases },
common,
} = getState();
const defaultDbId = common.conf.SQLLAB_DEFAULT_DBID;
const activeQueryEditor = queryEditors.find(
qe => qe.id === tabHistory[tabHistory.length - 1],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ function mapStateToProps({ sqlLab, common }) {
queries: sqlLab.queries,
tabHistory: sqlLab.tabHistory,
tables: sqlLab.tables,
defaultDbId: sqlLab.defaultDbId,
defaultDbId: common.conf.SQLLAB_DEFAULT_DBID,
displayLimit: common.conf.DISPLAY_MAX_ROW,
offline: sqlLab.offline,
defaultQueryLimit: common.conf.DEFAULT_SQLLAB_LIMIT,
Expand Down
3 changes: 1 addition & 2 deletions superset-frontend/src/SqlLab/reducers/getInitialState.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export function dedupeTabHistory(tabHistory) {
}

export default function getInitialState({
defaultDbId,
common,
active_tab: activeTab,
tab_state_ids: tabStateIds = [],
Expand All @@ -55,7 +54,7 @@ export default function getInitialState({
latestQueryId: null,
autorun: false,
templateParams: null,
dbId: defaultDbId,
dbId: common.conf.SQLLAB_DEFAULT_DBID,
queryLimit: common.conf.DEFAULT_SQLLAB_LIMIT,
validationResult: {
id: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import getInitialState, { dedupeTabHistory } from './getInitialState';

const apiData = {
defaultDbId: 1,
common: {
conf: {
DEFAULT_SQLLAB_LIMIT: 1,
Expand Down
63 changes: 63 additions & 0 deletions superset/sqllab/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,31 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations

from typing import Any

import pyarrow as pa

from superset import db, is_feature_enabled
from superset.common.db_query_status import QueryStatus
from superset.daos.database import DatabaseDAO
from superset.models.sql_lab import Query, TabState

DATABASE_KEYS = [
"allow_file_upload",
"allow_ctas",
"allow_cvas",
"allow_dml",
"allow_run_async",
"allows_subquery",
"backend",
"database_name",
"expose_in_sqllab",
"force_ctas_schema",
"id",
"disable_data_preview",
]


def apply_display_max_row_configuration_if_require( # pylint: disable=invalid-name
Expand Down Expand Up @@ -56,3 +76,46 @@ def write_ipc_buffer(table: pa.Table) -> pa.Buffer:
writer.write_table(table)

return sink.getvalue()


def bootstrap_sqllab_data(user_id: int | None) -> dict[str, Any]:
# send list of tab state ids
tabs_state = (
db.session.query(TabState.id, TabState.label).filter_by(user_id=user_id).all()
)
tab_state_ids = [str(tab_state[0]) for tab_state in tabs_state]
# return first active tab, or fallback to another one if no tab is active
active_tab = (
db.session.query(TabState)
.filter_by(user_id=user_id)
.order_by(TabState.active.desc())
.first()
)

databases: dict[int, Any] = {}
for database in DatabaseDAO.find_all():
databases[database.id] = {
k: v for k, v in database.to_json().items() if k in DATABASE_KEYS
}
databases[database.id]["backend"] = database.backend
queries: dict[str, Any] = {}

# These are unnecessary if sqllab backend persistence is disabled
if is_feature_enabled("SQLLAB_BACKEND_PERSISTENCE"):
# return all user queries associated with existing SQL editors
user_queries = (
db.session.query(Query)
.filter_by(user_id=user_id)
.filter(Query.sql_editor_id.in_(tab_state_ids))
.all()
)
queries = {
query.client_id: dict(query.to_dict().items()) for query in user_queries
}

return {
"tab_state_ids": tabs_state,
"active_tab": active_tab.to_dict() if active_tab else None,
"databases": databases,
"queries": queries,
}
1 change: 1 addition & 0 deletions superset/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"SQL_MAX_ROW",
"SUPERSET_WEBSERVER_DOMAINS",
"SQLLAB_SAVE_WARNING_MESSAGE",
"SQLLAB_DEFAULT_DBID",
"DISPLAY_MAX_ROW",
"GLOBAL_ASYNC_QUERIES_TRANSPORT",
"GLOBAL_ASYNC_QUERIES_POLLING_DELAY",
Expand Down
67 changes: 3 additions & 64 deletions superset/views/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
from superset.connectors.base.models import BaseDatasource
from superset.connectors.sqla.models import SqlaTable
from superset.daos.chart import ChartDAO
from superset.daos.database import DatabaseDAO
from superset.daos.datasource import DatasourceDAO
from superset.dashboards.commands.importers.v0 import ImportDashboardsCommand
from superset.dashboards.permalink.commands.get import GetDashboardPermalinkCommand
Expand All @@ -69,8 +68,9 @@
from superset.models.core import Database
from superset.models.dashboard import Dashboard
from superset.models.slice import Slice
from superset.models.sql_lab import Query, TabState
from superset.models.sql_lab import Query
from superset.models.user_attributes import UserAttribute
from superset.sqllab.utils import bootstrap_sqllab_data
from superset.superset_typing import FlaskResponse
from superset.tasks.async_queries import load_explore_json_into_cache
from superset.utils import core as utils
Expand Down Expand Up @@ -115,21 +115,6 @@
stats_logger = config["STATS_LOGGER"]
logger = logging.getLogger(__name__)

DATABASE_KEYS = [
"allow_file_upload",
"allow_ctas",
"allow_cvas",
"allow_dml",
"allow_run_async",
"allows_subquery",
"backend",
"database_name",
"expose_in_sqllab",
"force_ctas_schema",
"id",
"disable_data_preview",
]

DATASOURCE_MISSING_ERR = __("The data source seems to have been deleted")
USER_MISSING_ERR = __("The user seems to have been deleted")
PARAMETER_MISSING_ERR = __(
Expand Down Expand Up @@ -1019,51 +1004,6 @@ def profile(self) -> FlaskResponse:
),
)

@staticmethod
def _get_sqllab_tabs(user_id: int | None) -> dict[str, Any]:
# send list of tab state ids
tabs_state = (
db.session.query(TabState.id, TabState.label)
.filter_by(user_id=user_id)
.all()
)
tab_state_ids = [str(tab_state[0]) for tab_state in tabs_state]
# return first active tab, or fallback to another one if no tab is active
active_tab = (
db.session.query(TabState)
.filter_by(user_id=user_id)
.order_by(TabState.active.desc())
.first()
)

databases: dict[int, Any] = {}
for database in DatabaseDAO.find_all():
databases[database.id] = {
k: v for k, v in database.to_json().items() if k in DATABASE_KEYS
}
databases[database.id]["backend"] = database.backend
queries: dict[str, Any] = {}

# These are unnecessary if sqllab backend persistence is disabled
if is_feature_enabled("SQLLAB_BACKEND_PERSISTENCE"):
# return all user queries associated with existing SQL editors
user_queries = (
db.session.query(Query)
.filter_by(user_id=user_id)
.filter(Query.sql_editor_id.in_(tab_state_ids))
.all()
)
queries = {
query.client_id: dict(query.to_dict().items()) for query in user_queries
}

return {
"tab_state_ids": tabs_state,
"active_tab": active_tab.to_dict() if active_tab else None,
"databases": databases,
"queries": queries,
}

@has_access
@event_logger.log_this
@expose(
Expand All @@ -1076,9 +1016,8 @@ def _get_sqllab_tabs(user_id: int | None) -> dict[str, Any]:
def sqllab(self) -> FlaskResponse:
"""SQL Editor"""
payload = {
"defaultDbId": config["SQLLAB_DEFAULT_DBID"],
"common": common_bootstrap_payload(g.user),
**self._get_sqllab_tabs(get_user_id()),
**bootstrap_sqllab_data(get_user_id()),
}

if form_data := request.form.get("form_data"):
Expand Down
4 changes: 3 additions & 1 deletion tests/integration_tests/core_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from superset.models.slice import Slice
from superset.models.sql_lab import Query
from superset.result_set import SupersetResultSet
from superset.sqllab.utils import bootstrap_sqllab_data
from superset.utils import core as utils
from superset.utils.core import backend
from superset.utils.database import get_example_database
Expand Down Expand Up @@ -1135,7 +1136,8 @@ def test_sqllab_backend_persistence_payload(self):

# we should have only 1 query returned, since the second one is not
# associated with any tabs
payload = views.Superset._get_sqllab_tabs(user_id=user_id)
# TODO: replaces this spec by api/v1/sqllab spec later
payload = bootstrap_sqllab_data(user_id)
self.assertEqual(len(payload["queries"]), 1)

@mock.patch.dict(
Expand Down

0 comments on commit a44c998

Please sign in to comment.