fluent-query-sql 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +26 -0
- data/LICENSE.txt +20 -0
- data/README.md +33 -0
- data/Rakefile +31 -0
- data/VERSION +1 -0
- data/fluent-query-sql.gemspec +74 -0
- data/lib/fluent-query/drivers/shared/tokens/sql.rb +128 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/delete.rb +58 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/from.rb +103 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/groupby.rb +117 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/having.rb +100 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/insert.rb +60 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/join.rb +98 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/orderby.rb +148 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/select.rb +147 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/set.rb +94 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/truncate.rb +59 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/union.rb +65 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/update.rb +58 -0
- data/lib/fluent-query/drivers/shared/tokens/sql/where.rb +100 -0
- data/lib/fluent-query/drivers/sql.rb +559 -0
- data/lib/fluent-query/queries/sql.rb +54 -0
- metadata +135 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
3
|
+
require "hash-utils/object" # >= 0.17.0
|
4
|
+
|
5
|
+
module FluentQuery
|
6
|
+
module Drivers
|
7
|
+
module Shared
|
8
|
+
module Tokens
|
9
|
+
module SQL
|
10
|
+
|
11
|
+
##
|
12
|
+
# Generic SQL query SELECT token.
|
13
|
+
#
|
14
|
+
|
15
|
+
class Select < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
16
|
+
|
17
|
+
##
|
18
|
+
# Renders this token.
|
19
|
+
#
|
20
|
+
|
21
|
+
public
|
22
|
+
def render!(mode = :build)
|
23
|
+
stack = [ ]
|
24
|
+
unknown = [ ]
|
25
|
+
fields = [ ]
|
26
|
+
aliases = { }
|
27
|
+
distinct = false
|
28
|
+
|
29
|
+
result = "SELECT "
|
30
|
+
processor = @_query.processor
|
31
|
+
|
32
|
+
_class = self.unknown_token
|
33
|
+
|
34
|
+
# Process subtokens
|
35
|
+
|
36
|
+
@_subtokens.each do |token|
|
37
|
+
arguments = token.arguments
|
38
|
+
name = token.name
|
39
|
+
|
40
|
+
# Known select process
|
41
|
+
if (name == :select) or (name == :distinct)
|
42
|
+
length = arguments.length
|
43
|
+
|
44
|
+
if length > 0
|
45
|
+
first = arguments.first
|
46
|
+
|
47
|
+
if first.symbol?
|
48
|
+
stack << arguments
|
49
|
+
elsif first.string?
|
50
|
+
stack << processor.process_formatted(arguments, mode)
|
51
|
+
else
|
52
|
+
arguments.each do |argument|
|
53
|
+
if argument.array?
|
54
|
+
fields += argument
|
55
|
+
elsif argument.hash?
|
56
|
+
aliases.merge! argument
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Closes opened native token with unknown tokens
|
63
|
+
if unknown.length > 0
|
64
|
+
native = _class::new(@_driver, @_query, unknown)
|
65
|
+
stack << native.render!
|
66
|
+
unknown = [ ]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Unknowns arguments pushes to the general native token
|
70
|
+
else
|
71
|
+
unknown << token
|
72
|
+
end
|
73
|
+
|
74
|
+
distinct = (name == :distinct)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Closes opened native token with unknown tokens
|
78
|
+
if unknown.length > 0
|
79
|
+
native = _class::new(@_driver, @_query, unknown)
|
80
|
+
stack << native.render!
|
81
|
+
unknown = [ ]
|
82
|
+
end
|
83
|
+
|
84
|
+
# process distinct
|
85
|
+
if distinct
|
86
|
+
result << "DISTINCT "
|
87
|
+
end
|
88
|
+
|
89
|
+
# Process stack with results
|
90
|
+
|
91
|
+
first = true
|
92
|
+
|
93
|
+
if not fields.empty?
|
94
|
+
stack.unshift(fields.uniq)
|
95
|
+
end
|
96
|
+
|
97
|
+
if not aliases.empty?
|
98
|
+
stack.unshift(aliases)
|
99
|
+
end
|
100
|
+
|
101
|
+
stack.each do |item|
|
102
|
+
|
103
|
+
if item.array?
|
104
|
+
if not first
|
105
|
+
result << ", "
|
106
|
+
end
|
107
|
+
|
108
|
+
result << processor.process_identifiers(item)
|
109
|
+
first = false
|
110
|
+
|
111
|
+
elsif item.hash?
|
112
|
+
fields = [ ]
|
113
|
+
|
114
|
+
item.each_pair do |key, value|
|
115
|
+
key = @_driver.quote_identifier(key)
|
116
|
+
value = @_driver.quote_identifier(value)
|
117
|
+
|
118
|
+
fields << (key.to_s + " AS " + value.to_s)
|
119
|
+
end
|
120
|
+
|
121
|
+
if not first
|
122
|
+
result << ", "
|
123
|
+
end
|
124
|
+
|
125
|
+
result << fields.join(", ")
|
126
|
+
first = false
|
127
|
+
|
128
|
+
elsif item.string?
|
129
|
+
if not first
|
130
|
+
result << ", "
|
131
|
+
end
|
132
|
+
|
133
|
+
result << item
|
134
|
+
first = false
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
return result
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
3
|
+
require "fluent-query/drivers/exception"
|
4
|
+
require "hash-utils/object" # >= 0.17.0
|
5
|
+
|
6
|
+
module FluentQuery
|
7
|
+
module Drivers
|
8
|
+
module Shared
|
9
|
+
module Tokens
|
10
|
+
module SQL
|
11
|
+
|
12
|
+
##
|
13
|
+
# Generic SQL query SET token.
|
14
|
+
#
|
15
|
+
|
16
|
+
class Set < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
17
|
+
|
18
|
+
##
|
19
|
+
# Renders this token.
|
20
|
+
#
|
21
|
+
|
22
|
+
public
|
23
|
+
def render!(mode = :build)
|
24
|
+
_class = self.unknown_token
|
25
|
+
|
26
|
+
stack = [ ]
|
27
|
+
unknown = [ ]
|
28
|
+
|
29
|
+
operator = @_driver.quote_operator(:and)
|
30
|
+
processor = @_query.processor
|
31
|
+
result = "SET "
|
32
|
+
|
33
|
+
@_subtokens.each do |token|
|
34
|
+
arguments = token.arguments
|
35
|
+
|
36
|
+
# SET token
|
37
|
+
|
38
|
+
if token.name == :set
|
39
|
+
length = arguments.length
|
40
|
+
|
41
|
+
# Checks for arguments
|
42
|
+
if length > 0
|
43
|
+
if (length > 1) or (arguments.first.string?)
|
44
|
+
stack << processor.process_formatted(arguments, mode)
|
45
|
+
elsif arguments.first.hash?
|
46
|
+
stack << processor.process_hash(arguments.first, ", ", :assigning)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise FluentQuery::Drivers::Exception::new("SET token expects Hash or formatted string as argument.")
|
50
|
+
end
|
51
|
+
|
52
|
+
# Unknown tokens renders directly
|
53
|
+
else
|
54
|
+
result << _class::new(@_driver, @_query, [token]).render!
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Closes opened native token with unknown tokens
|
61
|
+
if unknown.length > 0
|
62
|
+
native = _class::new(@_driver, @_query, unknown)
|
63
|
+
stack << native
|
64
|
+
unknown = [ ]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Process stack with results
|
68
|
+
first = true
|
69
|
+
|
70
|
+
stack.each do |item|
|
71
|
+
if item.kind_of? _class
|
72
|
+
result << item.render!
|
73
|
+
elsif item.string?
|
74
|
+
if not first
|
75
|
+
result << operator << " "
|
76
|
+
else
|
77
|
+
first = false
|
78
|
+
end
|
79
|
+
|
80
|
+
result << item
|
81
|
+
end
|
82
|
+
|
83
|
+
result << " "
|
84
|
+
end
|
85
|
+
|
86
|
+
return result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
3
|
+
require "fluent-query/drivers/exception"
|
4
|
+
require "hash-utils/object" # >= 0.17.0
|
5
|
+
|
6
|
+
module FluentQuery
|
7
|
+
module Drivers
|
8
|
+
module Shared
|
9
|
+
module Tokens
|
10
|
+
module SQL
|
11
|
+
|
12
|
+
##
|
13
|
+
# Generic SQL query TRUNCATE token.
|
14
|
+
#
|
15
|
+
|
16
|
+
class Truncate < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
17
|
+
|
18
|
+
##
|
19
|
+
# Renders this token.
|
20
|
+
#
|
21
|
+
|
22
|
+
public
|
23
|
+
def render!(mode = nil)
|
24
|
+
processor = @_query.processor
|
25
|
+
result = "TRUNCATE TABLE "
|
26
|
+
|
27
|
+
@_subtokens.each do |token|
|
28
|
+
arguments = token.arguments
|
29
|
+
|
30
|
+
# FROM token
|
31
|
+
|
32
|
+
if token.name == :truncate
|
33
|
+
|
34
|
+
# Checks for arguments
|
35
|
+
if (not arguments.first.symbol?)
|
36
|
+
raise FluentQuery::Drivers::Exception::new("Symbol argument expected for #truncate method.")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Process
|
40
|
+
table = processor.quote_identifier(arguments.first)
|
41
|
+
result << table
|
42
|
+
|
43
|
+
# Unknown tokens renders directly
|
44
|
+
else
|
45
|
+
result << self.unknown_token::new(@_driver, @_query, [token]).render!
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
result << " CASCADE"
|
51
|
+
return result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/query"
|
3
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
4
|
+
require "fluent-query/drivers/exception"
|
5
|
+
require "hash-utils/object" # >= 0.17.0
|
6
|
+
|
7
|
+
module FluentQuery
|
8
|
+
module Drivers
|
9
|
+
module Shared
|
10
|
+
module Tokens
|
11
|
+
module SQL
|
12
|
+
|
13
|
+
##
|
14
|
+
# Generic SQL query UNION token.
|
15
|
+
#
|
16
|
+
|
17
|
+
class Union < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
18
|
+
|
19
|
+
##
|
20
|
+
# Renders this token.
|
21
|
+
#
|
22
|
+
|
23
|
+
public
|
24
|
+
def render!(mode = nil)
|
25
|
+
result = ""
|
26
|
+
|
27
|
+
@_subtokens.each do |token|
|
28
|
+
arguments = token.arguments
|
29
|
+
|
30
|
+
# SET token
|
31
|
+
|
32
|
+
if token.name == :union
|
33
|
+
length = arguments.length
|
34
|
+
|
35
|
+
# Checks for arguments
|
36
|
+
if length >= 2
|
37
|
+
queries = [ ]
|
38
|
+
|
39
|
+
arguments.each do |argument|
|
40
|
+
if argument.string?
|
41
|
+
queries << argument
|
42
|
+
elsif argument.kind_of? FluentQuery::Query
|
43
|
+
queries << argument.build!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
else
|
48
|
+
raise FluentQuery::Drivers::Exception::new("UNION token expects at least two queries or strings as arguments.")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Process stack with results
|
54
|
+
queries.map! { |i| @_driver.quote_subquery(i) }
|
55
|
+
result << queries.join(" UNION ")
|
56
|
+
|
57
|
+
return result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
3
|
+
require "fluent-query/drivers/exception"
|
4
|
+
require "hash-utils/object" # >= 0.17.0
|
5
|
+
|
6
|
+
module FluentQuery
|
7
|
+
module Drivers
|
8
|
+
module Shared
|
9
|
+
module Tokens
|
10
|
+
module SQL
|
11
|
+
|
12
|
+
##
|
13
|
+
# Generic SQL query UPDATE token.
|
14
|
+
#
|
15
|
+
|
16
|
+
class Update < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
17
|
+
|
18
|
+
##
|
19
|
+
# Renders this token.
|
20
|
+
#
|
21
|
+
|
22
|
+
public
|
23
|
+
def render!(mode = nil)
|
24
|
+
|
25
|
+
processor = @_query.processor
|
26
|
+
result = "UPDATE "
|
27
|
+
|
28
|
+
@_subtokens.each do |token|
|
29
|
+
arguments = token.arguments
|
30
|
+
|
31
|
+
# UPDATE token
|
32
|
+
if token.name == :update
|
33
|
+
|
34
|
+
# Checks for arguments
|
35
|
+
if (not arguments.first.symbol?)
|
36
|
+
raise FluentQuery::Drivers::Exception::("Symbol arguments expected for #update method.")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Process
|
40
|
+
table = processor.quote_identifier(arguments.first)
|
41
|
+
result << table
|
42
|
+
|
43
|
+
# Unknown tokens renders directly
|
44
|
+
else
|
45
|
+
result = self.unknown_token::new(@_driver, @_query, token).render!
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fluent-query/drivers/shared/tokens/sql"
|
3
|
+
require "hash-utils/object" # >= 0.17.0
|
4
|
+
|
5
|
+
module FluentQuery
|
6
|
+
module Drivers
|
7
|
+
module Shared
|
8
|
+
module Tokens
|
9
|
+
module SQL
|
10
|
+
|
11
|
+
##
|
12
|
+
# Generic SQL query WHERE token.
|
13
|
+
#
|
14
|
+
|
15
|
+
class Where < FluentQuery::Drivers::Shared::Tokens::SQLToken
|
16
|
+
|
17
|
+
##
|
18
|
+
# Renders this token.
|
19
|
+
#
|
20
|
+
|
21
|
+
public
|
22
|
+
def render!(mode = :build)
|
23
|
+
_class = self.unknown_token
|
24
|
+
|
25
|
+
stack = [ ]
|
26
|
+
unknown = [ ]
|
27
|
+
|
28
|
+
operator = @_driver.quote_operator(:and)
|
29
|
+
processor = @_query.processor
|
30
|
+
|
31
|
+
result = "WHERE "
|
32
|
+
|
33
|
+
# Process subtokens
|
34
|
+
|
35
|
+
@_subtokens.each do |token|
|
36
|
+
arguments = token.arguments
|
37
|
+
|
38
|
+
# Known process
|
39
|
+
if token.name == :where
|
40
|
+
length = arguments.length
|
41
|
+
first = arguments.first
|
42
|
+
|
43
|
+
if length > 0
|
44
|
+
if (length > 1) or (first.string?)
|
45
|
+
stack << processor.process_formatted(arguments, mode)
|
46
|
+
elsif first.array?
|
47
|
+
stack << first.join(operator)
|
48
|
+
elsif first.hash?
|
49
|
+
stack << processor.process_hash(first, operator)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Closes opened native token with unknown tokens
|
54
|
+
if unknown.length > 0
|
55
|
+
native = _class::new(@_driver, @_query, unknown)
|
56
|
+
stack << native
|
57
|
+
unknown = [ ]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Unknowns arguments pushes to the general native token
|
61
|
+
else
|
62
|
+
unknown << token
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# Closes opened native token with unknown tokens
|
68
|
+
if unknown.length > 0
|
69
|
+
native = _class::new(@_driver, @_query, unknown)
|
70
|
+
stack << native
|
71
|
+
unknown = [ ]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Process stack with results
|
75
|
+
first = true
|
76
|
+
|
77
|
+
stack.each do |item|
|
78
|
+
if item.kind_of? _class
|
79
|
+
result << item.render!
|
80
|
+
elsif item.string?
|
81
|
+
if not first
|
82
|
+
result << operator << " "
|
83
|
+
else
|
84
|
+
first = false
|
85
|
+
end
|
86
|
+
|
87
|
+
result << item
|
88
|
+
end
|
89
|
+
|
90
|
+
result << " "
|
91
|
+
end
|
92
|
+
|
93
|
+
return result
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|