summaryrefslogtreecommitdiffstats
path: root/test/orderbyA.test
blob: 4400f4e05ff67b310a08fb23fe26f8d9255290e1 (plain)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# 2019-09-21
#
# 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.
#
# Specifically, it tests cases where the expressions in a GROUP BY 
# clause are the same as those in the ORDER BY clause.
# 

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

proc do_sortcount_test {tn sql cnt res} {
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  set rcnt [regexp -all {USE TEMP} $eqp]
  uplevel [list do_test         $tn.1 [list set {} $rcnt] $cnt]
  uplevel [list do_execsql_test $tn.2 $sql $res]
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('one',   1, 11);
  INSERT INTO t1 VALUES('three', 7, 11);
  INSERT INTO t1 VALUES('one',   2, 11);
  INSERT INTO t1 VALUES('one',   3, 11);
  INSERT INTO t1 VALUES('two',   4, 11);
  INSERT INTO t1 VALUES('two',   6, 11);
  INSERT INTO t1 VALUES('three', 8, 11);
  INSERT INTO t1 VALUES('two',   5, 11);
  INSERT INTO t1 VALUES('three', 9, 11);
}

foreach {tn idx} {
  1 {}
  2 {CREATE INDEX i1 ON t1(a)}
  3 {CREATE INDEX i1 ON t1(a DESC)}
} {
  execsql { DROP INDEX IF EXISTS i1 }
  execsql $idx

  # $match is the number of temp-table sorts we expect if the GROUP BY
  # can use the same sort order as the ORDER BY. $nomatch is the number
  # of expected sorts if the GROUP BY and ORDER BY are not compatible.
  set match   1
  set nomatch 2
  if {$tn>=2} {
    set match   0
    set nomatch 1
  }

  do_sortcount_test 1.$tn.1.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a
  } $match {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.1.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC
  } $match {two 15 three 24 one 6}
  
  do_sortcount_test 1.$tn.2.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||''
  } $nomatch {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.2.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||'' DESC
  } $nomatch {two 15 three 24 one 6}
  
  do_sortcount_test 1.$tn.3.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a NULLS LAST
  } $nomatch {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.3.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC NULLS FIRST
  } $nomatch {two 15 three 24 one 6}
}

#-------------------------------------------------------------------------
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c);
  INSERT INTO t2 VALUES(1, 'one', 1);
  INSERT INTO t2 VALUES(1, 'two', 2);
  INSERT INTO t2 VALUES(1, 'one', 3);
  INSERT INTO t2 VALUES(1, 'two', 4);
  INSERT INTO t2 VALUES(1, 'one', 5);
  INSERT INTO t2 VALUES(1, 'two', 6);

  INSERT INTO t2 VALUES(2, 'one', 7);
  INSERT INTO t2 VALUES(2, 'two', 8);
  INSERT INTO t2 VALUES(2, 'one', 9);
  INSERT INTO t2 VALUES(2, 'two', 10);
  INSERT INTO t2 VALUES(2, 'one', 11);
  INSERT INTO t2 VALUES(2, 'two', 12);

  INSERT INTO t2 VALUES(NULL, 'one', 13);
  INSERT INTO t2 VALUES(NULL, 'two', 14);
  INSERT INTO t2 VALUES(NULL, 'one', 15);
  INSERT INTO t2 VALUES(NULL, 'two', 16);
  INSERT INTO t2 VALUES(NULL, 'one', 17);
  INSERT INTO t2 VALUES(NULL, 'two', 18);
}

foreach {tn idx} {
  1 {}

  2 { CREATE INDEX i2 ON t2(a, b)           }
  3 { CREATE INDEX i2 ON t2(a DESC, b DESC) }

  4 { CREATE INDEX i2 ON t2(a, b DESC)      }
  5 { CREATE INDEX i2 ON t2(a DESC, b)      }
} {
  execsql { DROP INDEX IF EXISTS i2 }
  execsql $idx


  set nSort [expr ($tn==2 || $tn==3) ? 0 : 1]
  do_sortcount_test 2.$tn.1.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b;
  } $nSort {{} one 45  {} two 48  1 one 9  1 two 12  2 one 27  2 two 30}
  do_sortcount_test 2.$tn.1.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b DESC;
  } $nSort {2 two 30  2 one 27  1 two 12  1 one 9  {} two 48  {} one 45}

  set nSort [expr ($tn==4 || $tn==5) ? 0 : 1]
  do_sortcount_test 2.$tn.2.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC;
  } $nSort { {} two 48  {} one 45  1 two 12  1 one 9  2 two 30 2 one 27 }
  do_sortcount_test 2.$tn.2.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b;
  } $nSort { 2 one 27  2 two 30  1 one 9  1 two 12  {} one 45 {} two 48 }

  # ORDER BY can never piggyback on the GROUP BY sort if it uses 
  # non-standard NULLS behaviour.
  set nSort [expr $tn==1 ? 2 : 1]
  do_sortcount_test 2.$tn.3.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC NULLS FIRST;
  } $nSort { {} two 48  {} one 45  1 two 12  1 one 9  2 two 30 2 one 27 }
  do_sortcount_test 2.$tn.3.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b NULLS LAST;
  } $nSort { 2 one 27  2 two 30  1 one 9  1 two 12  {} one 45 {} two 48 }
}


finish_test