sql-rewriter 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []