| title | Known issues |
|---|---|
| layout | default |
| nav_order | 9 |
Status as of v1.8.8 (2026-07-10).
OpenADS speaks its own documented wire protocol on tcp:// / tls://.
It is not byte-compatible with the proprietary SAP Advantage 11.x/12.x
TCP protocol. Talking to a legacy ADS server as a drop-in client requires
a future SapWireTransport layer (ads:// / sap:// URIs).
OpenADS reads SAP-built CDX files without modification. Once OpenADS
writes a CDX (append, reindex, INDEX ON, etc.), the file uses
Harbour's DBFCDX layout (magic RCHB at offset 0x14). SAP ACE does not
recognize that header and returns error 7017 (Corrupt .ADI, .CDX, or
.IDX index). Rollback is not automatic — back up original .cdx files
before migration, or delete and rebuild all tags under SAP after reverting.
See Migrating from ADS for the full checklist.
Only the Polish CP-852 table (NTXPL852 / PL852) is implemented.
Other OEM_CHAR_SET values SAP supports in adslocal.cfg (MAZOVIA,
additional NTX* variants, GREEK437, RUSSIAN, …) are recognised but
leave the default at raw byte order. Tracked as
issue #127.
Activation for OEM apps is zero-config since v1.8.9-dev: a table
opened with usCharType = ADS_OEM (rddads AdsSetCharType(ADS_OEM))
picks up the default OEM collation from adslocal.cfg
(OEM_CHAR_SET=NTXPL852, file next to openace64.dll or in the
current directory) or from the OPENADS_OEM_COLLATION environment
variable (which wins when both are set).
AdsSetCollation(hConn, ...) stays available as a per-connection
override. If OEM data was indexed on v1.8.6/v1.8.7 (which built
UPPER() keys without CP-852 casing), run REINDEX once after
configuring the collation.
The default OEM collation is applied by the in-process engine
(LocalServer). openads_serverd remote connections do not yet
propagate the client's char type to the server.
CDX REINDEX and AdsCreateIndex* now use the bulk bottom-up B+tree
build (v1.8.0) and, for the key-collection phase, direct driver reads
that preserve the read-ahead cache instead of per-record goto_record
(which invalidated the cache on every step). This targets the ~11×
gap reported for local rddads INDEX ON vs. SAP ACE on real DBFCDX
workloads (issue #128). Further parity work may be needed for
expression evaluation (e.g. UPPER/VAL on OEM data) and multi-tag
resync overheads. Tracked as issue #128.
For .add files created by SAP Data Architect, per-table group
permission levels are encoded in encrypted 8-byte blobs that OpenADS
cannot decode yet. Imported DDs may show full DML for every group
where SAP shows read-only access. Use pmsys_imported.add (via
tools/import_dd) or grant permissions from OpenADS-native tooling.
tls:// verifies peer certificates by default. Self-signed or
private-CA endpoints require either a CA bundle (future
AdsSetTlsCa entry point) or the dev-only environment variable
OPENADS_TLS_INSECURE=1.
Client-side TLS (tls:// in ace64.dll) is implemented via mbedtls.
openads_serverd does not terminate TLS natively — front it with
nginx, Caddy, or stunnel. See TLS deployment.
LocalServer mode (Studio embedded in ace64.dll / ace32.dll) has no
HTTP Basic auth. The default bind is 127.0.0.1; if you set
OPENADS_STUDIO_HOST=0.0.0.0, put the console behind a reverse proxy
that handles authentication. Remote Server mode (openads_serverd)
supports --http-user user:password.
ALTER TABLE, DROP TABLE, and DROP INDEX are parsed but
backend execution hooks are not wired yet.
Seven timing-sensitive cases fail intermittently on loaded/shared CI
runners while passing everywhere else (different victims across
identical runs — the flake signature): the two connection-storm
cases in abi_remote_create_stress_test.cpp, OpenIndex on exclusive-held bag (abi_openindex_create_race_test.cpp, strict
6106 vs 7040 order-dependence), Teardown batching: dirty flush travels alone under a park (network_teardown_batch_test.cpp,
intermittent SIGSEGV), and — since v1.09.63 — the three MT
contention cases in abi_mt_contention_test.cpp that share
verify_mt (8-writer key counts at :165, walk length at :193,
walk order at :186; observed failing on the TLS leg and the
release Ubuntu leg, always the remote-server variant, e.g.
prev=[Charlie]@1 cur=[Alice]@12). They are tagged [flaky],
excluded from the default and slow ctest tiers (still runnable
explicitly, e.g. openads_unit_tests -tc=*storm*), and tracked
here until de-flaked properly. They blocked four consecutive
releases via the all-or-nothing gate (v1.09.52–56 era) —
quarantining the suite is what lets releases proceed while the
races are investigated.
OPEN QUESTION (v1.09.64): the :186 backward key jump happened on
a quiescent post-join tree, which a pure load flake cannot explain
— it smells like a shape-dependent duplicate-ordering issue in the
remote ordered-skip path (this test deliberately stresses
duplicate-key page splits with 10 shared names). If it reproduces
deterministically for a given tree shape it gets a real fix, not
just quarantine; until then the quarantine holds the gate.
- Linux/macOS CI and release builds broken (NTXPL852 tests) — fixed
v1.8.2: shared
polish_oem_fixture.h; Clang-Wstring-concatenation/ greedy\xescape errors in unit tests. OrdScope/AdsSetScopeon character fields — fixed v1.8.1: unpadded scope strings (Harbourhb_itemGetCLen) are now space-padded to indexkey_lengthbefore comparison — work-ordersetScopeTop/setScopeBottom+gotopon local and remote.- NTXPL852 / PL852 OEM collation — fixed v1.8.0: CDX build, seek,
insert, and reindex honour the PL852 sort table;
AdsSetCollationacceptsNTXPL852/PL852. - CDX
REINDEXper-record rebuild — improved v1.8.0: bulkbuild_bulk()path for CDX tags. - Remote
AdsSetScope/OrdScopeignored — fixed v1.7.0:GotoTop/Skipnow honour scoped key ranges overtcp://. - Remote
OrdKeyCount()returns 0 — fixed v1.6.5: newGetKeyCountwire opcode; xBrowse grids show the correct filtered row count. AdsGetDate()crash on remote Date fields — fixed v1.6.5:RemoteIndexhandles resolve to the parentRemoteTablebefore field I/O.- Numeric
dbSeeknot-found on aliased CDX tags — fixed v1.6.x: seek path converts raw double keys to the storedFoxNumeric/ ASCII form; alias qualifiers stripped on the read side. - Conditional index re-create stale order — fixed v1.6.x:
in-place
CREATE INDEXon an open bag rebinds expression, FOR, and the active order (abi_cond_refilter_no_close_test). - WSL2 / Linux
-Werror=conversionbuild failures — fixed: narrowing casts and linkage issues inace_exports.cpp; Linux CI green on v1.7.0. - Remote FiveWin / TDataBase field I/O — fixed v1.6.4: Date columns,
ordinal-as-pointer idiom, unlocked-write
EG_UNLOCKEDparity. - Remote xBrowse index navigation — fixed v1.6.3:
AdsKeyNo, bookmarkGotoRecordsync,AdsAtBOFat first key. - VFP header 0x32 (autoinc + nullable) — fixed v1.5.1.
- Plus SQLite / MSSQL read-only — fixed v1.5.1: navigational write.
- Remote
AdsSetRelation/AdsSetRecord/AdsCustomizeAOF— fixed v1.5.1 (Fase 2).
See CHANGELOG.md for the full per-release breakdown.
openads_serverd now binds 127.0.0.1 by default, including the setup
wizard. Explicit host values in existing INI files still override this default. Existing clients and wire payloads are unchanged.
A non-loopback bind without auth_user is rejected unless the operator
explicitly selects --allow_anonymous (allow_anonymous=true in INI).
The same gate applies to an enabled Studio listener without http_user.
All non-loopback TCP listeners emit a cleartext warning, including those
with authentication. This is exposure mitigation, not native TLS:
use the documented TLS proxy, and firewall its cleartext backend so only
the proxy can reach it. Do not expose TCP credentials to untrusted networks.
Credential hardening: new DD passwords use salted PBKDF2-SHA256. Existing
plaintext password entries are verified in constant time and migrated after
successful named login; unknown or invalid users are never migrated. Password
property 1101 is now write-only through AdsDDGetUserProperty. This deliberately
breaks applications that read passwords back. Named logins now require a valid
password even if LOG_IN_REQUIRED is disabled, preventing AdsSys impersonation.
Legacy anonymous local dictionary setup still works; it is not a network grant.
Security hardening limits: network Mutex Lock is now fail-fast on contention, not an infinite wait for timeout=0. Applications must retry. Network idle sessions expire after 5 minutes; handshake and incomplete frames after 30 seconds. Maximum 256 tables/cursors and 64 created mutexes per connection.
Explicit and AppendBlank record locks are capped at 4096 per session; SQL-generated append locks remain under review.