Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ examples/fivewin/err.txt
.DS_Store
Thumbs.db

# Rust (openmonitor)
tools/openmonitor/target/

# Compiler / linker artefacts
*.obj
*.o
Expand Down
64 changes: 64 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ option(OPENADS_WITH_TLS "Enable TLS transport (vendors mbedtls 3.6 LTS via Fetch
# and nlohmann/json (MIT) at configure time via FetchContent.
option(OPENADS_WITH_HTTP "Enable embedded HTTP web console (Studio) in openads_serverd / ace64.dll" ON)

# Optional PostgreSQL table driver (libpq). OFF by default.
option(OPENADS_WITH_POSTGRESQL "Enable PostgreSQL-backed table driver (libpq)" OFF)

# Pull in mbedtls FIRST so our strict /WX -Werror flags don't bleed
# into the upstream sources (C4200 zero-sized arrays etc). Each
# OpenADS target adds the strict flags target-locally below via
Expand Down Expand Up @@ -126,12 +129,73 @@ if(OPENADS_WITH_HTTP)
message(STATUS "OpenADS: HTTP web console enabled (cpp-httplib + nlohmann/json)")
endif()

if(OPENADS_WITH_POSTGRESQL)
set(_openads_pg_linked FALSE)
set(OPENADS_LIBPQ_INCLUDE "" CACHE PATH "Directory containing libpq-fe.h")
set(OPENADS_LIBPQ_LIBRARY "" CACHE FILEPATH "libpq import library (.lib/.a)")
if(OPENADS_LIBPQ_INCLUDE AND OPENADS_LIBPQ_LIBRARY)
set(_openads_pg_inc "${OPENADS_LIBPQ_INCLUDE}")
set(_openads_pg_lib "${OPENADS_LIBPQ_LIBRARY}")
endif()
if(NOT _openads_pg_lib)
if(DEFINED ENV{OPENADS_LIBPQ_LIBRARY})
set(_openads_pg_lib "$ENV{OPENADS_LIBPQ_LIBRARY}")
endif()
if(DEFINED ENV{OPENADS_LIBPQ_INCLUDE})
set(_openads_pg_inc "$ENV{OPENADS_LIBPQ_INCLUDE}")
endif()
endif()
if(NOT _openads_pg_lib OR NOT _openads_pg_inc)
if(DEFINED ENV{OPENADS_TOOLCHAIN_ROOT})
set(_openads_toolchain_root "$ENV{OPENADS_TOOLCHAIN_ROOT}")
elseif(DEFINED OPENADS_TOOLCHAIN_ROOT)
set(_openads_toolchain_root "${OPENADS_TOOLCHAIN_ROOT}")
endif()
if(_openads_toolchain_root)
if(NOT _openads_pg_inc)
find_path(_openads_pg_inc libpq-fe.h
PATHS "${_openads_toolchain_root}/pgsql/include"
NO_DEFAULT_PATH)
endif()
if(NOT _openads_pg_lib)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
find_library(_openads_pg_lib NAMES libpq pq
PATHS "${_openads_toolchain_root}/libpq/x86"
"${_openads_toolchain_root}/libpq/x86/lib"
NO_DEFAULT_PATH)
else()
find_library(_openads_pg_lib NAMES pq libpq
PATHS "${_openads_toolchain_root}/pgsql/lib"
NO_DEFAULT_PATH)
endif()
endif()
endif()
endif()
if(_openads_pg_inc AND _openads_pg_lib)
add_library(openads_libpq INTERFACE)
target_include_directories(openads_libpq INTERFACE "${_openads_pg_inc}")
target_link_libraries(openads_libpq INTERFACE "${_openads_pg_lib}")
set(_openads_pg_linked TRUE)
message(STATUS "OpenADS: PostgreSQL backend (libpq: ${_openads_pg_lib})")
endif()
if(NOT _openads_pg_linked)
find_package(PostgreSQL REQUIRED)
add_library(openads_libpq INTERFACE)
target_include_directories(openads_libpq INTERFACE PostgreSQL_INCLUDE_DIRS)
target_link_libraries(openads_libpq INTERFACE PostgreSQL::PostgreSQL)
message(STATUS "OpenADS: PostgreSQL backend (libpq via find_package)")
endif()
endif()

if(MSVC)
add_compile_options(/W4 /permissive-)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
if(OPENADS_WARNINGS_AS_ERRORS)
add_compile_options(/WX)
endif()
elseif(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# MinGW/winlibs: static link toolchain runtime; libpq.dll still loads at runtime.
add_link_options(-static)
else()
add_compile_options(-Wall -Wextra -Wpedantic -Wshadow -Wconversion)
# _CRT_SECURE_NO_WARNINGS: needed when clang-cl targets MSVC CRT on Windows;
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,7 @@ OpenADS/
│ ├── import_dd/ # openads_import_dd — SAP .add → OpenADS import
│ │ └── main.cpp
│ ├── bench/ # openads_bench — synthetic SQL benchmark
│ ├── openmonitor/ # openmonitor — TUI + web dashboard for openads_serverd
│ ├── harbour_patch/ # rddads compatibility patches + ADS baseline fixture
│ ├── scripts/
│ │ ├── systemd/ # openads-serverd.service (Linux)
Expand Down
39 changes: 39 additions & 0 deletions docs/OPENADS_PLUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# OpenADS Plus — PostgreSQL

Extensão aditiva do [OpenADS](https://github.com/FiveTechSoft/OpenADS): tabelas PostgreSQL atrás da ABI ACE. DBF e wire inalterados.

## Deploy rápido

```bat
set OPENADS_TOOLCHAIN_ROOT=<dir com MSVC e pgsql\include/lib>
tools\scripts\build_nmake_postgres.bat
```

Saída: `build\pg\src\openace32.dll` — copiar para a pasta do `.exe` Harbour antes de outra `ace*.dll`.

## Conexão

`AdsConnect60("postgresql://user:pass@host:5432/dbname")`

## Teste ponta a ponta

```bat
set OPENADS_TEST_PG_URI=postgresql://user:pass@127.0.0.1:5432/testdb
build\pg\tests\openads_unit_tests.exe --test-case="*postgresql*"
```

O teste cria/derruba a tabela `clientes`, insere 3 linhas e valida navegação + SEEK pela ABI. Sem URI definida, os casos E2E fazem SKIP (CI não quebra).

## Segurança

- Nomes de tabela/coluna: só identificadores ASCII seguros (`[A-Za-z0-9_]`).
- Valores de SEEK e chaves: parâmetros preparados (`$1`), nunca concatenados.
- URI montada em runtime no app — sem paths hardcoded no código.

## Capacidades

| Recurso | Status |
|---------|--------|
| Read + navegação | Sim |
| SEEK por coluna | Sim |
| Write | Planejado |
14 changes: 14 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ add_library(openads_core STATIC
network/mg_wire.cpp
)

if(OPENADS_WITH_POSTGRESQL)
target_sources(openads_core PRIVATE
sql_backend/sql_common.cpp
sql_backend/postgres_uri.cpp
sql_backend/postgres_backend.cpp
sql_backend/postgres_connection.cpp
)
endif()

if(WIN32)
target_sources(openads_core PRIVATE
platform/file_win32.cpp
Expand Down Expand Up @@ -98,6 +107,11 @@ if(OPENADS_WITH_TLS)
MbedTLS::mbedtls MbedTLS::mbedx509 MbedTLS::mbedcrypto)
endif()

if(OPENADS_WITH_POSTGRESQL)
target_compile_definitions(openads_core PUBLIC OPENADS_WITH_POSTGRESQL=1)
target_link_libraries(openads_core PUBLIC openads_libpq)
endif()

# ----------------------------------------------------------------------
# Drop-in replacement DLL: ace32.dll (x86) / ace64.dll (x64).
# Harbour's contrib/rddads links against ace32.lib / ace64.lib import
Expand Down
Loading