pg-mem: Unable to run TypeORM sample code

Describe the bug

Hello, I am trying to run the sample code at pg-mem/samples/typeorm/simple.ts. I am using typeorm "^0.3.10", so I have modified the sample code according to this PR #238 , which addressed a previous typeorm issue #237 .

If there is an updated sample of using pg-mem with typeorm ^0.3.10 that someone can point me to, that might solve this issue.

Here is the error I am seeing locally (running on node v18.2.0) without the modifications suggested in the comments on PR #238

/Users/***/src/driver/postgres/PostgresQueryRunner.ts:299
            throw new QueryFailedError(query, parameters, err)
                  ^
QueryFailedError: ERROR: function current_database() does not exist
HINT: πŸ”¨ Please note that pg-mem implements very few native functions.

            πŸ‘‰ You can specify the functions you would like to use via "db.public.registerFunction(...)"

🐜 This seems to be an execution error, which means that your request syntax seems okay,
    but the resulting statement cannot be executed β†’ Probably not a pg-mem error.

*️⃣ Failed SQL statement: SELECT * FROM current_database();

πŸ‘‰ You can file an issue at https://github.com/oguimbal/pg-mem along with a way to reproduce this error (if you can), and  the stacktrace:


    at PostgresQueryRunner.query (/Users/***/src/driver/postgres/PostgresQueryRunner.ts:299:19)
    at async PostgresQueryRunner.getCurrentDatabase (/Users/***/src/driver/postgres/PostgresQueryRunner.ts:355:23)
    at async PostgresDriver.connect (/Users/***/src/driver/postgres/PostgresDriver.ts:352:33)
    at async DataSource.initialize (/Users/***/src/data-source/DataSource.ts:232:9) {
  query: 'SELECT * FROM current_database()',
  parameters: undefined,
  driverError: QueryError: ERROR: function current_database() does not exist
  HINT: πŸ”¨ Please note that pg-mem implements very few native functions.
  
              πŸ‘‰ You can specify the functions you would like to use via "db.public.registerFunction(...)"
  
  🐜 This seems to be an execution error, which means that your request syntax seems okay,
      but the resulting statement cannot be executed β†’ Probably not a pg-mem error.
  
  *️⃣ Failed SQL statement: SELECT * FROM current_database();
  
  πŸ‘‰ You can file an issue at https://github.com/oguimbal/pg-mem along with a way to reproduce this error (if you can), and  the stacktrace:
  
  
      at buildCall (/Users/***/node_modules/pg-mem/src/parser/function-call.ts:84:15)
      at Object.function (/Users/***/node_modules/pg-mem/src/evaluator.ts:336:25)
      at _buildCall (/Users/***/node_modules/pg-mem/src/parser/expression-builder.ts:183:26)
      at _buildValueReal (/Users/***/node_modules/pg-mem/src/parser/expression-builder.ts:107:20)
      at _buildValue (/Users/***/node_modules/pg-mem/src/parser/expression-builder.ts:51:11)
      at buildValue (/Users/***/node_modules/pg-mem/src/parser/expression-builder.ts:20:17)
      at buildRawSelectSubject (/Users/***/node_modules/pg-mem/src/execution/select.ts:109:45)
      at buildRawSelect (/Users/***/node_modules/pg-mem/src/execution/select.ts:165:15)
      at buildSelect (/Users/***/node_modules/pg-mem/src/execution/select.ts:55:20)
      at buildWithable (/Users/***/node_modules/pg-mem/src/execution/select.ts:35:20) {
    data: {
      error: 'function current_database() does not exist',
      hint: 'πŸ”¨ Please note that pg-mem implements very few native functions.\n' +
        '\n' +
        '            πŸ‘‰ You can specify the functions you would like to use via "db.public.registerFunction(...)"'
    },
    code: undefined,
    location: { start: 0, end: 0 },
    [Symbol(errorDetailsIncluded)]: true
  },
  data: {
    error: 'function current_database() does not exist',
    hint: 'πŸ”¨ Please note that pg-mem implements very few native functions.\n' +
      '\n' +
      '            πŸ‘‰ You can specify the functions you would like to use via "db.public.registerFunction(...)"'
  },
  code: undefined,
  location: { start: 0, end: 0 }
}

And here is the error I’m seeing with the updated code shown below in To Reproduce:

/Users/***/src/data-source/DataSource.ts:285
            throw new CannotExecuteNotConnectedError(this.name)
                  ^
CannotExecuteNotConnectedError: Cannot execute operation on "default" connection because connection is not yet established.
    at DataSource.destroy (/Users/***/src/data-source/DataSource.ts:285:19)
    at DataSource.close (/Users/***/src/data-source/DataSource.ts:302:21)
    at /Users/***/src/simple.ts:80:26
    at step (/Users/***/src/simple.ts:57:23)
    at Object.throw (/Users/***/src/simple.ts:38:53)
    at rejected (/Users/***/src/simple.ts:30:65)

To Reproduce

Here is my modified simple.ts. The main difference is that it’s using createTypeormDataSource, as suggested here.

import { Entity, PrimaryGeneratedColumn, Column, Connection, BaseEntity, LessThan } from "typeorm";
import { newDb } from 'pg-mem';
import { assert, expect } from 'chai';

// Declare an entity
@Entity()
export class User extends BaseEntity {

    @PrimaryGeneratedColumn({ type: 'integer' })
    id!: number;

    @Column({ type: 'text' })
    firstName!: string;

    @Column({ type: 'text' })
    lastName!: string;

    @Column({ type: 'int' })
    age!: number;

}

export async function typeormSimpleSample() {

    //==== create a memory db
    const db = newDb({
        // πŸ‘‰ Recommended when using Typeorm .synchronize(), which creates foreign keys but not indices !
       autoCreateForeignKeyIndices: true,
   });

    //==== create a Typeorm connection
    const datasource= await db.adapters.createTypeormDataSource({
        type: 'postgres',
        entities: [User]
    })

    try {
        //==== create tables
        // Initialize datasource
        await datasource.initialize();
        // create schema
        await datasource.synchronize();
        const users = datasource.getRepository(User);

        //==== create entities
        await users.create({
            firstName: 'john',
            lastName: 'doe',
            age: 18,
        }).save();
        await users.create({
            firstName: 'john',
            lastName: 'lennon',
            age: 99,
        }).save();
        const duck = await users.create({
            firstName: 'donald',
            lastName: 'duck',
            age: 12,
        }).save();

        //==== query entities
        const youngJohns = await users.find({
            firstName: 'john',
            age: LessThan(30)
        });

        expect(youngJohns.map(x => x.lastName))  // outputs 'doe' !
            .to.deep.equal(['doe']);


        //==== modify entities
        duck.firstName = 'daisy';
        await duck.save();

    } finally {
        // do not forget to close the connection once done...
        // ... typeorm stores connections in a static object,
        // and does not like opening 'default connections.
        await datasource.close();
    }
}

// try running the above
(async () => {
// run the code
await typeormSimpleSample()
})();


pg-mem version

2.6.4

I tried running the typeorm tests in the pg-mem repo here, and the typeormSimpleSample appears to be working. However, that repo is using typeorm 0.2.29, so maybe it’s a version issue?

Any help or suggestions would be greatly appreciated!

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (1 by maintainers)

Most upvoted comments

I think I found the solution, see it works for you guys too. @felipegbot @pablofretes @nathan-lapinski

import { PgTag, PgTool } from '@/infra/repositories/postgres/entities'

import { DataType, IMemoryDb, newDb, IBackup } from 'pg-mem'
import { DataSource } from 'typeorm'
import { v4 } from 'uuid'

describe('PgToolRepository', () => {
  let db: IMemoryDb
  let dataSource: DataSource

  beforeAll(async () => {
    db = newDb({ autoCreateForeignKeyIndices: true })

    db.public.registerFunction({
      name: 'current_database',
      args: [],
      returns: DataType.text,
      implementation: (x) => `hello world: ${x}`
    })

    db.public.registerFunction({
      name: 'version',
      args: [],
      returns: DataType.text,
      implementation: (x) => `hello world: ${x}`
    })

    db.registerExtension('uuid-ossp', (schema) => {
      schema.registerFunction({
        name: 'uuid_generate_v4',
        returns: DataType.uuid,
        implementation: v4,
        impure: true
      })
    })

    dataSource = db.adapters.createTypeormDataSource({
      type: 'postgres',
      entities: [PgTool, PgTag]
    })

    await dataSource.initialize()
    await dataSource.synchronize()
  })

  it('should test something', async () => {
    const tag = await dataSource.getRepository(PgTag).save({ slug: 'any_tag' })
    expect(tag.slug).toBe('any_tag')
  })
})

Thanks @remithomas @alexsandroveiga, i’m closing the issue !

LGTM. Thanks @alexsandroveiga !

@nathan-lapinski If everything works, you should close it πŸ˜„

Been looking for this for about 3 weeks now, thank you !!

Thank you, it works! @alexsandroveiga

@felipegbot thanks for posting this workaround!! I was able to run things locally with this change (I had to register the version function as well).

@alexsandroveiga Sure, but the solution that I was talking about was

image

using it resolves the problem (as a workaround)