Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ff828b1

Browse files
chore: Initial commit
1 parent a58de04 commit ff828b1

File tree

6 files changed

+640
-0
lines changed

6 files changed

+640
-0
lines changed

‎dropzone.min.css‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎dropzone.min.js‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎gui.js‎

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
const execBtn = document.getElementById("execute");
2+
const outputElm = document.getElementById('output');
3+
const errorElm = document.getElementById('error');
4+
const commandsElm = document.getElementById('commands');
5+
const dbFileElm = document.getElementById('dbfile');
6+
const savedbElm = document.getElementById('savedb');
7+
const querySection = document.getElementById('query');
8+
const uploadSection = document.getElementById('dropzone');
9+
10+
// Start the worker in which sql.js will run
11+
const worker = new Worker("worker.sql-wasm.js");
12+
worker.onerror = error;
13+
14+
// Open a database
15+
worker.postMessage({ action: 'open' });
16+
17+
// Connect to the HTML element we 'print' to
18+
function print(text) {
19+
outputElm.innerHTML = text.replace(/\n/g, '<br>');
20+
}
21+
22+
function error(e) {
23+
console.log(e);
24+
errorElm.classList.remove('visually-hidden');
25+
errorElm.classList.add('alert', 'alert-danger');
26+
errorElm.textContent = e.message;
27+
}
28+
29+
function noerror() {
30+
errorElm.classList.add('visually-hidden');
31+
errorElm.classList.remove('alert', 'alert-danger');
32+
}
33+
34+
// Run a command in the database
35+
function execute(commands) {
36+
tic();
37+
worker.onmessage = function (event) {
38+
var results = event.data.results;
39+
40+
toc("Executing SQL");
41+
if (!results) {
42+
error({message: event.data.error});
43+
return;
44+
}
45+
46+
tic();
47+
outputElm.innerHTML = "";
48+
for (var i = 0; i < results.length; i++) {
49+
outputElm.appendChild(tableCreate(results[i].columns, results[i].values));
50+
}
51+
toc("Displaying results");
52+
}
53+
worker.postMessage({ action: 'exec', sql: commands });
54+
outputElm.textContent = "Fetching results...";
55+
}
56+
57+
// Create an HTML table
58+
var tableCreate = function () {
59+
function valconcat(vals, tagName) {
60+
if (vals.length === 0) return '';
61+
var open = '<' + tagName + '>', close = '</' + tagName + '>';
62+
return open + vals.join(close + open) + close;
63+
}
64+
return function (columns, values) {
65+
var tbl = document.createElement('table');
66+
tbl.classList.add('table', 'table-hover')
67+
var html = '<thead>' + valconcat(columns, 'th') + '</thead>';
68+
var rows = values.map(function (v) { return valconcat(v, 'td'); });
69+
html += '<tbody>' + valconcat(rows, 'tr') + '</tbody>';
70+
tbl.innerHTML = html;
71+
return tbl;
72+
}
73+
}();
74+
75+
// Execute the commands when the button is clicked
76+
function execEditorContents() {
77+
noerror()
78+
execute(editor.getValue() + ';');
79+
}
80+
execBtn.addEventListener("click", execEditorContents, true);
81+
82+
// Performance measurement functions
83+
var tictime;
84+
if (!window.performance || !performance.now) { window.performance = { now: Date.now } }
85+
function tic() { tictime = performance.now() }
86+
function toc(msg) {
87+
var dt = performance.now() - tictime;
88+
console.log((msg || 'toc') + ": " + dt + "ms");
89+
}
90+
91+
// Add syntax highlihjting to the textarea
92+
var editor = CodeMirror.fromTextArea(commandsElm, {
93+
mode: 'text/x-sql',
94+
viewportMargin: Infinity,
95+
autofocus: true,
96+
indentWithTabs: true,
97+
smartIndent: true,
98+
lineNumbers: true,
99+
matchBrackets: true,
100+
autofocus: true,
101+
extraKeys: {
102+
"Ctrl-Enter": execEditorContents,
103+
"Ctrl-S": savedb,
104+
}
105+
});
106+
107+
// Load a db from a file
108+
var dbFile = new FileReader();
109+
var defaultQuery = "SELECT `name`, `sql`\n FROM `sqlite_master`\n WHERE type='table';"
110+
111+
dbFile.onload = function () {
112+
worker.onmessage = function () {
113+
toc("Loading database from file");
114+
// Show the schema of the loaded database
115+
editor.setValue(localStorage.getItem('lastQuery') || defaultQuery);
116+
execEditorContents();
117+
118+
uploadSection.classList.add('visually-hidden');
119+
querySection.classList.remove('visually-hidden');
120+
noerror();
121+
};
122+
tic();
123+
try {
124+
worker.postMessage({ action: 'open', buffer: dbFile.result }, [dbFile.result]);
125+
}
126+
catch (exception) {
127+
worker.postMessage({ action: 'open', buffer: dbFile.result });
128+
}
129+
}
130+
131+
132+
function init() {
133+
let dropzoneElement = new Dropzone("#demo-upload");
134+
135+
136+
dropzoneElement.uploadFiles = function(files) {
137+
var self = this,
138+
minSteps = 6,
139+
maxSteps = 60,
140+
timeBetweenSteps = 1,
141+
bytesPerStep = 1000000;
142+
143+
for (var i = 0; i < files.length; i++) {
144+
145+
var file = files[i];
146+
totalSteps = Math.round(Math.min(maxSteps, Math.max(minSteps, file.size / bytesPerStep)));
147+
148+
for (var step = 0; step < totalSteps; step++) {
149+
var duration = timeBetweenSteps * (step + 1);
150+
setTimeout(function(file, totalSteps, step) {
151+
return function() {
152+
file.upload = {
153+
progress: 100 * (step + 1) / totalSteps,
154+
total: file.size,
155+
bytesSent: (step + 1) * file.size / totalSteps
156+
};
157+
158+
self.emit('uploadprogress', file, file.upload.progress, file.upload.bytesSent);
159+
if (file.upload.progress == 100) {
160+
file.status = Dropzone.SUCCESS;
161+
self.emit("success", file, 'success', null);
162+
self.emit("complete", file);
163+
self.processQueue();
164+
}
165+
};
166+
}(file, totalSteps, step), duration);
167+
}
168+
dbFile.readAsArrayBuffer(files[0]);
169+
}
170+
}
171+
172+
function saveQuery(e) {
173+
if (e.getValue()) {
174+
localStorage.setItem('lastQuery', e.getValue());
175+
}
176+
}
177+
178+
editor.setValue(localStorage.getItem('lastQuery') || defaultQuery);
179+
editor.on("changes", saveQuery);
180+
}
181+
182+
Dropzone.autoDiscover = false;
183+
document.addEventListener("DOMContentLoaded", init);
184+
185+
// Save the db to a file
186+
function savedb() {
187+
worker.onmessage = function (event) {
188+
toc("Exporting the database");
189+
var arraybuff = event.data.buffer;
190+
var blob = new Blob([arraybuff]);
191+
var a = document.createElement("a");
192+
document.body.appendChild(a);
193+
a.href = window.URL.createObjectURL(blob);
194+
a.download = "sql.db";
195+
a.onclick = function () {
196+
setTimeout(function () {
197+
window.URL.revokeObjectURL(a.href);
198+
}, 1500);
199+
};
200+
a.click();
201+
};
202+
tic();
203+
worker.postMessage({ action: 'export' });
204+
}
205+
206+
savedbElm.addEventListener("click", savedb, true);

‎sql-wasm.wasm‎

1.08 MB
Binary file not shown.

‎sql.html‎

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<!doctype html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<title>משחקים ב־SQL</title>
8+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.1/codemirror.css">
9+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/css/bootstrap.min.css" integrity="sha384-DhY6onE6f3zzKbjUPRc2hOzGAdEf4/Dz+WJwBvEYL/lkkIsI3ihufq9hk9K4lVoK" crossorigin="anonymous">
10+
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.1/codemirror.js"></script>
11+
<style>
12+
h1, h2 h3, p, form, main, footer {
13+
direction: rtl;
14+
text-align: right;
15+
}
16+
17+
textarea, #code-section, table, table * {
18+
direction: ltr;
19+
text-align: left;
20+
}
21+
22+
#results table {
23+
width: 100%;
24+
}
25+
26+
h1, h2, h3 {
27+
text-align: center;
28+
margin-top: 1.5rem;
29+
margin-bottom: 1.5rem;
30+
}
31+
32+
footer {
33+
position: fixed;
34+
left: 0;
35+
bottom: 0;
36+
padding: 0.5rem;
37+
width: 100%;
38+
text-align: center;
39+
background: #aaa;
40+
color: white;
41+
margin-top: 2em;
42+
text-decoration: white;
43+
}
44+
45+
footer > a:link {
46+
color: white;
47+
}
48+
49+
footer > a:visited {
50+
color: #d9d9d9;
51+
}
52+
53+
.dropzone {
54+
align-items: center;
55+
background: white;
56+
border-radius: 5px !important;
57+
border: 2px dashed #0087f7 !important;
58+
display: flex;
59+
justify-content: center;
60+
min-height: 30vh !important;
61+
}
62+
63+
#dropzone {
64+
width: 60%;
65+
height: 60%;
66+
margin-right: auto;
67+
margin-left: auto;
68+
margin-top: 5%;
69+
}
70+
71+
#buttons {
72+
margin: 1rem;
73+
margin-left: auto;
74+
margin-right: auto;
75+
padding: 0.5rem;
76+
width: max-content;
77+
}
78+
79+
#error {
80+
width: 60%;
81+
margin-top: 3rem;
82+
margin-left: auto;
83+
margin-right: auto;
84+
text-align: left;
85+
}
86+
87+
#results {
88+
margin-bottom: 3rem;
89+
}
90+
</style>
91+
<link rel="stylesheet" href="dropzone.min.css">
92+
</head>
93+
<body>
94+
<div class="container">
95+
<h1>הריצו את ה־SQL שלכם</h1>
96+
97+
<main>
98+
<div id="dropzone">
99+
<form action="/upload" class="dropzone needsclick dz-clickable" id="demo-upload">
100+
<div class="dz-message needsclick">
101+
<button type="button" name='file' id='dbfile' class="dz-button">גררו לכאן את קובץ מסד הנתונים, או לחצו ובחרו אותו מהמחשב שלכם.</button>
102+
</div>
103+
</form>
104+
</div>
105+
<div id="query" class="visually-hidden">
106+
<label for='commands'>הזינו שאילתה:</label>
107+
<br>
108+
109+
<div id="code-section">
110+
<textarea id="commands">SELECT * FROM movies;</textarea>
111+
</div>
112+
113+
114+
<div id="buttons">
115+
<button id="execute" class="btn btn-primary">הריצו</button>
116+
<button id='savedb' class="btn btn-secondary">שמרו</button>
117+
</div>
118+
</div>
119+
120+
<div id="results">
121+
<div id="error" class="error" role="alert"></div>
122+
<pre id="output"></pre>
123+
</div>
124+
</main>
125+
126+
127+
<footer>
128+
אנחנו משתמשים ב־<a href='https://github.com/sql-js/sql.js'>sql.js</a> כמנוע.
129+
רוב ה־GUI נכתב על־ידי ים מסיקה, עבור קורס פייתון (<a href='https://github.com/PythonFreeCourse/sql-js-gui'>sql-js-gui</a>).
130+
</footer>
131+
132+
</div>
133+
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.1/mode/sql/sql.min.js"></script>
134+
<script type="text/javascript" src="dropzone.min.js"></script>
135+
<script type="text/javascript" src="gui.js"></script>
136+
</body>
137+
</html>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /