SQLite

Check-in [307478593d]
Login

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

Overview
Comment:Progress toward fixing iproblems with compound selects. (CVS 1911)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 307478593d5d96b79386da222c7742ea2eaa5467
User & Date: drh 2004-08-29 01:31:05.000
Context
2004-08-29
16:25
Corrections to transient table handling in compound select statments. Tickets #826 and #875. (CVS 1912) (check-in: 9cc765be46 user: drh tags: trunk)
01:31
Progress toward fixing iproblems with compound selects. (CVS 1911) (check-in: 307478593d user: drh tags: trunk)
2004-08-28
18:21
Add prototype in sqlite3.h for the sqlite3_libversion() function. (CVS 1910) (check-in: d50c47b499 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.203 2004/08/21 17:54:45 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.204 2004/08/29 01:31:05 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
1275
1276
1277
1278
1279
1280
1281














1282

1283

1284
1285
1286

1287
1288
1289

1290
1291
1292
1293
1294
1295








1296
1297
1298
1299


1300
1301
1302
1303
1304
1305
1306
1307
1308
      (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  if( keyAsData ){
    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
  }
  return addr;
}















static int multiSelectOpenTempAddr(Select *p, int addr, IdList **ppOpenTemp){

  if( !p->ppOpenTemp ){

    *ppOpenTemp = sqlite3IdListAppend(0, 0);
    p->ppOpenTemp = ppOpenTemp;
  }else{

    *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0);
  }
  if( !(*p->ppOpenTemp) ){

    return SQLITE_NOMEM;
  }
  (*p->ppOpenTemp)->a[(*p->ppOpenTemp)->nId-1].idx = addr;
  return SQLITE_OK;
}









static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
  CollSeq *pRet = 0;
  if( p->pPrior ){
    pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);


  }
  if( !pRet ){
    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
  }
  return pRet;
}

/*
** This routine is called to process a query that is really the union







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

>

>



>


|
>


|



>
>
>
>
>
>
>
>

|


>
>

|







1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
      (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  if( keyAsData ){
    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
  }
  return addr;
}

/*
** FIX ME:
**    +  Omit the ppOpenTemp parameter from multiSelectOpenTempAddr().
**    +  Attach pOpenList to the right-most term always.
**    +  Make sure Select.ppOpenTemp is initialized to NULL
*/

/*
** Add the address "addr" to the set of all opcode addresses contained
** in the pOpenTemp list for the whole compound select.  If no pOpenTemp
** list has been created yet, then create a new one and make *ppOpenTemp
** point to it.  If the pOpenTemp list already exists, leave *ppOpenTemp
** unchanged and just add the new address to the existing list.
*/
static int multiSelectOpenTempAddr(Select *p, int addr, IdList **ppOpenTemp){
  IdList *pList;
  if( !p->ppOpenTemp ){
    /* Create a new list */
    *ppOpenTemp = sqlite3IdListAppend(0, 0);
    p->ppOpenTemp = ppOpenTemp;
  }else{
    /* Add a new element onto the end of the existing list */
    *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0);
  }
  pList = *p->ppOpenTemp;
  if( pList==0 ){
    return SQLITE_NOMEM;
  }
  pList->a[pList->nId-1].idx = addr;
  return SQLITE_OK;
}

/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p".  Return NULL if
** the column has no default collating sequence.
**
** The collating sequence for the compound select is taken from the
** left-most term of the select that has a collating sequence.
*/
static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
  CollSeq *pRet;
  if( p->pPrior ){
    pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);
  }else{
    pRet = 0;
  }
  if( pRet==0 ){
    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
  }
  return pRet;
}

