rossoc 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +21 -0
- data/.rubocop_todo.yml +44 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.base.md +190 -0
- data/README.ja.md +136 -0
- data/README.md +134 -0
- data/Rakefile +14 -0
- data/exe/rossoc +6 -0
- data/lib/rossoc/backend.rb +47 -0
- data/lib/rossoc/cli.rb +46 -0
- data/lib/rossoc/frontend.rb +154 -0
- data/lib/rossoc/ir.rb +77 -0
- data/lib/rossoc/parser.racc +346 -0
- data/lib/rossoc/parser.racc.rb +1542 -0
- data/lib/rossoc/parser.rex +111 -0
- data/lib/rossoc/parser.rex.rb +301 -0
- data/lib/rossoc/sql_visitor.rb +375 -0
- data/lib/rossoc/statement.rb +455 -0
- data/lib/rossoc/version.rb +5 -0
- data/lib/rossoc/views/arduino.erb +41 -0
- data/lib/rossoc/views/dev.erb +32 -0
- data/lib/rossoc/views/mruby.erb +44 -0
- data/lib/rossoc.rb +21 -0
- data/sig/rossoc.rbs +4 -0
- metadata +155 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rossoc'
|
4
|
+
|
5
|
+
# Rossoc
|
6
|
+
module Rossoc
|
7
|
+
# Frontend
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
9
|
+
class Frontend
|
10
|
+
class FrontendError < StandardError; end
|
11
|
+
|
12
|
+
RESERVED_PINS = %w[
|
13
|
+
din0 din1 din2 din3 din4 din5 din6 din7 din8 din9 din10
|
14
|
+
din11 din12 din13 din14 din15 din16 din17 din18 din19 din20
|
15
|
+
ain0 ain1 ain2 ain3 ain4 ain5 ain6 ain7 ain8 ain9 ain10
|
16
|
+
ain11 ain12 ain13 ain14 ain15 ain16 ain17 ain18 ain19 ain20
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def initialize(input)
|
20
|
+
@input = input
|
21
|
+
@out_pins = Set.new
|
22
|
+
@in_pins = Set.new
|
23
|
+
@table = nil
|
24
|
+
@where = nil
|
25
|
+
@ast = nil
|
26
|
+
@sleep_sec = 0
|
27
|
+
@speed = 9600
|
28
|
+
end
|
29
|
+
|
30
|
+
def ir
|
31
|
+
parser(@input)
|
32
|
+
check_columns
|
33
|
+
check_tables
|
34
|
+
check_condition
|
35
|
+
check_rsleep
|
36
|
+
check_rspeed
|
37
|
+
|
38
|
+
Rossoc::Ir.new(@in_pins, @out_pins, @table, @where, @ast,
|
39
|
+
@sleep_sec, @speed).result
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parser(sql)
|
45
|
+
parser = SQLParser::Parser.new
|
46
|
+
@ast = parser.scan_str(sql)
|
47
|
+
rescue Racc::ParseError => e
|
48
|
+
raise FrontendError, e
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_columns
|
52
|
+
columns = @ast.query_expression.list.columns
|
53
|
+
columns.each do |column|
|
54
|
+
name = column.name
|
55
|
+
index = RESERVED_PINS.index(name)
|
56
|
+
raise FrontendError, "unknown column value #{name}." if index.nil?
|
57
|
+
|
58
|
+
@in_pins.add(name)
|
59
|
+
@out_pins.add(name)
|
60
|
+
end
|
61
|
+
rescue StandardError
|
62
|
+
raise FrontendError, 'unsupported column.'
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_tables
|
66
|
+
tables = @ast.query_expression.table_expression.from_clause.tables
|
67
|
+
tables.each do |table|
|
68
|
+
@table = table.name
|
69
|
+
end
|
70
|
+
rescue e
|
71
|
+
raise e
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_condition
|
75
|
+
begin
|
76
|
+
condition = if @ast.query_expression.table_expression.where_clause.nil?
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
@ast.query_expression.table_expression.where_clause.search_condition
|
80
|
+
end
|
81
|
+
rescue e
|
82
|
+
raise e
|
83
|
+
end
|
84
|
+
|
85
|
+
if condition.nil?
|
86
|
+
@where = 1
|
87
|
+
else
|
88
|
+
condition_parser(condition)
|
89
|
+
|
90
|
+
tokens = condition.to_sql.split
|
91
|
+
tokens.each_with_index do |token, index|
|
92
|
+
case token
|
93
|
+
when '='
|
94
|
+
token = '=='
|
95
|
+
when 'AND'
|
96
|
+
token = '&&'
|
97
|
+
when 'OR'
|
98
|
+
token = '||'
|
99
|
+
when '<>'
|
100
|
+
token = '!='
|
101
|
+
end
|
102
|
+
tokens[index] = token.gsub('`', '')
|
103
|
+
end
|
104
|
+
|
105
|
+
@where = tokens.join(' ')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def condition_parser(condition)
|
110
|
+
root_words = ['SQLParser::Statement::Equals',
|
111
|
+
'SQLParser::Statement::Greater',
|
112
|
+
'SQLParser::Statement::GreaterOrEquals',
|
113
|
+
'SQLParser::Statement::Less',
|
114
|
+
'SQLParser::Statement::LessOrEquals',
|
115
|
+
'SQLParser::Statement::And',
|
116
|
+
'SQLParser::Statement::Or']
|
117
|
+
not_words = ['SQLParser::Statement::Not']
|
118
|
+
value_words = ['SQLParser::Statement::Float',
|
119
|
+
'SQLParser::Statement::Integer']
|
120
|
+
column_words = ['SQLParser::Statement::Column']
|
121
|
+
|
122
|
+
if root_words.include?(condition.class.to_s)
|
123
|
+
condition_parser(condition.left)
|
124
|
+
condition_parser(condition.right)
|
125
|
+
elsif not_words.include?(condition.class.to_s)
|
126
|
+
condition_parser(condition.value.left)
|
127
|
+
condition_parser(condition.value.right)
|
128
|
+
elsif column_words.include?(condition.class.to_s)
|
129
|
+
name = condition.name
|
130
|
+
index = RESERVED_PINS.index(name)
|
131
|
+
raise FrontendError, "unknown column value #{name}." if index.nil?
|
132
|
+
|
133
|
+
@in_pins.add(name)
|
134
|
+
elsif value_words.include?(condition.class.to_s)
|
135
|
+
# none
|
136
|
+
else
|
137
|
+
raise FrontendError, "unknown token value #{condition}."
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def check_rsleep
|
142
|
+
return if @ast.rsleep.nil?
|
143
|
+
|
144
|
+
@sleep_sec = @ast.rsleep.rsleep_specification.value
|
145
|
+
end
|
146
|
+
|
147
|
+
def check_rspeed
|
148
|
+
return if @ast.rspeed.nil?
|
149
|
+
|
150
|
+
@speed = @ast.rspeed.rspeed_specification.value
|
151
|
+
end
|
152
|
+
end
|
153
|
+
# rubocop:enable Metrics/ClassLength
|
154
|
+
end
|
data/lib/rossoc/ir.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rossoc'
|
4
|
+
|
5
|
+
# Rossoc
|
6
|
+
module Rossoc
|
7
|
+
# Ir
|
8
|
+
class Ir
|
9
|
+
# rubocop:disable Metrics/ParameterLists
|
10
|
+
def initialize(in_pins, out_pins, table, where, ast,
|
11
|
+
sleep_sec, speed)
|
12
|
+
@in_pins = in_pins
|
13
|
+
@out_pins = out_pins
|
14
|
+
@table = table
|
15
|
+
@where = where
|
16
|
+
@ast = ast
|
17
|
+
@sleep = Rsleep.new(sleep_sec)
|
18
|
+
@speed = speed
|
19
|
+
end
|
20
|
+
# rubocop:enable Metrics/ParameterLists
|
21
|
+
|
22
|
+
# rubocop:disable Metrics/MethodLength
|
23
|
+
def result
|
24
|
+
din_pins = Set.new
|
25
|
+
ain_pins = Set.new
|
26
|
+
dout_pins = Set.new
|
27
|
+
aout_pins = Set.new
|
28
|
+
|
29
|
+
[@in_pins, @out_pins].each_with_index do |pins, i|
|
30
|
+
pins.each do |pin|
|
31
|
+
n = pin.gsub(/din|ain/, '').to_i
|
32
|
+
if pin.start_with?('din')
|
33
|
+
if i.zero?
|
34
|
+
din_pins.add(n)
|
35
|
+
else
|
36
|
+
dout_pins.add(n)
|
37
|
+
end
|
38
|
+
elsif i.zero?
|
39
|
+
ain_pins.add(n)
|
40
|
+
else
|
41
|
+
aout_pins.add(n)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
{
|
47
|
+
din_pins: din_pins,
|
48
|
+
ain_pins: ain_pins,
|
49
|
+
dout_pins: dout_pins,
|
50
|
+
aout_pins: aout_pins,
|
51
|
+
table: @table,
|
52
|
+
where: @where,
|
53
|
+
ast: @ast,
|
54
|
+
sleep: @sleep,
|
55
|
+
speed: @speed
|
56
|
+
}
|
57
|
+
end
|
58
|
+
# rubocop:enable Metrics/MethodLength
|
59
|
+
|
60
|
+
# RSLEEP
|
61
|
+
class Rsleep
|
62
|
+
def initialize(second)
|
63
|
+
@second = second
|
64
|
+
end
|
65
|
+
|
66
|
+
def positive?
|
67
|
+
@second.positive?
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_reader :second
|
71
|
+
|
72
|
+
def millisecond
|
73
|
+
(@second * 1000).to_i
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,346 @@
|
|
1
|
+
#
|
2
|
+
# Original source code
|
3
|
+
# sql-parser
|
4
|
+
# https://github.com/cryodex/sql-parser
|
5
|
+
#
|
6
|
+
|
7
|
+
class SQLParser::Parser
|
8
|
+
|
9
|
+
rule
|
10
|
+
# dynamic sql
|
11
|
+
|
12
|
+
direct_sql_statement
|
13
|
+
: direct_sql_data_statement
|
14
|
+
|
15
|
+
direct_sql_data_statement
|
16
|
+
: direct_select_statement_multiple_rows
|
17
|
+
| insert_specification
|
18
|
+
|
19
|
+
direct_select_statement_multiple_rows
|
20
|
+
: query_expression order_by_clause rsleep_clause rspeed_clause { result = SQLParser::Statement::DirectSelect.new(val[0], val[1], val[2], val[3]) }
|
21
|
+
|
22
|
+
# module contents
|
23
|
+
rsleep_clause
|
24
|
+
: # no action
|
25
|
+
| RSLEEP unsigned_literal { result = SQLParser::Statement::Rsleep.new(val[1]) }
|
26
|
+
|
27
|
+
rspeed_clause
|
28
|
+
: # no action
|
29
|
+
| RSPEED unsigned_literal { result = SQLParser::Statement::Rspeed.new(val[1]) }
|
30
|
+
|
31
|
+
order_by_clause
|
32
|
+
: # no action
|
33
|
+
| ORDER BY sort_specification_list { result = SQLParser::Statement::OrderBy.new(val[2]) }
|
34
|
+
|
35
|
+
sort_specification_list
|
36
|
+
: sort_specification_list comma sort_specification { result = Array(val[0]) + Array(val[2]) }
|
37
|
+
| sort_specification
|
38
|
+
|
39
|
+
sort_specification
|
40
|
+
: sort_key ordering_specification { result = val[1].new(val[0]) }
|
41
|
+
|
42
|
+
sort_key
|
43
|
+
: column_name
|
44
|
+
| unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
|
45
|
+
|
46
|
+
ordering_specification
|
47
|
+
: { result = SQLParser::Statement::Ascending } # default
|
48
|
+
| ASC { result = SQLParser::Statement::Ascending }
|
49
|
+
| DESC { result = SQLParser::Statement::Descending }
|
50
|
+
|
51
|
+
# queries
|
52
|
+
subquery
|
53
|
+
# FIXME: shortcut
|
54
|
+
: left_paren query_expression right_paren { result = SQLParser::Statement::Subquery.new(val[1]) }
|
55
|
+
|
56
|
+
query_expression
|
57
|
+
: query_specification
|
58
|
+
|
59
|
+
insert_specification
|
60
|
+
: INSERT INTO table_reference value_list { result = SQLParser::Statement::Insert.new(val[2], nil, val[3]) }
|
61
|
+
| INSERT INTO table_reference column_list value_list { result = SQLParser::Statement::Insert.new(val[2], val[3], val[4]) }
|
62
|
+
|
63
|
+
column_list
|
64
|
+
: left_paren in_column_list right_paren { result = SQLParser::Statement::InColumnList.new(val[1]) }
|
65
|
+
|
66
|
+
in_column_list
|
67
|
+
: value_expression comma in_column_list { result = Array(val[0]) + Array(val[2]) }
|
68
|
+
| value_expression
|
69
|
+
|
70
|
+
value_list
|
71
|
+
: VALUES left_paren in_value_list right_paren { result = SQLParser::Statement::InValueList.new(val[2]) }
|
72
|
+
|
73
|
+
query_specification
|
74
|
+
: SELECT select_list table_expression { result = SQLParser::Statement::Select.new(val[1], val[2]) }
|
75
|
+
| SELECT select_list { result = SQLParser::Statement::Select.new(val[1]) }
|
76
|
+
|
77
|
+
select_list
|
78
|
+
: asterisk { result = SQLParser::Statement::All.new }
|
79
|
+
| select_sublist { result = SQLParser::Statement::SelectList.new(val[0]) }
|
80
|
+
|
81
|
+
select_sublist
|
82
|
+
: derived_column comma select_sublist { result = Array(val[0]) + Array(val[2]) }
|
83
|
+
| derived_column
|
84
|
+
|
85
|
+
derived_column
|
86
|
+
: value_expression AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
|
87
|
+
| value_expression column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
|
88
|
+
| value_expression
|
89
|
+
|
90
|
+
table_expression
|
91
|
+
: from_clause where_clause group_by_clause having_clause { result = SQLParser::Statement::TableExpression.new(val[0], val[1], val[2], val[3]) }
|
92
|
+
|
93
|
+
from_clause
|
94
|
+
: FROM table_reference { result = SQLParser::Statement::FromClause.new(val[1]) }
|
95
|
+
|
96
|
+
table_reference
|
97
|
+
: table_name AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
|
98
|
+
| table_name column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
|
99
|
+
| table_name
|
100
|
+
| joined_table
|
101
|
+
|
102
|
+
table_subquery
|
103
|
+
: subquery
|
104
|
+
|
105
|
+
joined_table
|
106
|
+
: cross_join
|
107
|
+
| qualified_join
|
108
|
+
|
109
|
+
cross_join
|
110
|
+
: table_reference comma table_name { result = SQLParser::Statement::CrossJoin.new(val[0], val[2]) }
|
111
|
+
| table_reference CROSS JOIN table_name { result = SQLParser::Statement::CrossJoin.new(val[0], val[3]) }
|
112
|
+
|
113
|
+
qualified_join
|
114
|
+
: table_reference join_type JOIN table_reference join_specification { result = val[1].new(val[0], val[3], val[4]) }
|
115
|
+
|
116
|
+
join_type
|
117
|
+
: INNER { result = SQLParser::Statement::InnerJoin }
|
118
|
+
| LEFT OUTER { result = SQLParser::Statement::LeftOuterJoin }
|
119
|
+
| LEFT { result = SQLParser::Statement::LeftJoin }
|
120
|
+
| RIGHT OUTER { result = SQLParser::Statement::RightOuterJoin }
|
121
|
+
| RIGHT { result = SQLParser::Statement::RightJoin }
|
122
|
+
| FULL { result = SQLParser::Statement::FullJoin }
|
123
|
+
| FULL OUTER { result = SQLParser::Statement::FullOuterJoin }
|
124
|
+
|
125
|
+
join_specification
|
126
|
+
: join_condition
|
127
|
+
| named_columns_join
|
128
|
+
|
129
|
+
join_condition
|
130
|
+
: ON search_condition { result = SQLParser::Statement::On.new(val[1]) }
|
131
|
+
|
132
|
+
named_columns_join
|
133
|
+
: USING left_paren join_column_list right_paren { result = SQLParser::Statement::Using.new(val[2]) }
|
134
|
+
|
135
|
+
join_column_list
|
136
|
+
: column_name_list
|
137
|
+
|
138
|
+
where_clause
|
139
|
+
: # no action
|
140
|
+
| WHERE search_condition { result = SQLParser::Statement::WhereClause.new(val[1]) }
|
141
|
+
|
142
|
+
group_by_clause
|
143
|
+
: # no action
|
144
|
+
| GROUP BY grouping_column_reference_list { result = SQLParser::Statement::GroupByClause.new(val[2]) }
|
145
|
+
|
146
|
+
grouping_column_reference_list
|
147
|
+
: grouping_column_reference_list comma grouping_column_reference { result = Array(val[0]) + Array(val[2]) }
|
148
|
+
| grouping_column_reference
|
149
|
+
|
150
|
+
grouping_column_reference
|
151
|
+
: column_reference
|
152
|
+
|
153
|
+
having_clause
|
154
|
+
: # no action
|
155
|
+
| HAVING search_condition { result = SQLParser::Statement::HavingClause.new(val[1]) }
|
156
|
+
|
157
|
+
# query expression components
|
158
|
+
row_subquery
|
159
|
+
: subquery
|
160
|
+
|
161
|
+
between_predicate
|
162
|
+
: row_value_constructor NOT BETWEEN row_value_constructor AND row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Between.new(val[0], val[3], val[5])) }
|
163
|
+
| row_value_constructor BETWEEN row_value_constructor AND row_value_constructor { result = SQLParser::Statement::Between.new(val[0], val[2], val[4]) }
|
164
|
+
|
165
|
+
in_predicate
|
166
|
+
: row_value_constructor NOT IN in_predicate_value { result = SQLParser::Statement::Not.new(SQLParser::Statement::In.new(val[0], val[3])) }
|
167
|
+
| row_value_constructor IN in_predicate_value { result = SQLParser::Statement::In.new(val[0], val[2]) }
|
168
|
+
|
169
|
+
in_predicate_value
|
170
|
+
: table_subquery
|
171
|
+
| left_paren in_value_list right_paren { result = SQLParser::Statement::InValueList.new(val[1]) }
|
172
|
+
|
173
|
+
in_value_list
|
174
|
+
: value_expression comma in_value_list { result = Array(val[0]) + Array(val[2]) }
|
175
|
+
| value_expression
|
176
|
+
|
177
|
+
like_predicate
|
178
|
+
# FIXME: the SQL-92 grammar indicates these should be
|
179
|
+
# character_value_expression nodes, but changing them causes reduce/reduce
|
180
|
+
# conflicts.
|
181
|
+
: row_value_constructor NOT LIKE row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Like.new(val[0], val[3])) }
|
182
|
+
| row_value_constructor LIKE row_value_constructor { result = SQLParser::Statement::Like.new(val[0], val[2]) }
|
183
|
+
|
184
|
+
null_predicate
|
185
|
+
: row_value_constructor IS NOT NULL { result = SQLParser::Statement::Not.new(SQLParser::Statement::Is.new(val[0], SQLParser::Statement::Null.new)) }
|
186
|
+
| row_value_constructor IS NULL { result = SQLParser::Statement::Is.new(val[0], SQLParser::Statement::Null.new) }
|
187
|
+
|
188
|
+
exists_predicate
|
189
|
+
: EXISTS table_subquery { result = SQLParser::Statement::Exists.new(val[1]) }
|
190
|
+
|
191
|
+
# constraints
|
192
|
+
table_name
|
193
|
+
: identifier { result = SQLParser::Statement::Table.new(val[0]) }
|
194
|
+
|
195
|
+
column_name_list
|
196
|
+
: column_name_list comma column_name { result = Array(val[0]) + Array(val[2]) }
|
197
|
+
| column_name
|
198
|
+
|
199
|
+
# search condition
|
200
|
+
search_condition
|
201
|
+
: boolean_term
|
202
|
+
| search_condition OR boolean_term { result = SQLParser::Statement::Or.new(val[0], val[2]) }
|
203
|
+
|
204
|
+
boolean_term
|
205
|
+
: boolean_factor
|
206
|
+
| boolean_term AND boolean_factor { result = SQLParser::Statement::And.new(val[0], val[2]) }
|
207
|
+
|
208
|
+
boolean_factor:
|
209
|
+
: NOT boolean_test { result = SQLParser::Statement::Not.new(val[1]) }
|
210
|
+
| boolean_test
|
211
|
+
|
212
|
+
boolean_test
|
213
|
+
: boolean_primary
|
214
|
+
|
215
|
+
boolean_primary
|
216
|
+
: predicate
|
217
|
+
| left_paren search_condition right_paren { result = val[1] }
|
218
|
+
|
219
|
+
predicate
|
220
|
+
: comparison_predicate
|
221
|
+
| between_predicate
|
222
|
+
| in_predicate
|
223
|
+
| like_predicate
|
224
|
+
| null_predicate
|
225
|
+
| exists_predicate
|
226
|
+
|
227
|
+
comparison_predicate
|
228
|
+
: row_value_constructor equals_operator row_value_constructor { result = SQLParser::Statement::Equals.new(val[0], val[2]) }
|
229
|
+
| row_value_constructor not_equals_operator row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Equals.new(val[0], val[2])) }
|
230
|
+
| row_value_constructor less_than_operator row_value_constructor { result = SQLParser::Statement::Less.new(val[0], val[2]) }
|
231
|
+
| row_value_constructor greater_than_operator row_value_constructor { result = SQLParser::Statement::Greater.new(val[0], val[2]) }
|
232
|
+
| row_value_constructor less_than_or_equals_operator row_value_constructor { result = SQLParser::Statement::LessOrEquals.new(val[0], val[2]) }
|
233
|
+
| row_value_constructor greater_than_or_equals_operator row_value_constructor { result = SQLParser::Statement::GreaterOrEquals.new(val[0], val[2]) }
|
234
|
+
|
235
|
+
row_value_constructor
|
236
|
+
: row_value_constructor_element
|
237
|
+
| row_subquery
|
238
|
+
|
239
|
+
row_value_constructor_element
|
240
|
+
: value_expression
|
241
|
+
|
242
|
+
value_expression
|
243
|
+
: numeric_value_expression
|
244
|
+
| general_literal
|
245
|
+
|
246
|
+
numeric_value_expression
|
247
|
+
: term plus_sign numeric_value_expression { result = SQLParser::Statement::Add.new(val[0], val[2]) }
|
248
|
+
| term minus_sign numeric_value_expression { result = SQLParser::Statement::Subtract.new(val[0], val[2]) }
|
249
|
+
| term
|
250
|
+
|
251
|
+
term
|
252
|
+
: factor asterisk term { result = SQLParser::Statement::Multiply.new(val[0], val[2]) }
|
253
|
+
| factor solidus term { result = SQLParser::Statement::Divide.new(val[0], val[2]) }
|
254
|
+
| factor
|
255
|
+
|
256
|
+
factor
|
257
|
+
: sign value_expression_primary { result = val[0].new(val[1]) }
|
258
|
+
| value_expression_primary
|
259
|
+
|
260
|
+
value_expression_primary
|
261
|
+
: unsigned_value_specification
|
262
|
+
| column_reference
|
263
|
+
| set_function_specification
|
264
|
+
| left_paren value_expression right_paren { result = val[1] }
|
265
|
+
|
266
|
+
unsigned_value_specification
|
267
|
+
: unsigned_literal
|
268
|
+
| general_value_specification
|
269
|
+
|
270
|
+
unsigned_literal
|
271
|
+
: unsigned_numeric_literal
|
272
|
+
| general_literal
|
273
|
+
|
274
|
+
general_value_specification
|
275
|
+
: CURRENT_USER { result = SQLParser::Statement::CurrentUser.new }
|
276
|
+
|
277
|
+
column_reference
|
278
|
+
: qualifier period column_name { result = SQLParser::Statement::QualifiedColumn.new(val[0], val[2]) }
|
279
|
+
| column_name
|
280
|
+
|
281
|
+
qualifier
|
282
|
+
: table_name
|
283
|
+
|
284
|
+
set_function_specification
|
285
|
+
: COUNT left_paren asterisk right_paren { result = SQLParser::Statement::Count.new(SQLParser::Statement::All.new) }
|
286
|
+
| general_set_function
|
287
|
+
|
288
|
+
general_set_function
|
289
|
+
: COUNT left_paren value_expression right_paren { result = SQLParser::Statement::Count.new(val[2]) }
|
290
|
+
| AVG left_paren value_expression right_paren { result = SQLParser::Statement::Average.new(val[2]) }
|
291
|
+
| MAX left_paren value_expression right_paren { result = SQLParser::Statement::Maximum.new(val[2]) }
|
292
|
+
| MIN left_paren value_expression right_paren { result = SQLParser::Statement::Minimum.new(val[2]) }
|
293
|
+
| SUM left_paren value_expression right_paren { result = SQLParser::Statement::Sum.new(val[2]) }
|
294
|
+
|
295
|
+
# literal numbers, strings, dates and times
|
296
|
+
unsigned_numeric_literal
|
297
|
+
: exact_numeric_literal
|
298
|
+
| approximate_numeric_literal
|
299
|
+
|
300
|
+
exact_numeric_literal
|
301
|
+
: unsigned_integer period unsigned_integer { result = SQLParser::Statement::Float.new("#{val[0]}.#{val[2]}".to_f) }
|
302
|
+
| unsigned_integer period { result = SQLParser::Statement::Float.new(val[0]) }
|
303
|
+
| period unsigned_integer { result = SQLParser::Statement::Float.new("0.#{val[1]}".to_f) }
|
304
|
+
| unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
|
305
|
+
|
306
|
+
approximate_numeric_literal
|
307
|
+
: mantissa E exponent { result = SQLParser::Statement::ApproximateFloat.new(val[0], val[2]) }
|
308
|
+
|
309
|
+
mantissa
|
310
|
+
: exact_numeric_literal
|
311
|
+
|
312
|
+
exponent
|
313
|
+
: signed_integer
|
314
|
+
|
315
|
+
signed_integer
|
316
|
+
: sign unsigned_integer { result = val[0].new(SQLParser::Statement::Integer.new(val[1])) }
|
317
|
+
| unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
|
318
|
+
|
319
|
+
sign
|
320
|
+
: plus_sign { result = SQLParser::Statement::UnaryPlus }
|
321
|
+
| minus_sign { result = SQLParser::Statement::UnaryMinus }
|
322
|
+
|
323
|
+
# sql module
|
324
|
+
column_name
|
325
|
+
: identifier { result = SQLParser::Statement::Column.new(val[0]) }
|
326
|
+
|
327
|
+
# literals
|
328
|
+
general_literal
|
329
|
+
: quote character_string_literal quote { result = SQLParser::Statement::String.new(val[1]) }
|
330
|
+
| quote quote { result = SQLParser::Statement::String.new('') }
|
331
|
+
| datetime_literal
|
332
|
+
|
333
|
+
datetime_literal
|
334
|
+
: date_literal
|
335
|
+
|
336
|
+
date_literal
|
337
|
+
: DATE date_string { result = SQLParser::Statement::Date.new(val[1]) }
|
338
|
+
|
339
|
+
---- header ----
|
340
|
+
require File.dirname(__FILE__) + '/parser.rex.rb'
|
341
|
+
|
342
|
+
---- inner ----
|
343
|
+
|
344
|
+
def self.parse(sql)
|
345
|
+
new.scan_str(sql)
|
346
|
+
end
|