oguimbal / pg-mem

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

Typeorm integration fails after 0.2.30 #81

Open zebieksts opened 3 years ago

zebieksts commented 3 years ago

typeorm introduced this change link to diff after which pg-mem fails to integrate. It seems related to this #58 issue.

    it('can process updated typeorm columns schema selection', () => {
        simpleDb();
     const sql = `SELECT columns.*,
              pg_catalog.col_description(('"' || table_catalog || '"."' || table_schema || '"."' || table_name || '"')::regclass::oid, ordinal_position) AS description,
              ('"' || "udt_schema" || '"."' || "udt_name" || '"')::"regtype" AS "regtype",
              pg_catalog.format_type("col_attr"."atttypid", "col_attr"."atttypmod") AS "format_type"
              FROM "information_schema"."columns"
              LEFT JOIN "pg_catalog"."pg_attribute" AS "col_attr"
              ON "col_attr"."attname" = "columns"."column_name"
              AND "col_attr"."attrelid" = (
                SELECT
                  "cls"."oid" FROM "pg_catalog"."pg_class" AS "cls"
                  LEFT JOIN "pg_catalog"."pg_namespace" AS "ns"
                  ON "ns"."oid" = "cls"."relnamespace"
                WHERE "cls"."relname" = "columns"."table_name"
                AND "ns"."nspname" = "columns"."table_schema"
              )`;
        expect(many(sql).length)
            .to.equal(4);
        expect(many(sql))
            .to.deep.equal([{ regtype: 'text' }
                , { regtype: 'jsonb' }
                , { regtype: 'integer' }
                , { regtype: 'text' }]);
    });

Error: column "columns.table_name" does not exist

oguimbal commented 3 years ago

Quite good analysis 😊

Actually, this issue is a duplicate of #61 ... and will be fixed when the underlying cause #38 is fixed.

It requires a non trivial refactoring of how references are resolved in pg-mem, which I did not had the time do carry to its end yet :(

This is not an issue with Typeorm 0.2.29 and lower, if downgrading is an option for you, though.

ps: I'm leaving this issue open for future readers

bhavitsharma commented 2 years ago

Hi, is there a workaround we can do? Or perhaps I can help with refactoring given enough context/help. Downgrading typeorm is not an option for us unfortunately :(

oguimbal commented 2 years ago

Hi, I currently dont have any tested workaround, but I never looked into one.

That said, this could work:

const db = newDb();

const incriminatedQuery = `SELECT columns.*,
              pg_catalog.col_description(('"' || table_catalog || '"."' || table_schema || '"."' || table_name || '"')::regclass::oid, ordinal_position) AS description,
              ('"' || "udt_schema" || '"."' || "udt_name" || '"')::"regtype" AS "regtype",
              pg_catalog.format_type("col_attr"."atttypid", "col_attr"."atttypmod") AS "format_type"
              FROM "information_schema"."columns"
              LEFT JOIN "pg_catalog"."pg_attribute" AS "col_attr"
              ON "col_attr"."attname" = "columns"."column_name"
              AND "col_attr"."attrelid" = (
                SELECT
                  "cls"."oid" FROM "pg_catalog"."pg_class" AS "cls"
                  LEFT JOIN "pg_catalog"."pg_namespace" AS "ns"
                  ON "ns"."oid" = "cls"."relnamespace"
                WHERE "cls"."relname" = "columns"."table_name"
                AND "ns"."nspname" = "columns"."table_schema"
              )`;

db.public.interceptQueries(text => {
 if (text === incriminatedQuery) {
    return [];
}
 return null;
})

This will intercept the introspection query, which we know for a fact that it will not return anything on a blank database => forcing it to return [] is thus OK.

I did not test it, and the incriminatedQuery is probably wrong (at least the whitespace padding introduced here will be wrong).

Could you test that, tweak the query that fails, and tell me if it works (and repost here the right query if that works for others !)

Thanks :)

vvvvch commented 2 years ago

https://github.com/oguimbal/pg-mem/issues/81#issuecomment-933654078 The code above works for me except this detail:

if (text === incriminatedQuery) {
    return [];

In my query a dynamic (based on entities) WHERE-clause also generates. So I replaced this place with:

if (text.replace(/[\n ]/g, '').startsWith(incriminatedQuery.replace(/[\n ]/g, ''))) {
    return [];

And now it works. Still waiting for this issue to be resolved though.