sequelize / sequelize

Feature-rich ORM for modern Node.js and TypeScript, it supports PostgreSQL (with JSON and JSONB support), MySQL, MariaDB, SQLite, MS SQL Server, Snowflake, Oracle DB (v6), DB2 and DB2 for IBM i.
https://sequelize.org/
MIT License
29.58k stars 4.28k forks source link

Eager Loading VIRTUAL field when attributes specified ignores field #10240

Open fraywing opened 5 years ago

fraywing commented 5 years ago

What are you doing?

Including a model with a VIRTUAL field specified in a collection gets ignored when attributes are specified in any way.

const Game = sequelizeConfig.define(
  'Game',
    {
      Thing: {
        type: Sequelize.VIRTUAL(Sequelize.STRING),
        get() {
          return 'adsadasd';
        }

      },
      Released: Sequelize.BOOLEAN,
      Price: Sequelize.STRING,
      updatedAt: Sequelize.DATE,
      createdAt: Sequelize.DATE,
      deletedAt: Sequelize.DATE
    }
);

Project.findAll({
   include: [
      {
        model: Game,
        as: 'Game',
       attributes: ['ID', 'Thing']
     }
   ]
});

What do you expect to happen?

Project to return Thing but only returns ID (seems like it's skipping virtual fields)

What is actually happening?

Only returns ID (seems like it's skipping virtual fields)

Dialect: postgres Dialect version: 7.6.1 Database version: 11 Sequelize version: 5.0.0-beta.14 Tested with latest release: Yes

Note : Your issue may be ignored OR closed by maintainers if it's not tested against latest version OR does not follow issue template.

knoxcard commented 5 years ago

Desperately been wanting this, VIRTUAL columns absolutely need to be inclusive in attributes.

tsasaki609 commented 5 years ago

I didn't reproduce it with the following code.

Dialect: postgres Database(Docker): postgres-95 Sequelize version: 5.0.0-beta.14

Code:

const sequelize = new Sequelize('sequelize_test', 'sequelize_test', 'sequelize_test', {
  showWarnings: true,
  host: '127.0.0.1',
  port: '8990',
  dialect: 'postgres',
  operatorsAliases: false,
  logging: console.log,
  pool: {
    max: 1,
    min: 1,
    acquire: 30000,
    idle: 10000
  }
});

const Project = sequelize.define('Project');
const Game = sequelize.define(
  'Game',
  {
    Thing: {
      type: Sequelize.VIRTUAL(Sequelize.STRING),
      get() {
        return 'adsadasd';
      }
    },
    Released: Sequelize.BOOLEAN,
    Price: Sequelize.STRING,
    updatedAt: Sequelize.DATE,
    createdAt: Sequelize.DATE,
    deletedAt: Sequelize.DATE
  }
);

Project.hasMany(Game);

sequelize.sync({force: true }).then(() => {
  return Promise.all([Project.create(), Game.create({'Thing': 'test'})]);
}).then(result => {
  const [p, g] = result;
  return p.addGame(g);
}).then(() => {
  return Project.findAll({
    include: [
      {
        model: Game,
        as: 'Games',
        attributes: ['id', 'Thing']
      }]
  });
}).then(result => {
  console.log(result[0].Games[0].id);
  console.log(result[0].Games[0].Thing);
});

Output:

1
adsadasd

As far as looking at the output, both ID and Thing returns. If I misunderstand the issue, please let me know.

exsesx commented 5 years ago

@tsasaki609 You get a virtual attribute, because you literally get it (result[0].Games[0].Thing).

Virtual attributes are ignored if you, for example, return result to the client...

See #10552

tsasaki609 commented 5 years ago

@exsesx What does the client mean? The value of VIRTUAL columns is not ignored if it means to receive return value from a method.

function query() {
  return sequelize.sync({force: true }).then(() => {
    return Promise.all([Project.create(), Game.create({'Thing': 'test'})]);
  }).then(result => {
    const [p, g] = result;
    return p.addGame(g);
  }).then(() => {
    return Project.findAll({
      include: [
        {
          model: Game,
          as: 'Games',
          attributes: ['id', 'Thing']
        }]
    });
  });
}

async function client() {
  const result = await query();
  console.log(result[0].Games[0].id);
  console.log(result[0].Games[0].Thing);
}

client();

Output:

1
adsadasd
papb commented 5 years ago

Is this still an issue? Can someone please test with latest sequelize version (5.12.0)?

fzn0x commented 2 years ago

Is this still an issue? Can someone please test with latest sequelize version (5.12.0)?

This is still an issue until now. (v6.11.0)

We can get the virtual field value but we can't see if the virtual field is exist in _options->attributes.

fzn0x commented 2 years ago

@sdepold @WikiRik I added it to important issue, self-assign is welcome. I will try to fix the problem on weekend.

guilhermehalvescode commented 2 years ago

Is the problem solved at newer versions? I'm currently using 6.3.5 and still facing it

jonrhine commented 2 years ago

I'm also running into this issue at 6.4.1, virtual field is missing when specifying attributes

psiservices-collin-stowell commented 2 years ago

I can confirm this is still an issue as of 6.21.3.

Oddly enough this syntax works for virtuals:

attributes: { include: ['myVirtualField'] }

And this won't:

attributes: ['myVirtualField']