SQLite4
Check-in [0263259ac4]
Not logged in

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

Overview
SHA1 Hash:0263259ac41297f532414f889fa97b0aaa7ef60f
Date: 2013-05-08 14:37:24
User: dan
Comment:Add tests for authorizer_push() and authorizer_pop().
Tags And Properties
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233

234
235


236
237
238
239
240
241
242
  parse.h \
  sqlite4.h


# Source code to the test files.
#
TESTSRC = \
  $(TOP)/test/test_main.c \
  $(TOP)/test/test_thread0.c \
  $(TOP)/test/test_utf.c \
  $(TOP)/test/test_misc1.c \
  $(TOP)/test/test_config.c \
  $(TOP)/test/test_func.c \
  $(TOP)/test/test_hexio.c \
  $(TOP)/test/test_lsm.c \
  $(TOP)/test/test_kv.c \
  $(TOP)/test/test_kv2.c \

  $(TOP)/test/test_malloc.c \
  $(TOP)/test/test_mem.c \

  $(TOP)/test/test_mutex.c \
  $(TOP)/test/test_thread.c \


  $(TOP)/test/test_wsd.c

#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c

TESTSRC2 = \
  $(TOP)/src/attach.c \







<
<
|
<



|
|
|
>


>


>
>







215
216
217
218
219
220
221


222

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  parse.h \
  sqlite4.h


# Source code to the test files.
#
TESTSRC = \


  $(TOP)/test/test_auth.c \

  $(TOP)/test/test_config.c \
  $(TOP)/test/test_func.c \
  $(TOP)/test/test_hexio.c \
  $(TOP)/test/test_kv.c \
  $(TOP)/test/test_kv2.c \
  $(TOP)/test/test_lsm.c \
  $(TOP)/test/test_main.c \
  $(TOP)/test/test_malloc.c \
  $(TOP)/test/test_mem.c \
  $(TOP)/test/test_misc1.c \
  $(TOP)/test/test_mutex.c \
  $(TOP)/test/test_thread.c \
  $(TOP)/test/test_thread0.c \
  $(TOP)/test/test_utf.c \
  $(TOP)/test/test_wsd.c

#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c

TESTSRC2 = \
  $(TOP)/src/attach.c \

Changes to src/auth.c

130
131
132
133
134
135
136

137
138
139
140
141
142
143

144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
  const char *z4                  /* Sixth argument for auth callbacks */
){
  int rc = SQLITE4_OK;
  Authorizer *p;
  
  for(p=pParse->db->pAuth; p; p=p->pNext){
    int rcauth = p->xAuth(p->pCtx, eAuth, z1, z2, z3, z4);

    switch( rcauth ){
      case SQLITE4_IGNORE:
        /* fall through */
      case SQLITE4_DENY:
        rc = rcauth;
        /* fall through */
      case SQLITE4_OK:

      case SQLITE4_ALLOW:
        break;

      default:
        authBadReturnCode(pParse);
        rcauth = SQLITE4_DENY;
    }


    if( rcauth!=SQLITE4_OK && rcauth!=SQLITE4_IGNORE ) break;
  }

  assert( rc==SQLITE4_OK || rc==SQLITE4_DENY || rc==SQLITE4_IGNORE );
  return rc;
}

/*







>
|
|
<
|
|
|
<
>
|
|

|
|
|
|
>
|
<







130
131
132
133
134
135
136
137
138
139

140
141
142

143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
  const char *z4                  /* Sixth argument for auth callbacks */
){
  int rc = SQLITE4_OK;
  Authorizer *p;
  
  for(p=pParse->db->pAuth; p; p=p->pNext){
    int rcauth = p->xAuth(p->pCtx, eAuth, z1, z2, z3, z4);
    if( rcauth!=SQLITE4_OK ){
      switch( rcauth ){
        case SQLITE4_IGNORE:

        case SQLITE4_DENY:
          rc = rcauth;
          /* fall through */


        case SQLITE4_ALLOW:
          break;

        default:
          authBadReturnCode(pParse);
          rc = SQLITE4_DENY;
      }
      break;
    }

  }

  assert( rc==SQLITE4_OK || rc==SQLITE4_DENY || rc==SQLITE4_IGNORE );
  return rc;
}

