Skip to content

Commit

Permalink
Merge c63ce91 into c500d77
Browse files Browse the repository at this point in the history
  • Loading branch information
caseywebdev committed Nov 4, 2018
2 parents c500d77 + c63ce91 commit d308364
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 14 deletions.
46 changes: 33 additions & 13 deletions src/query/builder.js
Expand Up @@ -45,6 +45,22 @@ function Builder(client) {
}
inherits(Builder, EventEmitter);

const validateWithArgs = function(alias, statement, method) {
if (typeof alias !== 'string') {
throw new Error(`${method}() first argument must be a string`);
}
if (
typeof statement === 'function' ||
statement instanceof Builder ||
statement instanceof Raw
) {
return;
}
throw new Error(
`${method}() second argument must be a function / QueryBuilder or a raw`
);
};

assign(Builder.prototype, {
toString() {
return this.toQuery();
Expand Down Expand Up @@ -92,19 +108,8 @@ assign(Builder.prototype, {
// ------

with(alias, statement) {
if (typeof alias !== 'string') {
throw new Error('with() first argument must be a string');
}
if (
typeof statement === 'function' ||
statement instanceof Builder ||
statement instanceof Raw
) {
return this.withWrapped(alias, statement);
}
throw new Error(
'with() second argument must be a function / QueryBuilder or a raw'
);
validateWithArgs(alias, statement, 'with');
return this.withWrapped(alias, statement);
},

// Helper for compiling any advanced `with` queries.
Expand All @@ -118,6 +123,21 @@ assign(Builder.prototype, {
return this;
},

// With Recursive
// ------

withRecursive(alias, statement) {
validateWithArgs(alias, statement, 'withRecursive');
return this.withRecursiveWrapped(alias, statement);
},

// Helper for compiling any advanced `withRecursive` queries.
withRecursiveWrapped(alias, query) {
this.withWrapped(alias, query);
this._statements[this._statements.length - 1].recursive = true;
return this;
},

// Select
// ------

Expand Down
6 changes: 5 additions & 1 deletion src/query/compiler.js
Expand Up @@ -678,12 +678,16 @@ assign(QueryCompiler.prototype, {
if (!withs) return;
const sql = [];
let i = -1;
let isRecursive = false;
while (++i < withs.length) {
const stmt = withs[i];
if (stmt.recursive) {
isRecursive = true;
}
const val = this[stmt.type](stmt);
sql.push(val);
}
return 'with ' + sql.join(', ') + ' ';
return `with ${isRecursive ? 'recursive ' : ''}${sql.join(', ')} `;
},

withWrapped(statement) {
Expand Down
1 change: 1 addition & 0 deletions src/query/methods.js
Expand Up @@ -2,6 +2,7 @@
// from the `knex` object, e.g. `knex.select('*').from(...`
export default [
'with',
'withRecursive',
'select',
'as',
'columns',
Expand Down
38 changes: 38 additions & 0 deletions test/unit/query/builder.js
Expand Up @@ -8308,6 +8308,44 @@ describe('QueryBuilder', function() {
);
});

it("nested and chained wrapped 'withRecursive' clause", function() {
testsql(
qb()
.withRecursive('firstWithClause', function() {
this.withRecursive('firstWithSubClause', function() {
this.select('foo')
.as('foz')
.from('users');
})
.select('*')
.from('firstWithSubClause');
})
.withRecursive('secondWithClause', function() {
this.withRecursive('secondWithSubClause', function() {
this.select('bar')
.as('baz')
.from('users');
})
.select('*')
.from('secondWithSubClause');
})
.select('*')
.from('secondWithClause'),
{
mssql:
'with recursive [firstWithClause] as (with recursive [firstWithSubClause] as ((select [foo] from [users]) as [foz]) select * from [firstWithSubClause]), [secondWithClause] as (with recursive [secondWithSubClause] as ((select [bar] from [users]) as [baz]) select * from [secondWithSubClause]) select * from [secondWithClause]',
sqlite3:
'with recursive `firstWithClause` as (with recursive `firstWithSubClause` as ((select `foo` from `users`) as `foz`) select * from `firstWithSubClause`), `secondWithClause` as (with recursive `secondWithSubClause` as ((select `bar` from `users`) as `baz`) select * from `secondWithSubClause`) select * from `secondWithClause`',
pg:
'with recursive "firstWithClause" as (with recursive "firstWithSubClause" as ((select "foo" from "users") as "foz") select * from "firstWithSubClause"), "secondWithClause" as (with recursive "secondWithSubClause" as ((select "bar" from "users") as "baz") select * from "secondWithSubClause") select * from "secondWithClause"',
'pg-redshift':
'with recursive "firstWithClause" as (with recursive "firstWithSubClause" as ((select "foo" from "users") as "foz") select * from "firstWithSubClause"), "secondWithClause" as (with recursive "secondWithSubClause" as ((select "bar" from "users") as "baz") select * from "secondWithSubClause") select * from "secondWithClause"',
oracledb:
'with recursive "firstWithClause" as (with recursive "firstWithSubClause" as ((select "foo" from "users") "foz") select * from "firstWithSubClause"), "secondWithClause" as (with recursive "secondWithSubClause" as ((select "bar" from "users") "baz") select * from "secondWithSubClause") select * from "secondWithClause"',
}
);
});

describe('#2263, update / delete queries in with syntax', () => {
it('with update query passed as raw', () => {
testquery(
Expand Down

0 comments on commit d308364

Please sign in to comment.