diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..30cf57e
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# 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
new file mode 100644
index 0000000..a3aeb4c
--- /dev/null
+++ b/.idea/editor.xml
@@ -0,0 +1,367 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..498ae80
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/pgLab.iml b/.idea/pgLab.iml
new file mode 100644
index 0000000..6102194
--- /dev/null
+++ b/.idea/pgLab.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.junie/skills/reno-release-notes/SKILL.md b/.junie/skills/reno-release-notes/SKILL.md
new file mode 100644
index 0000000..2a1779f
--- /dev/null
+++ b/.junie/skills/reno-release-notes/SKILL.md
@@ -0,0 +1,110 @@
+---
+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
new file mode 100644
index 0000000..b9c08b0
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,32 @@
+# 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
new file mode 100644
index 0000000..a172074
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,30 @@
+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 bdf5ea0..7c2eb7e 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,41 @@ 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
deleted file mode 100644
index dcff145..0000000
--- a/common.pri
+++ /dev/null
@@ -1,15 +0,0 @@
-! 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 95b09fc..ec63cf3 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -1,41 +1,31 @@
-set(CMAKE_AUTOMOC ON)
-
add_library(core STATIC
- BackupFormatModel.cpp
- CsvWriter.cpp
my_boost_assert_handler.cpp
- PasswordManager.cpp
- SqlLexer.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
+ )
+
target_link_libraries(core PUBLIC
- boost
- botan
- Qt5::Core
+ Qt6::Core
)
-
-target_include_directories(core INTERFACE
+
+target_include_directories(core PUBLIC
$
-)
+ )
-set_target_properties(core PROPERTIES
- CXX_STANDARD 14
+set_target_properties(core PROPERTIES
+ CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
- POSITION_INDEPENDENT_CODE True
+ 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
deleted file mode 100644
index 0b424f6..0000000
--- a/core/core.pro
+++ /dev/null
@@ -1,43 +0,0 @@
-#-------------------------------------------------
-#
-# 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
deleted file mode 100644
index 44b8f1e..0000000
--- a/local.pri.sample
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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 d6a1072..ab4dda5 100644
--- a/pglab/CMakeLists.txt
+++ b/pglab/CMakeLists.txt
@@ -1,69 +1,115 @@
-cmake_minimum_required(VERSION 3.2)
-project(pglab)
+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
+ )
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTOUIC ON)
-set(CMAKE_AUTORCC ON)
+set(PGLAB_FORMS
+ ConnectionManagerWindow.ui
+ CreateDatabaseDialog.ui
+ DatabaseWindow.ui
+ tuplesresultwidget.ui
+ querytool/QueryTab.ui
+ ProcessStdioWidget.ui
+ crud/CrudTab.ui
+ CodeGenerator.ui
+ widgets/SingleRecordWidget.ui
+ )
add_executable(pglab
- 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
+ ${PGLAB_SOURCES}
+ ${PGLAB_FORMS}
resources.qrc
)
-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")
+if(WIN32)
+ set_target_properties(pglab PROPERTIES WIN32_EXECUTABLE ON)
endif()
-target_link_libraries( pglab
- core
+target_link_libraries(pglab PRIVATE
+ pglablib
pgsql
- boost-system
- Qt5::Widgets
- pthread
+ 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
)
diff --git a/pglab/CreateDatabaseDialog.h b/pglab/CreateDatabaseDialog.h
index bcc00af..74cb209 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 f17dbac..a16e077 100644
--- a/pglab/CreateDatabaseDialog.ui
+++ b/pglab/CreateDatabaseDialog.ui
@@ -148,7 +148,7 @@
CodeEditor
QPlainTextEdit
-
+
diff --git a/pglab/catalog/models/DatabasesTableModel.cpp b/pglab/catalog/models/DatabasesTableModel.cpp
index ac10ec5..289eea2 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 = d.size.totalBytes;
+ v = QVariant::fromValue(d.size.totalBytes);
break;
case AclCol:
v = db.aclString();
diff --git a/pglab/catalog/models/IndexModel.cpp b/pglab/catalog/models/IndexModel.cpp
index 7cee4e4..e04f715 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 = dat.sizeBytes;
+ v = QVariant::fromValue(dat.sizeBytes);
break;
case ExplicitIndexCol:
v = !dat.isSupportingIndex();
diff --git a/pglab/catalog/models/SequenceModel.cpp b/pglab/catalog/models/SequenceModel.cpp
index 659348f..640b50c 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 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 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 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 0df8ff2..d6a4e8b 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() : 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;
+ 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);
}
return QVariant();
diff --git a/pglab/crud/CrudModel.cpp b/pglab/crud/CrudModel.cpp
index d688bd6..8367f32 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 v.operator int64_t();
+ return QVariant::fromValue(static_cast(v));
case Pgsql::bool_oid:
return v.operator bool();
diff --git a/pglab/pglab.pro b/pglab/pglab.pro
deleted file mode 100644
index 93a9186..0000000
--- a/pglab/pglab.pro
+++ /dev/null
@@ -1,229 +0,0 @@
-#-------------------------------------------------
-#
-# 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 51381ec..bcce73b 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 = item->actualRows;
+ result = QVariant::fromValue(item->actualRows);
break;
case c_ColumnLoops:
result = item->actualLoops;
diff --git a/pglabAll.pro b/pglabAll.pro
deleted file mode 100644
index 8631a5e..0000000
--- a/pglabAll.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-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 1c27fb9..2b5c2fb 100644
--- a/pglablib/ASyncDBConnection.cpp
+++ b/pglablib/ASyncDBConnection.cpp
@@ -1,13 +1,14 @@
-#include "ASyncDBConnection.h"
+#include "ASyncDBConnection.h"
#include "ScopeGuard.h"
#include "util.h"
#include "Pgsql_PgException.h"
-#include "Win32Event.h"
-#include "WaitHandleList.h"
+#include
#include
#include
-#include
#include
+#include
+#include
+#include
namespace {
@@ -45,10 +46,6 @@ 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;
@@ -64,18 +61,29 @@ 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;
- /// \todo Implement new method to stop the thread
- Win32Event m_stopEvent;
+ 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
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();
@@ -97,7 +105,6 @@ private:
ASyncDBConnectionThread::ASyncDBConnectionThread(ASyncDBConnection *asco)
: asyncConnObject(asco)
- , m_stopEvent(Win32Event::Reset::Manual, Win32Event::Initial::Clear)
{}
void ASyncDBConnectionThread::run()
@@ -154,6 +161,59 @@ 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;
@@ -165,30 +225,14 @@ 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) {
- Win32Event socket_event(Win32Event::Reset::Auto, Win32Event::Initial::Clear);
-
- long fd = FD_WRITE;
+ QSocketNotifier::Type type = QSocketNotifier::Write;
while (true) {
// poll till complete or failed (we can get an abort command)
- 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);
+ 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);
- 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) {
+ if (res == WaitResult::Socket) {
auto poll_state = m_connection.connectPoll();
if (poll_state == PGRES_POLLING_OK) {
qDebug() << "ASyncDBConnection Connected";
@@ -202,17 +246,21 @@ bool ASyncDBConnectionThread::makeConnection()
}
else if (poll_state == PGRES_POLLING_READING) {
doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" });
- fd = FD_READ;
+ type = QSocketNotifier::Read;
}
else if (poll_state == PGRES_POLLING_WRITING) {
doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" });
- fd = FD_WRITE;
+ type = QSocketNotifier::Write;
}
}
- else if (res == wait_result_stop) {
+ else if (terminateRequested) {
+ m_connection.close();
+ return false;
+ }
+ else if (res == WaitResult::Timeout) {
+ doStateCallback({ ASyncDBConnection::State::NotConnected, "Connection timed out" });
m_connection.close();
return false;
-
}
} // end while (true)
}
@@ -252,7 +300,7 @@ void ASyncDBConnectionThread::communicate()
void ASyncDBConnectionThread::stop()
{
terminateRequested = true;
- m_stopEvent.set();
+ wake();
}
void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state)
@@ -264,34 +312,18 @@ void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state
bool ASyncDBConnectionThread::waitForAndSendCommand()
{
- 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);
-
- 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) {
+ if (hasQueuedCommand()) {
doNewCommand();
+ return true;
+ }
+
+ // 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;
+ }
}
- 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;
@@ -347,42 +379,16 @@ 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) {
- WSAEventSelect(sock, socket_event.handle(), fd);
+ WaitResult res = waitForSocket(QSocketNotifier::Read, -1, false);
- 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;
- }
+ if (res == WaitResult::Socket) {
+ if (consumeResultInput()) {
+ finished = true;
}
- else if (net_events.lNetworkEvents & FD_CLOSE) {
- doStateCallback({ ASyncDBConnection::State::NotConnected, "Close while waiting for result" });
- finished = true;
- stop();
- }
}
- if (res == wait_result_stop) {
+ else if (terminateRequested) {
// Send cancel, close connection and terminate thread
cancel();
doStateCallback(ASyncDBConnection::State::Terminating);
@@ -455,8 +461,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;
}
@@ -468,8 +474,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 02f5310..0479f5f 100644
--- a/pglablib/ASyncDBConnection.h
+++ b/pglablib/ASyncDBConnection.h
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
class ASyncDBConnectionThread;
/** \brief Class that handles asynchronous execution of queries.
@@ -33,7 +34,7 @@ public:
class StateData {
public:
- State State;
+ enum State State;
QString Message;
StateData(enum State state, QString message = QString())
diff --git a/pglablib/CMakeLists.txt b/pglablib/CMakeLists.txt
new file mode 100644
index 0000000..a3c759d
--- /dev/null
+++ b/pglablib/CMakeLists.txt
@@ -0,0 +1,187 @@
+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 a75620e..ff7f1d3 100644
--- a/pglablib/SqlFormattingUtils.cpp
+++ b/pglablib/SqlFormattingUtils.cpp
@@ -200,7 +200,7 @@ QString quoteIdent(QString ident)
{
assert(ident.length() > 0);
- static const wchar_t dquote = L'"';
+ static const QChar dquote = u'"';
if (identNeedsQuotes(ident)) {
QString out;
diff --git a/pglablib/WaitHandleList.cpp b/pglablib/WaitHandleList.cpp
deleted file mode 100644
index d219610..0000000
--- a/pglablib/WaitHandleList.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#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
deleted file mode 100644
index 376e817..0000000
--- a/pglablib/WaitHandleList.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#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
deleted file mode 100644
index 684d13f..0000000
--- a/pglablib/Win32Event.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#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 cd9dd4f..c224d23 100644
--- a/pglablib/catalog/PgLanguage.cpp
+++ b/pglablib/catalog/PgLanguage.cpp
@@ -1,13 +1,15 @@
#include "PgLanguage.h"
+#include
+
QString PgLanguage::createSql() const
{
- throw std::exception("PgLanguage::createSql() not implemented");
+ throw std::logic_error("PgLanguage::createSql() not implemented");
}
QString PgLanguage::dropSql() const
{
- throw std::exception("PgLanguage::dropSql() not implemented");
+ throw std::logic_error("PgLanguage::dropSql() not implemented");
}
QString PgLanguage::typeName() const
diff --git a/pglablib/catalog/PgProc.cpp b/pglablib/catalog/PgProc.cpp
index 83fe734..02cf6d0 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 == L'\'')
+ if (!double_quote && ch == u'\'')
single_quote = !single_quote;
- else if (!single_quote && ch == L'"')
+ else if (!single_quote && ch == u'"')
double_quote = !double_quote;
- else if (!double_quote && !single_quote && ch == L'(')
+ else if (!double_quote && !single_quote && ch == u'(')
brackets++;
- else if (!double_quote && !single_quote && ch == L')')
+ else if (!double_quote && !single_quote && ch == u')')
brackets--;
- else if (!double_quote && !single_quote && brackets == 0 && ch == L',') {
+ else if (!double_quote && !single_quote && brackets == 0 && ch == u',') {
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 f85bd1f..1108917 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(boost::optional acls)
+void PgServerObject::setAcls(std::optional acls)
{
m_acls = std::move(acls);
}
diff --git a/pglablib/catalog/PgServerObject.h b/pglablib/catalog/PgServerObject.h
index 5c08fd3..b1520a1 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(boost::optional acls);
+ void setAcls(std::optional acls);
QString aclString() const;
/**
* @brief grantSql
@@ -53,7 +53,7 @@ protected:
private:
Oid m_ownerOid = InvalidOid;
const PgAuthId * m_owner = nullptr;
- boost::optional m_acls;
+ std::optional m_acls;
};
#endif // PGSERVEROBJECT_H
diff --git a/pglablib/codebuilder/StringEscapeRule.h b/pglablib/codebuilder/StringEscapeRule.h
index a8c9822..fb01dd8 100644
--- a/pglablib/codebuilder/StringEscapeRule.h
+++ b/pglablib/codebuilder/StringEscapeRule.h
@@ -2,7 +2,6 @@
#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
deleted file mode 100644
index c41f973..0000000
--- a/pglablib/pglablib.pro
+++ /dev/null
@@ -1,222 +0,0 @@
-#-------------------------------------------------
-#
-# 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 b76de05..b17ec0f 100644
--- a/pglablib/utils/HumanReadableBytes.h
+++ b/pglablib/utils/HumanReadableBytes.h
@@ -1,5 +1,6 @@
#pragma once
+#include
#include
std::string HumanReadableBytes(uint64_t bytes);
diff --git a/pglablib/utils/PasswordManager.cpp b/pglablib/utils/PasswordManager.cpp
index b0a71de..dfa0476 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(cast_char_ptr_to_uint8(name.data()),
+ nist_key_wrap_padded(reinterpret_cast(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(cast_char_ptr_to_uint8(name.data()),
+ nist_key_wrap_padded(reinterpret_cast(name.data()),
name.size(),
*m_cipher);
diff --git a/pglablib/utils/PasswordManager.h b/pglablib/utils/PasswordManager.h
index 4bba574..8fb99d1 100644
--- a/pglablib/utils/PasswordManager.h
+++ b/pglablib/utils/PasswordManager.h
@@ -19,7 +19,11 @@ namespace Botan {
class PasswordManagerException: public std::exception {
public:
- using std::exception::exception; //(char const* const _Message);
+ 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;
};
class PasswordManagerLockedException: public PasswordManagerException {
diff --git a/pgsql/ArrayParser.cpp b/pgsql/ArrayParser.cpp
index 1f29a61..cdb5999 100644
--- a/pgsql/ArrayParser.cpp
+++ b/pgsql/ArrayParser.cpp
@@ -1,4 +1,5 @@
#include "ArrayParser.h"
+#include
#include
using namespace Pgsql;
diff --git a/pgsql/CMakeLists.txt b/pgsql/CMakeLists.txt
new file mode 100644
index 0000000..f6b0f39
--- /dev/null
+++ b/pgsql/CMakeLists.txt
@@ -0,0 +1,48 @@
+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
deleted file mode 100644
index 02c21a5..0000000
--- a/pgsql/pgsql.pro
+++ /dev/null
@@ -1,60 +0,0 @@
-#-------------------------------------------------
-#
-# 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
new file mode 100644
index 0000000..a02ee3c
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..34071a1
--- /dev/null
+++ b/tests/PgsqlTests/CMakeLists.txt
@@ -0,0 +1,24 @@
+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
deleted file mode 100644
index cb1d574..0000000
--- a/tests/PgsqlTests/PgsqlTests.pro
+++ /dev/null
@@ -1,46 +0,0 @@
-! 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
deleted file mode 100644
index d01d7f0..0000000
--- a/tests/PgsqlTests/gtest_dependency.pri
+++ /dev/null
@@ -1,29 +0,0 @@
-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
new file mode 100644
index 0000000..930a0ad
--- /dev/null
+++ b/tests/mygtestutils/CMakeLists.txt
@@ -0,0 +1,19 @@
+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
deleted file mode 100644
index a56a359..0000000
--- a/tests/mygtestutils/mygtestutils.pro
+++ /dev/null
@@ -1,32 +0,0 @@
-#-------------------------------------------------
-#
-# 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
new file mode 100644
index 0000000..f13dc29
--- /dev/null
+++ b/tests/pglabtests/CMakeLists.txt
@@ -0,0 +1,41 @@
+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
deleted file mode 100644
index a666430..0000000
--- a/tests/pglabtests/pglabtests.pro
+++ /dev/null
@@ -1,86 +0,0 @@
-! 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
deleted file mode 100644
index ee23c08..0000000
--- a/tests/tests.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS += PgsqlTests \
- pglabtests \
- mygtestutils
diff --git a/vcpkg.json b/vcpkg.json
new file mode 100644
index 0000000..4283df6
--- /dev/null
+++ b/vcpkg.json
@@ -0,0 +1,13 @@
+{
+ "name": "pglab",
+ "version-string": "0.1.0",
+ "dependencies": [
+ "boost-container",
+ "boost-timer",
+ "boost-chrono",
+ "boost-assert",
+ "botan",
+ "libpq",
+ "gtest"
+ ]
+}