Skip to content

Postgres adapter: BOOLEAN columns returned as 0/1 instead of true/false #1150

@hubyrod

Description

@hubyrod

Bug: @skip-adapter/postgres passes booleans as integers

Version: @skip-adapter/postgres@0.0.19

Problem

PostgreSQL BOOLEAN columns are passed to Skip Runtime mappers/enrichers as 0 / 1 (integers) instead of native JavaScript true / false.

This causes silent bugs: strict equality checks like === true or === false always fail, since the values are actually numbers.

Reproduction

Given a PostgreSQL table:

CREATE TABLE users (
  id TEXT PRIMARY KEY,
  username TEXT NOT NULL,
  is_test_user BOOLEAN NOT NULL DEFAULT false
);

INSERT INTO users (id, username, is_test_user) VALUES ('u1', 'alice', true);
INSERT INTO users (id, username, is_test_user) VALUES ('u2', 'bob', false);

And a mapper consuming the users external collection:

class MyMapper implements Mapper<string, DbUser, string, Output> {
  mapEntry(key: string, values: Values<DbUser>): Iterable<[string, Output]> {
    const user = values.getUnique();

    // BUG: user.is_test_user is 1 or 0, not true/false
    if (user.is_test_user === true) {
      // This branch NEVER executes, even for alice
      return [];
    }

    console.log(typeof user.is_test_user); // "number"
    console.log(user.is_test_user);        // 1 or 0

    return [[key, { ...user }]];
  }
}

Impact

  • === true / === false comparisons silently fail
  • Environment-based filtering breaks (e.g., separating test users from production users)
  • Every mapper/enricher that consumes a boolean column must defensively wrap the value in Boolean()

Current workaround

Wrapping every boolean field access with Boolean():

const isTestUser = Boolean(user.is_test_user); // converts 0/1 → false/true

This must be applied in every enricher and mapper that reads a boolean column.

Expected behavior

The postgres adapter should convert PostgreSQL BOOLEAN columns to native JavaScript true / false before passing them into the reactive graph.

The pg driver itself returns proper booleans — the conversion to 0/1 appears to happen somewhere in the adapter or serialization layer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions