adhoq 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +80 -0
  4. data/Rakefile +28 -0
  5. data/app/assets/javascripts/adhoq/application.js +19 -0
  6. data/app/assets/javascripts/adhoq/bootstrap-sprockets.js +12 -0
  7. data/app/assets/javascripts/adhoq/bootstrap.js +2107 -0
  8. data/app/assets/javascripts/adhoq/bootstrap/affix.js +142 -0
  9. data/app/assets/javascripts/adhoq/bootstrap/alert.js +92 -0
  10. data/app/assets/javascripts/adhoq/bootstrap/button.js +110 -0
  11. data/app/assets/javascripts/adhoq/bootstrap/carousel.js +223 -0
  12. data/app/assets/javascripts/adhoq/bootstrap/collapse.js +170 -0
  13. data/app/assets/javascripts/adhoq/bootstrap/dropdown.js +151 -0
  14. data/app/assets/javascripts/adhoq/bootstrap/modal.js +280 -0
  15. data/app/assets/javascripts/adhoq/bootstrap/popover.js +113 -0
  16. data/app/assets/javascripts/adhoq/bootstrap/scrollspy.js +170 -0
  17. data/app/assets/javascripts/adhoq/bootstrap/tab.js +128 -0
  18. data/app/assets/javascripts/adhoq/bootstrap/tooltip.js +457 -0
  19. data/app/assets/javascripts/adhoq/bootstrap/transition.js +59 -0
  20. data/app/assets/javascripts/adhoq/previewer.js.coffee +25 -0
  21. data/app/assets/stylesheets/adhoq/_bootstrap-compass.scss +7 -0
  22. data/app/assets/stylesheets/adhoq/_bootstrap-mincer.scss +17 -0
  23. data/app/assets/stylesheets/adhoq/_bootstrap-sprockets.scss +7 -0
  24. data/app/assets/stylesheets/adhoq/adhoq.css.sass +57 -0
  25. data/app/assets/stylesheets/adhoq/application.css +16 -0
  26. data/app/assets/stylesheets/adhoq/bootstrap.scss +50 -0
  27. data/app/assets/stylesheets/adhoq/bootstrap/_alerts.scss +68 -0
  28. data/app/assets/stylesheets/adhoq/bootstrap/_badges.scss +57 -0
  29. data/app/assets/stylesheets/adhoq/bootstrap/_breadcrumbs.scss +26 -0
  30. data/app/assets/stylesheets/adhoq/bootstrap/_button-groups.scss +240 -0
  31. data/app/assets/stylesheets/adhoq/bootstrap/_buttons.scss +157 -0
  32. data/app/assets/stylesheets/adhoq/bootstrap/_carousel.scss +243 -0
  33. data/app/assets/stylesheets/adhoq/bootstrap/_close.scss +35 -0
  34. data/app/assets/stylesheets/adhoq/bootstrap/_code.scss +68 -0
  35. data/app/assets/stylesheets/adhoq/bootstrap/_component-animations.scss +35 -0
  36. data/app/assets/stylesheets/adhoq/bootstrap/_dropdowns.scss +215 -0
  37. data/app/assets/stylesheets/adhoq/bootstrap/_forms.scss +538 -0
  38. data/app/assets/stylesheets/adhoq/bootstrap/_glyphicons.scss +237 -0
  39. data/app/assets/stylesheets/adhoq/bootstrap/_grid.scss +84 -0
  40. data/app/assets/stylesheets/adhoq/bootstrap/_input-groups.scss +166 -0
  41. data/app/assets/stylesheets/adhoq/bootstrap/_jumbotron.scss +48 -0
  42. data/app/assets/stylesheets/adhoq/bootstrap/_labels.scss +66 -0
  43. data/app/assets/stylesheets/adhoq/bootstrap/_list-group.scss +131 -0
  44. data/app/assets/stylesheets/adhoq/bootstrap/_media.scss +56 -0
  45. data/app/assets/stylesheets/adhoq/bootstrap/_mixins.scss +39 -0
  46. data/app/assets/stylesheets/adhoq/bootstrap/_modals.scss +150 -0
  47. data/app/assets/stylesheets/adhoq/bootstrap/_navbar.scss +659 -0
  48. data/app/assets/stylesheets/adhoq/bootstrap/_navs.scss +242 -0
  49. data/app/assets/stylesheets/adhoq/bootstrap/_normalize.scss +425 -0
  50. data/app/assets/stylesheets/adhoq/bootstrap/_pager.scss +55 -0
  51. data/app/assets/stylesheets/adhoq/bootstrap/_pagination.scss +88 -0
  52. data/app/assets/stylesheets/adhoq/bootstrap/_panels.scss +243 -0
  53. data/app/assets/stylesheets/adhoq/bootstrap/_popovers.scss +133 -0
  54. data/app/assets/stylesheets/adhoq/bootstrap/_print.scss +101 -0
  55. data/app/assets/stylesheets/adhoq/bootstrap/_progress-bars.scss +105 -0
  56. data/app/assets/stylesheets/adhoq/bootstrap/_responsive-embed.scss +34 -0
  57. data/app/assets/stylesheets/adhoq/bootstrap/_responsive-utilities.scss +174 -0
  58. data/app/assets/stylesheets/adhoq/bootstrap/_scaffolding.scss +150 -0
  59. data/app/assets/stylesheets/adhoq/bootstrap/_tables.scss +233 -0
  60. data/app/assets/stylesheets/adhoq/bootstrap/_theme.scss +258 -0
  61. data/app/assets/stylesheets/adhoq/bootstrap/_thumbnails.scss +38 -0
  62. data/app/assets/stylesheets/adhoq/bootstrap/_tooltip.scss +95 -0
  63. data/app/assets/stylesheets/adhoq/bootstrap/_type.scss +304 -0
  64. data/app/assets/stylesheets/adhoq/bootstrap/_utilities.scss +57 -0
  65. data/app/assets/stylesheets/adhoq/bootstrap/_variables.scss +850 -0
  66. data/app/assets/stylesheets/adhoq/bootstrap/_wells.scss +29 -0
  67. data/app/assets/stylesheets/adhoq/bootstrap/bootstrap.scss +50 -0
  68. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_alerts.scss +14 -0
  69. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_background-variant.scss +11 -0
  70. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_border-radius.scss +18 -0
  71. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_buttons.scss +50 -0
  72. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_center-block.scss +7 -0
  73. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_clearfix.scss +22 -0
  74. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_forms.scss +84 -0
  75. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_gradients.scss +58 -0
  76. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_grid-framework.scss +81 -0
  77. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_grid.scss +122 -0
  78. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_hide-text.scss +21 -0
  79. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_image.scss +34 -0
  80. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_labels.scss +12 -0
  81. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_list-group.scss +31 -0
  82. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_nav-divider.scss +10 -0
  83. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  84. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_opacity.scss +8 -0
  85. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_pagination.scss +23 -0
  86. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_panels.scss +24 -0
  87. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_progress-bar.scss +10 -0
  88. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_reset-filter.scss +8 -0
  89. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_resize.scss +6 -0
  90. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_responsive-visibility.scss +21 -0
  91. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_size.scss +10 -0
  92. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_tab-focus.scss +9 -0
  93. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_table-row.scss +28 -0
  94. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_text-emphasis.scss +11 -0
  95. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_text-overflow.scss +8 -0
  96. data/app/assets/stylesheets/adhoq/bootstrap/mixins/_vendor-prefixes.scss +219 -0
  97. data/app/controllers/adhoq/application_controller.rb +5 -0
  98. data/app/controllers/adhoq/authorization_methods.rb +36 -0
  99. data/app/controllers/adhoq/executions_controller.rb +25 -0
  100. data/app/controllers/adhoq/previews_controller.rb +13 -0
  101. data/app/controllers/adhoq/queries_controller.rb +38 -0
  102. data/app/helpers/adhoq/application_helper.rb +11 -0
  103. data/app/models/adhoq/execution.rb +29 -0
  104. data/app/models/adhoq/query.rb +14 -0
  105. data/app/models/adhoq/report.rb +42 -0
  106. data/app/models/adhoq/time_based_orders.rb +9 -0
  107. data/app/views/adhoq/application/_global_nav.html.slim +11 -0
  108. data/app/views/adhoq/application/_sidebar_queries_index.html.slim +10 -0
  109. data/app/views/adhoq/previews/create.html.slim +12 -0
  110. data/app/views/adhoq/previews/statement_invalid.html.slim +5 -0
  111. data/app/views/adhoq/queries/_form.html.slim +38 -0
  112. data/app/views/adhoq/queries/_query.html.slim +43 -0
  113. data/app/views/adhoq/queries/edit.html.slim +2 -0
  114. data/app/views/adhoq/queries/index.html.slim +1 -0
  115. data/app/views/adhoq/queries/new.html.slim +2 -0
  116. data/app/views/adhoq/queries/show.html.slim +1 -0
  117. data/app/views/layouts/adhoq/application.html.slim +18 -0
  118. data/config/routes.rb +9 -0
  119. data/db/migrate/20141003095645_create_adhoq_queries.rb +11 -0
  120. data/db/migrate/20141006014750_create_adhoq_executions.rb +13 -0
  121. data/db/migrate/20141007052308_create_adhoq_reports.rb +12 -0
  122. data/lib/adhoq.rb +13 -0
  123. data/lib/adhoq/configuration.rb +21 -0
  124. data/lib/adhoq/engine.rb +15 -0
  125. data/lib/adhoq/error.rb +4 -0
  126. data/lib/adhoq/executor.rb +27 -0
  127. data/lib/adhoq/global_variable.rb +34 -0
  128. data/lib/adhoq/reporter.rb +5 -0
  129. data/lib/adhoq/reporter/xlsx.rb +32 -0
  130. data/lib/adhoq/result.rb +18 -0
  131. data/lib/adhoq/storage.rb +5 -0
  132. data/lib/adhoq/storage/local_file.rb +45 -0
  133. data/lib/adhoq/version.rb +3 -0
  134. data/lib/tasks/adhoq_tasks.rake +4 -0
  135. data/spec/adhoq/executor_spec.rb +11 -0
  136. data/spec/adhoq/storage_spec.rb +19 -0
  137. data/spec/factories/adhoq_queries.rb +29 -0
  138. data/spec/models/adhoq/execution_spec.rb +4 -0
  139. data/spec/models/adhoq/query_spec.rb +4 -0
  140. data/spec/models/adhoq/report_spec.rb +25 -0
  141. data/spec/spec_helper.rb +36 -0
  142. data/spec/support/have_values_in_xlsx_sheet_matcher.rb +20 -0
  143. metadata +375 -0
