question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Find operators get passed as objects to transformers

See original GitHub issue

Issue type:

[ ] question [x] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [ ] postgres [x] sqlite [ ] sqljs [ ] react-native

TypeORM version:

[x] latest [ ] @next [ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

import 'reflect-metadata';
import { createConnection, Entity, Column, BaseEntity, PrimaryGeneratedColumn, Between } from 'typeorm';

@Entity()
class Thing extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    transformer: {
      from(value) {
        console.log('from', value);
        return value;
      },

      to(value) {
        console.log('to', value);
        return value;
      }
    }
  })
  field: number;
} 

async function run() {
  await createConnection({
    type: 'sqlite',
    database: './db.sqlite',
    entities: [Thing],
    synchronize: true,
    dropSchema: true
  });

  for (let i = 0; i < 5; i++) {
    const thing = new Thing();
    thing.field = i;
    await thing.save();
  }

  const result = await Thing.find({ where: { field: Between(2, 3) } });
  console.log(result);
}

run();

After running the above code you’ll see one piece of output from the transformer that looks like this:

to FindOperator {
  _type: 'between',
  _value: [ 2, 3 ],
  _useParameter: true,
  _multipleParameters: true }

What seems to be happening is that the Between find operator is getting passed to the transformer as an object. I first ran into this issue because this caused my transformer to throw an exception.

I searched around for this issue and judging from @pleerock’s comment here it seems that transformers are perhaps an underdeveloped feature right now. That’s fine if they aren’t applied in all cases, however it’d be ideal if things like find operators still worked at all under a transformer.

Would it be an easy fix to just sidestep transformers for find operators? That is, you’d use an un-transformed value for that Between operator.

My concrete use case here BTW is converting Date columns to use Luxon DateTimes.

Thanks in advance!

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:19
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

13reactions
pleerockcommented, Jun 23, 2018

Im keeping open all issues related to transformer and once I get more free time I’ll resolve them all

7reactions
nebkatcommented, Nov 28, 2020

Why shouldn’t the logic on how to handle FindOperator be part of the transformer you write?

I think in most circumstances one would want the transformer to act on the parameters to the FindOperator, rather than the operator itself. Take the example below:

export class UserRole {
    static readonly ADMIN = new UserRole('admin', 3);
    static readonly MODERATOR = new UserRole('moderator', 2);
    static readonly USER = new UserRole('user', 1);

    static fromRank(rank: 1 | 2 | 3) {
        return [UserRole.USER, UserRole.MODERATOR, UserRole.ADMIN][rank - 1];
    }

    static toRank(role: UserRole) {
        return role.rank;
    }

    private constructor(readonly value: string, readonly rank: number) {}
}

@Entity()
export class UserEntity {
    // ...

    @Column({
        type: 'tinyint',
        default: UserRole.USER.rank,
        transformer: {
            from: UserRole.fromRank,
            to: UserRole.toRank
        }
    }) role!: UserRole;

    // ...
}

Except for Raw(), which isn’t really an “operator”, all of the values here should be mapped to the rank representation using the transformer:

userRepository.find({
    role: Any(UserRole.USER, UserRole.MODERATOR), 
    role: Between(UserRole.USER, UserRole.MODERATOR),
    role: Equal(UserRole.ADMIN),
    role: In(UserRole.USER, UserRole.MODERATOR),
    role: LessThan(UserRole.MODERATOR),
    role: LessThanOrEqual(UserRole.MODERATOR),
    role: MoreThan(UserRole.MODERATOR),
    role: MoreThanOrEqual(UserRole.MODERATOR),
    role: Not(UserRole.MODERATOR),
   
    // Not relevant for this example
    role: ILike(UserRole.ADMIN),
    role: Like(UserRole.ADMIN),
    role: IsNull(),

    // Exception to the rule, of course
    role: Raw(UserRole.MODERATOR) // becomes `role = ${UserRole.MODERATOR}` directly
});

Only in situations where more complex logic applies should a transformer be expected to modify an operator, and I think @Ciantic’s suggestion would be the best way to achieve that. A good use case for this would be special handling for Date objects.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeORM FindOperators with transformer - Stack Overflow
When I inspect the toPostgres method, what I'm getting passed in there is the FindOperator object. This has the underlying CustomClass instance ...
Read more >
Transformers - Retool Docs
This changes the value of the query everywhere, so that when you use query1.data , you will get the results of the query...
Read more >
PyTerrier Transformers — PyTerrier 0.9.1 documentation
Some operators applied to transformer can be optimised by the underlying search engine - for instance, cutting a ranking earlier. So while the...
Read more >
Export to ONNX - Transformers - Hugging Face
By exposing a graph with standardized operators and data types, ONNX makes it easy to switch between frameworks. For example, a model trained...
Read more >
Composing new operators from existing ones using compose ...
Good developers find opportunities to reuse code, and RxJava provides this ability using ObservableTransformer and FlowableTransformer , which you can pass to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found