[tarantool-patches] [PATCH v2 6/9] sql: cleanup code from obsolete macros

  • From: Stanislav Zudin <szudin@xxxxxxxxxxxxx>
  • To: tarantool-patches@xxxxxxxxxxxxx, korablev@xxxxxxxxxxxxx
  • Date: Wed, 29 May 2019 17:01:28 +0300

Removes the following unused macros:
SQL_EXPLAIN_ESTIMATED_ROWS
SQL_ENABLE_COLUMN_USED_MASK
SQL_DISABLE_DIRSYNC
SQL_DEBUG_SORTER_THREADS
SQL_DEFAULT_WORKER_THREADS
SQL_LIMIT_WORKER_THREADS
SQL_MAX_WORKER_THREADS

Updates tests.

Part of #3978
---
 src/box/sql/CMakeLists.txt               |   1 -
 src/box/sql/expr.c                       |  14 -
 src/box/sql/main.c                       |   8 -
 src/box/sql/os_unix.c                    |   2 -
 src/box/sql/sqlInt.h                     |  21 +-
 src/box/sql/util.c                       |   5 -
 src/box/sql/vdbe.c                       |  20 -
 src/box/sql/vdbeInt.h                    |   3 -
 src/box/sql/vdbesort.c                   | 639 ++---------------------
 src/box/sql/where.c                      |  30 --
 src/box/sql/wherecode.c                  |   4 +-
 test/sql-tap/collation.test.lua          |   6 +-
 test/sql-tap/eqp.test.lua                | 246 ++++-----
 test/sql-tap/gh-2996-indexed-by.test.lua |  12 +-
 test/sql-tap/index6.test.lua             |   4 +-
 test/sql-tap/index7.test.lua             |   2 +-
 test/sql-tap/lua-tables.test.lua         |   4 +-
 test/sql-tap/tkt-385a5b56b9.test.lua     |  26 +-
 test/sql-tap/tkt-b75a9ca6b0.test.lua     |   4 +-
 test/sql-tap/tkt3442.test.lua            |   4 +-
 test/sql-tap/where3.test.lua             |   6 +-
 test/sql-tap/whereG.test.lua             |  16 +-
 test/sql/row-count.result                |   2 +-
 23 files changed, 213 insertions(+), 866 deletions(-)

diff --git a/src/box/sql/CMakeLists.txt b/src/box/sql/CMakeLists.txt
index b9dbe141a..7059b57cf 100644
--- a/src/box/sql/CMakeLists.txt
+++ b/src/box/sql/CMakeLists.txt
@@ -10,7 +10,6 @@ set(SQL_BIN_DIR ${CMAKE_BINARY_DIR}/src/box/sql)
 include_directories(${SQL_SRC_DIR})
 include_directories(${SQL_BIN_DIR})
 
