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

How to specify database schemas for different models? #85

Closed
ArsalanDotMe opened this issue Feb 17, 2016 · 13 comments
Closed

How to specify database schemas for different models? #85

ArsalanDotMe opened this issue Feb 17, 2016 · 13 comments

Comments

@ArsalanDotMe
Copy link

I've been at it for hours and still can't get it to work. I have a postgres database with two schemas, lets say s1 and s2 such that my table names are then s1.name or s2.name.

Now, if I rewrite all tablename references with schema included, objection relations stop working saying that I must specify the original table in either the from or to clause.
I have also tried subclassing Model and overriding the query method with something like this:

class ApiModel extends Model {
}
ApiModel.query = function query() {
  return Model.query.call(this).withSchema('s1');
};

But when I analyze the queries, objection is still making queries without the schema applied to table names. How do I handle default schemas for my models?

@koskimas
Copy link
Collaborator

So you have two schemas and tables that only exist in one but not the other and you want to create models that always use a certain schema? And there are relations between the models so that Schema1Model can have, lets say, HasOneRelation to Schema2Model?

What version of objection are you using?

@ArsalanDotMe
Copy link
Author

There isn't currently a case where a model in Schema1 may have a relation with Schema2. In my case, I have a database shared by several internal applications, each storing its data inside its own schema. Models for each application will use a certain schema and will have relationships with other models of the same application on the same schema.

EDIT: Using version 0.4.0

@koskimas
Copy link
Collaborator

Ok. Can you check the objection version also?

@ArsalanDotMe
Copy link
Author

The objection version is 0.4.0.

@koskimas
Copy link
Collaborator

Can you try to install npm install objection@next and check if the problems continue? There has just been some major changes to how withSchema works in the 0.5.0 alpha builds.

@ArsalanDotMe
Copy link
Author

Okay but how should I specify my schemas for my models?
As far as I understand, I have two options:

  1. Override the Model class in a way that applies withSchema to the QueryBuilder.
  2. Specify the schema inside tablenames. E.g.
class MyModel extends Model {
   static get tableName() { return 'schema.tablename'; }
}

Which way should I go with? I'm leaning towards the first but I'm not sure how to accomplish it.

@koskimas
Copy link
Collaborator

Setting the schema to the tableName doesn't work. knex doesn't interpret the dot as a schema separator, but as a part of the table name.

You can try implementing your own query builder class:

class DefaultSchemaQueryBuilder extends objection.QueryBuilder {
  constructor(modelClass) {
    super(modelClass);
    if (modelClass.defaultSchema) {
      this.withSchema(modelClass.defaultSchema);
    }
  }
}

objection.Model.QueryBuilder = DefaultSchemaQueryBuilder;
objection.Model.RelatedQueryBuilder = DefaultSchemaQueryBuilder;

and then in your models:

class Schema1Model extends Model {
  static get defaultSchema() {
    return 's1';
  }
}

class Schema2Model extends Model {
  static get defaultSchema() {
    return 's2';
  }
}

The problem may be caused by the fact that not all queries are created using the Model.query() method.

@ArsalanDotMe
Copy link
Author

Thanks for the quick response! I'm trying this now with the latest version.

@ArsalanDotMe
Copy link
Author

Nice!
It works with the version 0.5.0-alpha.2!
I tried doing something similar before but I wasn't overriding the RelatedQueryBuilder property. I'll try downgrading to the latest stable release and report if it still works.

@ArsalanDotMe
Copy link
Author

Works in 0.4.0 too. Thanks again for the quick response. You're awesome!

@koskimas
Copy link
Collaborator

Great! ❤️

@paseaf
Copy link

paseaf commented Jan 28, 2020

Is this solution still relevant for Objection version 2.X.X?

@parker789
Copy link

Hey @koskimas - sorry to bring up such an old thread here, but myself and team are at point where we need to make a decision on whether or not we can move forward using Objection as our ORM due to an issue related to what's written here. My problem lies in this question you asked above:

And there are relations between the models so that Schema1Model can have, lets say, HasOneRelation to Schema2Model?

I was able to get a somewhat working solution, although with everything I've read it seems to be a hack, by implementing this from another issue I read through:

class SomeModel extends Model {
  static get tableName {
    return 'schemaOne.someModels'
  }

  static get relationMapping() {
    return {
      relatedModel: {
        relation: Model.HasOneRelation,
        modelClass: 'RelatedModel',
        join: {
          from: 'schemaOne.someModels.id',
          to: 'schemaTwo.relatedModels.someModelsId',
        },
      },
    }
  }
}