/*
** This routine is called to process a query that is really the union
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
** So if this routine is called with p equal to the t3 query, then
** pPrior will be the t2 query.  p->op will be TK_UNION in this case.
**
** Notice that because of the way SQLite parses compound SELECTs, the
** individual selects always group from left to right.
*/
static int multiSelect(
  Parse *pParse, 
  Select *p, 
  int eDest, 
  int iParm, 
  char *aff           /* If eDest is SRT_Union, the affinity string */
){
  int rc = SQLITE_OK;  /* Success code from a subroutine */
  Select *pPrior;     /* Another SELECT immediately to our left */
  Vdbe *v;            /* Generate code to this VDBE */
  IdList *pOpenTemp = 0;

  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last SELECT in the series may have an ORDER BY or LIMIT.
  */
  if( p==0 || p->pPrior==0 ){
    rc = 1;
    goto multi_select_end;
  }
  pPrior = p->pPrior;
  if( pPrior->pOrderBy ){







|
|
|
|
|

|
|
|
|


|







1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
** So if this routine is called with p equal to the t3 query, then
** pPrior will be the t2 query.  p->op will be TK_UNION in this case.
**
** Notice that because of the way SQLite parses compound SELECTs, the
** individual selects always group from left to right.
*/
static int multiSelect(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  int eDest,            /* \___  Store query results as specified */
  int iParm,            /* /     by these two parameters.         */
  char *aff             /* If eDest is SRT_Union, the affinity string */
){
  int rc = SQLITE_OK;   /* Success code from a subroutine */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Vdbe *v;              /* Generate code to this VDBE */
  IdList *pOpenTemp = 0;/* OP_OpenTemp opcodes that need a KeyInfo */

  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  */
  if( p==0 || p->pPrior==0 ){
    rc = 1;
    goto multi_select_end;
  }
  pPrior = p->pPrior;
  if( pPrior->pOrderBy ){
1371
1372
1373
1374
1375
1376
1377







1378
1379
1380
1381
1382








1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ){
    rc = 1;
    goto multi_select_end;
  }








  /* Create the destination temporary table if necessary
  */
  if( eDest==SRT_TempTable ){
    assert( p->pEList );
    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0);








    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, p->pEList->nExpr);
    eDest = SRT_Table;
  }

  /* Generate code for the left and right SELECT statements.
  */
  switch( p->op ){
    case TK_ALL: {
      if( p->pOrderBy==0 ){
        pPrior->nLimit = p->nLimit;
        pPrior->nOffset = p->nOffset;
        pPrior->ppOpenTemp = p->ppOpenTemp;
        rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
        if( rc ){
          goto multi_select_end;
        }
        p->pPrior = 0;
        p->iLimit = pPrior->iLimit;
        p->iOffset = pPrior->iOffset;







>
>
>
>
>
>
>





>
>
>
>
>
>
>
>











|







1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ){
    rc = 1;
    goto multi_select_end;
  }

  /* PART OF FIX:
  */
  if( p->ppOpenTemp==0 ){
    p->ppOpenTemp = &pOpenTemp;
  }
  pPrior->ppOpenTemp = p->ppOpenTemp;

  /* Create the destination temporary table if necessary
  */
  if( eDest==SRT_TempTable ){
    assert( p->pEList );
    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0);

    /* FIX ME:
    ** p->pEList->nExpr might contain a "*" and so might not be the 
    ** correct number.  Go ahead and code the SetNumColumns instruction
    ** here, but also record its address.   Change the P2 value of the
    ** instruction to the number of columns after sqlite3Select() has
    ** been called to code the subquery and has modified pEList->nExpr
    ** to be the correct value. */
    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, p->pEList->nExpr);
    eDest = SRT_Table;
  }

  /* Generate code for the left and right SELECT statements.
  */
  switch( p->op ){
    case TK_ALL: {
      if( p->pOrderBy==0 ){
        pPrior->nLimit = p->nLimit;
        pPrior->nOffset = p->nOffset;
        /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */
        rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
        if( rc ){
          goto multi_select_end;
        }
        p->pPrior = 0;
        p->iLimit = pPrior->iLimit;
        p->iOffset = pPrior->iOffset;
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
          sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1);
        }
        assert( p->pEList );
      }

      /* Code the SELECT statements to our left
      */
      pPrior->ppOpenTemp = p->ppOpenTemp;
      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }
      if( p->op==TK_ALL ){
        sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, pPrior->pEList->nExpr);
      }







|







1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
          sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1);
        }
        assert( p->pEList );
      }

      /* Code the SELECT statements to our left
      */
      /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */
      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }
      if( p->op==TK_ALL ){
        sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, pPrior->pEList->nExpr);
      }
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
        goto multi_select_end;
      }
      sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1);
      assert( p->pEList );

      /* Code the SELECTs to our left into temporary table "tab1".
      */
      pPrior->ppOpenTemp = p->ppOpenTemp;
      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT into temporary table "tab2"
      */







|







1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
        goto multi_select_end;
      }
      sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1);
      assert( p->pEList );

      /* Code the SELECTs to our left into temporary table "tab1".
      */
      /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */
      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT into temporary table "tab2"
      */
1595
1596
1597
1598
1599
1600
1601





1602
1603
1604


1605
1606
1607
1608
1609
1610
1611
1612
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
    sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
      " do not have the same number of result columns", selectOpName(p->op));
    rc = 1;
    goto multi_select_end;
  }






  if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){
    int nCol = p->pEList->nExpr;
    int i;


    KeyInfo *pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*));
    if( !pKeyInfo ){
      rc = SQLITE_NOMEM;
      goto multi_select_end;
    }

    pKeyInfo->enc = pParse->db->enc;
    pKeyInfo->nField = nCol;







>
>
>
>
>

|
|
>
>
|







1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
    sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
      " do not have the same number of result columns", selectOpName(p->op));
    rc = 1;
    goto multi_select_end;
  }

  /* Compute collating sequences used by either the ORDER BY clause or
  ** by any temporary tables needed to implement the compound select.
  ** Attach the KeyInfo structure to all temporary tables.  Invoke the
  ** ORDER BY processing if there is an ORDER BY clause.
  */
  if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){
    int nCol = p->pEList->nExpr;  /* Number of columns in the result set */
    int i;                        /* Loop counter */
    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */

    pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*));
    if( !pKeyInfo ){
      rc = SQLITE_NOMEM;
      goto multi_select_end;
    }

    pKeyInfo->enc = pParse->db->enc;
    pKeyInfo->nField = nCol;
1621
1622
1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
    for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){
      int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO);
      int addr = pOpenTemp->a[i].idx;
      sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type);
    }

    if( p->pOrderBy ){

      for(i=0; i<p->pOrderBy->nExpr; i++){
        Expr *pExpr = p->pOrderBy->a[i].pExpr;
        char *zName = p->pOrderBy->a[i].zName;
        assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
        assert( !pExpr->pColl );
        if( zName ){
          pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1);
        }else{
          pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn];
        }







>
|
|
|







1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
    for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){
      int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO);
      int addr = pOpenTemp->a[i].idx;
      sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type);
    }

    if( p->pOrderBy ){
      struct ExprList_item *pOrderByTerm = p->pOrderBy->a;
      for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){
        Expr *pExpr = pOrderByTerm->pExpr;
        char *zName = pOrderByTerm->zName;
        assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
        assert( !pExpr->pColl );
        if( zName ){
          pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1);
        }else{
          pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn];
        }
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
  /* Identify column names if we will be using them in a callback.  This
  ** step is skipped if the output is going to some other destination.
  */
  if( eDest==SRT_Callback ){
    generateColumnNames(pParse, pTabList, pEList);
  }

#if 1  /* I do not think we need the following code any more.... */
  /* If the destination is SRT_Union, then set the number of columns in
  ** the records that will be inserted into the temporary table. The caller
  ** couldn't do this, in case the select statement is of the form 
  ** "SELECT * FROM ....". 
  **
  ** We need to do this before we start inserting records into the 
  ** temporary table (which has had OP_KeyAsData executed on it), because
  ** it is required by the key comparison function. So do it now, even
  ** though this means that OP_SetNumColumns may be executed on the same
  ** cursor more than once.
  */
  if( eDest==SRT_Union ){
    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr);
  }
#endif

  /* Generate code for all sub-queries in the FROM clause
  */
  for(i=0; i<pTabList->nSrc; i++){
    const char *zSavedAuthContext = 0;
    int needRestoreContext;








<














<







2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
  /* Identify column names if we will be using them in a callback.  This
  ** step is skipped if the output is going to some other destination.
  */
  if( eDest==SRT_Callback ){
    generateColumnNames(pParse, pTabList, pEList);
  }


  /* If the destination is SRT_Union, then set the number of columns in
  ** the records that will be inserted into the temporary table. The caller
  ** couldn't do this, in case the select statement is of the form 
  ** "SELECT * FROM ....". 
  **
  ** We need to do this before we start inserting records into the 
  ** temporary table (which has had OP_KeyAsData executed on it), because
  ** it is required by the key comparison function. So do it now, even
  ** though this means that OP_SetNumColumns may be executed on the same
  ** cursor more than once.
  */
  if( eDest==SRT_Union ){
    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr);
  }


  /* Generate code for all sub-queries in the FROM clause
  */
  for(i=0; i<pTabList->nSrc; i++){
    const char *zSavedAuthContext = 0;
    int needRestoreContext;