foxhound
Version:
A Database Query generation library.
987 lines (958 loc) • 33.4 kB
JavaScript
/**
* Unit tests for FoxHound
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*/
var Chai = require('chai');
var Expect = Chai.expect;
var Assert = Chai.assert;
var libFable = require('fable');
const _Fable = new libFable({Product:'FoxhoundTestsMSSQL'});
var libFoxHound = require('../source/FoxHound.js');
var _AnimalSchema = (
[
{ Column: "IDAnimal", Type:"AutoIdentity" },
{ Column: "GUIDAnimal", Type:"AutoGUID" },
{ Column: "CreateDate", Type:"CreateDate" },
{ Column: "CreatingIDUser", Type:"CreateIDUser" },
{ Column: "UpdateDate", Type:"UpdateDate" },
{ Column: "UpdatingIDUser", Type:"UpdateIDUser" },
{ Column: "Deleted", Type:"Deleted" },
{ Column: "DeletingIDUser", Type:"DeleteIDUser" },
{ Column: "DeleteDate", Type:"DeleteDate" },
{ Column: "Name", Type:"String" },
{ Column: "Age", Type:"Integer" }
]);
var _AnimalSchemaWithoutDeleted = (
[
{ Column: "IDAnimal", Type:"AutoIdentity" },
{ Column: "GUIDAnimal", Type:"AutoGUID" },
{ Column: "CreateDate", Type:"CreateDate" },
{ Column: "CreatingIDUser", Type:"CreateIDUser" },
{ Column: "UpdateDate", Type:"UpdateDate" },
{ Column: "UpdatingIDUser", Type:"UpdateIDUser" }
]);
suite
(
'FoxHound-Dialect-MSSQL',
function()
{
setup
(
function()
{
}
);
suite
(
'Object Sanity',
function()
{
test
(
'initialize should build a happy little object',
function()
{
var testFoxHound = libFoxHound.new(_Fable).setDialect('MSSQL');
Expect(testFoxHound.dialect.name)
.to.equal('MSSQL');
Expect(testFoxHound)
.to.be.an('object', 'FoxHound with MSSQL should initialize as an object directly from the require statement.');
}
);
}
);
suite
(
'Basic Query Generation',
function()
{
test
(
'Create Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setLogLevel(5)
.setDialect('MSSQL')
.setScope('Animal')
.addRecord({IDAnimal:null, Name:'Foo Foo', Age:15});
// Build the query
tmpQuery.buildCreateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Create Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal("INSERT INTO [Animal] ( [IDAnimal], [Name], [Age]) VALUES ( @IDAnimal_0, @Name_1, @Age_2);");
}
);
test
(
'Bad Create Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL');
// Build the query
tmpQuery.buildCreateQuery();
tmpQuery.addRecord({});
tmpQuery.buildCreateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Create Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal(false);
}
);
test
(
'Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Simple Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Animal].* FROM [Animal] ORDER BY [Cost] DESC;');
}
);
test
(
'Read Query with Index Hinting',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
tmpQuery.indexHints = ['AnimalIndex_1'];
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Simple Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Animal].* FROM [Animal] WITH(INDEX(AnimalIndex_1)) ORDER BY [Cost] DESC;');
}
);
test
(
'Read Query with Distinct',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
tmpQuery.addSort({Column:'Cost',Direction:'Descending'})
.setDistinct(true);
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Simple Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT DISTINCT [Animal].* FROM [Animal] ORDER BY [Cost] DESC;');
}
);
test
(
'Complex Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.addSort('Cost');
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] WHERE [Age] = @Age_w0 ORDER BY [Age], [Cost] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Complex Read Query with qualified and unqualified "SELECT *" cases',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['*', 'Name', 'Age', 'Cost', '[Animal].*'])
.setSort([{Column:'Age',Direction:'Ascending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.addSort('Cost');
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT *, [Name], [Age], [Cost], [Animal].* FROM [Animal] WHERE [Age] = @Age_w0 ORDER BY [Age], [Cost] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Complex Read Query 2',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDataElements(['Name', 'Age', 'Cost'])
.setCap(100)
.addFilter('Age', '25')
.addFilter('', '', '(')
.addFilter('Color', 'Red')
.addFilter('Color', 'Green', '=', 'OR')
.addFilter('', '', ')')
.addFilter('Description', '', 'IS NOT NULL')
.addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
tmpQuery.setLogLevel(0).addSort('Age');
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] WHERE [Age] = @Age_w0 AND ( [Color] = @Color_w2 OR [Color] = @Color_w3 ) AND [Description] IS NOT NULL AND [IDOffice] IN ( @IDOffice_w6 ) ORDER BY [Age] OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;');
}
);
test
(
'Custom Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'},{Column:'Cost',Direction:'Descending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.queryOverride = 'SELECT Name, Age * 5, Cost FROM <%= TableName %> <%= Where %> <%= Limit %>;';
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT Name, Age * 5, Cost FROM [Animal] WHERE [Age] = @Age_w0 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Custom Read Query with Custom Parameters',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'},{Column:'Cost',Direction:'Descending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.CustomFields = 'Name, Age * 5, Cost';
tmpQuery.parameters.queryOverride = 'SELECT <%= _Params.CustomFields %> FROM <%= TableName %> <%= Where %> <%= Limit %>;';
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT Name, Age * 5, Cost FROM [Animal] WHERE [Age] = @Age_w0 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Bad Custom Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.queryOverride = 'SELECT Name, Age * 5, Cost FROM <%= TableName <%= Where %> <%= Limit ;';
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal(false);
}
);
test
(
'Bad Custom Count Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName <%= TableName %> <%= Where;';
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Count Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal(false);
}
);
test
(
'Custom Count Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %><%= IndexHints %> <%= Where %>;';
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Count Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(*) AS RowCount FROM [Animal] WHERE [Age] = @Age_w0;');
}
);
test
(
'Custom Count Query with Index Hinting',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.indexHints = ['AnimalIndex_1'];
tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %><%= IndexHints %> <%= Where %>;';
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Count Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(*) AS RowCount FROM [Animal] WITH(INDEX(AnimalIndex_1)) WHERE [Age] = @Age_w0;');
}
);
test
(
'Custom Count Query with Custom Parameters',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
tmpQuery.parameters.CountAlias = 'RowCount';
tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS <%= _Params.CountAlias %> FROM <%= TableName %> <%= Where %>;';
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Custom Count Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(*) AS RowCount FROM [Animal] WHERE [Age] = @Age_w0;');
}
);
test
(
'Update Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.addRecord({Age:15,Color:'Brown'});
// Build the query
tmpQuery.buildUpdateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Update Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [Age] = @Age_0, [Color] = @Color_1 WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Bad Update Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL');
// Build the query
tmpQuery.buildUpdateQuery();
tmpQuery.addRecord({});
tmpQuery.buildUpdateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Update Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal(false);
}
);
test
(
'Delete Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setScope('Animal')
.addFilter('IDAnimal', 10);
// Build the query
tmpQuery.buildDeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Delete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('DELETE FROM [Animal] WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Count Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal');
tmpQuery.indexHints = ['AnimalIndex_1'];
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Count Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(*) AS Row_Count FROM [Animal] WITH(INDEX(AnimalIndex_1));');
}
);
test
(
'Count Distinct Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal');
tmpQuery.setDistinct(true);
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Count Distinct Query', tmpQuery.query);
Expect(tmpQuery.query.body)
// RowCount is a reserved word for MSSQL so we need to change it to Row_Count
.to.equal('SELECT COUNT(DISTINCT [IDAnimal]) AS Row_Count FROM [Animal] WHERE [Deleted] = @Deleted_w0;');
}
);
test
(
'Count Distinct Query without Schema',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal');
tmpQuery.setDistinct(true);
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Count Distinct Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(*) AS Row_Count FROM [Animal];');
}
);
test
(
'Count Distinct Query with Custom Fields',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDataElements(['Name']);
tmpQuery.setDistinct(true);
// Build the query
tmpQuery.buildCountQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Count Distinct Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT COUNT(DISTINCT [Name]) AS Row_Count FROM [Animal];');
}
);
}
);
suite
(
'Complex Query Generation - Schemas',
function()
{
test
(
'Create Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setLogLevel(5)
.setDialect('MSSQL')
.setScope('Animal')
.addRecord(
{
IDAnimal:false,
GUIDAnimal:false,
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Deleted:false,
DeletingIDUser:false,
DeleteDate:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildCreateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Create Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal("INSERT INTO [Animal] ( [GUIDAnimal], [CreateDate], [CreatingIDUser], [UpdateDate], [UpdatingIDUser], [Deleted], [Name], [Age]) VALUES ( @GUIDAnimal_1, GETUTCDATE(), @CreatingIDUser_3, GETUTCDATE(), @UpdatingIDUser_5, @Deleted_6, @Name_7, @Age_8);");
}
);
test
(
'Create Query -- with GUID specified',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setLogLevel(5)
.setDialect('MSSQL')
.setScope('Animal')
.addRecord(
{
IDAnimal:false,
GUIDAnimal:'0xabcdef',
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Deleted:false,
DeletingIDUser:false,
DeleteDate:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildCreateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Create Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal("INSERT INTO [Animal] ( [GUIDAnimal], [CreateDate], [CreatingIDUser], [UpdateDate], [UpdatingIDUser], [Deleted], [Name], [Age]) VALUES ( @GUIDAnimal_1, GETUTCDATE(), @CreatingIDUser_3, GETUTCDATE(), @UpdatingIDUser_5, @Deleted_6, @Name_7, @Age_8);");
}
);
test
(
'Create Query - with AutoIdentity disabled',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setLogLevel(5)
.setDialect('MSSQL')
.setScope('Animal')
.setDisableAutoIdentity(true)
.setDisableDeleteTracking(true)
.setDisableAutoDateStamp(true)
.setDisableAutoUserStamp(true)
.addRecord(
{
IDAnimal:false,
GUIDAnimal:false,
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Deleted:false,
DeletingIDUser:false,
DeleteDate:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildCreateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Create Query (AutoIdentity disabled)', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal("INSERT INTO [Animal] ( [IDAnimal], [GUIDAnimal], [CreateDate], [CreatingIDUser], [UpdateDate], [UpdatingIDUser], [Deleted], [DeletingIDUser], [DeleteDate], [Name], [Age]) VALUES ( @IDAnimal_0, @GUIDAnimal_1, @CreateDate_2, @CreatingIDUser_3, @UpdateDate_4, @UpdatingIDUser_5, @Deleted_6, @DeletingIDUser_7, @DeleteDate_8, @Name_9, @Age_10);");
}
);
test
(
'Complex Read Query 2, verify checking Deleted bit with no filters',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDataElements(['Name', 'Age', 'Cost'])
.setCap(100);
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] WHERE [Deleted] = @Deleted_w0 OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;');
}
);
test
(
'Complex Read Query 2, verify checking Deleted bit with no filters, with Distinct',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDataElements(['Name', 'Age', 'Cost'])
.setCap(100)
.setDistinct(true);
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT DISTINCT [Name], [Age], [Cost] FROM [Animal] WHERE [Deleted] = @Deleted_w0 OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;');
}
);
test
(
'Complex Read Query 2, manually checking Deleted bit with Schema that has one',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDataElements(['Name', 'Age', 'Cost'])
.setCap(100)
.addFilter('Age', '25')
.addFilter('', '', '(')
.addFilter('Color', 'Red')
.addFilter('Color', 'Green', '=', 'OR')
.addFilter('', '', ')')
.addFilter('Description', '', 'IS NOT NULL')
.addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN')
.addFilter('Deleted', '1');
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] WHERE [Age] = @Age_w0 AND ( [Color] = @Color_w2 OR [Color] = @Color_w3 ) AND [Description] IS NOT NULL AND [IDOffice] IN ( @IDOffice_w6 ) AND [Deleted] = @Deleted_w7 OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;');
}
);
test
(
'Complex Read Query 2, delete tracking disabled',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setDisableDeleteTracking(true)
.setDataElements(['Name', 'Age', 'Cost'])
.setCap(100);
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;');
}
);
test
(
'Delete Query with Filters',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setScope('Animal')
.addFilter('IDAnimal', 10);
//Perform delete with no record specified, but has a Deleted bit in the schema
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildDeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Delete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [UpdateDate] = GETUTCDATE(), [Deleted] = 1, [DeletingIDUser] = @DeletingIDUser_2, [DeleteDate] = GETUTCDATE() WHERE [IDAnimal] = @IDAnimal_w0 AND [Deleted] = @Deleted_w1;');
}
);
test
(
'Update Query -- without Deleted',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
// Build the query
tmpQuery.buildUpdateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Update Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [GUIDAnimal] = @GUIDAnimal_0, [UpdateDate] = GETUTCDATE(), [UpdatingIDUser] = @UpdatingIDUser_2, [Name] = @Name_3, [Age] = @Age_4 WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Update Query -- without Deleted, UpdateDate and UpdatingIDUser',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.setDisableAutoUserStamp(true)
.setDisableAutoDateStamp(true)
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
// Build the query
tmpQuery.buildUpdateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Update Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [GUIDAnimal] = @GUIDAnimal_0, [Name] = @Name_1, [Age] = @Age_2 WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Delete Query -- without Deleted',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
});
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
// Build the query
tmpQuery.buildDeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Delete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('DELETE FROM [Animal] WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Update Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.addFilter('Deleted', 0) //cover case where this can be overridden instead of automatically added
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
CreateDate:false,
CreatingIDUser:false,
UpdateDate:false,
UpdatingIDUser:false,
Deleted:0,
DeletingIDUser:false,
DeleteDate:false,
Name:'Froo Froo',
Age:18
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildUpdateQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Update Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [GUIDAnimal] = @GUIDAnimal_0, [UpdateDate] = GETUTCDATE(), [UpdatingIDUser] = @UpdatingIDUser_2, [Deleted] = @Deleted_3, [Name] = @Name_4, [Age] = @Age_5 WHERE [IDAnimal] = @IDAnimal_w0 AND [Deleted] = @Deleted_w1;');
}
);
test
(
'Delete Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.addFilter('IDAnimal', 9)
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildDeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Delete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [UpdateDate] = GETUTCDATE(), [Deleted] = 1, [DeletingIDUser] = @DeletingIDUser_2, [DeleteDate] = GETUTCDATE() WHERE [IDAnimal] = @IDAnimal_w0 AND [Deleted] = @Deleted_w1;');
}
);
test
(
'Delete Query with Delete Tracking Disabled',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setLogLevel(5)
.setScope('Animal')
.setDisableDeleteTracking(true)
.addFilter('IDAnimal', 9)
.addRecord({
IDAnimal:82,
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
});
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildDeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Delete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('DELETE FROM [Animal] WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Undelete Query with Deleted Bit',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setScope('Animal')
.addFilter('IDAnimal', 10);
//Use a schema that already defines a deleted bit
tmpQuery.query.schema = _AnimalSchema;
// Build the query
tmpQuery.buildUndeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Undelete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('UPDATE [Animal] SET [UpdateDate] = GETUTCDATE(), [UpdatingIDUser] = @UpdatingIDUser_1, [Deleted] = 0 WHERE [IDAnimal] = @IDAnimal_w0;');
}
);
test
(
'Undelete Query without Deleted Bit',
function()
{
var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
.setScope('Animal')
.addFilter('IDAnimal', 10);
// Build the query
tmpQuery.buildUndeleteQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Undelete Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT NULL;');
}
);
}
);
suite
(
'Join Query Generation',
function()
{
test
(
'Join Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'})
.setJoin({Table: 'Test', From:'Test.IDAnimal', To: 'Animal.IDAnimal'});
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Name], [Age], [Cost] FROM [Animal] INNER JOIN [Test] ON Test.IDAnimal = Animal.IDAnimal WHERE [Age] = @Age_w0 ORDER BY [Age] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Join Read Query with Distinct',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setCap(10)
.setBegin(0)
.setDataElements(['Name', 'Age', 'Cost'])
.setSort([{Column:'Age',Direction:'Ascending'}])
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'})
.setJoin({Table: 'Test', From:'Test.IDAnimal', To: 'Animal.IDAnimal'})
.setDistinct(true);
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT DISTINCT [Name], [Age], [Cost] FROM [Animal] INNER JOIN [Test] ON Test.IDAnimal = Animal.IDAnimal WHERE [Age] = @Age_w0 ORDER BY [Age] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;'); }
);
test
(
'Bad Join Read Query',
function()
{
var tmpQuery = libFoxHound.new(_Fable)
.setDialect('MSSQL')
.setScope('Animal')
.setJoin({Table: 'Test', From:'Bad.IDAnimal', To: 'Animal.IDAnimal'});
// Build the query
tmpQuery.buildReadQuery();
// This is the query generated by the MSSQL dialect
_Fable.log.trace('Select Query', tmpQuery.query);
Expect(tmpQuery.query.body)
.to.equal('SELECT [Animal].* FROM [Animal];'); //bad join is ignored, warn log is generated
}
);
}
);
}
);