teradata-cli 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teradata-cli.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Teradata::Cli
2
+
3
+ Teradata::Cli is an access module which allows Ruby scripts
4
+ to access Teradata RDBMS by CLIv2 interface.
5
+
6
+ It's based on the [Ruby/CLIv2](http://sourceforge.net/projects/rubycli/) library.
7
+
8
+
9
+ ## Requirements
10
+
11
+ CLIv2 (32bit / 64bit)
12
+ C compiler
13
+
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'teradata-cli'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install teradata-cli
28
+
29
+
30
+ ## Usage
31
+
32
+ Look the examples folder
33
+
34
+
35
+ ## Tests
36
+
37
+ $ export TEST_LOGON_STRING=dbc/user,password
38
+ $ ruby -Ilib:test test/all
39
+
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/examples/query.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Dispatches SQL query and shows result records.
4
+ #
5
+ # Usage:
6
+ # $ export LOGON_STRING=dbc/user,pass
7
+ # $ ruby example/query.rb 'SELECT * FROM x'
8
+ #
9
+
10
+ require 'teradata'
11
+ require 'logger'
12
+ require 'pp'
13
+
14
+ logon_string = ENV['LOGON_STRING']
15
+ unless logon_string
16
+ $stderr.puts "set environment variable LOGON_STRING"
17
+ exit 1
18
+ end
19
+
20
+ sql = ARGV[0]
21
+ unless sql
22
+ $stderr.puts "Usage: ruby #{File.basename($0)} QUERY"
23
+ exit 1
24
+ end
25
+
26
+ log = Logger.new($stderr)
27
+ log.sev_threshold = $DEBUG ? Logger::DEBUG : Logger::INFO
28
+
29
+ Teradata.connect(logon_string, :logger => log) {|conn|
30
+ conn.query(sql) {|result_sets|
31
+ result_sets.each_result_set do |rs|
32
+ pp rs
33
+ rs.each_record do |rec|
34
+ pp rec
35
+ end
36
+ end
37
+ }
38
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Show Query Bands of current sessions.
4
+ #
5
+ # Usage:
6
+ # $ export LOGON_STRING=dbc/user,pass
7
+ # $ ruby example/show-queryband.rb
8
+ #
9
+
10
+ require 'teradata'
11
+
12
+ logon_string = ENV['LOGON_STRING']
13
+ unless logon_string
14
+ $stderr.puts "set environment variable LOGON_STRING"
15
+ exit 1
16
+ end
17
+
18
+ Teradata.connect(logon_string) {|conn|
19
+ conn.query("SELECT * FROM dbc.sessionInfo") {|rs|
20
+ rs.each do |rec|
21
+ user = rec[:UserName].strip
22
+ band = rec[:QueryBand]
23
+ puts "#{user}\t#{band}"
24
+ end
25
+ }
26
+ }
@@ -0,0 +1,86 @@
1
+ require 'win32ole'
2
+ require 'fileutils'
3
+
4
+ class Excel
5
+
6
+ def Excel.open_worksheet(path, sheet_name, mode, &block)
7
+ open {|app| app.open_worksheet(path, sheet_name, mode, &block) }
8
+ end
9
+
10
+ def Excel.open_book(path, mode, &block)
11
+ open {|app| app.open_book(path, mode, &block) }
12
+ end
13
+
14
+ FileSystem = WIN32OLE.new('Scripting.FileSystemObject')
15
+
16
+ def Excel.open(visible = $DEBUG, &block)
17
+ new(visible, &block)
18
+ end
19
+
20
+ @@const_loaded = false
21
+
22
+ def initialize(visible = $DEBUG)
23
+ @app = WIN32OLE.new('Excel.Application')
24
+ unless @@const_loaded
25
+ WIN32OLE.const_load @app, Excel
26
+ @@const_loaded = true
27
+ end
28
+ @app.visible = true if visible
29
+ yield self if block_given?
30
+ ensure
31
+ quit if block_given? and @app
32
+ end
33
+
34
+ def quit
35
+ @app.quit
36
+ end
37
+
38
+ def open_book(path, mode)
39
+ begin
40
+ book = @app.workbooks.open(win_extend_path(path))
41
+ yield book
42
+ book.save if mode == 'w'
43
+ ensure
44
+ book.saved = true # avoid confirmation message
45
+ @app.workbooks.close
46
+ end
47
+ end
48
+
49
+ def open_worksheet(path, sheet_name, mode)
50
+ open_book(path, mode) {|book|
51
+ sheet = book.worksheets.item(1)
52
+ sheet.extend WorkSheetMethods
53
+ yield sheet
54
+ }
55
+ end
56
+
57
+ def win_extend_path(path)
58
+ FileSystem.getAbsolutePathName(path)
59
+ end
60
+ private :win_extend_path
61
+
62
+ module WorkSheetMethods
63
+ def [](y, x)
64
+ cell = cells().item(y, x)
65
+ if cell.mergeCells
66
+ cell.mergeArea.item(1, 1).value
67
+ else
68
+ cell.value
69
+ end
70
+ end
71
+
72
+ def []=(y, x, value)
73
+ cell = cells().item(y, x)
74
+ if cell.mergeCells
75
+ cell.mergeArea.item(1, 1).value = value
76
+ else
77
+ cell.value = value
78
+ end
79
+ end
80
+
81
+ def last_cell
82
+ cells().specialCells(Excel::XlLastCell)
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,94 @@
1
+ require 'excel'
2
+ require 'fileutils'
3
+ require 'pp'
4
+ require 'teradata'
5
+
6
+ def main
7
+ logon_string, template, output = ARGV
8
+ usage_exit unless logon_string
9
+ usage_exit unless template
10
+ output ||= 'out.xls'
11
+
12
+ FileUtils.cp template, output
13
+ Excel.open(true) {|app|
14
+ app.open_worksheet(output, 'Sheet1', 'w') {|sheet|
15
+ fill_sheet sheet, logon_string
16
+ }
17
+ }
18
+ end
19
+
20
+ def fill_sheet(sheet, logon_string)
21
+ # Get SQL Cell
22
+ sql_cell = sheet.cells.find('%SQL')
23
+ p ['sql_cell', sql_cell.address]
24
+ sql = sql_cell.value.slice(/%SQL\s+(.*)/m, 1).strip
25
+ p sql
26
+
27
+ # Get Value Cells
28
+ value_cell = sheet.cells.find('%=', sql_cell)
29
+ p ['value', value_cell.address]
30
+ exprs = [expr_proc(value_cell)]
31
+ c = value_cell
32
+ while true
33
+ next_c = sheet.range(address(c.row.to_i, c.column.to_i + 1))
34
+ break unless /^%=/ =~ next_c.value
35
+ c = next_c
36
+ p ['value', c.address]
37
+ exprs.push expr_proc(c)
38
+ end
39
+ pp exprs
40
+
41
+ tmpl_range = sheet.range(value_cell.address + ':' + c.address)
42
+ xl = value_cell.column
43
+ xr = c.column
44
+ y = value_cell.row + 1
45
+
46
+ # Execute SQL and fill cells by data
47
+ Teradata.connect(logon_string) {|conn|
48
+ conn.query(sql) {|rs|
49
+ rs.each do |rec|
50
+ pp rec
51
+ values = exprs.map {|expr| expr.call(rec) }
52
+ pp values
53
+ tmpl_range.copy
54
+ sheet.range(address(y, xl) + ':' + address(y, xr)).insert Excel::XlShiftDown
55
+ sheet.range(address(y, xl) + ':' + address(y, xr)).value = values
56
+ y += 1
57
+ end
58
+ }
59
+ }
60
+
61
+ # remove metadata cells
62
+ tmpl_range.delete Excel::XlShiftUp
63
+ sheet.rows(sql_cell.row).delete
64
+ end
65
+
66
+ def usage_exit
67
+ $stderr.puts "Usage: #{$0} LOGON_STRING TEMPLATE [OUTPUT]"
68
+ exit 1
69
+ end
70
+
71
+ def expr_proc(cell)
72
+ expr = cell.value.slice(/%=(.*)/m, 1).strip
73
+ lambda {|_| eval(expr).to_s }
74
+ end
75
+
76
+ def address(row, col)
77
+ "$#{column_string(col)}$#{row}"
78
+ end
79
+
80
+ ALPHA = ('a'..'z').to_a
81
+
82
+ def column_string(col)
83
+ result = []
84
+ n = col - 1
85
+ while n >= 26
86
+ n, mod = n.divmod(26)
87
+ result.unshift mod
88
+ n -= 1
89
+ end
90
+ result.unshift n
91
+ result.map {|i| ALPHA[i] }.join('')
92
+ end
93
+
94
+ main
Binary file
@@ -0,0 +1,6 @@
1
+ require 'teradata'
2
+ Teradata.connect(ENV['LOGON_STRING']) {|conn|
3
+ conn.tables("tudemo").
4
+ select {|table| /_bak$/ =~ table.name }.
5
+ each {|table| conn.drop table }
6
+ }
@@ -0,0 +1,7 @@
1
+ require 'teradata'
2
+ Teradata.connect(ENV['LOGON_STRING']) {|conn|
3
+ conn.tables("tudemo").
4
+ sort_by {|table| -table.size }.
5
+ first(5).
6
+ each {|table| puts "#{table.name}\t#{table.size}" }
7
+ }
@@ -0,0 +1,197 @@
1
+ # $Id: bitdao.rb 184 2009-08-12 08:46:22Z aamine $
2
+
3
+ class BitDAO
4
+ module Error; end
5
+
6
+ class BaseError < ::StandardError
7
+ include Error
8
+ end
9
+
10
+ class IntegrityError < BaseError; end
11
+ class ObjectNotExist < BaseError; end
12
+
13
+ def error
14
+ @connection.error_class
15
+ end
16
+
17
+ def sql_error
18
+ @connection.sql_error_class
19
+ end
20
+
21
+ def initialize(log, connection)
22
+ @log = log
23
+ @connection = connection
24
+ end
25
+
26
+ def load_object(_class, sql)
27
+ list = load_objects(_class, sql)
28
+ if list.empty?
29
+ raise ObjectNotExist, "no record exist: #{_class}"
30
+ end
31
+ if list.size > 1
32
+ raise IntegrityError, "too many #{_class} loaded: #{list.size} for 1"
33
+ end
34
+ list.first
35
+ end
36
+
37
+ def load_objects(_class, sql)
38
+ @log.info(self.class) { "[SEL] #{sql}" }
39
+ result = []
40
+ @connection.execute_query(sql) {|rs|
41
+ rs.each_record do |rec|
42
+ result.push _class.for_record(self, rec)
43
+ end
44
+ }
45
+ @log.info(self.class) { "#{result.size} records" }
46
+ result
47
+ end
48
+
49
+ def exec_sql(sql, level = Logger::INFO)
50
+ @log.add(level, nil, self.class) { "[UPD] #{sql}" } if level
51
+ @connection.execute_update sql
52
+ end
53
+
54
+ def transaction
55
+ aborting = false
56
+ exec_sql "BEGIN TRANSACTION;"
57
+ begin
58
+ yield
59
+ rescue Teradata::CLI::UserAbort => err
60
+ aborting = true
61
+ raise err
62
+ ensure
63
+ if $@
64
+ begin
65
+ abort unless aborting
66
+ rescue Teradata::CLI::UserAbort # do not override original exception
67
+ end
68
+ else
69
+ exec_sql "END TRANSACTION;"
70
+ end
71
+ end
72
+ end
73
+
74
+ def abort
75
+ exec_sql "ABORT;"
76
+ end
77
+
78
+ private
79
+
80
+ def int(n)
81
+ return 'NULL' unless n
82
+ n
83
+ end
84
+
85
+ def string(str)
86
+ return 'NULL' unless str
87
+ "'" + str.gsub(/'/, "''") + "'"
88
+ end
89
+
90
+ def date(d)
91
+ return 'NULL' unless d
92
+ "DATE '#{d.strftime('%Y-%m-%d')}'"
93
+ end
94
+
95
+ def timestamp(t)
96
+ return 'NULL' unless t
97
+ "TIMESTAMP '#{t.strftime('%Y-%m-%d %H:%M:%S')}'"
98
+ end
99
+
100
+
101
+ def BitDAO.define(&block)
102
+ PersistentObject.define(&block)
103
+ end
104
+
105
+ class PersistentObject
106
+
107
+ def PersistentObject.define(&block)
108
+ c = Class.new(PersistentObject)
109
+ c.module_eval(&block)
110
+ c.define_initialize c.slots
111
+ c
112
+ end
113
+
114
+ def PersistentObject.slot(name, _class, column = nil)
115
+ attr_reader name
116
+ (@slots ||= []).push Slot.new(name, _class, column)
117
+ end
118
+
119
+ class << self
120
+ attr_reader :slots
121
+ end
122
+
123
+ class Slot
124
+ def initialize(name, _class, column)
125
+ @name = name
126
+ @class = _class
127
+ @column = column || name
128
+ end
129
+
130
+ attr_reader :name
131
+ attr_reader :column
132
+
133
+ def parse(s)
134
+ @class.parse(s)
135
+ end
136
+ end
137
+
138
+ def PersistentObject.sql_integer
139
+ SQLInteger.new
140
+ end
141
+
142
+ class SQLInteger
143
+ def parse(i)
144
+ i
145
+ end
146
+ end
147
+
148
+ def PersistentObject.sql_string
149
+ SQLString.new
150
+ end
151
+
152
+ class SQLString
153
+ # CHAR/VARCHAR field returns extra spaces, remove it always.
154
+ def parse(str)
155
+ str ? str.rstrip : nil
156
+ end
157
+ end
158
+
159
+ def PersistentObject.sql_date
160
+ SQLDate.new
161
+ end
162
+
163
+ def PersistentObject.sql_timestamp
164
+ SQLDate.new
165
+ end
166
+
167
+ class SQLDate
168
+ def parse(str)
169
+ # "2009-01-23"
170
+ Time.parse(str)
171
+ end
172
+ end
173
+
174
+ def PersistentObject.for_record(dao, rec)
175
+ unless rec.size >= @slots.size
176
+ raise DatabaseError, "wrong column number of record (#{rec.size} for #{@slots.size})"
177
+ end
178
+ obj = new(* @slots.map {|slot| slot.parse(rec[slot.column]) })
179
+ obj._dao = dao
180
+ obj
181
+ end
182
+
183
+ def PersistentObject.define_initialize(slots)
184
+ param_list = slots.map {|s| s.name }.join(', ')
185
+ ivar_list = slots.map {|s| "@#{s.name}" }.join(', ')
186
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
187
+ def initialize(#{param_list})
188
+ #{ivar_list} = #{param_list}
189
+ end
190
+ End
191
+ end
192
+
193
+ attr_writer :_dao
194
+
195
+ end
196
+
197
+ end