SQLite4
Check-in [1431be77de]
Not logged in

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

Overview
Comment:Remove the obsolete and unused sqlite4_unlock_notify() interface.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1431be77de2253352a9ef0fc2f9f3a386783d661
User & Date: drh 2013-02-25 18:35:16
Context
2013-02-25
18:44
Fix a test case so that it avoids doing an == comparison between two imprecise floating point numbers. check-in: dae258f4ac user: drh tags: trunk
18:35
Remove the obsolete and unused sqlite4_unlock_notify() interface. check-in: 1431be77de user: drh tags: trunk
17:49
Fix a legacy test case that uses zeroblob(). check-in: 22d65927b3 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
** need to be reinitialized each time the statement is run.</dd>
** </dl>
*/
#define SQLITE4_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE4_STMTSTATUS_SORT              2
#define SQLITE4_STMTSTATUS_AUTOINDEX         3


/*
** CAPIREF: Unlock Notification
**
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE4_LOCKED] error if the required locks on the shared-cache or
** individual tables within the shared-cache cannot be obtained. See
** [SQLite Shared-Cache Mode] for a description of shared-cache locking. 
** ^This API may be used to register a callback that SQLite will invoke 
** when the connection currently holding the required lock relinquishes it.
** ^This API is only available if the library was compiled with the
** [SQLITE4_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
**
** See Also: [Using the SQLite Unlock Notification Feature].
**
** ^Shared-cache locks are released when a database connection concludes
** its current transaction, either by committing it or rolling it back. 
**
** ^When a connection (known as the blocked connection) fails to obtain a
** shared-cache lock and SQLITE4_LOCKED is returned to the caller, the
** identity of the database connection (the blocking connection) that
** has locked the required resource is stored internally. ^After an 
** application receives an SQLITE4_LOCKED error, it may call the
** sqlite4_unlock_notify() method with the blocked connection handle as 
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite4_step] or [sqlite4_close]
** call that concludes the blocking connections transaction.
**
** ^(If sqlite4_unlock_notify() is called in a multi-threaded application,
** there is a chance that the blocking connection will have already
** concluded its transaction by the time sqlite4_unlock_notify() is invoked.
** If this happens, then the specified callback is invoked immediately,
** from within the call to sqlite4_unlock_notify().)^
**
** ^If the blocked connection is attempting to obtain a write-lock on a
** shared-cache table, and more than one other connection currently holds
** a read-lock on the same table, then SQLite arbitrarily selects one of 
** the other connections to use as the blocking connection.
**
** ^(There may be at most one unlock-notify callback registered by a 
** blocked connection. If sqlite4_unlock_notify() is called when the
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite4_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
** unlock-notify callback is canceled. ^The blocked connections 
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite4_close()].
**
** The unlock-notify callback is not reentrant. If an application invokes
** any sqlite4_xxx API functions from within an unlock-notify callback, a
** crash or deadlock may be the result.
**
** ^Unless deadlock is detected (see below), sqlite4_unlock_notify() always
** returns SQLITE4_OK.
**
** <b>Callback Invocation Details</b>
**
** When an unlock-notify callback is registered, the application provides a 
** single void* pointer that is passed to the callback when it is invoked.
** However, the signature of the callback function allows SQLite to pass
** it an array of void* context pointers. The first argument passed to
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
** When a blocking connections transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** same callback function, then instead of invoking the callback function
** multiple times, it is invoked once with the set of void* context pointers
** specified by the blocked connections bundled together into an array.
** This gives the application an opportunity to prioritize any actions 
** related to the set of unblocked database connections.
**
** <b>Deadlock Detection</b>
**
** Assuming that after registering for an unlock-notify callback a 
** database waits for the callback to be issued before taking any further
** action (a reasonable assumption), then using this API may cause the
** application to deadlock. For example, if connection X is waiting for
** connection Y's transaction to be concluded, and similarly connection
** Y is waiting on connection X's transaction, then neither connection
** will proceed and the system may remain deadlocked indefinitely.
**
** To avoid this scenario, the sqlite4_unlock_notify() performs deadlock
** detection. ^If a given call to sqlite4_unlock_notify() would put the
** system in a deadlocked state, then SQLITE4_LOCKED is returned and no
** unlock-notify callback is registered. The system is said to be in
** a deadlocked state if connection A has registered for an unlock-notify
** callback on the conclusion of connection B's transaction, and connection
** B has itself registered for an unlock-notify callback when connection
** A's transaction is concluded. ^Indirect deadlock is also detected, so
** the system is also considered to be deadlocked if connection B has
** registered for an unlock-notify callback on the conclusion of connection
** C's transaction, where connection C is waiting on connection A. ^Any
** number of levels of indirection are allowed.
**
** <b>The "DROP TABLE" Exception</b>
**
** When a call to [sqlite4_step()] returns SQLITE4_LOCKED, it is almost 
** always appropriate to call sqlite4_unlock_notify(). There is however,
** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
** SQLite checks if there are any currently executing SELECT statements
** that belong to the same connection. If there are, SQLITE4_LOCKED is
** returned. In this case there is no "blocking connection", so invoking
** sqlite4_unlock_notify() results in the unlock-notify callback being
** invoked immediately. If the application then re-attempts the "DROP TABLE"
** or "DROP INDEX" query, an infinite loop might be the result.
**
** One way around this problem is to check the extended error code returned
** by an sqlite4_step() call. ^(If there is a blocking connection, then the
** extended error code is set to SQLITE4_LOCKED_SHAREDCACHE. Otherwise, in
** the special "DROP TABLE/INDEX" case, the extended error code is just 
** SQLITE4_LOCKED.)^
*/
int sqlite4_unlock_notify(
  sqlite4 *pBlocked,                          /* Waiting connection */
  void (*xNotify)(void **apArg, int nArg),    /* Callback function to invoke */
  void *pNotifyArg                            /* Argument to pass to xNotify */
);


/*
** CAPIREF: String Comparison
**
** ^The [sqlite4_strnicmp()] API allows applications and extensions to
** compare the contents of two buffers containing UTF-8 strings in a
** case-independent fashion, using the same definition of case independence 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







4030
4031
4032
4033
4034
4035
4036

























































































































4037
4038
4039
4040
4041
4042
4043
** need to be reinitialized each time the statement is run.</dd>
** </dl>
*/
#define SQLITE4_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE4_STMTSTATUS_SORT              2
#define SQLITE4_STMTSTATUS_AUTOINDEX         3



























































































































/*
** CAPIREF: String Comparison
**
** ^The [sqlite4_strnicmp()] API allows applications and extensions to
** compare the contents of two buffers containing UTF-8 strings in a
** case-independent fashion, using the same definition of case independence 

Changes to src/tclsqlite.c.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
....
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
....
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
  char *zTrace;              /* The trace callback routine */
  char *zProfile;            /* The profile callback routine */
  char *zProgress;           /* The progress callback routine */
  char *zAuth;               /* The authorization callback routine */
  int disableAuth;           /* Disable the authorizer if it exists */
  char *zNull;               /* Text to substitute for an SQL NULL value */
  SqlFunc *pFunc;            /* List of SQL functions */
  Tcl_Obj *pUnlockNotify;    /* Unlock notify script (if any) */
  SqlCollate *pCollate;      /* List of SQL collation functions */
  int rc;                    /* Return code of most recent sqlite4_exec() */
  Tcl_Obj *pCollateNeeded;   /* Collation needed script */
  SqlPreparedStmt *stmtList; /* List of prepared statements*/
  SqlPreparedStmt *stmtLast; /* Last statement in the list */
  int maxStmt;               /* The next maximum number of stmtList */
  int nStmt;                 /* Number of statements in stmtList */
................................................................................
  Tcl_DStringAppend(&str, pDb->zProfile, -1);
  Tcl_DStringAppendElement(&str, zSql);
  Tcl_DStringAppendElement(&str, zTm);
  Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
  Tcl_DStringFree(&str);
  Tcl_ResetResult(pDb->interp);
}
#endif

#if defined(SQLITE4_TEST) && defined(SQLITE4_ENABLE_UNLOCK_NOTIFY)
static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){
  char zBuf[64];
  sprintf(zBuf, "%d", iArg);
  Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY);
  sprintf(zBuf, "%d", nArg);
  Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY);
}
#else
# define setTestUnlockNotifyVars(x,y,z)
#endif

#ifdef SQLITE4_ENABLE_UNLOCK_NOTIFY
static void DbUnlockNotify(void **apArg, int nArg){
  int i;
  for(i=0; i<nArg; i++){
    const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
    SqliteDb *pDb = (SqliteDb *)apArg[i];
    setTestUnlockNotifyVars(pDb->interp, i, nArg);
    assert( pDb->pUnlockNotify);
    Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags);
    Tcl_DecrRefCount(pDb->pUnlockNotify);
    pDb->pUnlockNotify = 0;
  }
}
#endif

static void tclCollateNeeded(
  void *pCtx,
  sqlite4 *db,
  int enc,
  const char *zName
................................................................................
    "authorizer",         "cache",             "changes",
    "close",              "collate",           "collation_needed",
    "complete",           "copy",              "enable_load_extension", 
    "errorcode",          "eval",              "exists",             
    "function",           "interrupt",         
    "nullvalue",          "onecolumn",         "profile",
    "rekey",              "status",            "total_changes",
    "trace",              "transaction",       "unlock_notify",
    "version",            0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_CACHE,            DB_CHANGES,
    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION, 
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,            
    DB_FUNCTION,          DB_INTERRUPT,        
    DB_NULLVALUE,         DB_ONECOLUMN,        DB_PROFILE,           
    DB_REKEY,             DB_STATUS,           DB_TOTAL_CHANGES,    
    DB_TRACE,             DB_TRANSACTION,      DB_UNLOCK_NOTIFY,
    DB_VERSION
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
................................................................................
    ** or savepoint.  */
    if( DbUseNre() ){
      Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
      Tcl_NREvalObj(interp, pScript, 0);
    }else{
      rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
    }
    break;
  }

  /*
  **    $db unlock_notify ?script?
  */
  case DB_UNLOCK_NOTIFY: {
#ifndef SQLITE4_ENABLE_UNLOCK_NOTIFY
    Tcl_AppendResult(interp, "unlock_notify not available in this build", 0);
    rc = TCL_ERROR;
#else
    if( objc!=2 && objc!=3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
      rc = TCL_ERROR;
    }else{
      void (*xNotify)(void **, int) = 0;
      void *pNotifyArg = 0;

      if( pDb->pUnlockNotify ){
        Tcl_DecrRefCount(pDb->pUnlockNotify);
        pDb->pUnlockNotify = 0;
      }
  
      if( objc==3 ){
        xNotify = DbUnlockNotify;
        pNotifyArg = (void *)pDb;
        pDb->pUnlockNotify = objv[2];
        Tcl_IncrRefCount(pDb->pUnlockNotify);
      }
  
      if( sqlite4_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
        Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0);
        rc = TCL_ERROR;
      }
    }
#endif
    break;
  }

  /*    $db version
  **
  ** Return the version string for this database.
  */







<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|










|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







114
115
116
117
118
119
120

121
122
123
124
125
126
127
...
309
310
311
312
313
314
315



























316
317
318
319
320
321
322
....
1244
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
....
2086
2087
2088
2089
2090
2091
2092




































2093
2094
2095
2096
2097
2098
2099
  char *zTrace;              /* The trace callback routine */
  char *zProfile;            /* The profile callback routine */
  char *zProgress;           /* The progress callback routine */
  char *zAuth;               /* The authorization callback routine */
  int disableAuth;           /* Disable the authorizer if it exists */
  char *zNull;               /* Text to substitute for an SQL NULL value */
  SqlFunc *pFunc;            /* List of SQL functions */

  SqlCollate *pCollate;      /* List of SQL collation functions */
  int rc;                    /* Return code of most recent sqlite4_exec() */
  Tcl_Obj *pCollateNeeded;   /* Collation needed script */
  SqlPreparedStmt *stmtList; /* List of prepared statements*/
  SqlPreparedStmt *stmtLast; /* Last statement in the list */
  int maxStmt;               /* The next maximum number of stmtList */
  int nStmt;                 /* Number of statements in stmtList */
................................................................................
  Tcl_DStringAppend(&str, pDb->zProfile, -1);
  Tcl_DStringAppendElement(&str, zSql);
  Tcl_DStringAppendElement(&str, zTm);
  Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
  Tcl_DStringFree(&str);
  Tcl_ResetResult(pDb->interp);
}



























#endif

static void tclCollateNeeded(
  void *pCtx,
  sqlite4 *db,
  int enc,
  const char *zName
................................................................................
    "authorizer",         "cache",             "changes",
    "close",              "collate",           "collation_needed",
    "complete",           "copy",              "enable_load_extension", 
    "errorcode",          "eval",              "exists",             
    "function",           "interrupt",         
    "nullvalue",          "onecolumn",         "profile",
    "rekey",              "status",            "total_changes",
    "trace",              "transaction",
    "version",            0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_CACHE,            DB_CHANGES,
    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION, 
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,            
    DB_FUNCTION,          DB_INTERRUPT,        
    DB_NULLVALUE,         DB_ONECOLUMN,        DB_PROFILE,           
    DB_REKEY,             DB_STATUS,           DB_TOTAL_CHANGES,    
    DB_TRACE,             DB_TRANSACTION,
    DB_VERSION
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
................................................................................
    ** or savepoint.  */
    if( DbUseNre() ){
      Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
      Tcl_NREvalObj(interp, pScript, 0);
    }else{
      rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
    }




































    break;
  }

  /*    $db version
  **
  ** Return the version string for this database.
  */

Changes to test/tkt-bd484a090c.test.

20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37

38
do_test 1.1 {
  lindex [catchsql { SELECT datetime('now', 'localtime') }] 0
} {0}
do_test 1.2 {
  lindex [catchsql { SELECT datetime('now', 'utc') }] 0
} {0}


sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 1

do_test 2.1 {
  catchsql { SELECT datetime('now', 'localtime') }
} {1 {local time unavailable}}
do_test 2.2 {
  catchsql { SELECT datetime('now', 'utc') }
} {1 {local time unavailable}}

sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 0


finish_test







>










|
>

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
do_test 1.1 {
  lindex [catchsql { SELECT datetime('now', 'localtime') }] 0
} {0}
do_test 1.2 {
  lindex [catchsql { SELECT datetime('now', 'utc') }] 0
} {0}

if 0 {
sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 1

do_test 2.1 {
  catchsql { SELECT datetime('now', 'localtime') }
} {1 {local time unavailable}}
do_test 2.2 {
  catchsql { SELECT datetime('now', 'utc') }
} {1 {local time unavailable}}

sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 0
}

finish_test