### Copyright (c) 2014 Ramesh Nair (hiddentao.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ### squel = require "../dist/squel-basic" {_, testCreator, assert, expect, should} = require './testbase' test = testCreator() test['Blocks'] = 'Block base class': beforeEach: -> @inst = new squel.cls.Block() 'instanceof of BaseBuilder': -> assert.instanceOf @inst, squel.cls.BaseBuilder 'options': -> expectedOptions = _.extend {}, squel.cls.DefaultQueryBuilderOptions, usingValuePlaceholders: true dummy: true @inst = new squel.cls.Block usingValuePlaceholders: true dummy: true assert.same expectedOptions, @inst.options '_toParamString()': -> assert.throws (=> @inst.toString()), 'Not yet implemented' 'exposedMethods()': 'returns methods': -> @inst['method1'] = -> return false @inst['method2'] = -> return false assert.ok ['method1', 'method2'], (name for name of @inst.exposedMethods()) 'ignores methods prefixed with _': -> @inst['_method'] = -> return false assert.ok undefined is _.find (name for name of @inst.exposedMethods()), (name) -> return name is '_method' 'ignores toString()': -> assert.ok undefined is _.find (name for name of @inst.exposedMethods()), (name) -> return name is 'toString' 'cloning copies the options over': -> @inst.options.dummy = true; newinst = @inst.clone() @inst.options.dummy = false; assert.same true, newinst.options.dummy 'StringBlock': beforeEach: -> @cls = squel.cls.StringBlock @inst = new @cls 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block '_toParamString()': 'non-parameterized': -> @inst = new @cls {}, 'TAG' assert.same @inst._toParamString(), { text: 'TAG' values: [] } 'parameterized': -> @inst = new @cls {}, 'TAG' assert.same @inst._toParamString(buildParameterized: true), { text: 'TAG' values: [] } 'FunctionBlock': beforeEach: -> @cls = squel.cls.FunctionBlock @inst = new @cls 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'initial member values': -> assert.same [], @inst._values assert.same [], @inst._strings '_toParamString()': 'when not set': -> assert.same @inst._toParamString(), { text: '' values: [] } 'non-parameterized': -> @inst.function('bla') @inst.function('bla2') assert.same @inst._toParamString(), { text: 'bla bla2', values: [] } 'parameterized': -> @inst.function('bla ?', 2) @inst.function('bla2 ?', 3) assert.same @inst._toParamString(buildParameterized: true), { text: 'bla ? bla2 ?', values: [2, 3] } 'AbstractTableBlock': beforeEach: -> @cls = squel.cls.AbstractTableBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'initial field values': -> assert.same [], @inst._tables 'has table': 'no': -> assert.same false, @inst._hasTable() 'yes': -> @inst._table('blah') assert.same true, @inst._hasTable() '_table()': 'saves inputs': -> @inst._table('table1') @inst._table('table2', 'alias2') @inst._table('table3') expectedFroms = [ { table: 'table1', alias: null }, { table: 'table2', alias: 'alias2' }, { table: 'table3', alias: null } ] assert.same expectedFroms, @inst._tables 'sanitizes inputs': -> sanitizeTableSpy = test.mocker.stub @cls.prototype, '_sanitizeTable', -> return '_t' sanitizeAliasSpy = test.mocker.stub @cls.prototype, '_sanitizeTableAlias', -> return '_a' @inst._table('table', 'alias') assert.ok sanitizeTableSpy.calledWith 'table' assert.ok sanitizeAliasSpy.calledWithExactly 'alias' assert.same [ { table: '_t', alias: '_a' }], @inst._tables 'handles single-table mode': -> @inst.options.singleTable = true @inst._table('table1') @inst._table('table2') @inst._table('table3') expected = [ { table: 'table3', alias: null } ] assert.same expected, @inst._tables 'builder as table': -> sanitizeTableSpy = test.mocker.spy @cls.prototype, '_sanitizeTable' innerTable1 = squel.select() innerTable2 = squel.select() @inst._table(innerTable1) @inst._table(innerTable2, 'Inner2') assert.ok sanitizeTableSpy.calledWithExactly innerTable1 assert.ok sanitizeTableSpy.calledWithExactly innerTable2 expected = [ { alias: null table: innerTable1 } { alias: 'Inner2' table: innerTable2 } ] assert.same expected, @inst._tables '_toParamString()': beforeEach: -> @innerTable1 = squel.select().from('inner1').where('a = ?', 3) 'no table': -> assert.same @inst._toParamString(), { text: '' values: [] } 'prefix': -> @inst.options.prefix = 'TEST' @inst._table('table2', 'alias2') assert.same @inst._toParamString(), { text: 'TEST table2 `alias2`', values: [] } 'non-parameterized': -> @inst._table(@innerTable1) @inst._table('table2', 'alias2') @inst._table('table3') assert.same @inst._toParamString(), { text: '(SELECT * FROM inner1 WHERE (a = 3)), table2 `alias2`, table3' values: [] } 'parameterized': -> @inst._table(@innerTable1) @inst._table('table2', 'alias2') @inst._table('table3') assert.same @inst._toParamString(buildParameterized: true), { text: '(SELECT * FROM inner1 WHERE (a = ?)), table2 `alias2`, table3' values: [3] } 'FromTableBlock': beforeEach: -> @cls = squel.cls.FromTableBlock @inst = new @cls() 'check prefix': -> assert.same @inst.options.prefix, 'FROM' 'instanceof of AbstractTableBlock': -> assert.instanceOf @inst, squel.cls.AbstractTableBlock 'from()': 'calls base class handler': -> baseMethodSpy = test.mocker.stub squel.cls.AbstractTableBlock.prototype, '_table' @inst.from('table1') @inst.from('table2', 'alias2') assert.same 2, baseMethodSpy.callCount assert.ok baseMethodSpy.calledWithExactly('table1', null) assert.ok baseMethodSpy.calledWithExactly('table2', 'alias2') 'UpdateTableBlock': beforeEach: -> @cls = squel.cls.UpdateTableBlock @inst = new @cls() 'instanceof of AbstractTableBlock': -> assert.instanceOf @inst, squel.cls.AbstractTableBlock 'check prefix': -> assert.same @inst.options.prefix, undefined 'table()': 'calls base class handler': -> baseMethodSpy = test.mocker.stub squel.cls.AbstractTableBlock.prototype, '_table' @inst.table('table1') @inst.table('table2', 'alias2') assert.same 2, baseMethodSpy.callCount assert.ok baseMethodSpy.calledWithExactly('table1', null) assert.ok baseMethodSpy.calledWithExactly('table2', 'alias2') 'TargetTableBlock': beforeEach: -> @cls = squel.cls.TargetTableBlock @inst = new @cls() 'instanceof of AbstractTableBlock': -> assert.instanceOf @inst, squel.cls.AbstractTableBlock 'check prefix': -> assert.same @inst.options.prefix, undefined 'table()': 'calls base class handler': -> baseMethodSpy = test.mocker.stub squel.cls.AbstractTableBlock.prototype, '_table' @inst.target('table1') @inst.target('table2') assert.same 2, baseMethodSpy.callCount assert.ok baseMethodSpy.calledWithExactly('table1') assert.ok baseMethodSpy.calledWithExactly('table2') 'IntoTableBlock': beforeEach: -> @cls = squel.cls.IntoTableBlock @inst = new @cls() 'instanceof of AbstractTableBlock': -> assert.instanceOf @inst, squel.cls.AbstractTableBlock 'check prefix': -> assert.same @inst.options.prefix, 'INTO' 'single table': -> assert.ok @inst.options.singleTable 'into()': 'calls base class handler': -> baseMethodSpy = test.mocker.stub squel.cls.AbstractTableBlock.prototype, '_table' @inst.into('table1') @inst.into('table2') assert.same 2, baseMethodSpy.callCount assert.ok baseMethodSpy.calledWith('table1') assert.ok baseMethodSpy.calledWith('table2') '_toParamString()': 'requires table to have been provided': -> try @inst._toParamString() throw new Error 'should not reach here' catch err assert.same 'Error: into() needs to be called', err.toString() 'GetFieldBlock': beforeEach: -> @cls = squel.cls.GetFieldBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'fields() - object': 'saves inputs': -> fieldSpy = test.mocker.spy(@inst, 'field') @inst.fields({ 'field1': null 'field2': 'alias2' 'field3': null }, { dummy: true}) expected = [ { name: 'field1', alias: null, options: { dummy: true } }, { name: 'field2', alias: 'alias2' options: { dummy: true } }, { name: 'field3', alias: null options: { dummy: true } } ] assert.ok fieldSpy.calledThrice assert.ok fieldSpy.calledWithExactly('field1', null, dummy: true) assert.ok fieldSpy.calledWithExactly('field2', 'alias2', dummy: true) assert.ok fieldSpy.calledWithExactly('field3', null, dummy: true) assert.same expected, @inst._fields 'fields() - array': 'saves inputs': -> fieldSpy = test.mocker.spy(@inst, 'field') @inst.fields([ 'field1', 'field2', 'field3' ], { dummy: true}) expected = [ { name: 'field1', alias: null options: { dummy: true } }, { name: 'field2', alias: null options: { dummy: true } }, { name: 'field3', alias: null options: { dummy: true } } ] assert.ok fieldSpy.calledThrice assert.ok fieldSpy.calledWithExactly('field1', null, dummy: true) assert.ok fieldSpy.calledWithExactly('field2', null, dummy: true) assert.ok fieldSpy.calledWithExactly('field3', null, dummy: true) assert.same expected, @inst._fields 'field()': 'saves inputs': -> @inst.field('field1') @inst.field('field2', 'alias2') @inst.field('field3') expected = [ { name: 'field1', alias: null, options: {}, }, { name: 'field2', alias: 'alias2' options: {}, }, { name: 'field3', alias: null options: {}, } ] assert.same expected, @inst._fields 'field() - discard duplicates': 'saves inputs': -> @inst.field('field1') @inst.field('field2', 'alias2') @inst.field('field2', 'alias2') @inst.field('field1', 'alias1') expected = [ { name: 'field1', alias: null options: {}, }, { name: 'field2', alias: 'alias2' options: {}, }, { name: 'field1', alias: 'alias1' options: {}, } ] assert.same expected, @inst._fields 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> return '_f' sanitizeAliasSpy = test.mocker.stub @cls.prototype, '_sanitizeFieldAlias', -> return '_a' @inst.field('field1', 'alias1', { dummy: true}) assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.ok sanitizeAliasSpy.calledWithExactly 'alias1' assert.same @inst._fields, [ { name: '_f', alias: '_a' options: dummy: true } ] '_toParamString()': beforeEach: -> @queryBuilder = squel.select() @fromTableBlock = @queryBuilder.getBlock(squel.cls.FromTableBlock) 'returns all fields when none provided and table is set': -> @fromTableBlock._hasTable = -> true assert.same @inst._toParamString(queryBuilder: @queryBuilder), { text: '*', values: [] } 'but returns nothing if no table set': -> @fromTableBlock._hasTable = -> false assert.same @inst._toParamString(queryBuilder: @queryBuilder), { text: '' values: [] } 'returns formatted query phrase': -> beforeEach: -> @fromTableBlock._hasTable = -> true @inst.field(squel.str('GETDATE(?)', 3), 'alias1') @inst.field('field2', 'alias2', { dummy: true }) @inst.field('field3') 'non-parameterized': -> assert.same @inst._toParamString(queryBuilder: @queryBuilder), { text: '(GETDATE(3)) AS "alias1", field2 AS "alias2", field3' values: [] } 'parameterized': -> assert.same @inst._toParamString(queryBuilder: @queryBuilder, buildParameterized: true), { text: '(GETDATE(?)) AS "alias1", field2 AS "alias2", field3' values: [3] } 'AbstractSetFieldBlock': beforeEach: -> @cls = squel.cls.AbstractSetFieldBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block '_set()': 'saves inputs': -> @inst._set('field1', 'value1', dummy: 1) @inst._set('field2', 'value2', dummy: 2) @inst._set('field3', 'value3', dummy: 3) @inst._set('field4') expectedFields = [ 'field1', 'field2', 'field3', 'field4' ] expectedValues = [ [ 'value1', 'value2', 'value3', undefined ] ] expectedFieldOptions = [ [ {dummy: 1}, {dummy: 2}, {dummy: 3}, {} ] ] assert.same expectedFields, @inst._fields assert.same expectedValues, @inst._values assert.same expectedFieldOptions, @inst._valueOptions 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> '_f' sanitizeValueSpy = test.mocker.stub @cls.prototype, '_sanitizeValue', -> '_v' @inst._set('field1', 'value1', dummy: true) assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.ok sanitizeValueSpy.calledWithExactly 'value1' assert.same [ '_f' ], @inst._fields assert.same [ [ '_v' ] ], @inst._values '_setFields()': 'saves inputs': -> @inst._setFields 'field1': 'value1' 'field2': 'value2' 'field3': 'value3' expectedFields = [ 'field1', 'field2', 'field3' ] expectedValues = [ [ 'value1', 'value2', 'value3'] ] expectedFieldOptions = [ [ {}, {}, {} ] ] assert.same expectedFields, @inst._fields assert.same expectedValues, @inst._values assert.same expectedFieldOptions, @inst._valueOptions 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> '_f' sanitizeValueSpy = test.mocker.stub @cls.prototype, '_sanitizeValue', -> '_v' @inst._setFields({'field1': 'value1'}, {dummy: true}) assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.ok sanitizeValueSpy.calledWithExactly 'value1' assert.same [ '_f' ], @inst._fields assert.same [ [ '_v' ] ], @inst._values '_setFieldsRows()': 'saves inputs': -> @inst._setFieldsRows [ { 'field1': 'value1' 'field2': 'value2' 'field3': 'value3' } { 'field1': 'value21' 'field2': 'value22' 'field3': 'value23' } ] expectedFields = [ 'field1', 'field2', 'field3' ] expectedValues = [ [ 'value1', 'value2', 'value3' ], [ 'value21', 'value22', 'value23' ] ] expectedFieldOptions = [ [ {}, {}, {} ], [ {}, {}, {} ] ] assert.same expectedFields, @inst._fields assert.same expectedValues, @inst._values assert.same expectedFieldOptions, @inst._valueOptions 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> return '_f' sanitizeValueSpy = test.mocker.stub @cls.prototype, '_sanitizeValue', -> return '_v' @inst._setFieldsRows [ { 'field1': 'value1' }, { 'field1': 'value21' } ], { dummy: true } assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.ok sanitizeValueSpy.calledWithExactly 'value1' assert.ok sanitizeValueSpy.calledWithExactly 'value21' assert.same [ '_f' ], @inst._fields assert.same [ [ '_v' ], [ '_v' ] ], @inst._values '_toParamString()': -> assert.throws ( => @inst._toParamString()), 'Not yet implemented' 'SetFieldBlock': beforeEach: -> @cls = squel.cls.SetFieldBlock @inst = new @cls() 'instanceof of AbstractSetFieldBlock': -> assert.instanceOf @inst, squel.cls.AbstractSetFieldBlock 'set()': 'calls to _set()': -> spy = test.mocker.stub @inst, '_set' @inst.set 'f', 'v', dummy: true assert.ok spy.calledWithExactly('f', 'v', dummy: true) 'setFields()': 'calls to _setFields()': -> spy = test.mocker.stub @inst, '_setFields' @inst.setFields 'f', dummy: true assert.ok spy.calledWithExactly('f', dummy: true) '_toParamString()': 'needs at least one field to have been provided': -> try @inst.toString() throw new Error 'should not reach here' catch err assert.same 'Error: set() needs to be called', err.toString() 'fields set': beforeEach: -> @inst.set('field0 = field0 + 1') @inst.set('field1', 'value1', { dummy: true }) @inst.set('field2', 'value2') @inst.set('field3', squel.str('GETDATE(?)', 4)) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'SET field0 = field0 + 1, field1 = \'value1\', field2 = \'value2\', field3 = (GETDATE(4))', values: [], } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'SET field0 = field0 + 1, field1 = ?, field2 = ?, field3 = (GETDATE(?))', values: ['value1', 'value2', 4], } 'InsertFieldValueBlock': beforeEach: -> @cls = squel.cls.InsertFieldValueBlock @inst = new @cls() 'instanceof of AbstractSetFieldBlock': -> assert.instanceOf @inst, squel.cls.AbstractSetFieldBlock 'set()': 'calls to _set()': -> spy = test.mocker.stub @inst, '_set' @inst.set 'f', 'v', dummy: true assert.ok spy.calledWithExactly('f', 'v', dummy: true) 'setFields()': 'calls to _setFields()': -> spy = test.mocker.stub @inst, '_setFields' @inst.setFields 'f', dummy: true assert.ok spy.calledWithExactly('f', dummy: true) 'setFieldsRows()': 'calls to _setFieldsRows()': -> spy = test.mocker.stub @inst, '_setFieldsRows' @inst.setFieldsRows 'f', dummy: true assert.ok spy.calledWithExactly('f', dummy: true) '_toParamString()': 'needs at least one field to have been provided': -> assert.same '', @inst.toString() 'got fields': beforeEach: -> @inst.setFieldsRows([ { field1: 9, field2: 'value2', field3: squel.str('GETDATE(?)', 5) } { field1: 8, field2: true, field3: null } ]) 'non-parameterized': -> assert.same @inst._toParamString(), { text: '(field1, field2, field3) VALUES (9, \'value2\', (GETDATE(5))), (8, TRUE, NULL)' values: [], } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: '(field1, field2, field3) VALUES (?, ?, (GETDATE(?))), (?, ?, ?)' values: [9, 'value2', 5, 8, true, null], } 'InsertFieldsFromQueryBlock': beforeEach: -> @cls = squel.cls.InsertFieldsFromQueryBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'fromQuery()': 'sanitizes field names': -> spy = test.mocker.stub @inst, '_sanitizeField', -> 1 qry = squel.select() @inst.fromQuery(['test', 'one', 'two'], qry) assert.ok spy.calledThrice assert.ok spy.calledWithExactly 'test' assert.ok spy.calledWithExactly 'one' assert.ok spy.calledWithExactly 'two' 'sanitizes query': -> spy = test.mocker.stub @inst, '_sanitizeBaseBuilder', -> 1 qry = 123 @inst.fromQuery(['test', 'one', 'two'], qry) assert.ok spy.calledOnce assert.ok spy.calledWithExactly qry 'overwrites existing values': -> @inst._fields = 1 @inst._query = 2 qry = squel.select() @inst.fromQuery(['test', 'one', 'two'], qry) assert.same qry, @inst._query assert.same ['test', 'one', 'two'], @inst._fields '_toParamString()': 'needs fromQuery() to have been called': -> assert.same @inst._toParamString(), { text: '' values: [] } 'default': beforeEach: -> @qry = squel.select().from('mega').where('a = ?', 5) @inst.fromQuery ['test', 'one', 'two'], @qry 'non-parameterized': -> assert.same @inst._toParamString(), { text: "(test, one, two) (SELECT * FROM mega WHERE (a = 5))" values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: "(test, one, two) (SELECT * FROM mega WHERE (a = ?))" values: [5] } 'DistinctBlock': beforeEach: -> @cls = squel.cls.DistinctBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block '_toParamString()': 'output nothing if not set': -> assert.same @inst._toParamString(), { text: '' values: [] } 'output DISTINCT if set': -> @inst.distinct() assert.same @inst._toParamString(), { text: 'DISTINCT' values: [] } 'GroupByBlock': beforeEach: -> @cls = squel.cls.GroupByBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'group()': 'adds to list': -> @inst.group('field1') @inst.group('field2') assert.same ['field1', 'field2'], @inst._groups 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> return '_f' @inst.group('field1') assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.same ['_f'], @inst._groups 'toString()': 'output nothing if no fields set': -> @inst._groups = [] assert.same '', @inst.toString() 'output GROUP BY': -> @inst.group('field1') @inst.group('field2') assert.same 'GROUP BY field1, field2', @inst.toString() 'OffsetBlock': beforeEach: -> @cls = squel.cls.OffsetBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'offset()': 'set value': -> @inst.offset(1) assert.same 1, @inst._offsets @inst.offset(22) assert.same 22, @inst._offsets 'sanitizes inputs': -> sanitizeSpy = test.mocker.stub @cls.prototype, '_sanitizeLimitOffset', -> return 234 @inst.offset(23) assert.ok sanitizeSpy.calledWithExactly 23 assert.same 234, @inst._offsets 'toString()': 'output nothing if not set': -> @inst._offsets = null assert.same '', @inst.toString() 'output OFFSET': -> @inst.offset(12) assert.same 'OFFSET 12', @inst.toString() 'AbstractConditionBlock': beforeEach: -> @cls = squel.cls.AbstractConditionBlock @inst = new @cls { verb: 'ACB' } class squel.cls.MockConditionBlock extends squel.cls.AbstractConditionBlock constructor: (options) -> super _.extend({}, options, {verb: 'MOCKVERB'}) mockCondition: (condition, values...) -> @_condition condition, values... class squel.cls.MockSelectWithCondition extends squel.cls.Select constructor: (options, blocks = null) -> blocks = [ new squel.cls.StringBlock(options, 'SELECT'), new squel.cls.GetFieldBlock(options), new squel.cls.FromTableBlock(options), new squel.cls.MockConditionBlock(options) ] super options, blocks 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block '_condition()': 'adds to list': -> @inst._condition('a = 1') @inst._condition('b = 2 OR c = 3') assert.same [ { expr: 'a = 1' values: [] } { expr: 'b = 2 OR c = 3' values: [] } ], @inst._conditions 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeExpression', -> return '_c' @inst._condition('a = 1') assert.ok sanitizeFieldSpy.calledWithExactly 'a = 1' assert.same [{ expr: '_c' values: [] }], @inst._conditions '_toParamString()': 'output nothing if no conditions set': -> assert.same @inst._toParamString(), { text: '' values: [] } 'output QueryBuilder ': beforeEach: -> subquery = new squel.cls.MockSelectWithCondition() subquery.field('col1').from('table1').mockCondition('field1 = ?', 10) @inst._condition('a in ?', subquery) @inst._condition('b = ? OR c = ?', 2, 3) @inst._condition('d in ?', [4, 5, 6]) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'ACB (a in (SELECT col1 FROM table1 MOCKVERB (field1 = 10))) AND (b = 2 OR c = 3) AND (d in (4, 5, 6))' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'ACB (a in (SELECT col1 FROM table1 MOCKVERB (field1 = ?))) AND (b = ? OR c = ?) AND (d in (?, ?, ?))' values: [10, 2, 3, 4, 5, 6] } 'Fix for #64 - toString() does not change object': beforeEach: -> @inst._condition('a = ?', 1) @inst._condition('b = ? OR c = ?', 2, 3) @inst._condition('d in ?', [4, 5, 6]) @inst._toParamString() @inst._toParamString() 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'ACB (a = 1) AND (b = 2 OR c = 3) AND (d in (4, 5, 6))' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'ACB (a = ?) AND (b = ? OR c = ?) AND (d in (?, ?, ?))' values: [1, 2, 3, 4, 5, 6] } 'Fix for #226 - empty expressions': beforeEach: -> @inst._condition('a = ?', 1) @inst._condition(squel.expr()) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'ACB (a = 1)' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'ACB (a = ?)' values: [1] } 'WhereBlock': beforeEach: -> @cls = squel.cls.WhereBlock @inst = new @cls() 'instanceof of AbstractConditionBlock': -> assert.instanceOf @inst, squel.cls.AbstractConditionBlock 'sets verb to WHERE': -> @inst = new @cls assert.same 'WHERE', @inst.options.verb '_toParamString()': 'output nothing if no conditions set': -> assert.same @inst._toParamString(), { text: '' values: [] } 'output': beforeEach: -> subquery = new squel.cls.Select() subquery.field('col1').from('table1').where('field1 = ?', 10) @inst.where('a in ?', subquery) @inst.where('b = ? OR c = ?', 2, 3) @inst.where('d in ?', [4, 5, 6]) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'WHERE (a in (SELECT col1 FROM table1 WHERE (field1 = 10))) AND (b = 2 OR c = 3) AND (d in (4, 5, 6))' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'WHERE (a in (SELECT col1 FROM table1 WHERE (field1 = ?))) AND (b = ? OR c = ?) AND (d in (?, ?, ?))' values: [10, 2, 3, 4, 5, 6] } 'HavingBlock': beforeEach: -> @cls = squel.cls.HavingBlock @inst = new @cls() 'instanceof of AbstractConditionBlock': -> assert.instanceOf @inst, squel.cls.AbstractConditionBlock 'sets verb': -> @inst = new @cls assert.same 'HAVING', @inst.options.verb '_toParamString()': 'output nothing if no conditions set': -> assert.same @inst._toParamString(), { text: '' values: [] } 'output': beforeEach: -> subquery = new squel.cls.Select() subquery.field('col1').from('table1').where('field1 = ?', 10) @inst.having('a in ?', subquery) @inst.having('b = ? OR c = ?', 2, 3) @inst.having('d in ?', [4, 5, 6]) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'HAVING (a in (SELECT col1 FROM table1 WHERE (field1 = 10))) AND (b = 2 OR c = 3) AND (d in (4, 5, 6))' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'HAVING (a in (SELECT col1 FROM table1 WHERE (field1 = ?))) AND (b = ? OR c = ?) AND (d in (?, ?, ?))' values: [10, 2, 3, 4, 5, 6] } 'OrderByBlock': beforeEach: -> @cls = squel.cls.OrderByBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'order()': 'adds to list': -> @inst.order('field1') @inst.order('field2', false) @inst.order('field3', true) expected = [ { field: 'field1', dir: true values: [] }, { field: 'field2', dir: false values: [] }, { field: 'field3', dir: true values: [] } ] assert.same @inst._orders, expected 'sanitizes inputs': -> sanitizeFieldSpy = test.mocker.stub @cls.prototype, '_sanitizeField', -> return '_f' @inst.order('field1') assert.ok sanitizeFieldSpy.calledWithExactly 'field1' assert.same @inst._orders, [ { field: '_f', dir: true, values: [] } ] 'saves additional values': -> @inst.order('field1', false, 1.2, 4) assert.same @inst._orders, [ { field: 'field1', dir: false, values: [1.2, 4] } ] '_toParamString()': 'empty': -> assert.same @inst._toParamString(), { text: '', values: [] } 'default': -> beforeEach: -> @inst.order('field1') @inst.order('field2', false) @inst.order('GET(?, ?)', true, 2.5 ,5) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'ORDER BY field1 ASC, field2 DESC, GET(2.5, 5) ASC', values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'ORDER BY field1 ASC, field2 DESC, GET(?, ?) ASC', values: [2.5, 5] } 'LimitBlock': beforeEach: -> @cls = squel.cls.LimitBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'limit()': 'set value': -> @inst.limit(1) assert.same 1, @inst._limit @inst.limit(22) assert.same 22, @inst._limit 'sanitizes inputs': -> sanitizeSpy = test.mocker.stub @cls.prototype, '_sanitizeLimitOffset', -> return 234 @inst.limit(23) assert.ok sanitizeSpy.calledWithExactly 23 assert.same 234, @inst._limit '_toParamString()': 'output nothing if not set': -> assert.same @inst._toParamString(), { text: '', values: [] } 'default': beforeEach: -> @inst.limit(10) 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'LIMIT 10' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'LIMIT 10' values: [] } 'JoinBlock': beforeEach: -> @cls = squel.cls.JoinBlock @inst = new @cls() 'instanceof of Block': -> assert.instanceOf @inst, squel.cls.Block 'join()': 'adds to list': -> @inst.join('table1') @inst.join('table2', null, 'b = 1', 'LEFT') @inst.join('table3', 'alias3', 'c = 1', 'RIGHT') @inst.join('table4', 'alias4', 'd = 1', 'OUTER') @inst.join('table5', 'alias5', null, 'CROSS') expected = [ { type: 'INNER', table: 'table1', alias: null, condition: null }, { type: 'LEFT', table: 'table2', alias: null, condition: 'b = 1' }, { type: 'RIGHT', table: 'table3', alias: 'alias3', condition: 'c = 1' }, { type: 'OUTER', table: 'table4', alias: 'alias4', condition: 'd = 1' }, { type: 'CROSS', table: 'table5', alias: 'alias5', condition: null } ] assert.same @inst._joins, expected 'sanitizes inputs': -> sanitizeTableSpy = test.mocker.stub @cls.prototype, '_sanitizeTable', -> return '_t' sanitizeAliasSpy = test.mocker.stub @cls.prototype, '_sanitizeTableAlias', -> return '_a' sanitizeConditionSpy = test.mocker.stub @cls.prototype, '_sanitizeExpression', -> return '_c' @inst.join('table1', 'alias1', 'a = 1') assert.ok sanitizeTableSpy.calledWithExactly 'table1', true assert.ok sanitizeAliasSpy.calledWithExactly 'alias1' assert.ok sanitizeConditionSpy.calledWithExactly 'a = 1' expected = [ { type: 'INNER', table: '_t', alias: '_a', condition: '_c' } ] assert.same @inst._joins, expected 'nested queries': -> inner1 = squel.select() inner2 = squel.select() inner3 = squel.select() inner4 = squel.select() inner5 = squel.select() inner6 = squel.select() @inst.join(inner1) @inst.join(inner2, null, 'b = 1', 'LEFT') @inst.join(inner3, 'alias3', 'c = 1', 'RIGHT') @inst.join(inner4, 'alias4', 'd = 1', 'OUTER') @inst.join(inner5, 'alias5', 'e = 1', 'FULL') @inst.join(inner6, 'alias6', null, 'CROSS') expected = [ { type: 'INNER', table: inner1, alias: null, condition: null }, { type: 'LEFT', table: inner2, alias: null, condition: 'b = 1' }, { type: 'RIGHT', table: inner3, alias: 'alias3', condition: 'c = 1' }, { type: 'OUTER', table: inner4, alias: 'alias4', condition: 'd = 1' }, { type: 'FULL', table: inner5, alias: 'alias5', condition: 'e = 1' }, { type: 'CROSS', table: inner6, alias: 'alias6', condition: null } ] assert.same @inst._joins, expected 'left_join()': 'calls join()': -> joinSpy = test.mocker.stub(@inst, 'join') @inst.left_join('t', 'a', 'c') assert.ok joinSpy.calledOnce assert.ok joinSpy.calledWithExactly('t', 'a', 'c', 'LEFT') '_toParamString()': 'output nothing if nothing set': -> assert.same @inst._toParamString(), { text: '', values: [] } 'output JOINs with nested queries': beforeEach: -> inner2 = squel.select().function('GETDATE(?)', 2) inner3 = squel.select().from('3') inner4 = squel.select().from('4') inner5 = squel.select().from('5') expr = squel.expr().and('field1 = ?', 99) @inst.join('table') @inst.join(inner2, null, 'b = 1', 'LEFT') @inst.join(inner3, 'alias3', 'c = 1', 'RIGHT') @inst.join(inner4, 'alias4', 'e = 1', 'FULL') @inst.join(inner5, 'alias5', expr, 'CROSS') 'non-parameterized': -> assert.same @inst._toParamString(), { text: 'INNER JOIN table LEFT JOIN (SELECT GETDATE(2)) ON (b = 1) RIGHT JOIN (SELECT * FROM 3) `alias3` ON (c = 1) FULL JOIN (SELECT * FROM 4) `alias4` ON (e = 1) CROSS JOIN (SELECT * FROM 5) `alias5` ON (field1 = 99)' values: [] } 'parameterized': -> assert.same @inst._toParamString(buildParameterized: true), { text: 'INNER JOIN table LEFT JOIN (SELECT GETDATE(?)) ON (b = 1) RIGHT JOIN (SELECT * FROM 3) `alias3` ON (c = 1) FULL JOIN (SELECT * FROM 4) `alias4` ON (e = 1) CROSS JOIN (SELECT * FROM 5) `alias5` ON (field1 = ?)' values: [2, 99] } module?.exports[require('path').basename(__filename)] = test