| | @@ -130,10 +130,13 @@ |
| 130 | 130 | char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */ |
| 131 | 131 | int nBeforeCommit; /* Number of entries in azBeforeCommit */ |
| 132 | 132 | int nPriorChanges; /* sqlite3_total_changes() at transaction start */ |
| 133 | 133 | const char *zStartFile; /* File in which transaction was started */ |
| 134 | 134 | int iStartLine; /* Line of zStartFile where transaction started */ |
| 135 | + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); |
| 136 | + void *pAuthArg; /* Argument to the authorizer */ |
| 137 | + const char *zAuthName; /* Name of the authorizer */ |
| 135 | 138 | } db = {0, 0, 0, 0, 0, 0, }; |
| 136 | 139 | |
| 137 | 140 | /* |
| 138 | 141 | ** Arrange for the given file to be deleted on a failure. |
| 139 | 142 | */ |
| | @@ -316,10 +319,36 @@ |
| 316 | 319 | } |
| 317 | 320 | db.aHook[db.nCommitHook].sequence = sequence; |
| 318 | 321 | db.aHook[db.nCommitHook].xHook = x; |
| 319 | 322 | db.nCommitHook++; |
| 320 | 323 | } |
| 324 | + |
| 325 | +/* |
| 326 | +** Set or unset the query authorizer callback function |
| 327 | +*/ |
| 328 | +void db_set_authorizer( |
| 329 | + int(*xAuth)(void*,int,const char*,const char*,const char*,const char*), |
| 330 | + void *pArg, |
| 331 | + const char *zName /* for tracing */ |
| 332 | +){ |
| 333 | + if( db.xAuth ){ |
| 334 | + fossil_panic("multiple active db_set_authorizer() calls"); |
| 335 | + } |
| 336 | + if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg); |
| 337 | + db.xAuth = xAuth; |
| 338 | + db.pAuthArg = pArg; |
| 339 | + db.zAuthName = zName; |
| 340 | + if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName); |
| 341 | +} |
| 342 | +void db_clear_authorizer(void){ |
| 343 | + if( db.zAuthName && g.fSqlTrace ){ |
| 344 | + fossil_trace("-- discontinue authorizer %s\n", db.zAuthName); |
| 345 | + } |
| 346 | + if( g.db ) sqlite3_set_authorizer(g.db, 0, 0); |
| 347 | + db.xAuth = 0; |
| 348 | + db.pAuthArg = 0; |
| 349 | +} |
| 321 | 350 | |
| 322 | 351 | #if INTERFACE |
| 323 | 352 | /* |
| 324 | 353 | ** Possible flags to db_vprepare |
| 325 | 354 | */ |
| | @@ -844,34 +873,37 @@ |
| 844 | 873 | void db_init_database( |
| 845 | 874 | const char *zFileName, /* Name of database file to create */ |
| 846 | 875 | const char *zSchema, /* First part of schema */ |
| 847 | 876 | ... /* Additional SQL to run. Terminate with NULL. */ |
| 848 | 877 | ){ |
| 849 | | - sqlite3 *db; |
| 878 | + sqlite3 *xdb; |
| 850 | 879 | int rc; |
| 851 | 880 | const char *zSql; |
| 852 | 881 | va_list ap; |
| 853 | 882 | |
| 854 | | - db = db_open(zFileName ? zFileName : ":memory:"); |
| 855 | | - sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0); |
| 856 | | - rc = sqlite3_exec(db, zSchema, 0, 0, 0); |
| 883 | + xdb = db_open(zFileName ? zFileName : ":memory:"); |
| 884 | + sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0); |
| 885 | + if( db.xAuth ){ |
| 886 | + sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg); |
| 887 | + } |
| 888 | + rc = sqlite3_exec(xdb, zSchema, 0, 0, 0); |
| 857 | 889 | if( rc!=SQLITE_OK ){ |
| 858 | | - db_err("%s", sqlite3_errmsg(db)); |
| 890 | + db_err("%s", sqlite3_errmsg(xdb)); |
| 859 | 891 | } |
| 860 | 892 | va_start(ap, zSchema); |
| 861 | 893 | while( (zSql = va_arg(ap, const char*))!=0 ){ |
| 862 | | - rc = sqlite3_exec(db, zSql, 0, 0, 0); |
| 894 | + rc = sqlite3_exec(xdb, zSql, 0, 0, 0); |
| 863 | 895 | if( rc!=SQLITE_OK ){ |
| 864 | | - db_err("%s", sqlite3_errmsg(db)); |
| 896 | + db_err("%s", sqlite3_errmsg(xdb)); |
| 865 | 897 | } |
| 866 | 898 | } |
| 867 | 899 | va_end(ap); |
| 868 | | - sqlite3_exec(db, "COMMIT", 0, 0, 0); |
| 900 | + sqlite3_exec(xdb, "COMMIT", 0, 0, 0); |
| 869 | 901 | if( zFileName || g.db!=0 ){ |
| 870 | | - sqlite3_close(db); |
| 902 | + sqlite3_close(xdb); |
| 871 | 903 | }else{ |
| 872 | | - g.db = db; |
| 904 | + g.db = xdb; |
| 873 | 905 | } |
| 874 | 906 | } |
| 875 | 907 | |
| 876 | 908 | /* |
| 877 | 909 | ** Function to return the number of seconds since 1970. This is |
| | @@ -2089,10 +2121,11 @@ |
| 2089 | 2121 | ** argument is true. Ignore unfinalized statements when false. |
| 2090 | 2122 | */ |
| 2091 | 2123 | void db_close(int reportErrors){ |
| 2092 | 2124 | sqlite3_stmt *pStmt; |
| 2093 | 2125 | if( g.db==0 ) return; |
| 2126 | + sqlite3_set_authorizer(g.db, 0, 0); |
| 2094 | 2127 | if( g.fSqlStats ){ |
| 2095 | 2128 | int cur, hiwtr; |
| 2096 | 2129 | sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0); |
| 2097 | 2130 | fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr); |
| 2098 | 2131 | sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0); |
| | @@ -2118,17 +2151,20 @@ |
| 2118 | 2151 | fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare); |
| 2119 | 2152 | } |
| 2120 | 2153 | while( db.pAllStmt ){ |
| 2121 | 2154 | db_finalize(db.pAllStmt); |
| 2122 | 2155 | } |
| 2123 | | - if( db.nBegin && reportErrors ){ |
| 2124 | | - fossil_warning("Transaction started at %s:%d never commits", |
| 2125 | | - db.zStartFile, db.iStartLine); |
| 2156 | + if( db.nBegin ){ |
| 2157 | + if( reportErrors ){ |
| 2158 | + fossil_warning("Transaction started at %s:%d never commits", |
| 2159 | + db.zStartFile, db.iStartLine); |
| 2160 | + } |
| 2126 | 2161 | db_end_transaction(1); |
| 2127 | 2162 | } |
| 2128 | 2163 | pStmt = 0; |
| 2129 | | - g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */ |
| 2164 | + sqlite3_busy_timeout(g.db, 0); |
| 2165 | + g.dbIgnoreErrors++; /* Stop "database locked" warnings */ |
| 2130 | 2166 | sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0); |
| 2131 | 2167 | g.dbIgnoreErrors--; |
| 2132 | 2168 | db_close_config(); |
| 2133 | 2169 | |
| 2134 | 2170 | /* If the localdb has a lot of unused free space, |
| | @@ -2168,10 +2204,11 @@ |
| 2168 | 2204 | if( g.db ){ |
| 2169 | 2205 | int rc; |
| 2170 | 2206 | sqlite3_wal_checkpoint(g.db, 0); |
| 2171 | 2207 | rc = sqlite3_close(g.db); |
| 2172 | 2208 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc); |
| 2209 | + db_clear_authorizer(); |
| 2173 | 2210 | } |
| 2174 | 2211 | g.db = 0; |
| 2175 | 2212 | g.repositoryOpen = 0; |
| 2176 | 2213 | g.localOpen = 0; |
| 2177 | 2214 | } |
| 2178 | 2215 | |