diff --git a/packages/sql/src/operators.js b/packages/sql/src/operators.js index 55f24c04..dda6d9b7 100644 --- a/packages/sql/src/operators.js +++ b/packages/sql/src/operators.js @@ -9,7 +9,12 @@ function visit(callback) { function logical(op, clauses) { const children = clauses.filter(x => x != null).map(asColumn); const strings = children.map((c, i) => i ? ` ${op} ` : ''); - if (clauses.length) strings.push(''); + if (children.length === 1) { + strings.push('') + } else if (children.length > 1) { + strings[0] = '('; + strings.push(')'); + } return sql(strings, ...children).annotate({ op, children, visit }); } diff --git a/packages/sql/test/operator-test.js b/packages/sql/test/operator-test.js index 2cd32ea1..ea8dd97c 100644 --- a/packages/sql/test/operator-test.js +++ b/packages/sql/test/operator-test.js @@ -12,7 +12,8 @@ describe('Logical operators', () => { assert.strictEqual(String(and()), ''); assert.strictEqual(String(and('foo')), '"foo"'); assert.strictEqual(String(and(null, true)), 'TRUE'); - assert.strictEqual(String(and(true, true)), 'TRUE AND TRUE'); + assert.strictEqual(String(and(true, true)), '(TRUE AND TRUE)'); + assert.strictEqual(String(and(true, null, false)), '(TRUE AND FALSE)'); assert.strictEqual(and().op, 'AND'); assert.strictEqual(and().children.length, 0); assert.strictEqual(and('foo').children.length, 1); @@ -23,7 +24,8 @@ describe('Logical operators', () => { assert.strictEqual(String(or()), ''); assert.strictEqual(String(or('foo')), '"foo"'); assert.strictEqual(String(or(null, true)), 'TRUE'); - assert.strictEqual(String(or(false, true)), 'FALSE OR TRUE'); + assert.strictEqual(String(or(false, true)), '(FALSE OR TRUE)'); + assert.strictEqual(String(or(false, null, false)), '(FALSE OR FALSE)'); assert.strictEqual(or().op, 'OR'); assert.strictEqual(or().children.length, 0); assert.strictEqual(or('foo').children.length, 1);