Skip to content

build(sqlite): enable SQLITE_ENABLE_COLUMN_METADATA so PDOStatement::getColumnMeta() works#670

Draft
mho22 wants to merge 1 commit into
mainfrom
add-sqlite-metadata-to-php
Draft

build(sqlite): enable SQLITE_ENABLE_COLUMN_METADATA so PDOStatement::getColumnMeta() works#670
mho22 wants to merge 1 commit into
mainfrom
add-sqlite-metadata-to-php

Conversation

@mho22

@mho22 mho22 commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #577.

  • Adds -DSQLITE_ENABLE_COLUMN_METADATA to packages/registry/sqlite/build-sqlite.sh so libsqlite3.a exports sqlite3_column_table_name, _database_name, and _origin_name.
  • Bumps packages/registry/sqlite/build.toml revision 1 → 2 so the content-addressed cache rebuilds rather than serving the pre-define archive.
  • Bumps packages/registry/php/build.toml revision 3 → 4 so PHP relinks against the new libsqlite3.a (PHP statically links it).
  • Adds a vitest regression test (packages/registry/php/test/php-pdo-column-metadata.test.ts) that asserts PDOStatement::getColumnMeta(0) returns the column's table name without surfacing an Unimplemented import error.

Why

libsqlite3 was built without -DSQLITE_ENABLE_COLUMN_METADATA, so sqlite3_column_table_name() / _database_name() / _origin_name() were stripped from the static library. PHP's ext/pdo_sqlite/sqlite_statement.c:pdo_sqlite_stmt_col_meta() references sqlite3_column_table_name() unconditionally, so the symbol stayed undefined in the linked PHP binary, the wasm linker emitted it as an env. import, and host/src/worker-main.ts stubbed it with a throwing function:

Error: Unimplemented import: env.sqlite3_column_table_name
    at php-fpm.pdo_sqlite_stmt_col_meta (wasm-function[18575])
    at php-fpm.zim_PDOStatement_getColumnMeta (wasm-function[18465])

Any call to $stmt->getColumnMeta(N) killed the kernel-mode worker on the first row read.

The classic Emscripten php-wasm build statically links libsqlite3 with column metadata enabled — see packages/php-wasm/compile/libsqlite3/Dockerfile in WordPress/wordpress-playground (CFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS5 -DSQLITE_USE_URI"). This change mirrors that.

WordPress's modern WP_SQLite_Driver (shipped from sqlite-database-integration v3.x / trunk, used by the Adminer and phpMyAdmin shims in Playground) calls PDOStatement::getColumnMeta() for every column on every query, so this unblocks the kernel-mode Adminer / phpMyAdmin path on the Playground integration target (#382). Sibling gaps remain: #550 (libzip + --with-zip) and #551 (libcurl + --with-curl).

Scope / ABI

  • No ABI_VERSION bump — this is a libsqlite3 capability change, not a kernel ABI change.
  • package.toml is untouched on both packages: the revision field lives in build.toml per the current package-system layout (see wasm-posix-kernel/CLAUDE.md — "Revision lives in build.toml").
  • Two hosts unchanged: this is a build-flag adjustment. No host runtime, kernel, syscall, or libc changes; Node.js and browser hosts are both fed the same rebuilt php.wasm from CI.

Test plan

  • Local vitest scoped to the touched packages — only failure is the pre-existing @playwright/test-missing import in php-browser.spec.ts, unrelated to this change. The new php-pdo-column-metadata.test.ts follows the same skip-when-binary-missing pattern as php-concurrent-sqlite.test.ts, so it skips locally and runs in CI where the matrix produces php.wasm.
  • CI matrix rebuilds sqlite (revision 2) and php (revision 4); the published binaries-abi-v<N> index entries for both on wasm32 reference the new revisions.
  • The new vitest passes against the rebuilt php.wasm: getColumnMeta(0) returns name=c and table=t with no Unimplemented import in stderr.
  • Downstream WordPress Playground Adminer kernel-mode test (website-ui.spec.ts:437, currently test.skip()'d citing this issue) can be unskipped once these binaries are published.

🤖 Generated with Claude Code

libsqlite3 was built without -DSQLITE_ENABLE_COLUMN_METADATA, so
sqlite3_column_table_name / _database_name / _origin_name were stripped
from the static library. PHP's pdo_sqlite unconditionally calls
sqlite3_column_table_name() from pdo_sqlite_stmt_col_meta(), so the
symbol was left undefined, the wasm linker emitted it as an env. import,
and the kernel worker stubbed it with a throwing function — any
PDOStatement::getColumnMeta() call killed the worker on the first row.

The classic Emscripten php-wasm build statically links libsqlite3 with
column metadata enabled; mirror that. WordPress's modern WP_SQLite_Driver
(used by Adminer and phpMyAdmin shims in Playground) calls getColumnMeta
for every column on every query, so this unblocks the kernel-mode
Adminer / phpMyAdmin path on the Playground integration target (#382).

Bumps the sqlite revision so the content-addressed cache rebuilds rather
than serving the pre-define archive, and bumps PHP's revision so it
relinks against the new libsqlite3.a (PHP statically links it). No
ABI_VERSION bump — this is a libsqlite3 capability change, not a kernel
ABI change.

Adds a vitest regression test that asserts PDOStatement::getColumnMeta(0)
returns the column's table name without surfacing an "Unimplemented
import" error. Skipped when the PHP CLI binary is not built locally.

Fixes #577.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mho22 mho22 force-pushed the add-sqlite-metadata-to-php branch from 0bccc51 to fdb065c Compare June 10, 2026 14:18
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Phase B-1 matrix build status — pr-670-staging

ABI v14. 44 built, 22 failed, 66 total.

Package Arch Status Sha
libcurl wasm32 built e5a13d8d
libcxx wasm32 built f66a6604
libcxx wasm64 built 1a9c8659
libpng wasm32 built 15ed3cfb
libxml2 wasm32 built 4912ddec
libxml2 wasm64 built 0f264e25
ncurses wasm32 built d097bd15
openssl wasm32 built f1692aaa
openssl wasm64 built bc008447
sqlite wasm32 built 5dc78071
sqlite wasm64 built 90914f37
zlib wasm32 built 41c7d171
zlib wasm64 built 3703432b
bash wasm32 built b194796c
bc wasm32 built 3e4cb805
bzip2 wasm32 built 139e057c
coreutils wasm32 built f041cdc4
curl wasm32 built 5cd343a2
dash wasm32 built 1ed5b470
diffutils wasm32 built 61852bb7
dinit wasm32 built dbb5afa9
fbdoom wasm32 built 933689bf
file wasm32 built 98768983
findutils wasm32 built 221935c3
gawk wasm32 built 4dd82709
git wasm32 built 08f28bbf
grep wasm32 built df39087d
gzip wasm32 built a47302be
kandelo-sdk wasm32 failed
kernel wasm32 failed
lamp wasm32 built 969d3938
less wasm32 failed
lsof wasm32 built 9c850182
m4 wasm32 failed
make wasm32 built 2946c5c8
mariadb-test wasm32 failed
mariadb-vfs wasm32 failed
mariadb-vfs wasm64 built bb78e54e
mariadb wasm32 failed
mariadb wasm64 failed (prev bb78e54e)
msmtpd wasm32 built 7485b0e0
nano wasm32 built 88d24790
netcat wasm32 failed
nethack-browser-bundle wasm32 built 545e50f6
nethack wasm32 built 3f26ca09
nginx wasm32 failed
node-vfs wasm32 failed (prev d53be667)
node wasm32 failed (prev d53be667)
php wasm32 failed
posix-utils-lite wasm32 built ec8fbab6
rootfs wasm32 failed
sed wasm32 failed
shell wasm32 failed
spidermonkey-node wasm32 failed
spidermonkey wasm32 built 8734bd3d
tar wasm32 failed
tcl wasm32 built 73b1c2af
unzip wasm32 built 036c5a61
userspace wasm32 failed
vim-browser-bundle wasm32 failed
vim wasm32 failed
wget wasm32 failed
wordpress wasm32 built 5529387e
xz wasm32 built 3bc5088e
zip wasm32 built 6dd20732
zstd wasm32 built 741d05bf

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PHP: enable SQLITE_ENABLE_COLUMN_METADATA so PDOStatement::getColumnMeta() works

1 participant