/ Check-in [bc078e00]
Login

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

Overview
Comment:Add the reverse_unordered_selects pragma. (CVS 6314)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:bc078e0007b6c3dc07722820bb53798b643212b3
User & Date: drh 2009-02-23 16:52:08
Context
2009-02-23
17:33
Scan an index instead of a table for "SELECT count(*) FROM <tbl>" queries. Because an index is usually smaller than a table on disk, this saves some IO. (CVS 6315) check-in: 294ba6f7 user: danielk1977 tags: trunk
16:52
Add the reverse_unordered_selects pragma. (CVS 6314) check-in: bc078e00 user: drh tags: trunk
14:42
Ensure the return value of sqlite3_errmsg16() is aligned on a 2-byte boundary. Ticket #3665. (CVS 6313) check-in: 9b8acf83 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
168
169
170
171
172
173
174

175
176
177
178
179
180
181
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.203 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"

/* Ignore this whole file if pragmas are disabled
*/
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)

................................................................................
  } aPragma[] = {
    { "full_column_names",        SQLITE_FullColNames  },
    { "short_column_names",       SQLITE_ShortColNames },
    { "count_changes",            SQLITE_CountRows     },
    { "empty_result_callbacks",   SQLITE_NullCallback  },
    { "legacy_file_format",       SQLITE_LegacyFileFmt },
    { "fullfsync",                SQLITE_FullFSync     },

#ifdef SQLITE_DEBUG
    { "sql_trace",                SQLITE_SqlTrace      },
    { "vdbe_listing",             SQLITE_VdbeListing   },
    { "vdbe_trace",               SQLITE_VdbeTrace     },
#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },







|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.204 2009/02/23 16:52:08 drh Exp $
*/
#include "sqliteInt.h"

/* Ignore this whole file if pragmas are disabled
*/
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)

................................................................................
  } aPragma[] = {
    { "full_column_names",        SQLITE_FullColNames  },
    { "short_column_names",       SQLITE_ShortColNames },
    { "count_changes",            SQLITE_CountRows     },
    { "empty_result_callbacks",   SQLITE_NullCallback  },
    { "legacy_file_format",       SQLITE_LegacyFileFmt },
    { "fullfsync",                SQLITE_FullFSync     },
    { "reverse_unordered_selects", SQLITE_ReverseOrder  },
#ifdef SQLITE_DEBUG
    { "sql_trace",                SQLITE_SqlTrace      },
    { "vdbe_listing",             SQLITE_VdbeListing   },
    { "vdbe_trace",               SQLITE_VdbeTrace     },
#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
843
844
845
846
847
848
849

850
851
852
853
854
855
856
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.834 2009/02/19 14:39:25 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
#define SQLITE_FullFSync      0x00010000  /* Use full fsync on the backend */
#define SQLITE_LoadExtension  0x00020000  /* Enable load_extension */

#define SQLITE_RecoveryMode   0x00040000  /* Ignore schema errors */
#define SQLITE_SharedCache    0x00080000  /* Cache sharing is enabled */
#define SQLITE_Vtab           0x00100000  /* There exists a virtual table */
#define SQLITE_CommitBusy     0x00200000  /* In the process of committing */


/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/
#define SQLITE_MAGIC_OPEN     0xa029a697  /* Database is open */







|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.835 2009/02/23 16:52:08 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
#define SQLITE_FullFSync      0x00010000  /* Use full fsync on the backend */
#define SQLITE_LoadExtension  0x00020000  /* Enable load_extension */

#define SQLITE_RecoveryMode   0x00040000  /* Ignore schema errors */
#define SQLITE_SharedCache    0x00080000  /* Cache sharing is enabled */
#define SQLITE_Vtab           0x00100000  /* There exists a virtual table */
#define SQLITE_CommitBusy     0x00200000  /* In the process of committing */
#define SQLITE_ReverseOrder   0x00400000  /* Reverse unordered SELECTs */

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/
#define SQLITE_MAGIC_OPEN     0xa029a697  /* Database is open */

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1833
1834
1835
1836
1837
1838
1839






1840


1841
1842
1843
1844
1845
1846
1847
....
1983
1984
1985
1986
1987
1988
1989






1990
1991
1992
1993
1994
1995
1996
....
2743
2744
2745
2746
2747
2748
2749



2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.370 2009/02/20 10:58:42 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
................................................................................
        if( rev ){
          wsFlags |= WHERE_REVERSE;
        }
      }else{
        cost += cost*estLog(cost);
        WHERETRACE(("... sorting increases cost to %.9g\n", cost));
      }






    }


    if( cost<pCost->rCost ){
      pCost->rCost = cost;
      pCost->nRow = nRow;
      pCost->plan.wsFlags = wsFlags;
    }
  }

