FEATURE: Move query limit to hidden site setting (#153)
Previously the `QUERY_RESULT_DEFAULT_LIMIT` const was used to limit the number of query results. This commit adds the `data_explorer_query_result_limit` site setting which defaults to 1000 and has a max of 10000 which matches the const `QUERY_RESULT_MAX_LIMIT`.
This commit is contained in:
parent
8aca7767e2
commit
70b973ea9a
|
@ -181,7 +181,7 @@ class DataExplorer::QueryController < ::ApplicationController
|
||||||
result_count: pg_result.values.length || 0,
|
result_count: pg_result.values.length || 0,
|
||||||
params: query_params,
|
params: query_params,
|
||||||
columns: cols,
|
columns: cols,
|
||||||
default_limit: DataExplorer::QUERY_RESULT_DEFAULT_LIMIT
|
default_limit: SiteSetting.data_explorer_query_result_limit
|
||||||
}
|
}
|
||||||
json[:explain] = result[:explain] if opts[:explain]
|
json[:explain] = result[:explain] if opts[:explain]
|
||||||
|
|
||||||
|
|
|
@ -2,3 +2,7 @@ plugins:
|
||||||
data_explorer_enabled:
|
data_explorer_enabled:
|
||||||
default: false
|
default: false
|
||||||
client: true
|
client: true
|
||||||
|
data_explorer_query_result_limit:
|
||||||
|
default: 1000
|
||||||
|
hidden: true
|
||||||
|
max: 10000
|
||||||
|
|
|
@ -25,7 +25,8 @@ end
|
||||||
add_admin_route 'explorer.title', 'explorer'
|
add_admin_route 'explorer.title', 'explorer'
|
||||||
|
|
||||||
module ::DataExplorer
|
module ::DataExplorer
|
||||||
QUERY_RESULT_DEFAULT_LIMIT = 1000
|
# This should always match the max value for the data_explorer_query_result_limit
|
||||||
|
# site setting.
|
||||||
QUERY_RESULT_MAX_LIMIT = 10000
|
QUERY_RESULT_MAX_LIMIT = 10000
|
||||||
|
|
||||||
def self.plugin_name
|
def self.plugin_name
|
||||||
|
@ -117,7 +118,7 @@ after_initialize do
|
||||||
WITH query AS (
|
WITH query AS (
|
||||||
#{query.sql}
|
#{query.sql}
|
||||||
) SELECT * FROM query
|
) SELECT * FROM query
|
||||||
LIMIT #{opts[:limit] || DataExplorer::QUERY_RESULT_DEFAULT_LIMIT}
|
LIMIT #{opts[:limit] || SiteSetting.data_explorer_query_result_limit}
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
time_start = Time.now
|
time_start = Time.now
|
||||||
|
|
|
@ -97,8 +97,8 @@ describe DataExplorer::QueryController do
|
||||||
post :run, params: { id: id, _params: MultiJson.dump(params) }, format: :json
|
post :run, params: { id: id, _params: MultiJson.dump(params) }, format: :json
|
||||||
end
|
end
|
||||||
it "can run queries" do
|
it "can run queries" do
|
||||||
q = make_query('SELECT 23 as my_value')
|
query = make_query('SELECT 23 as my_value')
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(response_json['success']).to eq(true)
|
expect(response_json['success']).to eq(true)
|
||||||
expect(response_json['errors']).to eq([])
|
expect(response_json['errors']).to eq([])
|
||||||
|
@ -107,20 +107,20 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can process parameters" do
|
it "can process parameters" do
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
-- [params]
|
-- [params]
|
||||||
-- int :foo = 34
|
-- int :foo = 34
|
||||||
SELECT :foo as my_value
|
SELECT :foo as my_value
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id, foo: 23
|
run_query query.id, foo: 23
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(response_json['errors']).to eq([])
|
expect(response_json['errors']).to eq([])
|
||||||
expect(response_json['success']).to eq(true)
|
expect(response_json['success']).to eq(true)
|
||||||
expect(response_json['columns']).to eq(['my_value'])
|
expect(response_json['columns']).to eq(['my_value'])
|
||||||
expect(response_json['rows']).to eq([[23]])
|
expect(response_json['rows']).to eq([[23]])
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(response_json['errors']).to eq([])
|
expect(response_json['errors']).to eq([])
|
||||||
expect(response_json['success']).to eq(true)
|
expect(response_json['success']).to eq(true)
|
||||||
|
@ -128,7 +128,7 @@ describe DataExplorer::QueryController do
|
||||||
expect(response_json['rows']).to eq([[34]])
|
expect(response_json['rows']).to eq([[34]])
|
||||||
|
|
||||||
# 2.3 is not an integer
|
# 2.3 is not an integer
|
||||||
run_query q.id, foo: '2.3'
|
run_query query.id, foo: '2.3'
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
|
@ -138,12 +138,12 @@ describe DataExplorer::QueryController do
|
||||||
it "doesn't allow you to modify the database #1" do
|
it "doesn't allow you to modify the database #1" do
|
||||||
p = create_post
|
p = create_post
|
||||||
|
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
UPDATE posts SET cooked = '<p>you may already be a winner!</p>' WHERE id = #{p.id}
|
UPDATE posts SET cooked = '<p>you may already be a winner!</p>' WHERE id = #{p.id}
|
||||||
RETURNING id
|
RETURNING id
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
p.reload
|
p.reload
|
||||||
|
|
||||||
# Manual Test - comment out the following lines:
|
# Manual Test - comment out the following lines:
|
||||||
|
@ -160,7 +160,7 @@ describe DataExplorer::QueryController do
|
||||||
it "doesn't allow you to modify the database #2" do
|
it "doesn't allow you to modify the database #2" do
|
||||||
p = create_post
|
p = create_post
|
||||||
|
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
SELECT 1
|
SELECT 1
|
||||||
)
|
)
|
||||||
SELECT * FROM query;
|
SELECT * FROM query;
|
||||||
|
@ -173,7 +173,7 @@ describe DataExplorer::QueryController do
|
||||||
SELECT 1
|
SELECT 1
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
p.reload
|
p.reload
|
||||||
|
|
||||||
# Manual Test - change out the following line:
|
# Manual Test - change out the following line:
|
||||||
|
@ -195,11 +195,11 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't allow you to lock rows" do
|
it "doesn't allow you to lock rows" do
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
SELECT id FROM posts FOR UPDATE
|
SELECT id FROM posts FOR UPDATE
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
|
@ -207,11 +207,11 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't allow you to create a table" do
|
it "doesn't allow you to create a table" do
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
CREATE TABLE mytable (id serial)
|
CREATE TABLE mytable (id serial)
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
|
@ -219,31 +219,31 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't allow you to break the transaction" do
|
it "doesn't allow you to break the transaction" do
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
COMMIT
|
COMMIT
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
expect(response_json['errors'].first).to match(/syntax error/)
|
expect(response_json['errors'].first).to match(/syntax error/)
|
||||||
|
|
||||||
q.sql = <<~SQL
|
query.sql = <<~SQL
|
||||||
)
|
)
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
expect(response_json['errors'].first).to match(/syntax error/)
|
expect(response_json['errors'].first).to match(/syntax error/)
|
||||||
|
|
||||||
q.sql = <<~SQL
|
query.sql = <<~SQL
|
||||||
RELEASE SAVEPOINT active_record_1
|
RELEASE SAVEPOINT active_record_1
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response_json['errors']).to_not eq([])
|
expect(response_json['errors']).to_not eq([])
|
||||||
expect(response_json['success']).to eq(false)
|
expect(response_json['success']).to eq(false)
|
||||||
|
@ -251,8 +251,8 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can export data in CSV format" do
|
it "can export data in CSV format" do
|
||||||
q = make_query('SELECT 23 as my_value')
|
query = make_query('SELECT 23 as my_value')
|
||||||
post :run, params: { id: q.id, download: 1 }, format: :csv
|
post :run, params: { id: query.id, download: 1 }, format: :csv
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -264,27 +264,19 @@ describe DataExplorer::QueryController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should limit the results in JSON response" do
|
it "should limit the results in JSON response" do
|
||||||
begin
|
SiteSetting.data_explorer_query_result_limit = 2
|
||||||
original_const = DataExplorer::QUERY_RESULT_DEFAULT_LIMIT
|
query = make_query <<~SQL
|
||||||
DataExplorer.send(:remove_const, "QUERY_RESULT_DEFAULT_LIMIT")
|
|
||||||
DataExplorer.const_set("QUERY_RESULT_DEFAULT_LIMIT", 2)
|
|
||||||
|
|
||||||
q = make_query <<~SQL
|
|
||||||
SELECT id FROM posts
|
SELECT id FROM posts
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
run_query q.id
|
run_query query.id
|
||||||
expect(response_json['rows'].count).to eq(2)
|
expect(response_json['rows'].count).to eq(2)
|
||||||
|
|
||||||
post :run, params: { id: q.id, limit: 1 }, format: :json
|
post :run, params: { id: query.id, limit: 1 }, format: :json
|
||||||
expect(response_json['rows'].count).to eq(1)
|
expect(response_json['rows'].count).to eq(1)
|
||||||
|
|
||||||
post :run, params: { id: q.id, limit: "ALL" }, format: :json
|
post :run, params: { id: query.id, limit: "ALL" }, format: :json
|
||||||
expect(response_json['rows'].count).to eq(3)
|
expect(response_json['rows'].count).to eq(3)
|
||||||
ensure
|
|
||||||
DataExplorer.send(:remove_const, "QUERY_RESULT_DEFAULT_LIMIT")
|
|
||||||
DataExplorer.const_set("QUERY_RESULT_DEFAULT_LIMIT", original_const)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should limit the results in CSV download" do
|
it "should limit the results in CSV download" do
|
||||||
|
@ -295,18 +287,18 @@ describe DataExplorer::QueryController do
|
||||||
|
|
||||||
ids = Post.order(:id).pluck(:id)
|
ids = Post.order(:id).pluck(:id)
|
||||||
|
|
||||||
q = make_query <<~SQL
|
query = make_query <<~SQL
|
||||||
SELECT id FROM posts
|
SELECT id FROM posts
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
post :run, params: { id: q.id, download: 1 }, format: :csv
|
post :run, params: { id: query.id, download: 1 }, format: :csv
|
||||||
expect(response.body.split("\n").count).to eq(3)
|
expect(response.body.split("\n").count).to eq(3)
|
||||||
|
|
||||||
post :run, params: { id: q.id, download: 1, limit: 1 }, format: :csv
|
post :run, params: { id: query.id, download: 1, limit: 1 }, format: :csv
|
||||||
expect(response.body.split("\n").count).to eq(2)
|
expect(response.body.split("\n").count).to eq(2)
|
||||||
|
|
||||||
# The value `ALL` is not supported in csv exports.
|
# The value `ALL` is not supported in csv exports.
|
||||||
post :run, params: { id: q.id, download: 1, limit: "ALL" }, format: :csv
|
post :run, params: { id: query.id, download: 1, limit: "ALL" }, format: :csv
|
||||||
expect(response.body.split("\n").count).to eq(1)
|
expect(response.body.split("\n").count).to eq(1)
|
||||||
ensure
|
ensure
|
||||||
DataExplorer.send(:remove_const, "QUERY_RESULT_MAX_LIMIT")
|
DataExplorer.send(:remove_const, "QUERY_RESULT_MAX_LIMIT")
|
||||||
|
|
Loading…
Reference in New Issue