vorax 0.4.2 → 5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.md +4 -29
  2. data/vorax.gemspec +3 -11
  3. metadata +4 -92
  4. data/.rspec +0 -1
  5. data/Rakefile +0 -30
  6. data/lib/vorax.rb +0 -60
  7. data/lib/vorax/base_funnel.rb +0 -30
  8. data/lib/vorax/output/html_convertor.rb +0 -120
  9. data/lib/vorax/output/html_funnel.rb +0 -79
  10. data/lib/vorax/output/pagezip_convertor.rb +0 -20
  11. data/lib/vorax/output/tablezip_convertor.rb +0 -22
  12. data/lib/vorax/output/vertical_convertor.rb +0 -53
  13. data/lib/vorax/output/zip_convertor.rb +0 -117
  14. data/lib/vorax/parser/argument.rb~ +0 -125
  15. data/lib/vorax/parser/conn_string.rb +0 -104
  16. data/lib/vorax/parser/grammars/alias.rb +0 -904
  17. data/lib/vorax/parser/grammars/alias.rl +0 -138
  18. data/lib/vorax/parser/grammars/column.rb +0 -454
  19. data/lib/vorax/parser/grammars/column.rl +0 -64
  20. data/lib/vorax/parser/grammars/common.rl +0 -107
  21. data/lib/vorax/parser/grammars/declare.rb +0 -9606
  22. data/lib/vorax/parser/grammars/declare.rl +0 -160
  23. data/lib/vorax/parser/grammars/for_block.rb +0 -440
  24. data/lib/vorax/parser/grammars/for_block.rl +0 -73
  25. data/lib/vorax/parser/grammars/plsql_def.rb +0 -539
  26. data/lib/vorax/parser/grammars/plsql_def.rl +0 -73
  27. data/lib/vorax/parser/grammars/statement.rb +0 -925
  28. data/lib/vorax/parser/grammars/statement.rl +0 -83
  29. data/lib/vorax/parser/parser.rb +0 -344
  30. data/lib/vorax/parser/plsql_structure.rb +0 -222
  31. data/lib/vorax/parser/plsql_walker.rb +0 -143
  32. data/lib/vorax/parser/statement_inspector.rb~ +0 -52
  33. data/lib/vorax/parser/stmt_inspector.rb +0 -78
  34. data/lib/vorax/parser/target_ref.rb +0 -110
  35. data/lib/vorax/sqlplus.rb +0 -273
  36. data/lib/vorax/version.rb +0 -7
  37. data/lib/vorax/vorax_io.rb +0 -70
  38. data/spec/column_spec.rb +0 -40
  39. data/spec/conn_string_spec.rb +0 -53
  40. data/spec/declare_spec.rb +0 -281
  41. data/spec/pagezip_spec.rb +0 -153
  42. data/spec/parser_spec.rb +0 -352
  43. data/spec/plsql_structure_spec.rb +0 -68
  44. data/spec/spec_helper.rb +0 -13
  45. data/spec/sql/create_objects.sql +0 -69
  46. data/spec/sql/dbms_crypto.spc +0 -339
  47. data/spec/sql/dbms_stats.spc +0 -4097
  48. data/spec/sql/drop_user.sql +0 -10
  49. data/spec/sql/muci.spc +0 -26
  50. data/spec/sql/setup_user.sql +0 -22
  51. data/spec/sql/test.fnc +0 -12
  52. data/spec/sql/test.pkg +0 -83
  53. data/spec/sqlplus_spec.rb +0 -52
  54. data/spec/stmt_inspector_spec.rb +0 -96
  55. data/spec/tablezip_spec.rb +0 -111
  56. data/spec/vertical_spec.rb +0 -150
