Fossil SCM
Taught "fossil settings" how to accept multiple ?VALUES? parameters, storing the result as a JSON-encoded array in the config table. Nothing uses this yet, but the resulting SQL DB manipulation appears to work correctly.
Commit
ca069402f8fb2d53e6d05bd5066e1d7c564f365bf9590c3af02c7c30df1cbbd4
Parent
4223fe8cb521331…
1 file changed
+36
-3
M
src/db.c
+36
-3
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -3218,10 +3218,38 @@ | ||
| 3218 | 3218 | if( globalFlag && g.repositoryOpen ){ |
| 3219 | 3219 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 3220 | 3220 | } |
| 3221 | 3221 | db_end_transaction(0); |
| 3222 | 3222 | db_protect_pop(); |
| 3223 | +} | |
| 3224 | +void db_set_array(const char *zName, char* azValues[], size_t nValues, int globalFlag){ | |
| 3225 | + Stmt q; | |
| 3226 | + db_assert_protection_off_or_not_sensitive(zName); | |
| 3227 | + db_unprotect(PROTECT_CONFIG); | |
| 3228 | + db_begin_transaction(); | |
| 3229 | + if( globalFlag ){ | |
| 3230 | + db_swap_connections(); | |
| 3231 | + sqlite3_carray_init(g.db, 0, 0); /* not registered globally on purpose */ | |
| 3232 | + db_prepare(&q, "REPLACE INTO global_config(name,value) VALUES(%Q," | |
| 3233 | + "(SELECT json_group_array(value) FROM carray(?1)))", | |
| 3234 | + zName); | |
| 3235 | + sqlite3_carray_bind(q.pStmt, 1, azValues, nValues, CARRAY_TEXT, SQLITE_STATIC); | |
| 3236 | + db_exec(&q); | |
| 3237 | + db_swap_connections(); | |
| 3238 | + }else{ | |
| 3239 | + sqlite3_carray_init(g.db, 0, 0); /* ditto */ | |
| 3240 | + db_prepare(&q, "REPLACE INTO config(name,value,mtime) VALUES(%Q," | |
| 3241 | + "(SELECT json_group_array(value) FROM carray(?1)),now())", | |
| 3242 | + zName); | |
| 3243 | + sqlite3_carray_bind(q.pStmt, 1, azValues, nValues, CARRAY_TEXT, SQLITE_STATIC); | |
| 3244 | + db_exec(&q); | |
| 3245 | + } | |
| 3246 | + if( globalFlag && g.repositoryOpen ){ | |
| 3247 | + db_multi_exec("DELETE FROM config WHERE name=%Q", zName); | |
| 3248 | + } | |
| 3249 | + db_end_transaction(0); | |
| 3250 | + db_protect_pop(); | |
| 3223 | 3251 | } |
| 3224 | 3252 | void db_unset(const char *zName, int globalFlag){ |
| 3225 | 3253 | db_begin_transaction(); |
| 3226 | 3254 | db_unprotect(PROTECT_CONFIG); |
| 3227 | 3255 | if( globalFlag ){ |
| @@ -4385,21 +4413,21 @@ | ||
| 4385 | 4413 | |
| 4386 | 4414 | if( g.argc==2 ){ |
| 4387 | 4415 | for(i=0; i<nSetting; i++){ |
| 4388 | 4416 | print_setting(&aSetting[i]); |
| 4389 | 4417 | } |
| 4390 | - }else if( g.argc==3 || g.argc==4 ){ | |
| 4418 | + }else if( g.argc>=3 ){ | |
| 4391 | 4419 | const char *zName = g.argv[2]; |
| 4392 | 4420 | int n = (int)strlen(zName); |
| 4393 | 4421 | const Setting *pSetting = db_find_setting(zName, !exactFlag); |
| 4394 | 4422 | if( pSetting==0 ){ |
| 4395 | 4423 | fossil_fatal("no such setting: %s", zName); |
| 4396 | 4424 | } |
| 4397 | 4425 | if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){ |
| 4398 | 4426 | fossil_fatal("cannot set 'manifest' globally"); |
| 4399 | 4427 | } |
| 4400 | - if( unsetFlag || g.argc==4 ){ | |
| 4428 | + if( unsetFlag || g.argc>=4 ){ | |
| 4401 | 4429 | int isManifest = fossil_strcmp(pSetting->name, "manifest")==0; |
| 4402 | 4430 | if( n!=strlen(pSetting[0].name) && pSetting[1].name && |
| 4403 | 4431 | fossil_strncmp(pSetting[1].name, zName, n)==0 ){ |
| 4404 | 4432 | Blob x; |
| 4405 | 4433 | int i; |
| @@ -4416,11 +4444,16 @@ | ||
| 4416 | 4444 | } |
| 4417 | 4445 | if( unsetFlag ){ |
| 4418 | 4446 | db_unset(pSetting->name, globalFlag); |
| 4419 | 4447 | }else{ |
| 4420 | 4448 | db_protect_only(PROTECT_NONE); |
| 4421 | - db_set(pSetting->name, g.argv[3], globalFlag); | |
| 4449 | + if( g.argc==4 ){ | |
| 4450 | + db_set(pSetting->name, g.argv[3], globalFlag); | |
| 4451 | + } | |
| 4452 | + else { | |
| 4453 | + db_set_array(pSetting->name, g.argv+3, g.argc-3, globalFlag); | |
| 4454 | + } | |
| 4422 | 4455 | db_protect_pop(); |
| 4423 | 4456 | } |
| 4424 | 4457 | if( isManifest && g.localOpen ){ |
| 4425 | 4458 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4426 | 4459 | } |
| 4427 | 4460 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3218,10 +3218,38 @@ | |
| 3218 | if( globalFlag && g.repositoryOpen ){ |
| 3219 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 3220 | } |
| 3221 | db_end_transaction(0); |
| 3222 | db_protect_pop(); |
| 3223 | } |
| 3224 | void db_unset(const char *zName, int globalFlag){ |
| 3225 | db_begin_transaction(); |
| 3226 | db_unprotect(PROTECT_CONFIG); |
| 3227 | if( globalFlag ){ |
| @@ -4385,21 +4413,21 @@ | |
| 4385 | |
| 4386 | if( g.argc==2 ){ |
| 4387 | for(i=0; i<nSetting; i++){ |
| 4388 | print_setting(&aSetting[i]); |
| 4389 | } |
| 4390 | }else if( g.argc==3 || g.argc==4 ){ |
| 4391 | const char *zName = g.argv[2]; |
| 4392 | int n = (int)strlen(zName); |
| 4393 | const Setting *pSetting = db_find_setting(zName, !exactFlag); |
| 4394 | if( pSetting==0 ){ |
| 4395 | fossil_fatal("no such setting: %s", zName); |
| 4396 | } |
| 4397 | if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){ |
| 4398 | fossil_fatal("cannot set 'manifest' globally"); |
| 4399 | } |
| 4400 | if( unsetFlag || g.argc==4 ){ |
| 4401 | int isManifest = fossil_strcmp(pSetting->name, "manifest")==0; |
| 4402 | if( n!=strlen(pSetting[0].name) && pSetting[1].name && |
| 4403 | fossil_strncmp(pSetting[1].name, zName, n)==0 ){ |
| 4404 | Blob x; |
| 4405 | int i; |
| @@ -4416,11 +4444,16 @@ | |
| 4416 | } |
| 4417 | if( unsetFlag ){ |
| 4418 | db_unset(pSetting->name, globalFlag); |
| 4419 | }else{ |
| 4420 | db_protect_only(PROTECT_NONE); |
| 4421 | db_set(pSetting->name, g.argv[3], globalFlag); |
| 4422 | db_protect_pop(); |
| 4423 | } |
| 4424 | if( isManifest && g.localOpen ){ |
| 4425 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4426 | } |
| 4427 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3218,10 +3218,38 @@ | |
| 3218 | if( globalFlag && g.repositoryOpen ){ |
| 3219 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 3220 | } |
| 3221 | db_end_transaction(0); |
| 3222 | db_protect_pop(); |
| 3223 | } |
| 3224 | void db_set_array(const char *zName, char* azValues[], size_t nValues, int globalFlag){ |
| 3225 | Stmt q; |
| 3226 | db_assert_protection_off_or_not_sensitive(zName); |
| 3227 | db_unprotect(PROTECT_CONFIG); |
| 3228 | db_begin_transaction(); |
| 3229 | if( globalFlag ){ |
| 3230 | db_swap_connections(); |
| 3231 | sqlite3_carray_init(g.db, 0, 0); /* not registered globally on purpose */ |
| 3232 | db_prepare(&q, "REPLACE INTO global_config(name,value) VALUES(%Q," |
| 3233 | "(SELECT json_group_array(value) FROM carray(?1)))", |
| 3234 | zName); |
| 3235 | sqlite3_carray_bind(q.pStmt, 1, azValues, nValues, CARRAY_TEXT, SQLITE_STATIC); |
| 3236 | db_exec(&q); |
| 3237 | db_swap_connections(); |
| 3238 | }else{ |
| 3239 | sqlite3_carray_init(g.db, 0, 0); /* ditto */ |
| 3240 | db_prepare(&q, "REPLACE INTO config(name,value,mtime) VALUES(%Q," |
| 3241 | "(SELECT json_group_array(value) FROM carray(?1)),now())", |
| 3242 | zName); |
| 3243 | sqlite3_carray_bind(q.pStmt, 1, azValues, nValues, CARRAY_TEXT, SQLITE_STATIC); |
| 3244 | db_exec(&q); |
| 3245 | } |
| 3246 | if( globalFlag && g.repositoryOpen ){ |
| 3247 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 3248 | } |
| 3249 | db_end_transaction(0); |
| 3250 | db_protect_pop(); |
| 3251 | } |
| 3252 | void db_unset(const char *zName, int globalFlag){ |
| 3253 | db_begin_transaction(); |
| 3254 | db_unprotect(PROTECT_CONFIG); |
| 3255 | if( globalFlag ){ |
| @@ -4385,21 +4413,21 @@ | |
| 4413 | |
| 4414 | if( g.argc==2 ){ |
| 4415 | for(i=0; i<nSetting; i++){ |
| 4416 | print_setting(&aSetting[i]); |
| 4417 | } |
| 4418 | }else if( g.argc>=3 ){ |
| 4419 | const char *zName = g.argv[2]; |
| 4420 | int n = (int)strlen(zName); |
| 4421 | const Setting *pSetting = db_find_setting(zName, !exactFlag); |
| 4422 | if( pSetting==0 ){ |
| 4423 | fossil_fatal("no such setting: %s", zName); |
| 4424 | } |
| 4425 | if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){ |
| 4426 | fossil_fatal("cannot set 'manifest' globally"); |
| 4427 | } |
| 4428 | if( unsetFlag || g.argc>=4 ){ |
| 4429 | int isManifest = fossil_strcmp(pSetting->name, "manifest")==0; |
| 4430 | if( n!=strlen(pSetting[0].name) && pSetting[1].name && |
| 4431 | fossil_strncmp(pSetting[1].name, zName, n)==0 ){ |
| 4432 | Blob x; |
| 4433 | int i; |
| @@ -4416,11 +4444,16 @@ | |
| 4444 | } |
| 4445 | if( unsetFlag ){ |
| 4446 | db_unset(pSetting->name, globalFlag); |
| 4447 | }else{ |
| 4448 | db_protect_only(PROTECT_NONE); |
| 4449 | if( g.argc==4 ){ |
| 4450 | db_set(pSetting->name, g.argv[3], globalFlag); |
| 4451 | } |
| 4452 | else { |
| 4453 | db_set_array(pSetting->name, g.argv+3, g.argc-3, globalFlag); |
| 4454 | } |
| 4455 | db_protect_pop(); |
| 4456 | } |
| 4457 | if( isManifest && g.localOpen ){ |
| 4458 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4459 | } |
| 4460 |