-add_definitions(-DSQL_MAX_WORKER_THREADS=0)
 add_definitions(-DSQL_OMIT_AUTOMATIC_INDEX)
 
 set(TEST_DEFINITIONS
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 71d0cbf46..48d7185f3 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -2570,20 +2570,6 @@ sqlFindInIndex(Parse * pParse,   /* Parsing context */
                                                parts[0].sort_order;
 
                                        if (prRhsHasNull) {
-#ifdef SQL_ENABLE_COLUMN_USED_MASK
-                                                       i64 mask =
-                                                           (1 << nExpr) - 1;
-                                                       sqlVdbeAddOp4Dup8(v,
-                                                                             
OP_ColumnsUsed,
-                                                                             
iTab,
-                                                                             0,
-                                                                             0,
-                                                                             
(u8
-                                                                              
*)
-                                                                             &
-                                                                             
mask,
-                                                                             
P4_INT64);
-#endif
                                                *prRhsHasNull = ++pParse->nMem;
                                                if (nExpr == 1) {
                                                        /* Tarantool: Check for 
null is performed on first key of the index.  */
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index c0c334f89..339b456df 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -533,7 +533,6 @@ static const int aHardLimit[] = {
        SQL_MAX_ATTACHED,
        SQL_MAX_LIKE_PATTERN_LENGTH,
        SQL_MAX_TRIGGER_DEPTH,
-       SQL_MAX_WORKER_THREADS,
 };
 
 /*
@@ -569,9 +568,6 @@ static const int aHardLimit[] = {
 #if SQL_MAX_TRIGGER_DEPTH<1
 #error SQL_MAX_TRIGGER_DEPTH must be at least 1
 #endif
-#if SQL_MAX_WORKER_THREADS<0 || SQL_MAX_WORKER_THREADS>50
-#error SQL_MAX_WORKER_THREADS must be between 0 and 50
-#endif
 
 /*
  * Change the value of a limit.  Report the old value.
@@ -607,9 +603,6 @@ sql_limit(sql * db, int limitId, int newLimit)
               SQL_MAX_LIKE_PATTERN_LENGTH);
        assert(aHardLimit[SQL_LIMIT_TRIGGER_DEPTH] ==
               SQL_MAX_TRIGGER_DEPTH);
-       assert(aHardLimit[SQL_LIMIT_WORKER_THREADS] ==
-              SQL_MAX_WORKER_THREADS);
-       assert(SQL_LIMIT_WORKER_THREADS == (SQL_N_LIMIT - 1));
 
        if (limitId < 0 || limitId >= SQL_N_LIMIT) {
                return -1;
@@ -652,7 +645,6 @@ sql_init_db(sql **out_db)
 
        assert(sizeof(db->aLimit) == sizeof(aHardLimit));
        memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
-       db->aLimit[SQL_LIMIT_WORKER_THREADS] = SQL_DEFAULT_WORKER_THREADS;
        db->aLimit[SQL_LIMIT_COMPOUND_SELECT] = SQL_DEFAULT_COMPOUND_SELECT;
        db->szMmap = sqlGlobalConfig.szMmap;
        db->nMaxSorterMmap = 0x7FFFFFFF;
diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c
index 615d539b5..f9969b447 100644
--- a/src/box/sql/os_unix.c
+++ b/src/box/sql/os_unix.c
@@ -1937,7 +1937,6 @@ unixDelete(sql_vfs * NotUsed,     /* VFS containing this 
as the xDelete method */
                }
                return rc;
        }
-#ifndef SQL_DISABLE_DIRSYNC
        if ((dirSync & 1) != 0) {
                int fd;
                rc = openDirectory(zPath, &fd);
@@ -1953,7 +1952,6 @@ unixDelete(sql_vfs * NotUsed,     /* VFS containing this 
as the xDelete method */
                        rc = SQL_OK;
                }
        }
-#endif
        return rc;
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 807fdd440..1d1401f2c 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -341,7 +341,6 @@ struct sql_vfs {
 #define SQL_LIMIT_ATTACHED                  7
 #define SQL_LIMIT_LIKE_PATTERN_LENGTH       8
 #define SQL_LIMIT_TRIGGER_DEPTH             9
-#define SQL_LIMIT_WORKER_THREADS           10
 
 enum sql_ret_code {
        /** Result of a routine is ok. */
@@ -956,17 +955,6 @@ sql_bind_parameter_lindex(sql_stmt * pStmt, const char 
*zName,
 #define SQL_DEFAULT_RECURSIVE_TRIGGERS 0
 #endif
 
-#ifndef SQL_MAX_WORKER_THREADS
-#define SQL_MAX_WORKER_THREADS 8
-#endif
-#ifndef SQL_DEFAULT_WORKER_THREADS
-#define SQL_DEFAULT_WORKER_THREADS 0
-#endif
-#if SQL_DEFAULT_WORKER_THREADS>SQL_MAX_WORKER_THREADS
-#undef SQL_MAX_WORKER_THREADS
-#define SQL_MAX_WORKER_THREADS SQL_DEFAULT_WORKER_THREADS
-#endif
-
 /**
  * Default count of allowed compound selects.
  *
@@ -1307,7 +1295,7 @@ typedef int VList;
  * The number of different kinds of things that can be limited
  * using the sql_limit() interface.
  */
-#define SQL_N_LIMIT (SQL_LIMIT_WORKER_THREADS+1)
+#define SQL_N_LIMIT (SQL_LIMIT_TRIGGER_DEPTH+1)
 
 /*
  * Lookaside malloc is a set of fixed-size buffers that can be used
@@ -4869,13 +4857,6 @@ int sqlMemdebugNoType(void *, u8);
 #define MEMTYPE_SCRATCH    0x04        /* Scratch allocations */
 #define MEMTYPE_PCACHE     0x08        /* Page cache allocations */
 
-/*
- * Threading interface
- */
-#if SQL_MAX_WORKER_THREADS>0
-int sqlThreadCreate(sqlThread **, void *(*)(void *), void *);
-int sqlThreadJoin(sqlThread *, void **);
-#endif
 
 int sqlExprVectorSize(Expr * pExpr);
 int sqlExprIsVector(Expr * pExpr);
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index 31378041d..39632e38d 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -1337,15 +1337,10 @@ sqlLogEstToInt(LogEst x)
                n -= 2;
        else if (n >= 1)
                n -= 1;
-#if defined(SQL_EXPLAIN_ESTIMATED_ROWS)
-       if (x > 60)
-               return (u64) LARGEST_INT64;
-#else
        /* The largest input possible to this routine is 310,
         * resulting in a maximum x of 31
         */
        assert(x <= 60);
-#endif
        return x >= 3 ? (n + 8) << (x - 3) : (n + 8) >> (3 - x);
 }
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 5c7605a31..020a4e4a8 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -3346,26 +3346,6 @@ case OP_Close: {
        break;
 }
 
-#ifdef SQL_ENABLE_COLUMN_USED_MASK
-/* Opcode: ColumnsUsed P1 * * P4 *
- *
- * This opcode (which only exists if sql was compiled with
- * SQL_ENABLE_COLUMN_USED_MASK) identifies which columns of the
- * table or index for cursor P1 are used.  P4 is a 64-bit integer
- * (P4_INT64) in which the first 63 bits are one for each of the
- * first 63 columns of the table or index that are actually used
- * by the cursor.  The high-order bit is set if any column after
- * the 64th is used.
- */
-case OP_ColumnsUsed: {
-       VdbeCursor *pC;
-       pC = p->apCsr[pOp->p1];
-       assert(pC->eCurType==CURTYPE_TARANTOOL);
-       pC->maskUsed = *(u64*)pOp->p4.pI64;
-       break;
-}
-#endif
-
 /* Opcode: SeekGE P1 P2 P3 P4 P5
  * Synopsis: key=r[P3@P4]
  *
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index a5933a5e7..a070e87f8 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -116,9 +116,6 @@ struct VdbeCursor {
        const u8 *aRow;         /* Data for the current row, if all on one page 
*/
        u32 payloadSize;        /* Total number of bytes in the record */
        u32 szRow;              /* Byte available in aRow */
-#ifdef SQL_ENABLE_COLUMN_USED_MASK
-       u64 maskUsed;           /* Mask of columns used by this cursor */
-#endif
        u32 nRowField;          /* Number of fields in the current row */
        /* Offsets for all fields in the record [nField+1]
         * Order of fields is the same as it was passes to create table 
statement
diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c
index ddea6752c..a37fbd911 100644
--- a/src/box/sql/vdbesort.c
+++ b/src/box/sql/vdbesort.c
@@ -118,11 +118,6 @@
  * there are already N worker threads running, the main thread does the work
  * itself.
  *
- * The sorter is running in multi-threaded mode if (a) the library was built
- * with pre-processor symbol SQL_MAX_WORKER_THREADS set to a value greater
- * than zero, and (b) worker threads have been enabled at runtime by calling
- * "PRAGMA threads=N" with some value of N greater than 0.
- *
  * When Rewind() is called, any data remaining in memory is flushed to a
  * final PMA. So at this point the data is stored in some number of sorted
  * PMAs within temporary files on disk.
@@ -159,15 +154,6 @@
 #include "sqlInt.h"
 #include "vdbeInt.h"
 
-/*
- * If SQL_DEBUG_SORTER_THREADS is defined, this module outputs various
- * messages to stderr that may be helpful in understanding the performance
- * characteristics of the sorter in multi-threaded mode.
- */
-#if 0
-#define SQL_DEBUG_SORTER_THREADS 1
-#endif
-
 /*
  * Hard-coded maximum amount of data to accumulate in memory before flushing
  * to a level 0 PMA. The purpose of this limit is to prevent various integer
@@ -297,18 +283,14 @@ struct MergeEngine {
  *
  * Before a background thread is launched, variable bDone is set to 0. Then,
  * right before it exits, the thread itself sets bDone to 1. This is used for
- * two purposes:
+ * the following purpose:
  *
- *   1. When flushing the contents of memory to a level-0 PMA on disk, to
+ *      When flushing the contents of memory to a level-0 PMA on disk, to
  *      attempt to select a SortSubtask for which there is not already an
  *      active background thread (since doing so causes the main thread
  *      to block until it finishes).
  *
- *   2. If SQL_DEBUG_SORTER_THREADS is defined, to determine if a call
- *      to sqlThreadJoin() is likely to block. Cases that are likely to
- *      block provoke debugging output.
- *
- * In both cases, the effects of the main thread seeing (bDone==0) even
+ * The effects of the main thread seeing (bDone==0) even
  * after the thread has finished are not dire. So we don't worry about
  * memory barriers and such here.
  */
@@ -855,25 +837,6 @@ sqlVdbeSorterInit(sql * db,        /* Database connection 
(for malloc()) */
        int i;                  /* Used to iterate through aTask[] */
        VdbeSorter *pSorter;    /* The new sorter */
        int rc = SQL_OK;
-#if SQL_MAX_WORKER_THREADS==0
-#define nWorker 0
-#else
-       int nWorker;
-#endif
-
-       /* Initialize the upper limit on the number of worker threads */
-#if SQL_MAX_WORKER_THREADS>0
-       nWorker = db->aLimit[SQL_LIMIT_WORKER_THREADS];
-#endif
-
-       /* Do not allow the total number of threads (main thread + all workers)
-        * to exceed the maximum merge count
-        */
-#if SQL_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT
-       if (nWorker >= SORTER_MAX_MERGE_COUNT) {
-               nWorker = SORTER_MAX_MERGE_COUNT - 1;
-       }
-#endif
 
        assert(pCsr->key_def != NULL);
        assert(pCsr->eCurType == CURTYPE_SORTER);
@@ -885,8 +848,8 @@ sqlVdbeSorterInit(sql * db, /* Database connection (for 
malloc()) */
        } else {
                pSorter->key_def = pCsr->key_def;
                pSorter->pgsz = pgsz = 1024;
-               pSorter->nTask = nWorker + 1;
-               pSorter->iPrev = (u8) (nWorker - 1);
+               pSorter->nTask = 1;
+               pSorter->iPrev = (u8) (-1);
                pSorter->bUseThreads = (pSorter->nTask > 1);
                pSorter->db = db;
                for (i = 0; i < pSorter->nTask; i++) {
@@ -927,8 +890,6 @@ sqlVdbeSorterInit(sql * db, /* Database connection (for 
malloc()) */
        return rc;
 }
 
-#undef nWorker                 /* Defined at the top of this function */
-
 /*
  * Free the list of sorted records starting at pRecord.
  */
@@ -951,18 +912,10 @@ static void
 vdbeSortSubtaskCleanup(sql * db, SortSubtask * pTask)
 {
        sqlDbFree(db, pTask->pUnpacked);
-#if SQL_MAX_WORKER_THREADS>0
-       /* pTask->list.aMemory can only be non-zero if it was handed memory
-        * from the main thread.  That only occurs SQL_MAX_WORKER_THREADS>0
-        */
-       if (pTask->list.aMemory) {
-               sql_free(pTask->list.aMemory);
-       } else
-#endif
-       {
-               assert(pTask->list.aMemory == 0);
-               vdbeSorterRecordFree(0, pTask->list.pList);
-       }
+
+       assert(pTask->list.aMemory == 0);
+       vdbeSorterRecordFree(0, pTask->list.pList);
+
        if (pTask->file.pFd) {
                sqlOsCloseFree(pTask->file.pFd);
        }
@@ -972,116 +925,7 @@ vdbeSortSubtaskCleanup(sql * db, SortSubtask * pTask)
        memset(pTask, 0, sizeof(SortSubtask));
 }
 
-#ifdef SQL_DEBUG_SORTER_THREADS
-static void
-vdbeSorterWorkDebug(SortSubtask * pTask, const char *zEvent)
-{
-       i64 t;
-       int iTask = (pTask - pTask->pSorter->aTask);
-       sqlOsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
-       fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
-}
-
-static void
-vdbeSorterRewindDebug(const char *zEvent)
-{
-       i64 t;
-       sqlOsCurrentTimeInt64(sql_vfs_find(0), &t);
-       fprintf(stderr, "%lld:X %s\n", t, zEvent);
-}
-
-static void
-vdbeSorterPopulateDebug(SortSubtask * pTask, const char *zEvent)
-{
-       i64 t;
-       int iTask = (pTask - pTask->pSorter->aTask);
-       sqlOsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
-       fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent);
-}
-
-static void
-vdbeSorterBlockDebug(SortSubtask * pTask, int bBlocked, const char *zEvent)
-{
-       if (bBlocked) {
-               i64 t;
-               sqlOsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
-               fprintf(stderr, "%lld:main %s\n", t, zEvent);
-       }
-}
-#else
-#define vdbeSorterWorkDebug(x,y)
-#define vdbeSorterRewindDebug(y)
-#define vdbeSorterPopulateDebug(x,y)
-#define vdbeSorterBlockDebug(x,y,z)
-#endif
-
-#if SQL_MAX_WORKER_THREADS>0
-/*
- * Join thread pTask->thread.
- */
-static int
-vdbeSorterJoinThread(SortSubtask * pTask)
-{
-       int rc = SQL_OK;
-       if (pTask->pThread) {
-#ifdef SQL_DEBUG_SORTER_THREADS
-               int bDone = pTask->bDone;
-#endif
-               void *pRet = SQL_INT_TO_PTR(SQL_ERROR);
-               vdbeSorterBlockDebug(pTask, !bDone, "enter");
-               (void)sqlThreadJoin(pTask->pThread, &pRet);
-               vdbeSorterBlockDebug(pTask, !bDone, "exit");
-               rc = SQL_PTR_TO_INT(pRet);
-               assert(pTask->bDone == 1);
-               pTask->bDone = 0;
-               pTask->pThread = 0;
-       }
-       return rc;
-}
-
-/*
- * Launch a background thread to run xTask(pIn).
- */
-static int
-vdbeSorterCreateThread(SortSubtask * pTask,    /* Thread will use this task 
object */
-                      void *(*xTask) (void *), /* Routine to run in a separate 
thread */
-                      void *pIn        /* Argument passed into xTask() */
-    )
-{
-       assert(pTask->pThread == 0 && pTask->bDone == 0);
-       return sqlThreadCreate(&pTask->pThread, xTask, pIn);
-}
-
-/*
- * Join all outstanding threads launched by SorterWrite() to create
- * level-0 PMAs.
- */
-static int
-vdbeSorterJoinAll(VdbeSorter * pSorter, int rcin)
-{
-       int rc = rcin;
-       int i;
-
-       /* This function is always called by the main user thread.
-        *
-        * If this function is being called after SorterRewind() has been 
called,
-        * it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread
-        * is currently attempt to join one of the other threads. To avoid a 
race
-        * condition where this thread also attempts to join the same object, 
join
-        * thread pSorter->aTask[pSorter->nTask-1].pThread first.
-        */
-       for (i = pSorter->nTask - 1; i >= 0; i--) {
-               SortSubtask *pTask = &pSorter->aTask[i];
-               int rc2 = vdbeSorterJoinThread(pTask);
-               if (rc == SQL_OK)
-                       rc = rc2;
-       }
-       return rc;
-}
-#else
 #define vdbeSorterJoinAll(x,rcin) (rcin)
-#define vdbeSorterJoinThread(pTask) SQL_OK
-#endif
 
 /*
  * Allocate a new MergeEngine object capable of handling up to
@@ -1137,15 +981,6 @@ static void
 vdbeIncrFree(IncrMerger * pIncr)
 {
        if (pIncr) {
-#if SQL_MAX_WORKER_THREADS>0
-               if (pIncr->bUseThread) {
-                       vdbeSorterJoinThread(pIncr->pTask);
-                       if (pIncr->aFile[0].pFd)
-                               sqlOsCloseFree(pIncr->aFile[0].pFd);
-                       if (pIncr->aFile[1].pFd)
-                               sqlOsCloseFree(pIncr->aFile[1].pFd);
-               }
-#endif
                vdbeMergeEngineFree(pIncr->pMerger);
                sql_free(pIncr);
        }
@@ -1160,13 +995,6 @@ sqlVdbeSorterReset(sql * db, VdbeSorter * pSorter)
        int i;
        (void)vdbeSorterJoinAll(pSorter, SQL_OK);
        assert(pSorter->bUseThreads || pSorter->pReader == 0);
-#if SQL_MAX_WORKER_THREADS>0
-       if (pSorter->pReader) {
-               vdbePmaReaderClear(pSorter->pReader);
-               sqlDbFree(db, pSorter->pReader);
-               pSorter->pReader = 0;
-       }
-#endif
        vdbeMergeEngineFree(pSorter->pMerger);
        pSorter->pMerger = 0;
        for (i = 0; i < pSorter->nTask; i++) {
@@ -1516,7 +1344,6 @@ vdbeSorterListToPMA(SortSubtask * pTask, SorterList * 
pList)
            pList->szPMA + sqlVarintLen(pList->szPMA) + pTask->file.iEof;
 #endif
 
-       vdbeSorterWorkDebug(pTask, "enter");
        memset(&writer, 0, sizeof(PmaWriter));
        assert(pList->szPMA > 0);
 
@@ -1558,7 +1385,6 @@ vdbeSorterListToPMA(SortSubtask * pTask, SorterList * 
pList)
                rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof);
        }
 
-       vdbeSorterWorkDebug(pTask, "exit");
        assert(rc != SQL_OK || pList->pList == 0);
        assert(rc != SQL_OK || pTask->file.iEof == iSz);
        return rc;
@@ -1648,22 +1474,6 @@ vdbeMergeEngineStep(MergeEngine * pMerger,       /* The 
merge engine to advance to the
        return (rc == SQL_OK ? pTask->pUnpacked->errCode : rc);
 }
 
-#if SQL_MAX_WORKER_THREADS>0
-/*
- * The main routine for background threads that write level-0 PMAs.
- */
-static void *
-vdbeSorterFlushThread(void *pCtx)
-{
-       SortSubtask *pTask = (SortSubtask *) pCtx;
-       int rc;                 /* Return code */
-       assert(pTask->bDone == 0);
-       rc = vdbeSorterListToPMA(pTask, &pTask->list);
-       pTask->bDone = 1;
-       return SQL_INT_TO_PTR(rc);
-}
-#endif                         /* SQL_MAX_WORKER_THREADS>0 */
-
 /*
  * Flush the current contents of VdbeSorter.list to a new PMA, possibly
  * using a background thread.
@@ -1671,76 +1481,8 @@ vdbeSorterFlushThread(void *pCtx)
 static int
 vdbeSorterFlushPMA(VdbeSorter * pSorter)
 {
-#if SQL_MAX_WORKER_THREADS==0
        pSorter->bUsePMA = 1;
        return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list);
-#else
-       int rc = SQL_OK;
-       int i;
-       SortSubtask *pTask = 0; /* Thread context used to create new PMA */
-       int nWorker = (pSorter->nTask - 1);
-
-       /* Set the flag to indicate that at least one PMA has been written.
-        * Or will be, anyhow.
-        */
-       pSorter->bUsePMA = 1;
-
-       /* Select a sub-task to sort and flush the current list of in-memory
-        * records to disk. If the sorter is running in multi-threaded mode,
-        * round-robin between the first (pSorter->nTask-1) tasks. Except, if
-        * the background thread from a sub-tasks previous turn is still 
running,
-        * skip it. If the first (pSorter->nTask-1) sub-tasks are all still 
busy,
-        * fall back to using the final sub-task. The first (pSorter->nTask-1)
-        * sub-tasks are prefered as they use background threads - the final
-        * sub-task uses the main thread.
-        */
-       for (i = 0; i < nWorker; i++) {
-               int iTest = (pSorter->iPrev + i + 1) % nWorker;
-               pTask = &pSorter->aTask[iTest];
-               if (pTask->bDone) {
-                       rc = vdbeSorterJoinThread(pTask);
-               }
-               if (rc != SQL_OK || pTask->pThread == 0)
-                       break;
-       }
-
-       if (rc == SQL_OK) {
-               if (i == nWorker) {
-                       /* Use the foreground thread for this operation */
-                       rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker],
-                                                &pSorter->list);
-               } else {
-                       /* Launch a background thread for this operation */
-                       u8 *aMem = pTask->list.aMemory;
-                       void *pCtx = (void *)pTask;
-
-                       assert(pTask->pThread == 0 && pTask->bDone == 0);
-                       assert(pTask->list.pList == 0);
-                       assert(pTask->list.aMemory == 0
-                              || pSorter->list.aMemory != 0);
-
-                       pSorter->iPrev = (u8) (pTask - pSorter->aTask);
-                       pTask->list = pSorter->list;
-                       pSorter->list.pList = 0;
-                       pSorter->list.szPMA = 0;
-                       if (aMem) {
-                               pSorter->list.aMemory = aMem;
-                               pSorter->nMemory = sqlMallocSize(aMem);
-                       } else if (pSorter->list.aMemory) {
-                               pSorter->list.aMemory =
-                                   sqlMalloc(pSorter->nMemory);
-                               if (!pSorter->list.aMemory)
-                                       return SQL_NOMEM;
-                       }
-
-                       rc = vdbeSorterCreateThread(pTask,
-                                                   vdbeSorterFlushThread,
-                                                   pCtx);
-               }
-       }
-
-       return rc;
-#endif                         /* SQL_MAX_WORKER_THREADS!=0 */
 }
 
 /*
@@ -1876,8 +1618,6 @@ vdbeIncrPopulate(IncrMerger * pIncr)
        PmaWriter writer;
        assert(pIncr->bEof == 0);
 
-       vdbeSorterPopulateDebug(pTask, "enter");
-
        vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart);
        while (rc == SQL_OK) {
                int dummy;
@@ -1904,36 +1644,9 @@ vdbeIncrPopulate(IncrMerger * pIncr)
        rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof);
        if (rc == SQL_OK)
                rc = rc2;
-       vdbeSorterPopulateDebug(pTask, "exit");
        return rc;
 }
 
-#if SQL_MAX_WORKER_THREADS>0
-/*
- * The main routine for background threads that populate aFile[1] of
- * multi-threaded IncrMerger objects.
- */
-static void *
-vdbeIncrPopulateThread(void *pCtx)
-{
-       IncrMerger *pIncr = (IncrMerger *) pCtx;
-       void *pRet = SQL_INT_TO_PTR(vdbeIncrPopulate(pIncr));
-       pIncr->pTask->bDone = 1;
-       return pRet;
-}
-
-/*
- * Launch a background thread to populate aFile[1] of pIncr.
- */
-static int
-vdbeIncrBgPopulate(IncrMerger * pIncr)
-{
-       void *p = (void *)pIncr;
-       assert(pIncr->bUseThread);
-       return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p);
-}
-#endif
-
 /*
  * This function is called when the PmaReader corresponding to pIncr has
  * finished reading the contents of aFile[0]. Its purpose is to "refill"
@@ -1954,33 +1667,10 @@ vdbeIncrBgPopulate(IncrMerger * pIncr)
 static int
 vdbeIncrSwap(IncrMerger * pIncr)
 {
-       int rc = SQL_OK;
-
-#if SQL_MAX_WORKER_THREADS>0
-       if (pIncr->bUseThread) {
-               rc = vdbeSorterJoinThread(pIncr->pTask);
-
-               if (rc == SQL_OK) {
-                       SorterFile f0 = pIncr->aFile[0];
-                       pIncr->aFile[0] = pIncr->aFile[1];
-                       pIncr->aFile[1] = f0;
-               }
-
-               if (rc == SQL_OK) {
-                       if (pIncr->aFile[0].iEof == pIncr->iStartOff) {
-                               pIncr->bEof = 1;
-                       } else {
-                               rc = vdbeIncrBgPopulate(pIncr);
-                       }
-               }
-       } else
-#endif
-       {
-               rc = vdbeIncrPopulate(pIncr);
-               pIncr->aFile[0] = pIncr->aFile[1];
-               if (pIncr->aFile[0].iEof == pIncr->iStartOff) {
-                       pIncr->bEof = 1;
-               }
+       int rc = vdbeIncrPopulate(pIncr);
+       pIncr->aFile[0] = pIncr->aFile[1];
+       if (pIncr->aFile[0].iEof == pIncr->iStartOff) {
+               pIncr->bEof = 1;
        }
 
        return rc;
@@ -2015,18 +1705,6 @@ vdbeIncrMergerNew(SortSubtask * pTask,   /* The thread 
that will be using the new
        return rc;
 }
 
-#if SQL_MAX_WORKER_THREADS>0
-/*
- * Set the "use-threads" flag on object pIncr.
- */
-static void
-vdbeIncrMergerSetThreads(IncrMerger * pIncr)
-{
-       pIncr->bUseThread = 1;
-       pIncr->pTask->file2.iEof -= pIncr->mxSz;
-}
-#endif                         /* SQL_MAX_WORKER_THREADS>0 */
-
 /*
  * Recompute pMerger->aTree[iOut] by comparing the next keys on the
  * two PmaReaders that feed that entry.  Neither of the PmaReaders
@@ -2077,38 +1755,20 @@ vdbeMergeEngineCompare(MergeEngine * pMerger,   /* 
Merge engine containing PmaRead
        pMerger->aTree[iOut] = iRes;
 }
 
-/*
- * Allowed values for the eMode parameter to vdbeMergeEngineInit()
- * and vdbePmaReaderIncrMergeInit().
- *
- * Only INCRINIT_NORMAL is valid in single-threaded builds (when
- * SQL_MAX_WORKER_THREADS==0).  The other values are only used
- * when there exists one or more separate worker threads.
- */
-#define INCRINIT_NORMAL 0
-#define INCRINIT_TASK   1
-#define INCRINIT_ROOT   2
-
 /*
  * Forward reference required as the vdbeIncrMergeInit() and
  * vdbePmaReaderIncrInit() routines are called mutually recursively when
  * building a merge tree.
  */
-static int vdbePmaReaderIncrInit(PmaReader * pReadr, int eMode);
+static int vdbePmaReaderIncrInit(PmaReader * pReader);
 
 /*
  * Initialize the MergeEngine object passed as the second argument. Once this
  * function returns, the first key of merged data may be read from the
  * MergeEngine object in the usual fashion.
  *
- * If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge
- * objects attached to the PmaReader objects that the merger reads from have
- * already been populated, but that they have not yet populated aFile[0] and
- * set the PmaReader objects up to read from it. In this case all that is
- * required is to call vdbePmaReaderNext() on each PmaReader to point it at
- * its first key.
  *
- * Otherwise, if eMode is any value other than INCRINIT_ROOT, then use
+ * Use
  * vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data
  * to pMerger.
  *
@@ -2116,36 +1776,19 @@ static int vdbePmaReaderIncrInit(PmaReader * pReadr, 
int eMode);
  */
 static int
 vdbeMergeEngineInit(SortSubtask * pTask,       /* Thread that will run pMerger 
*/
-                   MergeEngine * pMerger,      /* MergeEngine to initialize */
-                   int eMode   /* One of the INCRINIT_XXX constants */
+                   MergeEngine * pMerger       /* MergeEngine to initialize */
     )
 {
        int rc = SQL_OK;        /* Return code */
        int i;                  /* For looping over PmaReader objects */
        int nTree = pMerger->nTree;
 
-       /* eMode is always INCRINIT_NORMAL in single-threaded mode */
-       assert(SQL_MAX_WORKER_THREADS > 0 || eMode == INCRINIT_NORMAL);
-
        /* Verify that the MergeEngine is assigned to a single thread */
        assert(pMerger->pTask == 0);
        pMerger->pTask = pTask;
 
        for (i = 0; i < nTree; i++) {
-               if (SQL_MAX_WORKER_THREADS > 0 && eMode == INCRINIT_ROOT) {
-                       /* PmaReaders should be normally initialized in order, 
as if they are
-                        * reading from the same temp file this makes for more 
linear file IO.
-                        * However, in the INCRINIT_ROOT case, if PmaReader 
aReadr[nTask-1] is
-                        * in use it will block the vdbePmaReaderNext() call 
while it uses
-                        * the main thread to fill its buffer. So calling 
PmaReaderNext()
-                        * on this PmaReader before any of the multi-threaded 
PmaReaders takes
-                        * better advantage of multi-processor hardware.
-                        */
-                       rc = vdbePmaReaderNext(&pMerger->aReadr[nTree - i - 1]);
-               } else {
-                       rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i],
-                                                  INCRINIT_NORMAL);
-               }
+               rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i]);
                if (rc != SQL_OK)
                        return rc;
        }
@@ -2157,50 +1800,27 @@ vdbeMergeEngineInit(SortSubtask * pTask,        /* 
Thread that will run pMerger */
 }
 
 /*
- * The PmaReader passed as the first argument is guaranteed to be an
+ * The PmaReader is guaranteed to be an
  * incremental-reader (pReadr->pIncr!=0). This function serves to open
  * and/or initialize the temp file related fields of the IncrMerge
  * object at (pReadr->pIncr).
  *
- * If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
- * in the sub-tree headed by pReadr are also initialized. Data is then
+ * All PmaReaders
+ * in the sub-tree headed by pReadr are also initialized. Data is
  * loaded into the buffers belonging to pReadr and it is set to point to
  * the first key in its range.
  *
- * If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
- * to be a multi-threaded PmaReader and this function is being called in a
- * background thread. In this case all PmaReaders in the sub-tree are
- * initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to
- * pReadr is populated. However, pReadr itself is not set up to point
- * to its first key. A call to vdbePmaReaderNext() is still required to do
- * that.
- *
- * The reason this function does not call vdbePmaReaderNext() immediately
- * in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has
- * to block on thread (pTask->thread) before accessing aFile[1]. But, since
- * this entire function is being run by thread (pTask->thread), that will
- * lead to the current background thread attempting to join itself.
- *
- * Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed
- * that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all
- * child-trees have already been initialized using IncrInit(INCRINIT_TASK).
- * In this case vdbePmaReaderNext() is called on all child PmaReaders and
- * the current PmaReader set to point to the first key in its range.
- *
  * SQL_OK is returned if successful, or an sql error code otherwise.
  */
 static int
-vdbePmaReaderIncrMergeInit(PmaReader * pReadr, int eMode)
+vdbePmaReaderIncrMergeInit(PmaReader * pReadr)
 {
        int rc = SQL_OK;
        IncrMerger *pIncr = pReadr->pIncr;
        SortSubtask *pTask = pIncr->pTask;
        sql *db = pTask->pSorter->db;
 
-       /* eMode is always INCRINIT_NORMAL in single-threaded mode */
-       assert(SQL_MAX_WORKER_THREADS > 0 || eMode == INCRINIT_NORMAL);
-
-       rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
+       rc = vdbeMergeEngineInit(pTask, pIncr->pMerger);
 
        /* Set up the required files for pIncr. A multi-theaded IncrMerge object
         * requires two temp files to itself, whereas a single-threaded object
@@ -2208,74 +1828,27 @@ vdbePmaReaderIncrMergeInit(PmaReader * pReadr, int 
eMode)
         */
        if (rc == SQL_OK) {
                int mxSz = pIncr->mxSz;
-#if SQL_MAX_WORKER_THREADS>0
-               if (pIncr->bUseThread) {
-                       rc = vdbeSorterOpenTempFile(db, mxSz,
-                                                   &pIncr->aFile[0].pFd);
-                       if (rc == SQL_OK) {
-                               rc = vdbeSorterOpenTempFile(db, mxSz,
-                                                           &pIncr->aFile[1].
-                                                           pFd);
-                       }
-               } else
-#endif
-                       /*if( !pIncr->bUseThread ) */  {
-                       if (pTask->file2.pFd == 0) {
-                               assert(pTask->file2.iEof > 0);
-                               rc = vdbeSorterOpenTempFile(db,
-                                                           pTask->file2.iEof,
-                                                           &pTask->file2.pFd);
-                               pTask->file2.iEof = 0;
-                       }
-                       if (rc == SQL_OK) {
-                               pIncr->aFile[1].pFd = pTask->file2.pFd;
-                               pIncr->iStartOff = pTask->file2.iEof;
-                               pTask->file2.iEof += mxSz;
-                       }
-                       }
-       }
-#if SQL_MAX_WORKER_THREADS>0
-       if (rc == SQL_OK && pIncr->bUseThread) {
-               /* Use the current thread to populate aFile[1], even though this
-                * PmaReader is multi-threaded. If this is an INCRINIT_TASK 
object,
-                * then this function is already running in background thread
-                * pIncr->pTask->thread.
-                *
-                * If this is the INCRINIT_ROOT object, then it is running in 
the
-                * main VDBE thread. But that is Ok, as that thread cannot 
return
-                * control to the VDBE or proceed with anything useful until the
-                * first results are ready from this merger object anyway.
-                */
-               assert(eMode == INCRINIT_ROOT || eMode == INCRINIT_TASK);
-               rc = vdbeIncrPopulate(pIncr);
+               if (pTask->file2.pFd == 0) {
+                       assert(pTask->file2.iEof > 0);
+                       rc = vdbeSorterOpenTempFile(db,
+                                                   pTask->file2.iEof,
+                                                   &pTask->file2.pFd);
+                       pTask->file2.iEof = 0;
+               }
+               if (rc == SQL_OK) {
+                       pIncr->aFile[1].pFd = pTask->file2.pFd;
+                       pIncr->iStartOff = pTask->file2.iEof;
+                       pTask->file2.iEof += mxSz;
+               }
        }
-#endif
 
-       if (rc == SQL_OK
-           && (SQL_MAX_WORKER_THREADS == 0 || eMode != INCRINIT_TASK)) {
+       if (rc == SQL_OK) {
                rc = vdbePmaReaderNext(pReadr);
        }
 
        return rc;
 }
 
-#if SQL_MAX_WORKER_THREADS>0
-/*
- * The main routine for vdbePmaReaderIncrMergeInit() operations run in
- * background threads.
- */
-static void *
-vdbePmaReaderBgIncrInit(void *pCtx)
-{
-       PmaReader *pReader = (PmaReader *) pCtx;
-       void *pRet =
-           SQL_INT_TO_PTR(vdbePmaReaderIncrMergeInit(pReader, INCRINIT_TASK)
-           );
-       pReader->pIncr->pTask->bDone = 1;
-       return pRet;
-}
-#endif
-
 /*
  * If the PmaReader passed as the first argument is not an incremental-reader
  * (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
@@ -2288,23 +1861,12 @@ vdbePmaReaderBgIncrInit(void *pCtx)
  * using the current thread.
  */
 static int
-vdbePmaReaderIncrInit(PmaReader * pReadr, int eMode)
+vdbePmaReaderIncrInit(PmaReader * pReadr)
 {
        IncrMerger *pIncr = pReadr->pIncr;      /* Incremental merger */
        int rc = SQL_OK;        /* Return code */
        if (pIncr) {
-#if SQL_MAX_WORKER_THREADS>0
-               assert(pIncr->bUseThread == 0 || eMode == INCRINIT_TASK);
-               if (pIncr->bUseThread) {
-                       void *pCtx = (void *)pReadr;
-                       rc = vdbeSorterCreateThread(pIncr->pTask,
-                                                   vdbePmaReaderBgIncrInit,
-                                                   pCtx);
-               } else
-#endif
-               {
-                       rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
-               }
+               rc = vdbePmaReaderIncrMergeInit(pReadr);
        }
        return rc;
 }
@@ -2451,23 +2013,10 @@ vdbeSorterMergeTreeBuild(VdbeSorter * pSorter,  /* The 
VDBE cursor that implement
        int rc = SQL_OK;
        int iTask;
 
-#if SQL_MAX_WORKER_THREADS>0
-       /* If the sorter uses more than one task, then create the top-level
-        * MergeEngine here. This MergeEngine will read data from exactly
-        * one PmaReader per sub-task.
-        */
-       assert(pSorter->bUseThreads || pSorter->nTask == 1);
-       if (pSorter->nTask > 1) {
-               pMain = vdbeMergeEngineNew(pSorter->nTask);
-               if (pMain == 0)
-                       rc = SQL_NOMEM;
-       }
-#endif
-
        for (iTask = 0; rc == SQL_OK && iTask < pSorter->nTask; iTask++) {
                SortSubtask *pTask = &pSorter->aTask[iTask];
-               assert(pTask->nPMA > 0 || SQL_MAX_WORKER_THREADS > 0);
-               if (SQL_MAX_WORKER_THREADS == 0 || pTask->nPMA) {
+               assert(pTask->nPMA > 0);
+               if (pTask->nPMA) {
                        MergeEngine *pRoot = 0; /* Root node of tree for this 
task */
                        int nDepth = vdbeSorterTreeDepth(pTask->nPMA);
                        i64 iReadOff = 0;
@@ -2505,18 +2054,8 @@ vdbeSorterMergeTreeBuild(VdbeSorter * pSorter,   /* The 
VDBE cursor that implement
                        }
 
                        if (rc == SQL_OK) {
-#if SQL_MAX_WORKER_THREADS>0
-                               if (pMain != 0) {
-                                       rc = vdbeIncrMergerNew(pTask, pRoot,
-                                                              &pMain->
-                                                              aReadr[iTask].
-                                                              pIncr);
-                               } else
-#endif
-                               {
-                                       assert(pMain == 0);
-                                       pMain = pRoot;
-                               }
+                               assert(pMain == 0);
+                               pMain = pRoot;
                        } else {
                                vdbeMergeEngineFree(pRoot);
                        }
@@ -2546,88 +2085,12 @@ vdbeSorterSetupMerge(VdbeSorter * pSorter)
        int rc;                 /* Return code */
        SortSubtask *pTask0 = &pSorter->aTask[0];
        MergeEngine *pMain = 0;
-#if SQL_MAX_WORKER_THREADS
-       sql *db = pTask0->pSorter->db;
-       int i;
-       SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
-       for (i = 0; i < pSorter->nTask; i++) {
-               pSorter->aTask[i].xCompare = xCompare;
-       }
-#endif
 
        rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
        if (rc == SQL_OK) {
-#if SQL_MAX_WORKER_THREADS
-               assert(pSorter->bUseThreads == 0 || pSorter->nTask > 1);
-               if (pSorter->bUseThreads) {
-                       int iTask;
-                       PmaReader *pReadr = 0;
-                       SortSubtask *pLast =
-                           &pSorter->aTask[pSorter->nTask - 1];
-                       rc = vdbeSortAllocUnpacked(pLast);
-                       if (rc == SQL_OK) {
-                               pReadr =
-                                   (PmaReader *) sqlDbMallocZero(db,
-                                                                     sizeof
-                                                                     
(PmaReader));
-                               pSorter->pReader = pReadr;
-                               if (pReadr == 0)
-                                       rc = SQL_NOMEM;
-                       }
-                       if (rc == SQL_OK) {
-                               rc = vdbeIncrMergerNew(pLast, pMain,
-                                                      &pReadr->pIncr);
-                               if (rc == SQL_OK) {
-                                       vdbeIncrMergerSetThreads(pReadr->pIncr);
-                                       for (iTask = 0;
-                                            iTask < (pSorter->nTask - 1);
-                                            iTask++) {
-                                               IncrMerger *pIncr;
-                                               if ((pIncr =
-                                                    pMain->aReadr[iTask].
-                                                    pIncr)) {
-                                                       vdbeIncrMergerSetThreads
-                                                           (pIncr);
-                                                       assert(pIncr->pTask !=
-                                                              pLast);
-                                               }
-                                       }
-                                       for (iTask = 0;
-                                            rc == SQL_OK
-                                            && iTask < pSorter->nTask;
-                                            iTask++) {
-                                               /* Check that:
-                                                *
-                                                *   a) The incremental merge 
object is configured to use the
-                                                *      right task, and
-                                                *   b) If it is using task 
(nTask-1), it is configured to run
-                                                *      in single-threaded 
mode. This is important, as the
-                                                *      root merge 
(INCRINIT_ROOT) will be using the same task
-                                                *      object.
-                                                */
-                                               PmaReader *p =
-                                                   &pMain->aReadr[iTask];
-                                               assert(p->pIncr == 0 || 
((p->pIncr->pTask == &pSorter->aTask[iTask])    /* a */
-                                                                        
&&(iTask != pSorter->nTask - 1 || p->pIncr->bUseThread == 0)   /* b */
-                                                      ));
-                                               rc = vdbePmaReaderIncrInit(p,
-                                                                          
INCRINIT_TASK);
-                                       }
-                               }
-                               pMain = 0;
-                       }
-                       if (rc == SQL_OK) {
-                               rc = vdbePmaReaderIncrMergeInit(pReadr,
-                                                               INCRINIT_ROOT);
-                       }
-               } else
-#endif
-               {
-                       rc = vdbeMergeEngineInit(pTask0, pMain,
-                                                INCRINIT_NORMAL);
-                       pSorter->pMerger = pMain;
-                       pMain = 0;
-               }
+               rc = vdbeMergeEngineInit(pTask0, pMain);
+               pSorter->pMerger = pMain;
+               pMain = 0;
        }
 
        if (rc != SQL_OK) {
@@ -2676,8 +2139,6 @@ sqlVdbeSorterRewind(const VdbeCursor * pCsr, int *pbEof)
        /* Join all threads */
        rc = vdbeSorterJoinAll(pSorter, rc);
 
-       vdbeSorterRewindDebug("rewind");
-
        /* Assuming no errors have occurred, set up a merger structure to
         * incrementally read and merge all remaining PMAs.
         */
@@ -2687,7 +2148,6 @@ sqlVdbeSorterRewind(const VdbeCursor * pCsr, int *pbEof)
                *pbEof = 0;
        }
 
-       vdbeSorterRewindDebug("rewinddone");
        return rc;
 }
 
@@ -2708,12 +2168,6 @@ sqlVdbeSorterNext(sql * db, const VdbeCursor * pCsr, int 
*pbEof)
                assert(pSorter->pReader == 0 || pSorter->pMerger == 0);
                assert(pSorter->bUseThreads == 0 || pSorter->pReader);
                assert(pSorter->bUseThreads == 1 || pSorter->pMerger);
-#if SQL_MAX_WORKER_THREADS>0
-               if (pSorter->bUseThreads) {
-                       rc = vdbePmaReaderNext(pSorter->pReader);
-                       *pbEof = (pSorter->pReader->pFd == 0);
-               } else
-#endif
                        /*if( !pSorter->bUseThreads ) */  {
                        assert(pSorter->pMerger != 0);
                        assert(pSorter->pMerger->pTask == (&pSorter->aTask[0]));
@@ -2743,11 +2197,6 @@ vdbeSorterRowkey(const VdbeSorter * pSorter,     /* 
Sorter object */
        void *pKey;
        if (pSorter->bUsePMA) {
                PmaReader *pReader;
-#if SQL_MAX_WORKER_THREADS>0
-               if (pSorter->bUseThreads) {
-                       pReader = pSorter->pReader;
-               } else
-#endif
                        /*if( !pSorter->bUseThreads ) */  {
                        pReader =
                            &pSorter->pMerger->aReadr[pSorter->pMerger->
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index efd4f4f4b..1e8c721af 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -4561,12 +4561,6 @@ sqlWhereBegin(Parse * pParse,    /* The parser context */
                        VdbeComment((v, "%s", space->def->name));
                        assert(pTabItem->iCursor == pLevel->iTabCur);
                        sqlVdbeChangeP5(v, bFordelete);
-#ifdef SQL_ENABLE_COLUMN_USED_MASK
-                       sqlVdbeAddOp4Dup8(v, OP_ColumnsUsed,
-                                             pTabItem->iCursor, 0, 0,
-                                             (const u8 *)&pTabItem->colUsed,
-                                             P4_INT64);
-#endif
                }
                if (pLoop->wsFlags & WHERE_INDEXED) {
                        struct index_def *idx_def = pLoop->index_def;
@@ -4641,30 +4635,6 @@ sqlWhereBegin(Parse * pParse,    /* The parser context */
                                        sqlVdbeChangeP5(v, OPFLAG_SEEKEQ);      
/* Hint to COMDB2 */
                                }
                                VdbeComment((v, "%s", idx_def->name));
-#ifdef SQL_ENABLE_COLUMN_USED_MASK
-                               {
-                                       u64 colUsed = 0;
-                                       int ii, jj;
-                                       for (ii = 0; ii < pIx->nColumn; ii++) {
-                                               jj = pIx->aiColumn[ii];
-                                               if (jj < 0)
-                                                       continue;
-                                               if (jj > 63)
-                                                       jj = 63;
-                                               if ((pTabItem->
-                                                    colUsed & MASKBIT(jj)) ==
-                                                   0)
-                                                       continue;
-                                               colUsed |=
-                                                   ((u64) 1) << (ii <
-                                                                 63 ? ii : 63);
-                                       }
-                                       sqlVdbeAddOp4Dup8(v, OP_ColumnsUsed,
-                                                             iIndexCur, 0, 0,
-                                                             (u8 *) & colUsed,
-                                                             P4_INT64);
-                               }
-#endif                         /* SQL_ENABLE_COLUMN_USED_MASK */
                        }
                }
        }
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 4dedb38a7..c9a2b7dcb 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -253,14 +253,14 @@ sqlWhereExplainOneScan(Parse * pParse,    /* Parse 
context */
                                       " USING INTEGER PRIMARY KEY (rowid%s?)",
                                       zRangeOp);
                }
-#ifdef SQL_EXPLAIN_ESTIMATED_ROWS
+
                if (pLoop->nOut >= 10) {
                        sqlXPrintf(&str, " (~%llu rows)",
                                       sqlLogEstToInt(pLoop->nOut));
                } else {
                        sqlStrAccumAppend(&str, " (~1 row)", 9);
                }
-#endif
+
                zMsg = sqlStrAccumFinish(&str);
                ret =
                    sqlVdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,
diff --git a/test/sql-tap/collation.test.lua b/test/sql-tap/collation.test.lua
index 0bf54576d..79547361c 100755
--- a/test/sql-tap/collation.test.lua
+++ b/test/sql-tap/collation.test.lua
@@ -452,7 +452,7 @@ for _, data_collation in ipairs(data_collations) do
         test:do_execsql_test(
             extendex_prefix.."select_plan_contains_b-tree",
             string.format("explain query plan select b from t1 order by b 
%s;",data_collation[1]),
-            {0,0,0,"SCAN TABLE T1",
+            {0,0,0,"SCAN TABLE T1 (~1048576 rows)",
                 0,0,0,"USE TEMP B-TREE FOR ORDER BY"})
         test:do_execsql_test(
             extendex_prefix.."select",
@@ -465,7 +465,7 @@ for _, data_collation in ipairs(data_collations) do
         test:do_execsql_test(
             extendex_prefix.."select_from_index_plan_does_not_contain_b-tree",
             string.format("explain query plan select b from t1 order by b 
%s;",data_collation[1]),
-            {0,0,0,"SCAN TABLE T1 USING COVERING INDEX I"})
+            {0,0,0,"SCAN TABLE T1 USING COVERING INDEX I (~1048576 rows)"})
         test:do_execsql_test(
             extendex_prefix.."select_from_index",
             string.format("select b from t1 order by b %s;",data_collation[1]),
@@ -494,7 +494,7 @@ local like_testcases =
         {0, {"Aab", "aaa"}} },
     {"2.1.2",
         "EXPLAIN QUERY PLAN SELECT * FROM tx1 WHERE s1 LIKE 'A%';",
-        {0, {0, 0, 0, "SEARCH TABLE TX1 USING COVERING INDEX I1 (S1>? AND 
S1<?)"}}},
+        {0, {0, 0, 0, "SEARCH TABLE TX1 USING COVERING INDEX I1 (S1>? AND 
S1<?) (~16384 rows)"}}},
     {"2.2.0",
         "PRAGMA case_sensitive_like = true;",
         {0}},
diff --git a/test/sql-tap/eqp.test.lua b/test/sql-tap/eqp.test.lua
index 2aa2d9675..b8c3c6607 100755
--- a/test/sql-tap/eqp.test.lua
+++ b/test/sql-tap/eqp.test.lua
@@ -30,7 +30,7 @@ local testprefix = "eqp"
 --
 
 test:do_execsql_test(
-    1.1,
+    "1.1",
     [[
         CREATE TABLE t1(idt1  INT primary key, a INT, b INT, ex TEXT);
         CREATE INDEX i1 ON t1(a);
@@ -40,67 +40,67 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test(
-    1.2,
+    "1.2",
     [[
         SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
     ]], {
         -- <1.2>
-        {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
-        {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (B=?)"},
-        {0, 1, 0, "SCAN TABLE T2"}
+        {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
+        {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (B=?) (~10 rows)"},
+        {0, 1, 0, "SCAN TABLE T2 (~1048576 rows)"}
         -- </1.2>
     })
 
 test:do_eqp_test(
-    1.3,
+    "1.3",
     [[
         SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
     ]], {
         -- <1.3>
-        {0, 0, 0, "SCAN TABLE T2"},
-        {0, 1, 1, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
-        {0, 1, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (B=?)"}
+        {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
+        {0, 1, 1, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
+        {0, 1, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (B=?) (~10 rows)"}
         -- </1.3>
     })
 
 test:do_eqp_test(
-    1.3,
+    "1.3",
     [[
         SELECT a FROM t1 ORDER BY a
     ]], {
         -- <1.3>
-        {0, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1"}
+        {0, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1 (~1048576 rows)"}
         -- </1.3>
     })
 
 test:do_eqp_test(
-    1.4,
+    "1.4",
     [[
         SELECT a FROM t1 ORDER BY +a
     ]], {
         -- <1.4>
-        {0, 0, 0, "SCAN TABLE T1"},
+        {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"}
         -- </1.4>
     })
 
 test:do_eqp_test(
-    1.5,
+    "1.5",
     [[
         SELECT a FROM t1 WHERE a=4
     ]], {
         -- <1.5>
-        {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"}
+        {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"}
         -- </1.5>
     })
 
 test:do_eqp_test(
-    1.6,
+    "1.6",
     [[
         SELECT DISTINCT count(*) FROM t3 GROUP BY a;
     ]], {
         -- <1.6>
-        {0, 0, 0, "SCAN TABLE T3"},
+        {0, 0, 0, "SCAN TABLE T3 (~1048576 rows)"},
         {0, 0, 0, "USE TEMP B-TREE FOR GROUP BY"},
         {0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
         
@@ -108,40 +108,40 @@ test:do_eqp_test(
     })
 
 test:do_eqp_test(
-    1.7,
+    "1.7",
     [[
         SELECT * FROM t3 JOIN (SELECT 1)
     ]], {
         -- <1.7>
-        {0, 0, 1, "SCAN SUBQUERY 1"},
-        {0, 1, 0, "SCAN TABLE T3"},
+        {0, 0, 1, "SCAN SUBQUERY 1 (~1 row)"},
+        {0, 1, 0, "SCAN TABLE T3 (~1048576 rows)"},
         
         -- </1.7>
     })
 
 test:do_eqp_test(
-    1.8,
+    "1.8",
     [[
         SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
     ]], {
         -- <1.8>
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)"},
-        {0, 0, 1, "SCAN SUBQUERY 1"},
-        {0, 1, 0, "SCAN TABLE T3"},
+        {0, 0, 1, "SCAN SUBQUERY 1 (~1 row)"},
+        {0, 1, 0, "SCAN TABLE T3 (~1048576 rows)"},
         
         -- </1.8>
     })
 
 test:do_eqp_test(
-    1.9,
+    "1.9",
     [[
         SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
     ]], {
         -- <1.9>
-        {3, 0, 0, "SCAN TABLE T3"},
+        {3, 0, 0, "SCAN TABLE T3 (~1048576 rows)"},
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)"},
-        {0, 0, 1,"SCAN SUBQUERY 1"},
-        {0, 1, 0,"SCAN TABLE T3"},
+        {0, 0, 1,"SCAN SUBQUERY 1 (~1 row)"},
+        {0, 1, 0,"SCAN TABLE T3 (~1048576 rows)"},
 
         -- </1.9>
     })
@@ -152,24 +152,24 @@ test:do_eqp_test(
         SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
     ]], {
         -- <1.10>
-        {3, 0, 0, "SCAN TABLE T3"},
+        {3, 0, 0, "SCAN TABLE T3 (~1048576 rows)"},
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)"},
-        {0, 0, 1, "SCAN SUBQUERY 1"},
-        {0, 1, 0, "SCAN TABLE T3"},
+        {0, 0, 1, "SCAN SUBQUERY 1 (~1 row)"},
+        {0, 1, 0, "SCAN TABLE T3 (~1048576 rows)"},
         
         -- </1.10>
     })
 
 test:do_eqp_test(
-    1.11,
+    "1.11",
     [[
         SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
     ]], {
         -- <1.11>
-        {3, 0, 0, "SCAN TABLE T3"},
+        {3, 0, 0, "SCAN TABLE T3 (~1048576 rows)"},
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)"},
-        {0, 0, 1, "SCAN SUBQUERY 1"},
-        {0, 1, 0, "SCAN TABLE T3"},
+        {0, 0, 1, "SCAN SUBQUERY 1 (~1 row)"},
+        {0, 1, 0, "SCAN TABLE T3 (~1048576 rows)"},
         
         -- </1.11>
     })
@@ -179,7 +179,7 @@ test:do_eqp_test(
 --
 test:drop_all_tables()
 test:do_execsql_test(
-    2.1,
+    "2.1",
     [[
         CREATE TABLE t1(idt1  INT primary key, x INT, y INT, ex TEXT);
 
@@ -188,13 +188,13 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test("2.2.1", "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x 
ORDER BY 1", {
-    {0, 0, 0, "SCAN TABLE T1"},
+    {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
     {0, 0, 0, "USE TEMP B-TREE FOR GROUP BY"},
     {0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
 test:do_eqp_test("2.2.2", "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x 
ORDER BY 1", {
-    {0, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+    {0, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
     {0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
@@ -204,34 +204,34 @@ test:do_eqp_test("2.2.2", "SELECT DISTINCT min(x), max(x) 
FROM t2 GROUP BY x ORD
 --    {0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
 --})
 test:do_eqp_test("2.2.4", "SELECT DISTINCT * FROM t1, t2", {
-    {0, 0, 0, "SCAN TABLE T1"},
+    {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
     -- changed after reordering indexes
     -- actually it does not matter (in fact, it seems like pk should have been 
used in both cases)
     --{0, 1, 1, "SCAN TABLE T2 USING COVERING INDEX t2i1"},
-    {0, 1, 1, "SCAN TABLE T2"},
+    {0, 1, 1, "SCAN TABLE T2 (~1048576 rows)"},
     --{0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
 })
 test:do_eqp_test("2.2.5", "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x", {
-    {0, 0, 0, "SCAN TABLE T1"},
-    {0, 1, 1, "SCAN TABLE T2"},
+    {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
+    {0, 1, 1, "SCAN TABLE T2 (~1048576 rows)"},
     --{0, 0, 0, "USE TEMP B-TREE FOR DISTINCT"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
 test:do_eqp_test("2.2.6", "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x", {
-    {0, 0, 1, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
-    {0, 1, 0, "SCAN TABLE T1"},
+    {0, 0, 1, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
+    {0, 1, 0, "SCAN TABLE T1 (~1048576 rows)"},
 })
 test:do_eqp_test("2.3.1", "SELECT max(x) FROM t2", {
-    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2I1"},
+    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
 })
 test:do_eqp_test("2.3.2", "SELECT min(x) FROM t2", {
-    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2I1"},
+    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
 })
 test:do_eqp_test("2.3.3", "SELECT min(x), max(x) FROM t2", {
-    {0, 0, 0, "SCAN TABLE T2"},
+    {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
 })
 test:do_eqp_test("2.4.1", "SELECT * FROM t1 WHERE idt1=?", {
-    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (IDT1=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (IDT1=?) (~1 row)"},
 })
 ---------------------------------------------------------------------------
 -- Test cases eqp-3.* - tests for select statements that use sub-selects.
@@ -242,9 +242,9 @@ test:do_eqp_test(
         SELECT (SELECT x FROM t1 AS sub) FROM t1;
     ]], {
         -- <3.1.1>
-        {0, 0, 0, "SCAN TABLE T1"},
+        {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "EXECUTE SCALAR SUBQUERY 1"},
-        {1, 0, 0, "SCAN TABLE T1 AS SUB"},
+        {1, 0, 0, "SCAN TABLE T1 AS SUB (~1048576 rows)"},
         
         -- </3.1.1>
     })
@@ -255,9 +255,9 @@ test:do_eqp_test(
         SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
     ]], {
         -- <3.1.2>
-        {0, 0, 0, "SCAN TABLE T1"},
+        {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "EXECUTE SCALAR SUBQUERY 1"},
-        {1, 0, 0, "SCAN TABLE T1 AS SUB"},
+        {1, 0, 0, "SCAN TABLE T1 AS SUB (~1048576 rows)"},
         
         -- </3.1.2>
     })
@@ -268,9 +268,9 @@ test:do_eqp_test(
         SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
     ]], {
         -- <3.1.3>
-        {0, 0, 0, "SCAN TABLE T1"},
+        {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "EXECUTE SCALAR SUBQUERY 1"},
-        {1, 0, 0, "SCAN TABLE T1 AS SUB"},
+        {1, 0, 0, "SCAN TABLE T1 AS SUB (~1048576 rows)"},
         {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
         
         -- </3.1.3>
@@ -282,9 +282,9 @@ test:do_eqp_test(
         SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
     ]], {
         -- <3.1.4>
-        {0, 0, 0, "SCAN TABLE T1"},
+        {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "EXECUTE SCALAR SUBQUERY 1"},
-        {1, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {1, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         
         -- </3.1.4>
     })
@@ -292,9 +292,9 @@ test:do_eqp_test(
 test:do_eqp_test("3.2.1", [[
   SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
 ]], {
-    {1, 0, 0, "SCAN TABLE T1"}, 
+    {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
     {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"}, 
-    {0, 0, 0, "SCAN SUBQUERY 1"}, 
+    {0, 0, 0, "SCAN SUBQUERY 1 (~1 row)"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
 test:do_eqp_test("3.2.2", [[
@@ -303,33 +303,33 @@ test:do_eqp_test("3.2.2", [[
     (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
   ORDER BY x2.y LIMIT 5
 ]], {
-    {1, 0, 0, "SCAN TABLE T1"}, 
+    {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
     {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"}, 
-    {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
-    {0, 0, 0, "SCAN SUBQUERY 1 AS X1"}, 
-    {0, 1, 1, "SCAN SUBQUERY 2 AS X2"}, 
+    {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
+    {0, 0, 0, "SCAN SUBQUERY 1 AS X1 (~1 row)"},
+    {0, 1, 1, "SCAN SUBQUERY 2 AS X2 (~1 row)"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
 test:do_eqp_test("3.3.1", [[
   SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
 ]], {
-    {0, 0, 0, "SCAN TABLE T1"}, 
+    {0, 0, 0, "SCAN TABLE T1 (~983040 rows)"},
     {0, 0, 0, "EXECUTE LIST SUBQUERY 1"}, 
-    {1, 0, 0, "SCAN TABLE T2"},
+    {1, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
 })
 test:do_eqp_test("3.3.2", [[
   SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
 ]], {
-    {0, 0, 0, "SCAN TABLE T1"}, 
+    {0, 0, 0, "SCAN TABLE T1 (~983040 rows)"},
     {0, 0, 0, "EXECUTE CORRELATED LIST SUBQUERY 1"}, 
-    {1, 0, 0, "SCAN TABLE T2"},
+    {1, 0, 0, "SCAN TABLE T2 (~983040 rows)"},
 })
 test:do_eqp_test("3.3.3", [[
   SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
 ]], {
-    {0, 0, 0, "SCAN TABLE T1"}, 
+    {0, 0, 0, "SCAN TABLE T1 (~983040 rows)"},
     {0, 0, 0, "EXECUTE CORRELATED SCALAR SUBQUERY 1"}, 
-    {1, 0, 0, "SCAN TABLE T2"},
+    {1, 0, 0, "SCAN TABLE T2 (~983040 rows)"},
 })
 ---------------------------------------------------------------------------
 -- Test cases eqp-4.* - tests for composite select statements.
@@ -340,8 +340,8 @@ test:do_eqp_test(
         SELECT * FROM t1 UNION ALL SELECT * FROM t2
     ]], {
         -- <4.1.1>
-        {1, 0, 0, "SCAN TABLE T1"},
-        {2, 0, 0, "SCAN TABLE T2"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
+        {2, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)"},
         
         -- </4.1.1>
@@ -353,9 +353,9 @@ test:do_eqp_test(
         SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
     ]], {
         -- <4.1.2>
-        {1, 0, 0, "SCAN TABLE T1"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
-        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)"},
         
         -- </4.1.2>
@@ -367,9 +367,9 @@ test:do_eqp_test(
         SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
     ]], {
         -- <4.1.3>
-        {1, 0, 0, "SCAN TABLE T1"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
-        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         {2, 0, 0, "USE TEMP B-TREE FOR RIGHT PART OF ORDER BY"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (UNION)"},
         
@@ -382,9 +382,9 @@ test:do_eqp_test(
         SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
     ]], {
         -- <4.1.4>
-        {1, 0, 0, "SCAN TABLE T1"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
-        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         {2, 0, 0, "USE TEMP B-TREE FOR RIGHT PART OF ORDER BY"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)"},
         
@@ -397,9 +397,9 @@ test:do_eqp_test(
         SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
     ]], {
         -- <4.1.5>
-        {1, 0, 0, "SCAN TABLE T1"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {1, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
-        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {2, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         {2, 0, 0, "USE TEMP B-TREE FOR RIGHT PART OF ORDER BY"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)"}
         -- </4.1.5>
@@ -470,8 +470,8 @@ test:do_eqp_test(
         SELECT x FROM t1 UNION SELECT x FROM t2
     ]], {
         -- <4.3.1>
-        {1, 0, 0, "SCAN TABLE T1"},
-        {2, 0, 0, "SCAN TABLE T2"},
+        {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
+        {2, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)"},
         
         -- </4.3.1>
@@ -483,10 +483,10 @@ test:do_eqp_test(
         SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
     ]], {
         -- <4.3.2>
-        {2, 0, 0, "SCAN TABLE T1"},
-        {3, 0, 0, "SCAN TABLE T2"},
+        {2, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
+        {3, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)"},
-        {4, 0, 0, "SCAN TABLE T1"},
+        {4, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)"}
         -- </4.3.2>
     })
@@ -497,11 +497,11 @@ test:do_eqp_test(
         SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER 
BY 1
     ]], {
         -- <4.3.3>
-        {2, 0, 0, "SCAN TABLE T1"},
+        {2, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {2, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
-        {3, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1"},
+        {3, 0, 0, "SCAN TABLE T2 USING COVERING INDEX T2I1 (~1048576 rows)"},
         {1, 0, 0, "COMPOUND SUBQUERIES 2 AND 3 (UNION)"},
-        {4, 0, 0, "SCAN TABLE T1"},
+        {4, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
         {4, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
         {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 4 (UNION)"}
         -- </4.3.3>
@@ -523,7 +523,7 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test("5.1.1", "SELECT a, b FROM t1 WHERE a=1", {
-    {0, 0, 0, "SCAN TABLE T1"},
+    {0, 0, 0, "SCAN TABLE T1 (~524288 rows)"},
 })
 -- EVIDENCE-OF: R-55852-17599 sql> CREATE INDEX i1 ON t1(a);
 -- sql> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
@@ -536,7 +536,7 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test("5.2.1", "SELECT a, b FROM t1 WHERE a=1", {
-    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
 })
 -- EVIDENCE-OF: R-21179-11011 sql> CREATE INDEX i2 ON t1(a, b);
 -- sql> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
@@ -551,7 +551,7 @@ test:do_execsql_test(
 test:do_eqp_test("5.3.1", "SELECT a, b FROM t1 WHERE a=1", {
     -- It is equal for tarantol wheather to use i1 or i2
     -- because both of them are covering
-    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
     --{0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
 })
 -- EVIDENCE-OF: R-09991-48941 sql> EXPLAIN QUERY PLAN
@@ -566,8 +566,8 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test("5.4.1", "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND 
t1.b>2", {
-    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=? AND B>?)"},
-    {0, 1, 1, "SCAN TABLE T2"},
+    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=? AND B>?) (~2 
rows)"},
+    {0, 1, 1, "SCAN TABLE T2 (~1048576 rows)"},
 })
 -- EVIDENCE-OF: R-33626-61085 sql> EXPLAIN QUERY PLAN
 -- SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
@@ -575,8 +575,8 @@ test:do_eqp_test("5.4.1", "SELECT t1.a, t2.c FROM t1, t2 
WHERE t1.a=1 AND t1.b>2
 -- 0|1|0|SCAN TABLE T2
 --
 test:do_eqp_test(5.5, "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2", 
{
-    {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=? AND B>?)"},
-    {0, 1, 0, "SCAN TABLE T2"},
+    {0, 0, 1, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=? AND B>?) (~2 
rows)"},
+    {0, 1, 0, "SCAN TABLE T2 (~1048576 rows)"},
 })
 -- EVIDENCE-OF: R-04002-25654 sql> CREATE INDEX i3 ON t1(b);
 -- sql> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
@@ -593,8 +593,8 @@ test:do_eqp_test("5.6.1", "SELECT a, b FROM t1 WHERE a=1 OR 
b=2", {
     -- It is equal for tarantol wheather to use i1 or i2
     -- because both of them are covering
     --{0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=?)"},
-    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
-    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I3 (B=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I3 (B=?) (~10 rows)"},
 })
 -- EVIDENCE-OF: R-24577-38891 sql> EXPLAIN QUERY PLAN
 -- SELECT c, d FROM t2 ORDER BY c;
@@ -602,7 +602,7 @@ test:do_eqp_test("5.6.1", "SELECT a, b FROM t1 WHERE a=1 OR 
b=2", {
 -- 0|0|0|USE TEMP B-TREE FOR ORDER BY
 --
 test:do_eqp_test(5.7, "SELECT c, d FROM t2 ORDER BY c", {
-    {0, 0, 0, "SCAN TABLE T2"},
+    {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
     {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
 })
 -- EVIDENCE-OF: R-58157-12355 sql> CREATE INDEX i4 ON t2(c);
@@ -616,7 +616,7 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test("5.8.1", "SELECT c, d FROM t2 ORDER BY c", {
-    {0, 0, 0, "SCAN TABLE T2 USING COVERING INDEX I4"},
+    {0, 0, 0, "SCAN TABLE T2 USING COVERING INDEX I4 (~1048576 rows)"},
 })
 -- EVIDENCE-OF: R-13931-10421 sql> EXPLAIN QUERY PLAN SELECT
 -- (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
@@ -626,17 +626,17 @@ test:do_eqp_test("5.8.1", "SELECT c, d FROM t2 ORDER BY 
c", {
 -- 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
 -- 2|0|0|SEARCH TABLE T1 USING COVERING INDEX i3 (b=?)
 --
-test:do_eqp_test(5.9, [[
+test:do_eqp_test("5.9", [[
   SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
 ]], {
-    {0, 0, 0, "SCAN TABLE T2"},
+    {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
     {0, 0, 0, "EXECUTE SCALAR SUBQUERY 1"},
     -- It is equally for tarantol wheather to use i1 or i2
     -- because both of them are covering
     --{1, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I2 (A=?)"},
-    {1, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?)"},
+    {1, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I1 (A=?) (~10 rows)"},
     {0, 0, 0, "EXECUTE CORRELATED SCALAR SUBQUERY 2"},
-    {2, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I3 (B=?)"},
+    {2, 0, 0, "SEARCH TABLE T1 USING COVERING INDEX I3 (B=?) (~10 rows)"},
 })
 -- EVIDENCE-OF: R-50892-45943 sql> EXPLAIN QUERY PLAN
 -- SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
@@ -644,11 +644,11 @@ test:do_eqp_test(5.9, [[
 -- 0|0|0|SCAN SUBQUERY 1
 -- 0|0|0|USE TEMP B-TREE FOR GROUP BY
 --
-test:do_eqp_test(5.10, [[
+test:do_eqp_test("5.10", [[
   SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
 ]], {
-    {1, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1"},
-    {0, 0, 0, "SCAN SUBQUERY 1"},
+    {1, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1 (~1048576 rows)"},
+    {0, 0, 0, "SCAN SUBQUERY 1 (~1 row)"},
     {0, 0, 0, "USE TEMP B-TREE FOR GROUP BY"},
 })
 -- EVIDENCE-OF: R-46219-33846 sql> EXPLAIN QUERY PLAN
@@ -656,9 +656,9 @@ test:do_eqp_test(5.10, [[
 -- 0|0|0|SEARCH TABLE T2 USING COVERING INDEX i4 (c=?)
 -- 0|1|1|SCAN TABLE T1
 --
-test:do_eqp_test(5.11, "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1", {
-    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX I4 (C=?)"},
-    {0, 1, 1, "SCAN TABLE T1"},
+test:do_eqp_test("5.11", "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1", {
+    {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX I4 (C=?) (~10 rows)"},
+    {0, 1, 1, "SCAN TABLE T1 (~1048576 rows)"},
 })
 -- EVIDENCE-OF: R-37879-39987 sql> EXPLAIN QUERY PLAN
 -- SELECT a FROM t1 UNION SELECT c FROM t2;
@@ -666,9 +666,9 @@ test:do_eqp_test(5.11, "SELECT a, b FROM (SELECT * FROM t2 
WHERE c=1), t1", {
 -- 2|0|0|SCAN TABLE T2
 -- 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
 --
-test:do_eqp_test(5.12, "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2", {
-    {1, 0, 0, "SCAN TABLE T1"},
-    {2, 0, 0, "SCAN TABLE T2"},
+test:do_eqp_test("5.12", "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2", {
+    {1, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
+    {2, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
     {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)"},
 })
 -- EVIDENCE-OF: R-44864-63011 sql> EXPLAIN QUERY PLAN
@@ -677,9 +677,9 @@ test:do_eqp_test(5.12, "SELECT a,b FROM t1 UNION SELECT c, 
99 FROM t2", {
 -- 2|0|0|SCAN TABLE T2 2|0|0|USE TEMP B-TREE FOR ORDER BY
 -- 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
 --
-test:do_eqp_test(5.13, "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1", {
-    {1, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1"},
-    {2, 0, 0, "SCAN TABLE T2"},
+test:do_eqp_test("5.13", "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 
1", {
+    {1, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1 (~1048576 rows)"},
+    {2, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
     {2, 0, 0, "USE TEMP B-TREE FOR ORDER BY"},
     {0, 0, 0, "COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)"},
 })
@@ -725,24 +725,24 @@ test:do_eqp_test(5.13, "SELECT a FROM t1 EXCEPT SELECT d 
FROM t2 ORDER BY 1", {
 --
 test:drop_all_tables()
 test:do_execsql_test(
-    7.0,
+    "7.0",
     [[
         CREATE TABLE t1(idt1  INT primary key, a INT, b INT, ex VARCHAR(100));
         CREATE TABLE t2(idt2  INT primary key, a INT, b INT, ex VARCHAR(100));
         CREATE INDEX i1 ON t2(a);
     ]])
 
-test:do_eqp_test(7.1, "SELECT count(*) FROM t1", {
+test:do_eqp_test("7.1", "SELECT count(*) FROM t1", {
     {0, 0, 0, "B+tree count T1"},
 })
-test:do_eqp_test(7.2, "SELECT count(*) FROM t2", {
+test:do_eqp_test("7.2", "SELECT count(*) FROM t2", {
     {0, 0, 0, "B+tree count T2"},
 })
 -- MUST_WORK_TEST
 if (0 > 0)
  then
     test:do_execsql_test(
-        7.3,
+        "7.3",
         [[
            INSERT INTO t1(a,b) VALUES(1, 2);
            INSERT INTO t1(a,b) VALUES(3, 4);
@@ -756,10 +756,10 @@ if (0 > 0)
 
     --db("close")
     --sql("db", "test.db")
-    test:do_eqp_test(7.4, "SELECT count(*) FROM t1", {
+    test:do_eqp_test("7.4", "SELECT count(*) FROM t1", {
        {0, 0, 0, "SCAN TABLE T1"}
    })
-    test:do_eqp_test(7.5, "SELECT count(*) FROM t2", {
+    test:do_eqp_test("7.5", "SELECT count(*) FROM t2", {
        {0, 0, 0, "SCAN TABLE T2 USING COVERING INDEX I1"}
    })
     ---------------------------------------------------------------------------
@@ -768,14 +768,14 @@ if (0 > 0)
 end
 test:drop_all_tables()
 test:do_execsql_test(
-    8.0,
+    "8.0",
     [[
         CREATE TABLE t1(a INT , b INT , c INT , PRIMARY KEY(b, c));
         CREATE TABLE t2(id  INT primary key, a INT , b INT , c INT );
     ]])
 
 test:do_eqp_test("8.1.1", "SELECT * FROM t2", {
-    {0, 0, 0, "SCAN TABLE T2"},
+    {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"},
 })
 -- test:do_eqp_test 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
 --     {0, 0, 0, "SEARCH TABLE T2 USING INTEGER PRIMARY KEY (rowid=?)"},
@@ -784,13 +784,13 @@ test:do_eqp_test("8.1.3", "SELECT count(*) FROM t2", {
     {0, 0, 0, "B+tree count T2"},
 })
 test:do_eqp_test("8.2.1", "SELECT * FROM t1", {
-    {0, 0, 0, "SCAN TABLE T1"},
+    {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"},
 })
 test:do_eqp_test("8.2.2", "SELECT * FROM t1 WHERE b=?", {
-    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (B=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (B=?) (~10 rows)"},
 })
 test:do_eqp_test("8.2.3", "SELECT * FROM t1 WHERE b=? AND c=?", {
-    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (B=? AND C=?)"},
+    {0, 0, 0, "SEARCH TABLE T1 USING PRIMARY KEY (B=? AND C=?) (~1 row)"},
 })
 test:do_eqp_test("8.2.4", "SELECT count(*) FROM t1", {
     {0, 0, 0, "B+tree count T1"},
diff --git a/test/sql-tap/gh-2996-indexed-by.test.lua 
b/test/sql-tap/gh-2996-indexed-by.test.lua
index 1039ac15c..4c5a4d053 100755
--- a/test/sql-tap/gh-2996-indexed-by.test.lua
+++ b/test/sql-tap/gh-2996-indexed-by.test.lua
@@ -37,7 +37,7 @@ test:do_eqp_test(
     "indexed-by-1.1",
     "SELECT b FROM t1 WHERE b <= 5", {
         -- <indexed-by-1.1>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B<?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B<?) (~262144 
rows)' }
         -- <indexed-by-1.1>
     })
 
@@ -45,7 +45,7 @@ test:do_eqp_test(
     "indexed-by-1.2",
     "SELECT b FROM t1 INDEXED BY t1ix1 WHERE b <= 5", {
         -- <indexed-by-1.2>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B<?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B<?) (~262144 
rows)' }
         -- <indexed-by-1.2>
     })
 
@@ -82,7 +82,7 @@ test:do_eqp_test(
     "indexed-by-1.5",
     "DELETE FROM t1 WHERE b <= 5", {
         -- <indexed-by-1.5>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B<?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B<?) (~262144 
rows)' }
         -- <indexed-by-1.5>
     })
 
@@ -90,7 +90,7 @@ test:do_eqp_test(
     "indexed-by-1.6",
     "DELETE FROM t1 INDEXED BY t1ix1  WHERE b <= 5", {
         -- <indexed-by-1.6>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B<?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B<?) (~262144 
rows)' }
         -- <indexed-by-1.6>
     })
 
@@ -124,7 +124,7 @@ test:do_eqp_test(
     "indexed-by-1.9",
     "UPDATE t1 SET b = 20 WHERE b = 10", {
         -- <indexed-by-1.9>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B=?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX2 (B=?) (~10 
rows)' }
         -- <indexed-by-1.9>
     })
 
@@ -132,7 +132,7 @@ test:do_eqp_test(
     "indexed-by-1.10",
     "UPDATE t1 INDEXED BY t1ix1 SET b = 20 WHERE b = 10", {
         -- <indexed-by-1.10>
-        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B=?)' }
+        { 0, 0, 0, 'SEARCH TABLE T1 USING COVERING INDEX T1IX1 (B=?) (~10 
rows)' }
         -- <indexed-by-1.10>
     })
 
diff --git a/test/sql-tap/index6.test.lua b/test/sql-tap/index6.test.lua
index 416b800e1..15ae49245 100755
--- a/test/sql-tap/index6.test.lua
+++ b/test/sql-tap/index6.test.lua
@@ -334,8 +334,8 @@ test:do_eqp_test(
         SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
     ]], {
         -- <index6-8.1>
-    {0, 0, 0, "SCAN TABLE T8A"},
-    {0, 1, 1, "SEARCH TABLE T8B USING COVERING INDEX I8C (Y=?)"}
+    {0, 0, 0, "SCAN TABLE T8A (~1048576 rows)"},
+    {0, 1, 1, "SEARCH TABLE T8B USING COVERING INDEX I8C (Y=?) (~9 rows)"}
         -- </index6-8.1>
     })
 
diff --git a/test/sql-tap/index7.test.lua b/test/sql-tap/index7.test.lua
index 22072ec93..ed2b17c74 100755
--- a/test/sql-tap/index7.test.lua
+++ b/test/sql-tap/index7.test.lua
@@ -279,7 +279,7 @@ test:do_eqp_test(
         SELECT * FROM v4 WHERE d='xyz' AND c='def'
     ]], {
         -- <index7-6.4>
-    {0, 0, 0, "SEARCH TABLE T4 USING COVERING INDEX I4 (C=?)"}
+    {0, 0, 0, "SEARCH TABLE T4 USING COVERING INDEX I4 (C=?) (~9 rows)"}
         -- </index7-6.4>
     })
 
diff --git a/test/sql-tap/lua-tables.test.lua b/test/sql-tap/lua-tables.test.lua
index 7ba1d7ac5..07e0f6a1e 100755
--- a/test/sql-tap/lua-tables.test.lua
+++ b/test/sql-tap/lua-tables.test.lua
@@ -149,7 +149,7 @@ test:do_eqp_test(
     [[
         SELECT * FROM test WHERE id = 2;
     ]], {
-        {0, 0, 0, 'SEARCH TABLE TEST USING PRIMARY KEY (ID=?)'}
+        {0, 0, 0, 'SEARCH TABLE TEST USING PRIMARY KEY (ID=?) (~1 row)'}
     })
 
 test:do_eqp_test(
@@ -157,7 +157,7 @@ test:do_eqp_test(
     [[
         SELECT * FROM test WHERE a = 5;
     ]], {
-        {0, 0, 0, 'SEARCH TABLE TEST USING COVERING INDEX secondary (A=?)'}
+        {0, 0, 0, 'SEARCH TABLE TEST USING COVERING INDEX secondary (A=?) (~1 
row)'}
     })
 
 -- Make sure that without format it is impossible to create
diff --git a/test/sql-tap/tkt-385a5b56b9.test.lua 
b/test/sql-tap/tkt-385a5b56b9.test.lua
index ffbb1a941..653d68222 100755
--- a/test/sql-tap/tkt-385a5b56b9.test.lua
+++ b/test/sql-tap/tkt-385a5b56b9.test.lua
@@ -19,7 +19,7 @@ test:plan(9)
 -- ["source",[["testdir"],"\/tester.tcl"]]
 testprefix = "tkt-385a5b56b9"
 test:do_execsql_test(
-    1.0,
+    "1.0",
     [[
         CREATE TABLE t1(id INT primary key, x INT, y INT);
         INSERT INTO t1 VALUES(1, 1, NULL);
@@ -28,7 +28,7 @@ test:do_execsql_test(
     ]])
 
 test:do_execsql_test(
-    1.1,
+    "1.1",
     [[
         SELECT DISTINCT x, y FROM t1 
     ]], {
@@ -38,13 +38,13 @@ test:do_execsql_test(
     })
 
 test:do_execsql_test(
-    1.2,
+    "1.2",
     [[
         CREATE UNIQUE INDEX i1 ON t1(x, y)
     ]])
 
 test:do_execsql_test(
-    1.3,
+    "1.3",
     [[
         SELECT DISTINCT x, y FROM t1 
     ]], {
@@ -55,7 +55,7 @@ test:do_execsql_test(
 
 ---------------------------------------------------------------------------
 test:do_execsql_test(
-    2.0,
+    "2.0",
     [[
         CREATE TABLE t2(x INT primary key, y INT NOT NULL);
         CREATE UNIQUE INDEX t2x ON t2(x);
@@ -63,41 +63,41 @@ test:do_execsql_test(
     ]])
 
 test:do_eqp_test(
-    2.1,
+    "2.1",
     " SELECT DISTINCT x FROM t2 ", {
         -- <2.1>
-        {0, 0, 0, "SCAN TABLE T2"}
+        {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"}
         -- </2.1>
     })
 
 test:do_eqp_test(
-    2.2,
+    "2.2",
     " SELECT DISTINCT y FROM t2 ", {
         -- <2.2>
         -- changed after reordering indexes
         -- actually it does not matter, because each y val is
         -- distinct even in pk
         --{0, 0, 0, "SCAN TABLE t2 USING COVERING INDEX t2y"}
-        {0, 0, 0, "SCAN TABLE T2"}
+        {0, 0, 0, "SCAN TABLE T2 (~1048576 rows)"}
         -- </2.2>
     })
 
 test:do_eqp_test(
-    2.3,
+    "2.3",
     " SELECT DISTINCT x, y FROM t2 WHERE y=10 ", {
         -- <2.3>
-        {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2Y (Y=?)"}
+        {0, 0, 0, "SEARCH TABLE T2 USING COVERING INDEX T2Y (Y=?) (~1 row)"}
         -- </2.3>
     })
 
 test:do_eqp_test(
-    2.4,
+    "2.4",
     " SELECT DISTINCT x, y FROM t2 WHERE x=10 ", {
         -- <2.4>
         -- changed after reordering indexes + add pk to x affected
         -- actually it does not matter
         --{0, 0, 0, "SEARCH TABLE t2 USING INDEX t2x (x=?)"}
-        {0, 0, 0, "SEARCH TABLE T2 USING PRIMARY KEY (X=?)"}
+        {0, 0, 0, "SEARCH TABLE T2 USING PRIMARY KEY (X=?) (~1 row)"}
         -- </2.4>
     })
 
diff --git a/test/sql-tap/tkt-b75a9ca6b0.test.lua 
b/test/sql-tap/tkt-b75a9ca6b0.test.lua
index ea684a73d..89817d2af 100755
--- a/test/sql-tap/tkt-b75a9ca6b0.test.lua
+++ b/test/sql-tap/tkt-b75a9ca6b0.test.lua
@@ -39,8 +39,8 @@ test:do_execsql_test(
         CREATE INDEX i1 ON t1(x, y);
     ]])
 
-local idxscan = {0, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1"}
-local tblscan = {0, 0, 0, "SCAN TABLE T1"}
+local idxscan = {0, 0, 0, "SCAN TABLE T1 USING COVERING INDEX I1 (~1048576 
rows)"}
+local tblscan = {0, 0, 0, "SCAN TABLE T1 (~1048576 rows)"}
 local grpsort = {0, 0, 0, "USE TEMP B-TREE FOR GROUP BY"}
 local sort = {0, 0, 0, "USE TEMP B-TREE FOR ORDER BY"}
 local eqps = {
diff --git a/test/sql-tap/tkt3442.test.lua b/test/sql-tap/tkt3442.test.lua
index bdfdf8e17..5b26122ef 100755
--- a/test/sql-tap/tkt3442.test.lua
+++ b/test/sql-tap/tkt3442.test.lua
@@ -55,7 +55,7 @@ test:do_test(
         return EQP(" SELECT node FROM listhash WHERE id='5000' LIMIT 1; ")
     end, {
         -- <tkt3442-1.2>
-        0, 0, 0, "SEARCH TABLE LISTHASH USING COVERING INDEX IDIDX (ID=?)"
+        0, 0, 0, "SEARCH TABLE LISTHASH USING COVERING INDEX IDIDX (ID=?) (~1 
row)"
         -- </tkt3442-1.2>
     })
 
@@ -65,7 +65,7 @@ test:do_test(
         return EQP([[ SELECT node FROM listhash WHERE id=5000 LIMIT 1; ]])
     end, {
         -- <tkt3442-1.3>
-        0, 0, 0, "SCAN TABLE LISTHASH"
+        0, 0, 0, "SCAN TABLE LISTHASH (~262144 rows)"
         -- </tkt3442-1.3>
     })
 
diff --git a/test/sql-tap/where3.test.lua b/test/sql-tap/where3.test.lua
index 86329d096..ae9e37f61 100755
--- a/test/sql-tap/where3.test.lua
+++ b/test/sql-tap/where3.test.lua
@@ -407,7 +407,7 @@ if 0
             SELECT * FROM t400, t401, t402 WHERE t402.z LIKE 'abc%';
         ]], {
             -- <where3-4.0>
-            0, 0, 2, "SCAN TABLE T402", 0, 1, 0, "SCAN TABLE T400", 0, 2, 1, 
"SCAN TABLE T401"
+            0, 0, 2, "SCAN TABLE T402 (~983040 rows)", 0, 1, 0, "SCAN TABLE 
T400 (~1048576 rows)", 0, 2, 1, "SCAN TABLE T401 (~1048576 rows)"
             -- </where3-4.0>
         })
 
@@ -418,7 +418,7 @@ if 0
             SELECT * FROM t400, t401, t402 WHERE t401.r LIKE 'abc%';
         ]], {
             -- <where3-4.1>
-            0, 0, 1, "SCAN TABLE T401", 0, 1, 0, "SCAN TABLE T400", 0, 2, 2, 
"SCAN TABLE T402"
+            0, 0, 1, "SCAN TABLE T401 (~983040 rows)", 0, 1, 0, "SCAN TABLE 
T400 (~1048576 rows)", 0, 2, 2, "SCAN TABLE T402 (~1048576 rows)"
             -- </where3-4.1>
         })
 
@@ -429,7 +429,7 @@ if 0
             SELECT * FROM t400, t401, t402 WHERE t400.c LIKE 'abc%';
         ]], {
             -- <where3-4.2>
-            0, 0, 0, "SCAN TABLE T400", 0, 1, 1, "SCAN TABLE T401", 0, 2, 2, 
"SCAN TABLE T402"
+            0, 0, 0, "SCAN TABLE T400 (~983040 rows)", 0, 1, 1, "SCAN TABLE 
T401 (~1048576 rows)", 0, 2, 2, "SCAN TABLE T402 (~1048576 rows)"
             -- </where3-4.2>
         })
 
diff --git a/test/sql-tap/whereG.test.lua b/test/sql-tap/whereG.test.lua
index e9a39c5ce..177d9d14e 100755
--- a/test/sql-tap/whereG.test.lua
+++ b/test/sql-tap/whereG.test.lua
@@ -278,7 +278,7 @@ test:do_execsql_test(
 --
 -- reset_db
 test:do_execsql_test(
-    5.1,
+    "5.1",
     [[
         DROP TABLE IF EXISTS t1;
         CREATE TABLE t1(a INT , b INT , c INT , PRIMARY KEY (a,b));
@@ -323,7 +323,7 @@ test:do_execsql_test(
 --
 
 test:do_execsql_test(
-    6.0,
+    "6.0",
     [[
         DROP TABLE IF EXISTS t1;
         CREATE TABLE t1(i int PRIMARY KEY, x INT , y INT , z INT );
@@ -343,7 +343,7 @@ test:do_execsql_test(
 -- Crash discovered by AFL
 -- MUST_WORK_TEST
 test:do_execsql_test(
-    7.0,
+    "7.0",
     [[
         DROP TABLE IF EXISTS t1;
         CREATE TABLE t1(a INT , b INT , PRIMARY KEY(a,b));
@@ -359,7 +359,7 @@ test:do_execsql_test(
     })
 
 test:do_execsql_test(
-    7.1,
+    "7.1",
     [[
         SELECT unlikely(a), x FROM t1, t2 ORDER BY 1, 2;
     ]], {
@@ -369,7 +369,7 @@ test:do_execsql_test(
     })
 
 test:do_execsql_test(
-    7.2,
+    "7.2",
     [[
         SELECT likelihood(a,0.5), x FROM t1, t2 ORDER BY 1, 2;
     ]], {
@@ -379,7 +379,7 @@ test:do_execsql_test(
     })
 
 test:do_execsql_test(
-    7.3,
+    "7.3",
     [[
         SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2;
     ]], {
@@ -444,7 +444,7 @@ test:do_execsql_test(
     [[
         EXPLAIN QUERY PLAN SELECT name FROM people WHERE height>=180;
     ]],
-    {0,0,0,"SCAN TABLE PEOPLE"})
+    {0,0,0,"SCAN TABLE PEOPLE (~983040 rows)"})
 
 test:do_execsql_test(
     "7.3",
@@ -454,7 +454,7 @@ test:do_execsql_test(
     ]],
     -- {0,0,0,"SEARCH TABLE PEOPLE USING COVERING INDEX PEOPLE_IDX1" ..
     --     " (ANY(ROLE) AND HEIGHT>?)"}
-    {0,0,0,"SCAN TABLE PEOPLE" }
+    {0,0,0,"SCAN TABLE PEOPLE (~983040 rows)" }
     )
 
 test:finish_test()
diff --git a/test/sql/row-count.result b/test/sql/row-count.result
index da9b70e79..e7841caa1 100644
--- a/test/sql/row-count.result
+++ b/test/sql/row-count.result
@@ -303,7 +303,7 @@ box.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES 
('b'), ('c'), ('d');")
   - name: detail
     type: TEXT
   rows:
-  - [0, 0, 0, 'SCAN TABLE T2']
+  - [0, 0, 0, 'SCAN TABLE T2 (~262144 rows)']
 ...
 box.execute("SELECT ROW_COUNT();")
 ---
-- 
2.17.1


Other related posts:

  • » [tarantool-patches] [PATCH v2 6/9] sql: cleanup code from obsolete macros - Stanislav Zudin