db2c 0.0.4 → 1.0.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.
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
- a db2 console with with history and autocomplete support
1
+ A DB2 console with history and autocomplete support, and few other goodies
2
2
  ====================================
3
3
 
4
- DB2 console mode does not support readline and autocomplete, this is a wrapper for the db2 command with support for both.
4
+ DB2 console mode does not support readline and autocomplete, this is a wrapper for the db2 command mode with support for both. It also tries to make using db2 a little bit more tolerable, adding support for psql-like commands and other shortcuts.
5
5
 
6
6
  Install
7
7
  -------
8
8
 
9
- $ apt-get install [rlwrap][0]
10
- $ gem install db2c
9
+ * apt-get install [rlwrap][0]
10
+ * gem install db2c
11
11
 
12
12
  Contributing
13
13
  ------------
@@ -23,8 +23,8 @@ Once you've made your great commits:
23
23
  Acknowledgement
24
24
  ------------
25
25
 
26
- Chris Jester-Young ([CKY][4]) found out the problem of using shell metacharacters when executing commands from Ruby.
27
- The initial script was inspired by [defunkt's repl][3], for a genenral purpose repl/wrapper, this is your friend.
26
+ * Chris Jester-Young ([CKY][4]) found out the problem of using shell metacharacters when executing commands from Ruby.
27
+ * The initial script was inspired by [defunkt's repl][3], for a genenral purpose repl/wrapper, this is your friend.
28
28
 
29
29
  Meta
30
30
  ----
data/bin/db2c CHANGED
@@ -4,19 +4,38 @@ $LOAD_PATH.unshift 'lib'
4
4
  require "db2c"
5
5
 
6
6
  run = Db2c::Run.new *ARGV
7
+ $DB2CDBG = run.debug?
7
8
 
8
9
  exec "man #{run.gdir}/man/db2c.1" if run.help?
9
- exec "rlwrap -z pipeto -i -r -s 999999 -pBLUE -f #{run.autocomplete} -H ~/.db2c_history db2c --no-rlwrap #{run.args}" if run.wrap?
10
+
11
+ puts "wrapping #{$0} #{run.args}" if run.debug? && !run.nowrap?
12
+ exec "RLWRAP_FILTERDIR=#{run.filters} rlwrap -z 'pipes less grep' -i -r -s 999999 -pBLUE -f #{run.autocomplete} -H ~/.db2c_history #{$0} --now #{run.args}" unless run.nowrap?
13
+
14
+ Db2c::Command.execute "use #{run.default_db}" if run.default_db
15
+ $/ = ";" if run.multiline?
10
16
 
11
17
  loop do
12
18
  print Db2c::Command.prompt
13
19
  begin
14
- command = Db2c::Command.new $stdin.gets
20
+ input = $stdin.gets
21
+ input = input.gsub(/;$/,'') if input
22
+ if input =~ /^(edit|vi|vim|emacs)$/
23
+ command = Db2c::Command.new Db2c::Editor.edit input
24
+ next if command.quit?
25
+ elsif input =~ /^(cat|cp|date|df|du|find|grep|irb|kill|less|ls|man|more|mv|ps|rm|sudo|tail|touch|top|wc|which|who)/
26
+ system input
27
+ next
28
+ elsif input =~ /^!/
29
+ system input[1..-1]
30
+ next
31
+ else
32
+ command = Db2c::Command.new input
33
+ end
15
34
  rescue Interrupt
16
35
  exit
17
36
  end
18
37
  exit if command.quit?
19
- system 'less ~/.db2c_history' if command.history?
38
+ system 'cat ~/.db2c_history' if command.history?
20
39
  system "man #{run.gdir}/man/db2c.1" if command.help?
21
40
  command.execute
22
41
  end
data/lib/db2c.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  module Db2c
2
2
  DEFAULT_PROMPT = "db2c => "
3
- VERSION = "0.0.4"
3
+ VERSION = "1.0.0"
4
+ module CONSTANTS
5
+ DTSELECT = "select char(strip(tabschema) || '.' || strip(tabname), 128) as table from syscat.tables"
6
+ DTORDER = "order by tabschema, tabname"
7
+ end
4
8
  end
5
9
 
6
10
  require "db2c/run.rb"
7
11
  require "db2c/command.rb"
12
+ require "db2c/editor.rb"
data/lib/db2c/command.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  module Db2c
2
2
  class Command
3
3
 
4
+ include CONSTANTS
4
5
  @@cdb = ''
5
- @@debug = false
6
6
 
7
7
  def initialize input
8
8
  if input
9
- puts "initializing: #{input}" if @@debug
10
- @input = input.chomp.strip
11
- parse
9
+ puts "initializing: #{input}" if $DB2CDBG
10
+ @input = input.chomp.strip.gsub(/^db2 /i,'')
11
+ parse unless @input =~ /^(select|update|delete|insert)/i
12
12
  end
13
13
  end
14
14
 
@@ -17,17 +17,46 @@ module Db2c
17
17
  end
18
18
 
19
19
  def parse
20
- @input.gsub! /^db2 /i, ''
21
- @input.gsub! /;$/, ''
22
20
  @input.gsub! /^use /, 'connect to '
23
- @input.gsub! /^\\d /, 'describe '
24
- @input.insert 0, "? sql" if @input =~ /^\-\d+$/
25
- @input.insert 0, "? " if @input =~ /^\d+$/
26
- @input.insert 0, "values " if @input =~ /^current.+$/i
27
21
 
22
+ @input.gsub! /^\\d /, 'describe '
28
23
  if @input =~ /describe [^. ]+\.[^.+ ]+/
29
24
  @input.gsub! /describe /, 'describe table '
25
+ return
26
+ end
27
+
28
+ if @input =~ /^(show|list) databases/ || @input == '\l'
29
+ @input = "list database directory"
30
+ return
31
+ end
32
+
33
+ if @input =~ /^\\lt ?(\w*)$/
34
+ @input = "list tables"
35
+ unless $1.empty?
36
+ @input += $1 == "all" ? " for all" : " for schema #{$1}"
37
+ end
38
+ return
39
+ end
40
+
41
+ if @input =~ /^\\d([a|s|t|v]) ?(\w*)$/
42
+ @input = DTSELECT
43
+ @input += " where type = '#{$1.upcase}'"
44
+ @input += " and tabschema = '#{$2.upcase}'" unless $2.empty?
45
+ @input += " #{DTORDER}"
46
+ return
30
47
  end
48
+
49
+ shortcuts
50
+ end
51
+
52
+ def shortcuts
53
+ prepend /^\-\d+$/, "? sql"
54
+ prepend /^\d+$/, "? "
55
+ prepend /^current.+$/i, "values "
56
+ end
57
+
58
+ def prepend regex, value
59
+ @input.insert 0, value if @input =~ regex
31
60
  end
32
61
 
33
62
  def quit?
@@ -47,7 +76,7 @@ module Db2c
47
76
  end
48
77
 
49
78
  def execute
50
- puts "executing: #{@input}" if @@debug
79
+ puts "executing: #{@input}" if $DB2CDBG
51
80
  system 'db2', @input if valid?
52
81
  if @input =~ /^connect to (.*)$/i
53
82
  @@cdb = $1.downcase
@@ -57,14 +86,6 @@ module Db2c
57
86
  end
58
87
  end
59
88
 
60
- def self.debug=(value)
61
- @@debug = value
62
- end
63
-
64
- def self.debug?
65
- @@debug
66
- end
67
-
68
89
  def self.prompt
69
90
  "db2c".tap do |pr|
70
91
  pr << "(#{@@cdb})" if @@cdb.length > 0
@@ -72,5 +93,9 @@ module Db2c
72
93
  end
73
94
  end
74
95
 
96
+ def self.execute command
97
+ new(command).execute
98
+ end
99
+
75
100
  end
76
101
  end
@@ -0,0 +1,33 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+
4
+ module Db2c
5
+ class Editor
6
+ def self.edit editor
7
+ puts "editor #{editor}" if $DB2CDBG
8
+ @file ||= Tempfile.new(["db2_tempfile", ".sql"])
9
+ mtime = File.stat(@file.path).mtime
10
+
11
+ args = []
12
+ args << command(editor)
13
+ args << @file.path
14
+ args.flatten!
15
+
16
+ @file.close
17
+
18
+ puts "editor args: #{args.inspect}" if $DB2CDBG
19
+
20
+ system(*args)
21
+
22
+ if mtime < File.stat(@file.path).mtime
23
+ return IO.read(@file.path)
24
+ end
25
+ end
26
+
27
+ def self.command editor
28
+ return ["emacs", "-nw"] if editor =~ /^emacs/
29
+ ["vi"]
30
+ end
31
+
32
+ end
33
+ end
data/lib/db2c/run.rb CHANGED
@@ -4,18 +4,17 @@ module Db2c
4
4
 
5
5
  def initialize *args
6
6
  @args = args
7
- puts "args: #{@args}" if debug?
7
+ puts "args: #{@args.inspect}" if debug?
8
8
  @gdir = File.expand_path('../../../', __FILE__)
9
- puts "cdir: #{@gdir}" if debug?
10
- Db2c::Command.debug = debug?
9
+ puts "cdir: #{@gdir.inspect}" if debug?
11
10
 
12
11
  die "version #{Db2c::VERSION}" if version?
13
12
  die "The db2 command was not found!" unless system("which db2 > /dev/null 2> /dev/null")
14
- die "This program depends on rlwrap, please install rlwrap" if wrap? && !system("which rlwrap > /dev/null 2> /dev/null")
13
+ die "This program depends on rlwrap, please install rlwrap" unless nowrap? || system("which rlwrap > /dev/null 2> /dev/null")
15
14
  end
16
15
 
17
16
  def help?
18
- !(@args & %w{-h help -help --help --man}).empty?
17
+ !(@args & %w{-h help -help --help man --man}).empty?
19
18
  end
20
19
  def version?
21
20
  !(@args & %w{-v version -version --version}).empty?
@@ -23,18 +22,33 @@ module Db2c
23
22
  def debug?
24
23
  !(@args & %w{-d debug -debug --debug}).empty?
25
24
  end
26
- def wrap?
27
- (@args & %w{--no-rlwrap --now}).empty?
25
+ def nowrap?
26
+ !(@args & %w{--no-rlwrap --now}).empty?
27
+ end
28
+ def multiline?
29
+ !(@args & %w{-t}).empty?
30
+ end
31
+
32
+ def default_db
33
+ words.first if words.length == 1 && words.first !~ /(help|man|debug|version)/
28
34
  end
29
35
 
30
36
  def autocomplete
31
37
  "#{@gdir}/lib/autocomplete"
32
38
  end
33
39
 
40
+ def filters
41
+ "#{@gdir}/rlwrap/filters"
42
+ end
43
+
34
44
  def args
35
45
  @args.join(' ')
36
46
  end
37
47
 
48
+ def words
49
+ @args.reject { |arg| arg.start_with?('-') }
50
+ end
51
+
38
52
  def die message
39
53
  puts "DB2C: #{message}"
40
54
  puts "DB2C: #{self.inspect}" if debug?
data/man/db2c.1 CHANGED
@@ -1,13 +1,13 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "DB2C" "1" "November 2011" "" ""
4
+ .TH "DB2C" "1" "February 2012" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBdb2c\fR \- A DB2 console with with history and autocomplete support, and few other goodies
8
8
  .
9
9
  .SH "SYNOPSIS"
10
- \fBdb2c\fR \fI\fIoptions\fR\fR
10
+ \fBdb2c\fR [\fIoptions\fR] [dbname]
11
11
  .
12
12
  .SH "DESCRIPTION && EXAMPLES"
13
13
  DB2 console mode does not support readline and autocomplete, this is a wrapper for the db2 command with support for both\.
@@ -51,15 +51,15 @@ db2(testdb) => select * from xyz\.tab[double\-tab]
51
51
 
52
52
  .
53
53
  .IP "\(bu" 4
54
- \fBYou can pipe\fR:
54
+ For example, if a command outputs long lines, \fBless \-S\fR is your friend:
55
55
  .
56
56
  .IP "" 4
57
57
  .
58
58
  .nf
59
59
 
60
60
 
61
- db2(testdb) => select * from large\.table | grep \-v something
62
- db2(testdb) => select * from large\.table | less
61
+ db2(testdb) => select * from table\.with\.many\.columns | less \-S
62
+ (you can scorll horizontally with left/right arrows)
63
63
  .
64
64
  .fi
65
65
  .
@@ -67,15 +67,15 @@ db2(testdb) => select * from large\.table | less
67
67
 
68
68
  .
69
69
  .IP "\(bu" 4
70
- For example, if a command outputs long lines, \fBless \-S\fR is your friend:
70
+ \fBYou can edit last statement or use the editor to write a new multiline statement\fR:
71
71
  .
72
72
  .IP "" 4
73
73
  .
74
74
  .nf
75
75
 
76
76
 
77
- db2(testdb) => select * from table\.with\.many\.columns | less \-S
78
- (you can scorll horizontally with left/right arrows)
77
+ db2(testdb) => edit
78
+ db2(testdb) => emacs
79
79
  .
80
80
  .fi
81
81
  .
@@ -83,23 +83,78 @@ db2(testdb) => select * from table\.with\.many\.columns | less \-S
83
83
 
84
84
  .
85
85
  .IP "\(bu" 4
86
- You can use \fIsome psql\-like\fR commands
86
+ \fBAny !command will be sent to the shell as is\fR:
87
+ .
88
+ .IP "" 4
89
+ .
90
+ .nf
91
+
92
+
93
+ db2(testdb) => !clear
94
+ .
95
+ .fi
96
+ .
97
+ .IP "" 0
98
+
99
+ .
100
+ .IP "\(bu" 4
101
+ You can use \fIsome\fR common shell commands directly:
102
+ .
103
+ .IP "" 4
104
+ .
105
+ .nf
106
+
107
+
108
+ db2(testdb) => ls ~
109
+ db2(testdb) => less ~/somefile
110
+ db2(testdb) => top
111
+ db2(testdb) => irb
112
+ .
113
+ .fi
114
+ .
115
+ .IP "" 0
116
+
117
+ .
118
+ .IP "\(bu" 4
119
+ You can use \fIsome psql\-like\fR meta commands
87
120
  .
88
121
  .IP "" 4
89
122
  .
90
123
  .nf
91
124
 
92
125
 
93
- db2(testdb) => \fB\ed schema\.table\fR
94
- == describe table schema\.table
95
126
  db2(testdb) => \fB\eh\fR
96
127
  == To see this help from within the console
128
+ db2(testdb) => \fB\el\fR
129
+ == list database directory
130
+ db2(testdb) => \fB\elt [all|schema]\fR
131
+ == list tables for all or one schema using db2 list command
132
+ db2(testdb) => \fB\el[t|v|a|s] [schema]\fR
133
+ == list tables|views|aliases|summary\-tables for all or one schema using syscat\.tables
134
+ db2(testdb) => \fB\ed schema\.table\fR
135
+ == describe table schema\.table
97
136
  db2(testdb) => \fB\eq\fR
98
137
  .
99
138
  .fi
100
139
  .
101
140
  .IP "" 0
102
141
 
142
+ .
143
+ .IP "\(bu" 4
144
+ \fBYou can pipe\fR:
145
+ .
146
+ .IP "" 4
147
+ .
148
+ .nf
149
+
150
+
151
+ db2(testdb) => \edv | grep \-v SYS
152
+ db2(testdb) => select * from large\.table | less
153
+ .
154
+ .fi
155
+ .
156
+ .IP "" 0
157
+
103
158
  .
104
159
  .IP "" 0
105
160
  .
@@ -110,6 +165,10 @@ db2(testdb) => \fB\eq\fR
110
165
  Displays this help page\.
111
166
  .
112
167
  .TP
168
+ \fB\-t\fR
169
+ Commands will be executed when you enter a terminating semicolon (;)
170
+ .
171
+ .TP
113
172
  \fB\-\-debug\fR
114
173
  Displays annoying messages\.
115
174
  .
data/man/db2c.1.html CHANGED
@@ -75,7 +75,7 @@
75
75
 
76
76
  <h2 id="SYNOPSIS">SYNOPSIS</h2>
77
77
 
78
- <p><code>db2c</code> <var><a href="#OPTIONS" title="OPTIONS" data-bare-link="true">options</a></var></p>
78
+ <p><code>db2c</code> [<var>options</var>] [dbname]</p>
79
79
 
80
80
  <h2 id="DESCRIPTION-EXAMPLES">DESCRIPTION &amp;&amp; EXAMPLES</h2>
81
81
 
@@ -98,24 +98,46 @@ it remembers..
98
98
  db2(testdb) => list tables for schema xyz
99
99
  db2(testdb) => select * from xyz.tab[double-tab]
100
100
  </pre></li>
101
- <li><p><strong>You can pipe</strong>:
102
- </p><pre>
103
- db2(testdb) => select * from large.table | grep -v something
104
- db2(testdb) => select * from large.table | less
105
- </pre></li>
106
101
  <li><p>For example, if a command outputs long lines, <strong>less -S</strong> is your friend:
107
102
  </p><pre>
108
103
  db2(testdb) => select * from table.with.many.columns | less -S
109
104
  (you can scorll horizontally with left/right arrows)
110
105
  </pre></li>
111
- <li><p>You can use <em>some psql-like</em> commands
106
+ <li><p><strong>You can edit last statement or use the editor to write a new multiline statement</strong>:
107
+ </p><pre>
108
+ db2(testdb) => edit
109
+ db2(testdb) => emacs
110
+ </pre></li>
111
+ <li><p><strong>Any !command will be sent to the shell as is</strong>:
112
+ </p><pre>
113
+ db2(testdb) => !clear
114
+ </pre></li>
115
+ <li><p>You can use <em>some</em> common shell commands directly:
116
+ </p><pre>
117
+ db2(testdb) => ls ~
118
+ db2(testdb) => less ~/somefile
119
+ db2(testdb) => top
120
+ db2(testdb) => irb
121
+ </pre></li>
122
+ <li><p>You can use <em>some psql-like</em> meta commands
112
123
  </p><pre>
113
- db2(testdb) => <strong>\d schema.table</strong>
114
- == describe table schema.table
115
124
  db2(testdb) => <strong>\h</strong>
116
125
  == To see this help from within the console
126
+ db2(testdb) => <strong>\l</strong>
127
+ == list database directory
128
+ db2(testdb) => <strong>\lt [all|schema]</strong>
129
+ == list tables for all or one schema using db2 list command
130
+ db2(testdb) => <strong>\l[t|v|a|s] [schema]</strong>
131
+ == list tables|views|aliases|summary-tables for all or one schema using syscat.tables
132
+ db2(testdb) => <strong>\d schema.table</strong>
133
+ == describe table schema.table
117
134
  db2(testdb) => <strong>\q</strong>
118
135
  </pre></li>
136
+ <li><p><strong>You can pipe</strong>:
137
+ </p><pre>
138
+ db2(testdb) => \dv | grep -v SYS
139
+ db2(testdb) => select * from large.table | less
140
+ </pre></li>
119
141
  </ul>
120
142
 
121
143
 
@@ -123,6 +145,7 @@ db2(testdb) => <strong>\q</strong>
123
145
 
124
146
  <dl>
125
147
  <dt><code>-h</code>, <code>--help</code>, <code>--man</code></dt><dd><p>Displays this help page.</p></dd>
148
+ <dt class="flush"><code>-t</code></dt><dd><p>Commands will be executed when you enter a terminating semicolon (;)</p></dd>
126
149
  <dt class="flush"><code>--debug</code></dt><dd><p>Displays annoying messages.</p></dd>
127
150
  <dt><code>--no-rlrwap</code></dt><dd><p>Don't use rlwrap</p></dd>
128
151
  </dl>
@@ -134,7 +157,7 @@ db2(testdb) => <strong>\q</strong>
134
157
 
135
158
  <h2 id="AUTHOR">AUTHOR</h2>
136
159
 
137
- <p>Samer Abukhait <a href="&#x6d;&#x61;&#x69;&#x6c;&#x74;&#111;&#x3a;&#115;&#97;&#109;&#101;&#x72;&#x40;&#111;&#110;&#45;&#x73;&#x69;&#x74;&#x65;&#x4e;&#79;&#x53;&#80;&#65;&#x4d;&#x2e;&#99;&#111;&#109;" data-bare-link="true">&#x73;&#x61;&#109;&#101;&#114;&#x40;&#x6f;&#110;&#x2d;&#x73;&#105;&#x74;&#101;&#x4e;&#79;&#83;&#x50;&#x41;&#x4d;&#46;&#99;&#111;&#x6d;</a>, @s4mer</p>
160
+ <p>Samer Abukhait <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#111;&#x3a;&#115;&#97;&#x6d;&#101;&#114;&#x40;&#x6f;&#110;&#x2d;&#115;&#x69;&#x74;&#x65;&#78;&#x4f;&#83;&#80;&#x41;&#x4d;&#46;&#99;&#x6f;&#x6d;" data-bare-link="true">&#x73;&#97;&#x6d;&#101;&#114;&#64;&#111;&#x6e;&#45;&#115;&#105;&#116;&#x65;&#x4e;&#79;&#x53;&#80;&#65;&#x4d;&#46;&#x63;&#x6f;&#x6d;</a>, @s4mer</p>
138
161
 
139
162
  <h2 id="SEE-ALSO">SEE ALSO</h2>
140
163
 
@@ -143,7 +166,7 @@ db2(testdb) => <strong>\q</strong>
143
166
 
144
167
  <ol class='man-decor man-foot man foot'>
145
168
  <li class='tl'></li>
146
- <li class='tc'>November 2011</li>
169
+ <li class='tc'>February 2012</li>
147
170
  <li class='tr'>db2c(1)</li>
148
171
  </ol>
149
172