diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 30cf57e..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/editor.xml b/.idea/editor.xml deleted file mode 100644 index a3aeb4c..0000000 --- a/.idea/editor.xml +++ /dev/null @@ -1,367 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index df87cf9..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 498ae80..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/pgLab.iml b/.idea/pgLab.iml deleted file mode 100644 index 6102194..0000000 --- a/.idea/pgLab.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.junie/skills/reno-release-notes/SKILL.md b/.junie/skills/reno-release-notes/SKILL.md deleted file mode 100644 index 2a1779f..0000000 --- a/.junie/skills/reno-release-notes/SKILL.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -name: reno-release-notes -description: Create, review and lint pgLab release notes with reno (releasenotes/notes YAML fragments). Use whenever the user mentions reno, release notes, releasenotes/notes, "reno new", "reno lint", or asks to add or check a note for a user-visible change in pgLab, even if reno is not named explicitly. ---- - -# reno release notes in pgLab - -pgLab uses [reno](https://docs.openstack.org/reno/latest/) for release notes. -Each user-visible change adds its own small YAML file in `releasenotes/notes/`, -committed together with the change. reno derives the release from git tags, so -never move or rename notes to change releases. Content is reStructuredText, not -Markdown. - -The notes are rendered in the Sphinx user docs through the -`.. release-notes::` directive in `docs/releasenotes.rst` (docs build: -`pip install -r docs/requirements.txt && sphinx-build -b html docs userdocs`). -The About dialog links to the generated `releasenotes.html`. - -## When to write a note - -Write one for: new features, behaviour changes users will notice (UI, menus, -shortcuts, query/code generation output, connection handling), bug fixes, -known issues, and upgrade impact (e.g. changed stored settings or connection -config format). - -Skip: pure refactors, build-system/CI changes, test-only changes, internal -code cleanup, docs-only edits. - -## Sections configured for this project - -Defined in `releasenotes/config.yaml` (render order). Only these keys are valid; -others (`deprecations`, `critical`) are NOT configured here and will not render. - -| Key | Rendered title | Use for | -|------------|------------------|--------------------------------------------| -| `prelude` | (implicit) | Release-wide summary, single string | -| `features` | New Features | New functionality | -| `other` | Changes | Changes to existing behaviour, minor items | -| `issues` | Known Issues | Known problems / limitations | -| `upgrade` | Upgrade Notes | What users must do or know when upgrading | -| `security` | Security Issues | Security fixes | -| `fixes` | Bug Fixes | Ordinary bug fixes | - -Every section except `prelude` is a list of strings. Encoding is utf8. - -## Creating a note - -From the repo root (`pip install reno` if missing): - -```bash -reno new short-descriptive-slug -``` - -This creates `releasenotes/notes/short-descriptive-slug-<16 hex>.yaml`. Keep the -random suffix. Existing examples: `f5-bindings-…`, -`connection-details-in-window-title-…`, `dollar-quoted-string-…`. -Delete all unused template sections, keep only what you need. - -```yaml ---- -features: - - | - The query tool now executes the current statement with - :kbd:`F5`. -fixes: - - | - Fixed reconnect dialog that kept popping up after the connection was lost. -``` - -Short single-line items may be plain (`- text`), longer ones use `- |`. -Wrap at roughly 80 columns. - -## Writing style - -- Write for pgLab users, not patch reviewers: describe the visible effect, not - the implementation (no class or function names unless users see them). -- Past or present tense, full sentences, one bullet per distinct change. -- RST markup: inline literals with double backticks (``` ``pg_catalog`` ```), - links as `` `text `_ ``, GUI menu paths with - `:menuselection:` (e.g. `:menuselection:`Help --> About``), keys with - `:kbd:`. No Markdown, no single-backtick code. -- Mention the PostgreSQL feature or object type involved when relevant. -- For `upgrade`, state the action required. - -## Validate before committing - -```bash -reno lint -reno list # note must be tracked by git to appear for tagged history -``` - -Common failures: YAML indentation/tabs, misspelled section key, a string where -a list is required (or a list for `prelude`), an unconfigured section, bad RST. -Optionally build the docs (command above) to check rendering. - -## Commit rules - -- `git add releasenotes/notes/` and commit it in the same commit as the - change, not a follow-up. -- Commit messages are plain imperative sentences (e.g. "Fix reconnect dialog - popping up repeatedly."). -- To correct a note, edit the same file; don't add a second one. - -## Troubleshooting - -- Note missing in report: not committed, or shallow clone without tags - (`git fetch --tags --unshallow`). -- Wrong release: decided by git history/tags; check `reno list`. -- Broken rendering: almost always RST (single backticks, Markdown links, - indentation). diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index b9c08b0..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,32 +0,0 @@ -# AGENTS.md - -pgLab: Qt 6 / C++20 desktop GUI for PostgreSQL. - -## Layout (link order: core, pgsql -> pglablib -> pglab) -- `core/` – generic utilities (SQL lexer, CSV writer, `Expected`, JSON); no DB access. -- `pgsql/` – thin C++ wrapper around libpq (connection, result, params, oids). -- `pglablib/` – catalog models, code builders, query generation, connection config. -- `pglab/` – the Qt Widgets application (executable). -- `tests/` – gtest executables `PgsqlTests` and `pglabtests`, plus `mygtestutils` (Qt `PrintTo` helpers). -- `docs/` – Sphinx user docs; `releasenotes/notes` – `reno` notes. - -## Build and test -CMake + vcpkg is the active build system (`VCPKG_ROOT` must be set). Qt 6 is not provided by vcpkg; it must be installed on the system. -``` -cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -cmake --build build -ctest --test-dir build --output-on-failure -``` -- Run one suite: `./build/tests/pglabtests/pglabtests --gtest_filter='SqlLexer*'` (same for `PgsqlTests`). -- `-DBUILD_TESTS=OFF` skips tests. `build/` is git-ignored; the first configure builds dependencies and is slow. -- Run the app headless with `QT_QPA_PLATFORM=offscreen ./build/pglab/pglab`. It needs a PostgreSQL server for anything useful. - -## Gotchas -- Tests are registered per executable, so each `ctest` entry covers a whole suite. -- A new test file must be added to the `add_executable` list in `tests//CMakeLists.txt`. Sources are listed explicitly, with no globbing. The same goes for new sources in each library's `CMakeLists.txt`. -- `core/test/` is not referenced by any CMake file (its tests are built from `tests/pglabtests`). Don't expect changes there to be compiled. -- `AUTOMOC`/`AUTOUIC`/`AUTORCC` are on globally, so `.ui` and `.qrc` files only need to be listed as sources. -- `BOOST_ENABLE_ASSERT_HANDLER` is defined; the handler lives in `core/my_boost_assert_handler.cpp`. -- Commit messages are plain imperative sentences. User-visible changes need a reno note (`releasenotes/notes`). -- Docs build: `pip install -r docs/requirements.txt && sphinx-build -b html docs userdocs`. -- Windows (VS 2022) is also a supported platform. Avoid Linux-only code, and don't break `WIN32_LEAN_AND_MEAN`/`NOMINMAX` assumptions. diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index a172074..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -cmake_minimum_required(VERSION 3.21) - -project(pgLab LANGUAGES C CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -add_compile_definitions(BOOST_ENABLE_ASSERT_HANDLER QT_DEPRECATED_WARNINGS) -if(WIN32) - add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX) -endif() - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Sql Concurrent) - -option(BUILD_TESTS "Build the gtest executables and register them with ctest" ON) - -add_subdirectory(core) -add_subdirectory(pgsql) -add_subdirectory(pglablib) -add_subdirectory(pglab) - -if(BUILD_TESTS) - enable_testing() - add_subdirectory(tests) -endif() diff --git a/README.md b/README.md index 7c2eb7e..bdf5ea0 100644 --- a/README.md +++ b/README.md @@ -11,41 +11,3 @@ The release notes use collected from git using [reno](https://docs.openstack.org - googletest - libpq -Boost, Botan, libpq and googletest are provided by vcpkg through the manifest in `vcpkg.json`, so you do not install them manually. - -## Required tools - -- CMake 3.21 or newer -- A C++20 compiler (GCC or Clang on Linux, Visual Studio 2022 on Windows) -- Qt 6 with the Core, Gui, Widgets, Sql and Concurrent components -- vcpkg, with the `VCPKG_ROOT` environment variable pointing to its checkout -- Ninja or make (optional, for faster builds) -- A PostgreSQL server (only needed to run the application against a database) - -## Building - -Configure with the vcpkg toolchain file. The first configure downloads and builds the dependencies, which takes a while: - -``` -cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -cmake --build build -``` - -To skip the test executables, add `-DBUILD_TESTS=OFF` to the configure command. - -## Running the tests - -From the build directory, run: - -``` -ctest --output-on-failure -``` - -## Running the application - -The executable is built to `build/pglab/pglab`. On a machine without a display, set `QT_QPA_PLATFORM=offscreen`: - -``` -./build/pglab/pglab -``` - diff --git a/common.pri b/common.pri new file mode 100644 index 0000000..dcff145 --- /dev/null +++ b/common.pri @@ -0,0 +1,15 @@ +! include( ./local.pri ) { +error( "Use local.pri.sample to create your own local.pri" ) +} + +LIBS += -lUser32 -lws2_32 -llibpq + +CONFIG += c++20 + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += BOOST_ENABLE_ASSERT_HANDLER +DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX _WIN32_WINNT=0x0501 diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index ec63cf3..95b09fc 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,31 +1,41 @@ +set(CMAKE_AUTOMOC ON) + add_library(core STATIC - my_boost_assert_handler.cpp - SqlLexer.cpp - CsvWriter.cpp BackupFormatModel.cpp - ExplainTreeModelItem.cpp - jsoncpp.cpp - SqlLexer.h - ScopeGuard.h - CsvWriter.h - BackupFormatModel.h - Expected.h - ExplainTreeModelItem.h - json/json.h - std_utils.h - IntegerRange.h - ) - + CsvWriter.cpp + my_boost_assert_handler.cpp + PasswordManager.cpp + SqlLexer.cpp) + target_link_libraries(core PUBLIC - Qt6::Core + boost + botan + Qt5::Core ) - -target_include_directories(core PUBLIC + +target_include_directories(core INTERFACE $ +) + +set_target_properties(core PROPERTIES + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON + POSITION_INDEPENDENT_CODE True ) -set_target_properties(core PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - POSITION_INDEPENDENT_CODE ON +add_executable(runtests + test/main.cpp + test/tst_CsvWriter.cpp + test/tst_expected.cpp + test/tst_PasswordManager.cpp + test/tst_scopeguard.cpp + test/tst_SqlLexer.cpp ) + +target_link_libraries(runtests + core + gtest + Threads::Threads + ) + +add_test(tests runtests) diff --git a/core/core.pro b/core/core.pro new file mode 100644 index 0000000..0b424f6 --- /dev/null +++ b/core/core.pro @@ -0,0 +1,43 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-02-26T10:51:14 +# +#------------------------------------------------- + +QT -= gui + +TARGET = core +TEMPLATE = lib +CONFIG += staticlib + +! include( ../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += my_boost_assert_handler.cpp \ + SqlLexer.cpp \ + CsvWriter.cpp \ + BackupFormatModel.cpp \ + ExplainTreeModelItem.cpp \ + jsoncpp.cpp + +HEADERS += \ + SqlLexer.h \ + ScopeGuard.h \ + CsvWriter.h \ + BackupFormatModel.h \ + Expected.h \ + ExplainTreeModelItem.h \ + json/json.h \ + std_utils.h \ + IntegerRange.h + +unix { + target.path = /usr/lib + INSTALLS += target +} diff --git a/local.pri.sample b/local.pri.sample new file mode 100644 index 0000000..44b8f1e --- /dev/null +++ b/local.pri.sample @@ -0,0 +1,17 @@ +# Need paths here to find following library headers +# - botan +# - boost +# - libpq +# ??? +INCLUDEPATH += c:/prog/include +INCLUDEPATH += c:/prog/include/pgsql +INCLUDEPATH += c:/VSproj/boost/include/boost-1_68 + +# Need paths here to find library files for +# - botan +# - boost +# - libpq +# +LIBS += -L\VSproj\boost\lib -L/PROG/LIB + +GOOGLETEST_DIR = c:/prog/googletest diff --git a/pglab/CMakeLists.txt b/pglab/CMakeLists.txt index ab4dda5..d6a1072 100644 --- a/pglab/CMakeLists.txt +++ b/pglab/CMakeLists.txt @@ -1,115 +1,69 @@ -set(PGLAB_SOURCES - main.cpp - About.cpp - catalog/delegates/IconColumnDelegate.cpp - catalog/models/BaseTableModel.cpp - catalog/models/ColumnTableModel.cpp - catalog/models/ConstraintModel.cpp - catalog/models/DatabasesTableModel.cpp - catalog/models/DependantsTableModel.cpp - catalog/models/IndexModel.cpp - catalog/models/ProcTableModel.cpp - catalog/models/RolesTableModel.cpp - catalog/models/SequenceModel.cpp - catalog/models/TriggerTableModel.cpp - catalog/tables/TablesTableModel.cpp - catalog/widgets/CatalogConstraintPage.cpp - catalog/widgets/CatalogFunctionsPage.cpp - catalog/widgets/CatalogIndexPage.cpp - catalog/widgets/CatalogInspector.cpp - catalog/widgets/CatalogNamespacePage.cpp - catalog/widgets/CatalogPageBase.cpp - catalog/widgets/CatalogSequencesPage.cpp - catalog/widgets/CatalogTablesPage.cpp - catalog/widgets/CatalogTypesPage.cpp - catalog/widgets/ColumnPage.cpp - catalog/widgets/DependantsPage.cpp - catalog/widgets/TriggerPage.cpp - codeeditor/CodeEditor.cpp - codeeditor/EditorGutter.cpp - codeeditor/GutterPainter.cpp - crud/CrudModel.cpp - crud/CrudTab.cpp - querytool/QueryExplainModel.cpp - querytool/QueryParamListController.cpp - querytool/QueryResultModel.cpp - querytool/QueryTool.cpp - serverinspector/DatabasesPage.cpp - serverinspector/RolesPage.cpp - serverinspector/ServerInspector.cpp - util/Colors.cpp - util/PgLabItemDelegate.cpp - util/PgLabTableView.cpp - util/SqlSyntaxHighlighter.cpp - ConnectionConfigurationWidget.cpp - ConnectionController.cpp - ManagedPage.cpp - PgDumpOutputHighlighter.cpp - CreateDatabaseDialog.cpp - ConnectionManagerWindow.cpp - ConnectionListModel.cpp - SslModeModel.cpp - stopwatch.cpp - tuplesresultwidget.cpp - BackupDialog.cpp - MasterController.cpp - ParamTypeDelegate.cpp - OpenDatabase.cpp - ProcessStdioWidget.cpp - ResultTableModelUtil.cpp - NamespaceItemModel.cpp - PropertyProxyModel.cpp - CodeGenerator.cpp - UserConfiguration.cpp - widgets/SqlCodePreview.cpp - CustomFilterSortModel.cpp - PropertiesPage.cpp - PasswordPromptDialog.cpp - EditTableWidget.cpp - EditColumnTableModel.cpp - DatabaseWindow.cpp - widgets/SingleRecordModel.cpp - widgets/SingleRecordWidget.cpp - ) +cmake_minimum_required(VERSION 3.2) +project(pglab) -set(PGLAB_FORMS - ConnectionManagerWindow.ui - CreateDatabaseDialog.ui - DatabaseWindow.ui - tuplesresultwidget.ui - querytool/QueryTab.ui - ProcessStdioWidget.ui - crud/CrudTab.ui - CodeGenerator.ui - widgets/SingleRecordWidget.ui - ) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) add_executable(pglab - ${PGLAB_SOURCES} - ${PGLAB_FORMS} + ASyncDBConnection.cpp + ASyncWindow.cpp + BackupDialog.cpp + BackupRestore.cpp + CodeBuilderConfiguration.cpp + ConnectionConfig.cpp + ConnectionList.cpp + ConnectionListModel.cpp + ConnectionManagerWindow.cpp + DatabaseInspectorWidget.cpp + DatabasesTableModel.cpp + DatabaseWindow.cpp + ExplainTreeModelItem.cpp + GlobalIoService.cpp + jsoncpp.cpp + main.cpp + MainWindow.cpp + MasterController.cpp + OpenDatabase.cpp + ParamListModel.cpp + ParamTypeDelegate.cpp + PgAuthIdContainer.cpp + PgAuthId.cpp + PgClass.cpp + PgDatabaseCatalogue.cpp + PgDatabaseContainer.cpp + PgDatabase.cpp + PgNamespace.cpp + PgTypeContainer.cpp + PgType.cpp + ProcessStdioWidget.cpp + QueryExplainModel.cpp + QueryResultModel.cpp + QueryTab.cpp + RolesTableModel.cpp + ServerWindow.cpp + SqlSyntaxHighlighter.cpp + stopwatch.cpp + tsqueue.cpp + tuplesresultwidget.cpp + TypeSelectionItemModel.cpp + util.cpp resources.qrc ) -if(WIN32) - set_target_properties(pglab PROPERTIES WIN32_EXECUTABLE ON) +set_target_properties(pglab PROPERTIES + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON) + +if(CMAKE_COMPILER_IS_GNUCXX) + # target_compile_options(pglab PRIVATE -Wall -fpic -march=native ) + # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og") endif() -target_link_libraries(pglab PRIVATE - pglablib +target_link_libraries( pglab + core pgsql - core - Qt6::Core - Qt6::Gui - Qt6::Widgets - Qt6::Sql - Qt6::Concurrent - ) - -target_include_directories(pglab PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -set_target_properties(pglab PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON + boost-system + Qt5::Widgets + pthread ) diff --git a/pglab/CreateDatabaseDialog.h b/pglab/CreateDatabaseDialog.h index 74cb209..bcc00af 100644 --- a/pglab/CreateDatabaseDialog.h +++ b/pglab/CreateDatabaseDialog.h @@ -3,7 +3,7 @@ #include -#include "catalog/PgDatabase.h" +#include "catalog\PgDatabase.h" class PgDatabaseCatalog; diff --git a/pglab/CreateDatabaseDialog.ui b/pglab/CreateDatabaseDialog.ui index a16e077..f17dbac 100644 --- a/pglab/CreateDatabaseDialog.ui +++ b/pglab/CreateDatabaseDialog.ui @@ -148,7 +148,7 @@ CodeEditor QPlainTextEdit -
codeeditor/CodeEditor.h
+
codeeditor\CodeEditor.h
diff --git a/pglab/catalog/models/DatabasesTableModel.cpp b/pglab/catalog/models/DatabasesTableModel.cpp index 289eea2..ac10ec5 100644 --- a/pglab/catalog/models/DatabasesTableModel.cpp +++ b/pglab/catalog/models/DatabasesTableModel.cpp @@ -169,7 +169,7 @@ QVariant DatabasesTableModel::getData(const QModelIndex &index) const break; case SizeCol: if (d.size.totalBytes >= 0) - v = QVariant::fromValue(d.size.totalBytes); + v = d.size.totalBytes; break; case AclCol: v = db.aclString(); diff --git a/pglab/catalog/models/IndexModel.cpp b/pglab/catalog/models/IndexModel.cpp index e04f715..7cee4e4 100644 --- a/pglab/catalog/models/IndexModel.cpp +++ b/pglab/catalog/models/IndexModel.cpp @@ -114,7 +114,7 @@ QVariant IndexModel::getData(const QModelIndex &index) const break; case SizeCol: - v = QVariant::fromValue(dat.sizeBytes); + v = dat.sizeBytes; break; case ExplicitIndexCol: v = !dat.isSupportingIndex(); diff --git a/pglab/catalog/models/SequenceModel.cpp b/pglab/catalog/models/SequenceModel.cpp index 640b50c..659348f 100644 --- a/pglab/catalog/models/SequenceModel.cpp +++ b/pglab/catalog/models/SequenceModel.cpp @@ -102,12 +102,12 @@ QVariant SequenceModel::data(const QModelIndex &index, int role) const case NameCol: return seq.objectName(); case SchemaCol: return seq.nsName(); case OwnerCol: return seq.ownerName(); - case LastCol: return QVariant::fromValue(seq.last); - case StartCol: return QVariant::fromValue(seq.start); - case MinCol: return QVariant::fromValue(seq.min); - case MaxCol: return QVariant::fromValue(seq.max); - case IncrementCol: return QVariant::fromValue(seq.increment); - case CacheCol: return QVariant::fromValue(seq.cache); + case LastCol: return seq.last; + case StartCol: return seq.start; + case MinCol: return seq.min; + case MaxCol: return seq.max; + case IncrementCol: return seq.increment; + case CacheCol: return seq.cache; case CycledCol: return seq.cycled; case CalledCol: return seq.called; case AclCol: return seq.aclString(); diff --git a/pglab/catalog/tables/TablesTableModel.cpp b/pglab/catalog/tables/TablesTableModel.cpp index d6a4e8b..0df8ff2 100644 --- a/pglab/catalog/tables/TablesTableModel.cpp +++ b/pglab/catalog/tables/TablesTableModel.cpp @@ -178,10 +178,10 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const case OptionsCol: break; case AclCol: return t.aclString(); case CommentCol: return t.description; - case TotalSizeCol: return s.oid == 0 ? QVariant() : QVariant::fromValue(s.totalBytes); - case TableSizeCol: return s.oid == 0 ? QVariant() : QVariant::fromValue(s.totalBytes - s.indexBytes - s.toastBytes); - case IndexSizeCol: return s.oid == 0 ? QVariant() : QVariant::fromValue(s.indexBytes); - case ToastSizeCol: return s.oid == 0 ? QVariant() : QVariant::fromValue(s.toastBytes); + case TotalSizeCol: return s.oid == 0 ? QVariant() : s.totalBytes; + case TableSizeCol: return s.oid == 0 ? QVariant() : s.totalBytes - s.indexBytes - s.toastBytes; + case IndexSizeCol: return s.oid == 0 ? QVariant() : s.indexBytes; + case ToastSizeCol: return s.oid == 0 ? QVariant() : s.toastBytes; } return QVariant(); diff --git a/pglab/crud/CrudModel.cpp b/pglab/crud/CrudModel.cpp index 8367f32..d688bd6 100644 --- a/pglab/crud/CrudModel.cpp +++ b/pglab/crud/CrudModel.cpp @@ -150,7 +150,7 @@ QVariant StringToVariant(const std::string &str, Oid oid) case Pgsql::oid_oid: case Pgsql::int8_oid: - return QVariant::fromValue(static_cast(v)); + return v.operator int64_t(); case Pgsql::bool_oid: return v.operator bool(); diff --git a/pglab/pglab.pro b/pglab/pglab.pro new file mode 100644 index 0000000..93a9186 --- /dev/null +++ b/pglab/pglab.pro @@ -0,0 +1,229 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-11-11T09:17:13 +# +#------------------------------------------------- + +QT += core gui concurrent + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets sql + + +TARGET = pglab +TEMPLATE = app + +! include( ../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} + +DEFINES += _WIN32_WINNT=0x0501 + +win32:RC_ICONS += pglab.ico + +SOURCES += main.cpp\ + About.cpp \ + catalog/delegates/IconColumnDelegate.cpp \ + catalog/models/BaseTableModel.cpp \ + catalog/models/ColumnTableModel.cpp \ + catalog/models/ConstraintModel.cpp \ + catalog/models/DatabasesTableModel.cpp \ + catalog/models/DependantsTableModel.cpp \ + catalog/models/IndexModel.cpp \ + catalog/models/ProcTableModel.cpp \ + catalog/models/RolesTableModel.cpp \ + catalog/models/SequenceModel.cpp \ + catalog/models/TriggerTableModel.cpp \ + catalog/tables/TablesTableModel.cpp \ + catalog/widgets/CatalogConstraintPage.cpp \ + catalog/widgets/CatalogFunctionsPage.cpp \ + catalog/widgets/CatalogIndexPage.cpp \ + catalog/widgets/CatalogInspector.cpp \ + catalog/widgets/CatalogNamespacePage.cpp \ + catalog/widgets/CatalogPageBase.cpp \ + catalog/widgets/CatalogSequencesPage.cpp \ + catalog/widgets/CatalogTablesPage.cpp \ + catalog/widgets/CatalogTypesPage.cpp \ + catalog/widgets/ColumnPage.cpp \ + catalog/widgets/DependantsPage.cpp \ + catalog/widgets/TriggerPage.cpp \ + codeeditor/CodeEditor.cpp \ + codeeditor/EditorGutter.cpp \ + codeeditor/GutterPainter.cpp \ + crud/CrudModel.cpp \ + crud/CrudTab.cpp \ + querytool/QueryExplainModel.cpp \ + querytool/QueryParamListController.cpp \ + querytool/QueryResultModel.cpp \ + querytool/QueryTool.cpp \ + serverinspector/DatabasesPage.cpp \ + serverinspector/RolesPage.cpp \ + serverinspector/ServerInspector.cpp \ + util/Colors.cpp \ + util/PgLabItemDelegate.cpp \ + util/PgLabTableView.cpp \ + util/SqlSyntaxHighlighter.cpp \ + ConnectionConfigurationWidget.cpp \ + ConnectionController.cpp \ + ManagedPage.cpp \ + PgDumpOutputHighlighter.cpp \ + CreateDatabaseDialog.cpp \ + ConnectionManagerWindow.cpp \ + ConnectionListModel.cpp \ + SslModeModel.cpp \ + stopwatch.cpp \ + TuplesResultWidget.cpp \ + BackupDialog.cpp \ + MasterController.cpp \ + ParamTypeDelegate.cpp \ + OpenDatabase.cpp \ + ProcessStdioWidget.cpp \ + ResultTableModelUtil.cpp \ + NamespaceItemModel.cpp \ + PropertyProxyModel.cpp \ + CodeGenerator.cpp \ + UserConfiguration.cpp \ + widgets/SqlCodePreview.cpp \ + CustomFilterSortModel.cpp \ + PropertiesPage.cpp \ + PasswordPromptDialog.cpp \ + EditTableWidget.cpp \ + EditColumnTableModel.cpp \ + DatabaseWindow.cpp \ + widgets/SingleRecordModel.cpp \ + widgets/SingleRecordWidget.cpp + +HEADERS += \ + About.h \ + Config.h \ + catalog/delegates/IconColumnDelegate.h \ + catalog/models/BaseTableModel.h \ + catalog/models/ColumnTableModel.h \ + catalog/models/ConstraintModel.h \ + catalog/models/DatabasesTableModel.h \ + catalog/models/DependantsTableModel.h \ + catalog/models/IndexModel.h \ + catalog/models/ProcTableModel.h \ + catalog/models/RolesTableModel.h \ + catalog/models/SequenceModel.h \ + catalog/models/TriggerTableModel.h \ + catalog/tables/TablesTableModel.h \ + catalog/widgets/CatalogConstraintPage.h \ + catalog/widgets/CatalogFunctionsPage.h \ + catalog/widgets/CatalogIndexPage.h \ + catalog/widgets/CatalogInspector.h \ + catalog/widgets/CatalogNamespacePage.h \ + catalog/widgets/CatalogPageBase.h \ + catalog/widgets/CatalogSequencesPage.h \ + catalog/widgets/CatalogTablesPage.h \ + catalog/widgets/CatalogTypesPage.h \ + catalog/widgets/ColumnPage.h \ + catalog/widgets/DependantsPage.h \ + catalog/widgets/TriggerPage.h \ + codeeditor/CodeEditor.h \ + codeeditor/EditorGutter.h \ + codeeditor/GutterPainter.h \ + crud/CrudModel.h \ + crud/CrudTab.h \ + querytool/QueryExplainModel.h \ + querytool/QueryParamListController.h \ + querytool/QueryResultModel.h \ + querytool/QueryTool.h \ + serverinspector/DatabasesPage.h \ + serverinspector/RolesPage.h \ + serverinspector/ServerInspector.h \ + util/Colors.h \ + util/PgLabItemDelegate.h \ + util/PgLabTableView.h \ + util/PgLabTableViewHelper.h \ + util/SqlSyntaxHighlighter.h \ + ConnectionConfigurationWidget.h \ + ConnectionController.h \ + IDatabaseWindow.h \ + ManagedPage.h \ + PgDumpOutputHighlighter.h \ + CreateDatabaseDialog.h \ + ConnectionManagerWindow.h \ + ConnectionListModel.h \ + SslModeModel.h \ + stopwatch.h \ + TuplesResultWidget.h \ + BackupDialog.h \ + MasterController.h \ + ParamTypeDelegate.h \ + OpenDatabase.h \ + ProcessStdioWidget.h \ + ResultTableModelUtil.h \ + NamespaceItemModel.h \ + AbstractCommand.h \ + PropertyProxyModel.h \ + CustomDataRole.h \ + CodeGenerator.h \ + UserConfiguration.h \ + widgets/SqlCodePreview.h \ + CustomFilterSortModel.h \ + PropertiesPage.h \ + PasswordPromptDialog.h \ + EditTableWidget.h \ + EditColumnTableModel.h \ + DatabaseWindow.h \ + NamespaceFilter.h \ + widgets/SingleRecordModel.h \ + widgets/SingleRecordWidget.h + +FORMS += \ + ConnectionManagerWindow.ui \ + CreateDatabaseDialog.ui \ + DatabaseWindow.ui \ + TuplesResultWidget.ui \ + querytool/QueryTab.ui \ + ProcessStdioWidget.ui \ + crud/CrudTab.ui \ + CodeGenerator.ui \ + widgets/SingleRecordWidget.ui + +RESOURCES += \ + resources.qrc + +#QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01 + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -lcore +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -lcore + +INCLUDEPATH += $$PWD/../core +DEPENDPATH += $$PWD/../core + +win32:CONFIG(debug, debug|release): LIBS += -lbotand +else:win32:CONFIG(release, debug|release): LIBS += -lbotan + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib + + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../pgsql/release/ -lpgsql +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../pgsql/debug/ -lpgsql +else:unix:!macx: LIBS += -L$$OUT_PWD/../pgsql/ -lpgsql + +INCLUDEPATH += $$PWD/../pgsql +DEPENDPATH += $$PWD/../pgsql + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/libpgsql.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/libpgsql.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/pgsql.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/pgsql.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../pgsql/libpgsql.a + + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../pglablib/release/ -lpglablib +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../pglablib/debug/ -lpglablib +else:unix:!macx: LIBS += -L$$OUT_PWD/../pglablib/ -lpglablib + +INCLUDEPATH += $$PWD/../pglablib +DEPENDPATH += $$PWD/../pglablib + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pglablib/release/libpglablib.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pglablib/debug/libpglablib.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pglablib/release/pglablib.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pglablib/debug/pglablib.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../pglablib/libpglablib.a diff --git a/pglab/querytool/QueryExplainModel.cpp b/pglab/querytool/QueryExplainModel.cpp index bcce73b..51381ec 100644 --- a/pglab/querytool/QueryExplainModel.cpp +++ b/pglab/querytool/QueryExplainModel.cpp @@ -40,7 +40,7 @@ if (role == Qt::DisplayRole) { result = item->estimateError(); break; case c_ColumnRowCount: - result = QVariant::fromValue(item->actualRows); + result = item->actualRows; break; case c_ColumnLoops: result = item->actualLoops; diff --git a/pglabAll.pro b/pglabAll.pro new file mode 100644 index 0000000..8631a5e --- /dev/null +++ b/pglabAll.pro @@ -0,0 +1,18 @@ +TEMPLATE = subdirs + +DEFINES += BOOST_ENABLE_ASSERT_HANDLER + +SUBDIRS += core \ + pgsql \ + pglablib \ + pglab + +pglab.depends = core pgsql pglablib +pgsql.depends = core +pglablib.depends = core pgsql +tests.depends = core pgsql pglablib + + +CONFIG(debug, debug|release) { +SUBDIRS += tests +} diff --git a/pglablib/ASyncDBConnection.cpp b/pglablib/ASyncDBConnection.cpp index 2b5c2fb..1c27fb9 100644 --- a/pglablib/ASyncDBConnection.cpp +++ b/pglablib/ASyncDBConnection.cpp @@ -1,14 +1,13 @@ -#include "ASyncDBConnection.h" +#include "ASyncDBConnection.h" #include "ScopeGuard.h" #include "util.h" #include "Pgsql_PgException.h" -#include +#include "Win32Event.h" +#include "WaitHandleList.h" #include #include +#include #include -#include -#include -#include namespace { @@ -46,6 +45,10 @@ public: struct t_Command { std::mutex m_mutex; t_CommandQueue m_queue; + Win32Event m_newEvent; + t_Command() + : m_newEvent(Win32Event::Reset::Auto, Win32Event::Initial::Clear) + {} } m_commandQueue; ConnectionConfig m_config; @@ -61,29 +64,18 @@ public: void stop(); - /// Wakes the worker thread when it is waiting in its event loop - void wake(); - private: - enum class WaitResult { - Socket, ///< the socket became ready - Wakeup, ///< woken up by stop() or by a new command - Timeout ///< the timeout expired - }; - ASyncDBConnection *asyncConnObject = nullptr; - std::atomic terminateRequested{false}; ///< is set when the thread should stop - std::mutex m_wakeMutex; - QEventLoop *m_loop = nullptr; ///< loop the worker blocks in, guarded by m_wakeMutex + /// \todo Implement new method to stop the thread + Win32Event m_stopEvent; Pgsql::Connection m_connection; + bool terminateRequested = false; ///< is set when the thread should stop bool m_terminated = true; Pgsql::Canceller m_canceller; QElapsedTimer m_timer; - bool hasQueuedCommand(); - WaitResult waitForSocket(QSocketNotifier::Type type, int timeout_ms, bool wakeOnNewCommand); bool makeConnection(); void communicate(); @@ -105,6 +97,7 @@ private: ASyncDBConnectionThread::ASyncDBConnectionThread(ASyncDBConnection *asco) : asyncConnObject(asco) + , m_stopEvent(Win32Event::Reset::Manual, Win32Event::Initial::Clear) {} void ASyncDBConnectionThread::run() @@ -161,59 +154,6 @@ bool ASyncDBConnectionThread::cancel() return m_canceller.cancel(nullptr); } -bool ASyncDBConnectionThread::hasQueuedCommand() -{ - std::lock_guard lg(m_commandQueue.m_mutex); - return !m_commandQueue.m_queue.empty(); -} - -ASyncDBConnectionThread::WaitResult ASyncDBConnectionThread::waitForSocket(QSocketNotifier::Type type, int timeout_ms, bool wakeOnNewCommand) -{ - QEventLoop loop; - WaitResult result = WaitResult::Wakeup; - - QSocketNotifier notifier(m_connection.socket(), type); - QObject::connect(¬ifier, &QSocketNotifier::activated, &loop, [&result, &loop] { - result = WaitResult::Socket; - loop.quit(); - }); - - QTimer timer; - timer.setSingleShot(true); - if (timeout_ms >= 0) { - QObject::connect(&timer, &QTimer::timeout, &loop, [&result, &loop] { - result = WaitResult::Timeout; - loop.quit(); - }); - timer.start(timeout_ms); - } - - { - std::lock_guard lg(m_wakeMutex); - m_loop = &loop; - } - - // Checked after publishing the loop, so a wake-up that happened before is not lost - bool pending = terminateRequested || (wakeOnNewCommand && hasQueuedCommand()); - if (!pending) { - loop.exec(); - } - - { - std::lock_guard lg(m_wakeMutex); - m_loop = nullptr; - } - return result; -} - -void ASyncDBConnectionThread::wake() -{ - std::lock_guard lg(m_wakeMutex); - if (m_loop) { - QMetaObject::invokeMethod(m_loop, [loop = m_loop] { loop->quit(); }, Qt::QueuedConnection); - } -} - bool ASyncDBConnectionThread::makeConnection() { using namespace std::literals::chrono_literals; @@ -225,14 +165,30 @@ bool ASyncDBConnectionThread::makeConnection() bool ok = m_connection.connectStart(conn_string); //keywords, values); auto start = std::chrono::steady_clock::now(); if (ok && m_connection.status() != CONNECTION_BAD) { - QSocketNotifier::Type type = QSocketNotifier::Write; + Win32Event socket_event(Win32Event::Reset::Auto, Win32Event::Initial::Clear); + + long fd = FD_WRITE; while (true) { // poll till complete or failed (we can get an abort command) - auto elapsed = std::chrono::steady_clock::now() - start; - auto remaining = std::chrono::duration_cast(30s - elapsed).count(); - WaitResult res = waitForSocket(type, remaining > 0 ? static_cast(remaining) : 0, false); + int sock = m_connection.socket(); + WSAEventSelect(sock, socket_event.handle(), fd); + WaitHandleList whl; + auto wait_result_socket_event = whl.add(socket_event); + auto wait_result_stop = whl.add(m_stopEvent); - if (res == WaitResult::Socket) { + auto nu = std::chrono::steady_clock::now(); + std::chrono::duration diff = -(nu-start); + diff += 30s; + DWORD timeout = diff.count(); + + DWORD res = MsgWaitForMultipleObjectsEx( + whl.count(), // _In_ DWORD nCount, + whl, // _In_ const HANDLE *pHandles, + timeout, // _In_ DWORD dwMilliseconds, + 0, // _In_ DWORD dwWakeMask, + 0 // _In_ DWORD dwFlags + ); + if (res == wait_result_socket_event) { auto poll_state = m_connection.connectPoll(); if (poll_state == PGRES_POLLING_OK) { qDebug() << "ASyncDBConnection Connected"; @@ -246,21 +202,17 @@ bool ASyncDBConnectionThread::makeConnection() } else if (poll_state == PGRES_POLLING_READING) { doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" }); - type = QSocketNotifier::Read; + fd = FD_READ; } else if (poll_state == PGRES_POLLING_WRITING) { doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" }); - type = QSocketNotifier::Write; + fd = FD_WRITE; } } - else if (terminateRequested) { - m_connection.close(); - return false; - } - else if (res == WaitResult::Timeout) { - doStateCallback({ ASyncDBConnection::State::NotConnected, "Connection timed out" }); + else if (res == wait_result_stop) { m_connection.close(); return false; + } } // end while (true) } @@ -300,7 +252,7 @@ void ASyncDBConnectionThread::communicate() void ASyncDBConnectionThread::stop() { terminateRequested = true; - wake(); + m_stopEvent.set(); } void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state) @@ -312,18 +264,34 @@ void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state bool ASyncDBConnectionThread::waitForAndSendCommand() { - if (hasQueuedCommand()) { - doNewCommand(); - return true; - } + SOCKET sock = static_cast(m_connection.socket()); + Win32Event socket_event(Win32Event::Reset::Manual, Win32Event::Initial::Clear); + long fd = FD_READ | FD_CLOSE; + WSAEventSelect(sock, socket_event.handle(), fd); - // Idle connection: a readable socket carries notifies or notices, or signals a lost connection - if (waitForSocket(QSocketNotifier::Read, -1, true) == WaitResult::Socket) { - if (!m_connection.consumeInput()) { - doStateCallback({ ASyncDBConnection::State::NotConnected, "Connection lost" }); - return false; - } + WaitHandleList whl; + auto wait_result_new_command = whl.add(m_commandQueue.m_newEvent); + auto wait_result_socket = whl.add(socket_event); + whl.add(m_stopEvent); + + DWORD res = MsgWaitForMultipleObjectsEx( + whl.count(), // _In_ DWORD nCount, + whl, // _In_ const HANDLE *pHandles, + INFINITE, // _In_ DWORD dwMilliseconds, + 0, // _In_ DWORD dwWakeMask, + 0 // _In_ DWORD dwFlags + ); + if (res == wait_result_new_command) { + doNewCommand(); } + else if (res == wait_result_socket) { + WSANETWORKEVENTS net_events; + WSAEnumNetworkEvents(sock, socket_event.handle(), &net_events); + if (net_events.lNetworkEvents & FD_CLOSE) { + doStateCallback({ ASyncDBConnection::State::NotConnected, "Connection lost" }); + return false; + } + } // Note if it was stop we can just return and function // above will stop looping because terminateRequested has been set too by stop return true; @@ -379,16 +347,42 @@ bool ASyncDBConnectionThread::consumeResultInput() void ASyncDBConnectionThread::waitForResult() { + SOCKET sock = static_cast(m_connection.socket()); + Win32Event socket_event(Win32Event::Reset::Manual, Win32Event::Initial::Clear); + + long fd = FD_READ | FD_CLOSE; + bool finished = false; while ( ! finished) { - WaitResult res = waitForSocket(QSocketNotifier::Read, -1, false); + WSAEventSelect(sock, socket_event.handle(), fd); - if (res == WaitResult::Socket) { - if (consumeResultInput()) { - finished = true; + WaitHandleList whl; + auto wait_result_socket = whl.add(socket_event); + auto wait_result_stop = whl.add(m_stopEvent); + + DWORD res = MsgWaitForMultipleObjectsEx( + whl.count(), // _In_ DWORD nCount, + whl, // _In_ const HANDLE *pHandles, + INFINITE, // _In_ DWORD dwMilliseconds, + 0, // _In_ DWORD dwWakeMask, + 0 // _In_ DWORD dwFlags + ); + if (res == wait_result_socket) { + WSANETWORKEVENTS net_events; + WSAEnumNetworkEvents(sock, socket_event.handle(), &net_events); + + if (net_events.lNetworkEvents & FD_READ) { + if (consumeResultInput()) { + finished = true; + } } + else if (net_events.lNetworkEvents & FD_CLOSE) { + doStateCallback({ ASyncDBConnection::State::NotConnected, "Close while waiting for result" }); + finished = true; + stop(); + } } - else if (terminateRequested) { + if (res == wait_result_stop) { // Send cancel, close connection and terminate thread cancel(); doStateCallback(ASyncDBConnection::State::Terminating); @@ -461,8 +455,8 @@ bool ASyncDBConnection::send(const std::string &command, on_result_callback on_r { std::lock_guard lg(m_threadData->m_commandQueue.m_mutex); m_threadData->m_commandQueue.m_queue.emplace(command, on_result); + m_threadData->m_commandQueue.m_newEvent.set(); } - m_threadData->wake(); return true; } @@ -474,8 +468,8 @@ bool ASyncDBConnection::send(const std::string &command, Pgsql::Params params, o { std::lock_guard lg(m_threadData->m_commandQueue.m_mutex); m_threadData->m_commandQueue.m_queue.emplace(command, std::move(params), on_result); + m_threadData->m_commandQueue.m_newEvent.set(); } - m_threadData->wake(); return true; } diff --git a/pglablib/ASyncDBConnection.h b/pglablib/ASyncDBConnection.h index 0479f5f..02f5310 100644 --- a/pglablib/ASyncDBConnection.h +++ b/pglablib/ASyncDBConnection.h @@ -11,7 +11,6 @@ #include #include #include -#include class ASyncDBConnectionThread; /** \brief Class that handles asynchronous execution of queries. @@ -34,7 +33,7 @@ public: class StateData { public: - enum State State; + State State; QString Message; StateData(enum State state, QString message = QString()) diff --git a/pglablib/CMakeLists.txt b/pglablib/CMakeLists.txt deleted file mode 100644 index a3c759d..0000000 --- a/pglablib/CMakeLists.txt +++ /dev/null @@ -1,187 +0,0 @@ -add_library(pglablib STATIC - Pglablib.cpp - ASyncDBConnection.cpp - ConnectionConfig.cpp - TestConnection.cpp - catalog/PgType.cpp - catalog/PgTypeContainer.cpp - catalog/PgNamespace.cpp - catalog/PgClass.cpp - catalog/PgDatabase.cpp - catalog/PgDatabaseContainer.cpp - catalog/PgAuthId.cpp - catalog/PgAuthIdContainer.cpp - catalog/PgClassContainer.cpp - catalog/PgDatabaseCatalog.cpp - catalog/PgNamespaceContainer.cpp - catalog/PgAttribute.cpp - catalog/PgContainer.cpp - catalog/PgAttributeContainer.cpp - catalog/PgIndex.cpp - catalog/PgIndexContainer.cpp - catalog/PgConstraint.cpp - catalog/PgConstraintContainer.cpp - ParamListJson.cpp - ParamListModel.cpp - sqlite/SQLiteConnection.cpp - sqlite/sqlite3.c - ui/catalog/tables/TableNode.cpp - ui/catalog/tables/TableSize.cpp - ui/catalog/tables/TableTreeBuilder.cpp - util.cpp - SqlFormattingUtils.cpp - catalog/PgKeywordList.cpp - QueryGenerator.cpp - catalog/PgObject.cpp - catalog/PgTablespace.cpp - catalog/PgTablespaceContainer.cpp - codebuilder/LanguageConfig.cpp - codebuilder/CodeBuilder.cpp - codebuilder/NameManglingRules.cpp - codebuilder/DefaultConfigs.cpp - codebuilder/TypeMappings.cpp - codebuilder/IndentationConfig.cpp - codebuilder/StructureTemplate.cpp - FormatToStream.cpp - codebuilder/StringLiteralRules.cpp - codebuilder/StringEscapeRule.cpp - catalog/PgTrigger.cpp - catalog/PgTriggerContainer.cpp - catalog/PgProc.cpp - catalog/PgProcContainer.cpp - catalog/PgDatabaseObject.cpp - catalog/PgServerObject.cpp - catalog/PgNamespaceObject.cpp - catalog/PgCollation.cpp - catalog/PgCollationContainer.cpp - catalog/PgInherits.cpp - catalog/PgInheritsContainer.cpp - SelectionEditorFactory.cpp - catalog/PgAm.cpp - model/TypeModelFactory.cpp - model/TypeSelectionItemModel.cpp - catalog/PgAmContainer.cpp - model/CollationModel.cpp - model/CollationModelFactory.cpp - catalog/PgLanguageContainer.cpp - catalog/PgLanguage.cpp - catalog/PgAcl.cpp - catalog/PgSequence.cpp - catalog/PgSequenceContainer.cpp - utils/HumanReadableBytes.cpp - utils/KeyStrengthener.cpp - utils/PasswordManager.cpp - utils/PostgresqlUrlParser.cpp - Pglablib.h - ASyncDBConnection.h - ConnectionConfig.h - TestConnection.h - catalog/PgType.h - catalog/PgTypeContainer.h - catalog/PgNamespace.h - catalog/PgClass.h - catalog/PgDatabase.h - catalog/PgDatabaseContainer.h - catalog/PgContainer.h - catalog/PgAuthId.h - catalog/PgAuthIdContainer.h - catalog/PgClassContainer.h - catalog/PgDatabaseCatalog.h - catalog/PgNamespaceContainer.h - catalog/PgAttribute.h - catalog/PgAttributeContainer.h - catalog/PgIndex.h - catalog/PgIndexContainer.h - catalog/PgConstraint.h - catalog/PgConstraintContainer.h - ParamListJson.h - ParamListModel.h - sqlite/SQLiteConnection.h - sqlite/sqlite3.h - sqlite/sqlite3ext.h - ui/catalog/tables/TableNode.h - ui/catalog/tables/TableSize.h - ui/catalog/tables/TableTreeBuilder.h - util.h - SqlFormattingUtils.h - catalog/PgCatalogTypes.h - catalog/PgKeywordList.h - QueryGenerator.h - catalog/PgObject.h - catalog/PgTablespace.h - catalog/PgTablespaceContainer.h - codebuilder/LanguageConfig.h - codebuilder/CodeBuilder.h - codebuilder/NameManglingRules.h - codebuilder/DefaultConfigs.h - codebuilder/TypeMappings.h - codebuilder/IndentationConfig.h - codebuilder/StructureTemplate.h - FormatToStream.h - codebuilder/ResultLoopTemplate.h - codebuilder/StringEscapeRule.h - codebuilder/StringLiteralRules.h - catalog/PgTrigger.h - catalog/PgTriggerContainer.h - catalog/PgProc.h - catalog/PgProcContainer.h - catalog/PgDatabaseObject.h - catalog/PgServerObject.h - catalog/PgNamespaceObject.h - catalog/PgCollation.h - catalog/PgCollationContainer.h - AbstractModelFactory.h - AbstractEditorFactory.h - catalog/PgInherits.h - catalog/PgInheritsContainer.h - SelectionEditorFactory.h - model/TypeSelectionItemModel.h - model/TypeModelFactory.h - catalog/PgAm.h - catalog/PgAmContainer.h - model/CollationModel.h - model/CollationModelFactory.h - catalog/PgLanguageContainer.h - catalog/PgLanguage.h - catalog/PgAcl.h - catalog/PgSequence.h - catalog/PgSequenceContainer.h - utils/HumanReadableBytes.h - utils/KeyStrengthener.h - utils/PasswordManager.h - utils/PostgresqlUrlParser.h - ) - -find_package(Boost REQUIRED COMPONENTS container timer chrono assert) - -find_path(BOTAN_INCLUDE_DIR botan/hash.h REQUIRED) -find_library(BOTAN_LIBRARY NAMES botan-3 botan REQUIRED) -if(NOT TARGET Botan::Botan) - add_library(Botan::Botan STATIC IMPORTED) - set_target_properties(Botan::Botan PROPERTIES - IMPORTED_LOCATION "${BOTAN_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${BOTAN_INCLUDE_DIR}" - ) -endif() - -target_link_libraries(pglablib PUBLIC - core - pgsql - Boost::container - Boost::timer - Boost::chrono - Boost::assert - Botan::Botan - Qt6::Core - Qt6::Widgets - ) - -target_include_directories(pglablib PUBLIC - $ - ) - -set_target_properties(pglablib PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - POSITION_INDEPENDENT_CODE ON - ) diff --git a/pglablib/SqlFormattingUtils.cpp b/pglablib/SqlFormattingUtils.cpp index ff7f1d3..a75620e 100644 --- a/pglablib/SqlFormattingUtils.cpp +++ b/pglablib/SqlFormattingUtils.cpp @@ -200,7 +200,7 @@ QString quoteIdent(QString ident) { assert(ident.length() > 0); - static const QChar dquote = u'"'; + static const wchar_t dquote = L'"'; if (identNeedsQuotes(ident)) { QString out; diff --git a/pglablib/WaitHandleList.cpp b/pglablib/WaitHandleList.cpp new file mode 100644 index 0000000..d219610 --- /dev/null +++ b/pglablib/WaitHandleList.cpp @@ -0,0 +1,31 @@ +#include "WaitHandleList.h" +#include "win32event.h" + +WaitHandleList::WaitHandleList() = default; +WaitHandleList::~WaitHandleList() = default; + +WaitResultValue WaitHandleList::add(HANDLE h) +{ + m_waitHandles.push_back(h); + return WAIT_OBJECT_0 + static_cast(m_waitHandles.size() - 1); +} + +WaitResultValue WaitHandleList::add(Win32Event &e) +{ + return add(e.handle()); +} + +DWORD WaitHandleList::count() const +{ + return static_cast(m_waitHandles.size()); +} + +void WaitHandleList::clear() +{ + m_waitHandles.clear(); +} + +WaitHandleList::operator const HANDLE*() const +{ + return m_waitHandles.data(); +} diff --git a/pglablib/WaitHandleList.h b/pglablib/WaitHandleList.h new file mode 100644 index 0000000..376e817 --- /dev/null +++ b/pglablib/WaitHandleList.h @@ -0,0 +1,26 @@ +#ifndef WAITHANDLELIST_H +#define WAITHANDLELIST_H + +#include +#include + +class Win32Event; + +using WaitResultValue = DWORD; + +class WaitHandleList { +public: + WaitHandleList(); + ~WaitHandleList(); + + WaitResultValue add(HANDLE h); + WaitResultValue add(Win32Event &e); + DWORD count() const; + void clear(); + operator const HANDLE*() const; + +private: + std::vector m_waitHandles; +}; + +#endif // WAITHANDLELIST_H diff --git a/pglablib/Win32Event.h b/pglablib/Win32Event.h new file mode 100644 index 0000000..684d13f --- /dev/null +++ b/pglablib/Win32Event.h @@ -0,0 +1,47 @@ +#ifndef WIN32EVENT_H +#define WIN32EVENT_H + +#include + +#include +/** Simpel wrapper around a Win32 Event object. + +Mostly to make cleanup automatic.*/ +class Win32Event { +public: + enum class Reset { Auto=0, Manual=1 }; + enum class Initial { Clear=0, Set=1 }; + + Win32Event(Reset r, Initial is) + : hEvent(CreateEvent( + nullptr, // _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, + BOOL(r), // _In_ BOOL bManualReset, + BOOL(is), // _In_ BOOL bInitialState, + nullptr //_In_opt_ LPCTSTR lpName + )) + {} + + Win32Event(Reset r, Initial is, int sock, long net_events) + : Win32Event(r, is) + { + WSAEventSelect(sock, hEvent, net_events); + } + + ~Win32Event() + { + CloseHandle(hEvent); + } + + Win32Event(const Win32Event &) = delete; + Win32Event &operator=(const Win32Event &) = delete; + + void set() { SetEvent(hEvent); } + + void reset() { ResetEvent(hEvent); } + + HANDLE handle() { return hEvent; } +private: + HANDLE hEvent; +}; + +#endif // WIN32EVENT_H diff --git a/pglablib/catalog/PgLanguage.cpp b/pglablib/catalog/PgLanguage.cpp index c224d23..cd9dd4f 100644 --- a/pglablib/catalog/PgLanguage.cpp +++ b/pglablib/catalog/PgLanguage.cpp @@ -1,15 +1,13 @@ #include "PgLanguage.h" -#include - QString PgLanguage::createSql() const { - throw std::logic_error("PgLanguage::createSql() not implemented"); + throw std::exception("PgLanguage::createSql() not implemented"); } QString PgLanguage::dropSql() const { - throw std::logic_error("PgLanguage::dropSql() not implemented"); + throw std::exception("PgLanguage::dropSql() not implemented"); } QString PgLanguage::typeName() const diff --git a/pglablib/catalog/PgProc.cpp b/pglablib/catalog/PgProc.cpp index 02cf6d0..83fe734 100644 --- a/pglablib/catalog/PgProc.cpp +++ b/pglablib/catalog/PgProc.cpp @@ -48,15 +48,15 @@ namespace { for(; index < len; index++) { QChar ch = str[index]; - if (!double_quote && ch == u'\'') + if (!double_quote && ch == L'\'') single_quote = !single_quote; - else if (!single_quote && ch == u'"') + else if (!single_quote && ch == L'"') double_quote = !double_quote; - else if (!double_quote && !single_quote && ch == u'(') + else if (!double_quote && !single_quote && ch == L'(') brackets++; - else if (!double_quote && !single_quote && ch == u')') + else if (!double_quote && !single_quote && ch == L')') brackets--; - else if (!double_quote && !single_quote && brackets == 0 && ch == u',') { + else if (!double_quote && !single_quote && brackets == 0 && ch == L',') { if (index != start_array) res.push_back(str.mid(start_array, index - 1).trimmed()); else diff --git a/pglablib/catalog/PgServerObject.cpp b/pglablib/catalog/PgServerObject.cpp index 1108917..f85bd1f 100644 --- a/pglablib/catalog/PgServerObject.cpp +++ b/pglablib/catalog/PgServerObject.cpp @@ -38,7 +38,7 @@ QString PgServerObject::alterOwnerSql(const QString& ident) const } -void PgServerObject::setAcls(std::optional acls) +void PgServerObject::setAcls(boost::optional acls) { m_acls = std::move(acls); } diff --git a/pglablib/catalog/PgServerObject.h b/pglablib/catalog/PgServerObject.h index b1520a1..5c08fd3 100644 --- a/pglablib/catalog/PgServerObject.h +++ b/pglablib/catalog/PgServerObject.h @@ -4,7 +4,7 @@ #include #include "PgObject.h" #include "PgAcl.h" -#include +#include class PgAuthId; @@ -26,7 +26,7 @@ public: * @brief setAcls * @param acls Important: pass empty optional when acl IS NULL, pass empty list for empty array */ - void setAcls(std::optional acls); + void setAcls(boost::optional acls); QString aclString() const; /** * @brief grantSql @@ -53,7 +53,7 @@ protected: private: Oid m_ownerOid = InvalidOid; const PgAuthId * m_owner = nullptr; - std::optional m_acls; + boost::optional m_acls; }; #endif // PGSERVEROBJECT_H diff --git a/pglablib/codebuilder/StringEscapeRule.h b/pglablib/codebuilder/StringEscapeRule.h index fb01dd8..a8c9822 100644 --- a/pglablib/codebuilder/StringEscapeRule.h +++ b/pglablib/codebuilder/StringEscapeRule.h @@ -2,6 +2,7 @@ #define STRINGESCAPERULE_H #include +#include enum class ConvertToNumericEscape { Utf8, ///< Generates upto four escapes for 4 utf8 chars diff --git a/pglablib/pglablib.pro b/pglablib/pglablib.pro new file mode 100644 index 0000000..c41f973 --- /dev/null +++ b/pglablib/pglablib.pro @@ -0,0 +1,222 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-12-13T17:36:43 +# +#------------------------------------------------- + +QT += widgets core + +TARGET = pglablib +TEMPLATE = lib +CONFIG += staticlib + +! include( ../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + Pglablib.cpp \ + ASyncDBConnection.cpp \ + ConnectionConfig.cpp \ + TestConnection.cpp \ + WaitHandleList.cpp \ + catalog/PgType.cpp \ + catalog/PgTypeContainer.cpp \ + catalog/PgNamespace.cpp \ + catalog/PgClass.cpp \ + catalog/PgDatabase.cpp \ + catalog/PgDatabaseContainer.cpp \ + catalog/PgAuthId.cpp \ + catalog/PgAuthIdContainer.cpp \ + catalog/PgClassContainer.cpp \ + catalog/PgDatabaseCatalog.cpp \ + catalog/PgNamespaceContainer.cpp \ + catalog/PgAttribute.cpp \ + catalog/PgContainer.cpp \ + catalog/PgAttributeContainer.cpp \ + catalog/PgIndex.cpp \ + catalog/PgIndexContainer.cpp \ + catalog/PgConstraint.cpp \ + catalog/PgConstraintContainer.cpp \ + ParamListJson.cpp \ + ParamListModel.cpp \ + sqlite/SQLiteConnection.cpp \ + sqlite/sqlite3.c \ + ui/catalog/tables/TableNode.cpp \ + ui/catalog/tables/TableSize.cpp \ + ui/catalog/tables/TableTreeBuilder.cpp \ + util.cpp \ + SqlFormattingUtils.cpp \ + catalog/PgKeywordList.cpp \ + QueryGenerator.cpp \ + catalog/PgObject.cpp \ + catalog/PgTablespace.cpp \ + catalog/PgTablespaceContainer.cpp \ + codebuilder/LanguageConfig.cpp \ + codebuilder/CodeBuilder.cpp \ + codebuilder/NameManglingRules.cpp \ + codebuilder/DefaultConfigs.cpp \ + codebuilder/TypeMappings.cpp \ + codebuilder/IndentationConfig.cpp \ + codebuilder/StructureTemplate.cpp \ + FormatToStream.cpp \ + codebuilder/StringLiteralRules.cpp \ + codebuilder/StringEscapeRule.cpp \ + catalog/PgTrigger.cpp \ + catalog/PgTriggerContainer.cpp \ + catalog/PgProc.cpp \ + catalog/PgProcContainer.cpp \ + catalog/PgDatabaseObject.cpp \ + catalog/PgServerObject.cpp \ + catalog/PgNamespaceObject.cpp \ + catalog/PgCollation.cpp \ + catalog/PgCollationContainer.cpp \ + catalog/PgInherits.cpp \ + catalog/PgInheritsContainer.cpp \ + SelectionEditorFactory.cpp \ + catalog/PgAm.cpp \ + model/TypeModelFactory.cpp \ + model/TypeSelectionItemModel.cpp \ + catalog/PgAmContainer.cpp \ + model/CollationModel.cpp \ + model/CollationModelFactory.cpp \ + catalog/PgLanguageContainer.cpp \ + catalog/PgLanguage.cpp \ + catalog/PgAcl.cpp \ + catalog/PgSequence.cpp \ + catalog/PgSequenceContainer.cpp \ + utils/HumanReadableBytes.cpp \ + utils/KeyStrengthener.cpp \ + utils/PasswordManager.cpp \ + utils/PostgresqlUrlParser.cpp + +HEADERS += \ + Pglablib.h \ + ASyncDBConnection.h \ + ConnectionConfig.h \ + TestConnection.h \ + WaitHandleList.h \ + Win32Event.h \ + catalog/PgType.h \ + catalog/PgTypeContainer.h \ + catalog/PgNamespace.h \ + catalog/PgClass.h \ + catalog/PgDatabase.h \ + catalog/PgDatabaseContainer.h \ + catalog/PgContainer.h \ + catalog/PgAuthId.h \ + catalog/PgAuthIdContainer.h \ + catalog/PgClassContainer.h \ + catalog/PgDatabaseCatalog.h \ + catalog/PgNamespaceContainer.h \ + catalog/PgAttribute.h \ + catalog/PgAttributeContainer.h \ + catalog/PgIndex.h \ + catalog/PgIndexContainer.h \ + catalog/PgConstraint.h \ + catalog/PgConstraintContainer.h \ + ParamListJson.h \ + ParamListModel.h \ + sqlite/SQLiteConnection.h \ + sqlite/sqlite3.h \ + sqlite/sqlite3ext.h \ + ui/catalog/tables/TableNode.h \ + ui/catalog/tables/TableSize.h \ + ui/catalog/tables/TableTreeBuilder.h \ + util.h \ + SqlFormattingUtils.h \ + catalog/PgCatalogTypes.h \ + catalog/PgKeywordList.h \ + QueryGenerator.h \ + catalog/PgObject.h \ + catalog/PgTablespace.h \ + catalog/PgTablespaceContainer.h \ + codebuilder/LanguageConfig.h \ + codebuilder/CodeBuilder.h \ + codebuilder/NameManglingRules.h \ + codebuilder/DefaultConfigs.h \ + codebuilder/TypeMappings.h \ + codebuilder/IndentationConfig.h \ + codebuilder/StructureTemplate.h \ + FormatToStream.h \ + codebuilder/ResultLoopTemplate.h \ + codebuilder/StringEscapeRule.h \ + codebuilder/StringLiteralRules.h \ + catalog/PgTrigger.h \ + catalog/PgTriggerContainer.h \ + catalog/PgProc.h \ + catalog/PgProcContainer.h \ + catalog/PgDatabaseObject.h \ + catalog/PgServerObject.h \ + catalog/PgNamespaceObject.h \ + catalog/PgCollation.h \ + catalog/PgCollationContainer.h \ + AbstractModelFactory.h \ + AbstractEditorFactory.h \ + catalog/PgInherits.h \ + catalog/PgInheritsContainer.h \ + SelectionEditorFactory.h \ + model/TypeSelectionItemModel.h \ + model/TypeModelFactory.h \ + catalog/PgAm.h \ + catalog/PgAmContainer.h \ + model/CollationModel.h \ + model/CollationModelFactory.h \ + catalog/PgLanguageContainer.h \ + catalog/PgLanguage.h \ + catalog/PgAcl.h \ + catalog/PgSequence.h \ + catalog/PgSequenceContainer.h \ + utils/HumanReadableBytes.h \ + utils/KeyStrengthener.h \ + utils/PasswordManager.h \ + utils/PostgresqlUrlParser.h + +unix { + target.path = /usr/lib + INSTALLS += target +} + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -lcore +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -lcore +else:unix:!macx: LIBS += -L$$OUT_PWD/../core/ -lcore + +INCLUDEPATH += $$PWD/../core +DEPENDPATH += $$PWD/../core + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../core/libcore.a + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../pgsql/release/ -lpgsql +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../pgsql/debug/ -lpgsql +else:unix:!macx: LIBS += -L$$OUT_PWD/../pgsql/ -lpgsql + +INCLUDEPATH += $$PWD/../pgsql +DEPENDPATH += $$PWD/../pgsql + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/libpgsql.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/libpgsql.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/pgsql.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/pgsql.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../pgsql/libpgsql.a + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -lcore +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -lcore +else:unix: LIBS += -L$$OUT_PWD/../core/ -lcore + +INCLUDEPATH += $$PWD/../core +DEPENDPATH += $$PWD/../core + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib +else:unix: PRE_TARGETDEPS += $$OUT_PWD/../core/libcore.a diff --git a/pglablib/utils/HumanReadableBytes.h b/pglablib/utils/HumanReadableBytes.h index b17ec0f..b76de05 100644 --- a/pglablib/utils/HumanReadableBytes.h +++ b/pglablib/utils/HumanReadableBytes.h @@ -1,6 +1,5 @@ #pragma once -#include #include std::string HumanReadableBytes(uint64_t bytes); diff --git a/pglablib/utils/PasswordManager.cpp b/pglablib/utils/PasswordManager.cpp index dfa0476..b0a71de 100644 --- a/pglablib/utils/PasswordManager.cpp +++ b/pglablib/utils/PasswordManager.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include using namespace Botan; @@ -33,7 +33,7 @@ public: * distinct key which is derived by hashing the wrapped key name with HMAC. */ const std::vector wrapped_name = - nist_key_wrap_padded(reinterpret_cast(name.data()), + nist_key_wrap_padded(cast_char_ptr_to_uint8(name.data()), name.size(), *m_cipher); @@ -47,7 +47,7 @@ public: secure_vector get(const std::string& name, const std::string_view &wrapped_key) const { const std::vector wrapped_name = - nist_key_wrap_padded(reinterpret_cast(name.data()), + nist_key_wrap_padded(cast_char_ptr_to_uint8(name.data()), name.size(), *m_cipher); diff --git a/pglablib/utils/PasswordManager.h b/pglablib/utils/PasswordManager.h index 8fb99d1..4bba574 100644 --- a/pglablib/utils/PasswordManager.h +++ b/pglablib/utils/PasswordManager.h @@ -19,11 +19,7 @@ namespace Botan { class PasswordManagerException: public std::exception { public: - PasswordManagerException() = default; - explicit PasswordManagerException(const char *message) : m_message(message) {} - const char *what() const noexcept override { return m_message.c_str(); } -private: - std::string m_message; + using std::exception::exception; //(char const* const _Message); }; class PasswordManagerLockedException: public PasswordManagerException { diff --git a/pgsql/ArrayParser.cpp b/pgsql/ArrayParser.cpp index cdb5999..1f29a61 100644 --- a/pgsql/ArrayParser.cpp +++ b/pgsql/ArrayParser.cpp @@ -1,5 +1,4 @@ #include "ArrayParser.h" -#include #include using namespace Pgsql; diff --git a/pgsql/CMakeLists.txt b/pgsql/CMakeLists.txt deleted file mode 100644 index f6b0f39..0000000 --- a/pgsql/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -find_package(PostgreSQL REQUIRED) - -add_library(pgsql STATIC - Pgsql_Connection.cpp - Pgsql_Params.cpp - Pgsql_PgException.cpp - Pgsql_Result.cpp - Pgsql_Row.cpp - Pgsql_Value.cpp - ArrayParser.cpp - Pgsql_oids.cpp - Pgsql_Transaction.cpp - Pgsql_ErrorDetails.cpp - Pgsql_Canceller.cpp - Pgsql_Connection.h - Pgsql_IResult.h - Pgsql_Params.h - Pgsql_PgException.h - Pgsql_Result.h - Pgsql_ResultConstIterator.h - Pgsql_Row.h - Pgsql_Value.h - Pgsql_declare.h - Pgsql_Col.h - ArrayParser.h - Pgsql_oids.h - SqlGenerator.h - Pgsql_Transaction.h - Pgsql_ErrorDetails.h - Pgsql_Canceller.h - ) - -target_link_libraries(pgsql PUBLIC - core - PostgreSQL::PostgreSQL - Qt6::Core - Qt6::Widgets - ) - -target_include_directories(pgsql PUBLIC - $ - ) - -set_target_properties(pgsql PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - POSITION_INDEPENDENT_CODE ON - ) diff --git a/pgsql/pgsql.pro b/pgsql/pgsql.pro new file mode 100644 index 0000000..02c21a5 --- /dev/null +++ b/pgsql/pgsql.pro @@ -0,0 +1,60 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-11-11T09:17:13 +# +#------------------------------------------------- + +CONFIG += staticlib +QT += core + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = pgsql +TEMPLATE = lib + +! include( ../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} + +LIBS += -lws2_32 -llibpq + +SOURCES += Pgsql_Connection.cpp \ + Pgsql_Params.cpp \ + Pgsql_PgException.cpp \ + Pgsql_Result.cpp \ + Pgsql_Row.cpp \ + Pgsql_Value.cpp \ + ArrayParser.cpp \ + Pgsql_oids.cpp \ + Pgsql_Transaction.cpp \ + Pgsql_ErrorDetails.cpp \ + Pgsql_Canceller.cpp + +HEADERS += Pgsql_Connection.h \ + Pgsql_IResult.h \ + Pgsql_Params.h \ + Pgsql_PgException.h \ + Pgsql_Result.h \ + Pgsql_ResultConstIterator.h \ + Pgsql_Row.h \ + Pgsql_Value.h \ + Pgsql_declare.h \ + Pgsql_Col.h \ + ArrayParser.h \ + Pgsql_oids.h \ + SqlGenerator.h \ + Pgsql_Transaction.h \ + Pgsql_ErrorDetails.h \ + Pgsql_Canceller.h + + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -lcore +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -lcore + +INCLUDEPATH += $$PWD/../core +DEPENDPATH += $$PWD/../core + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index a02ee3c..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -find_package(GTest CONFIG REQUIRED) - -add_subdirectory(mygtestutils) -add_subdirectory(PgsqlTests) -add_subdirectory(pglabtests) diff --git a/tests/PgsqlTests/CMakeLists.txt b/tests/PgsqlTests/CMakeLists.txt deleted file mode 100644 index 34071a1..0000000 --- a/tests/PgsqlTests/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_executable(PgsqlTests - main.cpp - tst_Value.cpp - tst_ArrayParser.cpp - tst_Pgsql_oids.cpp - ) - -target_link_libraries(PgsqlTests PRIVATE - pgsql - mygtestutils - GTest::gtest - Qt6::Core - ) - -target_include_directories(PgsqlTests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -set_target_properties(PgsqlTests PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - ) - -add_test(NAME PgsqlTests COMMAND PgsqlTests) diff --git a/tests/PgsqlTests/PgsqlTests.pro b/tests/PgsqlTests/PgsqlTests.pro new file mode 100644 index 0000000..cb1d574 --- /dev/null +++ b/tests/PgsqlTests/PgsqlTests.pro @@ -0,0 +1,46 @@ +! include( ../../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} +include(gtest_dependency.pri) + +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG += thread +CONFIG += qt + +QT += core + +HEADERS += + +SOURCES += main.cpp \ + tst_Value.cpp \ + tst_ArrayParser.cpp \ + tst_Pgsql_oids.cpp + + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../pgsql/release/ -lpgsql +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../pgsql/debug/ -lpgsql +else:unix: LIBS += -L$$OUT_PWD/../../pgsql/ -lpgsql + +INCLUDEPATH += $$PWD/../../pgsql +DEPENDPATH += $$PWD/../../pgsql + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/release/libpgsql.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/debug/libpgsql.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/release/pgsql.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/debug/pgsql.lib +else:unix: PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/libpgsql.a + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/release/ -lmygtestutils +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/debug/ -lmygtestutils +else:unix:!macx: LIBS += -L$$OUT_PWD/../mygtestutils/ -lmygtestutils + +INCLUDEPATH += $$PWD/../mygtestutils +DEPENDPATH += $$PWD/../mygtestutils + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/libmygtestutils.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/libmygtestutils.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/mygtestutils.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/mygtestutils.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/libmygtestutils.a diff --git a/tests/PgsqlTests/gtest_dependency.pri b/tests/PgsqlTests/gtest_dependency.pri new file mode 100644 index 0000000..d01d7f0 --- /dev/null +++ b/tests/PgsqlTests/gtest_dependency.pri @@ -0,0 +1,29 @@ +isEmpty(GOOGLETEST_DIR):GOOGLETEST_DIR=$$(GOOGLETEST_DIR) + +isEmpty(GOOGLETEST_DIR) { + warning("Using googletest src dir specified at Qt Creator wizard") + message("set GOOGLETEST_DIR as environment variable or qmake variable to get rid of this message") + GOOGLETEST_DIR = C:/Prog/googletest +} + +!isEmpty(GOOGLETEST_DIR): { + GTEST_SRCDIR = $$GOOGLETEST_DIR/googletest + GMOCK_SRCDIR = $$GOOGLETEST_DIR/googlemock +} + +requires(exists($$GTEST_SRCDIR):exists($$GMOCK_SRCDIR)) + +!exists($$GOOGLETEST_DIR):message("No googletest src dir found - set GOOGLETEST_DIR to enable.") + +DEFINES += \ + GTEST_LANG_CXX11 + +INCLUDEPATH *= \ + $$GTEST_SRCDIR \ + $$GTEST_SRCDIR/include \ + $$GMOCK_SRCDIR \ + $$GMOCK_SRCDIR/include + +SOURCES += \ + $$GTEST_SRCDIR/src/gtest-all.cc \ + $$GMOCK_SRCDIR/src/gmock-all.cc diff --git a/tests/mygtestutils/CMakeLists.txt b/tests/mygtestutils/CMakeLists.txt deleted file mode 100644 index 930a0ad..0000000 --- a/tests/mygtestutils/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_library(mygtestutils STATIC - PrintTo_Qt.cpp - PrintTo_Qt.h - ) - -target_link_libraries(mygtestutils PUBLIC - GTest::gtest - Qt6::Core - ) - -target_include_directories(mygtestutils PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -set_target_properties(mygtestutils PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - POSITION_INDEPENDENT_CODE ON - ) diff --git a/tests/mygtestutils/mygtestutils.pro b/tests/mygtestutils/mygtestutils.pro new file mode 100644 index 0000000..a56a359 --- /dev/null +++ b/tests/mygtestutils/mygtestutils.pro @@ -0,0 +1,32 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-12-01T10:07:31 +# +#------------------------------------------------- + +QT -= gui + +TARGET = mygtestutils +TEMPLATE = lib +CONFIG += staticlib + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + PrintTo_Qt.cpp + +HEADERS += \ + PrintTo_Qt.h +unix { + target.path = /usr/lib + INSTALLS += target +} diff --git a/tests/pglabtests/CMakeLists.txt b/tests/pglabtests/CMakeLists.txt deleted file mode 100644 index f13dc29..0000000 --- a/tests/pglabtests/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -add_executable(pglabtests - main.cpp - TableTreeBuilderTests.cpp - tst_ConvertLangToSqlString.cpp - tst_ConvertToMultiLineCString.cpp - tst_ExplainJsonParser.cpp - tst_HumanReadableBytes.cpp - tst_TryParsePostgresqlUrl.cpp - tst_escapeConnectionStringValue.cpp - tst_expected.cpp - tst_SqlLexer.cpp - tst_scopeguard.cpp - tst_CsvWriter.cpp - tst_PasswordManager.cpp - tst_ParamJson.cpp - tst_CodeBuilder.cpp - tst_NameManglingRules.cpp - tst_TypeMappings.cpp - tst_Range.cpp - ) - -target_link_libraries(pglabtests PRIVATE - pglablib - pgsql - core - mygtestutils - GTest::gtest - Qt6::Core - Qt6::Widgets - ) - -target_include_directories(pglabtests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -set_target_properties(pglabtests PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - ) - -add_test(NAME pglabtests COMMAND pglabtests) diff --git a/tests/pglabtests/pglabtests.pro b/tests/pglabtests/pglabtests.pro new file mode 100644 index 0000000..a666430 --- /dev/null +++ b/tests/pglabtests/pglabtests.pro @@ -0,0 +1,86 @@ +! include( ../../common.pri ) { +error( "Couldn't find the common.pri file!" ) +} +include(gtest_dependency.pri) + +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG += thread +CONFIG += qt + +QT += core widgets + +HEADERS += + +SOURCES += main.cpp \ + TableTreeBuilderTests.cpp \ + tst_ConvertLangToSqlString.cpp \ + tst_ConvertToMultiLineCString.cpp \ + tst_ExplainJsonParser.cpp \ + tst_HumanReadableBytes.cpp \ + tst_TryParsePostgresqlUrl.cpp \ + tst_escapeConnectionStringValue.cpp \ + tst_expected.cpp \ + tst_SqlLexer.cpp \ + tst_scopeguard.cpp \ + tst_CsvWriter.cpp \ + tst_PasswordManager.cpp \ + tst_ParamJson.cpp \ + tst_CodeBuilder.cpp \ + tst_NameManglingRules.cpp \ + tst_TypeMappings.cpp \ + tst_Range.cpp + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore + +INCLUDEPATH += $$PWD/../../core +DEPENDPATH += $$PWD/../../core + +win32:CONFIG(debug, debug|release): LIBS += -lbotand +else:win32:CONFIG(release, debug|release): LIBS += -lbotan + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/libcore.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/debug/libcore.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/core.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/debug/core.lib + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../pgsql/release/ -lpgsql +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../pgsql/debug/ -lpgsql +else:unix:!macx: LIBS += -L$$OUT_PWD/../../pgsql/ -lpgsql + +INCLUDEPATH += $$PWD/../../pgsql +DEPENDPATH += $$PWD/../../pgsql + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/release/libpgsql.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/debug/libpgsql.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/release/pgsql.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/debug/pgsql.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../../pgsql/libpgsql.a + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../pglablib/release/ -lpglablib +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../pglablib/debug/ -lpglablib +else:unix:!macx: LIBS += -L$$OUT_PWD/../../pglablib/ -lpglablib + +INCLUDEPATH += $$PWD/../../pglablib +DEPENDPATH += $$PWD/../../pglablib + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/release/libpglablib.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/debug/libpglablib.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/release/pglablib.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/debug/pglablib.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/libpglablib.a + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/release/ -lmygtestutils +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/debug/ -lmygtestutils +else:unix:!macx: LIBS += -L$$OUT_PWD/../mygtestutils/ -lmygtestutils + +INCLUDEPATH += $$PWD/../mygtestutils +DEPENDPATH += $$PWD/../mygtestutils + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/libmygtestutils.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/libmygtestutils.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/mygtestutils.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/mygtestutils.lib +else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/libmygtestutils.a diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..ee23c08 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += PgsqlTests \ + pglabtests \ + mygtestutils diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index 4283df6..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "pglab", - "version-string": "0.1.0", - "dependencies": [ - "boost-container", - "boost-timer", - "boost-chrono", - "boost-assert", - "botan", - "libpq", - "gtest" - ] -}