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.
- data/lib/sql-rewriter.rb +37 -0
- data/lib/sql-rewriter/adapters.rb +105 -0
- data/lib/sql-rewriter/hooks.rb +46 -0
- data/lib/sql-rewriter/version.rb +5 -0
- metadata +97 -0
data/lib/sql-rewriter.rb
ADDED
@@ -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
|
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: []
|