mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-01 03:52:15 +00:00
Fix race condition; history and sharing capabilities
This commit is contained in:
parent
711f64048b
commit
2c982b4ccf
@ -30,17 +30,6 @@
|
|||||||
It can be done in background, e.g. wait 100 ms after address/credentials change and do the check.
|
It can be done in background, e.g. wait 100 ms after address/credentials change and do the check.
|
||||||
Also it can provide visual indication that credentials are correct.
|
Also it can provide visual indication that credentials are correct.
|
||||||
|
|
||||||
3. Add history in localstorage. Integrate with history API.
|
|
||||||
There can be a counter in localstorage, that will be appended to location #fragment.
|
|
||||||
The 'back', 'forward' buttons in browser should work.
|
|
||||||
Also there should be UI element to list all the queries from history and select from the list.
|
|
||||||
|
|
||||||
4. Trivial sharing capabilities.
|
|
||||||
Sharing is only possible when system.query_log is accessible. Read the X-ClickHouse-QueryId from the response.
|
|
||||||
Share button will: - emit SYSTEM FLUSH LOGS if not readonly; - find the query in the query_log;
|
|
||||||
- generate an URL with the query id and: server address if not equal to the URL's host; user name if not default;
|
|
||||||
indication that password should be entered in case of non-empty password.
|
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@ -299,14 +288,21 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
/// Incremental request number. When response is received,
|
||||||
|
/// if it's request number does not equal to the current request number, response will be ignored.
|
||||||
|
/// This is to avoid race conditions.
|
||||||
|
var request_num = 0;
|
||||||
|
|
||||||
|
/// Save query in history only if it is different.
|
||||||
|
var previous_query = '';
|
||||||
|
|
||||||
/// Substitute the address of the server where the page is served.
|
/// Substitute the address of the server where the page is served.
|
||||||
if (location.protocol != 'file:') {
|
if (location.protocol != 'file:') {
|
||||||
document.getElementById('url').value = location.origin;
|
document.getElementById('url').value = location.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
function post()
|
function postImpl(posted_request_num, query)
|
||||||
{
|
{
|
||||||
/// TODO: Avoid race condition on subsequent requests when responses may come out of order.
|
|
||||||
/// TODO: Check if URL already contains query string (append parameters).
|
/// TODO: Check if URL already contains query string (append parameters).
|
||||||
|
|
||||||
var url = document.getElementById('url').value +
|
var url = document.getElementById('url').value +
|
||||||
@ -318,7 +314,6 @@
|
|||||||
/// Safety settings to prevent results that browser cannot display.
|
/// Safety settings to prevent results that browser cannot display.
|
||||||
'&max_result_rows=1000&max_result_bytes=10000000&result_overflow_mode=break';
|
'&max_result_rows=1000&max_result_bytes=10000000&result_overflow_mode=break';
|
||||||
|
|
||||||
var query = document.getElementById('query').value;
|
|
||||||
var xhr = new XMLHttpRequest;
|
var xhr = new XMLHttpRequest;
|
||||||
|
|
||||||
xhr.open('POST', url, true);
|
xhr.open('POST', url, true);
|
||||||
@ -326,18 +321,25 @@
|
|||||||
|
|
||||||
xhr.onreadystatechange = function()
|
xhr.onreadystatechange = function()
|
||||||
{
|
{
|
||||||
if (this.readyState === XMLHttpRequest.DONE) {
|
if (posted_request_num != request_num) {
|
||||||
if (this.status === 200) {
|
return;
|
||||||
var json;
|
} else if (this.readyState === XMLHttpRequest.DONE) {
|
||||||
try { json = JSON.parse(this.response); } catch (e) {}
|
renderResponse(this.status, this.response);
|
||||||
if (json !== undefined && json.statistics !== undefined) {
|
|
||||||
renderResult(json);
|
/// The query is saved in browser history (in state JSON object)
|
||||||
} else {
|
/// as well as in URL fragment identifier.
|
||||||
renderUnparsedResult(this.response);
|
if (query != previous_query) {
|
||||||
}
|
previous_query = query;
|
||||||
} else {
|
var title = "ClickHouse Query: " + query;
|
||||||
/// TODO: Proper rendering of network errors.
|
history.pushState(
|
||||||
renderError(this.response);
|
{
|
||||||
|
query: query,
|
||||||
|
status: this.status,
|
||||||
|
response: this.response.length > 100000 ? null : this.response /// Lower than the browser's limit.
|
||||||
|
},
|
||||||
|
title,
|
||||||
|
window.location.pathname + '#' + window.btoa(query));
|
||||||
|
document.title = title;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//console.log(this);
|
//console.log(this);
|
||||||
@ -345,6 +347,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderResponse(status, response) {
|
||||||
|
if (status === 200) {
|
||||||
|
var json;
|
||||||
|
try { json = JSON.parse(response); } catch (e) {}
|
||||||
|
if (json !== undefined && json.statistics !== undefined) {
|
||||||
|
renderResult(json);
|
||||||
|
} else {
|
||||||
|
renderUnparsedResult(response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/// TODO: Proper rendering of network errors.
|
||||||
|
renderError(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onpopstate = function(event) {
|
||||||
|
if (!event.state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.getElementById('query').value = event.state.query;
|
||||||
|
if (!event.state.response) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
renderResponse(event.state.status, event.state.response);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (window.location.hash) {
|
||||||
|
document.getElementById('query').value = window.atob(window.location.hash.substr(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function post()
|
||||||
|
{
|
||||||
|
++request_num;
|
||||||
|
var query = document.getElementById('query').value;
|
||||||
|
postImpl(request_num, query);
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('run').onclick = function()
|
document.getElementById('run').onclick = function()
|
||||||
{
|
{
|
||||||
post();
|
post();
|
||||||
|
Loading…
Reference in New Issue
Block a user