Vincit/objection.js

$fetchGraph returning empty array when it should return data

Open

#2258 aperta il 13 apr 2022

Vedi su GitHub
 (7 commenti) (0 reazioni) (0 assegnatari)JavaScript (663 fork)batch import
bughelp wanted

Metriche repository

Star
 (7146 star)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

I tried asking this in Gitter several weeks ago but didn't get very far.

I'm having a strange issue with $fetchGraph() that I'm sure is something I'm doing wrong. Given these (simplified) models:

class User extends Model {
  static get tableName() {
    return 'users';
  }

  static get relationMappings() {
    return {
      hardwareTokenRegistrations: {
        relation: HasManyRelation,
        modelClass: HardwareTokenRegistration,
        join: {
          from: 'users.id',
          to: 'hardware_token_registrations.user_id',
        },
      },
    };
  }
};

class HardwareTokenRegistration extends Model {
  static get tableName() {
    return 'hardware_token_registrations';
  }

  static get relationMappings() {
    return {
      hardwareToken: {
        relation: HasOneRelation,
        modelClass: HardwareToken,
        join: {
          from: 'hardware_token_registrations.hardware_token_id',
          to: 'hardware_tokens.id',
        },
      },
      user: {
        relation: HasOneRelation,
        modelClass: User,
        join: {
          from: 'hardware_token_registrations.user_id',
          to: 'users.id',
        },
      },
    };
  }
};

Schema:

mfa=# \d users
                                       Table "public.users"
   Column   |           Type           | Collation | Nullable |              Default
------------+--------------------------+-----------+----------+-----------------------------------
 id         | integer                  |           | not null | nextval('users_id_seq'::regclass)
 uuid       | character varying(255)   |           | not null |
 username   | character varying(255)   |           | not null |
 created_at | timestamp with time zone |           |          | CURRENT_TIMESTAMP
 updated_at | timestamp with time zone |           |          | CURRENT_TIMESTAMP
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "users_username_index" btree (username)
    "users_username_unique" UNIQUE CONSTRAINT, btree (username)
    "users_uuid_index" btree (uuid)
    "users_uuid_unique" UNIQUE CONSTRAINT, btree (uuid)
Referenced by:
    TABLE "hardware_token_registrations" CONSTRAINT "hardware_token_registrations_user_id_foreign" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
... others removed ...

mfa=# \d hardware_token_registrations;
                                          Table "public.hardware_token_registrations"
      Column       |           Type           | Collation | Nullable |                         Default
-------------------+--------------------------+-----------+----------+----------------------------------------------------------
 id                | integer                  |           | not null | nextval('hardware_token_registrations_id_seq'::regclass)
 user_id           | integer                  |           | not null |
 hardware_token_id | integer                  |           | not null |
 validation_code   | character varying(255)   |           | not null |
 created_at        | timestamp with time zone |           |          | CURRENT_TIMESTAMP
 updated_at        | timestamp with time zone |           |          | CURRENT_TIMESTAMP
Indexes:
    "hardware_token_registrations_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "hardware_token_registrations_hardware_token_id_foreign" FOREIGN KEY (hardware_token_id) REFERENCES hardware_tokens(id)
    "hardware_token_registrations_user_id_foreign" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE

I have an instance of User and want to fetch its HardwareTokenRegistrations:

let user = await User.query().findById(1);
let userWithRegistrations = await user.$fetchGraph('hardwareTokenRegistrations');

/* 
returns:

User {
  id: 1,
  uuid: 'grahamb',
  username: 'grahamb',
  createdAt: 2021-12-16T23:57:14.000Z,
  updatedAt: 2022-03-30T20:56:59.239Z,
  hardwareTokenRegistrations: []
}
*/

Note that the hardwareTokenRegistrations array is empty. In reality, there is one related record.

The query generated by the $fetchGraph query is:

{
  method: 'select',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [ 1 ],
  __knexQueryUid: 'qCYLMv1SfgVFnMl4FCa_p',
  sql: 'select "hardware_token_registrations".* from "hardware_token_registrations" where "hardware_token_registrations"."user_id" in (?)'
}

If I run the same query manually against the database, the records are retrieved:

mfa=# select "hardware_token_registrations".* from "hardware_token_registrations" where "hardware_token_registrations"."user_id" in (1);
-[ RECORD 1 ]-----+-----------------------------
id                | 1
user_id           | 1
hardware_token_id | 4
validation_code   | 851728
created_at        | 2021-12-16 23:57:14+00
updated_at        | 2022-03-14 21:52:58.75705+00

I can't figure out what I'm doing wrong here. Any clues?

Guida contributor