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.

table name "xxx" specified more than once - objection

See original GitHub issue

I’m using you gist code to check casl rights directly at the database. But when i do a eager or withGraphJoined the interpret function will add a second join for the relation, leading to the error table name "xxx" specified more than once - objection. My ability checks if the user id is either TechnicalContact or AccountOwner.

I see there is a sample which seems to prevent adding a new relation join, but this is not available with objection.

My code:

import {interpret} from '@ucast/sql/objection';

toObjectionQuery<M extends Model>(
  ability: AnyAbility,
  action: string,
  query: QueryBuilder<M, M[]>
): QueryBuilder<M, M[]> {
  const q =
    rulesToQuery(ability, action, query.modelClass(), rule => {
      if (!rule.ast) {
        throw new Error('Unable to create Objection.Query without AST');
      }
      return rule.ast;
    }) || {};

  if (q) {
    const {$and = [], $or = []} = q;
    const condition = new CompoundCondition('and', [
      ...$and,
      new CompoundCondition('or', [...$or] as CompoundCondition[]),
    ] as CompoundCondition[]);

    return interpret(
      condition,
      query as QueryBuilder<Model, Model[]>
    ) as QueryBuilder<M, M[]>;
  }
  return query;
}

const ability = fastify.userAbilities;

// Create query that takes abilities into account
const accountQuery = this.toObjectionQuery<AwsAccountModel>(
  ability,
  'read',
  AwsAccountModel.query().withGraphJoined(
    '[technicalContact,accountOwner,costcenterData]'
  )
);

Error: Results in an sql query like this: table name "technical_contact" specified more than once

and the sql looks somewhat like this:

...
INNER JOIN "users" AS "technical_contact"
ON "technical_contact"."id" = CAST("acc"."data"#>>'{TechnicalContact}' AS text)
LEFT JOIN "users" AS "technical_contact"
ON "technical_contact"."id" = CAST("acc"."data"#>>'{TechnicalContact}' AS text)
...
WHERE (("technical_contact"."id" = ? or "account_owner"."id" = ?))

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
stalniycommented, Jan 20, 2021

Ah, the fix should be trivial if objection provides an api to check whether the table was joined before and retrieve its alias

0reactions
MoJo2600commented, May 4, 2021

Sorry, I was a bit in a hurry yesterday. I should have added more information and not waste your time. Here is everything i figured out so far:

I created a test like this:

  it('doest not join relation again when condition is set on relation field and already joined', () => {
    const condition = new FieldCondition('eq', 'projects.name', 'test')
    const userQuery = User.query().withGraphJoined('[projects]')
    const query = interpret(condition, userQuery)

    expect(query.toKnexQuery().toString()).to.equal(linearize`
      select "users".*
      from "users"
        inner join "projects" on "projects"."user_id" = "users"."id"
      where "projects"."name" = 'test'
    `.trim())
  })

This results in the error: Error: table metadata has not been fetched. Are you trying to call toKnexQuery() for a withGraphJoined query? To make sure the table metadata is fetched see the objection.initialize function.

If I add the initialize method of objection.js like this:

const knex = Knex({ client: 'pg' })
initialize(knex, [User, Project]).then()

it results in an timeout, because the initialize method tries to connect to the database to retrieve the metadata.

So I’m not sure how to properly test the resulting sql from an objection.js query with withGraphJoined as it seems to require a database connection. Objection.js itself is using an integration test with a mock database to test withGraphJoined queries. I’m not a expert in objection.js, but maybe there is another way or I’m on the wrong track on how to add a test for this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQL Server the column name is specified more than once in ...
I got an error like this using EF Core. 'PropertyNameID' is specified more than once in the SET clause or column list of...
Read more >
WITH common_table_expression (Transact-SQL) - SQL Server
Specifies a column name in the common table expression. ... Specifying more than one WITH clause in a CTE isn't allowed.
Read more >
Cannot find the object "xxx" because it does not exist or you ...
For the first pipeline run, remove the Pre-copy script. After pipeline is run once, tables would be created. Now add the Truncate query...
Read more >
SQL20500 - SQL20999 - IBM
Explanation. A dynamic statement name is specified in a cursor value constructor that: also specifies one or more named parameters in a cursor...
Read more >
CA Datacom/DB System Tables Reference Guide
This guide is intended for those responsible for one or more of the following: ... database ID matching the SYSTEMDBID, the CA Datacom...
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