dbi 0.4.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.
Files changed (45) hide show
  1. data/ChangeLog +3694 -0
  2. data/LICENSE +25 -0
  3. data/README +271 -0
  4. data/bin/dbi +518 -0
  5. data/build/Rakefile.dbi.rb +57 -0
  6. data/examples/test1.pl +39 -0
  7. data/examples/test1.rb +20 -0
  8. data/examples/xmltest.rb +8 -0
  9. data/lib/dbi.rb +323 -0
  10. data/lib/dbi/base_classes.rb +12 -0
  11. data/lib/dbi/base_classes/database.rb +135 -0
  12. data/lib/dbi/base_classes/driver.rb +47 -0
  13. data/lib/dbi/base_classes/statement.rb +167 -0
  14. data/lib/dbi/binary.rb +25 -0
  15. data/lib/dbi/columninfo.rb +106 -0
  16. data/lib/dbi/exceptions.rb +65 -0
  17. data/lib/dbi/handles.rb +49 -0
  18. data/lib/dbi/handles/database.rb +211 -0
  19. data/lib/dbi/handles/driver.rb +60 -0
  20. data/lib/dbi/handles/statement.rb +375 -0
  21. data/lib/dbi/row.rb +249 -0
  22. data/lib/dbi/sql.rb +23 -0
  23. data/lib/dbi/sql/preparedstatement.rb +115 -0
  24. data/lib/dbi/sql_type_constants.rb +75 -0
  25. data/lib/dbi/trace.rb +91 -0
  26. data/lib/dbi/types.rb +158 -0
  27. data/lib/dbi/typeutil.rb +108 -0
  28. data/lib/dbi/utils.rb +60 -0
  29. data/lib/dbi/utils/date.rb +59 -0
  30. data/lib/dbi/utils/tableformatter.rb +112 -0
  31. data/lib/dbi/utils/time.rb +52 -0
  32. data/lib/dbi/utils/timestamp.rb +96 -0
  33. data/lib/dbi/utils/xmlformatter.rb +73 -0
  34. data/test/dbi/tc_columninfo.rb +94 -0
  35. data/test/dbi/tc_date.rb +88 -0
  36. data/test/dbi/tc_dbi.rb +178 -0
  37. data/test/dbi/tc_row.rb +256 -0
  38. data/test/dbi/tc_sqlbind.rb +168 -0
  39. data/test/dbi/tc_statementhandle.rb +16 -0
  40. data/test/dbi/tc_time.rb +77 -0
  41. data/test/dbi/tc_timestamp.rb +142 -0
  42. data/test/dbi/tc_types.rb +220 -0
  43. data/test/dbi/trace.rb +26 -0
  44. data/test/ts_dbi.rb +15 -0
  45. metadata +108 -0
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ (C) 2008 Erik Hollensbe <erik@hollensbe.org>. All rights reserved.
2
+
3
+ Please see "README" for earlier copyrights.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+ 3. The name of the author may not be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19
+ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,271 @@
1
+ = Description
2
+ The DBI package is a vendor independent interface for accessing databases.
3
+ It is similar, but not identical to, Perl's DBI module.
4
+
5
+ = Synopsis
6
+
7
+ require 'dbi'
8
+
9
+ # Connect to a database, old style
10
+ dbh = DBI.connect('DBI:Mysql:test', 'testuser', 'testpwd')
11
+
12
+ # Insert some rows, use placeholders
13
+ 1.upto(13) do |i|
14
+ sql = "insert into simple01 (SongName, SongLength_s) VALUES (?, ?)"
15
+ dbh.do(sql, "Song #{i}", "#{i*10}")
16
+ end
17
+
18
+ # Select all rows from simple01
19
+ sth = dbh.prepare('select * from simple01')
20
+ sth.execute
21
+
22
+ # Print out each row
23
+ while row=sth.fetch do
24
+ p row
25
+ end
26
+
27
+ # Close the statement handle when done
28
+ sth.finish
29
+
30
+ # Don't prepare, just do it!
31
+ dbh.do('delete from simple01 where internal_id > 10')
32
+
33
+ # And finally, disconnect
34
+ dbh.disconnect
35
+
36
+ # Same example, but a little more Ruby-ish
37
+ DBI.connect('DBI:Mysql:test', 'testuser', 'testpwd') do | dbh |
38
+
39
+ sql = "insert into simple01 (SongName, SongLength_s) VALUES (?, ?)"
40
+
41
+ dbh.prepare(sql) do | sth |
42
+ 1.upto(13) { |i| sth.execute("Song #{i}", "#{i*10}") }
43
+ end
44
+
45
+ dbh.select_all('select * from simple01') do | row |
46
+ p row
47
+ end
48
+
49
+ dbh.do('delete from simple01 where internal_id > 10')
50
+
51
+ end
52
+
53
+ = Prerequisites
54
+ Ruby 1.8.6 or later is the test target, however you may have success with
55
+ earlier 1.8.x versions of Ruby.
56
+
57
+ = RubyForge Project
58
+ General information: http://ruby-dbi.rubyforge.org
59
+ Project information: http://rubyforge.org/projects/ruby-dbi/
60
+ Downloads: http://rubyforge.org/frs/?group_id=234
61
+
62
+ = Installation
63
+ There are many database drivers (DBDs) available. You only need to install
64
+ the DBDs for the database software that you will be using.
65
+
66
+ == Gem setup:
67
+
68
+ gem install dbi
69
+ # One or more of:
70
+ gem install dbd-mysql
71
+ gem install dbd-pg
72
+ gem install dbd-sqlite3
73
+ gem install dbd-sqlite
74
+
75
+ == Without rubygems:
76
+
77
+ ruby setup.rb config
78
+ ruby setup.rb setup
79
+ ruby setup.rb install
80
+
81
+ == The bleeding edge:
82
+
83
+ git clone git://hollensbe.org/git/ruby-dbi.git
84
+ git checkout -b development origin/development
85
+
86
+ Also available at
87
+
88
+ git clone git://github.com/erikh/ruby-dbi.git
89
+
90
+ = Available Database Drivers (DBDs)
91
+
92
+ == DBD::MySQL
93
+ MySQL
94
+ Depends on the mysql-ruby package from http://www.tmtm.org/mysql or
95
+ available from the RAA.
96
+
97
+ == DBD::ODBC
98
+ ODBC
99
+ Depends on the ruby-odbc package (0.5 or later, 0.9.3 or later recommended) at
100
+ http://www.ch-werner.de/rubyodbc or available from the RAA. Works together
101
+ with unix-odbc.
102
+
103
+ == DBD::OCI8
104
+ OCI8 (Oracle)
105
+ Depends on the the ruby-oci8 package, available on the RAA and RubyForge.
106
+
107
+ == DBD::Pg
108
+ PostgreSQL
109
+ Depends on the pg package, available on RubyForge.
110
+
111
+ == DBD::SQLite
112
+ SQLite (versions 2.x and earlier)
113
+ Depends on the sqlite-ruby package, available on rubyforge.
114
+
115
+ == DBD::SQLite3
116
+ SQLite 3.x
117
+ Depends on the sqlite3-ruby package, available on rubyforge.
118
+
119
+ = Additional Documentation
120
+ See the directories doc/* for DBI and DBD specific information.
121
+ The DBI specification is at doc/DBI_SPEC.rdoc.
122
+ The DBD specification is at doc/DBD_SPEC.rdoc.
123
+
124
+ = Articles
125
+ == Tutorial: Using the Ruby DBI Module
126
+ http://www.kitebird.com/articles/ruby-dbi.html
127
+
128
+ = Applications
129
+ == dbi
130
+ The SQL command line interpreter dbi is available in directory
131
+ bin/. It gets installed by default.
132
+
133
+ = License
134
+
135
+ Copyright (c) 2008 Erik Hollensbe
136
+
137
+ Copyright (c) 2005-2006 Kirk Haines, Francis Hwang, Patrick May and Daniel
138
+ Berger.
139
+
140
+ Copyright (c) 2001, 2002, 2003, 2004 Michael Neumann <mneumann@ntecs.de>
141
+ and others (see the beginning of each file for copyright holder information).
142
+
143
+ All rights reserved.
144
+
145
+ Redistribution and use in source and binary forms, with or without
146
+ modification, are permitted provided that the following conditions are met:
147
+
148
+ 1. Redistributions of source code must retain the above copyright notice,
149
+ this list of conditions and the following disclaimer.
150
+ 2. Redistributions in binary form must reproduce the above copyright notice,
151
+ this list of conditions and the following disclaimer in the documentation
152
+ and/or other materials provided with the distribution.
153
+ 3. The name of the author may not be used to endorse or promote products
154
+ derived from this software without specific prior written permission.
155
+
156
+ THIS SOFTWARE IS PROVIDED 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
157
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
158
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
159
+ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
160
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
161
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
162
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
163
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
164
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
165
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
166
+
167
+ This is the BSD license which is less restrictive than GNU's GPL
168
+ (General Public License).
169
+
170
+ = Contributors
171
+
172
+ Pistos
173
+ Too much to specify. Infinite patience and help.
174
+
175
+ Christopher Maujean
176
+ Lots of initial help when reviving the project.
177
+
178
+ Jun Mukai <mukai@jmuk.org>
179
+ Contributed initial SQLite3 DBD.
180
+
181
+ John J. Fox IV
182
+ Lots of help testing on multiple platforms.
183
+
184
+ Kirk Haines
185
+ One of the authors of the rewrite effort (January 2006).
186
+
187
+ Francis Hwang
188
+ One of the authors of the rewrite effort (January 2006).
189
+
190
+ Patrick May
191
+ One of the authors of the rewrite effort (January 2006).
192
+
193
+ Daniel Berger
194
+ One of the authors of the rewrite effort (January 2006).
195
+
196
+ Michael Neumann
197
+ Original author of Ruby/DBI; wrote the DBI and most of the DBDs.
198
+
199
+ Rainer Perl
200
+ Author of Ruby/DBI 0.0.4 from which many good ideas were taken.
201
+
202
+ Jim Weirich
203
+ Original author of DBD::Pg. Wrote additional code (e.g. sql.rb,
204
+ testcases). Gave many helpful hints and comments.
205
+
206
+ Eli Green
207
+ Implemented DatabaseHandle#columns for Mysql and Pg.
208
+
209
+ Masatoshi SEKI
210
+ For his version of module BasicQuote in sql.rb.
211
+
212
+ John Gorman
213
+ For his case insensitive load_driver patch and parameter parser.
214
+
215
+ David Muse
216
+ For testing the DBD::SQLRelay and for his initial DBD.
217
+
218
+ Jim Menard
219
+ Extended DBD::Oracle for method columns.
220
+
221
+ Joseph McDonald
222
+ Fixed bug in DBD::Pg (default values in method columns).
223
+
224
+ Norbert Gawor
225
+ Fixed bug in DBD::ODBC (method columns) and proxyserver.
226
+
227
+ James F. Hranicky
228
+ Patch for DBD::Pg (cache PGResult#result in Tuples) which increased
229
+ performance by a factor around 100.
230
+
231
+ Stephen Davies
232
+ Added method Statement#fetch_scroll for DBD::Pg.
233
+
234
+ Dave Thomas
235
+ Several enhancements.
236
+
237
+ Brad Hilton
238
+ Column coercing patch for DBD::Mysql.
239
+
240
+ Sean Chittenden
241
+ Originally a co-owner of the project. Submitted several patches
242
+ and helped with lots of comments.
243
+
244
+ MoonWolf
245
+ Provided the quote/escape_byte patch for DBD::Pg, DBD::SQLite patch and
246
+ Database#columns implementation. Further patches.
247
+
248
+ Paul DuBois
249
+ Fixed typos and formatting. Maintains DBD::Mysql.
250
+
251
+ Tim Bates
252
+ Bug fixes for Mysql and DBI.
253
+
254
+ Brian Candler
255
+ Zero-padding date/time/timestamps fix.
256
+
257
+ Florian G. Pflug
258
+ Discussion and helpful comments/benchmarks about DBD::Pg async_exec vs.
259
+ exec.
260
+
261
+ Oliver M. Bolzer
262
+ Patches to support Postgres arrays for DBD::Pg.
263
+
264
+ Stephen R. Veit
265
+ ruby-db2 and DBD::DB2 enhancements.
266
+
267
+ Dennis Vshivkov
268
+ DBD::Pg patches
269
+
270
+ Cail Borrell from frontbase.com
271
+ For the Frontbase DBD and C interface.
data/bin/dbi ADDED
@@ -0,0 +1,518 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2001, 2002 Michael Neumann <neumann@s-direktnet.de>
4
+ #
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products
16
+ # derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
+ # THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
+ # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
+ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ #
29
+ # $Id: sqlsh.rb,v 1.2 2006/01/24 04:20:01 francis Exp $
30
+ #
31
+
32
+ begin
33
+ require 'rubygems'
34
+ gem 'dbi'
35
+ rescue LoadError => e
36
+ end
37
+
38
+ require "dbi"
39
+
40
+ begin
41
+ require "readline"
42
+ $use_readline = true
43
+ rescue LoadError
44
+ $use_readline = false
45
+ end
46
+
47
+ require "irb"
48
+ require "irb/completion"
49
+
50
+ $paging = true
51
+ $irb_completion = Readline.completion_proc
52
+
53
+ require "getoptlong"
54
+
55
+ class ReadlineControl
56
+
57
+ attr_accessor :keywords
58
+
59
+ def initialize
60
+ @keywords = []
61
+ set_prompt
62
+ initCompletion
63
+ end
64
+
65
+ def initCompletion
66
+ if $use_readline
67
+ Readline.completion_proc = proc {|str| complete(str) }
68
+ end
69
+ end
70
+
71
+ def complete(str)
72
+ @keywords.grep(/^#{Regexp.escape(str)}/i)
73
+ end
74
+
75
+ def set_prompt(prompt="> ")
76
+ @prompt = prompt
77
+ end
78
+
79
+ def readline
80
+ if $use_readline
81
+ Readline.readline(@prompt, true)
82
+ else
83
+ print @prompt
84
+ $stdin.readline
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ class Command
91
+
92
+ def tokens(sql)
93
+ DBI::SQL::PreparedStatement.tokens(sql)
94
+ end
95
+
96
+ def readCommand
97
+ line = ""
98
+
99
+ $rd.set_prompt(PROMPT)
100
+ begin
101
+ if $input.nil?
102
+ # no source file to read from
103
+ l = $rd.readline
104
+ else
105
+ # source file has still data
106
+ l = $input.gets
107
+ if l.nil?
108
+ $input = nil
109
+ next
110
+ end
111
+ end
112
+
113
+ next if l.strip.empty?
114
+ l = l.chomp + "\n"
115
+ line << l
116
+
117
+ puts $file + INPUT + l unless $input.nil?
118
+ $rd.set_prompt(PROMPT_CONT)
119
+ end until complete?(line)
120
+
121
+ return line.strip
122
+ end
123
+
124
+ private
125
+
126
+ def complete?(line)
127
+ line =~ /^\s*\\/ or (tokens(line).last || "") =~ /;\s*$/
128
+ end
129
+ end
130
+
131
+ class Actions
132
+ ACTIONS = [
133
+ [ /^\\q(uit)?\s*$/i, :quit ],
134
+ [ /^\\h(elp)?\s*$/i, :help ],
135
+ [ /^\\t(ables)?/i, :tables ],
136
+ [ /^\\dt/i, :describeTable ],
137
+ [ /^\\s(elect)?/i, :select ],
138
+
139
+ [ /^\\rb/i, :ruby ],
140
+ [ /^\\irb/i, :irb ],
141
+
142
+ [ /^\\c(ommit)?\s*$/i, :commit ],
143
+ [ /^\\r(ollback)?\s*$/i, :rollback ],
144
+ [ /^\\a(utocommit)?(\s+(on|off)?)?\s*$/i, :autocommit ],
145
+ [ /^\\i(nput)?/i, :input ],
146
+ [ /^\\o(utput)?/i, :output ],
147
+ [ /^\\pl/i, :pageLength ],
148
+ [ /^\\p/i, :togglePaging ],
149
+
150
+ [ //, :unknownCommand ]
151
+ ]
152
+
153
+ def dispatchCommand(line)
154
+ ACTIONS.each do |regexp, action|
155
+ if line =~ regexp then
156
+ send(action, $~)
157
+ return
158
+ end
159
+ end
160
+ end
161
+
162
+ def quit(match)
163
+ puts
164
+ puts "BYE"
165
+ puts
166
+
167
+ begin
168
+ Conn.disconnect
169
+ rescue DBI::Error => err
170
+ puts
171
+ puts err.message
172
+ p err.backtrace if $DEBUG
173
+ puts
174
+ end
175
+
176
+ exit
177
+ end
178
+
179
+ def help(match)
180
+ head = %w(Function Description)
181
+ rows = [
182
+ ["\\h[elp]", "Display this help screen"],
183
+ ["", ""],
184
+
185
+ ["\\t[ables]", "Display all available tables"],
186
+ ["\\dt table", "Describe columns of 'table'"],
187
+ ["\\s[elect] table", "short for SELECT * FROM 'table'"],
188
+
189
+ ["", ""],
190
+ ["\\c[ommit]", "Commits the current transaction"],
191
+ ["\\r[ollback]", "Rolls back the current transaction"],
192
+ ["\\a[utocommit]", "Show current autocommit mode"],
193
+ ["\\a[utocommit] on|off", "Switch autocommit mode on/off"],
194
+ ["", ""],
195
+
196
+ ["\\i[nput] filename", "Read and execute lines from 'filename'"],
197
+ ["\\o[utput]", "Disable output"],
198
+ ["\\o[utput] filename", "Store SQL statments the user inputs into 'filename'"],
199
+ ["", ""],
200
+
201
+ ["\\pl n", "Set page length to 'n'"],
202
+ ["\\p", "Toggle paging"],
203
+ ["", ""],
204
+ ["\\rb ...", "Execute the rest of the line as Ruby sourcecode"],
205
+ ["\\irb", "Execute irb within this context"],
206
+
207
+ ["", ""],
208
+
209
+ ["\\q[uit]", "Quit this program"]
210
+ ]
211
+
212
+ puts
213
+ puts "Help: "
214
+ output_table(head, rows)
215
+ puts
216
+ end
217
+
218
+ def tables(match)
219
+ head = ["Table name"]
220
+ rows = Conn.tables.collect {|name| [name]}
221
+
222
+ puts
223
+ puts "Tables: "
224
+ output_table(head, rows)
225
+ puts
226
+ end
227
+
228
+ def describeTable(match)
229
+ table = match.post_match.strip
230
+
231
+ head = %w(name type_name precision scale default nullable indexed primary unique)
232
+
233
+ rows = Conn.columns(table).collect {|col| head.collect{|a| col[a]} }
234
+
235
+ puts
236
+ puts "Table '#{table}': "
237
+ output_table(head, rows)
238
+ puts
239
+ end
240
+
241
+ def select(match)
242
+ executeSQL("SELECT * FROM #{match.post_match};")
243
+ end
244
+
245
+ def commit(match)
246
+ Conn.commit
247
+ puts
248
+ puts "COMMIT"
249
+ puts
250
+ end
251
+
252
+ def rollback(match)
253
+ Conn.rollback
254
+ puts
255
+ puts "ROLLBACK"
256
+ puts
257
+ end
258
+
259
+ def autocommit(match)
260
+ mode = match[3]
261
+ if mode =~ /on/i
262
+ Conn['AutoCommit'] = true
263
+ puts
264
+ puts "AUTOCOMMIT IS NOW ON"
265
+ puts
266
+ elsif mode =~ /off/i
267
+ Conn['AutoCommit'] = false
268
+ puts
269
+ puts "AUTOCOMMIT IS NOW OFF"
270
+ puts
271
+ else
272
+ puts
273
+ if Conn['AutoCommit'] == true
274
+ puts "AUTOCOMMIT is currently switched ON"
275
+ elsif Conn['AutoCommit'] == false
276
+ puts "AUTOCOMMIT is currently switched OFF"
277
+ else
278
+ puts "AUTOCOMMIT is in unknown state"
279
+ end
280
+ puts
281
+ end
282
+ end
283
+
284
+ def input(match)
285
+ puts
286
+ $file = match.post_match.strip
287
+
288
+ begin
289
+ $input = File.open($file)
290
+ puts "EXECUTE file #{$file}"
291
+ puts
292
+ rescue
293
+ puts "Couldn't read from file #{$file}"
294
+ puts
295
+ end
296
+ end
297
+
298
+ def output(match)
299
+ puts
300
+ file = match.post_match.strip
301
+
302
+ if file.empty?
303
+ $output.close if $output
304
+ $output = nil
305
+ puts "Disabled OUTPUT"
306
+ puts
307
+ else
308
+ begin
309
+ $output = File.new(file, "w+")
310
+ puts "Set OUTPUT to file #{file}"
311
+ puts
312
+ rescue
313
+ puts "Couldn't set OUTPUT to file #{file}"
314
+ puts
315
+ end
316
+ end
317
+ end
318
+
319
+ def togglePaging(match)
320
+ $paging = !$paging
321
+
322
+ puts "Paging is now " + ($paging ? "on" : "off") + "."
323
+ end
324
+
325
+ def pageLength(match)
326
+ puts
327
+ $page_len = match.post_match.strip.to_i
328
+ $page_len = DEFAULT_PAGE_LENGTH if $page_len <= 0
329
+
330
+ puts "New page length is #{$page_len}."
331
+ puts
332
+ end
333
+
334
+ def irb(match)
335
+ Readline.completion_proc = $irb_completion
336
+ puts
337
+ puts "================================== IRB ==============================="
338
+ begin
339
+ IRB.start
340
+ rescue SystemExit
341
+ end
342
+ puts "======================================================================"
343
+ $rd.initCompletion
344
+ end
345
+
346
+ def ruby(match)
347
+ puts
348
+ eval match.post_match
349
+ puts
350
+ end
351
+
352
+ def unknownCommand(match)
353
+ puts
354
+ puts "Unknown command!"
355
+ puts
356
+ end
357
+
358
+ end
359
+
360
+ def output_table(header, rows)
361
+ DBI::Utils::TableFormatter.ascii(header, rows, nil, nil, nil, nil, $page_len) do
362
+ if $paging
363
+ print "[enter to continue, a to abort]"
364
+ break if $stdin.readline.chomp.downcase == "a"
365
+ end
366
+ end
367
+ end
368
+
369
+ def executeSQL(sql)
370
+ sql = $` if sql =~ /;\s*$/
371
+
372
+ start = ::Time.now
373
+ stmt = Conn.execute(sql)
374
+
375
+ head = stmt.column_names
376
+
377
+ # DDL, DCL
378
+ if head.empty?
379
+ puts
380
+ nr = stmt.rows
381
+ if nr == 0
382
+ puts " No rows affected"
383
+ elsif nr == 1
384
+ puts " 1 row affected"
385
+ else
386
+ puts " #{nr} rows affected"
387
+ end
388
+ puts
389
+ else
390
+ rows = stmt.fetch_all
391
+ tm = ::Time.now - start
392
+
393
+ puts
394
+ output_table(head, rows || [])
395
+ print " "
396
+ if rows.nil?
397
+ print "No rows in set"
398
+ elsif rows.size == 1
399
+ print "1 row in set"
400
+ else
401
+ print "#{rows.size} rows in set"
402
+ end
403
+
404
+ puts " (#{(tm.to_f*1000).to_i / 1000.0} sec)"
405
+ puts
406
+ end
407
+
408
+ $rd.keywords = SQL_KEYWORDS + Conn.tables
409
+ end
410
+
411
+ DEFAULT_PAGE_LENGTH = 37
412
+
413
+ $output = nil
414
+ $input = nil
415
+ $page_len = DEFAULT_PAGE_LENGTH
416
+ PROMPT = "dbi => "
417
+ PROMPT_CONT = "dbi -> "
418
+ INPUT = " >> "
419
+
420
+ SQL_KEYWORDS = %w(
421
+ INSERT DELETE UPDATE SELECT FROM WHERE IN LIKE SET VALUES INTO
422
+ CREATE TABLE DROP
423
+ COMMIT ROLLBACK
424
+ CHAR VARCHAR VARCHAR2 INT INTEGER NUMBER FLOAT REAL LONG CLOB BLOB DECIMAL
425
+ DBCLOB DBBLOB
426
+ )
427
+
428
+ # ---------------------------------------------------------------------------
429
+
430
+ opts = GetoptLong.new(
431
+ ["--file", "-f", GetoptLong::REQUIRED_ARGUMENT ]
432
+ )
433
+ opts.each do |opt, arg|
434
+ case opt
435
+ when "--file"
436
+ $input_file_name = arg
437
+ end
438
+ end
439
+
440
+ if ARGV.size < 1 or ARGV.size > 3
441
+ puts
442
+ puts "USAGE: #{$0} [--file file] driver_url [user [password] ]"
443
+ puts
444
+
445
+ puts "Available driver and datasources:"
446
+ puts
447
+ for driver in DBI.available_drivers do
448
+ puts driver
449
+ begin
450
+ ds = DBI.data_sources(driver)
451
+ for datasource in ds
452
+ puts " " + datasource
453
+ end
454
+ rescue => err
455
+ end
456
+ puts
457
+ end
458
+ puts
459
+
460
+ exit 1
461
+ else
462
+ DRIVER_URL = ARGV.shift
463
+ USER = ARGV.shift
464
+ PASS = ARGV.shift
465
+ end
466
+
467
+ puts
468
+ begin
469
+ Conn = DBI.connect(DRIVER_URL, USER, PASS)
470
+ print "CONNECT TO #{DRIVER_URL} "
471
+ print "USER #{USER} " unless USER.nil?
472
+ print "PASS #{PASS} " unless PASS.nil?
473
+ print "\n"
474
+
475
+ rescue DBI::Error, DBI::Warning => err
476
+ p err
477
+ exit
478
+ end
479
+
480
+ puts
481
+
482
+ $rd = ReadlineControl.new
483
+ $rd.keywords = SQL_KEYWORDS + Conn.tables
484
+
485
+ cmd = Command.new
486
+ act = Actions.new
487
+
488
+ # --file option
489
+ if $input_file_name
490
+ def $input_file_name.post_match
491
+ $input_file_name
492
+ end
493
+ act.input($input_file_name)
494
+ end
495
+
496
+ # Main-Loop -----------------------------------
497
+
498
+ loop do
499
+ line = cmd.readCommand
500
+
501
+ $output.puts line unless $output.nil?
502
+
503
+ begin
504
+ if line =~ /^\\/ then
505
+ # Internal Command
506
+ act.dispatchCommand(line)
507
+ else
508
+ # SQL Command
509
+ executeSQL(line)
510
+ end
511
+ rescue DBI::Error => err
512
+ puts
513
+ puts err.message
514
+ p err.backtrace if $DEBUG
515
+ puts
516
+ end
517
+ end
518
+