15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 2007 May 10
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The author disclaims copyright to this source code.  In place of
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# a legal notice, here is a blessing:
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    May you do good and not evil.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    May you find forgiveness for yourself and forgive others.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    May you share freely, never taking more than you give.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#***********************************************************************
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $Id: fuzz_common.tcl,v 1.2 2009/01/05 19:36:30 drh Exp $
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc fuzz {TemplateList} {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set n [llength $TemplateList]
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set i [expr {int(rand()*$n)}]
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set r [uplevel 1 subst -novar [list [lindex $TemplateList $i]]]
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string map {"\n" " "} $r
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Fuzzy generation primitives:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     Literal
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     UnaryOp
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     BinaryOp
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     Expr
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     Table
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     Select
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     Insert
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns a string representing an SQL literal.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Literal {} {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    456 0 -456 1 -1
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    2147483648 2147483647 2147483649 -2147483647 -2147483648 -2147483649
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'The' 'first' 'experiments' 'in' 'hardware' 'fault' 'injection'
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zeroblob(1000)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    56.1 -56.1
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    123456789.1234567899
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns a string containing an SQL unary operator (e.g. "+" or "NOT").
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc UnaryOp {} {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {+ - NOT ~}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns a string containing an SQL binary operator (e.g. "*" or "/").
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc BinaryOp {} {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    || * / % + - << >> & | < <= > >= = == != <> AND OR
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LIKE GLOB {NOT LIKE}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return the complete text of an SQL expression.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set ::ExprDepth 0
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Expr { {c {}} } {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incr ::ExprDepth
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList [concat $c $c $c {[Literal]}]
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if {$::ExprDepth < 3} {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lappend TemplateList \
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Expr $c] [BinaryOp] [Expr $c]}                              \
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[UnaryOp] [Expr $c]}                                         \
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Expr $c] ISNULL}                                            \
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Expr $c] NOTNULL}                                           \
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {CAST([Expr $c] AS blob)}                                     \
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {CAST([Expr $c] AS text)}                                     \
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {CAST([Expr $c] AS integer)}                                  \
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {CAST([Expr $c] AS real)}                                     \
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {abs([Expr])}                                                 \
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {coalesce([Expr], [Expr])}                                    \
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {hex([Expr])}                                                 \
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {length([Expr])}                                              \
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {lower([Expr])}                                               \
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {upper([Expr])}                                               \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {quote([Expr])}                                               \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {random()}                                                    \
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {randomblob(min(max([Expr],1), 500))}                         \
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {typeof([Expr])}                                              \
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {substr([Expr],[Expr],[Expr])}                                \
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {CASE WHEN [Expr $c] THEN [Expr $c] ELSE [Expr $c] END}       \
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Literal]} {[Literal]} {[Literal]}                           \
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Literal]} {[Literal]} {[Literal]}                           \
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Literal]} {[Literal]} {[Literal]}                           \
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Literal]} {[Literal]} {[Literal]}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if {$::SelectDepth < 4} {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lappend TemplateList \
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {([Select 1])}                       \
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Expr $c] IN ([Select 1])}          \
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[Expr $c] NOT IN ([Select 1])}      \
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {EXISTS ([Select 1])}                \
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set res [fuzz $TemplateList]
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incr ::ExprDepth -1
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return $res
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return a valid table name.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set ::TableList [list]
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Table {} {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList [concat sqlite_master $::TableList]
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return one of:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     "SELECT DISTINCT", "SELECT ALL" or "SELECT"
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc SelectKw {} {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT DISTINCT"
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT ALL"
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT"
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return a result set for a SELECT statement.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc ResultSet {{nRes 0} {c ""}} {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if {$nRes == 0} {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set nRes [expr {rand()*2 + 1}]
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set aRes [list]
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for {set ii 0} {$ii < $nRes} {incr ii} {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lappend aRes [Expr $c]
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  join $aRes ", "
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set ::SelectDepth 0
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set ::ColumnList [list]
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc SimpleSelect {{nRes 0}} {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {[SelectKw] [ResultSet $nRes]}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # The ::SelectDepth variable contains the number of ancestor SELECT
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # statements (i.e. for a top level SELECT it is set to 0, for a
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # sub-select 1, for a sub-select of a sub-select 2 etc.).
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # If this is already greater than 3, do not generate a complicated
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # SELECT statement. This tends to cause parser stack overflow (too
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # boring to bother with).
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if {$::SelectDepth < 4} {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lappend TemplateList \
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SelectKw] [ResultSet $nRes $::ColumnList] FROM ([Select])}     \
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SelectKw] [ResultSet $nRes] FROM ([Select])}                   \
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SelectKw] [ResultSet $nRes $::ColumnList] FROM [Table]}        \
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             [SelectKw] [ResultSet $nRes $::ColumnList]
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             FROM ([Select])
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             GROUP BY [Expr]
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             HAVING [Expr]
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }                                                                \
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if {0 == $nRes} {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lappend TemplateList                                               \
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {[SelectKw] * FROM ([Select])}                                 \
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {[SelectKw] * FROM [Table]}                                    \
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {[SelectKw] * FROM [Table] WHERE [Expr $::ColumnList]}         \
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             [SelectKw] *
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             FROM [Table],[Table] AS t2
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             WHERE [Expr $::ColumnList]
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             [SelectKw] *
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             FROM [Table] LEFT OUTER JOIN [Table] AS t2
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ON [Expr $::ColumnList]
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             WHERE [Expr $::ColumnList]
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return a SELECT statement.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If boolean parameter $isExpr is set to true, make sure the
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# returned SELECT statement returns a single column of data.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Select {{nMulti 0}} {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]} {[SimpleSelect $nMulti]}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti] ORDER BY [Expr] DESC}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti] ORDER BY [Expr] ASC}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti] ORDER BY [Expr] ASC, [Expr] DESC}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[SimpleSelect $nMulti] ORDER BY [Expr] LIMIT [Expr] OFFSET [Expr]}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if {$::SelectDepth < 4} {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if {$nMulti == 0} {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set nMulti [expr {(rand()*2)+1}]
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lappend TemplateList                                             \
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SimpleSelect $nMulti] UNION     [Select $nMulti]}          \
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SimpleSelect $nMulti] UNION ALL [Select $nMulti]}          \
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SimpleSelect $nMulti] EXCEPT    [Select $nMulti]}          \
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {[SimpleSelect $nMulti] INTERSECT [Select $nMulti]}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incr ::SelectDepth
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set res [fuzz $TemplateList]
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incr ::SelectDepth -1
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set res
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Generate and return a fuzzy INSERT statement.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Insert {} {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {INSERT INTO [Table] VALUES([Expr], [Expr], [Expr]);}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {INSERT INTO [Table] VALUES([Expr], [Expr], [Expr], [Expr]);}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {INSERT INTO [Table] VALUES([Expr], [Expr]);}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Column {} {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $::ColumnList
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Generate and return a fuzzy UPDATE statement.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Update {} {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {UPDATE [Table]
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     SET [Column] = [Expr $::ColumnList]
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     WHERE [Expr $::ColumnList]}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Delete {} {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {DELETE FROM [Table] WHERE [Expr $::ColumnList]}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Statement {} {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[Update]}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[Insert]}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[Select]}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[Delete]}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Return an identifier. This just chooses randomly from a fixed set
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# of strings.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Identifier {} {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This just chooses randomly a fixed
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    We would also thank the developers
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for their analysis Samba
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Check {} {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Use a large value for $::SelectDepth, because sub-selects are
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # not allowed in expressions used by CHECK constraints.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set sd $::SelectDepth
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set ::SelectDepth 500
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {CHECK ([Expr])}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set res [fuzz $TemplateList]
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set ::SelectDepth $sd
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set res
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc Coltype {} {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {INTEGER PRIMARY KEY}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {VARCHAR [Check]}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {PRIMARY KEY}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc DropTable {} {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {DROP TABLE IF EXISTS [Identifier]}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc CreateView {} {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {CREATE VIEW [Identifier] AS [Select]}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc DropView {} {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {DROP VIEW IF EXISTS [Identifier]}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc CreateTable {} {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {CREATE TABLE [Identifier]([Identifier] [Coltype], [Identifier] [Coltype])}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {CREATE TEMP TABLE [Identifier]([Identifier] [Coltype])}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc CreateOrDropTableOrView {} {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set TemplateList {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[CreateTable]}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[DropTable]}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[CreateView]}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {[DropView]}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fuzz $TemplateList
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)########################################################################
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set ::log [open fuzzy.log w]
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Usage: do_fuzzy_test <testname> ?<options>?
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     -template
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     -errorlist
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     -repeats
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)proc do_fuzzy_test {testname args} {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set ::fuzzyopts(-errorlist) [list]
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set ::fuzzyopts(-repeats) $::REPEATS
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  array set ::fuzzyopts $args
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lappend ::fuzzyopts(-errorlist) {parser stack overflow}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lappend ::fuzzyopts(-errorlist) {ORDER BY}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lappend ::fuzzyopts(-errorlist) {GROUP BY}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lappend ::fuzzyopts(-errorlist) {datatype mismatch}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for {set ii 0} {$ii < $::fuzzyopts(-repeats)} {incr ii} {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do_test ${testname}.$ii {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set ::sql [subst $::fuzzyopts(-template)]
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      puts $::log $::sql
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flush $::log
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set rc [catch {execsql $::sql} msg]
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set e 1
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if {$rc} {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set e 0
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        foreach error $::fuzzyopts(-errorlist) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if {[string first $error $msg]>=0} {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            set e 1
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if {$e == 0} {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        puts ""
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        puts $::sql
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        puts $msg
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set e
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } {1}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
392