/ Check-in [a25801df]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:{quote: KeyInfo} generation moved to a common subroutine. (CVS 2652)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:a25801df06e218e70570a6b9eae71603d590fe3a
User & Date: drh 2005-08-31 18:20:00
Context
2005-09-01
03:07
Sorting is now done using a sorting index rather than loading the entire result set into memory and doing a merge sort. The old merge sort technique was a carry-over from SQLite version 1. The new method uses a bounded amount of memory and scales to much larger result sets. There are still errors: some 39 regression tests fail. (CVS 2653) check-in: 09db0a24 user: drh tags: trunk
2005-08-31
18:20
{quote: KeyInfo} generation moved to a common subroutine. (CVS 2652) check-in: a25801df user: drh tags: trunk
13:48
Updates to the query optimizer overview document. (CVS 2651) check-in: b1dceef0 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
546
547
548
549
550
551
552




































553
554
555
556
557
558
559
...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
....
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
....
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.256 2005/08/30 00:54:03 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
      break;
    }
#endif
  }
  return 0;
}





































/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.
*/
................................................................................
  int eDest,       /* Write the sorted results here */
  int iParm        /* Optional parameter associated with eDest */
){
  int end1 = sqlite3VdbeMakeLabel(v);
  int end2 = sqlite3VdbeMakeLabel(v);
  int addr;
  KeyInfo *pInfo;
  ExprList *pOrderBy;
  int nCol, i;
  sqlite3 *db = pParse->db;

  if( eDest==SRT_Sorter ) return;
  pOrderBy = p->pOrderBy;
  nCol = pOrderBy->nExpr;
  pInfo = sqliteMalloc( sizeof(*pInfo) + nCol*(sizeof(CollSeq*)+1) );

  if( pInfo==0 ) return;
  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol];
  pInfo->nField = nCol;
  for(i=0; i<nCol; i++){
    /* If a collation sequence was specified explicity, then it
    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default
    ** collation type for the expression.
    */
    pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr);
    if( !pInfo->aColl[i] ){
      pInfo->aColl[i] = db->pDfltColl;
    }
    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder;
  }
  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
  codeLimiter(v, p, addr, end2, 1);
  switch( eDest ){
    case SRT_Table:
    case SRT_TempTable: {
      sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
................................................................................
** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not 
** UNION ALL).
**
** The value returned is the address of the OP_OpenVirtual instruction.
*/
static int openVirtualIndex(Parse *pParse, Select *p, int iTab){
  KeyInfo *pKeyInfo;
  int nColumn;
  sqlite3 *db = pParse->db;
  int i;
  Vdbe *v = pParse->pVdbe;
  int addr;

  if( prepSelectStmt(pParse, p) ){
    return 0;
  }
  nColumn = p->pEList->nExpr;
  pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) );
  if( pKeyInfo==0 ) return 0;
  pKeyInfo->enc = db->enc;
  pKeyInfo->nField = nColumn;
  for(i=0; i<nColumn; i++){
    pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
    if( !pKeyInfo->aColl[i] ){
      pKeyInfo->aColl[i] = db->pDfltColl;
    }
  }
  addr = sqlite3VdbeOp3(v, OP_OpenVirtual, iTab, 0, 
      (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  return addr;
}

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Add the address "addr" to the set of all OpenVirtual opcode addresses
** that are being accumulated in p->ppOpenVirtual.
................................................................................
          nExpr = pAggExpr->pList->nExpr;
        }
#endif
        sqlite3VdbeOp3(v, OP_AggInit, nExpr, i, (char*)pFunc, P3_FUNCDEF);
      }
    }
    if( pGroupBy ){
      int sz = sizeof(KeyInfo) + pGroupBy->nExpr*sizeof(CollSeq*);
      KeyInfo *pKey = (KeyInfo *)sqliteMalloc(sz);
      if( 0==pKey ){
        goto select_end;
      }
      pKey->enc = pParse->db->enc;
      pKey->nField = pGroupBy->nExpr;
      for(i=0; i<pGroupBy->nExpr; i++){
        pKey->aColl[i] = sqlite3ExprCollSeq(pParse, pGroupBy->a[i].pExpr);
        if( !pKey->aColl[i] ){
          pKey->aColl[i] = pParse->db->pDfltColl;
        }
      }
      sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF);
    }
  }

  /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
  */
  if( eDest==SRT_Mem || eDest==SRT_Exists ){
    sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
    sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
  }

  /* Open a temporary table to use for the distinct set.
  */
  if( isDistinct ){
    distinct = pParse->nTab++;
    openVirtualIndex(pParse, p, distinct);
  }else{
    distinct = -1;
  }







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<


<
<
<
>

<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<






|
<

<
<
<
<
<
<
<
<

|







 







|
<



<
<
<
<
<
<
<
<











|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
...
601
602
603
604
605
606
607



608
609



610
611













612
613
614
615
616
617
618
....
1337
1338
1339
1340
1341
1342
1343



1344
1345
1346
1347
1348
1349
1350

1351








1352
1353
1354
1355
1356
1357
1358
1359
1360
....
2698
2699
2700
2701
2702
2703
2704
2705

2706
2707
2708








2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.257 2005/08/31 18:20:00 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
      break;
    }
#endif
  }
  return 0;
}

/*
** Given an expression list, generate a KeyInfo structure that records
** the collating sequence for each expression in that expression list.
**
** Space to hold the KeyInfo structure is obtain from malloc.  The calling
** function is responsible for seeing that this structure is eventually
** freed.  Add the KeyInfo structure to the P3 field of an opcode using
** P3_KEYINFO_HANDOFF is the usual way of dealing with this.
*/
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
  sqlite3 *db = pParse->db;
  int nExpr;
  KeyInfo *pInfo;
  struct ExprList_item *pItem;
  int i;

  nExpr = pList->nExpr;
  pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
  if( pInfo ){
    pInfo->aSortOrder = (char*)&pInfo->aColl[nExpr];
    pInfo->nField = nExpr;
    pInfo->enc = db->enc;
    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
      CollSeq *pColl;
      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      if( !pColl ){
        pColl = db->pDfltColl;
      }
      pInfo->aColl[i] = pColl;
      pInfo->aSortOrder[i] = pItem->sortOrder;
    }
  }
  return pInfo;
}


/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.
*/
................................................................................
  int eDest,       /* Write the sorted results here */
  int iParm        /* Optional parameter associated with eDest */
){
  int end1 = sqlite3VdbeMakeLabel(v);
  int end2 = sqlite3VdbeMakeLabel(v);
  int addr;
  KeyInfo *pInfo;




  if( eDest==SRT_Sorter ) return;



  pInfo = keyInfoFromExprList(pParse, p->pOrderBy);
  if( pInfo==0 ) return;













  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
  codeLimiter(v, p, addr, end2, 1);
  switch( eDest ){
    case SRT_Table:
    case SRT_TempTable: {
      sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
................................................................................
** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not 
** UNION ALL).
**
** The value returned is the address of the OP_OpenVirtual instruction.
*/
static int openVirtualIndex(Parse *pParse, Select *p, int iTab){
  KeyInfo *pKeyInfo;



  Vdbe *v = pParse->pVdbe;
  int addr;

  if( prepSelectStmt(pParse, p) ){
    return 0;
  }
  pKeyInfo = keyInfoFromExprList(pParse, p->pEList);

  if( pKeyInfo==0 ) return 0;








  addr = sqlite3VdbeOp3(v, OP_OpenVirtual, iTab, 0, 
                        (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  return addr;
}

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Add the address "addr" to the set of all OpenVirtual opcode addresses
** that are being accumulated in p->ppOpenVirtual.
................................................................................
          nExpr = pAggExpr->pList->nExpr;
        }
#endif
        sqlite3VdbeOp3(v, OP_AggInit, nExpr, i, (char*)pFunc, P3_FUNCDEF);
      }
    }
    if( pGroupBy ){
      KeyInfo *pKey = keyInfoFromExprList(pParse, pGroupBy);

      if( 0==pKey ){
        goto select_end;
      }








      sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF);
    }
  }

  /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
  */
  if( eDest==SRT_Mem || eDest==SRT_Exists ){
    sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
    sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
  }

  /* Open a virtual index to use for the distinct set.
  */
  if( isDistinct ){
    distinct = pParse->nTab++;
    openVirtualIndex(pParse, p, distinct);
  }else{
    distinct = -1;
  }