sql-rewriter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ module SQLRewriter
2
+
3
+ require 'sql-parser'
4
+
5
+ require_relative 'sql-rewriter/hooks'
6
+ require_relative 'sql-rewriter/adapters'
7
+
8
+ class << self
9
+ attr_accessor :before_hook
10
+ attr_accessor :after_hook
11
+ end
12
+
13
+ self.before_hook = nil
14
+ self.after_hook = nil
15
+
16
+ def self.inject(adapter, &block)
17
+
18
+ if adapter.to_s == 'ActiveRecord'
19
+ SQLRewriter::Adapters::ActiveRecord.inject
20
+ else
21
+ raise 'No adapter for ' + adapter.to_s
22
+ end
23
+
24
+ instance_eval(&block)
25
+
26
+ end
27
+
28
+
29
+ def self.before_query(&block)
30
+ self.before_hook = block
31
+ end
32
+
33
+ def self.after_query(&block)
34
+ self.after_hook = block
35
+ end
36
+
37
+ end
@@ -0,0 +1,105 @@
1
+ module SQLRewriter
2
+
3
+ module Adapters
4
+
5
+ class ActiveRecord
6
+
7
+ # Most of this code is lifted from the Marginalia gem
8
+ def self.inject
9
+
10
+ if defined? ::ActiveRecord::ConnectionAdapters::Mysql2Adapter
11
+ if ::ActiveRecord::Base.connection.is_a?(
12
+ ::ActiveRecord::ConnectionAdapters::Mysql2Adapter)
13
+ ::ActiveRecord::ConnectionAdapters::Mysql2Adapter.module_eval do
14
+ include SQLRewriter::Adapters::ActiveRecord::Decorator
15
+ end
16
+ end
17
+ end
18
+
19
+ if defined? ::ActiveRecord::ConnectionAdapters::MysqlAdapter
20
+ if ::ActiveRecord::Base.connection.is_a?(
21
+ ::ActiveRecord::ConnectionAdapters::MysqlAdapter)
22
+ ::ActiveRecord::ConnectionAdapters::MysqlAdapter.module_eval do
23
+ include SQLRewriter::Adapters::ActiveRecord::Decorator
24
+ end
25
+ end
26
+ end
27
+
28
+ # SQL queries made through PostgreSQLAdapter#exec_delete will not be annotated.
29
+ if defined? ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
30
+ if ::ActiveRecord::Base.connection.is_a?(
31
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
32
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.module_eval do
33
+ include SQLRewriter::Adapters::ActiveRecord::Decorator
34
+ end
35
+ end
36
+ end
37
+
38
+ if defined? ::ActiveRecord::ConnectionAdapters::SQLite3Adapter
39
+ if ::ActiveRecord::Base.connection.is_a?(
40
+ ::ActiveRecord::ConnectionAdapters::SQLite3Adapter)
41
+ ::ActiveRecord::ConnectionAdapters::SQLite3Adapter.module_eval do
42
+ include SQLRewriter::Adapters::ActiveRecord::Decorator
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ if defined? Rails::Railtie
50
+ require 'rails/railtie'
51
+
52
+ class Railtie < Rails::Railtie
53
+
54
+ initializer 'SQLRewriter.insert' do
55
+ ActiveSupport.on_load :active_record do
56
+ SQLRewriter::ActiveRecord::Decorator.insert_into_active_record
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ module Decorator
65
+
66
+ include SQLRewriter::Hooks::AfterQuery
67
+ include SQLRewriter::Hooks::BeforeQuery
68
+
69
+ def self.included(decorated_class)
70
+
71
+ decorated_class.class_eval do
72
+ if decorated_class.method_defined?(:execute)
73
+ alias_method :execute_without_sqlr, :execute
74
+ alias_method :execute, :execute_with_sqlr
75
+ end
76
+
77
+ is_mysql2 = defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) &&
78
+ ActiveRecord::ConnectionAdapters::Mysql2Adapter == decorated_class
79
+
80
+ # Dont instrument exec_query on mysql2 and AR 3.2+, as it calls execute internally
81
+ unless is_mysql2 && ActiveRecord::VERSION::STRING > "3.1"
82
+ if decorated_class.method_defined?(:exec_query)
83
+ alias_method :exec_query_without_sqlr, :exec_query
84
+ alias_method :exec_query, :exec_query_with_sqlr
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def execute_with_sqlr(sql, name = nil, binds)
91
+ after_query(execute_without_sqlr(before_query(sql, binds), name))
92
+
93
+ end
94
+
95
+ def exec_query_with_sqlr(sql, name = 'SQL', binds = [])
96
+ after_query(exec_query_without_sqlr(before_query(sql, binds), name, binds))
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,46 @@
1
+ module SQLRewriter
2
+
3
+ module Hooks
4
+
5
+ module AfterQuery
6
+
7
+ def after_query(result)
8
+
9
+ SQLRewriter.after_hook.call(result)
10
+
11
+ end
12
+
13
+ end
14
+
15
+ module BeforeQuery
16
+
17
+ def before_query(sql, binds)
18
+
19
+ begin
20
+
21
+ sql_spliced = sql.dup
22
+
23
+ binds.map(&:last).each do |bind|
24
+ sql_spliced.sub!('?', '"' + bind + '"')
25
+ end
26
+
27
+ parser = SQLParser::Parser.new
28
+ ast = parser.scan_str(sql_spliced)
29
+
30
+ res = SQLRewriter.before_hook.call(sql, binds, ast)
31
+
32
+ res.to_sql
33
+
34
+ rescue
35
+
36
+ SQLRewriter.before_hook.call(sql, binds, nil)
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,5 @@
1
+ module SQLRewriter
2
+
3
+ VERSION = '0.0.1'
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sql-rewriter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Louis Mullie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sql-parser
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! ' Ruby library for SQL injection and re-writing in ActiveRecord '
63
+ email:
64
+ - louis.mullie@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/sql-rewriter/adapters.rb
70
+ - lib/sql-rewriter/hooks.rb
71
+ - lib/sql-rewriter/version.rb
72
+ - lib/sql-rewriter.rb
73
+ homepage: https://github.com/louismullie/sql-parser
74
+ licenses: []
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 1.8.25
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Ruby library for SQL injection and re-writing in ActiveRecord
97
+ test_files: []