Skip to content

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

@mho22

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
    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