indexes.test.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import { DataTypes } from '@sequelize/core';
  2. import { expect } from 'chai';
  3. import { sequelize } from '../../support';
  4. const dialect = sequelize.dialect;
  5. describe('Model indexes', () => {
  6. if (dialect.supports.dataTypes.JSONB) {
  7. it('uses a gin index for JSONB attributes by default', () => {
  8. const Model = sequelize.define('event', {
  9. eventData: {
  10. type: DataTypes.JSONB,
  11. field: 'data',
  12. index: true,
  13. },
  14. });
  15. expect(Model.getIndexes()).to.deep.eq([
  16. {
  17. column: 'eventData',
  18. fields: ['data'],
  19. using: 'gin',
  20. name: 'events_data',
  21. },
  22. ]);
  23. });
  24. }
  25. it('should set the unique property when type is unique', () => {
  26. const Model = sequelize.define(
  27. 'm',
  28. {},
  29. {
  30. indexes: [
  31. {
  32. type: 'unique',
  33. fields: ['firstName'],
  34. },
  35. {
  36. type: 'UNIQUE',
  37. fields: ['lastName'],
  38. },
  39. ],
  40. },
  41. );
  42. expect(Model.getIndexes()).to.deep.eq([
  43. {
  44. fields: ['firstName'],
  45. unique: true,
  46. name: 'ms_first_name_unique',
  47. },
  48. {
  49. fields: ['lastName'],
  50. unique: true,
  51. name: 'ms_last_name_unique',
  52. },
  53. ]);
  54. });
  55. // Model.getIndexes() is the only source of truth for indexes
  56. it('does not copy model-level indexes to individual attributes', () => {
  57. const User = sequelize.define(
  58. 'User',
  59. {
  60. username: DataTypes.STRING,
  61. },
  62. {
  63. indexes: [
  64. {
  65. unique: true,
  66. fields: ['username'],
  67. },
  68. ],
  69. },
  70. );
  71. // @ts-expect-error -- "unique" gets removed from built attributes
  72. expect(User.getAttributes().username.unique).to.be.undefined;
  73. });
  74. it('supports declaring an index on an attribute', () => {
  75. const User = sequelize.define('User', {
  76. name: {
  77. type: DataTypes.STRING,
  78. index: true,
  79. },
  80. });
  81. expect(User.getIndexes()).to.deep.eq([
  82. {
  83. column: 'name',
  84. fields: ['name'],
  85. name: 'users_name',
  86. },
  87. ]);
  88. });
  89. it('merges indexes with the same name', () => {
  90. const User = sequelize.define(
  91. 'User',
  92. {
  93. firstName: {
  94. type: DataTypes.STRING,
  95. index: 'name',
  96. },
  97. middleName: {
  98. type: DataTypes.STRING,
  99. index: {
  100. name: 'name',
  101. },
  102. },
  103. lastName: {
  104. type: DataTypes.STRING,
  105. index: 'name',
  106. },
  107. },
  108. {
  109. indexes: [
  110. {
  111. name: 'name',
  112. fields: ['nickname'],
  113. },
  114. ],
  115. },
  116. );
  117. expect(User.getIndexes()).to.deep.eq([
  118. {
  119. fields: ['nickname', 'firstName', 'middleName', 'lastName'],
  120. name: 'name',
  121. },
  122. ]);
  123. });
  124. it('throws if two indexes with the same name use incompatible options', () => {
  125. expect(() => {
  126. sequelize.define('User', {
  127. firstName: {
  128. type: DataTypes.STRING,
  129. index: {
  130. name: 'name',
  131. unique: true,
  132. },
  133. },
  134. lastName: {
  135. type: DataTypes.STRING,
  136. index: {
  137. name: 'name',
  138. unique: false,
  139. },
  140. },
  141. });
  142. }).to.throw(
  143. 'Index "name" has conflicting options: "unique" was defined with different values true and false.',
  144. );
  145. });
  146. it('supports using index & unique at the same time', () => {
  147. const User = sequelize.define('User', {
  148. firstName: {
  149. type: DataTypes.STRING,
  150. unique: true,
  151. index: true,
  152. },
  153. });
  154. expect(User.getIndexes()).to.deep.eq([
  155. {
  156. fields: ['firstName'],
  157. column: 'firstName',
  158. unique: true,
  159. name: 'users_first_name_unique',
  160. },
  161. {
  162. fields: ['firstName'],
  163. column: 'firstName',
  164. name: 'users_first_name',
  165. },
  166. ]);
  167. });
  168. it('supports configuring the index attribute options', () => {
  169. const User = sequelize.define('User', {
  170. firstName: {
  171. type: DataTypes.STRING,
  172. columnName: 'first_name',
  173. index: {
  174. name: 'first_last_name',
  175. unique: true,
  176. attribute: {
  177. collate: 'en_US',
  178. operator: 'text_pattern_ops',
  179. order: 'DESC',
  180. },
  181. },
  182. },
  183. lastName: {
  184. type: DataTypes.STRING,
  185. columnName: 'last_name',
  186. index: {
  187. name: 'first_last_name',
  188. unique: true,
  189. },
  190. },
  191. });
  192. expect(User.getIndexes()).to.deep.eq([
  193. {
  194. fields: [
  195. {
  196. name: 'first_name',
  197. collate: 'en_US',
  198. operator: 'text_pattern_ops',
  199. order: 'DESC',
  200. },
  201. 'last_name',
  202. ],
  203. unique: true,
  204. name: 'first_last_name',
  205. },
  206. ]);
  207. });
  208. });