Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
View
1 TODO.md
@@ -4,7 +4,6 @@
* Input validation
* Data download
-* Cancelable queries
## Eventually (1.1 or later)
View
6 lib/oculus/connection/mysql2.rb
@@ -9,10 +9,14 @@ def initialize(options = {})
def execute(sql)
results = @connection.query(sql)
- [results.fields] + results.map(&:values)
+ [results.fields] + results.map(&:values) if results
rescue ::Mysql2::Error => e
raise Connection::Error.new(e.message)
end
+
+ def thread_id
+ @connection.thread_id
+ end
end
end
end
View
4 lib/oculus/query.rb
@@ -7,6 +7,7 @@ class Query
attr_accessor :results
attr_accessor :error
attr_accessor :date
+ attr_accessor :thread_id
def initialize(attributes = {})
attributes.each do |attr, value|
@@ -19,7 +20,8 @@ def attributes
:description => description,
:author => author,
:query => query,
- :date => date
+ :date => date,
+ :thread_id => thread_id
}
attrs[:error] = error if error
attrs
View
12 lib/oculus/server.rb
@@ -22,13 +22,21 @@ class Server < Sinatra::Base
erb :index
end
+ post '/queries/:id/cancel' do
+ query = Oculus::Query.find(params[:id])
+ connection = Oculus::Connection::Mysql2.new(Oculus.connection_options)
+ connection.execute("KILL QUERY #{query.thread_id}")
+ [200, "OK"]
+ end
+
post '/queries' do
+ connection = Oculus::Connection::Mysql2.new(Oculus.connection_options)
query = Oculus::Query.create(:author => params[:author],
:description => params[:description],
- :query => params[:query])
+ :query => params[:query],
+ :thread_id => connection.thread_id)
pid = fork do
- connection = Oculus::Connection::Mysql2.new(Oculus.connection_options)
query.execute(connection)
query.save
end
View
5 lib/oculus/server/public/css/style.css
@@ -93,3 +93,8 @@ body {
.status .indicator-loading {
background: #fc0;
}
+
+#query-actions {
+ text-align: right;
+ margin-top: 10px;
+}
View
19 lib/oculus/server/views/loading.erb
@@ -2,6 +2,21 @@
var queryId = window.location.href.match(/\/queries\/([0-9]+)\/loading/)[1];
var statusUrl = '/queries/' + queryId + '/ready';
var resultsUrl = '/queries/' + queryId;
+ var cancelUrl = '/queries/' + queryId + '/cancel';
+
+ $(function() {
+ $('#query-actions .cancel').click(function(e) {
+ var btn = $(this);
+
+ if (!btn.hasClass('disabled')) {
+ btn.addClass('disabled');
+
+ $.post(cancelUrl, function() {
+ window.location.href = resultsUrl;
+ });
+ }
+ });
+ });
function poll() {
$.ajax({
@@ -70,3 +85,7 @@
<div id="elapsed-time"></div>
<pre class="cm-s-default"><%= @query.query %></pre>
+
+<div id="query-actions">
+ <a class="btn cancel"><i class="icon-remove"></i> Cancel</a>
+</div>
View
27 spec/connection_spec.rb
@@ -26,9 +26,36 @@
subject.execute("SELECT * FROM oculus_users").should == [['id', 'name'], [1, 'Paul'], [2, 'Amy'], [3, 'Peter']]
end
+ it "returns nil for queries that don't return result sets" do
+ query_connection = Mysql2::Client.new(:host => "localhost", :database => "test")
+ thread_id = query_connection.thread_id
+ Thread.new {
+ query_connection.execute("SELECT * FROM oculus_users WHERE SLEEP(2)")
+ }
+
+ sleep 0.1
+ subject.execute("KILL QUERY #{thread_id}").should be_nil
+ end
+
it "raises a Connection::Error on syntax errors" do
lambda {
subject.execute("FOO BAZ QUUX")
}.should raise_error(Oculus::Connection::Error)
end
+
+ it "raises a Connection::Error when the query is interrupted" do
+ thread_id = subject.thread_id
+ Thread.new {
+ sleep 0.1
+ Mysql2::Client.new(:host => "localhost", :username => "root").query("KILL QUERY #{thread_id}")
+ }
+
+ lambda {
+ subject.execute("SELECT * FROM oculus_users WHERE SLEEP(2)")
+ }.should raise_error(Oculus::Connection::Error)
+ end
+
+ it "provides the connection's thread_id" do
+ subject.thread_id.should be_an Integer
+ end
end
View
6 spec/file_store_spec.rb
@@ -7,6 +7,7 @@
Oculus::Query.new(:description => "All users",
:query => "SELECT * FROM oculus_users",
:author => "Paul",
+ :thread_id => 42,
:results => [['id', 'users'], ['1', 'Paul'], ['2', 'Amy']])
end
@@ -14,6 +15,7 @@
Oculus::Query.new(:description => "Admin users",
:query => "SELECT * FROM oculus_users WHERE is_admin = 1",
:author => "Paul",
+ :thread_id => 42,
:results => [['id', 'users'], ['2', 'Amy']])
end
@@ -21,6 +23,7 @@
Oculus::Query.new(:description => "Admin users",
:query => "FOO BAZ QUUX",
:author => "Paul",
+ :thread_id => 42,
:error => "You have an error in your SQL syntax")
end
@@ -40,6 +43,7 @@
subject.load_query(query.id).date.should == query.date
subject.load_query(query.id).author.should == query.author
subject.load_query(query.id).id.should == query.id
+ subject.load_query(query.id).thread_id.should == query.thread_id
end
it "round-trips a query with an error to disk" do
@@ -50,6 +54,7 @@
subject.load_query(broken_query.id).date.should == broken_query.date
subject.load_query(broken_query.id).author.should == broken_query.author
subject.load_query(broken_query.id).id.should == broken_query.id
+ subject.load_query(broken_query.id).thread_id.should == broken_query.thread_id
end
it "round-trips a query to disk" do
@@ -59,6 +64,7 @@
subject.load_query(query.id).date.should == query.date
subject.load_query(query.id).author.should == query.author
subject.load_query(query.id).id.should == query.id
+ subject.load_query(query.id).thread_id.should == query.thread_id
end
it "doesn't overwrite an existing query id when saving" do
View
5 spec/query_spec.rb
@@ -32,6 +32,11 @@
query.query.should == 'SELECT * FROM users'
end
+ it "stores the querying connection's thread ID" do
+ query = Oculus::Query.new(:thread_id => 42)
+ query.thread_id.should == 42
+ end
+
it "has a date" do
query = Oculus::Query.new
query.date.should be nil

No commit comments for this range

Something went wrong with that request. Please try again.