/*

Changes to src/sqlite.h.in

1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
** In this case, instead of reading the required value from a table column, 
** the database engine substitues an SQL NULL value instead. If SQLITE4_IGNORE 
** is returned by an authorization callback requesting anything other than to 
** read a table column, then statement compilation is allowed to continue,
** but the requested action is silently omitted.
**
** If there is more than one authorization callback on the stack when a
** statement is compiled (or recompiled), they are invoked in turn, starting 
** with the callback on the top of the stack. If a single authorization 
** callback returns SQLITE4_DENY, then permission for the action is denied
** and no further authorization callbacks are invoked. If one or more
** authorization callbacks return SQLITE4_IGNORE, but all others return
** SQLITE4_OK or SQLITE4_ALLOW, then the column value is replaced by an
** SQL NULL, as described above. If all authorization callbacks return
** SQLITE_OK or SQLITE_ALLOW, then the specified action is authorized and
** statement compilation proceeds.
**
** The difference between SQLITE4_OK and SQLITE4_ALLOW is as follows - if
** an authorization callback returns SQLITE4_ALLOW, then no further callbacks
** are invoked for the action. The action is either authorized (if all
** prior authorization callbacks returned SQLITE_OK) or ignored (if one or
** more earlier callbacks returned SQLITE4_IGNORE).
**
** An authorizer callback must not do anything that will modify the state
** of the database connection that invoked the authorizer callback. Note that 
** [sqlite4_prepare()] and [sqlite4_step()] both modify the state of their 
** database connections for the meaning of "modify" in this paragraph.
*/
int sqlite4_authorizer_push(







|
|
|
|
|
<
<
<
<



|
<
<







1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256




1257
1258
1259
1260


1261
1262
1263
1264
1265
1266
1267
** In this case, instead of reading the required value from a table column, 
** the database engine substitues an SQL NULL value instead. If SQLITE4_IGNORE 
** is returned by an authorization callback requesting anything other than to 
** read a table column, then statement compilation is allowed to continue,
** but the requested action is silently omitted.
**
** If there is more than one authorization callback on the stack when a
** statement is compiled (or recompiled), then the callback on the top of
** the stack is invoked first. If it returns other than SQLITE4_OK, then no 
** further callbacks are issued and the value returned is interpreted by 
** SQLite4 as described above. Or, if it does return SQLITE4_OK, then the
** next callback on the stack is invoked, and so on.




**
** The difference between SQLITE4_OK and SQLITE4_ALLOW is as follows - if
** an authorization callback returns SQLITE4_ALLOW, then no further callbacks
** are invoked for the action. The action is authorized.


**
** An authorizer callback must not do anything that will modify the state
** of the database connection that invoked the authorizer callback. Note that 
** [sqlite4_prepare()] and [sqlite4_step()] both modify the state of their 
** database connections for the meaning of "modify" in this paragraph.
*/
int sqlite4_authorizer_push(

Changes to src/tclsqlite.c

1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
....
2873
2874
2875
2876
2877
2878
2879


2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899

  /*    $db authorizer ?CALLBACK?
  **
  ** Invoke the given callback to authorize each SQL operation as it is
  ** compiled.  5 arguments are appended to the callback before it is
  ** invoked:
  **
  **   (1) The authorization type (ex: SQLITE4_CREATE_TABLE, SQLITE4_INSERT, ...)
  **   (2) First descriptive name (depends on authorization type)
  **   (3) Second descriptive name
  **   (4) Name of the database (ex: "main", "temp")
  **   (5) Name of trigger that is doing the access
  **
  ** The callback should return on of the following strings: SQLITE4_OK,
  ** SQLITE4_IGNORE, or SQLITE4_DENY.  Any other return value is an error.
................................................................................
    extern int SqliteSuperlock_Init(Tcl_Interp*);
    extern int SqlitetestSyscall_Init(Tcl_Interp*);
    extern int Sqliteteststorage_Init(Tcl_Interp*);
    extern int Sqliteteststorage2_Init(Tcl_Interp*);
    extern int SqlitetestLsm_Init(Tcl_Interp*);
    extern int Sqlitetest_mem_Init(Tcl_Interp*);



    Sqliteconfig_Init(interp);
    Sqlitetest1_Init(interp);
    Sqlitetest4_Init(interp);
    Sqlitetest5_Init(interp);
    Sqlitetest9_Init(interp);
    Sqlitetest_hexio_Init(interp);
    Sqlitetest_malloc_Init(interp);
    Sqlitetest_mutex_Init(interp);
    SqlitetestThread_Init(interp);
    Sqliteteststorage_Init(interp);
    Sqliteteststorage2_Init(interp);
    SqlitetestLsm_Init(interp);
    Sqlitetest_mem_Init(interp);



    Tcl_CreateObjCommand(
        interp, "load_testfixture_extensions", init_all_cmd, 0, 0
    );
    Tcl_CreateObjCommand(
        interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0







|







 







>
>













>







1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
....
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

  /*    $db authorizer ?CALLBACK?
  **
  ** Invoke the given callback to authorize each SQL operation as it is
  ** compiled.  5 arguments are appended to the callback before it is
  ** invoked:
  **
  **   (1) The authorization type (ex: SQLITE4_CREATE_TABLE, SQLITE4_READ, ...)
  **   (2) First descriptive name (depends on authorization type)
  **   (3) Second descriptive name
  **   (4) Name of the database (ex: "main", "temp")
  **   (5) Name of trigger that is doing the access
  **
  ** The callback should return on of the following strings: SQLITE4_OK,
  ** SQLITE4_IGNORE, or SQLITE4_DENY.  Any other return value is an error.
................................................................................
    extern int SqliteSuperlock_Init(Tcl_Interp*);
    extern int SqlitetestSyscall_Init(Tcl_Interp*);
    extern int Sqliteteststorage_Init(Tcl_Interp*);
    extern int Sqliteteststorage2_Init(Tcl_Interp*);
    extern int SqlitetestLsm_Init(Tcl_Interp*);
    extern int Sqlitetest_mem_Init(Tcl_Interp*);

    extern void sqlite4TestInit(Tcl_Interp*);

    Sqliteconfig_Init(interp);
    Sqlitetest1_Init(interp);
    Sqlitetest4_Init(interp);
    Sqlitetest5_Init(interp);
    Sqlitetest9_Init(interp);
    Sqlitetest_hexio_Init(interp);
    Sqlitetest_malloc_Init(interp);
    Sqlitetest_mutex_Init(interp);
    SqlitetestThread_Init(interp);
    Sqliteteststorage_Init(interp);
    Sqliteteststorage2_Init(interp);
    SqlitetestLsm_Init(interp);
    Sqlitetest_mem_Init(interp);
    sqlite4TestInit(interp);


    Tcl_CreateObjCommand(
        interp, "load_testfixture_extensions", init_all_cmd, 0, 0
    );
    Tcl_CreateObjCommand(
        interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0

Changes to test/auth.test

4
5
6
7
8
9
10



11
12
13
14
15
16
17
# 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 script is testing the sqlite4_set_authorizer() API
# and related functionality.
#
# $Id: auth.test,v 1.46 2009/07/02 18:40:35 danielk1977 Exp $
#








>
>
>







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 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 is a legacy SQLite3 test file. New authorization callback related
# tests should be added to auth4.test and later.
#
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the sqlite4_set_authorizer() API
# and related functionality.
#
# $Id: auth.test,v 1.46 2009/07/02 18:40:35 danielk1977 Exp $
#

Changes to test/auth2.test

4
5
6
7
8
9
10



11
12
13
14
15
16
17
# 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 script is testing the sqlite4_set_authorizer() API
# and related functionality.
#
# $Id: auth2.test,v 1.3 2008/07/02 13:13:53 danielk1977 Exp $
#








>
>
>







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 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 is a legacy SQLite3 test file. New authorization callback related
# tests should be added to auth4.test and later.
#
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the sqlite4_set_authorizer() API
# and related functionality.
#
# $Id: auth2.test,v 1.3 2008/07/02 13:13:53 danielk1977 Exp $
#

Changes to test/auth3.test

4
5
6
7
8
9
10


11
12
13
14
15
16
17
# 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.
#
#***********************************************************************


#
# Test that the truncate optimization is disabled if the SQLITE4_DELETE
# authorization callback returns SQLITE4_IGNORE.
#
# $Id: auth3.test,v 1.2 2009/05/04 01:58:31 drh Exp $
#








>
>







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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 is a legacy SQLite3 test file. New authorization callback related
# tests should be added to auth4.test and later.
#
# Test that the truncate optimization is disabled if the SQLITE4_DELETE
# authorization callback returns SQLITE4_IGNORE.
#
# $Id: auth3.test,v 1.2 2009/05/04 01:58:31 drh Exp $
#

Changes to test/permutations.test

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test

  auth.test auth2.test auth3.test
  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test
  bind.test







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test

  auth.test auth2.test auth3.test auth4.test
  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test
  bind.test

Added test/testInt.h



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
** 2013 May 8
**
** 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.
**
*/

#ifndef __TEST_INT_H
#define __TEST_INT_H

#include <tcl.h>


/* test_auth.c */
int Sqlitetest_auth_init(Tcl_Interp *interp);

/* test_main.c */
void sqlite4TestInit(Tcl_Interp*);
void *sqlite4TestTextToPtr(const char *z);
int sqlite4TestDbHandle(Tcl_Interp *, Tcl_Obj *, sqlite4 **);
int sqlite4TestSetResult(Tcl_Interp *interp, int rc);

#endif

Added test/test_auth.c



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
** 2013 May 8
**
** 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.
**
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>

#include "sqlite4.h"
#include "testInt.h"

typedef struct TestAuth TestAuth;
struct TestAuth {
  Tcl_Interp *interp;
  Tcl_Obj *pScript;
  sqlite4 *db;
};

static const char *sqlite4TestAuthCode(int rcauth){
  switch( rcauth ){
    case SQLITE4_CREATE_INDEX: return "SQLITE4_CREATE_INDEX";
    case SQLITE4_CREATE_TABLE: return "SQLITE4_CREATE_TABLE";
    case SQLITE4_CREATE_TEMP_INDEX: return "SQLITE4_CREATE_TEMP_INDEX";
    case SQLITE4_CREATE_TEMP_TABLE: return "SQLITE4_CREATE_TEMP_TABLE";
    case SQLITE4_CREATE_TEMP_TRIGGER: return "SQLITE4_CREATE_TEMP_TRIGGER";
    case SQLITE4_CREATE_TEMP_VIEW: return "SQLITE4_CREATE_TEMP_VIEW";
    case SQLITE4_CREATE_TRIGGER: return "SQLITE4_CREATE_TRIGGER";
    case SQLITE4_CREATE_VIEW: return "SQLITE4_CREATE_VIEW";
    case SQLITE4_DELETE: return "SQLITE4_DELETE";
    case SQLITE4_DROP_INDEX: return "SQLITE4_DROP_INDEX";
    case SQLITE4_DROP_TABLE: return "SQLITE4_DROP_TABLE";
    case SQLITE4_DROP_TEMP_INDEX: return "SQLITE4_DROP_TEMP_INDEX";
    case SQLITE4_DROP_TEMP_TABLE: return "SQLITE4_DROP_TEMP_TABLE";
    case SQLITE4_DROP_TEMP_TRIGGER: return "SQLITE4_DROP_TEMP_TRIGGER";
    case SQLITE4_DROP_TEMP_VIEW: return "SQLITE4_DROP_TEMP_VIEW";
    case SQLITE4_DROP_TRIGGER: return "SQLITE4_DROP_TRIGGER";
    case SQLITE4_DROP_VIEW: return "SQLITE4_DROP_VIEW";
    case SQLITE4_INSERT: return "SQLITE4_INSERT";
    case SQLITE4_PRAGMA: return "SQLITE4_PRAGMA";
    case SQLITE4_READ: return "SQLITE4_READ";
    case SQLITE4_SELECT: return "SQLITE4_SELECT";
    case SQLITE4_TRANSACTION: return "SQLITE4_TRANSACTION";
    case SQLITE4_UPDATE: return "SQLITE4_UPDATE";
    case SQLITE4_ATTACH: return "SQLITE4_ATTACH";
    case SQLITE4_DETACH: return "SQLITE4_DETACH";
    case SQLITE4_ALTER_TABLE: return "SQLITE4_ALTER_TABLE";
    case SQLITE4_REINDEX: return "SQLITE4_REINDEX";
    case SQLITE4_ANALYZE: return "SQLITE4_ANALYZE";
    case SQLITE4_CREATE_VTABLE: return "SQLITE4_CREATE_VTABLE";
    case SQLITE4_DROP_VTABLE: return "SQLITE4_DROP_VTABLE";
    case SQLITE4_FUNCTION: return "SQLITE4_FUNCTION";
    case SQLITE4_SAVEPOINT: return "SQLITE4_SAVEPOINT";
  }
  return "unknown";
}

static void testauth_xDel(void *pCtx){
  TestAuth *p = (TestAuth *)pCtx;
  Tcl_DecrRefCount(p->pScript);
  sqlite4_free(sqlite4_db_env(p->db), p);
}

static int testauth_xAuth(
  void *pCtx,
  int code,
  const char *z1,
  const char *z2,
  const char *z3,
  const char *z4
){
  TestAuth *p = (TestAuth *)pCtx;
  Tcl_Interp *interp = p->interp;
  Tcl_Obj *pEval;
  Tcl_Obj *pCode;
  int rc;

  pEval = Tcl_DuplicateObj(p->pScript);
  Tcl_IncrRefCount(pEval);

  pCode = Tcl_NewStringObj(sqlite4TestAuthCode(code), -1);
  if( TCL_OK!=Tcl_ListObjAppendElement(interp, pEval, pCode)
   || TCL_OK!=Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(z1, -1))
   || TCL_OK!=Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(z2, -1))
   || TCL_OK!=Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(z3, -1))
   || TCL_OK!=Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(z4, -1))
  ){
    rc = -1;
  }else{
    if( TCL_OK!=Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL) ){
      rc = -2;
    }else{
      const char *zRes = Tcl_GetStringResult(p->interp);
      rc = -3;
      if( strcmp(zRes, "SQLITE4_OK")==0 ) rc = SQLITE4_OK;
      if( strcmp(zRes, "SQLITE4_ALLOW")==0 ) rc = SQLITE4_ALLOW;
      if( strcmp(zRes, "SQLITE4_IGNORE")==0 ) rc = SQLITE4_IGNORE;
      if( strcmp(zRes, "SQLITE4_DENY")==0 ) rc = SQLITE4_DENY;
    }
  }

  Tcl_DecrRefCount(pEval);
  return rc;
}

/*
** sqlite4_authorizer_push DB SCRIPT
*/
static int testauth_push(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  TestAuth *pNew;
  sqlite4 *db;
  int rc;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
    return TCL_ERROR;
  }
  rc = sqlite4TestDbHandle(interp, objv[1], &db);
  if( rc!=TCL_OK ) return rc;

  pNew = (TestAuth *)sqlite4_malloc(sqlite4_db_env(db), sizeof(TestAuth));
  if( !pNew ) return sqlite4TestSetResult(interp, SQLITE4_NOMEM);

  pNew->interp = interp;
  pNew->db = db;
  pNew->pScript = Tcl_DuplicateObj(objv[2]);
  Tcl_IncrRefCount(pNew->pScript);

  rc = sqlite4_authorizer_push(db, (void *)pNew, testauth_xAuth, testauth_xDel);
  if( rc!=SQLITE4_OK ){
    /* If sqlite4_authorizer_push() fails, the destructor is not invoked. */
    testauth_xDel((void *)pNew);
  }

  return sqlite4TestSetResult(interp, rc);
}

/*
** sqlite4_authorizer_pop DB
*/
static int testauth_pop(
  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc;
  sqlite4 *db;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB");
    return TCL_ERROR;
  }
  rc = sqlite4TestDbHandle(interp, objv[1], &db);
  if( rc!=TCL_OK ) return rc;

  rc = sqlite4_authorizer_pop(db);
  return sqlite4TestSetResult(interp, rc);
}

int Sqlitetest_auth_init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "sqlite4_authorizer_push", testauth_push, 0, 0);
  Tcl_CreateObjCommand(interp, "sqlite4_authorizer_pop", testauth_pop, 0, 0);
  return TCL_OK;
}

Changes to test/test_main.c

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174






175
176
177
178
179
180
181
....
4397
4398
4399
4400
4401
4402
4403




4404
4405
4406
4407
4408
4409
4410
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite4*)sqlite4TestTextToPtr(zA);
  }
  return TCL_OK;
}





const char *sqlite4TestErrorName(int rc){
  const char *zName = 0;
  switch( rc ){
    case SQLITE4_OK:                  zName = "SQLITE4_OK";                break;
    case SQLITE4_ERROR:               zName = "SQLITE4_ERROR";             break;
    case SQLITE4_INTERNAL:            zName = "SQLITE4_INTERNAL";          break;
    case SQLITE4_PERM:                zName = "SQLITE4_PERM";              break;
    case SQLITE4_ABORT:               zName = "SQLITE4_ABORT";             break;
    case SQLITE4_BUSY:                zName = "SQLITE4_BUSY";              break;
    case SQLITE4_LOCKED:              zName = "SQLITE4_LOCKED";            break;
    case SQLITE4_LOCKED_SHAREDCACHE:  zName = "SQLITE4_LOCKED_SHAREDCACHE";break;
    case SQLITE4_NOMEM:               zName = "SQLITE4_NOMEM";             break;
    case SQLITE4_READONLY:            zName = "SQLITE4_READONLY";          break;
    case SQLITE4_INTERRUPT:           zName = "SQLITE4_INTERRUPT";         break;
    case SQLITE4_IOERR:               zName = "SQLITE4_IOERR";             break;
    case SQLITE4_CORRUPT:             zName = "SQLITE4_CORRUPT";           break;
    case SQLITE4_NOTFOUND:            zName = "SQLITE4_NOTFOUND";          break;
    case SQLITE4_FULL:                zName = "SQLITE4_FULL";              break;
    case SQLITE4_CANTOPEN:            zName = "SQLITE4_CANTOPEN";          break;
    case SQLITE4_PROTOCOL:            zName = "SQLITE4_PROTOCOL";          break;
    case SQLITE4_EMPTY:               zName = "SQLITE4_EMPTY";             break;
    case SQLITE4_SCHEMA:              zName = "SQLITE4_SCHEMA";            break;
    case SQLITE4_TOOBIG:              zName = "SQLITE4_TOOBIG";            break;
    case SQLITE4_CONSTRAINT:          zName = "SQLITE4_CONSTRAINT";        break;
    case SQLITE4_MISMATCH:            zName = "SQLITE4_MISMATCH";          break;
    case SQLITE4_MISUSE:              zName = "SQLITE4_MISUSE";            break;
    case SQLITE4_NOLFS:               zName = "SQLITE4_NOLFS";             break;
    case SQLITE4_AUTH:                zName = "SQLITE4_AUTH";              break;
    case SQLITE4_FORMAT:              zName = "SQLITE4_FORMAT";            break;
    case SQLITE4_RANGE:               zName = "SQLITE4_RANGE";             break;
    case SQLITE4_NOTADB:              zName = "SQLITE4_NOTADB";            break;
    case SQLITE4_ROW:                 zName = "SQLITE4_ROW";               break;
    case SQLITE4_DONE:                zName = "SQLITE4_DONE";              break;
    case SQLITE4_INEXACT:             zName = "SQLITE4_INEXACT";           break;
    case SQLITE4_IOERR_READ:          zName = "SQLITE4_IOERR_READ";        break;
    case SQLITE4_IOERR_SHORT_READ:    zName = "SQLITE4_IOERR_SHORT_READ";  break;
    case SQLITE4_IOERR_WRITE:         zName = "SQLITE4_IOERR_WRITE";       break;
    case SQLITE4_IOERR_FSYNC:         zName = "SQLITE4_IOERR_FSYNC";       break;
    case SQLITE4_IOERR_DIR_FSYNC:     zName = "SQLITE4_IOERR_DIR_FSYNC";   break;
    case SQLITE4_IOERR_TRUNCATE:      zName = "SQLITE4_IOERR_TRUNCATE";    break;
    case SQLITE4_IOERR_FSTAT:         zName = "SQLITE4_IOERR_FSTAT";       break;
    case SQLITE4_IOERR_UNLOCK:        zName = "SQLITE4_IOERR_UNLOCK";      break;
    case SQLITE4_IOERR_RDLOCK:        zName = "SQLITE4_IOERR_RDLOCK";      break;
    case SQLITE4_IOERR_DELETE:        zName = "SQLITE4_IOERR_DELETE";      break;
    case SQLITE4_IOERR_BLOCKED:       zName = "SQLITE4_IOERR_BLOCKED";     break;
    case SQLITE4_IOERR_NOMEM:         zName = "SQLITE4_IOERR_NOMEM";       break;
    case SQLITE4_IOERR_ACCESS:        zName = "SQLITE4_IOERR_ACCESS";      break;
    case SQLITE4_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE4_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE4_IOERR_LOCK:          zName = "SQLITE4_IOERR_LOCK";        break;
    case SQLITE4_CORRUPT_VTAB:        zName = "SQLITE4_CORRUPT_VTAB";      break;
    case SQLITE4_READONLY_RECOVERY:   zName = "SQLITE4_READONLY_RECOVERY"; break;
    case SQLITE4_READONLY_CANTLOCK:   zName = "SQLITE4_READONLY_CANTLOCK"; break;
    default:                         zName = "SQLITE4_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite4TestErrorName







/*
** Convert an sqlite4_stmt* into an sqlite4*.  This depends on the
** fact that the sqlite4* is the first field in the Vdbe structure.
*/
#define StmtToDb(X)   sqlite4_db_handle(X)

................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  return test_num_predicate( interp, argc, argv, sqlite4_num_isnan );
}





/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite4_search_count;
  extern int sqlite4_found_count;







>
>
|
>



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|





>
>
>
>
>
>







 







>
>
>
>







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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
....
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite4*)sqlite4TestTextToPtr(zA);
  }
  return TCL_OK;
}

int sqlite4TestDbHandle(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite4 **ppDb){
  return getDbPointer(interp, Tcl_GetString(pObj), ppDb);
}

const char *sqlite4TestErrorName(int rc){
  const char *zName = 0;
  switch( rc ){
    case SQLITE4_OK:                 zName = "SQLITE4_OK";                break;
    case SQLITE4_ERROR:              zName = "SQLITE4_ERROR";             break;
    case SQLITE4_INTERNAL:           zName = "SQLITE4_INTERNAL";          break;
    case SQLITE4_PERM:               zName = "SQLITE4_PERM";              break;
    case SQLITE4_ABORT:              zName = "SQLITE4_ABORT";             break;
    case SQLITE4_BUSY:               zName = "SQLITE4_BUSY";              break;
    case SQLITE4_LOCKED:             zName = "SQLITE4_LOCKED";            break;
    case SQLITE4_LOCKED_SHAREDCACHE: zName = "SQLITE4_LOCKED_SHAREDCACHE";break;
    case SQLITE4_NOMEM:              zName = "SQLITE4_NOMEM";             break;
    case SQLITE4_READONLY:           zName = "SQLITE4_READONLY";          break;
    case SQLITE4_INTERRUPT:          zName = "SQLITE4_INTERRUPT";         break;
    case SQLITE4_IOERR:              zName = "SQLITE4_IOERR";             break;
    case SQLITE4_CORRUPT:            zName = "SQLITE4_CORRUPT";           break;
    case SQLITE4_NOTFOUND:           zName = "SQLITE4_NOTFOUND";          break;
    case SQLITE4_FULL:               zName = "SQLITE4_FULL";              break;
    case SQLITE4_CANTOPEN:           zName = "SQLITE4_CANTOPEN";          break;
    case SQLITE4_PROTOCOL:           zName = "SQLITE4_PROTOCOL";          break;
    case SQLITE4_EMPTY:              zName = "SQLITE4_EMPTY";             break;
    case SQLITE4_SCHEMA:             zName = "SQLITE4_SCHEMA";            break;
    case SQLITE4_TOOBIG:             zName = "SQLITE4_TOOBIG";            break;
    case SQLITE4_CONSTRAINT:         zName = "SQLITE4_CONSTRAINT";        break;
    case SQLITE4_MISMATCH:           zName = "SQLITE4_MISMATCH";          break;
    case SQLITE4_MISUSE:             zName = "SQLITE4_MISUSE";            break;
    case SQLITE4_NOLFS:              zName = "SQLITE4_NOLFS";             break;
    case SQLITE4_AUTH:               zName = "SQLITE4_AUTH";              break;
    case SQLITE4_FORMAT:             zName = "SQLITE4_FORMAT";            break;
    case SQLITE4_RANGE:              zName = "SQLITE4_RANGE";             break;
    case SQLITE4_NOTADB:             zName = "SQLITE4_NOTADB";            break;
    case SQLITE4_ROW:                zName = "SQLITE4_ROW";               break;
    case SQLITE4_DONE:               zName = "SQLITE4_DONE";              break;
    case SQLITE4_INEXACT:            zName = "SQLITE4_INEXACT";           break;
    case SQLITE4_IOERR_READ:         zName = "SQLITE4_IOERR_READ";        break;
    case SQLITE4_IOERR_SHORT_READ:   zName = "SQLITE4_IOERR_SHORT_READ";  break;
    case SQLITE4_IOERR_WRITE:        zName = "SQLITE4_IOERR_WRITE";       break;
    case SQLITE4_IOERR_FSYNC:        zName = "SQLITE4_IOERR_FSYNC";       break;
    case SQLITE4_IOERR_DIR_FSYNC:    zName = "SQLITE4_IOERR_DIR_FSYNC";   break;
    case SQLITE4_IOERR_TRUNCATE:     zName = "SQLITE4_IOERR_TRUNCATE";    break;
    case SQLITE4_IOERR_FSTAT:        zName = "SQLITE4_IOERR_FSTAT";       break;
    case SQLITE4_IOERR_UNLOCK:       zName = "SQLITE4_IOERR_UNLOCK";      break;
    case SQLITE4_IOERR_RDLOCK:       zName = "SQLITE4_IOERR_RDLOCK";      break;
    case SQLITE4_IOERR_DELETE:       zName = "SQLITE4_IOERR_DELETE";      break;
    case SQLITE4_IOERR_BLOCKED:      zName = "SQLITE4_IOERR_BLOCKED";     break;
    case SQLITE4_IOERR_NOMEM:        zName = "SQLITE4_IOERR_NOMEM";       break;
    case SQLITE4_IOERR_ACCESS:       zName = "SQLITE4_IOERR_ACCESS";      break;
    case SQLITE4_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE4_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE4_IOERR_LOCK:         zName = "SQLITE4_IOERR_LOCK";        break;
    case SQLITE4_CORRUPT_VTAB:       zName = "SQLITE4_CORRUPT_VTAB";      break;
    case SQLITE4_READONLY_RECOVERY:  zName = "SQLITE4_READONLY_RECOVERY"; break;
    case SQLITE4_READONLY_CANTLOCK:  zName = "SQLITE4_READONLY_CANTLOCK"; break;
    default:                         zName = "SQLITE4_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite4TestErrorName

int sqlite4TestSetResult(Tcl_Interp *interp, int rc){
  const char *z = sqlite4TestErrorName(rc);
  Tcl_SetObjResult(interp, Tcl_NewStringObj(z, -1));
  return TCL_OK;
}

/*
** Convert an sqlite4_stmt* into an sqlite4*.  This depends on the
** fact that the sqlite4* is the first field in the Vdbe structure.
*/
#define StmtToDb(X)   sqlite4_db_handle(X)

................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  return test_num_predicate( interp, argc, argv, sqlite4_num_isnan );
}

void sqlite4TestInit(Tcl_Interp *interp){
  Sqlitetest_auth_init(interp);
}

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite4_search_count;
  extern int sqlite4_found_count;