get-constraint-snippet.test.ts 27 KB

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