Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add validation in .offset() #2908

Merged
merged 14 commits into from Oct 15, 2019
13 changes: 12 additions & 1 deletion lib/query/builder.js
Expand Up @@ -14,6 +14,7 @@ const {
isBoolean,
isEmpty,
isFunction,
isNil,
isNumber,
isObject,
isString,
Expand Down Expand Up @@ -856,7 +857,17 @@ assign(Builder.prototype, {

// Only allow a single "offset" to be set for the current query.
offset(value) {
this._single.offset = value;
if (isNil(value) || value instanceof Raw || value instanceof Builder) {
// Builder for backward compatibility
this._single.offset = value;
} else {
const val = parseInt(value, 10);
if (isNaN(val)) {
this.client.logger.warn('A valid integer must be provided to offset');
} else {
this._single.offset = val;
}
}
return this;
},

Expand Down
153 changes: 153 additions & 0 deletions test/unit/query/builder.js
Expand Up @@ -40,6 +40,32 @@ const clientsWithNullAsDefault = {
),
};

var customLoggerConfig = {
HurSungYun marked this conversation as resolved.
Show resolved Hide resolved
log: {
warn: function(message) {
throw new Error(message);
},
},
};
var clientsWithCustomLoggerForTestWarnings = {
mysql: new MySQL_Client(
Object.assign({ client: 'mysql' }, customLoggerConfig)
),
pg: new PG_Client(Object.assign({ client: 'pg' }, customLoggerConfig)),
'pg-redshift': new Redshift_Client(
Object.assign({ client: 'redshift' }, customLoggerConfig)
),
oracledb: new Oracledb_Client(
Object.assign({ client: 'oracledb' }, customLoggerConfig)
),
// sqlite3: new SQLite3_Client(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was no sqlite3 tests using offset a year ago.

maybe someone have missed test code so I did the same thing.

still some test does not include sqlite3, but it may be fixed in another PR.

anyway I un-commented it.

// Object.assign({ client: 'sqlite3' }, customLoggerConfig)
// ),
mssql: new MSSQL_Client(
Object.assign({ client: 'mssql' }, customLoggerConfig)
),
};

// note: as a workaround, we are using postgres here, since that's using the default " field wrapping
// otherwise subquery cloning would need to be fixed. See: https://github.com/tgriesser/knex/pull/2063
function qb() {
Expand Down Expand Up @@ -3868,6 +3894,39 @@ describe('QueryBuilder', () => {
);
});

it('limits and offsets with raw', () => {
testsql(
qb()
.select('*')
.from('users')
.offset(raw('5'))
.limit(raw('10')),
{
mysql: {
sql: 'select * from `users` limit ? offset 5',
bindings: [10],
},
mssql: {
sql: 'select * from [users] offset 5 rows fetch next ? rows only',
bindings: [10],
},
oracledb: {
sql:
'select * from (select row_.*, ROWNUM rownum_ from (select * from "users") row_ where rownum <= ?) where rownum_ > 5',
bindings: [15],
},
pg: {
sql: 'select * from "users" limit ? offset 5',
bindings: [10],
},
'pg-redshift': {
sql: 'select * from "users" limit ? offset 5',
bindings: [10],
},
}
);
});

it('limits and raw selects', () => {
testsql(
qb()
Expand Down Expand Up @@ -7177,6 +7236,100 @@ describe('QueryBuilder', () => {
);
});

it('should throw warning with null call in limit', function() {
try {
testsql(
qb()
.from('test')
.limit(null),
{
mysql: {
sql: 'select * from `test`',
bindings: [],
},
mssql: {
sql: 'select * from [test]',
bindings: [],
},
pg: {
sql: 'select * from "test"',
bindings: [],
},
'pg-redshift': {
sql: 'select * from "test"',
bindings: [],
},
},
clientsWithCustomLoggerForTestWarnings
);
} catch (error) {
expect(error.message).to.equal(
'A valid integer must be provided to limit'
);
}
});

it('should do nothing with offset when passing null', () => {
testsql(
qb()
.from('test')
.limit(10)
.offset(null),
{
mysql: {
sql: 'select * from `test` limit ?',
bindings: [10],
},
mssql: {
sql: 'select top (?) * from [test]',
bindings: [10],
},
pg: {
sql: 'select * from "test" limit ?',
bindings: [10],
},
'pg-redshift': {
sql: 'select * from "test" limit ?',
bindings: [10],
},
}
);
});

it('should throw warning with wrong value call in offset', function() {
try {
testsql(
qb()
.from('test')
.limit(10)
.offset('$10'),
{
mysql: {
sql: 'select * from `test` limit ?',
bindings: [10],
},
mssql: {
sql: 'select top (?) * from [test]',
bindings: [10],
},
pg: {
sql: 'select * from "test" limit ?',
bindings: [10],
},
'pg-redshift': {
sql: 'select * from "test" limit ?',
bindings: [10],
},
},
clientsWithCustomLoggerForTestWarnings
);
} catch (error) {
expect(error.message).to.equal(
'A valid integer must be provided to offset'
);
}
});

it('should clear offset when passing null', () => {
testsql(
qb()
Expand Down