Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -1721,38 +1721,32 @@ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i += pOp->p2; break; } -/* Opcode: MustBeInt P1 P2 * * P5 -** -** If P5 is 0, force the value in register P1 to be an integer. If -** the value in P1 is not an integer and cannot be converted into an -** integer without data loss, then jump immediately to P2, or if P2==0 -** raise an SQLITE_MISMATCH exception. -** -** Or, if P5 is non-zero, then force the register in P1 to be a number -** (real or integer). Jump to P2 if this cannot be accomplished without -** data loss. P2 must be non-zero in this case. +/* Opcode: MustBeInt P1 P2 * * * +** +** Force the value in register P1 to be an integer. If the value +** in P1 is not an integer and cannot be converted into an integer +** without data loss, then jump immediately to P2, or if P2==0 +** raise an SQLITE_MISMATCH exception. */ case OP_MustBeInt: { /* jump, in1 */ - u8 f; - f = (pOp->p5 ? (MEM_Int|MEM_Real) : MEM_Int); pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & f)==0 ){ + if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); - VdbeBranchTaken((pIn1->flags&f)==0, 2); - if( (pIn1->flags & f)==0 ){ + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); + if( (pIn1->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ goto jump_to_p2; } } } - if( f==MEM_Int ) MemSetTypeFlag(pIn1, MEM_Int); + MemSetTypeFlag(pIn1, MEM_Int); break; } #ifndef SQLITE_OMIT_FLOATING_POINT /* Opcode: RealAffinity P1 * * * * Index: src/window.c ================================================================== --- src/window.c +++ src/window.c @@ -1300,12 +1300,18 @@ static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge }; Vdbe *v = sqlite3GetVdbe(pParse); int regZero = sqlite3GetTempReg(pParse); assert( eCond>=0 && eCond=WINDOW_STARTING_NUM ) sqlite3VdbeChangeP5(v, 1); + if( eCond>=WINDOW_STARTING_NUM ){ + int regString = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); + sqlite3VdbeAddOp3(v, OP_Ge, regString, sqlite3VdbeCurrentAddr(v)+2, reg); + sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC); + }else{ + sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); + } VdbeCoverageIf(v, eCond==0); VdbeCoverageIf(v, eCond==1); VdbeCoverageIf(v, eCond==2); sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); VdbeCoverageNeverNullIf(v, eCond==0); Index: test/window1.test ================================================================== --- test/window1.test +++ test/window1.test @@ -935,9 +935,41 @@ SELECT current, exclude, filter, following, groups, no, others, over, partition, preceding, range, ties, unbounded, window FROM keyword_tab } + +#------------------------------------------------------------------------- +foreach {tn expr err} { + 1 4.5 0 + 2 NULL 1 + 3 0.0 0 + 4 0.1 0 + 5 -0.1 1 + 6 '' 1 + 7 '2.0' 0 + 8 '2.0x' 1 + 9 x'1234' 1 + 10 '1.2' 0 +} { + set res {0 1} + if {$err} {set res {1 {frame starting offset must be a non-negative number}} } + do_catchsql_test 22.$tn.1 " + WITH a(x, y) AS ( VALUES(1, 2) ) + SELECT sum(x) OVER ( + ORDER BY y RANGE BETWEEN $expr PRECEDING AND UNBOUNDED FOLLOWING + ) FROM a + " $res + + set res {0 1} + if {$err} {set res {1 {frame ending offset must be a non-negative number}} } + do_catchsql_test 22.$tn.2 " + WITH a(x, y) AS ( VALUES(1, 2) ) + SELECT sum(x) OVER ( + ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND $expr FOLLOWING + ) FROM a + " $res +} finish_test