OpenADS — Divergencia de formato ADI con Advantage Data Architect genuino (SAP): orden de tags prepend vs append, y propuesta de herramienta propia
| Campo |
Valor |
| Proyecto |
FiveTechSoft/OpenADS (drop-in de Advantage Client Engine) |
| Reporta |
Russoft / Zerus ERP (Harbour 3.2 + rddads + OpenADS x64) |
| Fecha |
2026-08-09 |
| Severidad |
Baja/cosmética para OpenADS mismo (lee sus propios índices sin problema) — alta si algún usuario valida sus datos con el Advantage Data Architect genuino de SAP |
| Tipo |
No es un bug de corrupción. Es una divergencia de convención de formato + una propuesta de diseño |
1. Resumen ejecutivo
Al crear un tag nuevo en el directorio de tags de un .ADI, hay dos convenciones posibles:
- prepend (anteponer): el tag nuevo pasa a la posición 0, empuja a los existentes.
- append (agregar al final): el tag nuevo se agrega después de los existentes.
Confirmamos, con datos creados por el Advantage Data Architect genuino de SAP (no por
OpenADS), que SAP usa prepend. OpenADS, desde el commit e511310 ("tag ordinals follow
creation order, as CDX does", mergeado a nuestro fork junto con la actualización a v1.8.68),
usa append.
Consecuencia: cuando el Advantage Data Architect genuino abre un .ADI escrito por OpenADS
(en modo append), su validación interna —que evidentemente asume prepend— lo reporta como
"duplicate index name", aunque el archivo no está roto: el propio OpenADS lo lee
perfecto (0 nombres duplicados, todos los tags accesibles).
2. Evidencia
Se creó prueba1.adt/.adi con el Advantage Data Architect genuino (no con OpenADS): 1 tag
inicial (header en página 3), se creció la tabla a 867 páginas vía
INSERT INTO ... SELECT * FROM ... repetido, y se creó un segundo tag ahí —su header cae en
página 867 (> 255), el caso que hacía falta para descartar un problema de ancho de campo.
Byte a byte, el directorio de tags (prueba1.adi, página 2, offset 24, entradas de 6 bytes):
tag#0 bytes=63 03 00 00 00 7a XX(u32 LE)=867 <- el tag NUEVO (2do creado)
tag#1 bytes=03 00 00 00 00 79 XX(u32 LE)=3 <- el tag ORIGINAL (1ro creado)
Dos lecturas:
- La codificación u32 LE del offset de página es correcta y compatible — no es un problema de
ancho de campo (nuestro fix b8eecbf, "keep every tag when the bag grows past page 255",
sigue siendo válido).
- El orden de las entradas está invertido respecto a lo que hoy escribe OpenADS: SAP puso
el tag nuevo en la posición 0 (prepend), OpenADS (post e511310) lo habría puesto en la 1
(append).
3. La tensión de diseño (por qué no es un revert trivial)
e511310 no fue capricho: corrigió un bug real reportado por nosotros. Con prepend, una
aplicación que navega órdenes por número —OrdSetFocus(n) / OrdName(n), que es
exactamente lo que hace un browse con click-to-sort de columna— activa el orden equivocado, y
no puede compensarlo sin saber de antemano cuántos tags va a terminar teniendo la bolsa. Sobre
un .CDX la misma aplicación obtiene el orden de creación (CDX sí es append de forma nativa).
Revertir a prepend (lo probamos en un branch local, con tests actualizados y suite 100 %
verde) es correcto para paridad con SAP, pero rompe cualquier consumidor que dependa de
OrdSetFocus(NÚMERO) fijo sobre una tabla ADI existente, salvo que ese consumidor resuelva
el número vía el nombre del tag (OrdNumber(nombre)) en vez de un literal. En nuestro caso
concreto eso no es inmediato: buena parte de los tags de producción (los generados por nuestro
propio indexador sin TAG explícito) no tienen nombre semántico — ADS los autonombra ORD9,
ORD10, etc. por posición, así que "el nombre" hoy es la posición, y cambiar el orden
físico los vuelve a barajar igual, con o sin el fix.
4. Lo que decidimos de nuestro lado (por si sirve de contexto)
No vamos a perseguir la paridad byte-a-byte con SAP en este momento: el driver se queda en
modo append (el mismo comportamiento que ya tenía nuestra producción antes de esta
actualización, cero cambios en la aplicación), y dejamos de usar el Advantage Data Architect
genuino para inspeccionar estos archivos — es una herramienta externa de diagnóstico que nunca
usa el ERP en producción, así que el falso "duplicate index name" no lo ve ningún usuario real.
5. Propuesta: un "Architect" propio de OpenADS, en vez de perseguir el formato privativo
Creemos que perseguir paridad exacta con el Advantage Data Architect genuino tiene un techo
bajo: es una herramienta comercial cerrada, su validación interna no está documentada, y ya
encontramos una convención (prepend) que no coincide con lo que el propio equipo de OpenADS
decidió por una razón válida (e511310). Es razonable que en el futuro aparezcan más
divergencias de esta familia, cada una exigiendo elegir entre "compatible con SAP" o
"compatible con lo que ya escribimos".
En vez de perseguir ese blanco móvil, proponemos que el proyecto ofrezca su propia
herramienta de inspección/administración de índices (algo como openads-architect: listar
tags de un .ADI/.CDX, detectar nombres duplicados de verdad, validar la integridad del
árbol, y opcionalmente reparar/reindexar) que entienda el formato que el propio motor
escribe, sin intermediar la validación interna de una herramienta de terceros. Beneficios:
- Los usuarios de OpenADS dejan de depender de una licencia/instalación de Advantage Data
Architect genuino solo para verificar la salud de sus índices.
- El comportamiento a validar es el que el propio proyecto define y documenta (como con
e511310), no el que un tercero infiere de un binario cerrado.
- Sirve como arnés de regresión natural para cualquier cambio futuro al formato ADI/CDX.
No es un pedido urgente — lo dejamos documentado con la evidencia completa por si en algún
momento el equipo quiere retomar la paridad con SAP, o directamente construir esta herramienta.
El fix a prepend que probamos (AdiIndex::add_tag(), con sus dos tests actualizados,
abi_adi_tagdir_order_test.cpp y abi_adi_native_estaelec_test.cpp) sigue disponible si hace
falta como punto de partida.
6. Referencia cruzada
Relacionado con los reportes previos de la misma serie:
OPENADS_PR_SEEK_PARCIAL_DELETED.md (PR #154) y
OPENADS_ISSUE_refilter_parity.md / PR #155 (scope parcial).
OpenADS — Divergencia de formato ADI con Advantage Data Architect genuino (SAP): orden de tags prepend vs append, y propuesta de herramienta propia
1. Resumen ejecutivo
Al crear un tag nuevo en el directorio de tags de un
.ADI, hay dos convenciones posibles:Confirmamos, con datos creados por el Advantage Data Architect genuino de SAP (no por
OpenADS), que SAP usa prepend. OpenADS, desde el commit
e511310("tag ordinals followcreation order, as CDX does", mergeado a nuestro fork junto con la actualización a v1.8.68),
usa append.
Consecuencia: cuando el Advantage Data Architect genuino abre un
.ADIescrito por OpenADS(en modo append), su validación interna —que evidentemente asume prepend— lo reporta como
"duplicate index name", aunque el archivo no está roto: el propio OpenADS lo lee
perfecto (0 nombres duplicados, todos los tags accesibles).
2. Evidencia
Se creó
prueba1.adt/.adicon el Advantage Data Architect genuino (no con OpenADS): 1 taginicial (header en página 3), se creció la tabla a 867 páginas vía
INSERT INTO ... SELECT * FROM ...repetido, y se creó un segundo tag ahí —su header cae enpágina 867 (> 255), el caso que hacía falta para descartar un problema de ancho de campo.
Byte a byte, el directorio de tags (
prueba1.adi, página 2, offset 24, entradas de 6 bytes):Dos lecturas:
ancho de campo (nuestro fix
b8eecbf, "keep every tag when the bag grows past page 255",sigue siendo válido).
el tag nuevo en la posición 0 (prepend), OpenADS (post
e511310) lo habría puesto en la 1(append).
3. La tensión de diseño (por qué no es un revert trivial)
e511310no fue capricho: corrigió un bug real reportado por nosotros. Con prepend, unaaplicación que navega órdenes por número —
OrdSetFocus(n)/OrdName(n), que esexactamente lo que hace un browse con click-to-sort de columna— activa el orden equivocado, y
no puede compensarlo sin saber de antemano cuántos tags va a terminar teniendo la bolsa. Sobre
un
.CDXla misma aplicación obtiene el orden de creación (CDX sí es append de forma nativa).Revertir a prepend (lo probamos en un branch local, con tests actualizados y suite 100 %
verde) es correcto para paridad con SAP, pero rompe cualquier consumidor que dependa de
OrdSetFocus(NÚMERO)fijo sobre una tabla ADI existente, salvo que ese consumidor resuelvael número vía el nombre del tag (
OrdNumber(nombre)) en vez de un literal. En nuestro casoconcreto eso no es inmediato: buena parte de los tags de producción (los generados por nuestro
propio indexador sin
TAGexplícito) no tienen nombre semántico — ADS los autonombraORD9,ORD10, etc. por posición, así que "el nombre" hoy es la posición, y cambiar el ordenfísico los vuelve a barajar igual, con o sin el fix.
4. Lo que decidimos de nuestro lado (por si sirve de contexto)
No vamos a perseguir la paridad byte-a-byte con SAP en este momento: el driver se queda en
modo append (el mismo comportamiento que ya tenía nuestra producción antes de esta
actualización, cero cambios en la aplicación), y dejamos de usar el Advantage Data Architect
genuino para inspeccionar estos archivos — es una herramienta externa de diagnóstico que nunca
usa el ERP en producción, así que el falso "duplicate index name" no lo ve ningún usuario real.
5. Propuesta: un "Architect" propio de OpenADS, en vez de perseguir el formato privativo
Creemos que perseguir paridad exacta con el Advantage Data Architect genuino tiene un techo
bajo: es una herramienta comercial cerrada, su validación interna no está documentada, y ya
encontramos una convención (prepend) que no coincide con lo que el propio equipo de OpenADS
decidió por una razón válida (
e511310). Es razonable que en el futuro aparezcan másdivergencias de esta familia, cada una exigiendo elegir entre "compatible con SAP" o
"compatible con lo que ya escribimos".
En vez de perseguir ese blanco móvil, proponemos que el proyecto ofrezca su propia
herramienta de inspección/administración de índices (algo como
openads-architect: listartags de un
.ADI/.CDX, detectar nombres duplicados de verdad, validar la integridad delárbol, y opcionalmente reparar/reindexar) que entienda el formato que el propio motor
escribe, sin intermediar la validación interna de una herramienta de terceros. Beneficios:
Architect genuino solo para verificar la salud de sus índices.
e511310), no el que un tercero infiere de un binario cerrado.No es un pedido urgente — lo dejamos documentado con la evidencia completa por si en algún
momento el equipo quiere retomar la paridad con SAP, o directamente construir esta herramienta.
El fix a prepend que probamos (
AdiIndex::add_tag(), con sus dos tests actualizados,abi_adi_tagdir_order_test.cppyabi_adi_native_estaelec_test.cpp) sigue disponible si hacefalta como punto de partida.
6. Referencia cruzada
Relacionado con los reportes previos de la misma serie:
OPENADS_PR_SEEK_PARCIAL_DELETED.md (PR #154) y
OPENADS_ISSUE_refilter_parity.md / PR #155 (scope parcial).