oraora 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/LICENSE +21 -0
- data/README.md +141 -0
- data/bin/oraora +48 -0
- data/lib/oraora.rb +9 -0
- data/lib/oraora/app.rb +298 -0
- data/lib/oraora/awareness.rb +78 -0
- data/lib/oraora/completion.rb +56 -0
- data/lib/oraora/context.rb +90 -0
- data/lib/oraora/credentials.rb +64 -0
- data/lib/oraora/logger.rb +19 -0
- data/lib/oraora/meta.rb +39 -0
- data/lib/oraora/meta/column.rb +45 -0
- data/lib/oraora/meta/database.rb +27 -0
- data/lib/oraora/meta/materialized_view.rb +48 -0
- data/lib/oraora/meta/object.rb +46 -0
- data/lib/oraora/meta/schema.rb +40 -0
- data/lib/oraora/meta/sequence.rb +33 -0
- data/lib/oraora/meta/subprogram.rb +36 -0
- data/lib/oraora/meta/table.rb +42 -0
- data/lib/oraora/meta/view.rb +41 -0
- data/lib/oraora/oci.rb +56 -0
- data/lib/oraora/terminal.rb +55 -0
- data/oraora.gemspec +22 -0
- data/spec/context_spec.rb +132 -0
- data/spec/credentials_spec.rb +83 -0
- metadata +154 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module Oraora
|
2
|
+
class Meta
|
3
|
+
class Object
|
4
|
+
attr_reader :type
|
5
|
+
|
6
|
+
def initialize(schema, name, type = nil)
|
7
|
+
@schema = schema
|
8
|
+
@name = name
|
9
|
+
@type = type
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_from_oci(oci)
|
13
|
+
if !@type
|
14
|
+
@id, @type = oci.select_one("SELECT object_id, object_type FROM all_objects
|
15
|
+
WHERE owner = :schema AND object_name = :name
|
16
|
+
ORDER BY decode(namespace, 19, 0, 99)", @schema, @name) if !@type
|
17
|
+
raise NotExists if !@id
|
18
|
+
@id = @id.to_i
|
19
|
+
end
|
20
|
+
case @type
|
21
|
+
when 'TABLE' then Table.from_oci(oci, @schema, @name)
|
22
|
+
when 'VIEW' then View.from_oci(oci, @schema, @name)
|
23
|
+
when 'MATERIALIZED VIEW' then MaterializedView.from_oci(oci, @schema, @name)
|
24
|
+
when 'SEQUENCE' then Sequence.from_oci(oci, @schema, @name)
|
25
|
+
else self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.from_oci(oci, schema, name, type = nil)
|
30
|
+
new(schema, name, type).load_from_oci(oci)
|
31
|
+
end
|
32
|
+
|
33
|
+
def describe(options = {})
|
34
|
+
<<-HERE.reset_indentation
|
35
|
+
Object #{@schema}.#{@name}
|
36
|
+
Id: #{@id}
|
37
|
+
Type: #{@type}
|
38
|
+
HERE
|
39
|
+
end
|
40
|
+
|
41
|
+
def list(options = {}, filter = nil)
|
42
|
+
raise NotApplicable, "Cannot list for this object"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Oraora
|
2
|
+
class Meta
|
3
|
+
class Schema
|
4
|
+
def initialize(name)
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_from_oci(oci)
|
9
|
+
@id, @created = oci.select_one("SELECT user_id, created FROM all_users WHERE username = :name", @name)
|
10
|
+
raise NotExists if !@id
|
11
|
+
@id = @id.to_i
|
12
|
+
@objects = oci.pluck("SELECT object_name, min(object_type) object_type FROM all_objects
|
13
|
+
WHERE owner = :name
|
14
|
+
AND object_type IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW', 'SEQUENCE')
|
15
|
+
GROUP BY object_name
|
16
|
+
ORDER BY object_name", @name)
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_oci(oci, name)
|
21
|
+
new(name).load_from_oci(oci)
|
22
|
+
end
|
23
|
+
|
24
|
+
def describe(options = {})
|
25
|
+
<<-HERE.reset_indentation
|
26
|
+
Schema #{@name}
|
27
|
+
Id: #{@id}
|
28
|
+
Created: #{@created}
|
29
|
+
HERE
|
30
|
+
end
|
31
|
+
|
32
|
+
def list(options = {}, filter = nil)
|
33
|
+
objects = @objects.collect(&:first)
|
34
|
+
objects.reject! { |o| o =~ /^ISEQ\$\$/ || o =~ /^SYS_/ || o =~ /^ORA_/ } unless options['a']
|
35
|
+
objects.select! { |o| o =~ /^#{Regexp.escape(filter).gsub('\*', '.*').gsub('\?', '.')}$/ } if filter
|
36
|
+
objects
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative './object.rb'
|
2
|
+
|
3
|
+
module Oraora
|
4
|
+
class Meta
|
5
|
+
class Sequence < Object
|
6
|
+
def type
|
7
|
+
'SEQUENCE'
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_from_oci(oci)
|
11
|
+
@min, @max, @inc, @last = oci.select_one("SELECT min_value, max_value, increment_by, last_number
|
12
|
+
FROM all_sequences
|
13
|
+
WHERE sequence_owner = :schema AND sequence_name = :name", @schema, @name)
|
14
|
+
raise NotExists if !@min
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def describe(options = {})
|
19
|
+
<<-HERE.reset_indentation
|
20
|
+
Sequence #{@schema}.#{@name}
|
21
|
+
Min value: #{@min.to_i}
|
22
|
+
Max value: #{@max.to_i}
|
23
|
+
Increment by: #{@inc.to_i}
|
24
|
+
Last value: #{@last.to_i}
|
25
|
+
HERE
|
26
|
+
end
|
27
|
+
|
28
|
+
def list(options = {}, filter = nil)
|
29
|
+
raise NotApplicable, "Nothing to list for sequence"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Oraora
|
2
|
+
class Meta
|
3
|
+
class Subprogram
|
4
|
+
attr_reader :id, :schema, :package, :name
|
5
|
+
|
6
|
+
def initialize(schema, package, name)
|
7
|
+
@schema = schema
|
8
|
+
@package = package
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_from_oci(oci)
|
13
|
+
@id =
|
14
|
+
oci.select_one("SELECT subprogram_id FROM all_procedues WHERE owner = :schema AND object_name = :package AND procedure_name = :name", @schema, @package, @name)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_oci(oci, schema, package, name)
|
19
|
+
new(schema, package, name).load_from_oci(oci)
|
20
|
+
end
|
21
|
+
|
22
|
+
def describe(options = {})
|
23
|
+
<<-HERE.reset_indentation
|
24
|
+
Schema: #{@schema}
|
25
|
+
Package: #{@package}
|
26
|
+
Name: #{@name}
|
27
|
+
Id: #{@id}
|
28
|
+
HERE
|
29
|
+
end
|
30
|
+
|
31
|
+
def list(options = {}, filter = nil)
|
32
|
+
raise NotApplicable, "Nothing to list for subprogram"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative './object.rb'
|
2
|
+
|
3
|
+
module Oraora
|
4
|
+
class Meta
|
5
|
+
class Table < Object
|
6
|
+
def type
|
7
|
+
'TABLE'
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_from_oci(oci)
|
11
|
+
@partitioned = oci.select_one("SELECT partitioned FROM all_tables WHERE owner = :schema AND table_name = :name", @schema, @name).first
|
12
|
+
raise NotExists if !@partitioned
|
13
|
+
@columns = oci.pluck("SELECT column_name, column_id, data_type, data_length, data_precision, data_scale, char_used, char_length " +
|
14
|
+
"FROM all_tab_columns WHERE owner = :schema AND table_name = :name ORDER BY column_id", @schema, @name).collect do |col|
|
15
|
+
Column.new(@schema, @name, col[0], id: col[1].to_i, type: col[2], length: col[3] && col[3].to_i,
|
16
|
+
precision: col[4] && col[4].to_i, scale: col[5] && col[5].to_i, char_used: col[6],
|
17
|
+
char_length: col[7] && col[7].to_i)
|
18
|
+
end
|
19
|
+
@columns_hash = Hash[@columns.collect { |col| [col.name, col] }]
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def describe(options = {})
|
24
|
+
<<-HERE.reset_indentation
|
25
|
+
Table #{@schema}.#{@name}
|
26
|
+
Partitioned: #{@partitioned}
|
27
|
+
HERE
|
28
|
+
end
|
29
|
+
|
30
|
+
def list(options = {}, filter = nil)
|
31
|
+
columns = @columns_hash.keys
|
32
|
+
columns.select! { |c| c =~ /^#{Regexp.escape(filter).gsub('\*', '.*').gsub('\?', '.')}$/ } if filter
|
33
|
+
columns
|
34
|
+
end
|
35
|
+
|
36
|
+
def columns(column)
|
37
|
+
raise NotExists if !@columns_hash[column]
|
38
|
+
@columns_hash[column]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative './object.rb'
|
2
|
+
|
3
|
+
module Oraora
|
4
|
+
class Meta
|
5
|
+
class View < Object
|
6
|
+
def type
|
7
|
+
'VIEW'
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_from_oci(oci)
|
11
|
+
x = oci.select_one("SELECT 1 FROM all_views WHERE owner = :schema AND view_name = :name", @schema, @name).first
|
12
|
+
raise NotExists if !x
|
13
|
+
@columns = oci.pluck("SELECT column_name, column_id, data_type, data_length, data_precision, data_scale, char_used, char_length " +
|
14
|
+
"FROM all_tab_columns WHERE owner = :schema AND table_name = :name ORDER BY column_id", @schema, @name).collect do |col|
|
15
|
+
Column.new(@schema, @name, col[0], id: col[1].to_i, type: col[2], length: col[3] && col[3].to_i,
|
16
|
+
precision: col[4] && col[4].to_i, scale: col[5] && col[5].to_i, char_used: col[6],
|
17
|
+
char_length: col[7] && col[7].to_i)
|
18
|
+
end
|
19
|
+
@columns_hash = Hash[@columns.collect { |col| [col.name, col] }]
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def describe(options = {})
|
24
|
+
<<-HERE.reset_indentation
|
25
|
+
View #{@schema}.#{@name}
|
26
|
+
HERE
|
27
|
+
end
|
28
|
+
|
29
|
+
def list(options = {}, filter = nil)
|
30
|
+
columns = @columns_hash.keys
|
31
|
+
columns.select! { |c| c =~ /^#{Regexp.escape(filter).gsub('\*', '.*').gsub('\?', '.')}$/ } if filter
|
32
|
+
columns
|
33
|
+
end
|
34
|
+
|
35
|
+
def columns(column)
|
36
|
+
raise NotExists if !@columns_hash[column]
|
37
|
+
@columns_hash[column]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/oraora/oci.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Oraora
|
2
|
+
# Wrapper around OCI8 to add some extra stuff
|
3
|
+
class OCI < OCI8
|
4
|
+
# Wrapped in a separate thread as OCI8 seems to ignore interrupts
|
5
|
+
def initialize(*args)
|
6
|
+
ret = nil
|
7
|
+
thread = Thread.new { ret = super }
|
8
|
+
thread.join
|
9
|
+
ret
|
10
|
+
end
|
11
|
+
|
12
|
+
# Wrapped in a separate thread as OCI8 seems to ignore interrupts
|
13
|
+
def logoff
|
14
|
+
ret = nil
|
15
|
+
thread = Thread.new { ret = super }
|
16
|
+
thread.join
|
17
|
+
ret
|
18
|
+
end
|
19
|
+
|
20
|
+
# Wrapped in a separate thread with Interrupt handling
|
21
|
+
def exec(sql, *bindvars, &block)
|
22
|
+
ret = nil
|
23
|
+
thread = Thread.new { ret = super }
|
24
|
+
thread.join
|
25
|
+
ret
|
26
|
+
rescue Interrupt
|
27
|
+
self.break
|
28
|
+
raise
|
29
|
+
end
|
30
|
+
|
31
|
+
# Wrapped in a separate thread with Interrupt handling
|
32
|
+
def select_one(sql, *bindvars)
|
33
|
+
ret = nil
|
34
|
+
thread = Thread.new { ret = super }
|
35
|
+
thread.join
|
36
|
+
ret
|
37
|
+
rescue Interrupt
|
38
|
+
self.break
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the query result as an array of arrays
|
43
|
+
def pluck(sql, *bindvars)
|
44
|
+
result = []
|
45
|
+
exec(sql, *bindvars) { |row| result << row }
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns first column of a query as an array
|
50
|
+
def pluck_one(sql, *bindvars)
|
51
|
+
result = []
|
52
|
+
exec(sql, *bindvars) { |row| result << row.first }
|
53
|
+
result
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Oraora
|
2
|
+
module Terminal
|
3
|
+
def self.width
|
4
|
+
HighLine::SystemExtensions.terminal_size[0]
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.height
|
8
|
+
HighLine::SystemExtensions.terminal_size[1]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.puts_grid(items)
|
12
|
+
# TODO: Disable terminal size check when not reading from terminal
|
13
|
+
terminal_cols = [width || 0, 32].max
|
14
|
+
object_cols = terminal_cols / 32
|
15
|
+
# TODO: Determine optimal object_cols
|
16
|
+
num_rows = (items.length + object_cols - 1) / object_cols
|
17
|
+
#@logger.debug "Determined #{num_rows} rows of #{object_cols} objects for #{items.count} objects and #{terminal_cols} terminal width"
|
18
|
+
(0...num_rows).each do |row|
|
19
|
+
line = ''
|
20
|
+
(0...object_cols).each do |col|
|
21
|
+
index = num_rows * col + row
|
22
|
+
line += items[index].ljust(32) if items[index]
|
23
|
+
end
|
24
|
+
puts line
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.puts_cursor(cursor)
|
29
|
+
# Column metadata
|
30
|
+
column_names = cursor.get_col_names
|
31
|
+
|
32
|
+
cursor.prefetch_rows = 1000
|
33
|
+
begin
|
34
|
+
# Fetch 1000 rows
|
35
|
+
output = []
|
36
|
+
column_lengths = Array.new(column_names.length, 1)
|
37
|
+
while output.length < 1000 && record = cursor.fetch
|
38
|
+
record.collect! { |val| val.is_a?(BigDecimal) ? val.to_s('F').gsub(/\.0+$/, '') : val.to_s }
|
39
|
+
output << record
|
40
|
+
column_lengths = column_lengths.zip(record.collect { |v| v.length}).collect(&:max)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Output
|
44
|
+
if !output.empty?
|
45
|
+
puts "%-*.*s " * column_names.length % column_lengths.zip(column_lengths, column_names).flatten
|
46
|
+
puts "%-*s " * column_names.length % column_lengths.zip(column_lengths.collect { |c| '-' * c }).flatten
|
47
|
+
output.each do |row|
|
48
|
+
puts "%-*s " * row.length % column_lengths.zip(row).flatten
|
49
|
+
end
|
50
|
+
puts
|
51
|
+
end
|
52
|
+
end while record
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/oraora.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'oraora'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
s.summary = "Interactive command-line utility for Oracle"
|
5
|
+
s.description = "Interactive command-line utility for Oracle"
|
6
|
+
|
7
|
+
s.author = "kmehkeri"
|
8
|
+
s.email = 'kmehkeri@gmail.com'
|
9
|
+
s.homepage = 'http://rubygems.org/gems/oraora'
|
10
|
+
s.license = 'MIT'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split($/)
|
13
|
+
s.executables = `git ls-files -- bin`.split($/).map { |f| File.basename(f) }
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'highline'
|
16
|
+
s.add_runtime_dependency 'ruby-oci8'
|
17
|
+
s.add_runtime_dependency 'indentation'
|
18
|
+
s.add_runtime_dependency 'colorize'
|
19
|
+
s.add_runtime_dependency 'bigdecimal'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'oraora/context'
|
2
|
+
|
3
|
+
describe Oraora::Context do
|
4
|
+
|
5
|
+
describe '.initialize' do
|
6
|
+
it "should initialize from hash" do
|
7
|
+
context = Oraora::Context.new('V', schema: 'X', object: 'Y', object_type: 'TABLE')
|
8
|
+
expect( context.level ).to eql :object
|
9
|
+
expect( context.user ).to eql 'V'
|
10
|
+
expect( context.schema ).to eql 'X'
|
11
|
+
expect( context.object ).to eql 'Y'
|
12
|
+
expect( context.object_type ).to eql 'TABLE'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.su' do
|
17
|
+
it "should return a different context object" do
|
18
|
+
context = Oraora::Context.new('V', schema: 'X', object: 'Y', object_type: 'TABLE')
|
19
|
+
expect( context.su('Z') ).not_to eql context
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should store specified user" do
|
23
|
+
context = Oraora::Context.new('V', schema: 'X', object: 'Y', object_type: 'TABLE').su('Z')
|
24
|
+
expect( context.user ).to eql 'Z'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should store original context's data" do
|
28
|
+
context = Oraora::Context.new('V', schema: 'X', object: 'Y', object_type: 'TABLE').su('Z')
|
29
|
+
expect( context.schema ).to eql 'X'
|
30
|
+
expect( context.object ).to eql 'Y'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.dup' do
|
35
|
+
it "should return equal context" do
|
36
|
+
context = Oraora::Context.new('V', schema: 'X', object: 'Y', object_type: 'TABLE').dup
|
37
|
+
expect( context.user ).to eql 'V'
|
38
|
+
expect( context.schema ).to eql 'X'
|
39
|
+
expect( context.object ).to eql 'Y'
|
40
|
+
expect( context.object_type ).to eql 'TABLE'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#set & #traverse' do
|
45
|
+
it "should set root context correctly" do
|
46
|
+
context = Oraora::Context.new.set({})
|
47
|
+
expect( context.level ).to be_nil
|
48
|
+
expect( context.schema ).to be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set schema context correctly" do
|
52
|
+
context = Oraora::Context.new.set(schema: 'A')
|
53
|
+
expect( context.level ).to eql :schema
|
54
|
+
expect( context.schema ).to eql 'A'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should set column context correctly" do
|
58
|
+
context = Oraora::Context.new.set(schema: 'A', object: 'B', object_type: 'TABLE', column: 'C')
|
59
|
+
expect( context.level ).to eql :column
|
60
|
+
expect( context.schema ).to eql 'A'
|
61
|
+
expect( context.object ).to eql 'B'
|
62
|
+
expect( context.column ).to eql 'C'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should set user correctly on the context" do
|
66
|
+
context = Oraora::Context.new('AA').set(schema: 'A')
|
67
|
+
expect( context.level ).to eql :schema
|
68
|
+
expect( context.user ).to eql 'AA'
|
69
|
+
expect( context.schema ).to eql 'A'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should save user when switching context" do
|
73
|
+
context = Oraora::Context.new('AA').set(schema: 'A')
|
74
|
+
context.set(schema: 'B')
|
75
|
+
expect( context.level ).to eql :schema
|
76
|
+
expect( context.user ).to eql 'AA'
|
77
|
+
expect( context.schema ).to eql 'B'
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should raise error on invalid key" do
|
81
|
+
expect { Oraora::Context.new.set(foo: 'A') }.to raise_exception(Oraora::Context::InvalidKey)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should raise error on missing object_type when object is present" do
|
85
|
+
expect { Oraora::Context.new.set(schema: 'A', object: 'B') }.to raise_exception(Oraora::Context::InvalidKey)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise error on invalid combination of keys" do
|
89
|
+
expect { Oraora::Context.new.set(schema: 'A', column: 'B', subprogram: 'C') }.to raise_exception(Oraora::Context::InvalidKey)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#up" do
|
94
|
+
it "should do nothing when already at root" do
|
95
|
+
context = Oraora::Context.new.up
|
96
|
+
expect( context.level ).to be_nil
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should go up from object to schema level" do
|
100
|
+
context = Oraora::Context.new(nil, schema: 'A', object: 'B', object_type: 'TABLE').up
|
101
|
+
expect( context.level ).to eql :schema
|
102
|
+
expect( context.schema ).to eql 'A'
|
103
|
+
expect( context.object ).to be_nil
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should go up from column to object level" do
|
107
|
+
context = Oraora::Context.new(nil, schema: 'X', object: 'Y', object_type: 'TABLE', column: 'Z').up
|
108
|
+
expect( context.level ).to eql :object
|
109
|
+
expect( context.schema ).to eql 'X'
|
110
|
+
expect( context.object ).to be_eql 'Y'
|
111
|
+
expect( context.column ).to be_nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#prompt' do
|
116
|
+
it "should display correct prompt for context" do
|
117
|
+
{
|
118
|
+
{} => '/',
|
119
|
+
{ schema: 'Q' } => 'Q',
|
120
|
+
{ schema: 'U' } => '~',
|
121
|
+
{ schema: 'A', object: 'B', object_type: 'TABLE' } => 'A.B',
|
122
|
+
{ schema: 'U', object: 'B', object_type: 'PACKAGE' } => '~.B',
|
123
|
+
{ schema: 'U', object: 'Y', object_type: 'TABLE', column: 'Z' } => '~.Y.Z',
|
124
|
+
{ schema: 'MMM', object: 'NNN', object_type: 'VIEW', column: 'TEST' } => 'MMM.NNN.TEST'
|
125
|
+
}.each do |hash, prompt|
|
126
|
+
expect( Oraora::Context.new('U', hash).prompt ).to eql prompt
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|