Compare commits

...

1 Commits

Author SHA1 Message Date
Diego Pucci
3a21559acd fix: Sql Lab incorrect state request 2025-09-27 14:06:17 +03:00
4 changed files with 105 additions and 15 deletions

View File

@@ -518,7 +518,7 @@ export function syncQueryEditor(queryEditor) {
...localStorageQueries.map(query => ...localStorageQueries.map(query =>
migrateQuery(query.id, newQueryEditor.tabViewId, dispatch), migrateQuery(query.id, newQueryEditor.tabViewId, dispatch),
), ),
]); ]).then(() => newQueryEditor); // Return the newQueryEditor for chaining
}) })
.catch(() => .catch(() =>
dispatch( dispatch(
@@ -649,7 +649,7 @@ export function loadQueryEditor(queryEditor) {
return { type: LOAD_QUERY_EDITOR, queryEditor }; return { type: LOAD_QUERY_EDITOR, queryEditor };
} }
export function setTables(tableSchemas) { export function setTables(tableSchemas, queryEditorId = null) {
const tables = tableSchemas const tables = tableSchemas
.filter(tableSchema => tableSchema.description !== null) .filter(tableSchema => tableSchema.description !== null)
.map(tableSchema => { .map(tableSchema => {
@@ -661,9 +661,12 @@ export function setTables(tableSchemas) {
indexes, indexes,
dataPreviewQueryId, dataPreviewQueryId,
} = tableSchema.description; } = tableSchema.description;
// Use the provided queryEditorId if available, otherwise use tab_state_id
const tableQueryEditorId = queryEditorId || tableSchema.tab_state_id.toString();
return { return {
dbId: tableSchema.database_id, dbId: tableSchema.database_id,
queryEditorId: tableSchema.tab_state_id.toString(), queryEditorId: tableQueryEditorId,
catalog: tableSchema.catalog, catalog: tableSchema.catalog,
schema: tableSchema.schema, schema: tableSchema.schema,
name: tableSchema.table, name: tableSchema.table,
@@ -706,7 +709,8 @@ export function fetchQueryEditor(queryEditor, displayLimit) {
hideLeftBar: json.hide_left_bar, hideLeftBar: json.hide_left_bar,
}; };
dispatch(loadQueryEditor(loadedQueryEditor)); dispatch(loadQueryEditor(loadedQueryEditor));
dispatch(setTables(json.table_schemas || [])); // Pass the queryEditor.id to setTables to ensure correct queryEditorId
dispatch(setTables(json.table_schemas || [], loadedQueryEditor.id));
if (json.latest_query && json.latest_query.resultsKey) { if (json.latest_query && json.latest_query.resultsKey) {
dispatch(fetchQueryResults(json.latest_query, displayLimit)); dispatch(fetchQueryResults(json.latest_query, displayLimit));
} }
@@ -953,13 +957,17 @@ export function mergeTable(table, query, prepend) {
export function addTable(queryEditor, tableName, catalogName, schemaName) { export function addTable(queryEditor, tableName, catalogName, schemaName) {
return function (dispatch, getState) { return function (dispatch, getState) {
const { dbId } = getUpToDateQuery(getState(), queryEditor, queryEditor.id); const { dbId } = getUpToDateQuery(getState(), queryEditor, queryEditor.id);
// Always use the actual queryEditor.id for consistency
// The syncTable function will handle converting to tabViewId when syncing to backend
const table = { const table = {
dbId, dbId,
queryEditorId: queryEditor.tabViewId ?? queryEditor.id, queryEditorId: queryEditor.id,
catalog: catalogName, catalog: catalogName,
schema: schemaName, schema: schemaName,
name: tableName, name: tableName,
}; };
dispatch( dispatch(
mergeTable({ mergeTable({
...table, ...table,
@@ -1016,13 +1024,54 @@ export function runTablePreviewQuery(newTable, runPreviewOnly) {
return Promise.resolve(); return Promise.resolve();
}; };
} }
export function syncTable(table, tableMetadata) { export function syncTable(table, tableMetadata) {
return function (dispatch) { return function (dispatch, getState) {
// Get the current queryEditor to use its tabViewId if available
const { queryEditors } = getState().sqlLab;
const queryEditor = queryEditors.find(qe => qe.id === table.queryEditorId);
// If queryEditor is still in localStorage (not synced), wait for sync first
if (queryEditor?.inLocalStorage) {
return dispatch(syncQueryEditor(queryEditor)).then((syncedEditor) => {
// After syncing, update the table with the new queryEditorId
const updatedTable = {
...table,
queryEditorId: syncedEditor?.tabViewId || queryEditor.tabViewId || table.queryEditorId
};
return dispatch(syncTable(updatedTable, tableMetadata));
});
}
// Use tabViewId if available, otherwise use the current queryEditorId
const correctQueryEditorId = queryEditor?.tabViewId || table.queryEditorId;
// Only sync to backend if we have a valid integer tabViewId
const canSyncToBackend = Boolean(queryEditor?.tabViewId && Number.isInteger(queryEditor.tabViewId));
if (!canSyncToBackend) {
// If we can't sync to backend, store in localStorage as fallback
dispatch(
mergeTable({
...table,
...tableMetadata,
expanded: true,
initialized: true,
inLocalStorage: true, // Mark as stored in localStorage
}),
);
return Promise.resolve();
}
const sync = isFeatureEnabled(FeatureFlag.SqllabBackendPersistence) const sync = isFeatureEnabled(FeatureFlag.SqllabBackendPersistence)
? SupersetClient.post({ ? SupersetClient.post({
endpoint: encodeURI('/tableschemaview/'), endpoint: encodeURI('/tableschemaview/'),
postPayload: { table: { ...tableMetadata, ...table } }, postPayload: {
table: {
...tableMetadata,
...table,
queryEditorId: correctQueryEditorId
}
},
}) })
: Promise.resolve({ json: { id: table.id } }); : Promise.resolve({ json: { id: table.id } });

View File

@@ -74,11 +74,6 @@ const SqlEditorLeftBar = ({
queryEditorId, queryEditorId,
height = 500, height = 500,
}: SqlEditorLeftBarProps) => { }: SqlEditorLeftBarProps) => {
const allSelectedTables = useSelector<SqlLabRootState, Table[]>(
({ sqlLab }) =>
sqlLab.tables.filter(table => table.queryEditorId === queryEditorId),
shallowEqual,
);
const dispatch = useDispatch(); const dispatch = useDispatch();
const queryEditor = useQueryEditor(queryEditorId, [ const queryEditor = useQueryEditor(queryEditorId, [
'dbId', 'dbId',
@@ -87,6 +82,32 @@ const SqlEditorLeftBar = ({
'tabViewId', 'tabViewId',
]); ]);
const allSelectedTables = useSelector<SqlLabRootState, Table[]>(
({ sqlLab }) => {
// Find the current queryEditor to get its tabViewId
const currentQueryEditor = sqlLab.queryEditors.find(
qe => qe.id === queryEditorId
);
const tabViewId = currentQueryEditor?.tabViewId;
const filtered = sqlLab.tables.filter(table => {
// Match tables that belong to this queryEditor
// Handle both cases: when queryEditor has a tabViewId (synced) or not (unsaved)
const matchesCurrentId = table.queryEditorId === queryEditorId;
const matchesTabViewId = tabViewId && (
table.queryEditorId === tabViewId ||
table.queryEditorId === String(tabViewId)
);
// Also check if the table's queryEditorId matches the tabViewId as a string
const matchesTabViewIdString = tabViewId && table.queryEditorId === String(tabViewId);
return matchesCurrentId || matchesTabViewId || matchesTabViewIdString;
});
return filtered;
},
shallowEqual,
);
const [_emptyResultsWithSearch, setEmptyResultsWithSearch] = useState(false); const [_emptyResultsWithSearch, setEmptyResultsWithSearch] = useState(false);
const [userSelectedDb, setUserSelected] = useState<DatabaseObject | null>( const [userSelectedDb, setUserSelected] = useState<DatabaseObject | null>(
null, null,
@@ -151,6 +172,7 @@ const SqlEditorLeftBar = ({
}); });
tablesToAdd.forEach(tableName => { tablesToAdd.forEach(tableName => {
// Use the actual queryEditor object with its current id
dispatch(addTable(queryEditor, tableName, catalogName, schemaName)); dispatch(addTable(queryEditor, tableName, catalogName, schemaName));
}); });

View File

@@ -125,9 +125,11 @@ export default function getInitialState({
.filter(tableSchema => tableSchema.description !== null) .filter(tableSchema => tableSchema.description !== null)
.forEach(tableSchema => { .forEach(tableSchema => {
const { dataPreviewQueryId, ...persistData } = tableSchema.description; const { dataPreviewQueryId, ...persistData } = tableSchema.description;
// Use the active tab ID (which corresponds to the queryEditor.id) for consistency
const queryEditorId = activeTab.id.toString();
const table = { const table = {
dbId: tableSchema.database_id ?? 0, dbId: tableSchema.database_id ?? 0,
queryEditorId: tableSchema.tab_state_id.toString(), queryEditorId, // Use the activeTab.id which corresponds to queryEditor.id
catalog: tableSchema.catalog, catalog: tableSchema.catalog,
schema: tableSchema.schema, schema: tableSchema.schema,
name: tableSchema.table, name: tableSchema.table,

View File

@@ -480,12 +480,29 @@ export default function sqlLabReducer(state = {}, action) {
// continue regardless of error // continue regardless of error
} }
// replace localStorage query editor with the server backed one // replace localStorage query editor with the server backed one
return alterInArr( let newState = alterInArr(
state, state,
'queryEditors', 'queryEditors',
action.oldQueryEditor, action.oldQueryEditor,
action.newQueryEditor, action.newQueryEditor,
); );
// Update queryEditorId for all tables that reference the old queryEditor
const updatedTables = newState.tables.map(table => {
if (table.queryEditorId === action.oldQueryEditor.id) {
const newQueryEditorId = action.newQueryEditor.tabViewId || action.newQueryEditor.id;
return {
...table,
queryEditorId: newQueryEditorId,
};
}
return table;
});
return {
...newState,
tables: updatedTables,
};
}, },
[actions.MIGRATE_TABLE]() { [actions.MIGRATE_TABLE]() {
try { try {