1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-11 01:42:22 +03:00

Comment improvements to on the distinct-agg optimization. Show a line in

the EQP output when using an ephemeral table to implement DISTINCT on an
aggregate.

FossilOrigin-Name: 037ca79e6032ca962b4f6182187bc12a7d91170d73630c8cd6fb191d2c183ee4
This commit is contained in:
drh
2021-03-24 19:44:01 +00:00
parent 6db1c9da67
commit 9be1339faf
4 changed files with 43 additions and 34 deletions

View File

@@ -748,6 +748,9 @@ static void codeOffset(
** as follows:
**
** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
** Build an ephemeral table that contains all entries seen before and
** skip entries which have been seen before.
**
** Parameter iTab is the cursor number of an ephemeral table that must
** be opened before the VM code generated by this routine is executed.
** The ephemeral cursor table is queried for a record identical to the
@@ -758,20 +761,21 @@ static void codeOffset(
** The returned value in this case is a copy of parameter iTab.
**
** WHERE_DISTINCT_ORDERED:
** In this case rows are being delivered sorted order sorted. The ephermal
** table is not required in this case. Instead, the current set of
** registers are compared to previous row. If they match, the new row
** In this case rows are being delivered sorted order. The ephermal
** table is not required. Instead, the current set of values
** is compared against previous row. If they match, the new row
** is not distinct and control jumps to VM address addrRepeat. Otherwise,
** the VM program proceeds with processing the new row.
**
** The returned value in this case is the register number of the first
** in an array of registers used to store the previous result row so that
** it can be compared to the next. The caller must ensure that this cell
** is initialized to NULL and has the "clear" flag set.
** it can be compared to the next. The caller must ensure that this
** register is initialized to NULL. (The fixDistinctOpenEph() routine
** will take care of this initialization.)
**
** WHERE_DISTINCT_UNIQUE:
** In this case it has already been determined that the rows are distinct.
** No special action is required. The return value is always zero.
** No special action is required. The return value is zero.
**
** Parameter pEList is the list of expressions used to generated the
** contents of each row. It is used by this routine to determine (a)
@@ -841,25 +845,27 @@ static int codeDistinct(
}
/*
** A call to this function must be made for each call to codeDistinct().
** Parameter is passed the value returned by that call to codeDistinct(),
** and iOpenEphAddr the address of the instruction used to open the
** ephemeral table (that may be) used by codeDistinct().
** This routine runs after codeDistinct(). It makes necessary
** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
** routine made use of. This processing must be done separately since
** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
** laid down.
**
** Argument eTnctType is passed the strategy to be used for any DISTINCT
** operation, as returned by sqlite3WhereIsDistinct(). If the strategy
** is WHERE_DISTINCT_NOOP or WHERE_DISTINCT_UNORDERED, this function is
** a no-op. Otherwise:
** WHERE_DISTINCT_NOOP:
** WHERE_DISTINCT_UNORDERED:
**
** WHERE_DISTINCT_UNIQUE:
** In this case the ephemeral table is not required. So instruction
** iOpenEphAddr is replaced by an OP_Noop.
** No adjustments necessary. This function is a no-op.
**
** WHERE_DISTINCT_ORDERED:
** In this case the ephemeral table is not required. The instruction
** iOpenEphAddr is replaced by an OP_Null instruction to set register
** iVal to a NULL value with the "clear" flag set (see comments above
** codeDistinct() for details).
** WHERE_DISTINCT_UNIQUE:
**
** The ephemeral table is not needed. So change the
** OP_OpenEphemeral opcode into an OP_Noop.
**
** WHERE_DISTINCT_ORDERED:
**
** The ephemeral table is not needed. But we do need register
** iVal to be initialized to NULL. So change the OP_OpenEphemeral
** into an OP_Null on the iVal register.
*/
static void fixDistinctOpenEph(
Parse *pParse, /* Parsing and code generating context */
@@ -870,6 +876,9 @@ static void fixDistinctOpenEph(
if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
}
if( eTnctType==WHERE_DISTINCT_ORDERED ){
/* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
** bit on the first register of the previous value. This will cause the
@@ -5714,6 +5723,8 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
pFunc->pFunc->zName));
}
}
}