utils.test.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { DataTypes, Op, cast, fn } from '@sequelize/core';
  2. import { expect } from 'chai';
  3. import { beforeAll2, getTestDialectTeaser, sequelize, setResetMode } from './support';
  4. const dialectName = sequelize.dialect.name;
  5. describe(getTestDialectTeaser('fn()'), () => {
  6. setResetMode('none');
  7. const vars = beforeAll2(async () => {
  8. const Airplane = sequelize.define('Airplane', {
  9. wings: DataTypes.INTEGER,
  10. engines: DataTypes.INTEGER,
  11. });
  12. await Airplane.sync({ force: true });
  13. await Airplane.bulkCreate([
  14. {
  15. wings: 2,
  16. engines: 0,
  17. },
  18. {
  19. wings: 4,
  20. engines: 1,
  21. },
  22. {
  23. wings: 2,
  24. engines: 2,
  25. },
  26. ]);
  27. return { Airplane };
  28. });
  29. // some dialects return the result of arithmetic functions (SUM, COUNT) as integer & floats, others as bigints & decimals.
  30. const arithmeticAsNumber = dialectName === 'sqlite3' || dialectName === 'db2';
  31. if (dialectName !== 'mssql' && dialectName !== 'ibmi') {
  32. it('accepts condition object (with cast)', async () => {
  33. const type = dialectName === 'mysql' ? 'unsigned' : 'int';
  34. const [airplane] = await vars.Airplane.findAll({
  35. attributes: [
  36. [fn('COUNT', '*'), 'count'],
  37. [
  38. fn(
  39. 'SUM',
  40. cast(
  41. {
  42. engines: 1,
  43. },
  44. type,
  45. ),
  46. ),
  47. 'count-engines',
  48. ],
  49. [
  50. fn(
  51. 'SUM',
  52. cast(
  53. {
  54. [Op.or]: {
  55. engines: {
  56. [Op.gt]: 1,
  57. },
  58. wings: 4,
  59. },
  60. },
  61. type,
  62. ),
  63. ),
  64. 'count-engines-wings',
  65. ],
  66. ],
  67. });
  68. // These values are returned as strings
  69. // See https://github.com/sequelize/sequelize/issues/10533#issuecomment-1254141892 for more details
  70. expect(airplane.get('count')).to.equal(arithmeticAsNumber ? 3 : '3');
  71. expect(airplane.get('count-engines')).to.equal(arithmeticAsNumber ? 1 : '1');
  72. expect(airplane.get('count-engines-wings')).to.equal(arithmeticAsNumber ? 2 : '2');
  73. });
  74. }
  75. if (dialectName !== 'mssql' && dialectName !== 'postgres' && dialectName !== 'ibmi') {
  76. it('accepts condition object (auto casting)', async () => {
  77. const [airplane] = await vars.Airplane.findAll({
  78. attributes: [
  79. [fn('COUNT', '*'), 'count'],
  80. [
  81. fn('SUM', {
  82. engines: 1,
  83. }),
  84. 'count-engines',
  85. ],
  86. [
  87. fn('SUM', {
  88. [Op.or]: {
  89. engines: {
  90. [Op.gt]: 1,
  91. },
  92. wings: 4,
  93. },
  94. }),
  95. 'count-engines-wings',
  96. ],
  97. ],
  98. });
  99. // These values are returned as strings
  100. // See https://github.com/sequelize/sequelize/issues/10533#issuecomment-1254141892 for more details
  101. // Except for SQLite, which returns them as JS numbers, which the above issue will unify
  102. expect(airplane.get('count')).to.equal(arithmeticAsNumber ? 3 : '3');
  103. expect(airplane.get('count-engines')).to.equal(arithmeticAsNumber ? 1 : '1');
  104. expect(airplane.get('count-engines-wings')).to.equal(arithmeticAsNumber ? 2 : '2');
  105. });
  106. }
  107. });