SQLite

Check-in [6c0f44bd63]
Login

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

Overview
Comment:Fix a bug in the left outer join logic. (CVS 758)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6c0f44bd6374010f7a4a091e585eb36e0665f96f
User & Date: drh 2002-09-30 12:36:26.000
Context
2002-10-12
13:44
Remove the call to srand() and add better comments to the sqliteOsRandomSeed() routine. Ticket #163. (CVS 759) (check-in: d87a886d8f user: drh tags: trunk)
2002-09-30
12:36
Fix a bug in the left outer join logic. (CVS 758) (check-in: 6c0f44bd63 user: drh tags: trunk)
01:31
Fix an uninitialized variable that could cause problems when comparing two NULLs. (CVS 757) (check-in: 0154250018 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/where.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.64 2002/08/28 03:01:01 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.65 2002/09/30 12:36:26 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
421
422
423
424
425
426
427

428
429
430
431
432
433
434

    /* Check to see if there is an expression that uses only the
    ** ROWID field of this table.  For terms of the form ROWID==expr
    ** set iDirectEq[i] to the index of the term.  For terms of the
    ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
    ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i].
    */

    iDirectEq[i] = -1;
    iDirectLt[i] = -1;
    iDirectGt[i] = -1;
    for(j=0; j<nExpr; j++){
      if( aExpr[j].idxLeft==idx && aExpr[j].p->pLeft->iColumn<0
            && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
        switch( aExpr[j].p->op ){







>







421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

    /* Check to see if there is an expression that uses only the
    ** ROWID field of this table.  For terms of the form ROWID==expr
    ** set iDirectEq[i] to the index of the term.  For terms of the
    ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
    ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i].
    */
    pWInfo->a[i].iCur = -1;
    iDirectEq[i] = -1;
    iDirectLt[i] = -1;
    iDirectGt[i] = -1;
    for(j=0; j<nExpr; j++){
      if( aExpr[j].idxLeft==idx && aExpr[j].p->pLeft->iColumn<0
            && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
        switch( aExpr[j].p->op ){
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
    }
    pWInfo->a[i].pIdx = pBestIdx;
    pWInfo->a[i].score = bestScore;
    loopMask |= 1<<idx;
    if( pBestIdx ){
      pWInfo->a[i].iCur = pParse->nTab++;
      pWInfo->peakNTab = pParse->nTab;
    }else{
      pWInfo->a[i].iCur = -1;
    }
  }

  /* Check to see if the ORDER BY clause is or can be satisfied by the
  ** use of an index on the first table.
  */
  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){







<
<







574
575
576
577
578
579
580


581
582
583
584
585
586
587
    }
    pWInfo->a[i].pIdx = pBestIdx;
    pWInfo->a[i].score = bestScore;
    loopMask |= 1<<idx;
    if( pBestIdx ){
      pWInfo->a[i].iCur = pParse->nTab++;
      pWInfo->peakNTab = pParse->nTab;


    }
  }

  /* Check to see if the ORDER BY clause is or can be satisfied by the
  ** use of an index on the first table.
  */
  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
Changes to test/join.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins.
#
# $Id: join.test,v 1.5 2002/07/31 19:50:28 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c);







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins.
#
# $Id: join.test,v 1.6 2002/09/30 12:36:26 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
279
280
281
282
283
284
285














286


287
} {}
do_test join-4.10 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}


















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
} {}
do_test join-4.10 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}

do_test join-5.1 {
  execsql {
    BEGIN;
    create table centros (id integer primary key, centro);
    INSERT INTO centros VALUES(1,'xxx');
    create table usuarios (id integer primary key, nombre, apellidos,
    idcentro integer);
    INSERT INTO usuarios VALUES(1,'a','aa',1);
    INSERT INTO usuarios VALUES(2,'b','bb',1);
    INSERT INTO usuarios VALUES(3,'c','cc',NULL);
    create index idcentro on usuarios (idcentro);
    END;
    select usuarios.id, usuarios.nombre, centros.centro from
    usuarios left outer join centros on usuarios.idcentro = centros.id;
  }
} {1 a xxx 2 b xxx 3 c {}}

finish_test