fluent-query-sql 0.9.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 +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
|