This seemed to work when just querying, but when mixed with objection-find and an orderBy, the generated sql had a mismatch between the aliased table: [schema1.someModels], and in the select: [schema1].[someModels].[id]. Is this supported in some way?

Thanks!

Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 7, 2022
https://eaflood.atlassian.net/browse/WATER-3829

Our current solution for working with schemas is to specify the schema name in the `tableName()` getter respone.

That has been working fine when just working in isolation. But our [first attempt](#43) to generate a query that uses relations is erroring.

```text
Licence.relationMappings.charge-versions: join: either `from` or `to` must point to the owner model table and the other one to the related table. It might be that specified table 'water.charge_versions` is not correct
```

Some digging later we found [this issue](Vincit/objection.js#85) which highlights our solution won't work

> Setting the schema to the tableName doesn't work. knex doesn't interpret the dot as a schema separator, but as a part of the table name.

So, this change implements the solution documented in that issue. We extend Objection's `QueryBuilder` with one that defaults all queries to use `withSchema()` taking the schema to use from a new model property `defaultSchema`.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 7, 2022
Ok, so it was actually because we had not specified the table name properly. It all works if we correct that. So, no need to implement the solution defined in Vincit/objection.js#85; knex seems to be handling fine the use of dot notation.

It might not _truly_ be using schema. But if we stick to this format it will give us the flexibility of making relationships across schemas. So, this is a mid-PR change in direction. Now we're just fixing things rather than implementing a new 'ways-of-working'.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 8, 2022
https://eaflood.atlassian.net/browse/WATER-3829

Our [first attempt](#43) to generate a query that uses relations is erroring.

```text
Licence.relationMappings.charge-versions: join: either `from` or `to` must point to the owner model table and the other one to the related table. It might be that specified table 'water.charge_versions` is not correct
```

Initially, we thought it was the way we're working with schemas as highlighted in [this issue](Vincit/objection.js#85). But actually, it was just a typo.

So, this change fixes that. It also corrects some other details of the relationships and adds some tests just to ensure they are working as expected.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 22, 2022
In a [previous change](#70) we had to fix our Objection implementation because we realised

- our way of handling multiple schemas (using `tableName`) was [invalid](Vincit/objection.js#85 (comment))
- we were using the wrong case (snake vs camel) in most places. Under the hood Knex was fine, but once we leant into Objection relationships `withGraphFetched()` was bringing back nothing

What this highlighted was our existing model tests weren't really doing anything. Sure, a query can get generated but till you run them and confirm a result you can't be sure they are working as expected.

So, this change updates our model relationship tests to insert some data and confirm we get expected results back.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 22, 2022
In a [previous change](#70) we had to fix our Objection implementation because we realised

- our way of handling multiple schemas (using `tableName`) was [invalid](Vincit/objection.js#85 (comment))
- we were using the wrong case (snake vs camel) in most places. Under the hood Knex was fine, but once we leant into Objection relationships `withGraphFetched()` was bringing back nothing

What this highlighted was our existing model tests weren't really doing anything. Sure, a query can get generated but till you run them and confirm a result you can't be sure they are working as expected.

So, this change updates our model relationship tests to insert some data and confirm we get expected results back.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 23, 2022
In a [previous change](#70) we had to fix our Objection implementation because we realised

- our way of handling multiple schemas (using `tableName`) was [invalid](Vincit/objection.js#85 (comment))
- we were using the wrong case (snake vs camel) in most places. Under the hood Knex was fine, but once we leant into Objection relationships `withGraphFetched()` was bringing back nothing

What this highlighted was our existing model tests weren't really doing anything. Sure, a query can get generated but till you run them and confirm a result you can't be sure they are working as expected.

So, this change updates our model relationship tests to insert some data and confirm we get expected results back.
Cruikshanks added a commit to DEFRA/water-abstraction-system that referenced this issue Dec 23, 2022
In a [previous change](#70) we had to fix our Objection implementation because we realised

- our way of handling multiple schemas (using `tableName`) was [invalid](Vincit/objection.js#85 (comment))
- we were using the wrong case (snake vs camel) in most places. Under the hood Knex was fine, but once we leant into Objection relationships `withGraphFetched()` was bringing back nothing

What this highlighted was our existing model tests weren't really doing anything. Sure, a query can get generated but till you run them and confirm a result you can't be sure they are working as expected.

So, this change updates our model relationship tests to insert some data and confirm we get the expected results back.

**Notes - includes a couple of fixes in the models and how the relationships were defined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants