Skip to content

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

Description

@mho22

Summary

The Kandelo SQLite package (examples/libs/sqlite/build-sqlite.sh) builds libsqlite3 without -DSQLITE_ENABLE_COLUMN_METADATA, so the linker omits sqlite3_column_table_name(), sqlite3_column_database_name(), and sqlite3_column_origin_name() from the static library. PHP's pdo_sqlite extension unconditionally calls sqlite3_column_table_name() from pdo_sqlite_stmt_col_meta() (the C-side of PDOStatement::getColumnMeta()), so the symbol is left undefined in the linked PHP binary, the wasm linker emits it as an env. import, and the kernel worker stubs 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) kills the kernel-mode worker on the first row read.

Why this matters

The headline integration target on the roadmap (#382, Layer 0) is WordPress Playground with --experimental-posix-kernel. WordPress's modern SQLite driver (the WP_SQLite_Driver / WP_SQLite_Connection classes shipped from sqlite-database-integration v3.x / trunk) is the canonical entry point for Adminer and phpMyAdmin in Playground:

  • adminer-mysql-on-sqlite-driver.php:19require_once \$wp_env['db']['driver_path']
  • DbiMysqli.php:28 (phpMyAdmin) — same pattern

Both shims target the modern driver, which calls PDOStatement::getColumnMeta() for every column on every query. Without SQLITE_ENABLE_COLUMN_METADATA, the kernel-mode worker dies on the first query. The classic Emscripten-based php-wasm build statically links a libsqlite3 with column metadata enabled — see packages/php-wasm/compile/libsqlite3/Dockerfile (CFLAGS=\"-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS5 -DSQLITE_USE_URI\") in WordPress/wordpress-playground — so reaching feature parity with the kernel-mode build is what unblocks the modern SQLite driver path.

This is a sibling gap to #550 (libzip + --with-zip) and #551 (libcurl + --with-curl). All three are configure / build-flag adjustments to the kernel-mode PHP toolchain.

Reproducer

Against any current Kandelo PHP CLI binary:

echo '<?php
\$pdo = new PDO(\"sqlite::memory:\");
\$pdo->exec(\"CREATE TABLE t (c INTEGER)\");
\$pdo->exec(\"INSERT INTO t VALUES (1)\");
\$stmt = \$pdo->query(\"SELECT c FROM t\");
var_dump(\$stmt->getColumnMeta(0));
' | <run-php-via-kernel> -r -
# Expected: array(...) { [\"native_type\"] => \"integer\" [\"table\"] => \"t\" ... }
# Actual:   Error: Unimplemented import: env.sqlite3_column_table_name

Root cause

examples/libs/sqlite/build-sqlite.sh:57-64 defines SQLITE_CFLAGS with:

-O2
-DSQLITE_OMIT_LOAD_EXTENSION
-DSQLITE_THREADSAFE=0
-DSQLITE_OMIT_WAL
-DSQLITE_DEFAULT_SYNCHRONOUS=0
-DSQLITE_ENABLE_FTS5
-DSQLITE_ENABLE_JSON1
-DSQLITE_ENABLE_MATH_FUNCTIONS

SQLITE_ENABLE_COLUMN_METADATA is gating. Without it, libsqlite3 omits sqlite3_column_table_name, sqlite3_column_database_name, and sqlite3_column_origin_name from the build. PHP's ext/pdo_sqlite/sqlite_statement.c:pdo_sqlite_stmt_col_meta() references sqlite3_column_table_name() unconditionally, so the symbol is undefined in the PHP binary, emitted as an env. import by the wasm linker, and stubbed by wasm-posix-kernel/host/src/worker-main.ts:660 with a throwing function.

Proposed fix

Three small pieces (mirrors #550 / #551, but smaller — no new package, no new `--with-*` flag):

  1. Add the define in examples/libs/sqlite/build-sqlite.sh: append -DSQLITE_ENABLE_COLUMN_METADATA to SQLITE_CFLAGS.
  2. Bump examples/libs/sqlite/build.toml revision from 1 to 2 so the content-addressed cache rebuilds rather than serving the pre-define archive.
  3. Bump examples/libs/php/build.toml revision from 2 to 3 so PHP relinks against the new libsqlite3.a (PHP statically links it).

No ABI_VERSION bump required (libsqlite3 capability change, not a kernel ABI change).

Acceptance

  • A PHP CLI script calling \$stmt->getColumnMeta(0) against an in-memory PDO returns the full metadata array including table, not an "Unimplemented import" error.
  • The published binaries-abi-v<N> index entries for sqlite and php on wasm32 reference the new revisions.
  • WordPress Playground's Adminer kernel-mode test passes (website-ui.spec.ts:437 Adminer — currently test.skip()'d citing this issue) under packages/playground/website/playwright/e2e/posix-kernel/. (:509 phpMyAdmin will surface once PHP: add libzip + --with-zip so ZipArchive works #550 lands, since its install pipeline calls unzipFile first.)

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions