add-constraint-query.test.ts 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. import { Deferrable, Op } from '@sequelize/core';
  2. import { createSequelizeInstance, expectsql, sequelize } from '../../support';
  3. const dialect = sequelize.dialect;
  4. const notSupportedError = new Error(
  5. `Add constraint queries are not supported by ${dialect.name} dialect`,
  6. );
  7. const checkNotSupportedError = new Error(
  8. `Check constraints are not supported by ${dialect.name} dialect`,
  9. );
  10. const defaultNotSupportedError = new Error(
  11. `Default constraints are not supported by ${dialect.name} dialect`,
  12. );
  13. const deferrableNotSupportedError = new Error(
  14. `Deferrable constraints are not supported by ${dialect.name} dialect`,
  15. );
  16. const onUpdateNotSupportedError = new Error(
  17. `Foreign key constraint with onUpdate is not supported by ${dialect.name} dialect`,
  18. );
  19. describe('QueryGenerator#addConstraintQuery', () => {
  20. const queryGenerator = sequelize.queryGenerator;
  21. it('throws an error if invalid type', () => {
  22. expectsql(
  23. () => {
  24. return queryGenerator.addConstraintQuery('myTable', {
  25. // @ts-expect-error -- We're testing invalid options
  26. type: 'miss-typed',
  27. fields: ['otherId'],
  28. });
  29. },
  30. {
  31. default: new Error(
  32. `Constraint type miss-typed is not supported by ${dialect.name} dialect`,
  33. ),
  34. sqlite3: notSupportedError,
  35. },
  36. );
  37. });
  38. describe('CHECK constraints', () => {
  39. it('generates a query that adds a check constraint with a name', () => {
  40. expectsql(
  41. () =>
  42. queryGenerator.addConstraintQuery('myTable', {
  43. name: 'check',
  44. type: 'CHECK',
  45. fields: ['age'],
  46. where: { age: { [Op.gte]: 10 } },
  47. }),
  48. {
  49. default: 'ALTER TABLE [myTable] ADD CONSTRAINT [check] CHECK ([age] >= 10)',
  50. sqlite3: notSupportedError,
  51. snowflake: checkNotSupportedError,
  52. },
  53. );
  54. });
  55. it('generates a query that adds a check constraint with an array of values', () => {
  56. expectsql(
  57. () =>
  58. queryGenerator.addConstraintQuery('myTable', {
  59. name: 'check',
  60. type: 'CHECK',
  61. fields: ['role'],
  62. where: { age: ['admin', 'user', 'guest'] },
  63. }),
  64. {
  65. default: `ALTER TABLE [myTable] ADD CONSTRAINT [check] CHECK ([age] IN ('admin', 'user', 'guest'))`,
  66. mssql: `ALTER TABLE [myTable] ADD CONSTRAINT [check] CHECK ([age] IN (N'admin', N'user', N'guest'))`,
  67. sqlite3: notSupportedError,
  68. snowflake: checkNotSupportedError,
  69. },
  70. );
  71. });
  72. it('generates a query that adds a check constraint', () => {
  73. expectsql(
  74. () =>
  75. queryGenerator.addConstraintQuery('myTable', {
  76. type: 'CHECK',
  77. fields: ['age'],
  78. where: { age: { [Op.gte]: 10 } },
  79. }),
  80. {
  81. default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_age_ck] CHECK ([age] >= 10)',
  82. sqlite3: notSupportedError,
  83. snowflake: checkNotSupportedError,
  84. },
  85. );
  86. });
  87. it('generates a query that adds a check constraint for a model', () => {
  88. const MyModel = sequelize.define('MyModel', {});
  89. expectsql(
  90. () =>
  91. queryGenerator.addConstraintQuery(MyModel, {
  92. type: 'CHECK',
  93. fields: ['age'],
  94. where: { age: { [Op.gte]: 10 } },
  95. }),
  96. {
  97. default: 'ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_age_ck] CHECK ([age] >= 10)',
  98. sqlite3: notSupportedError,
  99. snowflake: checkNotSupportedError,
  100. },
  101. );
  102. });
  103. it('generates a query that adds a check constraint for a model definition', () => {
  104. const MyModel = sequelize.define('MyModel', {});
  105. const myDefinition = MyModel.modelDefinition;
  106. expectsql(
  107. () =>
  108. queryGenerator.addConstraintQuery(myDefinition, {
  109. type: 'CHECK',
  110. fields: ['age'],
  111. where: { age: { [Op.gte]: 10 } },
  112. }),
  113. {
  114. default: 'ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_age_ck] CHECK ([age] >= 10)',
  115. sqlite3: notSupportedError,
  116. snowflake: checkNotSupportedError,
  117. },
  118. );
  119. });
  120. it('generates a query that adds a check constraint with schema', () => {
  121. expectsql(
  122. () =>
  123. queryGenerator.addConstraintQuery(
  124. { tableName: 'myTable', schema: 'mySchema' },
  125. { type: 'CHECK', fields: ['age'], where: { age: { [Op.gte]: 10 } } },
  126. ),
  127. {
  128. default:
  129. 'ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_age_ck] CHECK ([age] >= 10)',
  130. sqlite3: notSupportedError,
  131. snowflake: checkNotSupportedError,
  132. },
  133. );
  134. });
  135. it('generates a query that adds a check constraint with default schema', () => {
  136. expectsql(
  137. () =>
  138. queryGenerator.addConstraintQuery(
  139. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  140. { type: 'CHECK', fields: ['age'], where: { age: { [Op.gte]: 10 } } },
  141. ),
  142. {
  143. default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_age_ck] CHECK ([age] >= 10)',
  144. sqlite3: notSupportedError,
  145. snowflake: checkNotSupportedError,
  146. },
  147. );
  148. });
  149. it('generates a query that adds a check constraint with globally set schema', () => {
  150. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  151. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  152. expectsql(
  153. () =>
  154. queryGeneratorSchema.addConstraintQuery('myTable', {
  155. type: 'CHECK',
  156. fields: ['age'],
  157. where: { age: { [Op.gte]: 10 } },
  158. }),
  159. {
  160. default:
  161. 'ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_age_ck] CHECK ([age] >= 10)',
  162. sqlite3: notSupportedError,
  163. snowflake: checkNotSupportedError,
  164. },
  165. );
  166. });
  167. it('generates a query that adds a check constraint with schema and custom delimiter argument', () => {
  168. // This test is only relevant for dialects that do not support schemas
  169. if (dialect.supports.schemas) {
  170. return;
  171. }
  172. expectsql(
  173. () =>
  174. queryGenerator.addConstraintQuery(
  175. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  176. { type: 'CHECK', fields: ['age'], where: { age: { [Op.gte]: 10 } } },
  177. ),
  178. {
  179. sqlite3: notSupportedError,
  180. },
  181. );
  182. });
  183. });
  184. describe('DEFAULT constraints', () => {
  185. it('generates a query that adds a default constraint with a name', () => {
  186. expectsql(
  187. () =>
  188. queryGenerator.addConstraintQuery('myTable', {
  189. name: 'default',
  190. type: 'DEFAULT',
  191. fields: ['role'],
  192. defaultValue: 'guest',
  193. }),
  194. {
  195. default: defaultNotSupportedError,
  196. mssql: `ALTER TABLE [myTable] ADD CONSTRAINT [default] DEFAULT (N'guest') FOR [role]`,
  197. sqlite3: notSupportedError,
  198. },
  199. );
  200. });
  201. it('generates a query that adds a default constraint', () => {
  202. expectsql(
  203. () =>
  204. queryGenerator.addConstraintQuery('myTable', {
  205. type: 'DEFAULT',
  206. fields: ['role'],
  207. defaultValue: 'guest',
  208. }),
  209. {
  210. default: defaultNotSupportedError,
  211. mssql: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_role_df] DEFAULT (N'guest') FOR [role]`,
  212. sqlite3: notSupportedError,
  213. },
  214. );
  215. });
  216. it('generates a query that adds a default constraint for a model', () => {
  217. const MyModel = sequelize.define('MyModel', {});
  218. expectsql(
  219. () =>
  220. queryGenerator.addConstraintQuery(MyModel, {
  221. type: 'DEFAULT',
  222. fields: ['role'],
  223. defaultValue: 'guest',
  224. }),
  225. {
  226. default: defaultNotSupportedError,
  227. mssql: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_role_df] DEFAULT (N'guest') FOR [role]`,
  228. sqlite3: notSupportedError,
  229. },
  230. );
  231. });
  232. it('generates a query that adds a default constraint for a model definition', () => {
  233. const MyModel = sequelize.define('MyModel', {});
  234. const myDefinition = MyModel.modelDefinition;
  235. expectsql(
  236. () =>
  237. queryGenerator.addConstraintQuery(myDefinition, {
  238. type: 'DEFAULT',
  239. fields: ['role'],
  240. defaultValue: 'guest',
  241. }),
  242. {
  243. default: defaultNotSupportedError,
  244. mssql: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_role_df] DEFAULT (N'guest') FOR [role]`,
  245. sqlite3: notSupportedError,
  246. },
  247. );
  248. });
  249. it('generates a query that adds a default constraint with schema', () => {
  250. expectsql(
  251. () =>
  252. queryGenerator.addConstraintQuery(
  253. { tableName: 'myTable', schema: 'mySchema' },
  254. { type: 'DEFAULT', fields: ['role'], defaultValue: 'guest' },
  255. ),
  256. {
  257. default: defaultNotSupportedError,
  258. mssql: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_role_df] DEFAULT (N'guest') FOR [role]`,
  259. sqlite3: notSupportedError,
  260. },
  261. );
  262. });
  263. it('generates a query that adds a default constraint with default schema', () => {
  264. expectsql(
  265. () =>
  266. queryGenerator.addConstraintQuery(
  267. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  268. { type: 'DEFAULT', fields: ['role'], defaultValue: 'guest' },
  269. ),
  270. {
  271. default: defaultNotSupportedError,
  272. mssql: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_role_df] DEFAULT (N'guest') FOR [role]`,
  273. sqlite3: notSupportedError,
  274. },
  275. );
  276. });
  277. it('generates a query that adds a default constraint with globally set schema', () => {
  278. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  279. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  280. expectsql(
  281. () =>
  282. queryGeneratorSchema.addConstraintQuery('myTable', {
  283. type: 'DEFAULT',
  284. fields: ['role'],
  285. defaultValue: 'guest',
  286. }),
  287. {
  288. default: defaultNotSupportedError,
  289. mssql: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_role_df] DEFAULT (N'guest') FOR [role]`,
  290. sqlite3: notSupportedError,
  291. },
  292. );
  293. });
  294. it('generates a query that adds a default constraint with schema and custom delimiter argument', () => {
  295. // This test is only relevant for dialects that do not support schemas
  296. if (dialect.supports.schemas) {
  297. return;
  298. }
  299. expectsql(
  300. () =>
  301. queryGenerator.addConstraintQuery(
  302. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  303. { type: 'DEFAULT', fields: ['role'], defaultValue: 'guest' },
  304. ),
  305. {
  306. sqlite3: notSupportedError,
  307. },
  308. );
  309. });
  310. });
  311. describe('UNIQUE constraints', () => {
  312. it('generates a query that adds a unique constraint with a name', () => {
  313. expectsql(
  314. () =>
  315. queryGenerator.addConstraintQuery('myTable', {
  316. name: 'unique',
  317. type: 'UNIQUE',
  318. fields: ['username'],
  319. }),
  320. {
  321. default: `ALTER TABLE [myTable] ADD CONSTRAINT [unique] UNIQUE ([username])`,
  322. sqlite3: notSupportedError,
  323. },
  324. );
  325. });
  326. it('generates a query that adds a deferred unique constraint', () => {
  327. expectsql(
  328. () =>
  329. queryGenerator.addConstraintQuery('myTable', {
  330. type: 'UNIQUE',
  331. fields: ['username'],
  332. deferrable: Deferrable.INITIALLY_IMMEDIATE,
  333. }),
  334. {
  335. default: deferrableNotSupportedError,
  336. sqlite3: notSupportedError,
  337. 'postgres snowflake': `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_uk] UNIQUE ([username]) DEFERRABLE INITIALLY IMMEDIATE`,
  338. },
  339. );
  340. });
  341. it('generates a query that adds a unique constraint with multiple columns', () => {
  342. expectsql(
  343. () =>
  344. queryGenerator.addConstraintQuery('myTable', {
  345. type: 'UNIQUE',
  346. fields: ['first_name', 'last_name'],
  347. }),
  348. {
  349. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_first_name_last_name_uk] UNIQUE ([first_name], [last_name])`,
  350. sqlite3: notSupportedError,
  351. },
  352. );
  353. });
  354. it('generates a query that adds a unique constraint', () => {
  355. expectsql(
  356. () =>
  357. queryGenerator.addConstraintQuery('myTable', { type: 'UNIQUE', fields: ['username'] }),
  358. {
  359. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_uk] UNIQUE ([username])`,
  360. sqlite3: notSupportedError,
  361. },
  362. );
  363. });
  364. it('generates a query that adds a unique constraint for a model', () => {
  365. const MyModel = sequelize.define('MyModel', {});
  366. expectsql(
  367. () => queryGenerator.addConstraintQuery(MyModel, { type: 'UNIQUE', fields: ['username'] }),
  368. {
  369. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_username_uk] UNIQUE ([username])`,
  370. sqlite3: notSupportedError,
  371. },
  372. );
  373. });
  374. it('generates a query that adds a unique constraint for a model definition', () => {
  375. const MyModel = sequelize.define('MyModel', {});
  376. const myDefinition = MyModel.modelDefinition;
  377. expectsql(
  378. () =>
  379. queryGenerator.addConstraintQuery(myDefinition, { type: 'UNIQUE', fields: ['username'] }),
  380. {
  381. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_username_uk] UNIQUE ([username])`,
  382. sqlite3: notSupportedError,
  383. },
  384. );
  385. });
  386. it('generates a query that adds a unique constraint with schema', () => {
  387. expectsql(
  388. () =>
  389. queryGenerator.addConstraintQuery(
  390. { tableName: 'myTable', schema: 'mySchema' },
  391. { type: 'UNIQUE', fields: ['username'] },
  392. ),
  393. {
  394. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_username_uk] UNIQUE ([username])`,
  395. sqlite3: notSupportedError,
  396. },
  397. );
  398. });
  399. it('generates a query that adds a unique constraint with unique schema', () => {
  400. expectsql(
  401. () =>
  402. queryGenerator.addConstraintQuery(
  403. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  404. { type: 'UNIQUE', fields: ['username'] },
  405. ),
  406. {
  407. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_uk] UNIQUE ([username])`,
  408. sqlite3: notSupportedError,
  409. },
  410. );
  411. });
  412. it('generates a query that adds a unique constraint with globally set schema', () => {
  413. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  414. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  415. expectsql(
  416. () =>
  417. queryGeneratorSchema.addConstraintQuery('myTable', {
  418. type: 'UNIQUE',
  419. fields: ['username'],
  420. }),
  421. {
  422. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_username_uk] UNIQUE ([username])`,
  423. sqlite3: notSupportedError,
  424. },
  425. );
  426. });
  427. it('generates a query that adds a unique constraint with schema and custom delimiter argument', () => {
  428. // This test is only relevant for dialects that do not support schemas
  429. if (dialect.supports.schemas) {
  430. return;
  431. }
  432. expectsql(
  433. () =>
  434. queryGenerator.addConstraintQuery(
  435. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  436. { type: 'UNIQUE', fields: ['username'] },
  437. ),
  438. {
  439. sqlite3: notSupportedError,
  440. },
  441. );
  442. });
  443. });
  444. describe('FOREIGN KEY constraints', () => {
  445. it('generates a query that adds a foreign key constraint with a name', () => {
  446. expectsql(
  447. () =>
  448. queryGenerator.addConstraintQuery('myTable', {
  449. name: 'foreign key',
  450. type: 'FOREIGN KEY',
  451. fields: ['otherId'],
  452. references: { table: 'otherTable', field: 'id' },
  453. }),
  454. {
  455. default: `ALTER TABLE [myTable] ADD CONSTRAINT [foreign key] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id])`,
  456. sqlite3: notSupportedError,
  457. },
  458. );
  459. });
  460. it('generates a query that adds a deferred foreign key constraint', () => {
  461. expectsql(
  462. () =>
  463. queryGenerator.addConstraintQuery('myTable', {
  464. type: 'FOREIGN KEY',
  465. fields: ['otherId'],
  466. references: { table: 'otherTable', field: 'id' },
  467. deferrable: Deferrable.INITIALLY_IMMEDIATE,
  468. }),
  469. {
  470. default: deferrableNotSupportedError,
  471. sqlite3: notSupportedError,
  472. 'postgres snowflake': `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) DEFERRABLE INITIALLY IMMEDIATE`,
  473. },
  474. );
  475. });
  476. it('generates a query that adds a composite foreign key constraint', () => {
  477. expectsql(
  478. () =>
  479. queryGenerator.addConstraintQuery('myTable', {
  480. type: 'FOREIGN KEY',
  481. fields: ['otherId', 'someId'],
  482. references: { table: 'otherTable', fields: ['id', 'someId'] },
  483. }),
  484. {
  485. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_someId_otherTable_fk] FOREIGN KEY ([otherId], [someId]) REFERENCES [otherTable] ([id], [someId])`,
  486. sqlite3: notSupportedError,
  487. },
  488. );
  489. });
  490. it('generates a query that adds a foreign key constraint with on delete', () => {
  491. expectsql(
  492. () =>
  493. queryGenerator.addConstraintQuery('myTable', {
  494. type: 'FOREIGN KEY',
  495. fields: ['otherId'],
  496. references: { table: 'otherTable', field: 'id' },
  497. onDelete: 'CASCADE',
  498. }),
  499. {
  500. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON DELETE CASCADE`,
  501. sqlite3: notSupportedError,
  502. },
  503. );
  504. });
  505. it('generates a query that adds a foreign key constraint with on update', () => {
  506. expectsql(
  507. () =>
  508. queryGenerator.addConstraintQuery('myTable', {
  509. type: 'FOREIGN KEY',
  510. fields: ['otherId'],
  511. references: { table: 'otherTable', field: 'id' },
  512. onUpdate: 'CASCADE',
  513. }),
  514. {
  515. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id]) ON UPDATE CASCADE`,
  516. sqlite3: notSupportedError,
  517. 'db2 ibmi': onUpdateNotSupportedError,
  518. },
  519. );
  520. });
  521. it('throws an error if no references is defined', () => {
  522. expectsql(
  523. () => {
  524. // @ts-expect-error -- We're testing invalid options
  525. return queryGenerator.addConstraintQuery('myTable', {
  526. type: 'FOREIGN KEY',
  527. fields: ['otherId'],
  528. });
  529. },
  530. {
  531. default: new Error(
  532. 'Invalid foreign key constraint options. `references` object with `table` and `field` must be specified',
  533. ),
  534. sqlite3: notSupportedError,
  535. },
  536. );
  537. });
  538. it('generates a query that adds a foreign key constraint', () => {
  539. expectsql(
  540. () =>
  541. queryGenerator.addConstraintQuery('myTable', {
  542. type: 'FOREIGN KEY',
  543. fields: ['otherId'],
  544. references: { table: 'otherTable', field: 'id' },
  545. }),
  546. {
  547. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id])`,
  548. sqlite3: notSupportedError,
  549. },
  550. );
  551. });
  552. it('generates a query that adds a foreign key constraint for a model', () => {
  553. const MyModel = sequelize.define('MyModel', {});
  554. const OtherModel = sequelize.define('OtherModel', {});
  555. expectsql(
  556. () =>
  557. queryGenerator.addConstraintQuery(MyModel, {
  558. type: 'FOREIGN KEY',
  559. fields: ['otherId'],
  560. references: { table: OtherModel, field: 'id' },
  561. }),
  562. {
  563. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_otherId_OtherModels_fk] FOREIGN KEY ([otherId]) REFERENCES [OtherModels] ([id])`,
  564. sqlite3: notSupportedError,
  565. },
  566. );
  567. });
  568. it('generates a query that adds a foreign key constraint for a model definition', () => {
  569. const MyModel = sequelize.define('MyModel', {});
  570. const myDefinition = MyModel.modelDefinition;
  571. const OtherModel = sequelize.define('OtherModel', {});
  572. const otherDefinition = OtherModel.modelDefinition;
  573. expectsql(
  574. () =>
  575. queryGenerator.addConstraintQuery(myDefinition, {
  576. type: 'FOREIGN KEY',
  577. fields: ['otherId'],
  578. references: { table: otherDefinition, field: 'id' },
  579. }),
  580. {
  581. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_otherId_OtherModels_fk] FOREIGN KEY ([otherId]) REFERENCES [OtherModels] ([id])`,
  582. sqlite3: notSupportedError,
  583. },
  584. );
  585. });
  586. it('generates a query that adds a foreign key constraint with schema', () => {
  587. expectsql(
  588. () =>
  589. queryGenerator.addConstraintQuery(
  590. { tableName: 'myTable', schema: 'mySchema' },
  591. {
  592. type: 'FOREIGN KEY',
  593. fields: ['otherId'],
  594. references: { table: { tableName: 'otherTable', schema: 'mySchema' }, field: 'id' },
  595. },
  596. ),
  597. {
  598. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [mySchema].[otherTable] ([id])`,
  599. sqlite3: notSupportedError,
  600. },
  601. );
  602. });
  603. it('generates a query that adds a foreign key constraint with foreign key schema', () => {
  604. expectsql(
  605. () =>
  606. queryGenerator.addConstraintQuery(
  607. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  608. {
  609. type: 'FOREIGN KEY',
  610. fields: ['otherId'],
  611. references: {
  612. table: { tableName: 'otherTable', schema: dialect.getDefaultSchema() },
  613. field: 'id',
  614. },
  615. },
  616. ),
  617. {
  618. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [otherTable] ([id])`,
  619. sqlite3: notSupportedError,
  620. },
  621. );
  622. });
  623. it('generates a query that adds a foreign key constraint with globally set schema', () => {
  624. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  625. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  626. expectsql(
  627. () =>
  628. queryGeneratorSchema.addConstraintQuery('myTable', {
  629. type: 'FOREIGN KEY',
  630. fields: ['otherId'],
  631. references: { table: 'otherTable', field: 'id' },
  632. }),
  633. {
  634. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_otherId_otherTable_fk] FOREIGN KEY ([otherId]) REFERENCES [mySchema].[otherTable] ([id])`,
  635. sqlite3: notSupportedError,
  636. },
  637. );
  638. });
  639. it('generates a query that adds a foreign key constraint with schema and custom delimiter argument', () => {
  640. // This test is only relevant for dialects that do not support schemas
  641. if (dialect.supports.schemas) {
  642. return;
  643. }
  644. expectsql(
  645. () =>
  646. queryGenerator.addConstraintQuery(
  647. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  648. {
  649. type: 'FOREIGN KEY',
  650. fields: ['otherId'],
  651. references: {
  652. table: { tableName: 'otherTable', schema: 'mySchema', delimiter: 'custom' },
  653. field: 'id',
  654. },
  655. },
  656. ),
  657. {
  658. sqlite3: notSupportedError,
  659. },
  660. );
  661. });
  662. });
  663. describe('PRIMARY KEY constraints', () => {
  664. it('generates a query that adds a primary key constraint with a name', () => {
  665. expectsql(
  666. () =>
  667. queryGenerator.addConstraintQuery('myTable', {
  668. name: 'primary key',
  669. type: 'PRIMARY KEY',
  670. fields: ['username'],
  671. }),
  672. {
  673. default: `ALTER TABLE [myTable] ADD CONSTRAINT [primary key] PRIMARY KEY ([username])`,
  674. sqlite3: notSupportedError,
  675. },
  676. );
  677. });
  678. it('generates a query that adds a deferred primary key constraint', () => {
  679. expectsql(
  680. () =>
  681. queryGenerator.addConstraintQuery('myTable', {
  682. type: 'PRIMARY KEY',
  683. fields: ['username'],
  684. deferrable: Deferrable.INITIALLY_IMMEDIATE,
  685. }),
  686. {
  687. default: deferrableNotSupportedError,
  688. sqlite3: notSupportedError,
  689. 'postgres snowflake': `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_pk] PRIMARY KEY ([username]) DEFERRABLE INITIALLY IMMEDIATE`,
  690. },
  691. );
  692. });
  693. it('generates a query that adds a primary key constraint with multiple columns', () => {
  694. expectsql(
  695. () =>
  696. queryGenerator.addConstraintQuery('myTable', {
  697. type: 'PRIMARY KEY',
  698. fields: ['first_name', 'last_name'],
  699. }),
  700. {
  701. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_first_name_last_name_pk] PRIMARY KEY ([first_name], [last_name])`,
  702. sqlite3: notSupportedError,
  703. },
  704. );
  705. });
  706. it('generates a query that adds a primary key constraint', () => {
  707. expectsql(
  708. () =>
  709. queryGenerator.addConstraintQuery('myTable', {
  710. type: 'PRIMARY KEY',
  711. fields: ['username'],
  712. }),
  713. {
  714. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_pk] PRIMARY KEY ([username])`,
  715. sqlite3: notSupportedError,
  716. },
  717. );
  718. });
  719. it('generates a query that adds a primary key constraint for a model', () => {
  720. const MyModel = sequelize.define('MyModel', {});
  721. expectsql(
  722. () =>
  723. queryGenerator.addConstraintQuery(MyModel, { type: 'PRIMARY KEY', fields: ['username'] }),
  724. {
  725. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_username_pk] PRIMARY KEY ([username])`,
  726. sqlite3: notSupportedError,
  727. },
  728. );
  729. });
  730. it('generates a query that adds a primary key constraint for a model definition', () => {
  731. const MyModel = sequelize.define('MyModel', {});
  732. const myDefinition = MyModel.modelDefinition;
  733. expectsql(
  734. () =>
  735. queryGenerator.addConstraintQuery(myDefinition, {
  736. type: 'PRIMARY KEY',
  737. fields: ['username'],
  738. }),
  739. {
  740. default: `ALTER TABLE [MyModels] ADD CONSTRAINT [MyModels_username_pk] PRIMARY KEY ([username])`,
  741. sqlite3: notSupportedError,
  742. },
  743. );
  744. });
  745. it('generates a query that adds a primary key constraint with schema', () => {
  746. expectsql(
  747. () =>
  748. queryGenerator.addConstraintQuery(
  749. { tableName: 'myTable', schema: 'mySchema' },
  750. { type: 'PRIMARY KEY', fields: ['username'] },
  751. ),
  752. {
  753. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_username_pk] PRIMARY KEY ([username])`,
  754. sqlite3: notSupportedError,
  755. },
  756. );
  757. });
  758. it('generates a query that adds a primary key constraint with primary key schema', () => {
  759. expectsql(
  760. () =>
  761. queryGenerator.addConstraintQuery(
  762. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  763. { type: 'PRIMARY KEY', fields: ['username'] },
  764. ),
  765. {
  766. default: `ALTER TABLE [myTable] ADD CONSTRAINT [myTable_username_pk] PRIMARY KEY ([username])`,
  767. sqlite3: notSupportedError,
  768. },
  769. );
  770. });
  771. it('generates a query that adds a primary key constraint with globally set schema', () => {
  772. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  773. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  774. expectsql(
  775. () =>
  776. queryGeneratorSchema.addConstraintQuery('myTable', {
  777. type: 'PRIMARY KEY',
  778. fields: ['username'],
  779. }),
  780. {
  781. default: `ALTER TABLE [mySchema].[myTable] ADD CONSTRAINT [myTable_username_pk] PRIMARY KEY ([username])`,
  782. sqlite3: notSupportedError,
  783. },
  784. );
  785. });
  786. it('generates a query that adds a primary key constraint with schema and custom delimiter argument', () => {
  787. // This test is only relevant for dialects that do not support schemas
  788. if (dialect.supports.schemas) {
  789. return;
  790. }
  791. expectsql(
  792. () =>
  793. queryGenerator.addConstraintQuery(
  794. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  795. { type: 'PRIMARY KEY', fields: ['username'] },
  796. ),
  797. {
  798. sqlite3: notSupportedError,
  799. },
  800. );
  801. });
  802. });
  803. });