Verify Informix 14.10 and 12.10; make the version matrix reproducible
Closes out the field report that prompted 2026.05.08.2. Full integration suite, same commit, all green: Informix 15.0.1.0.3DE 241 / 241 Informix 14.10.FC7W1DE 241 / 241 Informix 12.10.FC12W1DE 241 / 241 Including smart-LOB. The 28-type round-trip produces byte-identical wire output on all three — same type codes, same encoded lengths, same values. There is no 12-vs-14-vs-15 wire difference for anything we support. Testing three versions by hand was tedious and undocumented, which is part of why it never happened. Now: make ifx-legacy-up 12.10 on 9089, 14.10 on 9090, alongside 15 on 9088 make ifx-legacy-setup blobspace1 + sbspace1 in both make test-matrix the suite against all three tests/setup-spaces.sh absorbs the per-image differences that made this annoying: 12.10/14.10 use a flat INFORMIXDIR while 15 nests a versioned subdirectory; ONCONFIG is named differently across images; `bash -lc` wipes INFORMIXDIR and makes every utility fail with a misleading "Unable to read $INFORMIXDIR (/usr/informix)"; and 12.10 DE ships no ontape at all (the level-0 archive turns out to be unnecessary anyway). Without blobspace1/sbspace1, ~21 tests fail with errors that look like driver bugs and aren't. The documented workflow was validated from scratch — containers removed, recreated via compose, spaces created via the script, matrix run — rather than written up afterward from whichever commands happened to work. The README claim this replaces was wrong precisely because nobody did that.
This commit is contained in:
parent
87b5b7c354
commit
783b2bec97
25
CHANGELOG.md
25
CHANGELOG.md
@ -43,7 +43,7 @@ bytes 6-9 HIGH 32 bits, big-endian unsigned
|
||||
|
||||
### On the version question
|
||||
|
||||
The report arrived as "Informix 12 mangles result sets." It isn't a version issue. Running the same 28-type round-trip against **12.10.FC12W1DE** and **15.0.1.0.3DE** produced **byte-identical** wire output — same type codes, same encoded lengths, same values. Both servers were equally broken, and are now equally fixed.
|
||||
The report arrived as "Informix 12 mangles result sets." It isn't a version issue. Running the same 28-type round-trip against **12.10.FC12W1DE**, **14.10.FC7W1DE**, and **15.0.1.0.3DE** produced **byte-identical** wire output — same type codes, same encoded lengths, same values. All three were equally broken, and are now equally fixed.
|
||||
|
||||
The reason it read as version-specific: `INT8`/`SERIAL8` dominate Informix 12-era schemas (`BIGINT` only arrived in 11.50), while our test fixtures use `BIGINT`. The bugs were always there; older schemas just walk into them far more often.
|
||||
|
||||
@ -55,9 +55,26 @@ Added `tests/test_type_framing.py` (20 integration tests) and `tests/test_int8_u
|
||||
|
||||
### Verified
|
||||
|
||||
- 251/251 integration tests on Informix 15.0.1.0.3DE
|
||||
- 241/241 non-smart-LOB integration tests on Informix 12.10.FC12W1DE (the LOB tests need an sbspace that image doesn't have configured)
|
||||
- New framing tests: 20/20 on both servers
|
||||
Full integration suite, same commit, all green:
|
||||
|
||||
| Server | Result |
|
||||
|---|---|
|
||||
| 15.0.1.0.3DE | 241 / 241 |
|
||||
| 14.10.FC7W1DE | 241 / 241 |
|
||||
| 12.10.FC12W1DE | 241 / 241 |
|
||||
|
||||
New framing tests pass 34/34 on all three.
|
||||
|
||||
### Server matrix is now reproducible
|
||||
|
||||
Testing three versions by hand was tedious and undocumented, which is part of why it never happened. Added:
|
||||
|
||||
- `tests/docker-compose.legacy.yml` — 12.10 on 9089 and 14.10 on 9090, coexisting with the primary 15 container on 9088
|
||||
- `tests/setup-spaces.sh` — creates `blobspace1` + `sbspace1` in any dev container. Handles the layout differences between images (12.10/14.10 use a flat `INFORMIXDIR`, 15 nests a versioned subdirectory; `ONCONFIG` is named differently; 12.10 DE ships no `ontape`). Without these spaces ~21 tests fail with errors that look like driver bugs and aren't.
|
||||
- `make ifx-legacy-up` / `ifx-legacy-setup` / `ifx-legacy-down` / `ifx-spaces`
|
||||
- `make test-matrix` — the suite against all three versions
|
||||
|
||||
The whole documented workflow was validated from scratch (containers destroyed, recreated via compose, spaces created via the script, matrix run) rather than written up after the fact from commands that happened to work.
|
||||
|
||||
### Also
|
||||
|
||||
|
||||
31
Makefile
31
Makefile
@ -79,6 +79,37 @@ ifx-status: ## Check container health and listener readiness
|
||||
@docker ps --filter name=$(IFX_CONTAINER) --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
@nc -zv 127.0.0.1 9088 2>&1 | head -1
|
||||
|
||||
ifx-spaces: ## Create blobspace1 + sbspace1 in the Informix 15 container (needed for LOB tests)
|
||||
tests/setup-spaces.sh $(IFX_CONTAINER)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Server-compatibility matrix: Informix 12.10 / 14.10 alongside 15
|
||||
# ----------------------------------------------------------------------------
|
||||
# The legacy containers run on 9089 / 9090 so they coexist with the primary
|
||||
# 15 container on 9088. The integration suite targets whichever server
|
||||
# IFX_PORT names, so the matrix is just the same suite three times.
|
||||
|
||||
ifx-legacy-up: ## Start Informix 12.10 (9089) and 14.10 (9090) alongside 15
|
||||
docker compose -f tests/docker-compose.legacy.yml up -d
|
||||
@echo " 12.10 -> 127.0.0.1:9089"
|
||||
@echo " 14.10 -> 127.0.0.1:9090"
|
||||
@echo " Engine init takes ~1-3 min on first start; then: make ifx-legacy-setup"
|
||||
|
||||
ifx-legacy-setup: ## Create blobspace1 + sbspace1 in both legacy containers
|
||||
tests/setup-spaces.sh informix-db-test-1210
|
||||
tests/setup-spaces.sh informix-db-test-1410
|
||||
|
||||
ifx-legacy-down: ## Stop and remove the legacy containers
|
||||
docker compose -f tests/docker-compose.legacy.yml down
|
||||
|
||||
test-matrix: ## Run the integration suite against 15 (9088), 14.10 (9090), and 12.10 (9089)
|
||||
@echo "=== Informix 15 (9088) ==="
|
||||
@IFX_PORT=9088 uv run pytest -m "integration and not benchmark" -q --no-header
|
||||
@echo "=== Informix 14.10 (9090) ==="
|
||||
@IFX_PORT=9090 uv run pytest -m "integration and not benchmark" -q --no-header
|
||||
@echo "=== Informix 12.10 (9089) ==="
|
||||
@IFX_PORT=9089 uv run pytest -m "integration and not benchmark" -q --no-header
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Phase 0 spike: re-capture wire traffic against the dev container
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
29
README.md
29
README.md
@ -149,15 +149,30 @@ The fast-path RPC (`SQ_FPROUTINE` / `SQ_EXFPROUTINE`) bypasses PREPARE → EXECU
|
||||
|
||||
## Server compatibility
|
||||
|
||||
| Server | Status |
|
||||
|---|---|
|
||||
| **15.0.1.0.3DE** | Primary target. Full suite green (251 integration tests). |
|
||||
| **12.10.FC12W1DE** | Verified 2026-05-08. Full suite green except smart-LOB, which needs an sbspace we haven't configured on that image — not a driver limitation. |
|
||||
| **14.10** | Not yet tested. Expected to work; we'll confirm rather than assume. |
|
||||
All three tested against the official IBM developer-edition Docker images, full integration suite, same commit:
|
||||
|
||||
Earlier releases of this README claimed the wire protocol was "stable across modern versions" and should "work against 12.10+ unmodified." That was never tested when written. It has since been measured: running the same 28-type round-trip against 12.10 and 15 produces **byte-identical** wire output, so the claim turned out to be true — but it was a guess at the time, and a user lost debugging time to it. Apologies.
|
||||
| Server | Image | Integration suite |
|
||||
|---|---|---|
|
||||
| **15.0.1.0.3DE** | `icr.io/informix/informix-developer-database` | **241 / 241** |
|
||||
| **14.10.FC7W1DE** | `ibmcom/informix-developer-database` | **241 / 241** |
|
||||
| **12.10.FC12W1DE** | `ibmcom/informix-developer-database` | **241 / 241** |
|
||||
|
||||
One real caveat remains. SQLI negotiates some wire framing through a capability exchange (`SQ_PROTOCOLS`) that this driver does not yet perform; we hardcode the modern framing. That is correct for every server we have measured, but it is an assumption rather than a negotiation, and it is the first thing to suspect if you hit corrupt rows on a server we haven't listed above. Please open an issue with your server version if so.
|
||||
Reproduce the whole matrix:
|
||||
|
||||
```bash
|
||||
make ifx-up # Informix 15 on 9088
|
||||
make ifx-legacy-up # 12.10 on 9089, 14.10 on 9090
|
||||
make ifx-legacy-setup # blobspace1 + sbspace1 (smart-LOB tests need these)
|
||||
make test-matrix # the suite against all three
|
||||
```
|
||||
|
||||
The suite targets whichever server `IFX_PORT` names, so a single version is just `IFX_PORT=9089 uv run pytest -m "integration and not benchmark"`.
|
||||
|
||||
Beyond the suite passing, a 28-type round-trip (every scalar type we support, including the fiddly ones — `INT8`, `NCHAR`, `BOOLEAN`, `DATETIME YEAR TO FRACTION(5)`, `INTERVAL`, `DECIMAL`, `MONEY`, `LVARCHAR`) produces **byte-identical wire output** on all three versions: same type codes, same encoded lengths, same values.
|
||||
|
||||
Earlier releases of this README claimed the protocol was "stable across modern versions" and should "work against 12.10+ unmodified." That claim turned out to be correct, but it was written before anyone had run it against 12.10, and a user lost debugging time to a version-compatibility problem that didn't exist. It's measured now. Apologies for the earlier guess.
|
||||
|
||||
One caveat remains, and it's a real one. SQLI negotiates some wire framing through a capability exchange (`SQ_PROTOCOLS`) that this driver does not yet perform — we hardcode the modern framing. That is correct on all three servers above, but it is an assumption rather than a negotiation. If you hit corrupted rows on a server not in that table, this is the first thing to suspect; please open an issue with your server version and the `cursor.description` of the offending query.
|
||||
|
||||
For features that need server-side configuration (smart-LOBs, logged transactions), see [`docs/DECISION_LOG.md`](https://git.supported.systems/warehack.ing/informix-db/src/branch/main/docs/DECISION_LOG.md):
|
||||
- Phase 7 — logged-DB transactions
|
||||
|
||||
48
tests/docker-compose.legacy.yml
Normal file
48
tests/docker-compose.legacy.yml
Normal file
@ -0,0 +1,48 @@
|
||||
# Older Informix versions, for the server-compatibility matrix in the README.
|
||||
#
|
||||
# The primary dev container (tests/docker-compose.yml) runs Informix 15 on
|
||||
# 9088. These two run alongside it on 9089 / 9090 so all three can be tested
|
||||
# without tearing anything down.
|
||||
#
|
||||
# These images live on Docker Hub under ibmcom/ rather than icr.io/informix/ —
|
||||
# IBM stopped publishing the older developer editions to the newer registry.
|
||||
# They're tagged rather than digest-pinned because the ibmcom repo is frozen
|
||||
# (no new pushes since the icr.io move), so the tags are already immutable in
|
||||
# practice.
|
||||
#
|
||||
# make ifx-legacy-up start both
|
||||
# make ifx-legacy-setup create blobspace1 + sbspace1 (needed for LOB tests)
|
||||
# make test-matrix run the integration suite against all three
|
||||
# make ifx-legacy-down stop and remove
|
||||
services:
|
||||
ifx1210:
|
||||
container_name: informix-db-test-1210
|
||||
image: ibmcom/informix-developer-database:12.10.FC12W1DE
|
||||
privileged: true
|
||||
environment:
|
||||
LICENSE: accept
|
||||
SIZE: small
|
||||
ports:
|
||||
- "9089:9088"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9088 && exec 3<&- && exec 3>&-"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 60
|
||||
start_period: 30s
|
||||
|
||||
ifx1410:
|
||||
container_name: informix-db-test-1410
|
||||
image: ibmcom/informix-developer-database:14.10.FC7W1DE
|
||||
privileged: true
|
||||
environment:
|
||||
LICENSE: accept
|
||||
SIZE: small
|
||||
ports:
|
||||
- "9090:9088"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9088 && exec 3<&- && exec 3>&-"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 60
|
||||
start_period: 30s
|
||||
76
tests/setup-spaces.sh
Executable file
76
tests/setup-spaces.sh
Executable file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create blobspace1 + sbspace1 in an Informix dev container.
|
||||
#
|
||||
# The developer-edition images ship with only rootdbs. BYTE/TEXT tests need a
|
||||
# blobspace; BLOB/CLOB (smart-LOB) tests need an sbspace plus SBSPACENAME set.
|
||||
# Without them, ~21 integration tests fail with errors that look like driver
|
||||
# bugs but are pure server configuration.
|
||||
#
|
||||
# Usage: tests/setup-spaces.sh <container-name>
|
||||
#
|
||||
# Idempotent: re-running against a container that already has the spaces prints
|
||||
# the server's "already exists" complaint and exits 0.
|
||||
#
|
||||
# Version quirks this handles, learned the hard way:
|
||||
# * INFORMIXDIR differs — 12.10/14.10 use /opt/ibm/informix, 15 nests a
|
||||
# versioned subdirectory (/opt/ibm/informix/v15.0.1.0.3).
|
||||
# * ONCONFIG is named `onconfig` on some images and `onconfig.informix` on
|
||||
# others; we probe for the file rather than guessing.
|
||||
# * `bash -lc` wipes INFORMIXDIR from the environment on these images, which
|
||||
# makes every utility fail with "Unable to read $INFORMIXDIR (/usr/informix)".
|
||||
# Use `bash -c` and export explicitly.
|
||||
# * 12.10 DE ships no `ontape`. The level-0 archive turns out to be
|
||||
# unnecessary for the tests, so we attempt it and shrug if it's missing.
|
||||
set -euo pipefail
|
||||
|
||||
CONTAINER="${1:?usage: setup-spaces.sh <container-name>}"
|
||||
|
||||
docker exec -u informix "$CONTAINER" bash -c '
|
||||
set -u
|
||||
|
||||
# Locate INFORMIXDIR: either /opt/ibm/informix or a versioned subdir under it.
|
||||
for cand in /opt/ibm/informix /opt/ibm/informix/v*; do
|
||||
if [ -x "$cand/bin/onspaces" ]; then
|
||||
export INFORMIXDIR="$cand"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "${INFORMIXDIR:-}" ]; then
|
||||
echo "could not locate INFORMIXDIR (no bin/onspaces found)" >&2
|
||||
exit 1
|
||||
fi
|
||||
export PATH="$INFORMIXDIR/bin:$PATH"
|
||||
export INFORMIXSERVER=informix
|
||||
export INFORMIXSQLHOSTS="$INFORMIXDIR/etc/sqlhosts"
|
||||
|
||||
# ONCONFIG name varies across images.
|
||||
for cfg in onconfig onconfig.informix; do
|
||||
if [ -f "$INFORMIXDIR/etc/$cfg" ]; then
|
||||
export ONCONFIG="$cfg"
|
||||
break
|
||||
fi
|
||||
done
|
||||
: "${ONCONFIG:?no onconfig found in $INFORMIXDIR/etc}"
|
||||
|
||||
echo "INFORMIXDIR=$INFORMIXDIR ONCONFIG=$ONCONFIG"
|
||||
|
||||
SPACES=/opt/ibm/data/spaces
|
||||
mkdir -p "$SPACES"
|
||||
for f in blobspace1 sbspace1; do
|
||||
[ -e "$SPACES/$f" ] || : > "$SPACES/$f"
|
||||
chmod 660 "$SPACES/$f"
|
||||
done
|
||||
|
||||
onspaces -c -b blobspace1 -g 1 -p "$SPACES/blobspace1" -o 0 -s 50000 2>&1 | grep -vE "^\s*$" || true
|
||||
onspaces -c -S sbspace1 -p "$SPACES/sbspace1" -o 0 -s 50000 -Df "AVG_LO_SIZE=100" 2>&1 | grep -vE "^\s*$" || true
|
||||
onmode -wm SBSPACENAME=sbspace1 2>&1 | tail -1 || true
|
||||
|
||||
# Level-0 archive. Informix warns it is required after adding a space; in
|
||||
# practice the tests pass without it, and 12.10 DE has no ontape at all.
|
||||
onmode -wm TAPEDEV=/dev/null >/dev/null 2>&1 || true
|
||||
if command -v ontape >/dev/null 2>&1; then
|
||||
ontape -s -L 0 2>&1 | tail -1 || true
|
||||
else
|
||||
echo "ontape not present on this image; skipping level-0 archive"
|
||||
fi
|
||||
'
|
||||
Loading…
x
Reference in New Issue
Block a user