diff --git a/models/Grammars/BaseGrammar.cfc b/models/Grammars/BaseGrammar.cfc index 1204cc4..d61bfa4 100644 --- a/models/Grammars/BaseGrammar.cfc +++ b/models/Grammars/BaseGrammar.cfc @@ -576,8 +576,12 @@ component displayname="Grammar" accessors="true" singleton { * @return string */ private string function whereBetween( required QueryBuilder query, required struct where ) { - var start = isSimpleValue( where.start ) ? "?" : "(#compileSelect( where.start )#)"; - var end = isSimpleValue( where.end ) ? "?" : "(#compileSelect( where.end )#)"; + var start = variables.utils.isExpression( where.start ) ? where.start.getSql() : ( + isSimpleValue( where.start ) ? "?" : "(#compileSelect( where.start )#)" + ); + var end = variables.utils.isExpression( where.end ) ? where.end.getSql() : ( + isSimpleValue( where.end ) ? "?" : "(#compileSelect( where.end )#)" + ); return "#wrapColumn( where.column )# BETWEEN #start# AND #end#"; } diff --git a/models/Query/QueryBuilder.cfc b/models/Query/QueryBuilder.cfc index a6da3c1..12966c0 100644 --- a/models/Query/QueryBuilder.cfc +++ b/models/Query/QueryBuilder.cfc @@ -688,7 +688,7 @@ component displayname="QueryBuilder" accessors="true" { private void function renameAliasesInHavings( required string oldAlias, required string newAlias ) { for ( var having in variables.havings ) { - if ( having.keyExists( "column" ) ) { + if ( structKeyExists( having, "column" ) ) { if ( having.column.type == "simple" ) { having.column.value = swapAlias( having.column.value, arguments.oldAlias, arguments.newAlias ); } @@ -2255,11 +2255,24 @@ component displayname="QueryBuilder" accessors="true" { callback( arguments.end ); } - addBindings( utils.extractBinding( arguments.start, variables.grammar ), "where" ); - addBindings( utils.extractBinding( arguments.end, variables.grammar ), "where" ); + addBindings( + utils.isExpression( arguments.start ) ? arguments.start.getBindings() : utils.extractBinding( + arguments.start, + variables.grammar + ), + "where" + ); + addBindings( + utils.isExpression( arguments.end ) ? arguments.end.getBindings() : utils.extractBinding( + arguments.end, + variables.grammar + ), + "where" + ); if ( - isStruct( arguments.start ) && !structKeyExists( arguments.start, "isBuilder" ) && arguments.start.keyExists( + isStruct( arguments.start ) && !structKeyExists( arguments.start, "isBuilder" ) && structKeyExists( + arguments.start, "value" ) ) { @@ -2267,7 +2280,8 @@ component displayname="QueryBuilder" accessors="true" { } if ( - isStruct( arguments.end ) && !structKeyExists( arguments.end, "isBuilder" ) && arguments.end.keyExists( + isStruct( arguments.end ) && !structKeyExists( arguments.end, "isBuilder" ) && structKeyExists( + arguments.end, "value" ) ) { diff --git a/tests/resources/AbstractQueryBuilderSpec.cfc b/tests/resources/AbstractQueryBuilderSpec.cfc index c3c3b41..21f2160 100644 --- a/tests/resources/AbstractQueryBuilderSpec.cfc +++ b/tests/resources/AbstractQueryBuilderSpec.cfc @@ -779,6 +779,19 @@ component extends="testbox.system.BaseSpec" { }, whereBetween() ); } ); + it( "can add where between statements with raw expressions", function() { + testCase( function( builder ) { + builder + .select( "*" ) + .from( "users" ) + .whereBetween( + "createdDate", + builder.raw( "GETDATE() - 7" ), + builder.raw( "GETDATE()" ) + ); + }, whereBetweenRaw() ); + } ); + it( "can add where between statements with query param structs", function() { testCase( function( builder ) { builder diff --git a/tests/specs/Query/DerbyQueryBuilderSpec.cfc b/tests/specs/Query/DerbyQueryBuilderSpec.cfc index 0f6f1f4..7ea6549 100644 --- a/tests/specs/Query/DerbyQueryBuilderSpec.cfc +++ b/tests/specs/Query/DerbyQueryBuilderSpec.cfc @@ -256,7 +256,7 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { bindings: [ { "cfsqltype": "OTHER", - "value": true, + "value": 1, "list": false, "null": false } @@ -310,6 +310,13 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM ""users"" WHERE ""id"" BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { + sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN GETDATE() - 7 AND GETDATE()", + bindings: [] + }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN ? AND ?", @@ -752,7 +759,7 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { sql: "INSERT INTO ""users"" (""active"") VALUES (?)", bindings: [ { - "value": true, + "value": 1, "cfsqltype": "OTHER", "null": false, "list": false diff --git a/tests/specs/Query/MySQLQueryBuilderSpec.cfc b/tests/specs/Query/MySQLQueryBuilderSpec.cfc index 3ac0490..7ba8158 100644 --- a/tests/specs/Query/MySQLQueryBuilderSpec.cfc +++ b/tests/specs/Query/MySQLQueryBuilderSpec.cfc @@ -307,6 +307,10 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM `users` WHERE `id` BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { sql: "SELECT * FROM `users` WHERE `createdDate` BETWEEN GETDATE() - 7 AND GETDATE()", bindings: [] }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM `users` WHERE `createdDate` BETWEEN ? AND ?", diff --git a/tests/specs/Query/OracleQueryBuilderSpec.cfc b/tests/specs/Query/OracleQueryBuilderSpec.cfc index f0f084f..63b6412 100644 --- a/tests/specs/Query/OracleQueryBuilderSpec.cfc +++ b/tests/specs/Query/OracleQueryBuilderSpec.cfc @@ -316,6 +316,13 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM ""USERS"" WHERE ""ID"" BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { + sql: "SELECT * FROM ""USERS"" WHERE ""CREATEDDATE"" BETWEEN GETDATE() - 7 AND GETDATE()", + bindings: [] + }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM ""USERS"" WHERE ""CREATEDDATE"" BETWEEN ? AND ?", diff --git a/tests/specs/Query/PostgresQueryBuilderSpec.cfc b/tests/specs/Query/PostgresQueryBuilderSpec.cfc index e29a09d..5de9fd9 100644 --- a/tests/specs/Query/PostgresQueryBuilderSpec.cfc +++ b/tests/specs/Query/PostgresQueryBuilderSpec.cfc @@ -310,6 +310,13 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM ""users"" WHERE ""id"" BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { + sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN GETDATE() - 7 AND GETDATE()", + bindings: [] + }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN ? AND ?", diff --git a/tests/specs/Query/SQLiteQueryBuilderSpec.cfc b/tests/specs/Query/SQLiteQueryBuilderSpec.cfc index ce66413..d92772e 100644 --- a/tests/specs/Query/SQLiteQueryBuilderSpec.cfc +++ b/tests/specs/Query/SQLiteQueryBuilderSpec.cfc @@ -339,6 +339,13 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM ""users"" WHERE ""id"" BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { + sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN GETDATE() - 7 AND GETDATE()", + bindings: [] + }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM ""users"" WHERE ""createdDate"" BETWEEN ? AND ?", diff --git a/tests/specs/Query/SqlServerQueryBuilderSpec.cfc b/tests/specs/Query/SqlServerQueryBuilderSpec.cfc index 3cbb42b..c983878 100644 --- a/tests/specs/Query/SqlServerQueryBuilderSpec.cfc +++ b/tests/specs/Query/SqlServerQueryBuilderSpec.cfc @@ -307,6 +307,10 @@ component extends="tests.resources.AbstractQueryBuilderSpec" { return { sql: "SELECT * FROM [users] WHERE [id] BETWEEN ? AND ?", bindings: [ 1, 2 ] }; } + function whereBetweenRaw() { + return { sql: "SELECT * FROM [users] WHERE [createdDate] BETWEEN GETDATE() - 7 AND GETDATE()", bindings: [] }; + } + function whereBetweenWithQueryParamStructs() { return { sql: "SELECT * FROM [users] WHERE [createdDate] BETWEEN ? AND ?",