12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469 |
- 'use strict';
- const Support = require('../../support');
- const { DataTypes, Op } = require('@sequelize/core');
- const util = require('node:util');
- const {
- _validateIncludedElements,
- } = require('@sequelize/core/_non-semver-use-at-your-own-risk_/model-internals.js');
- const { beforeAll2, createSequelizeInstance } = require('../../support');
- const expectsql = Support.expectsql;
- const current = Support.sequelize;
- const sql = current.queryGenerator;
- const TICK_LEFT = Support.sequelize.dialect.TICK_CHAR_LEFT;
- const TICK_RIGHT = Support.sequelize.dialect.TICK_CHAR_RIGHT;
- // Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation
- describe(Support.getTestDialectTeaser('SQL'), () => {
- describe('select', () => {
- function expectSelect(options, expectation) {
- const model = options.model;
- return expectsql(
- () => sql.selectQuery(options.table || (model && model.table), options, options.model),
- expectation,
- );
- }
- const testsql = function (options, expectation, testFunction = it) {
- testFunction(util.inspect(options, { depth: 2 }), () => {
- expectSelect(options, expectation);
- });
- };
- testsql.only = (options, expectation) => testsql(options, expectation, it.only);
- testsql(
- {
- table: 'User',
- attributes: ['email', ['first_name', 'firstName']],
- where: {
- email: 'jon.snow@gmail.com',
- },
- order: [['email', 'DESC']],
- limit: 10,
- },
- {
- default:
- "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = 'jon.snow@gmail.com' ORDER BY [email] DESC LIMIT 10;",
- db2: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC FETCH NEXT 10 ROWS ONLY;',
- mssql:
- "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = N'jon.snow@gmail.com' ORDER BY [email] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;",
- ibmi: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC FETCH NEXT 10 ROWS ONLY',
- },
- );
- testsql(
- {
- table: 'User',
- attributes: ['email', ['first_name', 'firstName'], ['last_name', 'lastName']],
- order: [['last_name', 'ASC']],
- groupedLimit: {
- limit: 3,
- on: 'companyId',
- values: [1, 5],
- },
- },
- {
- default: `SELECT [User].* FROM (${[
- `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 1 ORDER BY [last_name] ASC LIMIT 3) AS sub`,
- `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 5 ORDER BY [last_name] ASC LIMIT 3) AS sub`,
- ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ')}) AS [User];`,
- 'db2 ibmi': `SELECT [User].* FROM (${[
- `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 1 ORDER BY "last_name" ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 5 ORDER BY "last_name" ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ')}) AS [User];`,
- mssql: `SELECT [User].* FROM (${[
- `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 1 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 5 ORDER BY [last_name] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ')}) AS [User];`,
- },
- );
- describe('With BelongsToMany', () => {
- const vars = beforeAll2(() => {
- const User = Support.sequelize.define('user', {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true,
- field: 'id_user',
- },
- });
- const Project = Support.sequelize.define('project', {
- title: DataTypes.STRING,
- });
- const ProjectUser = Support.sequelize.define(
- 'project_user',
- {
- userId: {
- type: DataTypes.INTEGER,
- field: 'user_id',
- },
- projectId: {
- type: DataTypes.INTEGER,
- field: 'project_id',
- },
- },
- { timestamps: false },
- );
- User.Projects = User.belongsToMany(Project, { through: ProjectUser });
- Project.belongsToMany(User, { through: ProjectUser });
- return { User, Project, ProjectUser };
- });
- it('supports groupedLimit', () => {
- const { User } = vars;
- expectSelect(
- {
- table: User.table,
- model: User,
- attributes: [['id_user', 'id']],
- order: [['last_name', 'ASC']],
- groupedLimit: {
- limit: 3,
- on: User.Projects,
- values: [1, 5],
- },
- },
- {
- default: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- 'db2 ibmi': `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- mssql: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- },
- );
- });
- it('supports groupedLimit with through', () => {
- const { User } = vars;
- expectSelect(
- {
- table: User.table,
- model: User,
- attributes: [['id_user', 'id']],
- order: [['last_name', 'ASC']],
- groupedLimit: {
- limit: 3,
- through: {
- where: {
- status: 1,
- },
- },
- on: User.Projects,
- values: [1, 5],
- },
- },
- {
- default: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 1
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 5
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- 'db2 ibmi': `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 1
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 5
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- mssql: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 1
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND ([project_user].[project_id] = 5
- AND [project_user].[status] = 1)
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- },
- );
- });
- it('supports groupedLimit with through and where', () => {
- const { User } = vars;
- expectSelect(
- {
- table: User.table,
- model: User,
- attributes: [['id_user', 'id']],
- order: [['id_user', 'ASC']],
- where: {
- age: {
- [Op.gte]: 21,
- },
- },
- groupedLimit: {
- limit: 3,
- on: User.Projects,
- values: [1, 5],
- },
- },
- {
- default: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC LIMIT 3
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- 'db2 ibmi': `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- mssql: `SELECT [user].* FROM (${[
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 1
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- `SELECT * FROM (
- SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_user].[user_id] AS [project_user.userId], [project_user].[project_id] AS [project_user.projectId]
- FROM [users] AS [user]
- INNER JOIN [project_users] AS [project_user]
- ON [user].[id_user] = [project_user].[user_id]
- AND [project_user].[project_id] = 5
- WHERE [user].[age] >= 21
- ORDER BY [subquery_order_0] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY
- ) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] ORDER BY [subquery_order_0] ASC;`,
- },
- );
- });
- });
- describe('With HasMany', () => {
- const vars = beforeAll2(() => {
- const User = Support.sequelize.define(
- 'user',
- {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true,
- field: 'id_user',
- },
- email: DataTypes.STRING,
- firstName: {
- type: DataTypes.STRING,
- field: 'first_name',
- },
- lastName: {
- type: DataTypes.STRING,
- field: 'last_name',
- },
- },
- {
- tableName: 'users',
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- userId: {
- type: DataTypes.INTEGER,
- field: 'user_id',
- },
- },
- {
- tableName: 'post',
- },
- );
- User.Posts = User.hasMany(Post, { foreignKey: 'userId', as: 'POSTS' });
- const Comment = Support.sequelize.define(
- 'Comment',
- {
- title: DataTypes.STRING,
- postId: {
- type: DataTypes.INTEGER,
- field: 'post_id',
- },
- },
- {
- tableName: 'comment',
- },
- );
- Post.Comments = Post.hasMany(Comment, { foreignKey: 'postId', as: 'COMMENTS' });
- const include = _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- },
- ],
- model: User,
- }).include;
- return { User, Post, include };
- });
- it('supports groupedLimit', () => {
- const { include, User } = vars;
- expectSelect(
- {
- table: User.table,
- model: User,
- include,
- attributes: [
- ['id_user', 'id'],
- 'email',
- ['first_name', 'firstName'],
- ['last_name', 'lastName'],
- ],
- order: [['last_name', 'ASC']],
- groupedLimit: {
- limit: 3,
- on: 'companyId',
- values: [1, 5],
- },
- },
- {
- default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC LIMIT 3) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC LIMIT 3) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];`,
- 'db2 ibmi': `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];`,
- mssql: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];`,
- },
- );
- });
- it('supports order, limit, offset', () => {
- const { include, User } = vars;
- expectSelect(
- {
- table: User.table,
- model: User,
- include,
- attributes: [
- ['id_user', 'id'],
- 'email',
- ['first_name', 'firstName'],
- ['last_name', 'lastName'],
- ],
- // [last_name] is not wrapped in a literal, so it's a column name and must be escaped
- // as [[[last_name]]]
- order: [
- [
- '[last_name]'
- .replaceAll('[', Support.sequelize.dialect.TICK_CHAR_LEFT)
- .replaceAll(']', Support.sequelize.dialect.TICK_CHAR_RIGHT),
- 'ASC',
- ],
- ],
- limit: 30,
- offset: 10,
- hasMultiAssociation: true, // must be set only for mssql dialect here
- subQuery: true,
- },
- {
- default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC LIMIT 30 OFFSET 10) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`,
- 'db2 ibmi mssql': `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC;`,
- },
- );
- });
- it('supports order, limit, offset without subQuery', () => {
- const { include, User } = vars;
- // By default, SELECT with include of a multi association & limit will be ran as a subQuery
- // This checks the result when the query is forced to be ran without a subquery
- expectSelect(
- {
- table: User.table,
- model: User,
- include,
- attributes: [
- ['id_user', 'id'],
- 'email',
- ['first_name', 'firstName'],
- ['last_name', 'lastName'],
- ],
- // [last_name] is not wrapped in a literal, so it's a column name and must be escaped
- // as [[[last_name]]]
- order: [
- [
- '[last_name]'
- .replaceAll('[', Support.sequelize.dialect.TICK_CHAR_LEFT)
- .replaceAll(']', Support.sequelize.dialect.TICK_CHAR_RIGHT),
- 'ASC',
- ],
- ],
- limit: 30,
- offset: 10,
- hasMultiAssociation: true, // must be set only for mssql dialect here
- subQuery: false,
- },
- {
- default: `SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName], [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title]
- FROM [users] AS [user] LEFT OUTER JOIN [post] AS [POSTS]
- ON [user].[id_user] = [POSTS].[user_id]
- ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC LIMIT 30 OFFSET 10;`,
- 'db2 ibmi mssql': `SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName], [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title]
- FROM [users] AS [user] LEFT OUTER JOIN [post] AS [POSTS]
- ON [user].[id_user] = [POSTS].[user_id]
- ORDER BY [user].${TICK_LEFT}${TICK_LEFT}${TICK_LEFT}last_name${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;`,
- },
- );
- });
- it('supports nested includes', () => {
- const { Post, User } = vars;
- const nestedInclude = _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- include: [
- {
- attributes: ['title'],
- association: Post.Comments,
- },
- ],
- },
- ],
- model: User,
- }).include;
- expectSelect(
- {
- table: User.table,
- model: User,
- include: nestedInclude,
- attributes: [
- ['id_user', 'id'],
- 'email',
- ['first_name', 'firstName'],
- ['last_name', 'lastName'],
- ],
- order: [['last_name', 'ASC']],
- groupedLimit: {
- limit: 3,
- on: 'companyId',
- values: [1, 5],
- },
- },
- {
- default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title], [POSTS->COMMENTS].[id] AS [POSTS.COMMENTS.id], [POSTS->COMMENTS].[title] AS [POSTS.COMMENTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC LIMIT 3) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC LIMIT 3) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];`,
- 'db2 ibmi': `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title], [POSTS->COMMENTS].[id] AS [POSTS.COMMENTS.id], [POSTS->COMMENTS].[title] AS [POSTS.COMMENTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];`,
- mssql: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title], [POSTS->COMMENTS].[id] AS [POSTS.COMMENTS.id], [POSTS->COMMENTS].[title] AS [POSTS.COMMENTS.title] FROM (${[
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) AS sub`,
- ].join(
- current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ',
- )}) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];`,
- },
- );
- });
- });
- it('include (left outer join)', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- ibmi: 'SELECT "User"."name", "User"."age", "posts"."id" AS "posts.id", "posts"."title" AS "posts.title" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "posts" ON "User"."id" = "posts"."user_id"',
- default:
- 'SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];',
- },
- );
- });
- it('include (right outer join)', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- right: true,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- default: `SELECT [User].[name], [User].[age], [posts].[id] AS [posts.id], [posts].[title] AS [posts.title] FROM [User] AS [User] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [Post] AS [posts] ON [User].[id] = [posts].[user_id];`,
- },
- );
- });
- it('include through (right outer join)', () => {
- const User = Support.sequelize.define('user', {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true,
- field: 'id_user',
- },
- });
- const Project = Support.sequelize.define('project', {
- title: DataTypes.STRING,
- });
- const ProjectUser = Support.sequelize.define(
- 'project_user',
- {
- userId: {
- type: DataTypes.INTEGER,
- field: 'user_id',
- },
- projectId: {
- type: DataTypes.INTEGER,
- field: 'project_id',
- },
- },
- { timestamps: false },
- );
- User.belongsToMany(Project, { through: ProjectUser });
- Project.belongsToMany(User, { through: ProjectUser });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['id_user', 'id'],
- include: _validateIncludedElements({
- include: [
- {
- model: Project,
- right: true,
- },
- ],
- model: User,
- }).include,
- model: User,
- // the order here is important, because a different piece of code is responsible for naming the through table name in ORDER BY
- // than in LEFT JOIN
- order: [['projects', ProjectUser, 'userId', 'ASC']],
- },
- User,
- ),
- {
- default: `
- SELECT [user].[id_user],
- [user].[id],
- [projects].[id] AS [projects.id],
- [projects].[title] AS [projects.title],
- [projects].[createdAt] AS [projects.createdAt],
- [projects].[updatedAt] AS [projects.updatedAt],
- [projects->project_user].[user_id] AS [projects.project_user.userId],
- [projects->project_user].[project_id] AS [projects.project_user.projectId]
- FROM [User] AS [user]
- ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN (
- [project_users] AS [projects->project_user]
- INNER JOIN [projects] AS [projects]
- ON [projects].[id] = [projects->project_user].[project_id]
- )
- ON [user].[id_user] = [projects->project_user].[user_id]
- ORDER BY [projects->project_user].[user_id] ASC;`,
- },
- );
- });
- describe('include (subQuery alias)', () => {
- const vars = beforeAll2(() => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id', as: 'postaliasname' });
- return { User };
- });
- it('w/o filters', () => {
- const { User } = vars;
- expectsql(
- sql.selectQuery(
- 'User',
- {
- table: User.table,
- model: User,
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- model: User,
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- subQuery: true,
- required: true,
- },
- ],
- as: 'User',
- }).include,
- subQuery: true,
- },
- User,
- ),
- {
- default:
- 'SELECT [User].* FROM ' +
- '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' +
- 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' +
- `WHERE EXISTS ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id]) ) AS [User];`,
- },
- );
- });
- it('w/ nested column filter', () => {
- const { User } = vars;
- expectsql(
- () =>
- sql.selectQuery(
- 'User',
- {
- table: User.table,
- model: User,
- attributes: ['name', 'age'],
- where: { '$postaliasname.title$': 'test' },
- include: _validateIncludedElements({
- model: User,
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- subQuery: true,
- required: true,
- },
- ],
- as: 'User',
- }).include,
- subQuery: true,
- },
- User,
- ),
- {
- default:
- 'SELECT [User].* FROM ' +
- '(SELECT [User].[name], [User].[age], [User].[id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' +
- 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' +
- `WHERE [postaliasname].[title] = ${sql.escape('test')} AND EXISTS ( SELECT [user_id] FROM [Post] AS [postaliasname] WHERE [postaliasname].[user_id] = [User].[id]) ) AS [User];`,
- },
- );
- });
- });
- it('include w/ subQuery + nested filter + paging', () => {
- const User = Support.sequelize.define('User', {
- scopeId: DataTypes.INTEGER,
- });
- const Company = Support.sequelize.define('Company', {
- name: DataTypes.STRING,
- public: DataTypes.BOOLEAN,
- scopeId: DataTypes.INTEGER,
- });
- const Profession = Support.sequelize.define('Profession', {
- name: DataTypes.STRING,
- scopeId: DataTypes.INTEGER,
- });
- User.Company = User.belongsTo(Company, { foreignKey: 'companyId' });
- User.Profession = User.belongsTo(Profession, { foreignKey: 'professionId' });
- Company.Users = Company.hasMany(User, { as: 'Users', foreignKey: 'companyId' });
- Profession.Users = Profession.hasMany(User, { as: 'Users', foreignKey: 'professionId' });
- expectsql(
- sql.selectQuery(
- 'Company',
- {
- table: Company.table,
- model: Company,
- attributes: ['name', 'public'],
- where: { '$Users.profession.name$': 'test', [Op.and]: { scopeId: [42] } },
- include: _validateIncludedElements({
- include: [
- {
- association: Company.Users,
- attributes: [],
- include: [
- {
- association: User.Profession,
- attributes: [],
- required: true,
- },
- ],
- subQuery: true,
- required: true,
- },
- ],
- model: Company,
- }).include,
- limit: 5,
- offset: 0,
- subQuery: true,
- },
- Company,
- ),
- {
- default:
- 'SELECT [Company].* FROM (' +
- 'SELECT [Company].[name], [Company].[public], [Company].[id] FROM [Company] AS [Company] ' +
- 'INNER JOIN [Users] AS [Users] ON [Company].[id] = [Users].[companyId] ' +
- 'INNER JOIN [Professions] AS [Users->profession] ON [Users].[professionId] = [Users->profession].[id] ' +
- `WHERE ([Company].[scopeId] IN (42) AND [Users->profession].[name] = ${sql.escape('test')}) AND ` +
- 'EXISTS ( SELECT [Users].[companyId] FROM [Users] AS [Users] ' +
- 'INNER JOIN [Professions] AS [profession] ON [Users].[professionId] = [profession].[id] ' +
- `WHERE [Users].[companyId] = [Company].[id] ) ORDER BY [Company].[id] LIMIT 5) AS [Company];`,
- 'db2 ibmi':
- 'SELECT [Company].* FROM (' +
- 'SELECT [Company].[name], [Company].[public], [Company].[id] FROM [Company] AS [Company] ' +
- 'INNER JOIN [Users] AS [Users] ON [Company].[id] = [Users].[companyId] ' +
- 'INNER JOIN [Professions] AS [Users->profession] ON [Users].[professionId] = [Users->profession].[id] ' +
- `WHERE ([Company].[scopeId] IN (42) AND [Users->profession].[name] = ${sql.escape('test')}) AND ` +
- 'EXISTS ( SELECT [Users].[companyId] FROM [Users] AS [Users] ' +
- 'INNER JOIN [Professions] AS [profession] ON [Users].[professionId] = [profession].[id] ' +
- `WHERE [Users].[companyId] = [Company].[id] ) ` +
- `ORDER BY [Company].[id] FETCH NEXT 5 ROWS ONLY) AS [Company];`,
- mssql:
- 'SELECT [Company].* FROM (' +
- 'SELECT [Company].[name], [Company].[public], [Company].[id] FROM [Company] AS [Company] ' +
- 'INNER JOIN [Users] AS [Users] ON [Company].[id] = [Users].[companyId] ' +
- 'INNER JOIN [Professions] AS [Users->profession] ON [Users].[professionId] = [Users->profession].[id] ' +
- `WHERE ([Company].[scopeId] IN (42) AND [Users->profession].[name] = ${sql.escape('test')}) AND ` +
- 'EXISTS ( SELECT [Users].[companyId] FROM [Users] AS [Users] ' +
- 'INNER JOIN [Professions] AS [profession] ON [Users].[professionId] = [profession].[id] ' +
- `WHERE [Users].[companyId] = [Company].[id] ) ` +
- `ORDER BY [Company].[id] OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) AS [Company];`,
- },
- );
- });
- it('properly stringify IN values as per field definition', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- data: DataTypes.BLOB,
- },
- {
- freezeTableName: true,
- },
- );
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age', 'data'],
- where: {
- data: ['123'],
- },
- },
- User,
- ),
- {
- ibmi: `SELECT "name", "age", "data" FROM "User" AS "User" WHERE "User"."data" IN (BLOB(X'313233'))`,
- db2: `SELECT "name", "age", "data" FROM "User" AS "User" WHERE "User"."data" IN (BLOB('123'));`,
- postgres: `SELECT "name", "age", "data" FROM "User" AS "User" WHERE "User"."data" IN ('\\x313233');`,
- snowflake: `SELECT "name", "age", "data" FROM "User" AS "User" WHERE "User"."data" IN (X'313233');`,
- 'mariadb mysql sqlite3':
- "SELECT `name`, `age`, `data` FROM `User` AS `User` WHERE `User`.`data` IN (X'313233');",
- mssql:
- 'SELECT [name], [age], [data] FROM [User] AS [User] WHERE [User].[data] IN (0x313233);',
- },
- );
- });
- describe('attribute escaping', () => {
- it('plain attributes (1)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: [
- '* FROM [User];'
- .replaceAll('[', Support.sequelize.dialect.TICK_CHAR_LEFT)
- .replaceAll(']', Support.sequelize.dialect.TICK_CHAR_RIGHT),
- ],
- }),
- {
- default: `SELECT ${TICK_LEFT}* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};${TICK_RIGHT} FROM ${TICK_LEFT}User${TICK_RIGHT};`,
- },
- );
- });
- it('plain attributes (2)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: ['* FROM User; DELETE FROM User;SELECT id'],
- }),
- {
- default: 'SELECT [* FROM User; DELETE FROM User;SELECT id] FROM [User];',
- ibmi: 'SELECT "* FROM User; DELETE FROM User;SELECT id" FROM "User"',
- },
- );
- });
- it('plain attributes (3)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: [`a', * FROM User; DELETE FROM User;SELECT id`],
- }),
- {
- default: `SELECT [a', * FROM User; DELETE FROM User;SELECT id] FROM [User];`,
- mssql: `SELECT [a', * FROM User; DELETE FROM User;SELECT id] FROM [User];`,
- ibmi: `SELECT "a', * FROM User; DELETE FROM User;SELECT id" FROM "User"`,
- },
- );
- });
- it('plain attributes (4)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: ['*, COUNT(*) FROM User; DELETE FROM User;SELECT id'],
- }),
- {
- default: 'SELECT [*, COUNT(*) FROM User; DELETE FROM User;SELECT id] FROM [User];',
- ibmi: 'SELECT "*, COUNT(*) FROM User; DELETE FROM User;SELECT id" FROM "User"',
- },
- );
- });
- it('aliased attributes (1)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: [
- // this is not wrapped in `literal()`, so it's a column name.
- // [ & ] will be escaped as [[ & ]]
- [
- '* FROM [User]; DELETE FROM [User];SELECT [id]'
- .replaceAll('[', Support.sequelize.dialect.TICK_CHAR_LEFT)
- .replaceAll(']', Support.sequelize.dialect.TICK_CHAR_RIGHT),
- 'myCol',
- ],
- ],
- }),
- {
- default: `SELECT [* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}myCol] FROM [User];`,
- ibmi: 'SELECT "* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "myCol" FROM "User"',
- },
- );
- });
- it('aliased attributes (2)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: [['* FROM User; DELETE FROM User;SELECT id', 'myCol']],
- }),
- {
- default: 'SELECT [* FROM User; DELETE FROM User;SELECT id] AS [myCol] FROM [User];',
- ibmi: 'SELECT "* FROM User; DELETE FROM User;SELECT id" AS "myCol" FROM "User"',
- },
- );
- });
- it('aliased attributes (3)', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: [['id', '* FROM User; DELETE FROM User;SELECT id']],
- }),
- {
- default: 'SELECT [id] AS [* FROM User; DELETE FROM User;SELECT id] FROM [User];',
- ibmi: 'SELECT "id" AS "* FROM User; DELETE FROM User;SELECT id" FROM "User"',
- },
- );
- });
- it('attributes from includes', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- // association name is Pascal case to test quoteIdentifier: false
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id', as: 'Posts' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: [
- // this is not wrapped in `literal()`, so it's a column name.
- // [ & ] will be escaped as [[ & ]]
- '* FROM [User]; DELETE FROM [User];SELECT [id]'
- .replaceAll('[', TICK_LEFT)
- .replaceAll(']', TICK_RIGHT),
- ],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself
- default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} FROM ${TICK_LEFT}User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`,
- ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"',
- },
- );
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: [
- // this is not wrapped in `literal()`, so it's a column name.
- // [ & ] will be escaped as [[ & ]]
- [
- '* FROM [User]; DELETE FROM [User];SELECT [id]'
- .replaceAll('[', Support.sequelize.dialect.TICK_CHAR_LEFT)
- .replaceAll(']', Support.sequelize.dialect.TICK_CHAR_RIGHT),
- 'data',
- ],
- ],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- // expectsql fails with consecutive TICKS so we add the dialect-specific one ourself
- default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT}; DELETE FROM ${TICK_LEFT}${TICK_LEFT}User${TICK_RIGHT}${TICK_RIGHT};SELECT ${TICK_LEFT}${TICK_LEFT}id${TICK_RIGHT}${TICK_RIGHT}${TICK_RIGHT} AS ${TICK_LEFT}Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];`,
- ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM ""User""; DELETE FROM ""User"";SELECT ""id""" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"',
- },
- );
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: [['* FROM User; DELETE FROM User;SELECT id', 'data']],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"',
- default:
- 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];',
- },
- );
- });
- });
- });
- describe('quoteIdentifiers: false', () => {
- let sql;
- beforeEach(() => {
- sql = createSequelizeInstance({
- quoteIdentifiers: false,
- }).queryGenerator;
- });
- it('*', () => {
- expectsql(sql.selectQuery('User'), {
- default: 'SELECT * FROM [User];',
- ibmi: 'SELECT * FROM "User"',
- postgres: 'SELECT * FROM "User";',
- snowflake: 'SELECT * FROM User;',
- });
- });
- it('with attributes', () => {
- expectsql(
- sql.selectQuery('User', {
- attributes: ['name', 'age'],
- }),
- {
- default: 'SELECT [name], [age] FROM [User];',
- ibmi: 'SELECT "name", "age" FROM "User"',
- postgres: 'SELECT name, age FROM "User";',
- snowflake: 'SELECT name, age FROM User;',
- },
- );
- });
- it('include (left outer join)', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- // association name is Pascal case to test quoteIdentifier: false
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id', as: 'Posts' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- default:
- 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];',
- ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."title" AS "Posts.title" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id"',
- postgres:
- 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;',
- snowflake:
- 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;',
- },
- );
- });
- it('nested include (left outer join)', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- const Comment = Support.sequelize.define(
- 'Comment',
- {
- title: DataTypes.STRING,
- },
- {
- freezeTableName: true,
- },
- );
- // association names are Pascal case to test quoteIdentifier: false
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id', as: 'Posts' });
- Post.Comments = Post.hasMany(Comment, { foreignKey: 'post_id', as: 'Comments' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age'],
- include: _validateIncludedElements({
- include: [
- {
- attributes: ['title'],
- association: User.Posts,
- include: [
- {
- model: Comment,
- },
- ],
- },
- ],
- model: User,
- }).include,
- model: User,
- },
- User,
- ),
- {
- default:
- 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title], [Posts->Comments].[id] AS [Posts.Comments.id], [Posts->Comments].[title] AS [Posts.Comments.title], [Posts->Comments].[createdAt] AS [Posts.Comments.createdAt], [Posts->Comments].[updatedAt] AS [Posts.Comments.updatedAt], [Posts->Comments].[post_id] AS [Posts.Comments.post_id] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id] LEFT OUTER JOIN [Comment] AS [Posts->Comments] ON [Posts].[id] = [Posts->Comments].[post_id];',
- ibmi: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."title" AS "Posts.title", "Posts->Comments"."id" AS "Posts.Comments.id", "Posts->Comments"."title" AS "Posts.Comments.title", "Posts->Comments"."createdAt" AS "Posts.Comments.createdAt", "Posts->Comments"."updatedAt" AS "Posts.Comments.updatedAt", "Posts->Comments"."post_id" AS "Posts.Comments.post_id" FROM "User" AS "User" LEFT OUTER JOIN "Post" AS "Posts" ON "User"."id" = "Posts"."user_id" LEFT OUTER JOIN "Comment" AS "Posts->Comments" ON "Posts"."id" = "Posts->Comments"."post_id"',
- postgres:
- 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;',
- snowflake:
- 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;',
- },
- );
- });
- it('attributes with dot notation', () => {
- const User = Support.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- age: DataTypes.INTEGER,
- statuslabel: {
- field: 'status.label',
- type: DataTypes.STRING,
- },
- },
- {
- freezeTableName: true,
- },
- );
- const Post = Support.sequelize.define(
- 'Post',
- {
- title: DataTypes.STRING,
- statuslabel: {
- field: 'status.label',
- type: DataTypes.STRING,
- },
- },
- {
- freezeTableName: true,
- },
- );
- // association name is Pascal case to test quoteIdentifier: false
- User.Posts = User.hasMany(Post, { foreignKey: 'user_id', as: 'Posts' });
- expectsql(
- sql.selectQuery(
- 'User',
- {
- attributes: ['name', 'age', ['status.label', 'statuslabel']],
- include: _validateIncludedElements({
- include: [
- {
- attributes: ['title', ['status.label', 'statuslabel']],
- association: User.Posts,
- },
- ],
- model: User,
- }).include,
- model: User,
- dotNotation: true,
- },
- User,
- ),
- {
- default:
- 'SELECT [User].[name], [User].[age], [User].[status.label] AS [statuslabel], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title], [Posts].[status.label] AS [Posts.statuslabel] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];',
- postgres:
- 'SELECT "User".name, "User".age, "User"."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;',
- snowflake:
- 'SELECT User.name, User.age, User."status.label" AS statuslabel, Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.statuslabel" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;',
- },
- );
- });
- });
- });
|