000001  # 2008 October 27
000002  #
000003  # The author disclaims copyright to this source code.  In place of
000004  # a legal notice, here is a blessing:
000005  #
000006  #    May you do good and not evil.
000007  #    May you find forgiveness for yourself and forgive others.
000008  #    May you share freely, never taking more than you give.
000009  #
000010  #***********************************************************************
000011  #
000012  # Test that the truncate optimization is disabled if the SQLITE_DELETE
000013  # authorization callback returns SQLITE_IGNORE.
000014  #
000015  # Test that authorizer is disabled during schema parsing.
000016  
000017  set testdir [file dirname $argv0]
000018  source $testdir/tester.tcl
000019  
000020  # disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
000021  # defined during compilation.
000022  if {[catch {db auth {}} msg]} {
000023    finish_test
000024    return
000025  }
000026  
000027  # Disable the statement cache for these tests.
000028  # 
000029  db cache size 0
000030  
000031  db authorizer ::auth
000032  proc auth {code arg1 arg2 arg3 arg4 args} {
000033    if {$code=="SQLITE_DELETE"} {
000034      return $::authcode
000035    }
000036    return SQLITE_OK
000037  }
000038  
000039  #--------------------------------------------------------------------------
000040  # The following tests - auth3-1.* - test that return values of SQLITE_DENY,
000041  # SQLITE_IGNORE, SQLITE_OK and <invalid> are correctly handled when returned
000042  # by an SQLITE_DELETE authorization callback triggered by a 
000043  # "DELETE FROM <table-name>" statement.
000044  #
000045  do_test auth3-1.1 {
000046    execsql {
000047      CREATE TABLE t1(a,b,c);
000048      INSERT INTO t1 VALUES(1, 2, 3);
000049      INSERT INTO t1 VALUES(4, 5, 6);
000050    }
000051  } {}
000052  do_test auth3.1.2 {
000053    set ::authcode SQLITE_DENY
000054    catchsql { DELETE FROM t1 }
000055  } {1 {not authorized}}
000056  # EVIDENCE-OF: R-64962-58611 If the authorizer callback returns any
000057  # value other than SQLITE_IGNORE, SQLITE_OK, or SQLITE_DENY then the
000058  # sqlite3_prepare_v2() or equivalent call that triggered the authorizer
000059  # will fail with an error message.
000060  do_test auth3.1.3 {
000061    set ::authcode SQLITE_INVALID
000062    catchsql { DELETE FROM t1 }
000063  } {1 {authorizer malfunction}}
000064  do_test auth3.1.4 {
000065    execsql { SELECT * FROM t1 }
000066  } {1 2 3 4 5 6}
000067  do_test auth3-1.5 {
000068    set ::authcode SQLITE_IGNORE
000069    execsql { 
000070      DELETE FROM t1;
000071      SELECT * FROM t1;
000072    }
000073  } {}
000074  do_test auth3-1.6 {
000075    set ::authcode SQLITE_OK
000076    execsql {
000077      INSERT INTO t1 VALUES(1, 2, 3);
000078      INSERT INTO t1 VALUES(4, 5, 6);
000079      DELETE FROM t1;
000080      SELECT * FROM t1;
000081    }
000082  } {}
000083  
000084  #--------------------------------------------------------------------------
000085  # These tests - auth3-2.* - test that returning SQLITE_IGNORE really does
000086  # disable the truncate optimization.
000087  #
000088  do_test auth3-2.1 {
000089    set ::authcode SQLITE_OK
000090    execsql {
000091      INSERT INTO t1 VALUES(1, 2, 3);
000092      INSERT INTO t1 VALUES(4, 5, 6);
000093    }
000094    set sqlite_search_count 0
000095    execsql {
000096      DELETE FROM t1;
000097    }
000098    set sqlite_search_count
000099  } {0}
000100  
000101  do_test auth3-2.2 {
000102    set ::authcode SQLITE_IGNORE
000103    execsql {
000104      INSERT INTO t1 VALUES(1, 2, 3);
000105      INSERT INTO t1 VALUES(4, 5, 6);
000106    }
000107    set sqlite_search_count 0
000108    execsql {
000109      DELETE FROM t1;
000110    }
000111    set sqlite_search_count
000112  } {1}
000113  
000114  # 2016-07-28.  A problem report from a private client complaining about
000115  # an authorizer failure during an ALTER TABLE.  The solution (I think) is
000116  # to disable the authorizer during schema parsing.
000117  #
000118  ifcapable altertable {
000119    proc auth {code args} {
000120      if {$code=="SQLITE_READ" && [regexp {DoNotRead} $args]} {
000121        return SQLITE_DENY
000122      }
000123      return SQLITE_OK
000124    }
000125    do_execsql_test auth3-3.0 {
000126      CREATE TEMPORARY TABLE TempTable (
000127          key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
000128          value TEXT NOT NULL ON CONFLICT FAIL);
000129      ALTER TABLE TempTable RENAME TO DoNotRead;
000130      SELECT name FROM temp.sqlite_master;
000131    } {DoNotRead sqlite_autoindex_DoNotRead_1}
000132  }
000133  
000134  finish_test