_fiddle_the_db
_fiddle_db_arg
_fiddle_db_filename
+_fiddle_reset_db
stderr("Restarting the app requires reloading the page.");
wMsg('error', err);
}
- fiddleModule.setStatus('Exception thrown, see JavaScript console');
- fiddleModule.setStatus = function(text) {
+ fiddleModule.setStatus('Exception thrown, see JavaScript console:',text);
+ /*fiddleModule.setStatus = function(text) {
console.error('[post-exception status]', text);
- };
+ };*/
};
const Sqlite3Shell = {
exec: function f(sql){
if(!f._) f._ = fiddleModule.cwrap('fiddle_exec', null, ['string']);
if(fiddleModule.isDead){
- wMsg('stderr', "shell module has exit()ed. Cannot run SQL.");
+ stderr("shell module has exit()ed. Cannot run SQL.");
return;
}
wMsg('working','start');
try {
if(f._running){
- wMsg('stderr','Cannot run multiple commands concurrently.');
+ stderr('Cannot run multiple commands concurrently.');
}else{
f._running = true;
f._(sql);
wMsg('working','end');
}
},
+ resetDb: function f(){
+ if(!f._) f._ = fiddleModule.cwrap('fiddle_reset_db', null);
+ stdout("Resetting database.");
+ f._();
+ stdout("Reset",this.dbFilename());
+ },
/* Interrupt can't work: this Worker is tied up working, so won't get the
interrupt event which would be needed to perform the interrupt. */
interrupt: function f(){
if(!f._) f._ = fiddleModule.cwrap('fiddle_interrupt', null);
- wMsg('stdout',"Requesting interrupt.");
+ stdout("Requesting interrupt.");
f._();
}
};
//console.debug("worker: onmessage.data",ev);
switch(ev.type){
case 'shellExec': Sqlite3Shell.exec(ev.data); return;
+ case 'db-reset': Sqlite3Shell.resetDb(); return;
case 'interrupt': Sqlite3Shell.interrupt(); return;
/** Triggers the export of the current db. Fires an
event in the form:
*/
case 'db-export': {
const fn = Sqlite3Shell.dbFilename();
- wMsg('stdout',"Exporting",fn+".");
+ stdout("Exporting",fn+".");
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
try{
if(!fn2) throw new Error("DB appears to be closed.");
}else if(buffer instanceof ArrayBuffer){
buffer = new Uint8Array(buffer);
}else{
- wMsg('stderr',"'open' expects {buffer:Uint8Array} containing an uploaded db.");
+ stderr("'open' expects {buffer:Uint8Array} containing an uploaded db.");
return;
}
const fn = (
if(oldName !== fn){
fiddleModule.FS.unlink(oldName);
}
- wMsg('stdout',"Replaced DB with",fn+".");
+ stdout("Replaced DB with",fn+".");
return;
}
};
label[for] {
cursor: pointer;
}
- fieldset {
- border-radius: 0.5em;
- }
.error {
color: red;
background-color: yellow;
pointer-events: none !important;
display: none !important;
}
- fieldset.options {
- font-size: 70%;
+ /* Safari supports neither styling of nor event handling on a
+ fieldset legend, so we emulate a fieldset-like widget. */
+ .fieldset {
+ border-radius: 0.5em;
+ border: 1px inset;
+ display: flex;
+ flex-direction: column;
}
- fieldset > legend {
+ .fieldset > .legend {
+ position: relative;
+ top: -1.5ex;
padding: 0 0.5em;
+ font-size: 85%;
+ margin-left: 0.5em;
+ flex: 0 1 auto;
+ align-self: self-start;
+ cursor: pointer;
}
- fieldset.options > div {
+ .fieldset.options > div {
display: flex;
flex-wrap: wrap;
+ font-size: 70%;
+ margin: 0 0.5em 0.5em 0.5em;
+ }
+ .fieldset > .legend > span {
+ position: relative;
+ }
+ .fieldset > .legend::before {
+ /* Hide the parent element's top border where this
+ element intersects it. */
+ content: ' ';
+ width: 100%;
+ height: 100%;
+ background-color: white
+ /* REALLY want to 'inherit' the color from the fieldset's
+ parent, but inherit leads to a transparent bg, which is
+ exactly what we're trying to avoid here. */;
+ opacity: 1;
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+ .fieldset > .legend::after {
+ content: " [hide]";
+ position: relative;
+ }
+ .fieldset.collapsed > .legend::after {
+ content: " [show]";
+ position: relative;
}
span.labeled-input {
padding: 0.25em;
display: flex;
flex-direction: column-reverse;
}
+ #view-split > .fieldset.options {
+ margin-top: 0.5em;
+ }
</style>
</head>
<body>
</div>
<div id='view-split' class='app-view initially-hidden'>
- <fieldset class='options'>
- <legend>Options</legend>
+ <div class='fieldset options collapsible'>
+ <span class='legend'><span>Options</span></span>
<div class=''>
<span class='labeled-input'>
<input type='checkbox' id='opt-cb-sbs'
<span class='labeled-input'>
<button id='btn-export'>Download DB</button>
</span>
+ <span class='labeled-input'>
+ <button id='btn-reset'>Reset DB</button>
+ </span>
<span class='labeled-input'>
<select id='select-examples'></select>
</span>
</div>
- </fieldset>
+ </div><!-- .fieldset -->
<div id='main-wrapper' class=''>
<div class='ta-wrapper input'>
<textarea id="input"
placeholder="Shell input. Ctrl-enter/shift-enter runs it.">
--- Use ctrl-enter or shift-enter to execute SQL
+-- Use ctrl-enter or shift-enter to execute SQL. If only a subset
+-- is currently selected, only that part is executed.
.nullvalue NULL
.mode box
CREATE TABLE t(a,b);
wMsg: function(type,data){
this.worker.postMessage({type, data});
return this;
+ },
+ /**
+ Prompts for confirmation and, if accepted, deletes
+ all content and tables in the (transient) database.
+ */
+ resetDb: function(){
+ if(window.confirm("Really destroy all content and tables "
+ +"in the (transient) db?")){
+ this.wMsg('db-reset');
+ }
+ return this;
}
};
delete this.onSFLoaded;
// Unhide all elements which start out hidden
EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
-
+ E('#btn-reset').addEventListener('click',()=>SF.resetDb());
const taInput = E('#input');
const btnClearIn = E('#btn-clear');
btnClearIn.addEventListener('click',function(){
if(SF.jqTerm) SF.jqTerm.clear();
},false);
const btnShellExec = E('#btn-shell-exec');
- btnShellExec.addEventListener('click',function(){
- const sql = taInput.value.trim();
+ btnShellExec.addEventListener('click',function(ev){
+ let sql;
+ ev.preventDefault();
+ if(taInput.selectionStart<taInput.selectionEnd){
+ sql = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
+ }else{
+ sql = taInput.value.trim();
+ }
if(sql) SF.dbExec(sql);
},false);
});
a.click();
});
-
/**
Handle load/import of an external db file.
*/
r.readAsArrayBuffer(f);
});
+ EAll('.fieldset.collapsible').forEach(function(fs){
+ const legend = E(fs,'span.legend'),
+ content = EAll(fs,':scope > div');
+ legend.addEventListener('click', function(){
+ fs.classList.toggle('collapsed');
+ content.forEach((d)=>d.classList.toggle('hidden'));
+ }, false);
+ });
+
/**
Given a DOM element, this routine measures its "effective
height", which is the bounding top/bottom range of this element
that height here. Larger than ~95% is too big for
Firefox on Android, causing the input area to move
off-screen. */
- const bcl = document.body.classList;
const appViews = EAll('.app-view');
+ const elemsToCount = [
+ /* Elements which we need to always count in the
+ visible body size. */
+ E('body > header'),
+ E('body > footer')
+ ];
const resized = function f(){
if(f.$disabled) return;
const wh = window.innerHeight;
var ht;
var extra = 0;
- const elemsToCount = [
- /* Elements which we need to always count in the
- visible body size. */
- E('body > header'),
- E('body > footer')
- ];
elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false);
ht = wh - extra;
appViews.forEach(function(e){
-C Fix\sissues\swith\sALTER\sTABLE\sand\striggers\scontaining\s"UPDATE...FROM"\sstatements.
-D 2022-05-26T19:10:11.700
+C fiddle:\sadded\san\soption\sto\scompletely\swipe/reset\sthe\sdb.\sThe\sOptions\sarea\scan\snow\sbe\stoggled\son/off\svia\stapping\sthe\slabel\sat\sits\stop.\sRunning\sthe\sinput\sSQL\sis\snow\slimited\sto\sthe\sselected\sarea\sif\sany\stext\sis\scurrently\sselected,\sper\ssuggestion\sin\sthe\sforum.
+D 2022-05-27T03:27:10.415
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/expert/sqlite3expert.c 6ca30d73b9ed75bd56d6e0d7f2c962d2affaa72c505458619d0ff5d9cdfac204
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
-F ext/fiddle/EXPORTED_FUNCTIONS.fiddle 2f7c561af85e6d711fb42f395bc0074b6e6fcf16bc57d495ce4e1c3d0484c5d2
+F ext/fiddle/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 540b9dec63a3a62a256e2f030827848a92e9b9d9b6fa5c0188295a4a1c5382cd
F ext/fiddle/EXPORTED_RUNTIME_METHODS b831017ba67ba993b34a27400cef2f6095bd6789c0fc4eba7e7a251c207be31c
F ext/fiddle/Makefile de65d04bfb312e94dbd7a0e7d99fb126f0abc1db62f920159c4124b5a42347d8
F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8a119ac338a8781c
F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
-F ext/fiddle/fiddle-worker.js 6000da12965319bed53d546f87885a6717a0cd8de0b4832edde7a95e63d1f33e
-F ext/fiddle/fiddle.html 70796dc8a867448b41bc7e2c5fd6b1865ed8010b3abe22ba0678e8915c062e9a
-F ext/fiddle/fiddle.js 45f96ac7f7d6678503568dded46afaa741d841a2464519035636da0fd77aec50
+F ext/fiddle/fiddle-worker.js e3e8c7af2d6d10d915c8d6b5c88bd48587afbfdab7cb76858829c3b83e83a810
+F ext/fiddle/fiddle.html 2d63f820b8b5001ebd0ec0045beef0fed7cbef8e02fd6717b79e9b35050ce2e0
+F ext/fiddle/fiddle.js 700df283e8c6e87519aba6839e1aa99d040b39ea545253cbe79da18e24af256a
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
F ext/fiddle/sqlite3-api.js 8500698d2163f4a25f8e5e6810ad826487342579d6a321d82b244dbc8e6f6db6
F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
F src/resolve.c a4eb3c617027fd049b07432f3b942ea7151fa793a332a11a7d0f58c9539e104f
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c a0dca0b4a328826d4713195a2fe305852cd8b1ed876311667b00c64b93a7fe23
-F src/shell.c.in f3e0eb3e817f4d2edaeb12a06b2a0c8b5302fa223d87db68975313b9ce768e03
+F src/shell.c.in b76e681f9e441928d574f21f9473ef615158bbeab1ae49f05ecab9d81730a51d
F src/sqlite.h.in 172528c287399a34f188154017b7268bf82c6d5b780902e361958d2318c4e37c
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846
-R 4d839461e9af3d0a5ea1b8ddf72bf796
-U dan
-Z 14299f1b8c4a8b0632845b66e1aabf6a
+P 2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259
+R d64445d576ad28e1599d65086ff528c2
+U stephan
+Z 4f4eb41f174aae895c1e375e4f35adbf
# Remove this line to create a well-formed Fossil manifest.
-2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259
\ No newline at end of file
+d100283e378f2d8e353399848184a4ab8ccf6316218fffc28b90a656cf81c279
\ No newline at end of file
: NULL;
}
+/*
+** Closes, unlinks, and reopens the db using its current filename (or
+** the default if the db is currently closed). It is assumed, for
+** purposes of the fiddle build, that the file is in a transient
+** virtual filesystem within the browser.
+*/
+void fiddle_reset_db(void){
+ char *zFilename = 0;
+ if(0==globalDb){
+ shellState.pAuxDb->zDbFilename = "/fiddle.sqlite3";
+ }else{
+ zFilename =
+ sqlite3_mprintf("%s", sqlite3_db_filename(globalDb, "main"));
+ shell_check_oom(zFilename);
+ close_db(globalDb);
+ shellDeleteFile(zFilename);
+ shellState.db = 0;
+ shellState.pAuxDb->zDbFilename = zFilename;
+ }
+ open_db(&shellState, 0);
+ sqlite3_free(zFilename);
+}
+
/*
** Trivial exportable function for emscripten. Needs to be exported using:
**
puts("WASM shell");
puts("Enter \".help\" for usage hints.");
if(once>0){
- shellState.pAuxDb->zDbFilename = "/fiddle.sqlite3";
- open_db(&shellState, 0);
+ fiddle_reset_db();
}
if(shellState.db){
printf("Connected to %s.\n", fiddle_db_filename(NULL));