@@ -1,79 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'nokogiri'
4
-
5
- module Vorax
6
-
7
- # A namespace for everything related to the sqlplus output processing.
8
- module Output
9
-
10
- # A special type of funnel to work with HTML convertors.
11
- class HTMLFunnel < BaseFunnel
12
-
13
- # Creates a new HTML funnel.
14
- #
15
- # @param convertor [HTMLConvertor] the convertor to be used
16
- # to transform the HTML content.
17
- def initialize(convertor)
18
- @tail = ''
19
- @parser = Nokogiri::HTML::SAX::PushParser.new(convertor)
20
- end
21
-
22
- # Put the html content into the funnel.
23
- #
24
- # @param text [String] a chunk of HTML text
25
- def write(text)
26
- if text && !text.empty?
27
- @parser.write text
28
- if @parser.document.should_spit_text?
29
- @tail << text
30
- # just to be sure we don't have stale text after
31
- # the last end tag
32
- ping
33
- end
34
- end
35
- end
36
-
37
- # Get the formatted text from the funnel, as it is transformed
38
- # by the buddy convertor.
39
- #
40
- # @return the formatted text
41
- def read
42
- @parser.document.io.rewind
43
- chunk = @parser.document.io.read
44
- @parser.document.io.truncate(0)
45
- @parser.document.io.seek(0)
46
- return chunk
47
- end
48
-
49
- private
50
-
51
- # This is a workaround. The Nokogiri pull parser doesn't spit anything
52
- # if there's no endding tag. For example, if "<p>Text" is given, "Text" will not
53
- # be spit because the end "</p>" is missing. In sqlplus this is common
54
- # especially for "prompt" or "accept" commands which spit output without
55
- # enclosing the text in any tags. The main problem is ACCEPT, where VoraX
56
- # will wait for users input, but the prompt will not be shown which will
57
- # make the poor user confused. The solution is to force a random tag into
58
- # the HTML input stream so that the parser to move along.
59
- def ping
60
- unless @tail.empty?
61
- # be carefull not to ping into incomplete tags
62
- last_open_tag_position = (@tail.rindex('<') || -1)
63
- last_close_tag_position = (@tail.rindex('>') || -1)
64
- last_open_entity_position = (@tail.rindex('&') || -1)
65
- last_close_entity_position = (@tail.rindex(';') || -1)
66
- hwm = [last_close_tag_position, last_close_entity_position].max
67
- @tail = @tail[hwm + 1 .. -1] if hwm >= 0
68
- if last_close_tag_position >= last_open_tag_position &&
69
- last_close_entity_position >= last_open_entity_position
70
- @parser << "<#{HTMLConvertor.ping_tag}/>"
71
- end
72
- end
73
- end
74
-
75
- end
76
-
77
- end
78
-
79
- end
@@ -1,20 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- module Vorax
4
- module Output
5
-
6
- # A convertor used to compress every page returned by sqlplus when executing
7
- # a query.
8
- class PagezipConvertor < ZipConvertor
9
-
10
- # @see ZipConvertor.should_spit?
11
- def should_spit?(end_tag)
12
- ("table" == end_tag) ||
13
- ("th" == end_tag && rows.size > 0)
14
- end
15
-
16
- end
17
-
18
- end
19
- end
20
-
@@ -1,22 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- module Vorax
4
-
5
- module Output
6
-
7
- # A convertor used to compress every HTML TABLE from the
8
- # sqlplus output.
9
- class TablezipConvertor < ZipConvertor
10
-
11
- # see ZipConvertor.should_spit?
12
- def should_spit?(current_tag)
13
- current_tag == "table"
14
- end
15
-
16
- end
17
-
18
- end
19
-
20
- end
21
-
22
-
@@ -1,53 +0,0 @@
1
- # encoding: UTF-8
2
- module Vorax
3
- module Output
4
-
5
- class VerticalConvertor < HTMLConvertor
6
-
7
- def initialize()
8
- super()
9
- reset_props()
10
- end
11
-
12
- def end_element name
13
- super(name)
14
- @io << "\n" if ['br', 'p'].include?(name)
15
- if "th" == name and @collect_columns
16
- column = @text.strip
17
- @columns << column
18
- @th_length = [column.length, @th_length].max
19
- end
20
- @values << @text.strip if "td" == name
21
- if "tr" == name && (not @values.empty?)
22
- @columns = Array.new(@values.size, "") if @columns.empty?
23
- @columns.each_with_index do |column, i|
24
- value = HTMLConvertor.ml_indent(@values[i], @th_length + 3)
25
- @io.print("#{column.ljust(@th_length)} : #{value}\n")
26
- end
27
- @values.clear
28
- @collect_columns = false
29
- print_row_separator
30
- end
31
- @text.clear unless HTMLConvertor.ping_tag == name
32
- reset_props() if name == "table"
33
- end
34
-
35
- def print_row_separator
36
- @separator ||= '-' * 60
37
- @io.print("#{'-' * 60}\n")
38
- end
39
-
40
- private
41
-
42
- def reset_props
43
- @columns = []
44
- @values = []
45
- @th_length = 0
46
- @text = ""
47
- @collect_columns = true
48
- end
49
-
50
- end
51
-
52
- end
53
- end
@@ -1,117 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- module Vorax
4
-
5
- module Output
6
-
7
- # A special type of HTML convertor used for compressing HTML tables. This is an
8
- # abstract class and every convertor which needs compressing utilities must
9
- # inherit from this class.
10
- class ZipConvertor < HTMLConvertor
11
-
12
- attr_reader :rows, :last_close_tag, :last_open_tag
13
-
14
- # Create a new ZipConvertor.
15
- def initialize()
16
- super()
17
- reset_props()
18
- end
19
-
20
- # @see HTMLConvertor.start_hook
21
- def start_hook name, attrs = []
22
- @last_open_tag[:name] = name
23
- @last_open_tag[:attrs] = attrs
24
- end
25
-
26
- # @see HTMLConvertor.end_hook
27
- def end_hook name
28
- @io << "\n" if ['br', 'p'].include?(name)
29
- @record << {:text => text.strip,
30
- :is_column => ("th" == name),
31
- :align => get_align(@last_open_tag)} if ["td", "th"].include?(name)
32
- if "tr" == name
33
- @rows << @record.dup
34
- @record.clear
35
- end
36
- if should_spit?(name)
37
- spit
38
- @rows.clear
39
- end
40
- text.clear unless HTMLConvertor.ping_tag == name
41
- @last_close_tag.clear
42
- @last_close_tag << name
43
- reset_props() if "table" == name
44
- end
45
-
46
- # A method which tells if the accumulated compressed text should
47
- # be spit or not. This is the only method which must be implemented
48
- # into subclasses.
49
- #
50
- # @param name [String] the end HTML tag
51
- def should_spit?(name)
52
- raise RuntimeError.new "Implement me"
53
- end
54
-
55
- private
56
-
57
- def columns_layout
58
- layout = []
59
- (0..@rows.first.size-1).each do |i|
60
- width = @rows.inject(0) do |result, element|
61
- [result, HTMLConvertor.ml_width(element[i][:text])].max
62
- end
63
- first_data_row = @rows.detect { |row| row[i][:is_column] == false }
64
- align = first_data_row[i][:align] if first_data_row
65
- layout << {:width => width, :align => (align && align == "right" ? "rjust" : "ljust")}
66
- end
67
- layout
68
- end
69
-
70
- def separator(layout)
71
- # spit separator
72
- layout.each_with_index do |column, i|
73
- @io << "-" * column[:width]
74
- @io << (i == layout.size - 1 ? "\n" : " ")
75
- end
76
- end
77
-
78
- def spit
79
- layout = columns_layout
80
- # spit records
81
- @rows.each do |record|
82
- max_height = record.inject(0) { |result, element| [result, HTMLConvertor.ml_count(element[:text])].max }
83
- (0..max_height).each do |j|
84
- layout.length.times do |i|
85
- @io << "\n" if record[i][:is_column] && i == 0 && @first_spit == false
86
- @first_spit = false
87
- @io << HTMLConvertor.ml_segment(record[i][:text], j).send(layout[i][:align], layout[i][:width])
88
- @io << (i == layout.size - 1 ? "\n" : " ")
89
- separator(layout) if i == layout.size - 1 && record[i][:is_column]
90
- end
91
- end
92
- end
93
- end
94
-
95
- def get_align(tag)
96
- attrs = tag[:attrs]
97
- if attrs
98
- align_pair = attrs.find { |pair| pair[0] == "align" }
99
- return align_pair[1] if align_pair
100
- end
101
- end
102
-
103
- def reset_props
104
- @record = []
105
- @rows = []
106
- @last_open_tag = {:name => '', :attrs => []}
107
- @last_close_tag = ''
108
- @first_spit = true
109
- end
110
-
111
- end
112
-
113
- end
114
-
115
- end
116
-
117
-
@@ -1,125 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Vorax
4
-
5
- module Parser
6
-
7
- # Given a statement and a position we want to see if on that position we should
8
- # provide code completion for an argument
9
- class Argument
10
-
11
- def initialize(statement)
12
- @stmt = statement
13
- # interesting points to search within statement
14
- @marks = [BEGIN_PLSQL_SPECIAL_QUOTING, BEGIN_QUOTING,
15
- CLOSE_PARAN, OPEN_PARAN, ANY]
16
- # level referes to open/close brackets
17
- @level = 0
18
- end
19
-
20
- # the function/procedure which owns the argument at the
21
- # provided position
22
- def belongs_to(position = @stmt.length)
23
- @belongs_to = ''
24
- stmt = @stmt[(0...position)]
25
- # remove all comments
26
- stmt = Parser::Comment.new.remove_all(stmt)
27
- stmt.reverse!
28
- @ss = StringScanner.new(stmt)
29
- consume
30
- return @belongs_to
31
- end
32
-
33
- private
34
-
35
- def consume
36
- while !@ss.eos?
37
- @ss.skip_until(/#{@marks.join('|')}/im)
38
-
39
- process_plsql_quoting
40
- process_double_quotes
41
- process_single_quotes
42
- process_close_paran
43
- process_open_paran
44
-
45
- p @ss.rest
46
- gets
47
- end
48
- end
49
-
50
- def process_plsql_quoting
51
- # pay attention, is reveresed
52
- if @ss.matched =~ /'\]/
53
- @ss.skip_until(/\['q/)
54
- p 'a intrat'
55
- end
56
- #@ss.skip_until(/\{'q/) if @ss.matched =~ /'\}/
57
- #@ss.skip_until(/\('q/) if @ss.matched =~ /'\)/
58
- #@ss.skip_until(/\>'q/) if @ss.matched =~ /'\</
59
- end
60
-
61
- def process_double_quotes
62
- @ss.skip_until(/"/) if @ss.matched == '"'
63
- end
64
-
65
- def process_single_quotes
66
- if @ss.matched == "'"
67
- begin
68
- @ss.skip_until(/\'+/)
69
- end while (@ss.matched != "'" && !@ss.eos?)
70
- end
71
- end
72
-
73
- def process_close_paran
74
- if @ss.matched =~ /#{CLOSE_PARAN}/
75
- @level += 1
76
- end
77
- end
78
-
79
- def process_open_paran
80
- if @ss.matched =~ /#{OPEN_PARAN}/
81
- if @level == 0
82
- extract_module
83
- else
84
- @level -= 1
85
- @ss.terminate if @level < 0 #give up, it's an invalid statement
86
- end
87
- end
88
- end
89
-
90
- def extract_module
91
- while !@ss.eos?
92
- # consume leading whitspaces
93
- @ss.scan(/\s*/)
94
- if @ss.check(/"/) == '"'
95
- # we have a quoted identifier
96
- @belongs_to << @ss.scan(/"/)
97
- @belongs_to << @ss.scan_until(/"/)
98
- else
99
- # unquoted identifier
100
- @belongs_to << @ss.scan(/\S+/)
101
- end
102
- # consume trailing whitespaces
103
- @ss.scan(/\s*/)
104
-
105
- # might be a dblink
106
- if @ss.check(/@/) == '@'
107
- @belongs_to << @ss.scan(/@/)
108
- next
109
- end
110
-
111
- # might be package or a owner
112
- if @ss.check(/\./) == '.'
113
- @belongs_to << @ss.scan(/\./)
114
- next
115
- end
116
- @ss.terminate
117
- end
118
- @belongs_to.reverse!
119
- end
120
-
121
- end
122
-
123
- end
124
-
125
- end
@@ -1,104 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'strscan'
4
-
5
- module Vorax
6
-
7
- module Parser
8
-
9
- # A class used to parse a connection string.
10
- class ConnString
11
-
12
- # Parse the given connection string.
13
- #
14
- # @return [Hash] a hash with the following keys:
15
- #
16
- # :user => the username,
17
- # :password => the password,
18
- # :db => the target database,
19
- # :role => sysdba, sysasm or sysoper (if that's the case),
20
- # :prompt_for => when some pieces are missing (e.g. password), the corresponding keys from above is put here
21
- def parse(cstr)
22
- # well known connection strings:
23
- # - user => just the password will be prompted
24
- # - user/pwd
25
- # - user@db => just the password will be prompted
26
- # - user/pwd@db [as sysdba|sysoper|sysasm]
27
- # - /
28
- # - / [as sysdba|sysoper|sysasm}
29
- # - /@db => use wallet
30
- Vorax::debug("parse connection string #{cstr.inspect}")
31
- result = {:user => '', :password => '', :db => '', :role => '', :prompt_for => nil}
32
- input = cstr.strip
33
- scanner = StringScanner.new(input)
34
- result[:user] = unquoted_scan(scanner, /[@\/]/)
35
- has_pwd_slash = false
36
-
37
- if scanner.matched?
38
- # we have a @ or a / in our connection string
39
- result[:user].chop!
40
- if scanner.matched == "/"
41
- has_pwd_slash = true
42
- result[:password] = unquoted_scan(scanner, /@/)
43
- if scanner.matched?
44
- # there is a "@" so we know where to stop to extract the pwd
45
- result[:password].chop!
46
- extract_db(scanner, result)
47
- else
48
- # there's no "@" so assume everything to be the password
49
- # except for the role
50
- result[:password] = scanner.scan_until(/\z/)
51
- extract_role(result, :password)
52
- end
53
- elsif scanner.matched == "@"
54
- extract_db(scanner, result)
55
- end
56
- else
57
- # we don't have a @ or a / in our connection string
58
- result[:user] = input
59
- end
60
- result[:user] = strip_quotes(result[:user])
61
- result[:password] = strip_quotes(result[:password])
62
- if result[:user].empty? && result[:password].empty? && has_pwd_slash
63
- # assume OS authentication
64
- result[:prompt_for] = nil
65
- else
66
- if result[:user].empty?
67
- result[:prompt_for] = :user
68
- elsif (not result[:user].empty?) && result[:password].empty?
69
- result[:prompt_for] = :password
70
- end
71
- end
72
- result
73
- end
74
-
75
- private
76
-
77
- def strip_quotes(text)
78
- text.gsub(/\A"|"\z/, '')
79
- end
80
-
81
- def extract_db(scanner, cstr_hash)
82
- cstr_hash[:db] = scanner.scan_until(/\z/)
83
- extract_role(cstr_hash, :db)
84
- end
85
-
86
- def extract_role(cstr_hash, from_attr)
87
- cstr_hash[from_attr].sub!(/\s+as\s+(sysdba|sysoper|sysasm)\z/i, '')
88
- cstr_hash[:role] = $1.downcase if $1
89
- end
90
-
91
- def unquoted_scan(scanner, pattern)
92
- result = ''
93
- begin
94
- fragment = scanner.scan_until(pattern)
95
- result << fragment if fragment
96
- end while fragment && result.count('"').odd? # go on if between quotes
97
- result
98
- end
99
-
100
- end
101
-
102
- end
103
-
104
- end