oguimbal / pg-mem

An in memory postgres DB instance for your unit tests
MIT License
1.96k stars 96 forks source link

Nested Value When Returning Table #132

Open michaeleliot opened 3 years ago

michaeleliot commented 3 years ago

Big fan of this project, love having contract tests with my jest code. I'm working on a some code that needs to select values via a function. However, it appears the pg-mem function returns a nested value from the function and not the row entries themselves.

Jest test showcasing the issue:

import {newDb} from 'pg-mem';

jest.mock("pg", () => {
    return {
        Client: theClient
    }
})

let db: any;
function theClient() {
  const { Client } = db.adapters.createPg();
  return new Client();
}

describe('function issue showcase', () => {  
  beforeEach(async () => {
    db = newDb()
    simpleDb()
  });

  function simpleDb() {
    db.public.none(`create table example(name varchar);`);
    // Select the table. Equivalent to
    // CREATE FUNCTION get_table() RETURNS table(name varchar) AS $$
    //  BEGIN
    //    RETURN query SELECT * from example;
    //  END;
    // $$ LANGUAGE plpgsql;
    db.public.registerFunction({
        name: 'get_table',
        args: [],
        implementation: () => {
          return db.public.many('SELECT * from example')
        },
    })
  }

  it('gets a scribe queue entry', async () => {
    db.public.none(`INSERT INTO example (name) VALUES ('foo')`);
    let query = db.public.many('SELECT * from example')
    let function_query = db.public.many('SELECT * from get_table()')
    expect(function_query).toStrictEqual(query)
  });
});

query returns [ { name: 'foo', [Symbol(_id)]: 'example_0' } ] while function_query returns [{ get_table: [ { name: 'foo', [Symbol(_id)]: 'example_0' } ], [Symbol()]: true, [Symbol(_id)]: 'vtbl1' }] but postgres would return equivalent values. Is there a way to unpack the function return value? Is this just a limitation of pg-mem? Per the registerFunctionSpec, I believe this is expected behavior for simple data types, but it feels incorrect for returning tables and rows. With nested values the following is impossible:

SELECT * FROM example
UNION
SELECT * FROM get_table();
oguimbal commented 3 years ago

Seems like a bug... I'll try to have a look, but I dont have time these days :(

Thanks for the report and for your kind words