@@ -0,0 +1,5 @@
1
+ module Adhoq
2
+ class ApplicationController < ::ApplicationController
3
+ include Adhoq::AuthorizationMethods
4
+ end
5
+ end
@@ -0,0 +1,36 @@
1
+ module Adhoq
2
+ module AuthorizationMethods
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |controller|
6
+ controller.before_action Authorizer.new
7
+
8
+ helper_method :adhoq_current_user
9
+ hide_action :adhoq_current_user
10
+ end
11
+
12
+ class Authorizer
13
+ def before(controller)
14
+ return true if authorization.call(controller)
15
+
16
+ if failure = Adhoq.config.authorization_failure_action
17
+ failure.call(controller)
18
+ else
19
+ controller.send(:render, text: 'No such file or directory', status: :not_found)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def authorization
26
+ @authorization ||= Adhoq.config.callablize(:authorization)
27
+ end
28
+ end
29
+
30
+ def adhoq_current_user
31
+ @_adhoq_current_user_proc ||= Adhoq.config.callablize(:current_user)
32
+
33
+ @_adhoq_current_user_proc.call(self)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module Adhoq
2
+ class ExecutionsController < ApplicationController
3
+ def show
4
+ @execution = current_query.executions.where(id: params[:id], report_format: params[:format]).first!
5
+
6
+ respond_report(@execution.report)
7
+ end
8
+
9
+ def create
10
+ @execution = current_query.execute!(params[:execution][:report_format])
11
+
12
+ redirect_to current_query
13
+ end
14
+
15
+ private
16
+
17
+ def current_query
18
+ @query ||= Adhoq::Query.find(params[:query_id])
19
+ end
20
+
21
+ def respond_report(report)
22
+ send_data report.data.read, type: report.mime_type, filename: report.name, disposition: 'attachment'
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module Adhoq
2
+ class PreviewsController < ApplicationController
3
+ layout false
4
+
5
+ def create
6
+ begin
7
+ @result = Adhoq::Executor.new(params[:query]).execute
8
+ rescue ActiveRecord::StatementInvalid => @statement_invalid
9
+ render 'statement_invalid', status: :unprocessable_entity
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module Adhoq
2
+ class QueriesController < ApplicationController
3
+ def index
4
+ @queries = Adhoq::Query.recent_first
5
+ end
6
+
7
+ def show
8
+ @query = Adhoq::Query.find(params[:id])
9
+ end
10
+
11
+ def new
12
+ @query = Adhoq::Query.new
13
+ end
14
+
15
+ def create
16
+ @query = Adhoq::Query.create!(query_attributes)
17
+
18
+ redirect_to @query
19
+ end
20
+
21
+ def edit
22
+ @query = Adhoq::Query.find(params[:id])
23
+ end
24
+
25
+ def update
26
+ @query = Adhoq::Query.find(params[:id])
27
+ @query.update_attributes!(query_attributes)
28
+
29
+ redirect_to @query
30
+ end
31
+
32
+ private
33
+
34
+ def query_attributes
35
+ params.require(:query).permit(:name, :description, :query)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ module Adhoq
2
+ module ApplicationHelper
3
+ def human(klass, attr = nil)
4
+ if attr
5
+ klass.human_attribute_name(attr)
6
+ else
7
+ klass.model_name.humanize
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ module Adhoq
2
+ class Execution < ActiveRecord::Base
3
+ include Adhoq::TimeBasedOrders
4
+
5
+ belongs_to :query
6
+ has_one :report, dependent: :destroy, inverse_of: :execution
7
+
8
+ def supported_formats
9
+ %w[xlsx]
10
+ end
11
+
12
+ def generate_report!
13
+ build_report.generate!
14
+ end
15
+
16
+ def name
17
+ [query.name, created_at.strftime('%Y%m%d-%H%M%S'), report_format].join('.')
18
+ end
19
+
20
+ def success?
21
+ report.try(:success?)
22
+ end
23
+
24
+ # TODO go decorator or view model or so
25
+ def status_label
26
+ success? ? :success : :failure
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ module Adhoq
2
+ class Query < ActiveRecord::Base
3
+ include Adhoq::TimeBasedOrders
4
+
5
+ has_many :executions, dependent: :destroy, inverse_of: :query
6
+
7
+ def execute!(report_format)
8
+ executions.create! {|exe|
9
+ exe.report_format = report_format
10
+ exe.raw_sql = query
11
+ }.tap(&:generate_report!)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ module Adhoq
2
+ class Report < ActiveRecord::Base
3
+ BUFSIZE = 10.kilobytes.to_i
4
+
5
+ belongs_to :execution
6
+
7
+ delegate :name, to: 'execution'
8
+ delegate :mime_type, to: :reporter
9
+
10
+ def generate!(storage = Adhoq.current_storage)
11
+ self.identifier = generate_and_persist_report!(storage)
12
+ self.generated_at = Time.now
13
+ self.storage = storage.identifier
14
+
15
+ save!
16
+ end
17
+
18
+ def success?
19
+ data.present?
20
+ end
21
+
22
+ def data(storage = Adhoq.current_storage)
23
+ storage.get(identifier)
24
+ end
25
+
26
+ private
27
+
28
+ def reporter
29
+ {'xlsx' => Adhoq::Reporter::Xlsx}[execution.report_format]
30
+ end
31
+
32
+ def generate_and_persist_report!(storage)
33
+ storage.store(".#{execution.report_format}") do |file, *|
34
+ executor = Executor.new(execution.raw_sql)
35
+
36
+ reporter.new(executor.execute).build_report.each(BUFSIZE) do |chunk|
37
+ file.write chunk
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Adhoq
2
+ module TimeBasedOrders
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ scope :recent_first, -> { order("#{quoted_table_name}.updated_at DESC") }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ nav#global-nav.navbar.navbar-default(role='navigation')
2
+ .container-fluid
3
+ .navbar-header
4
+ = link_to 'Adhoq', root_path, class: 'navbar-brand'
5
+ .navbar-collapse.collapse
6
+ ul.nav.navbar-nav.navbar-right
7
+ - if main_app.respond_to?(:root_path)
8
+ li
9
+ = link_to main_app.root_path do
10
+ i.fa.fa-arrow-circle-right.fa-pad-r
11
+ | Main app
@@ -0,0 +1,10 @@
1
+ h2
2
+ | Queries
3
+ = link_to 'Create new', :root, class: 'btn btn-primary new-query'
4
+ ul.queries.list-unstyled
5
+ - Adhoq::Query.recent_first.each do |query|
6
+ li.panel.panel-default[query]
7
+ .panel-heading
8
+ h2= link_to query.name, query_path(query)
9
+ p.panel-body.description= query.description
10
+
@@ -0,0 +1,12 @@
1
+ p.note #{@result.rows.size} rows
2
+
3
+ table.table.table-striped.table-focus
4
+ thead
5
+ tr
6
+ - @result.header.each do |column|
7
+ th= column
8
+ tbody
9
+ - @result.rows.take(100).each do |row|
10
+ tr
11
+ - row.each do |val|
12
+ td= val
@@ -0,0 +1,5 @@
1
+ p.statement-invalid.alert.alert-danger
2
+ strong= @statement_invalid.original_exception.class
3
+ br
4
+ = @statement_invalid.original_exception.message
5
+
@@ -0,0 +1,38 @@
1
+ = form_for query, html: {class: 'form form-horizontal query-form', role: 'form'} do |f|
2
+ .page-header
3
+ h1
4
+ = title
5
+ .actions.btn-in-header
6
+ button.btn.btn-primary
7
+ i.fa.fa-floppy-o.fa-pad-r
8
+ | Save
9
+ - if f.object.persisted?
10
+ = link_to 'Cancel', f.object, class: 'btn btn-default'
11
+
12
+ .form-group
13
+ = f.label :name, class: 'col-sm-2 control-label'
14
+ .col-sm-8
15
+ = f.text_field :name, class: 'form-control', required: true
16
+
17
+ .form-group
18
+ = f.label :description, class: 'col-sm-2 control-label'
19
+ .col-sm-8
20
+ = f.text_area :description, class: 'form-control', required: true
21
+
22
+ .form-group
23
+ = f.label :query, class: 'col-sm-2 control-label'
24
+ .col-sm-8
25
+ = f.text_area :query, class: 'form-control', rows: 10, required: true
26
+
27
+ .preview
28
+ h2
29
+ | Preview
30
+ .btn-in-header
31
+ = link_to preview_path, class: 'btn btn-default btn-sm js-preview-button', data: {source: '#query_query', result: '.js-preview-result', remote: true, method: 'POST'} do
32
+ i.fa.fa-refresh[data-title='Refresh preview']
33
+
34
+ .js-preview-result
35
+ .alert Preview is shown here
36
+
37
+ javascript:
38
+ $(function() { Adhoq.enablePreview($('.preview a.js-preview-button')) })
@@ -0,0 +1,43 @@
1
+ section.query
2
+ .page-header
3
+ h1
4
+ = query.name
5
+ small= "Updated at #{l(query.updated_at, format: :short)}"
6
+ = link_to [:edit, query], class: 'btn btn-default' do
7
+ i.fa.fa-pencil.fa-pad-r
8
+ | Edit
9
+ p.description= query.description
10
+
11
+ pre.query= query.query
12
+
13
+ section.new-execution
14
+ h2 Create report
15
+ = form_for [query, query.executions.build], html: {class: 'form-inline', role: 'form'} do |f|
16
+ .form-group.report_format
17
+ = f.label :report_format
18
+ = f.select :report_format, f.object.supported_formats, {}, class: 'form-control'
19
+ .form-group
20
+ = f.submit 'Create report', class: 'btn btn-default'
21
+
22
+ section.past-executions
23
+ h2 Reports
24
+ .col-md-10
25
+ table.executions.table.table-striped.table-hover
26
+ thead
27
+ tr
28
+ th.wip &nbsp;
29
+ th.created_at= human(Adhoq::Execution, :created_at)
30
+ th.status= human(Adhoq::Execution, :status)
31
+ th.report
32
+ tbody
33
+ - query.executions.recent_first.each do |exec|
34
+ tr[exec]
35
+ td.wip
36
+ td.created_at= exec.created_at.localtime.iso8601
37
+ td.status
38
+ span.label[class=(exec.success? ? 'label-success' : 'label-danger')]= exec.status_label
39
+ td.report
40
+ - if exec.success?
41
+ = link_to([query, exec, format: exec.report_format], class: 'btn btn-sm btn-default') do
42
+ i.fa.fa-download.fa-pad-r
43
+ = exec.report_format
@@ -0,0 +1,2 @@
1
+ section.edit-query
2
+ = render 'form', query: @query, title: 'Edit query'
@@ -0,0 +1 @@
1
+ = render 'query', query: @queries.first
@@ -0,0 +1,2 @@
1
+ section.new-query
2
+ = render 'form', query: @query, title: 'New query'
@@ -0,0 +1 @@
1
+ = render 'query', query: @query
@@ -0,0 +1,18 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Adhoq
5
+ = stylesheet_link_tag 'adhoq/application', media: 'all'
6
+ = javascript_include_tag 'adhoq/application'
7
+ = csrf_meta_tags
8
+
9
+ body
10
+ .container
11
+ = render 'global_nav'
12
+
13
+ #contents.row
14
+ #sidebar.col-md-3
15
+ = render 'sidebar_queries_index'
16
+
17
+ #main.col-md-9= yield
18
+
@@ -0,0 +1,9 @@
1
+ Adhoq::Engine.routes.draw do
2
+ root to: 'queries#new'
3
+
4
+ resources :queries, path: 'q', except: %w(new) do
5
+ resources :executions, only: %w(create show)
6
+ end
7
+
8
+ resource :preview, only: 'create'
9
+ end
@@ -0,0 +1,11 @@
1
+ class CreateAdhoqQueries < ActiveRecord::Migration
2
+ def change
3
+ create_table :adhoq_queries do |t|
4
+ t.string :name
5
+ t.string :description
6
+ t.text :query
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class CreateAdhoqExecutions < ActiveRecord::Migration
2
+ def change
3
+ create_table :adhoq_executions do |t|
4
+ t.belongs_to :query, null: false
5
+ t.text :raw_sql, null: false
6
+ t.string :report_format, null: false
7
+ t.string :status, null: false, default: 'requested'
8
+ t.text :log
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class CreateAdhoqReports < ActiveRecord::Migration
2
+ def change
3
+ create_table :adhoq_reports do |t|
4
+ t.belongs_to :execution, null: false, index: true
5
+ t.string :identifier, null: false
6
+ t.time :generated_at, null: false
7
+ t.string :storage, null: false
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end