tsql_parser 0.1.7 → 0.1.8
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.
- checksums.yaml +4 -4
- data/lib/parsing/formatter.rb +8 -7
- data/lib/parsing/formatters/format_factory.rb +1 -0
- data/lib/parsing/formatters/strategy/__formatters.rb +2 -0
- data/lib/parsing/formatters/strategy/cte_formatter.rb +28 -0
- data/lib/parsing/formatters/strategy/from_formatter.rb +46 -0
- data/lib/parsing/formatters/strategy/insert_formatter.rb +1 -0
- data/lib/parsing/formatters/strategy/join_formatter.rb +56 -7
- data/lib/parsing/formatters/strategy/select_formatter.rb +27 -2
- data/lib/parsing/formatters/strategy/set_formatter.rb +2 -1
- data/lib/parsing/formatters/strategy/update_formatter.rb +3 -1
- data/lib/parsing/formatters/strategy/where_formatter.rb +11 -3
- data/lib/parsing/tokenizer.rb +2 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e811afa0fc437610f1466d197aae259f227095dfa7c2d8ebfc6022387984072
|
4
|
+
data.tar.gz: c903812e94a81e2ba40c37f514315e25b86731768af0ce3829ca95879cf98ae9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6b6cd6ccaf82f4267b5028c053f98e6f0960a3a88110d9b623cc3ddc4e770392fb452e7d9fa78126071d89aa742102ecd0e1e49b7030d830c5d39cc6bb49d3a
|
7
|
+
data.tar.gz: a4ed89d5d67b03a7128a102a28edfe2b9b5b46bc115e25e83c14293314170e2cfa3f1c8e5bd182f967aad786c1aabd9d40f7f2c172e097c68a75a33d67d6b417
|
data/lib/parsing/formatter.rb
CHANGED
@@ -25,14 +25,15 @@ module TSqlParser::Parsing
|
|
25
25
|
lines = TokenTransformer.transform(tokens)
|
26
26
|
lines = self.cleanup_whitespace(lines)
|
27
27
|
lines = self.insert_indentation(lines, tab_count, tab)
|
28
|
-
#lines = self.insert_newlines(lines)
|
29
28
|
text = lines.join("\n")
|
30
|
-
text = TextFormatter.new(
|
31
|
-
text = TextFormatter.new(
|
32
|
-
text = TextFormatter.new(
|
33
|
-
text = TextFormatter.new(
|
34
|
-
text = TextFormatter.new(
|
35
|
-
text = TextFormatter.new(
|
29
|
+
text = TextFormatter.new(CTE, text, tab).format
|
30
|
+
text = TextFormatter.new(WHERE, text, tab).format if text.include? " WHERE "
|
31
|
+
text = TextFormatter.new(FROM, text, tab).format if text.include? " FROM "
|
32
|
+
text = TextFormatter.new(SELECT, text, tab).format if text.include? " SELECT "
|
33
|
+
text = TextFormatter.new(SET, text, tab).format if text.include? " SET "
|
34
|
+
text = TextFormatter.new(UPDATE, text, tab).format if text.include? " UPDATE "
|
35
|
+
text = TextFormatter.new(JOIN, text, tab).format if text.include? " JOIN "
|
36
|
+
text = TextFormatter.new(INSERT, text, tab).format if text.include? " INSERT "
|
36
37
|
text
|
37
38
|
end
|
38
39
|
|
@@ -20,6 +20,7 @@ module TSqlParser::Parsing
|
|
20
20
|
require_relative "select_formatter"
|
21
21
|
require_relative "update_formatter"
|
22
22
|
require_relative "where_formatter"
|
23
|
+
require_relative "from_formatter"
|
23
24
|
|
24
25
|
CTE = 0
|
25
26
|
INSERT = 1
|
@@ -28,4 +29,5 @@ module TSqlParser::Parsing
|
|
28
29
|
SET = 4
|
29
30
|
UPDATE = 5
|
30
31
|
WHERE = 6
|
32
|
+
FROM = 7
|
31
33
|
end
|
@@ -19,6 +19,34 @@ module TSqlParser::Parsing::Formatters
|
|
19
19
|
|
20
20
|
class CommonTableExpressionFormatter < BaseFormatter
|
21
21
|
def format(text, tab = Defaults.get_default_tab)
|
22
|
+
formatted = []
|
23
|
+
lines = text.split("\n")
|
24
|
+
lines.each_with_index do |line, index|
|
25
|
+
clean_line = line.strip
|
26
|
+
tab_count = self.get_tab_count(line, tab)
|
27
|
+
if clean_line.include? " AS (SELECT "
|
28
|
+
if clean_line.start_with? "WITH" and clean_line.end_with? ")"
|
29
|
+
cte_parts = clean_line.split(" AS (SELECT ")
|
30
|
+
cte_name = cte_parts[0]
|
31
|
+
cte_body = "AS (\n#{tab * (tab_count + 1)}SELECT #{cte_parts[1][..-2]}\n#{tab * tab_count})"
|
32
|
+
formatted << "#{tab * tab_count}#{cte_name} #{cte_body}"
|
33
|
+
elsif clean_line.end_with? ") ,"
|
34
|
+
cte_parts = clean_line.split(" AS (SELECT ")
|
35
|
+
cte_name = cte_parts[0]
|
36
|
+
cte_body = "AS (\n#{tab * (tab_count + 1)}SELECT #{cte_parts[1].sub(") ,", "")}\n#{tab * tab_count}),"
|
37
|
+
formatted << "#{tab * tab_count}#{cte_name} #{cte_body}"
|
38
|
+
elsif clean_line.end_with? ")"
|
39
|
+
cte_parts = clean_line.split(" AS (SELECT ")
|
40
|
+
cte_name = cte_parts[0]
|
41
|
+
cte_body = "AS (\n#{tab * (tab_count + 1)}SELECT #{cte_parts[1][..-2]}\n#{tab * tab_count})"
|
42
|
+
formatted << "#{tab * tab_count}#{cte_name} #{cte_body}"
|
43
|
+
end
|
44
|
+
else
|
45
|
+
formatted << line
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
formatted.join("\n")
|
22
50
|
end
|
23
51
|
end
|
24
52
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# __ .__
|
2
|
+
# _/ |_ ___________| | ___________ _______ ______ ___________
|
3
|
+
# \ __\/ ___/ ____/ | ______ \____ \__ \\_ __ \/ ___// __ \_ __ \
|
4
|
+
# | | \___ < <_| | |__ /_____/ | |_> > __ \| | \/\___ \\ ___/| | \/
|
5
|
+
# |__| /____ >__ |____/ | __(____ /__| /____ >\___ >__|
|
6
|
+
# \/ |__| |__| \/ \/ \/
|
7
|
+
#
|
8
|
+
# A very light-weight and opinionated T-SQL parser and formatter.
|
9
|
+
#
|
10
|
+
# github.com/scstauf
|
11
|
+
#
|
12
|
+
# path:
|
13
|
+
# parsing/formatters/from_formatter.rb
|
14
|
+
# object:
|
15
|
+
# TSqlParser::Parsing::Formatters::FromFormatter
|
16
|
+
|
17
|
+
module TSqlParser::Parsing::Formatters
|
18
|
+
require_relative "base_formatter"
|
19
|
+
|
20
|
+
class FromFormatter < BaseFormatter
|
21
|
+
def format(text, tab = Defaults.get_default_tab)
|
22
|
+
formatted = []
|
23
|
+
lines = text.split("\n")
|
24
|
+
lines.each_with_index do |line, index|
|
25
|
+
if line.strip.start_with? "--" or line.strip.start_with? "/*" or line.strip.end_with? "'"
|
26
|
+
formatted << line
|
27
|
+
next
|
28
|
+
end
|
29
|
+
|
30
|
+
if line.include? " FROM " and not line.include? " EXISTS ("
|
31
|
+
tab_count = self.get_tab_count(line, tab)
|
32
|
+
if line.count(" FROM ") == 1
|
33
|
+
from_parts = line.split(" FROM ")
|
34
|
+
formatted << "#{from_parts[0]}\n#{tab * tab_count}FROM #{from_parts[1]}"
|
35
|
+
else
|
36
|
+
formatted << line[..line.index(" FROM ") - 1]
|
37
|
+
formatted << "#{tab * tab_count}#{line[line.index(" FROM ") + 1..]}"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
formatted << line
|
41
|
+
end
|
42
|
+
end
|
43
|
+
formatted.join("\n")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -28,13 +28,17 @@ module TSqlParser::Parsing::Formatters
|
|
28
28
|
|
29
29
|
lines.each do |line|
|
30
30
|
first = line.strip.split(" ").first
|
31
|
-
if
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
next if first.nil?
|
32
|
+
|
33
|
+
if first.start_with? "--" or first.start_with? "/*" or line.strip.end_with? "'"
|
34
|
+
new_text << line
|
35
|
+
next
|
36
|
+
end
|
37
|
+
|
38
|
+
tab_count = self.get_tab_count(line, tab)
|
39
|
+
|
40
|
+
if line.include? " JOIN "
|
41
|
+
new_text << self.format_joins(line, tab, tab_count)
|
38
42
|
else
|
39
43
|
new_text << line
|
40
44
|
end
|
@@ -42,5 +46,50 @@ module TSqlParser::Parsing::Formatters
|
|
42
46
|
|
43
47
|
new_text.join("\n")
|
44
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def format_joins(line, tab, tab_count)
|
53
|
+
formatted = []
|
54
|
+
builder = []
|
55
|
+
tokens = line.strip.split(" ")
|
56
|
+
skip_count = 0
|
57
|
+
tokens.each_with_index do |t, i|
|
58
|
+
if skip_count > 0
|
59
|
+
skip_count -= 1
|
60
|
+
next
|
61
|
+
end
|
62
|
+
|
63
|
+
last_one = tokens[i - 1] if i - 1 > 0
|
64
|
+
future_one = tokens[i + 1] if i + 1 < tokens.size
|
65
|
+
future_two = tokens[i + 2] if i + 2 < tokens.size
|
66
|
+
future_three = tokens[i + 3] if i + 3 < tokens.size
|
67
|
+
|
68
|
+
next_two = "#{future_one} #{future_two}"
|
69
|
+
next_three = "#{future_one} #{future_two} #{future_three}"
|
70
|
+
|
71
|
+
if ["INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "FULL JOIN", "CROSS JOIN"].include? next_two
|
72
|
+
builder << t
|
73
|
+
formatted << "#{tab * tab_count}#{builder.join(" ")}" unless builder.empty?
|
74
|
+
builder = [next_two]
|
75
|
+
skip_count = 2
|
76
|
+
elsif ["LEFT OUTER JOIN", "RIGHT OUTER JOIN", "FULL OUTER JOIN"].include? next_three
|
77
|
+
builder << t
|
78
|
+
formatted << "#{tab * tab_count}#{builder.join(" ")}" unless builder.empty?
|
79
|
+
builder = [next_three]
|
80
|
+
skip_count = 3
|
81
|
+
elsif t == "JOIN" and (not last_one.nil? and not %w[INNER LEFT RIGHT FULL CROSS OUTER].include? last_one)
|
82
|
+
formatted << "#{tab * tab_count}#{builder.join(" ")}" unless builder.empty?
|
83
|
+
builder = [t]
|
84
|
+
else
|
85
|
+
builder << t
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
formatted << "#{tab * tab_count}#{builder.join(" ")}" unless builder.empty?
|
90
|
+
builder = []
|
91
|
+
|
92
|
+
formatted.join("\n")
|
93
|
+
end
|
45
94
|
end
|
46
95
|
end
|
@@ -23,6 +23,8 @@ module TSqlParser::Parsing::Formatters
|
|
23
23
|
lines = text.split("\n")
|
24
24
|
lines.each do |line|
|
25
25
|
first = line.strip.split(" ").first
|
26
|
+
next if first.nil?
|
27
|
+
|
26
28
|
if first != "SELECT"
|
27
29
|
formatted << line
|
28
30
|
next
|
@@ -45,8 +47,31 @@ module TSqlParser::Parsing::Formatters
|
|
45
47
|
def format_select(s, tab_count = Defaults.get_default_tab_count, tab = Defaults.get_default_tab)
|
46
48
|
return s if s.nil?
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
+
new_tokens = []
|
51
|
+
parenthesis = 0
|
52
|
+
builder = ""
|
53
|
+
skip_count = 0
|
54
|
+
s.split("").each do |c|
|
55
|
+
parenthesis += 1 if c == "("
|
56
|
+
parenthesis -= 1 if c == ")"
|
57
|
+
|
58
|
+
if skip_count > 0
|
59
|
+
skip_count -= 1
|
60
|
+
next
|
61
|
+
end
|
62
|
+
|
63
|
+
if c == "," and parenthesis == 0
|
64
|
+
new_tokens << builder unless builder.empty?
|
65
|
+
builder = ""
|
66
|
+
skip_count = 1
|
67
|
+
else
|
68
|
+
builder += c
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
new_tokens << builder unless builder.empty?
|
73
|
+
|
74
|
+
"\n#{new_tokens.map { |t| "#{tab * (tab_count + 1)}#{t}" }.join(",\n")}"
|
50
75
|
end
|
51
76
|
end
|
52
77
|
end
|
@@ -28,6 +28,7 @@ module TSqlParser::Parsing::Formatters
|
|
28
28
|
lines.each do |line|
|
29
29
|
tokens = line.strip.split(" ")
|
30
30
|
first = tokens.first
|
31
|
+
next if first.nil?
|
31
32
|
next_token = tokens[1] if tokens.size > 1
|
32
33
|
|
33
34
|
if %w[FROM WHERE].include? first and wait
|
@@ -59,7 +60,7 @@ module TSqlParser::Parsing::Formatters
|
|
59
60
|
parts = line.strip.split(" SET ")
|
60
61
|
tab_count = self.get_tab_count(line, tab)
|
61
62
|
formatted << "#{tab * tab_count}#{parts[0]}\n"
|
62
|
-
parts[1..].each { |p| formatted << "#{tab * tab_count}SET #{p}" }
|
63
|
+
parts[1..].each { |p| formatted << "#{tab * tab_count}SET #{self.format_set(p, tab_count, tab)}" }
|
63
64
|
elsif wait
|
64
65
|
set_lines << line
|
65
66
|
else
|
@@ -23,6 +23,8 @@ module TSqlParser::Parsing::Formatters
|
|
23
23
|
lines = text.split("\n")
|
24
24
|
lines.each do |line|
|
25
25
|
first = line.strip.split(" ").first
|
26
|
+
next if first.nil?
|
27
|
+
|
26
28
|
if first != "UPDATE"
|
27
29
|
formatted << line
|
28
30
|
next
|
@@ -35,7 +37,7 @@ module TSqlParser::Parsing::Formatters
|
|
35
37
|
formatted << line
|
36
38
|
next
|
37
39
|
end
|
38
|
-
formatted << line.sub(update, new_update)
|
40
|
+
formatted << "#{tab * tab_count}#{line.strip.sub(update, new_update)}"
|
39
41
|
end
|
40
42
|
formatted.join("\n")
|
41
43
|
end
|
@@ -22,19 +22,27 @@ module TSqlParser::Parsing::Formatters
|
|
22
22
|
formatted = []
|
23
23
|
text.split("\n").each do |line|
|
24
24
|
first = line.strip.split(" ").first
|
25
|
-
if first
|
25
|
+
next if first.nil?
|
26
|
+
if not line.include? "WHERE"
|
26
27
|
formatted << line
|
27
28
|
next
|
28
29
|
end
|
29
30
|
|
31
|
+
if line.strip.start_with? "--" or line.strip.start_with? "/*" or line.strip.end_with? "'"
|
32
|
+
formatted << line
|
33
|
+
next
|
34
|
+
end
|
35
|
+
|
36
|
+
where_clause = line[line.index(" WHERE ")..].strip
|
37
|
+
|
30
38
|
tab_count = self.get_tab_count(line, tab)
|
31
|
-
predicate =
|
39
|
+
predicate = where_clause.strip["WHERE".size + 1..]
|
32
40
|
new_predicate = self.format_predicate(predicate, tab_count, tab)
|
33
41
|
if new_predicate.nil?
|
34
42
|
formatted << line
|
35
43
|
next
|
36
44
|
end
|
37
|
-
formatted << line.sub(predicate, new_predicate)
|
45
|
+
formatted << line.sub("WHERE", "").sub(predicate, "\n#{tab * tab_count}WHERE#{new_predicate}")
|
38
46
|
end
|
39
47
|
|
40
48
|
formatted.join("\n")
|
data/lib/parsing/tokenizer.rb
CHANGED
@@ -25,6 +25,7 @@ module TSqlParser::Parsing
|
|
25
25
|
|
26
26
|
def basic_tokenize(tsql_string)
|
27
27
|
self.reset
|
28
|
+
tsql_string = tsql_string.gsub("\t", Defaults.get_default_tab)
|
28
29
|
tsql_chars = tsql_string.split("")
|
29
30
|
|
30
31
|
tsql_chars.each_with_index do |c, i|
|
@@ -64,7 +65,7 @@ module TSqlParser::Parsing
|
|
64
65
|
def handle_multicomment_start
|
65
66
|
if Parser.is_multiline_comment_start?(@c, @next_c)
|
66
67
|
@multiline_comment = true
|
67
|
-
self.flush_builder(c)
|
68
|
+
self.flush_builder(@c)
|
68
69
|
return true
|
69
70
|
end
|
70
71
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tsql_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Stauffer
|
@@ -10,8 +10,10 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2023-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
|
13
|
+
description: |-
|
14
|
+
A very light-weight and opinionated T-SQL parser and formatter.
|
15
|
+
Github has the most recent docs.
|
16
|
+
Contributions welcome!
|
15
17
|
email: scott@fuseraft.com
|
16
18
|
executables: []
|
17
19
|
extensions: []
|
@@ -24,6 +26,7 @@ files:
|
|
24
26
|
- lib/parsing/formatters/strategy/__formatters.rb
|
25
27
|
- lib/parsing/formatters/strategy/base_formatter.rb
|
26
28
|
- lib/parsing/formatters/strategy/cte_formatter.rb
|
29
|
+
- lib/parsing/formatters/strategy/from_formatter.rb
|
27
30
|
- lib/parsing/formatters/strategy/insert_formatter.rb
|
28
31
|
- lib/parsing/formatters/strategy/join_formatter.rb
|
29
32
|
- lib/parsing/formatters/strategy/select_formatter.rb
|