Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model strict: false is ignored with Postgre SQL repository #4042

Closed
shreking-around opened this issue Nov 1, 2019 · 5 comments · Fixed by loopbackio/loopback-datasource-juggler#1817
Assignees
Labels
db:PostgreSQL Topics specific to PostgreSQL developer-experience Issues affecting ease of use and overall experience of LB users feature
Milestone

Comments

@shreking-around
Copy link

shreking-around commented Nov 1, 2019

Hello,

I have a problem with class inheritance and repository using Postgre SQL.

Let's say we have Animal parent class and then Dog and Chicken child classes. I store them in one table (Table Per Hierarchy Inheritance) called animal.

In LB4 App I have Animal base model (entityType is a discriminator):

@model({
    settings: {
        postgresql: {
            table: 'animal',
        },
        idInjection: false,
        strict: false,
    },
})
export class Animal extends Entity {
    @property({
        type: 'string',
        id: true,
        postgresql: {
            dataType: 'uuid',
        },
    })
    id: string;

    @property({
        type: 'string',
        required: true,
    })
    entityType: string;
 
    @property({
        type: 'number',
        required: true,
    })
    weight: number;

    @hasMany(() => Zookeeper)
    zookepers?: Zookeeper[];
 

    constructor(data?: Partial<Animal>) {
        super(data);
    }
}

and child class dog

@model()
export class Dog extends Animal {
 
    @property({
        type: 'number',
        required: true

    })
    barkingLevel: number;

    constructor(data?: Partial<Dog>) {
        super(data);
    }
}

When I query a dog from the repository barkingLevel is ommited on output though the strict is set to false.

This will return animal (not a dog) without barkingLevel .

 const dog : Dog = await this.animalRepository.findById(id, {
            include: [
                { relation: 'zookepers' }
            ],
        }) as Dog;

Repository:

export class AnimalRepository extends DefaultCrudRepository<
    Animal,
    typeof Animal.prototype.id
> {
    //declare has-many repositories for related zookeeper entities
    public readonly zookeepers: HasManyRepositoryFactory<
        Zookeeper,
        typeof Zookeeper.prototype.id
    >;

....

Expected result: Returned animal from repository should include extra properties from dog since the strict setting is set to false.

Current result: Only properties belonging to parent class are returned.

NOTE: If I do the same thing in Mongo DB, everything works as expected.

Thank you.

Acceptance criteria

See #4042 (comment)

At the moment, the data is discarded silently, the framework does not print any warnings about unsupported strict value used with a SQL connector. Personally, I'd like the framework to detect this scenario and print a warning (once for each model), so that developers have easier time troubleshooting the unexpected behavior.

@hacksparrow
Copy link
Contributor

@shreking-around please share a minimal app reproducing the problem, so we can take a look at it.

@bajtos
Copy link
Member

bajtos commented Nov 5, 2019

Let's say we have Animal parent class and then Dog and Chicken child classes. I store them in one table (Table Per Hierarchy Inheritance) called animal.

I don't think that we support Table Per Hierarchy Inheritance in LoopBack.

Your AnimalRepository is configured with Animal model, therefore it is not aware of barkingLevel property. Under the hood, the repository creates a LB3-like Animal model, containing only Animal properties. The PostgreSQL connector is using that LB3-like model when deciding how to map between model properties and SQL table columns. Because barkingLevel is not a known property, it is silently discarded on writes. (This is a general rule - at the moment, all our SQL connector support strict: true mode only.)

Why is the behavior different with MongoDB? MongoDB is an object database that support free-form models, therefore additional properties are correctly written to & retrieved from the database.

There is one thing I find surprising and slightly annoying: the data is discarded silently, the framework does not print any warnings about unsupported strict value used with a SQL connector. Personally, I'd like the framework to detect this scenario and print a warning (once for each model), so that developers have easier time troubleshooting the unexpected behavior.

@shreking-around
Copy link
Author

Thank you for clarifying the issue. Do I understand it correctly that strict: true mode is "hardcoded" in the connector or is it possible to change it via datasource configuration?

@bajtos
Copy link
Member

bajtos commented Nov 15, 2019

Do I understand it correctly that strict: true mode is "hardcoded" in the connector

Yes, strict: true mode is enforced by SQL connectors.

In strict: false mode the connector would not know how to map unknown properties to SQL columns.

@bajtos bajtos added developer-experience Issues affecting ease of use and overall experience of LB users db:PostgreSQL Topics specific to PostgreSQL feature and removed bug labels Nov 15, 2019
@dhmlau dhmlau added the 2020Q1 label Nov 19, 2019
@jannyHou
Copy link
Contributor

Discussion in the estimation meeting:

  • Update the doc to explain that SQL dbs doesn't honour strict: false. They don't deal with unknown properties which don't map to any columns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
db:PostgreSQL Topics specific to PostgreSQL developer-experience Issues affecting ease of use and overall experience of LB users feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants