@@ -193,7 +193,7 @@ impl WhereOperator {
193193 Between => match right_value {
194194 Value :: Array ( bounds) if bounds. len ( ) == 2 => {
195195 match bounds[ 0 ] . partial_cmp ( & bounds[ 1 ] ) {
196- Some ( Ordering :: Less ) | Some ( Ordering :: Equal ) => {
196+ Some ( Ordering :: Less ) => {
197197 left_value >= & bounds[ 0 ] && left_value <= & bounds[ 1 ]
198198 }
199199 _ => false ,
@@ -204,9 +204,7 @@ impl WhereOperator {
204204 BetweenExcludeBounds => match right_value {
205205 Value :: Array ( bounds) if bounds. len ( ) == 2 => {
206206 match bounds[ 0 ] . partial_cmp ( & bounds[ 1 ] ) {
207- Some ( Ordering :: Less ) | Some ( Ordering :: Equal ) => {
208- left_value > & bounds[ 0 ] && left_value < & bounds[ 1 ]
209- }
207+ Some ( Ordering :: Less ) => left_value > & bounds[ 0 ] && left_value < & bounds[ 1 ] ,
210208 _ => false ,
211209 }
212210 }
@@ -215,9 +213,7 @@ impl WhereOperator {
215213 BetweenExcludeLeft => match right_value {
216214 Value :: Array ( bounds) if bounds. len ( ) == 2 => {
217215 match bounds[ 0 ] . partial_cmp ( & bounds[ 1 ] ) {
218- Some ( Ordering :: Less ) | Some ( Ordering :: Equal ) => {
219- left_value > & bounds[ 0 ] && left_value <= & bounds[ 1 ]
220- }
216+ Some ( Ordering :: Less ) => left_value > & bounds[ 0 ] && left_value <= & bounds[ 1 ] ,
221217 _ => false ,
222218 }
223219 }
@@ -226,9 +222,7 @@ impl WhereOperator {
226222 BetweenExcludeRight => match right_value {
227223 Value :: Array ( bounds) if bounds. len ( ) == 2 => {
228224 match bounds[ 0 ] . partial_cmp ( & bounds[ 1 ] ) {
229- Some ( Ordering :: Less ) | Some ( Ordering :: Equal ) => {
230- left_value >= & bounds[ 0 ] && left_value < & bounds[ 1 ]
231- }
225+ Some ( Ordering :: Less ) => left_value >= & bounds[ 0 ] && left_value < & bounds[ 1 ] ,
232226 _ => false ,
233227 }
234228 }
@@ -1462,11 +1456,11 @@ impl<'a> WhereClause {
14621456 if let Value :: Array ( bounds) = & self . value {
14631457 if bounds. len ( ) == 2 {
14641458 match bounds[ 0 ] . partial_cmp ( & bounds[ 1 ] ) {
1465- Some ( Ordering :: Less ) | Some ( Ordering :: Equal ) => { }
1459+ Some ( Ordering :: Less ) => { }
14661460 _ => {
14671461 return QuerySyntaxSimpleValidationResult :: new_with_error (
14681462 QuerySyntaxError :: InvalidBetweenClause (
1469- "when using between operator bounds must be ascending" ,
1463+ "when using between operator bounds must be strictly ascending" ,
14701464 ) ,
14711465 ) ;
14721466 }
@@ -1709,7 +1703,8 @@ mod tests {
17091703 use crate :: error:: query:: QuerySyntaxError ;
17101704 use crate :: query:: conditions:: WhereClause ;
17111705 use crate :: query:: conditions:: {
1712- Equal , GreaterThan , GreaterThanOrEquals , In , LessThan , LessThanOrEquals ,
1706+ Between , BetweenExcludeBounds , BetweenExcludeLeft , BetweenExcludeRight , Equal , GreaterThan ,
1707+ GreaterThanOrEquals , In , LessThan , LessThanOrEquals , ValueClause ,
17131708 } ;
17141709 use crate :: query:: InternalClauses ;
17151710 use dpp:: data_contract:: accessors:: v0:: DataContractV0Getters ;
@@ -1988,6 +1983,61 @@ mod tests {
19881983 assert ! ( res. is_valid( ) ) ;
19891984 }
19901985
1986+ #[ test]
1987+ fn validate_rejects_between_variants_with_equal_bounds ( ) {
1988+ let fixture = get_data_contract_fixture ( None , 0 , LATEST_PLATFORM_VERSION . protocol_version ) ;
1989+ let contract = fixture. data_contract_owned ( ) ;
1990+ let doc_type = contract
1991+ . document_type_for_name ( "uniqueDates" )
1992+ . expect ( "doc type exists" ) ;
1993+
1994+ for operator in [
1995+ Between ,
1996+ BetweenExcludeBounds ,
1997+ BetweenExcludeLeft ,
1998+ BetweenExcludeRight ,
1999+ ] {
2000+ let clause = WhereClause {
2001+ field : "$createdAt" . to_string ( ) ,
2002+ operator,
2003+ value : Value :: Array ( vec ! [ Value :: U64 ( 1000 ) , Value :: U64 ( 1000 ) ] ) ,
2004+ } ;
2005+
2006+ let res = clause. validate_against_schema ( doc_type) ;
2007+ assert ! (
2008+ res. is_err( ) ,
2009+ "{operator:?} should reject equal bounds during validation"
2010+ ) ;
2011+ assert ! ( matches!(
2012+ res. first_error( ) ,
2013+ Some ( QuerySyntaxError :: InvalidBetweenClause ( _) )
2014+ ) ) ;
2015+ }
2016+ }
2017+
2018+ #[ test]
2019+ fn value_clause_between_variants_do_not_match_equal_bounds ( ) {
2020+ let equal_bounds = Value :: Array ( vec ! [ Value :: U64 ( 1000 ) , Value :: U64 ( 1000 ) ] ) ;
2021+ let value_to_test = Value :: U64 ( 1000 ) ;
2022+
2023+ for operator in [
2024+ Between ,
2025+ BetweenExcludeBounds ,
2026+ BetweenExcludeLeft ,
2027+ BetweenExcludeRight ,
2028+ ] {
2029+ let clause = ValueClause {
2030+ operator,
2031+ value : equal_bounds. clone ( ) ,
2032+ } ;
2033+
2034+ assert ! (
2035+ !clause. matches_value( & value_to_test) ,
2036+ "{operator:?} should not match when bounds are equal"
2037+ ) ;
2038+ }
2039+ }
2040+
19912041 #[ test]
19922042 fn validate_rejects_meta_revision_float_equality ( ) {
19932043 let fixture = get_data_contract_fixture ( None , 0 , LATEST_PLATFORM_VERSION . protocol_version ) ;
0 commit comments