diff --git a/.github/workflows/mac_release.yml b/.github/workflows/mac_release.yml index 2b71a6c90c..cab611936e 100644 --- a/.github/workflows/mac_release.yml +++ b/.github/workflows/mac_release.yml @@ -1,6 +1,6 @@ env: QT_VERSION: '5.15.2' - TCL_VERSION: '8.6' + TCL_VERSION: '8.6.15' SQLITE_VERSION: '3470100' SQLITE_RELEASE_YEAR: '2024' PYTHON_VERSION: '3.9' @@ -173,7 +173,52 @@ jobs: brew uninstall tcl-tk r fi - - name: Install the InstallBuilder + #- name: Debug + #shell: bash + #run: | + # brew search tcl-tk + # ls -l /usr/local/ + # ls -l /usr/local/include + # ls -l /usr/local/opt/ + # ls -l /usr/local/opt/openssl/include/ + # ls -l /usr/local/opt/expat/include + + # 4 commented steps below are merged from 3.4 branch workflows and will probably be used in 3.5, but not yet + #- name: Install Tcl + # run: | + # set -x + # #brew install tcl-tk@8 + # #brew reinstall tcl-tk@8 + # echo "PATH=/usr/local/Cellar/tcl-tk@8/${{ env.TCL_VERSION }}/bin:$PATH" >> $GITHUB_ENV + # echo "TCL_CONFIG=/usr/local/Cellar/tcl-tk@8/${{ env.TCL_VERSION }}/lib/tclConfig.sh" >> $GITHUB_ENV + # + # find /usr/local -name tclsh + # find /usr/local -name tclConfig.sh + + #- name: Qt installation dir + # id: qt-installation-dir + # run: echo "DIR=$(readlink -f ${{ github.workspace }}/..)" >> $GITHUB_OUTPUT + + #- name: Install Qt + # uses: jurplel/install-qt-action@v3 + # with: + # cache: true + # version: ${{ env.QT_VERSION }} + # host: 'mac' + # dir: '${{ steps.qt-installation-dir.DIR }}' + # aqtversion: '==3.0.*' + # py7zrversion: '==0.20.*' + # setup-python: 'false' + # extra: '--external 7z' + + #- name: Fix Qt for MacOS 13 + # shell: bash + # run: | + # TCFILE=$(find $Qt5_DIR/mkspecs/features -name toolchain.prf -type f -maxdepth 1) + # echo "Updating file: $TCFILE" + # sed -i '' 's/if(!darwin:clang)|intel_icc/if(!darwin:clang)|intel_icc|darwin/' $TCFILE + + - name: Install the InstalBuilder shell: bash run: | curl -L ${{ env.INSTALLBUILDER_URL }} --output ib.dmg @@ -325,6 +370,10 @@ jobs: ../../../Plugins make -j 1 +# This is how it was for 3.4 branch - probably will be ised in 3.5 +# "INCLUDEPATH+=$pythonLocation/include/python$PYTHON_VERSION" "LIBS += -L$pythonLocation/lib" \ +# "TCL_CONFIG=${{ env.TCL_CONFIG }}" \ + - name: Copy SQLite extensions to output dir shell: bash run: | diff --git a/ChangeLog.md b/ChangeLog.md index 8745a27fb2..5acb9d3fdc 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,12 @@ # ChangeLog +### 3.4.10 +- CHANGE: #5160 The taskbar has been improved to make the currently active task more distinct from the others. +- BUGFIX: #5148 Fixed counting of tables in queries transparently attaching other databases. +- BIGFIX: #5162 Fixed crash when enabling STRICT option in Table Window. +- BIGFIX: Fixed dialog windows positioning, so it's remembered correctly if the dialog is only moved, but not resized. +- BIGFIX: System tables are again being presented on the database list if the app is configured to do so. + ### 3.4.9 - BUGFIX: #5148 Fixed executing queries that refer to tables with database prefix (i.e. dbName.tableName). - BUGFIX: #5149 Relaxed recent limitation on requiring Custom SQL Functions to have unique names, so that names can duplicate if input parameters differ. diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp index cb22959da2..3198ad5cd1 100644 --- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp @@ -32,6 +32,7 @@ #include #include #include +#include // TODO modify all executor steps to use rebuildTokensFromContents() method, instead of replacing tokens manually. @@ -297,13 +298,6 @@ void QueryExecutor::execInternal() simpleExecution = false; interrupted = false; - if (resultsCountingAsyncId != 0) - { - resultsCountingAsyncId = 0; - db->interrupt(); - releaseResultsAndCleanup(); - } - // Reset context delete context; context = new Context(); @@ -351,6 +345,24 @@ bool QueryExecutor::countResults() return false; } + // Apply all transparent attaches to the counting DB + auto it = context->dbNameToAttach.iterator(); + while (it.hasNext()) + { + auto entry = it.next(); + Db* dbToAttach = DBLIST->getByName(entry.key()); + SqlQueryPtr attachRes = countingDb->exec(QString("ATTACH '%1' AS %2").arg(dbToAttach->getPath(), entry.value())); + if (attachRes->isError()) + { + notifyError(tr("An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1") + .arg("Failed to attach necessary databases for counting.")); + + qDebug() << "Error while attaching db for counting:" << attachRes->getErrorText(); + countingDb->detachAll(); + return false; + } + } + if (asyncMode) { // Start asynchronous results counting query @@ -596,6 +608,7 @@ bool QueryExecutor::handleRowCountingResults(SqlQueryPtr results) .arg(results->getErrorText())); } + countingDb->detachAll(); return true; } diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h index 7610eb5740..4ed64c7797 100644 --- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h +++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h @@ -1385,14 +1385,6 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable */ qint64 simpleExecutionStartTime; - /** - * @brief Asynchronous ID of counting query execution. - * - * Asynchronous ID returned from Db::asyncExec() for the counting query execution. - * See countResults() for details on counting query. - */ - quint32 resultsCountingAsyncId = 0; - /** * @brief Flag indicating results preloading. * @@ -1496,6 +1488,7 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable bool forceSimpleMode = false; ChainExecutor* simpleExecutor = nullptr; Db* countingDb = nullptr; + QStringList countingAttaches; signals: /** diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp index e2acedc0fe..420e29eef7 100644 --- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp @@ -161,8 +161,11 @@ bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const Se QHash>& rowIdColsMap, bool isTopSelect) { SelectResolver::Table destilledTable = table; - if (destilledTable.database == "main" && destilledTable.originalDatabase.isNull()) + if (destilledTable.database.toLower() == "main" && (destilledTable.originalDatabase.isNull() || destilledTable.originalDatabase.toLower() == "main")) + { destilledTable.database = QString(); + destilledTable.originalDatabase = QString(); + } SelectResolver::Table keyTable = destilledTable; diff --git a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp index 5e7d56fa6c..960568671e 100644 --- a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp @@ -1045,6 +1045,21 @@ QList SchemaResolver::getAllTableListItems(const for (const SqlResultsRowPtr& row : results->getAll()) rows << row->valueMap(); + if (!ignoreSystemObjects) + { + static QHash sqliteMasterRow { + {"name", "sqlite_master"}, + {"type", "table"} + }; + + static QHash sqliteTempMasterRow { + {"name", "sqlite_temp_master"}, + {"type", "table"} + }; + + rows << QVariant(sqliteMasterRow) << QVariant(sqliteTempMasterRow); + } + if (useCache) cache.insert(key, new QVariant(rows)); } diff --git a/SQLiteStudio3/guiSQLiteStudio/common/dialogsizehandler.cpp b/SQLiteStudio3/guiSQLiteStudio/common/dialogsizehandler.cpp index 4e29518185..ca3ac208c5 100644 --- a/SQLiteStudio3/guiSQLiteStudio/common/dialogsizehandler.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/common/dialogsizehandler.cpp @@ -42,7 +42,7 @@ void DialogSizeHandler::applyFor(const QString &key, QObject *parent) bool DialogSizeHandler::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::Resize) + if (event->type() == QEvent::Resize | event->type() == QEvent::Move) { QWidget* w = qobject_cast(obj); recentGeometry = w->geometry(); diff --git a/SQLiteStudio3/guiSQLiteStudio/taskbar.cpp b/SQLiteStudio3/guiSQLiteStudio/taskbar.cpp index 4d362a8063..351f417268 100644 --- a/SQLiteStudio3/guiSQLiteStudio/taskbar.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/taskbar.cpp @@ -55,6 +55,18 @@ QList TaskBar::getTasks() const void TaskBar::init() { setAcceptDrops(true); + setStyleSheet(R"( + QToolButton:checked { + color: white; + background-color: #0078D7; + border: 2px solid #005A9E; + border-radius: 4px; + } + QToolButton:hover { + background-color: #005A9E; + color: white; + } + )"); } void TaskBar::mousePressed() diff --git a/SQLiteStudio3/guiSQLiteStudio/windows/tablewindow.cpp b/SQLiteStudio3/guiSQLiteStudio/windows/tablewindow.cpp index 82fda9136e..82184956ed 100644 --- a/SQLiteStudio3/guiSQLiteStudio/windows/tablewindow.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/windows/tablewindow.cpp @@ -1050,7 +1050,7 @@ bool TableWindow::validate(bool skipWarning) QStringList nonStrictColumns; for (SqliteCreateTable::Column* column : createTable->columns) { - if (DataType::isStrict(column->type->name)) + if (DataType::isStrict(column->type ? column->type->name : QString())) continue; nonStrictColumns << column->name; @@ -1402,8 +1402,11 @@ void TableWindow::strictChanged() { for (SqliteCreateTable::Column* column : createTable->columns) { - column->type->precision = QVariant(); - column->type->scale = QVariant(); + if (column->type) + { + column->type->precision = QVariant(); + column->type->scale = QVariant(); + } } }