ronin-sql 0.2.4 → 1.0.0
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/.document +4 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +623 -288
- data/{History.txt → ChangeLog.md} +33 -35
- data/Gemfile +25 -0
- data/README.md +110 -0
- data/Rakefile +30 -20
- data/bin/ronin-sql +18 -5
- data/gemspec.yml +16 -0
- data/lib/ronin/formatting/extensions/sql.rb +4 -3
- data/lib/ronin/formatting/extensions/sql/string.rb +83 -10
- data/lib/ronin/formatting/sql.rb +4 -3
- data/lib/ronin/sql.rb +5 -12
- data/lib/ronin/{code/sql/create_index.rb → sql/binary_expr.rb} +25 -18
- data/lib/ronin/sql/clause.rb +72 -0
- data/lib/ronin/sql/clauses.rb +297 -0
- data/lib/ronin/sql/emittable.rb +84 -0
- data/lib/ronin/sql/emitter.rb +375 -0
- data/lib/ronin/sql/field.rb +106 -0
- data/lib/ronin/{code/sql/as.rb → sql/fields.rb} +36 -17
- data/lib/ronin/{code/sql/binary_expr.rb → sql/function.rb} +27 -27
- data/lib/ronin/sql/functions.rb +989 -0
- data/lib/ronin/sql/injection.rb +125 -157
- data/lib/ronin/{code/sql/default_values_clause.rb → sql/literal.rb} +13 -11
- data/lib/ronin/sql/literals.rb +72 -0
- data/lib/ronin/sql/operators.rb +332 -0
- data/lib/ronin/sql/sql.rb +86 -0
- data/lib/ronin/sql/statement.rb +70 -0
- data/lib/ronin/sql/statement_list.rb +110 -0
- data/lib/ronin/sql/statements.rb +115 -0
- data/lib/ronin/{code/sql/desc.rb → sql/unary_expr.rb} +11 -11
- data/lib/ronin/sql/version.rb +5 -4
- data/ronin-sql.gemspec +61 -0
- data/spec/formatting/sql/string_spec.rb +172 -0
- data/spec/spec_helper.rb +1 -4
- data/spec/sql/binary_expr.rb +5 -0
- data/spec/sql/binary_expr_examples.rb +25 -0
- data/spec/sql/clause_examples.rb +43 -0
- data/spec/sql/clause_spec.rb +31 -0
- data/spec/sql/clauses_spec.rb +43 -0
- data/spec/sql/emittable_spec.rb +41 -0
- data/spec/sql/emitter_spec.rb +472 -0
- data/spec/sql/field_spec.rb +103 -0
- data/spec/sql/fields_spec.rb +40 -0
- data/spec/sql/function_examples.rb +30 -0
- data/spec/sql/function_spec.rb +25 -0
- data/spec/sql/functions_spec.rb +110 -0
- data/spec/sql/injection_spec.rb +233 -0
- data/spec/sql/literal_spec.rb +5 -0
- data/spec/sql/literals_spec.rb +46 -0
- data/spec/sql/operators_spec.rb +44 -0
- data/spec/sql/sql_spec.rb +18 -0
- data/spec/sql/statement_examples.rb +39 -0
- data/spec/sql/statement_list_spec.rb +48 -0
- data/spec/sql/statement_sql.rb +38 -0
- data/spec/sql/statements_spec.rb +22 -0
- data/spec/sql/unary_expr.rb +5 -0
- data/spec/sql/unary_expr_examples.rb +20 -0
- metadata +116 -217
- data.tar.gz.sig +0 -0
- data/Manifest.txt +0 -108
- data/README.txt +0 -112
- data/lib/ronin/code/sql.rb +0 -22
- data/lib/ronin/code/sql/add_column_clause.rb +0 -42
- data/lib/ronin/code/sql/alter_table.rb +0 -52
- data/lib/ronin/code/sql/asc.rb +0 -36
- data/lib/ronin/code/sql/between.rb +0 -66
- data/lib/ronin/code/sql/clause.rb +0 -35
- data/lib/ronin/code/sql/code.rb +0 -35
- data/lib/ronin/code/sql/common_dialect.rb +0 -66
- data/lib/ronin/code/sql/create.rb +0 -74
- data/lib/ronin/code/sql/create_table.rb +0 -44
- data/lib/ronin/code/sql/create_view.rb +0 -41
- data/lib/ronin/code/sql/delete.rb +0 -52
- data/lib/ronin/code/sql/dialect.rb +0 -282
- data/lib/ronin/code/sql/drop.rb +0 -55
- data/lib/ronin/code/sql/drop_index.rb +0 -41
- data/lib/ronin/code/sql/drop_table.rb +0 -41
- data/lib/ronin/code/sql/drop_view.rb +0 -41
- data/lib/ronin/code/sql/emittable.rb +0 -100
- data/lib/ronin/code/sql/exceptions.rb +0 -24
- data/lib/ronin/code/sql/exceptions/unknown_clause.rb +0 -29
- data/lib/ronin/code/sql/exceptions/unknown_dialect.rb +0 -29
- data/lib/ronin/code/sql/exceptions/unknown_statement.rb +0 -29
- data/lib/ronin/code/sql/expr.rb +0 -102
- data/lib/ronin/code/sql/field.rb +0 -101
- data/lib/ronin/code/sql/fields_clause.rb +0 -46
- data/lib/ronin/code/sql/from_clause.rb +0 -42
- data/lib/ronin/code/sql/function.rb +0 -53
- data/lib/ronin/code/sql/group_by_clause.rb +0 -46
- data/lib/ronin/code/sql/having_clause.rb +0 -46
- data/lib/ronin/code/sql/in.rb +0 -47
- data/lib/ronin/code/sql/injected_statement.rb +0 -100
- data/lib/ronin/code/sql/injection.rb +0 -203
- data/lib/ronin/code/sql/insert.rb +0 -54
- data/lib/ronin/code/sql/intersect_clause.rb +0 -42
- data/lib/ronin/code/sql/join_clause.rb +0 -123
- data/lib/ronin/code/sql/like.rb +0 -73
- data/lib/ronin/code/sql/limit_clause.rb +0 -42
- data/lib/ronin/code/sql/modifier.rb +0 -48
- data/lib/ronin/code/sql/offset_clause.rb +0 -42
- data/lib/ronin/code/sql/on_clause.rb +0 -55
- data/lib/ronin/code/sql/order_by_clause.rb +0 -42
- data/lib/ronin/code/sql/program.rb +0 -225
- data/lib/ronin/code/sql/rename_to_clause.rb +0 -42
- data/lib/ronin/code/sql/replace.rb +0 -54
- data/lib/ronin/code/sql/select.rb +0 -103
- data/lib/ronin/code/sql/set_clause.rb +0 -42
- data/lib/ronin/code/sql/statement.rb +0 -180
- data/lib/ronin/code/sql/token.rb +0 -62
- data/lib/ronin/code/sql/unary_expr.rb +0 -47
- data/lib/ronin/code/sql/union_all_clause.rb +0 -42
- data/lib/ronin/code/sql/union_clause.rb +0 -42
- data/lib/ronin/code/sql/update.rb +0 -52
- data/lib/ronin/code/sql/values_clause.rb +0 -46
- data/lib/ronin/code/sql/where_clause.rb +0 -42
- data/lib/ronin/sql/error.rb +0 -26
- data/lib/ronin/sql/error/error.rb +0 -62
- data/lib/ronin/sql/error/extensions.rb +0 -22
- data/lib/ronin/sql/error/extensions/string.rb +0 -77
- data/lib/ronin/sql/error/message.rb +0 -62
- data/lib/ronin/sql/error/pattern.rb +0 -104
- data/lib/ronin/sql/error/patterns.rb +0 -99
- data/lib/ronin/sql/extensions.rb +0 -22
- data/lib/ronin/sql/extensions/uri.rb +0 -22
- data/lib/ronin/sql/extensions/uri/http.rb +0 -107
- data/spec/code/sql/common_dialect_spec.rb +0 -205
- data/spec/code/sql/create_examples.rb +0 -19
- data/spec/code/sql/create_index_spec.rb +0 -25
- data/spec/code/sql/create_table_spec.rb +0 -27
- data/spec/code/sql/create_view_spec.rb +0 -16
- data/spec/code/sql/delete_spec.rb +0 -14
- data/spec/code/sql/drop_examples.rb +0 -10
- data/spec/code/sql/drop_index_spec.rb +0 -16
- data/spec/code/sql/drop_table_spec.rb +0 -16
- data/spec/code/sql/drop_view_spec.rb +0 -16
- data/spec/code/sql/has_default_values_clause_examples.rb +0 -10
- data/spec/code/sql/has_fields_clause_examples.rb +0 -15
- data/spec/code/sql/has_from_clause_examples.rb +0 -13
- data/spec/code/sql/has_values_clause_examples.rb +0 -15
- data/spec/code/sql/has_where_clause_examples.rb +0 -15
- data/spec/code/sql/insert_spec.rb +0 -21
- data/spec/code/sql/replace_spec.rb +0 -21
- data/spec/code/sql/select_spec.rb +0 -105
- data/spec/code/sql/update_spec.rb +0 -26
- data/spec/helpers/code.rb +0 -14
- data/spec/sql/error_spec.rb +0 -24
- data/spec/sql/extensions/uri/http_spec.rb +0 -34
- data/spec/sql_spec.rb +0 -9
- data/tasks/spec.rb +0 -10
- data/tasks/yard.rb +0 -13
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/sql/field'
|
|
3
|
+
|
|
4
|
+
describe SQL::Field do
|
|
5
|
+
describe "#initialize" do
|
|
6
|
+
it "should convert name to a String" do
|
|
7
|
+
described_class.new(:table).name.should == 'table'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should default parent to nil" do
|
|
11
|
+
described_class.new('table').parent.should be_nil
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "parse" do
|
|
16
|
+
context "when passed a single field" do
|
|
17
|
+
let(:name) { "column" }
|
|
18
|
+
|
|
19
|
+
subject { described_class.parse(name) }
|
|
20
|
+
|
|
21
|
+
it "should parse the field name" do
|
|
22
|
+
subject.name.should == name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not have a parent" do
|
|
26
|
+
subject.parent.should be_nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "when parsing multiple fields" do
|
|
31
|
+
let(:parent) { "table" }
|
|
32
|
+
let(:name) { "column" }
|
|
33
|
+
|
|
34
|
+
subject { described_class.parse("#{parent}.#{name}") }
|
|
35
|
+
|
|
36
|
+
it "should parse the field name" do
|
|
37
|
+
subject.name.should == name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should parse the parent field" do
|
|
41
|
+
subject.parent.name.should == parent
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#to_s" do
|
|
47
|
+
context "when parent is nil" do
|
|
48
|
+
let(:name) { "column" }
|
|
49
|
+
|
|
50
|
+
subject { described_class.new(name) }
|
|
51
|
+
|
|
52
|
+
it "should return the name" do
|
|
53
|
+
subject.to_s.should == name
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "when parent is set" do
|
|
58
|
+
let(:parent) { "table" }
|
|
59
|
+
let(:name) { "column" }
|
|
60
|
+
|
|
61
|
+
subject { described_class.new(name,described_class.new(parent)) }
|
|
62
|
+
|
|
63
|
+
it "should return the name" do
|
|
64
|
+
subject.to_s.should == "#{parent}.#{name}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "#method_missing" do
|
|
70
|
+
context "at depth 1" do
|
|
71
|
+
subject { described_class.new('table') }
|
|
72
|
+
|
|
73
|
+
it "should allow accessing sub-fields" do
|
|
74
|
+
subject.column.name.should == 'column'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "at depth 2" do
|
|
79
|
+
subject { described_class.new('table',described_class.new('db')) }
|
|
80
|
+
|
|
81
|
+
it "should allow accessing sub-fields" do
|
|
82
|
+
subject.column.name.should == 'column'
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "at depth 3" do
|
|
87
|
+
subject do
|
|
88
|
+
described_class.new(
|
|
89
|
+
'column',
|
|
90
|
+
described_class.new(
|
|
91
|
+
'table', described_class.new('db')
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "should not allow accessing sub-fields" do
|
|
97
|
+
lambda {
|
|
98
|
+
subject.column
|
|
99
|
+
}.should raise_error(NoMethodError)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/sql/fields'
|
|
3
|
+
|
|
4
|
+
describe SQL::Fields do
|
|
5
|
+
subject { Object.new.extend(described_class) }
|
|
6
|
+
|
|
7
|
+
describe "#respond_to_missing?" do
|
|
8
|
+
it "should return true" do
|
|
9
|
+
subject.respond_to_missing?(double(:method)).should be(true)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
its(:to_ary) { should be_nil }
|
|
14
|
+
|
|
15
|
+
describe "#method_missing" do
|
|
16
|
+
let(:name) { 'users' }
|
|
17
|
+
|
|
18
|
+
context "when called with no arguments and no block" do
|
|
19
|
+
it "should create a Field" do
|
|
20
|
+
subject.send(name).name.should == name
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "when called with arguments" do
|
|
25
|
+
it "should raise a NoMethodError" do
|
|
26
|
+
lambda {
|
|
27
|
+
subject.sned(name,1,2,3)
|
|
28
|
+
}.should raise_error(NoMethodError)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "when called with a block" do
|
|
33
|
+
it "should raise a NoMethodError" do
|
|
34
|
+
lambda {
|
|
35
|
+
subject.sned(name) { 1 + 1 }
|
|
36
|
+
}.should raise_error(NoMethodError)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples_for "Function" do |method,arguments=[],additional_arguments=[]|
|
|
4
|
+
describe "##{method}" do
|
|
5
|
+
let(:name) { method.upcase }
|
|
6
|
+
let(:func) { subject.send(method,*arguments) }
|
|
7
|
+
|
|
8
|
+
it "should create a #{method.upcase} function" do
|
|
9
|
+
func.name.should == name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
unless arguments.empty?
|
|
13
|
+
it "should set the arguments" do
|
|
14
|
+
func.arguments.should == arguments
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
unless additional_arguments.empty?
|
|
19
|
+
context "when passed additional arguments" do
|
|
20
|
+
let(:func) { subject.send(method,*additional_arguments) }
|
|
21
|
+
|
|
22
|
+
it "should set the arguments" do
|
|
23
|
+
func.arguments.should == additional_arguments
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'ronin/sql/function'
|
|
4
|
+
|
|
5
|
+
describe SQL::Function do
|
|
6
|
+
describe "#initialize" do
|
|
7
|
+
context "with no arguments" do
|
|
8
|
+
subject { described_class.new(:f) }
|
|
9
|
+
|
|
10
|
+
it "should set arguments to []" do
|
|
11
|
+
subject.arguments.should == []
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context "with multiple arguments" do
|
|
16
|
+
let(:arguments) { [1,2,3] }
|
|
17
|
+
|
|
18
|
+
subject { described_class.new(:f,*arguments) }
|
|
19
|
+
|
|
20
|
+
it "should set arguments" do
|
|
21
|
+
subject.arguments.should == arguments
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'sql/function_examples'
|
|
3
|
+
require 'ronin/sql/functions'
|
|
4
|
+
require 'ronin/sql/binary_expr'
|
|
5
|
+
|
|
6
|
+
describe SQL::Functions do
|
|
7
|
+
subject { Object.new.extend(described_class) }
|
|
8
|
+
|
|
9
|
+
describe "#count" do
|
|
10
|
+
it "should create a COUNT function" do
|
|
11
|
+
subject.count.name.should == :COUNT
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "without arguments" do
|
|
15
|
+
it "should default arguments to *" do
|
|
16
|
+
subject.count.arguments.should == [:*]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
include_examples "Function", :max, [:column]
|
|
22
|
+
include_examples "Function", :min, [:column]
|
|
23
|
+
include_examples "Function", :avg, [:column]
|
|
24
|
+
include_examples "Function", :sum, [:column]
|
|
25
|
+
include_examples "Function", :sqrt, [1]
|
|
26
|
+
include_examples "Function", :rand, [1]
|
|
27
|
+
include_examples "Function", :abs, [-1]
|
|
28
|
+
include_examples "Function", :acos, [30]
|
|
29
|
+
include_examples "Function", :asin, [30]
|
|
30
|
+
include_examples "Function", :atan, [30]
|
|
31
|
+
include_examples "Function", :atan2, [30,60]
|
|
32
|
+
include_examples "Function", :bit_and, [0xff]
|
|
33
|
+
include_examples "Function", :bit_count, [0xff]
|
|
34
|
+
include_examples "Function", :bit_or, [0xff]
|
|
35
|
+
include_examples "Function", :ceil, [0.5]
|
|
36
|
+
include_examples "Function", :ceiling, [0.5]
|
|
37
|
+
include_examples "Function", :cos, [0.5]
|
|
38
|
+
include_examples "Function", :cot, [0.5]
|
|
39
|
+
include_examples "Function", :degrees, [0.5]
|
|
40
|
+
include_examples "Function", :exp, [0.5]
|
|
41
|
+
include_examples "Function", :floor, [0.5]
|
|
42
|
+
include_examples "Function", :format, [:date, 'YYYY-MM-DD']
|
|
43
|
+
include_examples "Function", :greatest, [1,2,3,4]
|
|
44
|
+
include_examples "Function", :interval, [1,2,3,4]
|
|
45
|
+
include_examples "Function", :least, [1,2,3,4]
|
|
46
|
+
include_examples "Function", :log, [2], [10,2]
|
|
47
|
+
include_examples "Function", :log10, [2]
|
|
48
|
+
include_examples "Function", :mod, [2,10]
|
|
49
|
+
include_examples "Function", :pi
|
|
50
|
+
include_examples "Function", :pow, [2,10]
|
|
51
|
+
include_examples "Function", :power, [2,10]
|
|
52
|
+
include_examples "Function", :radians, [30]
|
|
53
|
+
include_examples "Function", :random
|
|
54
|
+
include_examples "Function", :round, [15.79], [15.79, 1]
|
|
55
|
+
include_examples "Function", :sign, [10]
|
|
56
|
+
include_examples "Function", :sin, [30]
|
|
57
|
+
include_examples "Function", :sqrt, [100]
|
|
58
|
+
include_examples "Function", :std, [:column]
|
|
59
|
+
include_examples "Function", :stddev, [:column]
|
|
60
|
+
include_examples "Function", :tan, [30]
|
|
61
|
+
include_examples "Function", :truncate, [:price,2]
|
|
62
|
+
include_examples "Function", :ascii, ["hello"]
|
|
63
|
+
include_examples "Function", :bin, [12]
|
|
64
|
+
include_examples "Function", :bit_length, ["hello"]
|
|
65
|
+
include_examples "Function", :char, [104, 101, 108, 108, 111]
|
|
66
|
+
include_examples "Function", :char_length, ["hello"]
|
|
67
|
+
include_examples "Function", :character_length, ["hello"]
|
|
68
|
+
include_examples "Function", :concat, ["he", "ll", "o"]
|
|
69
|
+
include_examples "Function", :concat_ws, ["he", "ll", "o"]
|
|
70
|
+
include_examples "Function", :conv, ["ff", 16, 10]
|
|
71
|
+
include_examples "Function", :elt, ["ff", 16, 10]
|
|
72
|
+
include_examples "Function", :export_set, [5, 'Y', 'N']
|
|
73
|
+
include_examples "Function", :field, ["hello", "lo"]
|
|
74
|
+
include_examples "Function", :find_in_set, ['b', 'a,b,c,d']
|
|
75
|
+
include_examples "Function", :glob, [:name, '*foo*']
|
|
76
|
+
include_examples "Function", :hex, ["hello"]
|
|
77
|
+
include_examples "Function", :insert, ["hello",1,2,"foo"]
|
|
78
|
+
include_examples "Function", :instr, ["hello","lo"]
|
|
79
|
+
include_examples "Function", :lcase, ["HELLO"]
|
|
80
|
+
include_examples "Function", :left, ["hello", 10]
|
|
81
|
+
include_examples "Function", :length, ["hello"]
|
|
82
|
+
include_examples "Function", :like, [:name, '%foo%']
|
|
83
|
+
include_examples "Function", :load_file, ["path"]
|
|
84
|
+
include_examples "Function", :locate, ["o", "hello"]
|
|
85
|
+
include_examples "Function", :lower, ["HELLO"]
|
|
86
|
+
include_examples "Function", :lpad, ["hello", 10, ' ']
|
|
87
|
+
include_examples "Function", :ltrim, [" hello"]
|
|
88
|
+
include_examples "Function", :make_set, [8|1, 'a', 'b', 'c', 'd']
|
|
89
|
+
include_examples "Function", :mid, ["hello",2,3]
|
|
90
|
+
include_examples "Function", :oct, ["55"]
|
|
91
|
+
include_examples "Function", :octet_length, ["55"]
|
|
92
|
+
include_examples "Function", :ord, ["55"]
|
|
93
|
+
include_examples "Function", :position, [SQL::BinaryExpr.new('55',:IN,:name)]
|
|
94
|
+
include_examples "Function", :quote, ["hello"]
|
|
95
|
+
include_examples "Function", :repeat, ["A", 100]
|
|
96
|
+
include_examples "Function", :replace, ["foox", "foo", "bar"]
|
|
97
|
+
include_examples "Function", :reverse, ["hello"]
|
|
98
|
+
include_examples "Function", :right, ["hello", 10]
|
|
99
|
+
include_examples "Function", :rpad, ["hello", 10, ' ']
|
|
100
|
+
include_examples "Function", :rtrim, ["hello "]
|
|
101
|
+
include_examples "Function", :soundex, ["smythe"]
|
|
102
|
+
include_examples "Function", :space, [10]
|
|
103
|
+
include_examples "Function", :strcmp, ['foo', 'foox']
|
|
104
|
+
include_examples "Function", :substring, ['hello', 2, 1]
|
|
105
|
+
include_examples "Function", :substring_index, ['foo-bar', '-', 1]
|
|
106
|
+
include_examples "Function", :trim, [' foo ']
|
|
107
|
+
include_examples "Function", :ucase, ['foo']
|
|
108
|
+
include_examples "Function", :unhex, ['4D7953514C']
|
|
109
|
+
include_examples "Function", :upper, ['hello']
|
|
110
|
+
end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/sql/injection'
|
|
3
|
+
|
|
4
|
+
describe SQL::Injection do
|
|
5
|
+
describe "PLACE_HOLDERS" do
|
|
6
|
+
subject { described_class::PLACE_HOLDERS }
|
|
7
|
+
|
|
8
|
+
it { should include(integer: 1) }
|
|
9
|
+
it { should include(decimal: 1.0) }
|
|
10
|
+
it { should include(string: '1') }
|
|
11
|
+
it { should include(list: [nil]) }
|
|
12
|
+
it { should include(column: :id) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "#initialize" do
|
|
16
|
+
context "with no arguments" do
|
|
17
|
+
its(:escape) { should == :integer }
|
|
18
|
+
its(:place_holder) { should == 1 }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "with :escape" do
|
|
22
|
+
context "with no :place_holder" do
|
|
23
|
+
let(:place_holders) { described_class::PLACE_HOLDERS }
|
|
24
|
+
let(:escape) { :string }
|
|
25
|
+
|
|
26
|
+
subject { described_class.new(:escape => escape) }
|
|
27
|
+
|
|
28
|
+
it "should default the place_holder based on the :escape type" do
|
|
29
|
+
subject.place_holder.should == place_holders[escape]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "with :place_holder" do
|
|
35
|
+
let(:data) { 'A' }
|
|
36
|
+
|
|
37
|
+
subject { described_class.new(:place_holder => data) }
|
|
38
|
+
|
|
39
|
+
its(:place_holder) { should == data }
|
|
40
|
+
its(:expression) { should == data }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "when a block is given" do
|
|
44
|
+
subject { described_class.new { @x = 1 } }
|
|
45
|
+
|
|
46
|
+
it "should instance_eval the block" do
|
|
47
|
+
subject.instance_variable_get(:@x).should == 1
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe "#and" do
|
|
53
|
+
context "on first call" do
|
|
54
|
+
before { subject.and { 1 } }
|
|
55
|
+
|
|
56
|
+
it "should create a 'AND' BinaryExpr" do
|
|
57
|
+
subject.expression.operator.should == :AND
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should create an expression with the place-holder" do
|
|
61
|
+
subject.expression.left.should == subject.place_holder
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should create an expression with the expression" do
|
|
65
|
+
subject.expression.right.should == 1
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context "on multiple calls" do
|
|
70
|
+
before { subject.and { 1 }.and { 2 } }
|
|
71
|
+
|
|
72
|
+
it "should create another 'AND' BinaryExpr" do
|
|
73
|
+
subject.expression.operator.should == :AND
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should nest the expressions" do
|
|
77
|
+
subject.expression.left.right.should == 1
|
|
78
|
+
subject.expression.right.should == 2
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "#or" do
|
|
84
|
+
context "on first call" do
|
|
85
|
+
before { subject.or { 1 } }
|
|
86
|
+
|
|
87
|
+
it "should create a 'OR' BinaryExpr" do
|
|
88
|
+
subject.expression.operator.should == :OR
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should create an expression with the place-holder" do
|
|
92
|
+
subject.expression.left.should == subject.place_holder
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should create an expression with the expression" do
|
|
96
|
+
subject.expression.right.should == 1
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "on multiple calls" do
|
|
101
|
+
before { subject.or { 1 }.or { 2 } }
|
|
102
|
+
|
|
103
|
+
it "should create another 'OR' BinaryExpr" do
|
|
104
|
+
subject.expression.operator.should == :OR
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should nest the expressions" do
|
|
108
|
+
subject.expression.left.right.should == 1
|
|
109
|
+
subject.expression.right.should == 2
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe "#to_sql" do
|
|
115
|
+
context "without an expression" do
|
|
116
|
+
subject { described_class.new(place_holder: 1) }
|
|
117
|
+
|
|
118
|
+
it "should still emit the place-holder value" do
|
|
119
|
+
subject.to_sql.should == '1'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "with clauses" do
|
|
123
|
+
subject do
|
|
124
|
+
sqli = described_class.new(place_holder: 1)
|
|
125
|
+
sqli.limit(100).offset(10)
|
|
126
|
+
sqli
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should emit the clauses" do
|
|
130
|
+
subject.to_sql.should == '1 LIMIT 100 OFFSET 10'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context "with an expression" do
|
|
136
|
+
subject do
|
|
137
|
+
sqli = described_class.new
|
|
138
|
+
sqli.or { 1 == 1 }
|
|
139
|
+
sqli
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should emit the expression" do
|
|
143
|
+
subject.to_sql.should == '1 OR 1=1'
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context "with clauses" do
|
|
147
|
+
subject do
|
|
148
|
+
sqli = described_class.new
|
|
149
|
+
sqli.or { 1 == 1 }.limit(100).offset(10)
|
|
150
|
+
sqli
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should emit the clauses" do
|
|
154
|
+
subject.to_sql.should == '1 OR 1=1 LIMIT 100 OFFSET 10'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context "with :space" do
|
|
158
|
+
it "should emit the clauses with custom spaces" do
|
|
159
|
+
subject.to_sql(space: '/**/').should == '1/**/OR/**/1=1/**/LIMIT/**/100/**/OFFSET/**/10'
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "with statements" do
|
|
165
|
+
subject do
|
|
166
|
+
sqli = described_class.new
|
|
167
|
+
sqli.or { 1 == 1 }.select(1,2,3)
|
|
168
|
+
sqli
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "should emit the clauses" do
|
|
172
|
+
subject.to_sql.should == '1 OR 1=1; SELECT (1,2,3)'
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "with :space" do
|
|
176
|
+
it "should emit the statements with custom spaces" do
|
|
177
|
+
subject.to_sql(space: '/**/').should == '1/**/OR/**/1=1;/**/SELECT/**/(1,2,3)'
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context "when escaping a string value" do
|
|
184
|
+
context "when the place-holder and last operand are Strings" do
|
|
185
|
+
subject do
|
|
186
|
+
sqli = described_class.new(escape: :string)
|
|
187
|
+
sqli.or { string(1) == string(1) }
|
|
188
|
+
sqli
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "should balance the quotes" do
|
|
192
|
+
subject.to_sql.should == "1' OR '1'='1"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
context "when the place-holder and last operand are not both Strings" do
|
|
197
|
+
subject do
|
|
198
|
+
sqli = described_class.new(escape: :string)
|
|
199
|
+
sqli.or { int(1) == int(1) }
|
|
200
|
+
sqli
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "should terminate the SQL statement" do
|
|
204
|
+
subject.to_sql.should == "1' OR 1=1;--"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
context "when terminating" do
|
|
209
|
+
subject do
|
|
210
|
+
sqli = described_class.new(escape: :string)
|
|
211
|
+
sqli.or { string(1) == string(1) }
|
|
212
|
+
sqli
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should terminate the SQL statement" do
|
|
216
|
+
subject.to_sql(terminate: true).should == "1' OR '1'='1';--"
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context "when terminating" do
|
|
222
|
+
subject do
|
|
223
|
+
sqli = described_class.new(escape: :integer)
|
|
224
|
+
sqli.or { 1 == 1 }
|
|
225
|
+
sqli
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "should terminate the SQL statement" do
|
|
229
|
+
subject.to_sql(terminate: true).should == "1 OR 1=1;--"
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|