describeTable.test.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. 'use strict';
  2. const chai = require('chai');
  3. const expect = chai.expect;
  4. const Support = require('../support');
  5. const { DataTypes } = require('@sequelize/core');
  6. const dialect = Support.getTestDialect();
  7. describe(Support.getTestDialectTeaser('QueryInterface'), () => {
  8. beforeEach(function () {
  9. this.queryInterface = this.sequelize.queryInterface;
  10. });
  11. describe('describeTable', () => {
  12. Support.allowDeprecationsInSuite(['SEQUELIZE0015']);
  13. if (Support.sequelize.dialect.supports.schemas) {
  14. it('reads the metadata of the table with schema in object', async function () {
  15. const MyTable1 = this.sequelize.define('my_table', {
  16. username1: DataTypes.STRING,
  17. });
  18. const MyTable2 = this.sequelize.define(
  19. 'my_table',
  20. {
  21. username2: DataTypes.STRING,
  22. },
  23. { schema: 'test_meta' },
  24. );
  25. await this.sequelize.createSchema('test_meta');
  26. await MyTable1.sync({ force: true });
  27. await MyTable2.sync({ force: true });
  28. const metadata0 = await this.queryInterface.describeTable({
  29. tableName: 'my_tables',
  30. schema: 'test_meta',
  31. });
  32. expect(metadata0.username2).not.to.be.undefined;
  33. const metadata = await this.queryInterface.describeTable('my_tables');
  34. expect(metadata.username1).not.to.be.undefined;
  35. });
  36. it('reads the metadata of the table with schema parameter', async function () {
  37. const MyTable1 = this.sequelize.define('my_table', {
  38. username1: DataTypes.STRING,
  39. });
  40. const MyTable2 = this.sequelize.define(
  41. 'my_table',
  42. {
  43. username2: DataTypes.STRING,
  44. },
  45. { schema: 'test_meta' },
  46. );
  47. await this.sequelize.createSchema('test_meta');
  48. await MyTable1.sync({ force: true });
  49. await MyTable2.sync({ force: true });
  50. const metadata0 = await this.queryInterface.describeTable('my_tables', 'test_meta');
  51. expect(metadata0.username2).not.to.be.undefined;
  52. const metadata = await this.queryInterface.describeTable('my_tables');
  53. expect(metadata.username1).not.to.be.undefined;
  54. });
  55. }
  56. it('rejects when no data is available', async function () {
  57. const table = this.sequelize.queryGenerator.extractTableDetails('_some_random_missing_table');
  58. await expect(this.queryInterface.describeTable(table)).to.be.rejectedWith(
  59. `No description found for table ${table.tableName}${table.schema ? ` in schema ${table.schema}` : ''}. Check the table name and schema; remember, they _are_ case sensitive.`,
  60. );
  61. });
  62. it('reads the metadata of the table', async function () {
  63. const Users = this.sequelize.define(
  64. '_Users',
  65. {
  66. username: DataTypes.STRING,
  67. city: {
  68. type: DataTypes.STRING,
  69. defaultValue: null,
  70. comment: 'Users City',
  71. },
  72. isAdmin: DataTypes.BOOLEAN,
  73. enumVals: DataTypes.ENUM('hello', 'world'),
  74. },
  75. { freezeTableName: true },
  76. );
  77. await Users.sync({ force: true });
  78. const metadata = await this.queryInterface.describeTable('_Users');
  79. const id = metadata.id;
  80. const username = metadata.username;
  81. const city = metadata.city;
  82. const isAdmin = metadata.isAdmin;
  83. const enumVals = metadata.enumVals;
  84. expect(id.primaryKey).to.be.true;
  85. if (['mysql', 'mssql', 'db2'].includes(dialect)) {
  86. expect(id.autoIncrement).to.be.true;
  87. }
  88. let assertVal = 'VARCHAR(255)';
  89. switch (dialect) {
  90. case 'postgres':
  91. assertVal = 'CHARACTER VARYING(255)';
  92. break;
  93. case 'mssql':
  94. assertVal = 'NVARCHAR(255)';
  95. break;
  96. case 'sqlite3':
  97. assertVal = 'TEXT';
  98. break;
  99. case 'ibmi':
  100. case 'db2':
  101. assertVal = 'VARCHAR';
  102. break;
  103. }
  104. expect(username.type).to.equal(assertVal);
  105. expect(username.allowNull).to.be.true;
  106. switch (dialect) {
  107. case 'sqlite3':
  108. expect(username.defaultValue).to.be.undefined;
  109. break;
  110. default:
  111. expect(username.defaultValue).to.be.null;
  112. }
  113. switch (dialect) {
  114. case 'sqlite3':
  115. expect(city.defaultValue).to.be.null;
  116. break;
  117. }
  118. assertVal = 'TINYINT(1)';
  119. switch (dialect) {
  120. case 'postgres':
  121. case 'db2':
  122. assertVal = 'BOOLEAN';
  123. break;
  124. case 'sqlite3':
  125. assertVal = 'INTEGER';
  126. break;
  127. case 'mssql':
  128. assertVal = 'BIT';
  129. break;
  130. case 'ibmi':
  131. assertVal = 'SMALLINT';
  132. break;
  133. }
  134. expect(isAdmin.type).to.equal(assertVal);
  135. expect(isAdmin.allowNull).to.be.true;
  136. switch (dialect) {
  137. case 'sqlite3':
  138. expect(isAdmin.defaultValue).to.be.undefined;
  139. break;
  140. default:
  141. expect(isAdmin.defaultValue).to.be.null;
  142. }
  143. if (dialect.startsWith('postgres')) {
  144. expect(enumVals.special).to.be.instanceof(Array);
  145. expect(enumVals.special).to.have.length(2);
  146. } else if (dialect === 'mysql') {
  147. expect(enumVals.type).to.eql("ENUM('hello','world')");
  148. }
  149. if (['postgres', 'mysql', 'mssql'].includes(dialect)) {
  150. expect(city.comment).to.equal('Users City');
  151. expect(username.comment).to.equal(null);
  152. }
  153. });
  154. it('should correctly determine the primary key columns', async function () {
  155. const Country = this.sequelize.define(
  156. '_Country',
  157. {
  158. code: { type: DataTypes.STRING, primaryKey: true },
  159. name: { type: DataTypes.STRING, allowNull: false },
  160. },
  161. { freezeTableName: true },
  162. );
  163. const Alumni = this.sequelize.define(
  164. '_Alumni',
  165. {
  166. year: { type: DataTypes.INTEGER, primaryKey: true },
  167. num: { type: DataTypes.INTEGER, primaryKey: true },
  168. username: { type: DataTypes.STRING, allowNull: false, unique: true },
  169. dob: { type: DataTypes.DATEONLY, allowNull: false },
  170. dod: { type: DataTypes.DATEONLY, allowNull: true },
  171. city: { type: DataTypes.STRING, allowNull: false },
  172. ctrycod: {
  173. type: DataTypes.STRING,
  174. allowNull: false,
  175. references: { model: Country, key: 'code' },
  176. },
  177. },
  178. { freezeTableName: true },
  179. );
  180. await Country.sync({ force: true });
  181. const metacountry = await this.queryInterface.describeTable('_Country');
  182. expect(metacountry.code.primaryKey).to.eql(true);
  183. expect(metacountry.name.primaryKey).to.eql(false);
  184. await Alumni.sync({ force: true });
  185. const metalumni = await this.queryInterface.describeTable('_Alumni');
  186. expect(metalumni.year.primaryKey).to.eql(true);
  187. expect(metalumni.num.primaryKey).to.eql(true);
  188. expect(metalumni.username.primaryKey).to.eql(false);
  189. expect(metalumni.dob.primaryKey).to.eql(false);
  190. expect(metalumni.dod.primaryKey).to.eql(false);
  191. expect(metalumni.ctrycod.primaryKey).to.eql(false);
  192. expect(metalumni.city.primaryKey).to.eql(false);
  193. });
  194. it('should correctly return the columns when the table contains a dot in the name', async function () {
  195. const User = this.sequelize.define(
  196. 'my.user',
  197. {
  198. name: DataTypes.STRING,
  199. },
  200. { freezeTableName: true },
  201. );
  202. await User.sync({ force: true });
  203. const metadata = await this.queryInterface.describeTable('my.user');
  204. expect(metadata).to.haveOwnProperty('name');
  205. });
  206. });
  207. });