sql_tree 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/sql_tree/node/assignment.rb +22 -0
- data/lib/sql_tree/node/delete_query.rb +28 -0
- data/lib/sql_tree/node/insert_query.rb +51 -0
- data/lib/sql_tree/node/select_query.rb +1 -1
- data/lib/sql_tree/node/update_query.rb +36 -0
- data/lib/sql_tree/node/variable.rb +1 -1
- data/lib/sql_tree/parser.rb +3 -0
- data/lib/sql_tree/token.rb +1 -1
- data/spec/integration/{full_queries_spec.rb → parse_and_generate_spec.rb} +34 -0
- data/spec/unit/delete_query_spec.rb +16 -0
- data/spec/unit/insert_query_spec.rb +24 -0
- data/spec/unit/select_query_spec.rb +24 -0
- data/spec/unit/update_query_spec.rb +22 -0
- data/sql_tree.gemspec +3 -3
- metadata +13 -3
@@ -0,0 +1,22 @@
|
|
1
|
+
module SQLTree::Node
|
2
|
+
|
3
|
+
class Assignment < Base
|
4
|
+
|
5
|
+
attr_accessor :field, :expression
|
6
|
+
|
7
|
+
def initialize(field, expression = nil)
|
8
|
+
@field, @expression = field, expression
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_sql
|
12
|
+
"#{quote_var(field)} = #{expression.to_sql}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse(tokens)
|
16
|
+
assignment = self.new(SQLTree::Node::Variable.parse(tokens).name)
|
17
|
+
tokens.consume(SQLTree::Token::EQ)
|
18
|
+
assignment.expression = SQLTree::Node::Expression.parse(tokens)
|
19
|
+
assignment
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SQLTree::Node
|
2
|
+
|
3
|
+
class DeleteQuery < Base
|
4
|
+
|
5
|
+
attr_accessor :table, :where
|
6
|
+
|
7
|
+
def initialize(table, where = nil)
|
8
|
+
@table, @where = table, where
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_sql
|
12
|
+
sql = "DELETE FROM #{self.quote_var(table)}"
|
13
|
+
sql << " WHERE #{where.to_sql}" if self.where
|
14
|
+
sql
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(tokens)
|
18
|
+
tokens.consume(SQLTree::Token::DELETE)
|
19
|
+
tokens.consume(SQLTree::Token::FROM)
|
20
|
+
delete_query = self.new(SQLTree::Node::Variable.parse(tokens).name)
|
21
|
+
if tokens.peek == SQLTree::Token::WHERE
|
22
|
+
tokens.consume(SQLTree::Token::WHERE)
|
23
|
+
delete_query.where = SQLTree::Node::Expression.parse(tokens)
|
24
|
+
end
|
25
|
+
return delete_query
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SQLTree::Node
|
2
|
+
|
3
|
+
class InsertQuery < Base
|
4
|
+
|
5
|
+
attr_accessor :table, :fields, :values
|
6
|
+
|
7
|
+
def initialize(table, fields = nil, values = [])
|
8
|
+
@table, @fields, @values = table, fields, values
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_sql
|
12
|
+
sql = "INSERT INTO #{self.quote_var(table)} "
|
13
|
+
sql << '(' + fields.map { |f| f.to_sql }.join(', ') + ') ' if fields
|
14
|
+
sql << 'VALUES (' + values.map { |v| v.to_sql }.join(', ') + ')'
|
15
|
+
sql
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse_field_list(tokens)
|
19
|
+
tokens.consume(SQLTree::Token::LPAREN)
|
20
|
+
fields = [SQLTree::Node::Variable.parse(tokens)]
|
21
|
+
while tokens.peek == SQLTree::Token::COMMA
|
22
|
+
tokens.consume(SQLTree::Token::COMMA)
|
23
|
+
fields << SQLTree::Node::Variable.parse(tokens)
|
24
|
+
end
|
25
|
+
tokens.consume(SQLTree::Token::RPAREN)
|
26
|
+
return fields
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse_value_list(tokens)
|
30
|
+
tokens.consume(SQLTree::Token::VALUES)
|
31
|
+
tokens.consume(SQLTree::Token::LPAREN)
|
32
|
+
values = [SQLTree::Node::Expression.parse(tokens)]
|
33
|
+
while tokens.peek == SQLTree::Token::COMMA
|
34
|
+
tokens.consume(SQLTree::Token::COMMA)
|
35
|
+
values << SQLTree::Node::Expression.parse(tokens)
|
36
|
+
end
|
37
|
+
tokens.consume(SQLTree::Token::RPAREN)
|
38
|
+
return values
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse(tokens)
|
42
|
+
tokens.consume(SQLTree::Token::INSERT)
|
43
|
+
tokens.consume(SQLTree::Token::INTO)
|
44
|
+
insert_query = self.new(SQLTree::Node::Variable.parse(tokens).name)
|
45
|
+
|
46
|
+
insert_query.fields = self.parse_field_list(tokens) if tokens.peek == SQLTree::Token::LPAREN
|
47
|
+
insert_query.values = self.parse_value_list(tokens)
|
48
|
+
return insert_query
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -13,7 +13,7 @@ module SQLTree::Node
|
|
13
13
|
raise "At least one SELECT expression is required" if self.select.empty?
|
14
14
|
sql = (self.distinct) ? "SELECT DISTINCT " : "SELECT "
|
15
15
|
sql << select.map { |s| s.to_sql }.join(', ')
|
16
|
-
sql << " FROM " << from.map { |f| f.to_sql }.join(', ')
|
16
|
+
sql << " FROM " << from.map { |f| f.to_sql }.join(', ') if from
|
17
17
|
sql << " WHERE " << where.to_sql if where
|
18
18
|
sql << " GROUP BY " << group_by.map { |g| g.to_sql }.join(', ') if group_by
|
19
19
|
sql << " ORDER BY " << order_by.map { |o| o.to_sql }.join(', ') if order_by
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module SQLTree::Node
|
2
|
+
|
3
|
+
class UpdateQuery < Base
|
4
|
+
|
5
|
+
attr_accessor :table, :updates, :where
|
6
|
+
|
7
|
+
def initialize(table, updates = [], where = nil)
|
8
|
+
@table, @updates, @where = table, updates, where
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_sql
|
12
|
+
sql = "UPDATE #{self.quote_var(table)} SET "
|
13
|
+
sql << updates.map { |u| u.to_sql }.join(', ')
|
14
|
+
sql << " WHERE " << where.to_sql if self.where
|
15
|
+
sql
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse(tokens)
|
19
|
+
tokens.consume(SQLTree::Token::UPDATE)
|
20
|
+
update_query = self.new(SQLTree::Node::Variable.parse(tokens).name)
|
21
|
+
tokens.consume(SQLTree::Token::SET)
|
22
|
+
update_query.updates = [SQLTree::Node::Assignment.parse(tokens)]
|
23
|
+
while tokens.peek == SQLTree::Token::COMMA
|
24
|
+
tokens.consume(SQLTree::Token::COMMA)
|
25
|
+
update_query.updates << SQLTree::Node::Assignment.parse(tokens)
|
26
|
+
end
|
27
|
+
|
28
|
+
if tokens.peek == SQLTree::Token::WHERE
|
29
|
+
tokens.consume(SQLTree::Token::WHERE)
|
30
|
+
update_query.where = SQLTree::Node::Expression.parse(tokens)
|
31
|
+
end
|
32
|
+
|
33
|
+
update_query
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/sql_tree/parser.rb
CHANGED
@@ -57,6 +57,9 @@ class SQLTree::Parser
|
|
57
57
|
def parse!
|
58
58
|
case self.peek
|
59
59
|
when SQLTree::Token::SELECT then SQLTree::Node::SelectQuery.parse(self)
|
60
|
+
when SQLTree::Token::INSERT then SQLTree::Node::InsertQuery.parse(self)
|
61
|
+
when SQLTree::Token::DELETE then SQLTree::Node::DeleteQuery.parse(self)
|
62
|
+
when SQLTree::Token::UPDATE then SQLTree::Node::UpdateQuery.parse(self)
|
60
63
|
else raise UnexpectedToken.new(self.peek)
|
61
64
|
end
|
62
65
|
end
|
data/lib/sql_tree/token.rb
CHANGED
@@ -112,7 +112,7 @@ class SQLTree::Token
|
|
112
112
|
|
113
113
|
# A list of all the SQL reserverd keywords.
|
114
114
|
KEYWORDS = %w{SELECT FROM WHERE GROUP HAVING ORDER DISTINCT LEFT RIGHT INNER FULL OUTER NATURAL JOIN USING
|
115
|
-
AND OR NOT AS ON IS NULL BY LIKE ILIKE BETWEEN IN ASC DESC}
|
115
|
+
AND OR NOT AS ON IS NULL BY LIKE ILIKE BETWEEN IN ASC DESC INSERT INTO VALUES DELETE UPDATE SET}
|
116
116
|
|
117
117
|
# Create a token for all the reserved keywords in SQL
|
118
118
|
KEYWORDS.each { |kw| const_set(kw, Class.new(SQLTree::Token::Keyword).new(kw)) }
|
@@ -2,6 +2,10 @@ require "#{File.dirname(__FILE__)}/../spec_helper"
|
|
2
2
|
|
3
3
|
describe SQLTree, 'parsing and generating SQL' do
|
4
4
|
|
5
|
+
it "should parse an generate q query without FROM" do
|
6
|
+
SQLTree['SELECT 1'].to_sql.should == 'SELECT 1'
|
7
|
+
end
|
8
|
+
|
5
9
|
it "should parse and generate SQL fo a simple list query" do
|
6
10
|
SQLTree["SELECT * FROM table"].to_sql.should == 'SELECT * FROM "table"'
|
7
11
|
end
|
@@ -38,4 +42,34 @@ describe SQLTree, 'parsing and generating SQL' do
|
|
38
42
|
SQLTree['SELECT SUM( field1 ) FROM t GROUP BY field1, MD5( field2 ) HAVING SUM( field1 ) > 10'].to_sql.should ==
|
39
43
|
'SELECT SUM("field1") FROM "t" GROUP BY "field1", MD5("field2") HAVING (SUM("field1") > 10)'
|
40
44
|
end
|
45
|
+
|
46
|
+
it "should parse and generate an INSERT query with field list" do
|
47
|
+
SQLTree['INSERT INTO table ( field1, field2) VALUES (1, 2)'].to_sql.should ==
|
48
|
+
'INSERT INTO "table" ("field1", "field2") VALUES (1, 2)'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse and generate an INSERT query without field list" do
|
52
|
+
SQLTree['INSERT INTO table VALUES (1, 2)'].to_sql.should ==
|
53
|
+
'INSERT INTO "table" VALUES (1, 2)'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should parse and generate an DELETE query without WHERE clause" do
|
57
|
+
SQLTree['DELETE FROM table'].to_sql.should ==
|
58
|
+
'DELETE FROM "table"'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should parse and generate an DELETE query with WHERE clause" do
|
62
|
+
SQLTree['DELETE FROM table WHERE 1 = 1'].to_sql.should ==
|
63
|
+
'DELETE FROM "table" WHERE (1 = 1)'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should parse and generate an UPDATE query without WHERE clause" do
|
67
|
+
SQLTree['UPDATE table SET field1 = 1, field2 = 2'].to_sql.should ==
|
68
|
+
'UPDATE "table" SET "field1" = 1, "field2" = 2'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should parse and generate an UPDATE query with WHERE clause" do
|
72
|
+
SQLTree['UPDATE table SET field1 = 123 WHERE id = 17'].to_sql.should ==
|
73
|
+
'UPDATE "table" SET "field1" = 123 WHERE ("id" = 17)'
|
74
|
+
end
|
41
75
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
describe SQLTree::Node::DeleteQuery do
|
4
|
+
|
5
|
+
it "should parse a delete query without WHERE clause correctly" do
|
6
|
+
delete = SQLTree::Node::DeleteQuery["DELETE FROM table"]
|
7
|
+
delete.table.should == 'table'
|
8
|
+
delete.where.should be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should parse a delete query without WHERE clause correctly" do
|
12
|
+
delete = SQLTree::Node::DeleteQuery["DELETE FROM table WHERE 1 = 1"]
|
13
|
+
delete.table.should == 'table'
|
14
|
+
delete.where.should be_kind_of(SQLTree::Node::Expression)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
describe SQLTree::Node::InsertQuery do
|
4
|
+
|
5
|
+
it "should parse an insert query without field list correctly" do
|
6
|
+
insert = SQLTree::Node::InsertQuery["INSERT INTO table VALUES (1, 'two', 3+4, MD5('$ecret'))"]
|
7
|
+
insert.table.should == 'table'
|
8
|
+
insert.fields.should be_nil
|
9
|
+
insert.values.should have(4).items
|
10
|
+
insert.values[0].should == SQLTree::Node::Value.new(1)
|
11
|
+
insert.values[1].should == SQLTree::Node::Value.new('two')
|
12
|
+
insert.values[2].should be_kind_of(SQLTree::Node::ArithmeticExpression)
|
13
|
+
insert.values[3].should be_kind_of(SQLTree::Node::FunctionExpression)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should parse an insert query with field list" do
|
17
|
+
insert = SQLTree::Node::InsertQuery['INSERT INTO table ("field1", "field2") VALUES (1, 2)']
|
18
|
+
insert.table.should == 'table'
|
19
|
+
insert.fields.should have(2).items
|
20
|
+
insert.fields[0].should == SQLTree::Node::Variable.new('field1')
|
21
|
+
insert.fields[1].should == SQLTree::Node::Variable.new('field2')
|
22
|
+
insert.values.should have(2).items
|
23
|
+
end
|
24
|
+
end
|
@@ -1,5 +1,29 @@
|
|
1
1
|
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
2
|
|
3
|
+
describe SQLTree::Node::SelectQuery do
|
4
|
+
|
5
|
+
it "should parse a query without FROM, WHERE, ORDER, GROUP or HAVING clause" do
|
6
|
+
tree = SQLTree::Node::SelectQuery['SELECT 1']
|
7
|
+
tree.select.first.expression.value.should == 1
|
8
|
+
tree.from.should be_nil
|
9
|
+
tree.where.should be_nil
|
10
|
+
tree.group_by.should be_nil
|
11
|
+
tree.having.should be_nil
|
12
|
+
tree.order_by.should be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse a query with all clauses" do
|
16
|
+
tree = SQLTree::Node::SelectQuery['SELECT 1 AS static, field FROM table1 AS t1, table2 LEFT JOIN table3 t3 ON (t1.id = t2.id)
|
17
|
+
WHERE t1.field = 1234 GROUP BY t2.group_field HAVING SUM(t2.group_field) > 100 ORDER BY t.timestamp DESC']
|
18
|
+
|
19
|
+
tree.select.length.should == 2
|
20
|
+
tree.from.length.should == 2
|
21
|
+
tree.where.should be_kind_of(SQLTree::Node::ComparisonExpression)
|
22
|
+
tree.group_by.first.should be_kind_of(SQLTree::Node::Field)
|
23
|
+
tree.having.should be_kind_of(SQLTree::Node::ComparisonExpression)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
3
27
|
describe SQLTree::Node::Source do
|
4
28
|
|
5
29
|
it "should parse the table name correctly" do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
describe SQLTree::Node::UpdateQuery do
|
4
|
+
|
5
|
+
it "should parse a delete query without WHERE clause correctly" do
|
6
|
+
update = SQLTree::Node::UpdateQuery["UPDATE table SET field1 = 1, field2 = 5 - 3"]
|
7
|
+
update.table.should == 'table'
|
8
|
+
update.updates.should have(2).items
|
9
|
+
update.updates[0].field.should == 'field1'
|
10
|
+
update.updates[0].expression.should == SQLTree::Node::Value.new(1)
|
11
|
+
update.updates[1].field.should == 'field2'
|
12
|
+
update.updates[1].expression.should be_kind_of(SQLTree::Node::ArithmeticExpression)
|
13
|
+
update.where.should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should parse a delete query without WHERE clause correctly" do
|
17
|
+
update = SQLTree::Node::UpdateQuery["UPDATE table SET field = 1 WHERE id = 17"]
|
18
|
+
update.table.should == 'table'
|
19
|
+
update.updates.should have(1).item
|
20
|
+
update.where.should be_kind_of(SQLTree::Node::Expression)
|
21
|
+
end
|
22
|
+
end
|
data/sql_tree.gemspec
CHANGED
@@ -3,7 +3,7 @@ Gem::Specification.new do |s|
|
|
3
3
|
|
4
4
|
# Do not modify the version and date values by hand, because this will
|
5
5
|
# automatically by them gem release script.
|
6
|
-
s.version = "0.0
|
6
|
+
s.version = "0.1.0"
|
7
7
|
s.date = "2009-10-09"
|
8
8
|
|
9
9
|
s.summary = "A pure Ruby library to represent SQL queries with a syntax tree for inspection and modification."
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
# Do not modify the files and test_files values by hand, because this will
|
24
24
|
# automatically by them gem release script.
|
25
|
-
s.files = %w(spec/unit/select_query_spec.rb spec/spec_helper.rb lib/sql_tree/tokenizer.rb lib/sql_tree/node/variable.rb lib/sql_tree/node/join.rb .gitignore lib/sql_tree/node/ordering.rb LICENSE spec/lib/matchers.rb
|
26
|
-
s.test_files = %w(spec/unit/select_query_spec.rb spec/
|
25
|
+
s.files = %w(spec/unit/select_query_spec.rb spec/unit/insert_query_spec.rb spec/spec_helper.rb lib/sql_tree/tokenizer.rb lib/sql_tree/node/variable.rb lib/sql_tree/node/join.rb .gitignore lib/sql_tree/node/ordering.rb LICENSE spec/lib/matchers.rb lib/sql_tree/parser.rb sql_tree.gemspec spec/unit/tokenizer_spec.rb spec/unit/expression_node_spec.rb spec/unit/delete_query_spec.rb lib/sql_tree/node/select_expression.rb lib/sql_tree/node/assignment.rb spec/unit/leaf_node_spec.rb lib/sql_tree/token.rb lib/sql_tree/node/table_reference.rb lib/sql_tree/node/source.rb lib/sql_tree/node/insert_query.rb lib/sql_tree/node/field.rb Rakefile tasks/github-gem.rake spec/unit/update_query_spec.rb spec/integration/parse_and_generate_spec.rb lib/sql_tree/node/select_query.rb lib/sql_tree/node.rb README.rdoc spec/integration/api_spec.rb lib/sql_tree/node/value.rb lib/sql_tree/node/expression.rb lib/sql_tree/node/delete_query.rb lib/sql_tree.rb lib/sql_tree/node/update_query.rb)
|
26
|
+
s.test_files = %w(spec/unit/select_query_spec.rb spec/unit/insert_query_spec.rb spec/unit/tokenizer_spec.rb spec/unit/expression_node_spec.rb spec/unit/delete_query_spec.rb spec/unit/leaf_node_spec.rb spec/unit/update_query_spec.rb spec/integration/parse_and_generate_spec.rb spec/integration/api_spec.rb)
|
27
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sql_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Willem van Bergen
|
@@ -23,6 +23,7 @@ extra_rdoc_files:
|
|
23
23
|
- README.rdoc
|
24
24
|
files:
|
25
25
|
- spec/unit/select_query_spec.rb
|
26
|
+
- spec/unit/insert_query_spec.rb
|
26
27
|
- spec/spec_helper.rb
|
27
28
|
- lib/sql_tree/tokenizer.rb
|
28
29
|
- lib/sql_tree/node/variable.rb
|
@@ -31,26 +32,32 @@ files:
|
|
31
32
|
- lib/sql_tree/node/ordering.rb
|
32
33
|
- LICENSE
|
33
34
|
- spec/lib/matchers.rb
|
34
|
-
- spec/integration/full_queries_spec.rb
|
35
35
|
- lib/sql_tree/parser.rb
|
36
36
|
- sql_tree.gemspec
|
37
37
|
- spec/unit/tokenizer_spec.rb
|
38
38
|
- spec/unit/expression_node_spec.rb
|
39
|
+
- spec/unit/delete_query_spec.rb
|
39
40
|
- lib/sql_tree/node/select_expression.rb
|
41
|
+
- lib/sql_tree/node/assignment.rb
|
40
42
|
- spec/unit/leaf_node_spec.rb
|
41
43
|
- lib/sql_tree/token.rb
|
42
44
|
- lib/sql_tree/node/table_reference.rb
|
43
45
|
- lib/sql_tree/node/source.rb
|
46
|
+
- lib/sql_tree/node/insert_query.rb
|
44
47
|
- lib/sql_tree/node/field.rb
|
45
48
|
- Rakefile
|
46
49
|
- tasks/github-gem.rake
|
50
|
+
- spec/unit/update_query_spec.rb
|
51
|
+
- spec/integration/parse_and_generate_spec.rb
|
47
52
|
- lib/sql_tree/node/select_query.rb
|
48
53
|
- lib/sql_tree/node.rb
|
49
54
|
- README.rdoc
|
50
55
|
- spec/integration/api_spec.rb
|
51
56
|
- lib/sql_tree/node/value.rb
|
52
57
|
- lib/sql_tree/node/expression.rb
|
58
|
+
- lib/sql_tree/node/delete_query.rb
|
53
59
|
- lib/sql_tree.rb
|
60
|
+
- lib/sql_tree/node/update_query.rb
|
54
61
|
has_rdoc: true
|
55
62
|
homepage: http://wiki.github.com/wvanbergen/sql_tree
|
56
63
|
licenses: []
|
@@ -86,8 +93,11 @@ specification_version: 3
|
|
86
93
|
summary: A pure Ruby library to represent SQL queries with a syntax tree for inspection and modification.
|
87
94
|
test_files:
|
88
95
|
- spec/unit/select_query_spec.rb
|
89
|
-
- spec/
|
96
|
+
- spec/unit/insert_query_spec.rb
|
90
97
|
- spec/unit/tokenizer_spec.rb
|
91
98
|
- spec/unit/expression_node_spec.rb
|
99
|
+
- spec/unit/delete_query_spec.rb
|
92
100
|
- spec/unit/leaf_node_spec.rb
|
101
|
+
- spec/unit/update_query_spec.rb
|
102
|
+
- spec/integration/parse_and_generate_spec.rb
|
93
103
|
- spec/integration/api_spec.rb
|