................................................................................
        if( rev ){
          wsFlags |= WHERE_REVERSE;
        }
      }else{
        cost += cost*estLog(cost);
        WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
      }






    }

    /* Check to see if we can get away with using just the index without
    ** ever reading the table.  If that is the case, then halve the
    ** cost of this index.
    */
    if( wsFlags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
................................................................................
  }else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */

  {
    /* Case 5:  There is no usable index.  We must do a complete
    **          scan of the entire table.
    */



    assert( omitTable==0 );
    assert( bRev==0 );
    pLevel->op = OP_Next;
    pLevel->p1 = iCur;
    pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addrBrk);
    pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
    codeRowSetEarly = 0;
  }
  notReady &= ~getMask(pWC->pMaskSet, iCur);

  /* Insert code to test every subexpression that can be completely
  ** computed using the current set of tables.







|







 







>
>
>
>
>
>

>
>







 







>
>
>
>
>
>







 







>
>
>

<
|

|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
....
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
....
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767

2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.371 2009/02/23 16:52:08 drh Exp $
*/
#include "sqliteInt.h"

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
................................................................................
        if( rev ){
          wsFlags |= WHERE_REVERSE;
        }
      }else{
        cost += cost*estLog(cost);
        WHERETRACE(("... sorting increases cost to %.9g\n", cost));
      }
    }else if( pParse->db->flags & SQLITE_ReverseOrder ){
      /* For application testing, randomly reverse the output order for
      ** SELECT statements that omit the ORDER BY clause.  This will help
      ** to find cases where
      */
      wsFlags |= WHERE_REVERSE;
    }

    /* Remember this case if it is the best so far */
    if( cost<pCost->rCost ){
      pCost->rCost = cost;
      pCost->nRow = nRow;
      pCost->plan.wsFlags = wsFlags;
    }
  }

................................................................................
        if( rev ){
          wsFlags |= WHERE_REVERSE;
        }
      }else{
        cost += cost*estLog(cost);
        WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
      }
    }else if( pParse->db->flags & SQLITE_ReverseOrder ){
      /* For application testing, randomly reverse the output order for
      ** SELECT statements that omit the ORDER BY clause.  This will help
      ** to find cases where
      */
      wsFlags |= WHERE_REVERSE;
    }

    /* Check to see if we can get away with using just the index without
    ** ever reading the table.  If that is the case, then halve the
    ** cost of this index.
    */
    if( wsFlags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
................................................................................
  }else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */

  {
    /* Case 5:  There is no usable index.  We must do a complete
    **          scan of the entire table.
    */
    static const u8 aStep[] = { OP_Next, OP_Prev };
    static const u8 aStart[] = { OP_Rewind, OP_Last };
    assert( bRev==0 || bRev==1 );
    assert( omitTable==0 );

    pLevel->op = aStep[bRev];
    pLevel->p1 = iCur;
    pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
    pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
    codeRowSetEarly = 0;
  }
  notReady &= ~getMask(pWC->pMaskSet, iCur);

  /* Insert code to test every subexpression that can be completely
  ** computed using the current set of tables.

Added test/whereA.test.



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 2009 February 23
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the reverse_select_order pragma.
#
# $Id: whereA.test,v 1.1 2009/02/23 16:52:08 drh Exp $

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

do_test whereA-1.1 {
  db eval {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 values(2,'hello','world');
    INSERT INTO t1 VALUES(3,4.53,NULL);
    SELECT * FROM t1
  }
} {1 2 3 2 hello world 3 4.53 {}}
do_test whereA-1.2 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1;
  }
} {3 4.53 {} 2 hello world 1 2 3}

do_test whereA-1.3 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1 ORDER BY rowid;
  }
} {1 2 3 2 hello world 3 4.53 {}}

do_test whereA-2.1 {
  db eval {
    PRAGMA reverse_unordered_selects=0;
    SELECT * FROM t1 WHERE a>0;
  }
} {1 2 3 2 hello world 3 4.53 {}}
do_test whereA-2.2 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1 WHERE a>0;
  }
} {3 4.53 {} 2 hello world 1 2 3}

do_test whereA-2.3 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1 WHERE a>0 ORDER BY rowid;
  }
} {1 2 3 2 hello world 3 4.53 {}}

do_test whereA-3.1 {
  db eval {
    PRAGMA reverse_unordered_selects=0;
    SELECT * FROM t1 WHERE b>0;
  }
} {1 2 3 3 4.53 {} 2 hello world}
do_test whereA-3.2 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1 WHERE b>0;
  }
} {2 hello world 3 4.53 {} 1 2 3}
do_test whereA-3.3 {
  db eval {
    PRAGMA reverse_unordered_selects=1;
    SELECT * FROM t1 WHERE b>0 ORDER BY b;
  }
} {1 2 3 3 4.53 {} 2 hello world}

finish_test