1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fix problems with RANGE windows and string, blob and NULL values.

FossilOrigin-Name: cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417
This commit is contained in:
dan
2019-03-16 20:29:54 +00:00
parent bf84515a2b
commit 1e7cb19be3
8 changed files with 2205 additions and 165 deletions

View File

@@ -1076,7 +1076,6 @@ Window *sqlite3WindowAlloc(
pWin->bImplicitFrame = bImplicitFrame;
pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd);
pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart);
/* pWin->eExclude = 1; */
return pWin;
windowAllocErr:
@@ -1742,11 +1741,14 @@ static void windowIfNewPeer(
/*
** This function is called as part of generating VM programs for RANGE
** offset PRECEDING/FOLLOWING frame boundaries. It generates code equivalent
** to:
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
** the ORDER BY term in the window, it generates code equivalent to:
**
** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
** if( csr1.rowid >= csr2.rowid ) goto lbl;
**
** A special type of arithmetic is used such that if csr.peerVal is not
** a numeric type (real or integer), then the result of the addition is
** a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
WindowCodeArg *p,
@@ -1761,6 +1763,10 @@ static void windowCodeRangeTest(
int reg1 = sqlite3GetTempReg(pParse);
int reg2 = sqlite3GetTempReg(pParse);
int arith = OP_Add;
int addrGe;
int addrNotNull;
int regString = ++pParse->nMem;
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 );
@@ -1775,11 +1781,24 @@ static void windowCodeRangeTest(
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
/* Check if the peer value for csr1 value is a text or blob by comparing
** it to the smallest possible string - ''. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
if( op==OP_Le ){
sqlite3VdbeAddOp2(v, OP_IsNull, reg1, lbl);
}
if( op==OP_Ge ){
sqlite3VdbeAddOp2(v, OP_NotNull, reg1, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
}
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
sqlite3VdbeJumpHere(v, addrGe);
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1);
sqlite3VdbeAddOp2(v, OP_Rowid, csr1, reg1);
sqlite3VdbeAddOp2(v, OP_Rowid, csr2, reg2);
sqlite3VdbeAddOp3(v, OP_Gt, reg2, lbl, reg1);
sqlite3ReleaseTempReg(pParse, reg1);
sqlite3ReleaseTempReg(pParse, reg2);
}