rubeus 0.0.7-java → 0.0.8-java

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.
@@ -0,0 +1,58 @@
1
+ module Rubeus::Jdbc
2
+ class MetaElement
3
+ attr_reader :meta_data, :jdbc_info, :options
4
+ def initialize(meta_data, attrs, options = nil)
5
+ @meta_data = meta_data
6
+ @jdbc_info = attrs.dup
7
+ attrs.each do |attr, value|
8
+ m = "#{attr.downcase}="
9
+ self.send(m, value) if respond_to?(m)
10
+ end
11
+ @options = options ? options.dup : {}
12
+ end
13
+
14
+ def pretty_print_instance_variables
15
+ self.instance_variables.sort.map{|v| v.to_sym} - [:@meta_data, :@jdbc_info, :@table]
16
+ end
17
+
18
+ end
19
+
20
+ module FullyQualifiedNamed
21
+ FQN_ATTRS = [:table_cat, :table_schem, :table_name]
22
+ FQN_ATTR_STRS = FQN_ATTRS.map{|attr| attr.to_s.upcase}
23
+
24
+ attr_accessor *FQN_ATTRS
25
+
26
+ def fully_qualified_name
27
+ [table_cat, table_schem, table_name]
28
+ end
29
+ alias_method :fqn, :fully_qualified_name
30
+
31
+ def same_fqn?(element)
32
+ if element.is_a?(Hash)
33
+ FQN_ATTR_STRS.all?{|attr|
34
+ jdbc_info[attr] == element[attr]
35
+ }
36
+ elsif element.is_a?(Array)
37
+ fully_qualified_name == element
38
+ elsif element.respond_to?(:fully_qualified_name)
39
+ fully_qualified_name == element.fully_qualified_name
40
+ else
41
+ raise ArgumentError, "Unsupported Object #{element.inspect}. Must be a Hash or a object which have 'fully_qualified_name' method."
42
+ end
43
+ end
44
+ end
45
+
46
+ class TableElement < MetaElement
47
+ attr_reader :table
48
+
49
+ def initialize(meta_data, table, *args, &block)
50
+ super(meta_data, *args, &block)
51
+ @table = table
52
+ end
53
+
54
+ def pretty_print_instance_variables
55
+ super - [:@table]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubeus/jdbc/meta_element'
3
+ module Rubeus::Jdbc
4
+ class PrimaryKey < TableElement
5
+ include FullyQualifiedNamed
6
+
7
+ # 1. TABLE_CAT String => テーブルカタログ (null の可能性がある)
8
+ # 2. TABLE_SCHEM String => テーブルスキーマ (null の可能性がある)
9
+ # 3. TABLE_NAME String => テーブル名
10
+ # 4. COLUMN_NAME String => 列名
11
+ # 5. KEY_SEQ short => 主キー中の連番
12
+ # 6. PK_NAME String => 主キー名 (null の可能性がある)
13
+ #
14
+ # see also:
15
+ # http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/sql/DatabaseMetaData.html#getPrimaryKeys(java.lang.String,%20java.lang.String,%20java.lang.String)
16
+
17
+ attr_accessor :column_name, :key_seq, :pk_name
18
+
19
+ alias_method :seq, :key_seq
20
+
21
+ def name
22
+ column_name.send(options[:name_case] || :to_s)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Rubeus::Jdbc
3
+ # ResultSetMetaDataから生成されます
4
+ class ResultSetColumn
5
+ ATTRIBUTES = [
6
+ :column_index , #
7
+ :catalog_name , # String # 指定された列のテーブルのカタログ名を取得します。
8
+ :column_class_name , # String # Java クラスの完全指定された名前を返します。
9
+ :column_display_size, # int # 指定された列の通常の最大幅を文字数で示します。
10
+ :column_label , # String # 印刷や表示に使用する、指定された列の推奨タイトルを取得します。
11
+ :column_name , # String # 指定された列の名前を取得します。
12
+ :column_type , # int # 指定された列の SQL 型を取得します。
13
+ :column_type_name , # String # 指定された列のデータベース固有の型名を取得します。
14
+ :precision , # int # 指定された列の 10 進桁数を取得します。
15
+ :scale , # int # 指定された列の小数点以下の桁数を取得します。
16
+ :schema_name , # String # 指定された列のテーブルのスキーマを取得します。
17
+ :table_name , # String # 指定された列のテーブル名を取得します。
18
+ :auto_increment , # boolean # 指定された列が自動的に番号付けされて読み取り専用として扱われるかどうかを示します。
19
+ :case_sensitive , # boolean # 列の大文字と小文字が区別されるかどうかを示します。
20
+ :currency , # boolean # 指定された列がキャッシュの値かどうかを示します。
21
+ :definitely_writable, # boolean # 指定された列の書き込みが必ず成功するかどうかを示します。
22
+ :is_nullable , # int # 指定された列に NULL をセットできるかどうかを示します。
23
+ :read_only , # boolean # 指定された列が絶対的に書き込み可能でないかどうかを示します。
24
+ :searchable , # boolean # 指定された列を where 節で使用できるかどうかを示します。
25
+ :signed , # boolean # 指定された列の値が符号付き数値かどうかを示します。
26
+ :writable # boolean # 指定された列への書き込みを成功させることができるかどうかを示します。
27
+ ]
28
+ attr_reader(*ATTRIBUTES)
29
+
30
+ alias_method :index , :column_index
31
+ alias_method :class_name , :column_class_name
32
+ alias_method :display_size, :column_display_size
33
+ alias_method :label , :column_label
34
+ alias_method :name , :column_name
35
+ alias_method :type_name , :column_type_name
36
+
37
+ alias_method :auto_increment? , :auto_increment
38
+ alias_method :case_sensitive? , :case_sensitive
39
+ alias_method :currency? , :currency
40
+ alias_method :definitely_writable?, :definitely_writable
41
+ # alias_method :nullable?
42
+ alias_method :read_only? , :read_only
43
+ alias_method :searchable? , :searchable
44
+ alias_method :signed? , :signed
45
+ alias_method :writable? , :writable
46
+
47
+ def initialize(index, attributes = {})
48
+ @index = index
49
+ attributes.each do |key, value|
50
+ instance_variable_set("@#{key.to_s}", value)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,207 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubeus/jdbc/meta_element'
3
+ require "rubeus/jdbc/column"
4
+ require "rubeus/jdbc/index"
5
+ require "rubeus/jdbc/primary_key"
6
+ require "rubeus/jdbc/foreign_key"
7
+ module Rubeus::Jdbc
8
+ class Table < MetaElement
9
+ include FullyQualifiedNamed
10
+
11
+ # 1. TABLE_CAT String => テーブルカタログ (null の可能性がある)
12
+ # 2. TABLE_SCHEM String => テーブルスキーマ (null の可能性がある)
13
+ # 3. TABLE_NAME String => テーブル名
14
+ # 4. TABLE_TYPE String => テーブルの型。典型的な型は、"TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS"、"SYNONYM" である
15
+ # 5. REMARKS String => テーブルに関する説明
16
+ # 6. TYPE_CAT String => の型のカタログ (null の可能性がある)
17
+ # 7. TYPE_SCHEM String => の型のスキーマ (null の可能性がある)
18
+ # 8. TYPE_NAME String => の型名 (null の可能性がある)
19
+ # 9. SELF_REFERENCING_COL_NAME String => 型付きテーブルの指定された「識別子」列の名前 (null の可能性がある)
20
+ # 10. REF_GENERATION String => SELF_REFERENCING_COL_NAME の値の作成方法を指定する。値は、"SYSTEM"、"USER"、"DERIVED" (null の可能性がある)
21
+ #
22
+ # see also:
23
+ # http://java.sun.com/javase/ja/6/docs/ja/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])
24
+ #
25
+ attr_accessor :table_type,
26
+ :remarks, :type_cat, :type_schem, :type_name,
27
+ :self_referencing_col_name, :ref_generation
28
+
29
+ attr_accessor :pluralize_table_name
30
+ attr_accessor :columns
31
+
32
+ def name
33
+ self.table_name.send(options[:name_case] || :to_s)
34
+ end
35
+
36
+ def [](column_name)
37
+ column_name = column_name.to_s.upcase
38
+ columns.detect{|col|col.column_name.upcase == column_name}
39
+ end
40
+
41
+ def primary_keys
42
+ unless @primary_keys
43
+ pkeys = meta_data.getPrimaryKeys(table_cat, table_schem, table_name).map{|r| r.to_hash}
44
+ @primary_keys = Rubeus::Util::NameAccessArray.new(
45
+ *pkeys.
46
+ select{|hash|self.same_fqn?(hash)}.
47
+ sort{|a,b| a['KEY_SEQ'] <=> b['KEY_SEQ']}.
48
+ map{|hash| Rubeus::Jdbc::PrimaryKey.new(meta_data, self, hash, options)})
49
+ end
50
+ @primary_keys
51
+ end
52
+ alias_method :pks, :primary_keys
53
+
54
+ def primary_key_names
55
+ primary_keys.map{|pk| pk.name}
56
+ end
57
+ alias_method :pk_names, :primary_key_names
58
+
59
+ def primary_key_columns
60
+ @primary_key_columns ||=
61
+ Rubeus::Util::NameAccessArray.new(*primary_keys.map{|pk| self.columns[pk.name]})
62
+ end
63
+ alias_method :pk_columns, :primary_key_columns
64
+
65
+ def self.singular_access_if_possible(method_name, plural_method)
66
+ define_method(method_name) do
67
+ values = self.send(plural_method)
68
+ (values.nil? || values.empty?) ? nil :
69
+ (values.length == 1) ? values.first : values
70
+ end
71
+ end
72
+
73
+ singular_access_if_possible(:pk, :pks)
74
+ singular_access_if_possible(:pk_name, :pk_names)
75
+ singular_access_if_possible(:pk_column, :pk_columns)
76
+ singular_access_if_possible(:primary_key, :primary_keys)
77
+ singular_access_if_possible(:primary_key_name, :primary_key_names)
78
+ singular_access_if_possible(:primary_key_column, :primary_key_columns)
79
+
80
+ def indexes
81
+ unless @indexes
82
+ @indexes = Rubeus::Util::NameAccessArray.new
83
+ index_infos = meta_data.getIndexInfo(table_cat, table_schem, table_name, false, true).map{|r| r.to_hash}
84
+ index_hash = {}
85
+ index_infos.each do |index_info|
86
+ index_uniq_key = Rubeus::Jdbc::Index::RECORD_UNIQUE_ATTRS.
87
+ map{|attr| attr.to_s}.map{|attr| attr.upcase}.map{|key| index_info[key]}
88
+ unless index_hash[index_uniq_key]
89
+ attrs = Rubeus::Jdbc::Index::ATTR_NAMES.map{|attr| attr.to_s}.
90
+ inject({}){|dest, name| dest[name.downcase] = index_info[name.upcase]; dest}
91
+ index = Rubeus::Jdbc::Index.new(meta_data, self, attrs, options)
92
+ @indexes << index
93
+ index_hash[index_uniq_key] = index
94
+ end
95
+ end
96
+ index_infos.each do |index_info|
97
+ index_uniq_key = Rubeus::Jdbc::Index::RECORD_UNIQUE_ATTRS.
98
+ map{|attr| attr.to_s}.map{|attr| attr.upcase}.map{|key| index_info[key]}
99
+ index = index_hash[index_uniq_key]
100
+ attrs = Rubeus::Jdbc::Index::Key::ATTR_NAMES.map{|attr| attr.to_s}.
101
+ inject({}){|dest, name| dest[name.downcase] = index_info[name.upcase]; dest}
102
+ index.keys << Rubeus::Jdbc::Index::Key.new(meta_data, index, attrs, options)
103
+ end
104
+ end
105
+ @indexes
106
+ end
107
+
108
+ IMPORTED_KEY_UNIQUE_ATTRS = %w(PKTABLE_CAT PKTABLE_SCHEM PKTABLE_NAME FK_NAME)
109
+
110
+ def imported_keys
111
+ unless @imported_keys
112
+ @imported_keys = Rubeus::Util::NameAccessArray.new
113
+ imported_key_hash = {}
114
+ imported_keys = meta_data.getImportedKeys(table_cat, table_schem, table_name).map{|r| r.to_hash}
115
+ imported_keys.each do |imported_key|
116
+ unique_key = IMPORTED_KEY_UNIQUE_ATTRS.map{|attr| imported_key[attr]}
117
+ unless imported_key_hash[unique_key]
118
+ attrs = Rubeus::Jdbc::ForeignKey::ATTR_NAMES.map{|attr| attr.to_s}.
119
+ inject({}){|dest, name| dest[name.downcase] = imported_key[name.upcase]; dest}
120
+ foreign_key = Rubeus::Jdbc::ForeignKey.new(meta_data, self, attrs, options)
121
+ foreign_key.fktable = self
122
+ foreign_key.pktable = meta_data.table_object(imported_key['PKTABLE_NAME'],
123
+ :catalog => imported_key['PKTABLE_CAT'], :schema => imported_key['PKTABLE_SCHEM'])
124
+ @imported_keys << foreign_key
125
+ imported_key_hash[unique_key] = foreign_key
126
+ end
127
+ end
128
+ imported_keys.each do |imported_key|
129
+ unique_key = IMPORTED_KEY_UNIQUE_ATTRS.map{|attr| imported_key[attr]}
130
+ foreign_key = imported_key_hash[unique_key]
131
+ foreign_key.fkcolumn_names ||= []
132
+ foreign_key.pkcolumn_names ||= []
133
+ foreign_key.fkcolumn_names << imported_key['FKCOLUMN_NAME'].send(options[:name_case] || :to_s)
134
+ foreign_key.pkcolumn_names << imported_key['PKCOLUMN_NAME'].send(options[:name_case] || :to_s)
135
+ end
136
+ end
137
+ @imported_keys
138
+ end
139
+
140
+ EXPORTED_KEY_UNIQUE_ATTRS = %w(FKTABLE_CAT FKTABLE_SCHEM FKTABLE_NAME PK_NAME)
141
+
142
+ def exported_keys
143
+ unless @exported_keys
144
+ @exported_keys = Rubeus::Util::NameAccessArray.new
145
+ exported_key_hash = {}
146
+ exported_keys = meta_data.getExportedKeys(table_cat, table_schem, table_name).map{|r| r.to_hash}
147
+ exported_keys.each do |exported_key|
148
+ unique_key = EXPORTED_KEY_UNIQUE_ATTRS.map{|attr| exported_key[attr]}
149
+ unless exported_key_hash[unique_key]
150
+ attrs = Rubeus::Jdbc::ForeignKey::ATTR_NAMES.map{|attr| attr.to_s}.
151
+ inject({}){|dest, name| dest[name.downcase] = exported_key[name.upcase]; dest}
152
+ foreign_key = Rubeus::Jdbc::ForeignKey.new(meta_data, self, attrs, options)
153
+ foreign_key.fktable = meta_data.table_object(exported_key['FKTABLE_NAME'],
154
+ :catalog => exported_key['FKTABLE_CAT'], :schema => exported_key['FKTABLE_SCHEM'])
155
+ foreign_key.pktable = self
156
+ @exported_keys << foreign_key
157
+ exported_key_hash[unique_key] = foreign_key
158
+ end
159
+ end
160
+ exported_keys.each do |exported_key|
161
+ unique_key = EXPORTED_KEY_UNIQUE_ATTRS.map{|attr| exported_key[attr]}
162
+ foreign_key = exported_key_hash[unique_key]
163
+ foreign_key.fkcolumn_names ||= []
164
+ foreign_key.pkcolumn_names ||= []
165
+ foreign_key.fkcolumn_names << exported_key['FKCOLUMN_NAME'].send(options[:name_case] || :to_s)
166
+ foreign_key.pkcolumn_names << exported_key['PKCOLUMN_NAME'].send(options[:name_case] || :to_s)
167
+ end
168
+ end
169
+ @exported_keys
170
+ end
171
+
172
+
173
+
174
+ def rails_table_name
175
+ unless @rails_table_name
176
+ @rails_table_name = table_name.downcase
177
+ @rails_table_name = @rails_table_name.pluralize if pluralize_table_name
178
+ end
179
+ @rails_table_name
180
+ end
181
+
182
+ def rails_table_name=(value)
183
+ @rails_table_name = value
184
+ end
185
+ attr_accessor :rails_options
186
+
187
+ def define_rails_model(mod)
188
+ class_name = "Rails#{rails_table_name.classify}"
189
+ class_def = "class #{class_name} < ActiveRecord::Base\n"
190
+ class_def << " set_table_name('#{rails_table_name}')\n"
191
+ class_def << "end"
192
+ mod.module_eval(class_def)
193
+ mod.const_get(class_name)
194
+ end
195
+
196
+ def define_jdbc_model(mod)
197
+ class_name = "Jdbc#{table_name.classify}"
198
+ class_def = "class #{class_name} < ActiveRecord::Base\n"
199
+ class_def << " set_table_name('#{table_name}')\n"
200
+ class_def << " establish_connection('#{meta_data.source_db}')\n"
201
+ class_def << "end"
202
+ mod.module_eval(class_def)
203
+ mod.const_get(class_name)
204
+ end
205
+
206
+ end
207
+ end
@@ -0,0 +1,5 @@
1
+ module Rubeus
2
+ module Util
3
+ autoload :NameAccessArray, 'rubeus/util/name_access_array'
4
+ end
5
+ end
@@ -0,0 +1,34 @@
1
+ module Rubeus::Util
2
+ class NameAccessArray < Array
3
+ def initialize(*args)
4
+ options = args.last.is_a?(Hash) ? args.pop : {}
5
+ options = {
6
+ :name_attr => :name,
7
+ :detect_with => :to_s
8
+ }.update(options)
9
+ @name_attr = options[:name_attr]
10
+ @detect_with = options[:detect_with]
11
+ args.each{|arg| push(arg)}
12
+ end
13
+
14
+ def by_name(name)
15
+ return nil unless name
16
+ detect_name = name.send(@detect_with)
17
+ detect do |item|
18
+ next unless item
19
+ ite_name = item.send(@name_attr)
20
+ next unless ite_name
21
+ ite_name.send(@detect_with) == detect_name
22
+ end
23
+ end
24
+
25
+ def [](*args)
26
+ if args.length == 1
27
+ if (args.first.is_a?(Symbol) || args.first.is_a?(String))
28
+ return by_name(args.first)
29
+ end
30
+ end
31
+ return super
32
+ end
33
+ end
34
+ end
@@ -1,12 +1,14 @@
1
1
  require 'test/unit'
2
2
  require 'rubygems'
3
3
  require 'rubeus'
4
+ require 'test/rubeus/extensions/java/sql/test_sql_helper'
4
5
 
5
6
  # Test for connetion.rb
6
7
  class TestConnection < Test::Unit::TestCase
7
- # setup method
8
+ include TestSqlHelper
9
+
8
10
  def setup
9
- @con = Rubeus::Jdbc::DriverManager.connect("jdbc:derby:test_db;create = true", "", "")
11
+ setup_connection
10
12
  end
11
13
 
12
14
  def test_statement
@@ -17,17 +19,8 @@ class TestConnection < Test::Unit::TestCase
17
19
  end
18
20
 
19
21
  def test_query
20
- # Drop test table
21
- begin
22
- @con.statement do |stmt|
23
- stmt.execute_update("DROP TABLE TEST")
24
- end
25
- rescue
26
- # table test is already exist
27
- end
28
-
29
22
  @con.statement do |stmt|
30
- stmt.execute_update("CREATE TABLE TEST (ID INT, NAME CHAR(10))")
23
+ create_table_after_drop("CREATE TABLE TEST (ID INT, NAME CHAR(10))", stmt)
31
24
  stmt.execute_update("INSERT INTO TEST VALUES(1, 'row1')")
32
25
  stmt.execute_update("INSERT INTO TEST VALUES(2, 'row2')")
33
26
  end
@@ -37,14 +30,13 @@ class TestConnection < Test::Unit::TestCase
37
30
  rs.each_hash do |rsNext|
38
31
  assert_equal(i, rsNext["ID"])
39
32
  assert_equal("row#{i} ", rsNext["NAME"])
40
-
41
33
  i += 1
42
34
  end
43
35
  end
44
36
  end
45
37
 
46
38
  def teardown
47
- @con.close
39
+ teardown_connection
48
40
  end
49
41
  end
50
42
 
@@ -0,0 +1,257 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'rubeus'
4
+ require 'test/rubeus/extensions/java/sql/test_sql_helper'
5
+
6
+ # Test for lib/rubeus/extensions/java/sql/database_meta_data.rb
7
+ class TestDatabaseMetaData < Test::Unit::TestCase
8
+ include TestSqlHelper
9
+
10
+ def setup
11
+ setup_connection
12
+ @con.statement do |stmt|
13
+ drop_table_if_exist("TEST", stmt)
14
+ # DDL from http://db.apache.org/derby/docs/dev/ja_JP/ref/rrefsqlj13590.html
15
+ # Index from http://db.apache.org/derby/docs/dev/ja_JP/ref/rrefsqlj20937.html
16
+ create_table_after_drop(<<-"EOS", stmt)
17
+ CREATE TABLE FLIGHTS(
18
+ FLIGHT_ID CHAR(6) NOT NULL ,
19
+ SEGMENT_NUMBER INTEGER NOT NULL ,
20
+ ORIG_AIRPORT CHAR(3),
21
+ DEPART_TIME TIME,
22
+ DEST_AIRPORT CHAR(3),
23
+ ARRIVE_TIME TIME,
24
+ MEAL CHAR(1) CONSTRAINT MEAL_CONSTRAINT
25
+ CHECK (MEAL IN ('B', 'L', 'D', 'S')),
26
+ PRIMARY KEY (FLIGHT_ID, SEGMENT_NUMBER)
27
+ );
28
+ CREATE TABLE FLTAVAIL(
29
+ FLIGHT_ID CHAR(6) NOT NULL,
30
+ SEGMENT_NUMBER INT NOT NULL,
31
+ FLIGHT_DATE DATE NOT NULL,
32
+ ECONOMY_SEATS_TAKEN INT,
33
+ BUSINESS_SEATS_TAKEN INT,
34
+ FIRSTCLASS_SEATS_TAKEN INT,
35
+ CONSTRAINT FLTAVAIL_PK PRIMARY KEY (FLIGHT_ID, SEGMENT_NUMBER),
36
+ CONSTRAINT FLTS_FK
37
+ FOREIGN KEY (FLIGHT_ID, SEGMENT_NUMBER)
38
+ REFERENCES Flights (FLIGHT_ID, SEGMENT_NUMBER)
39
+ );
40
+ EOS
41
+ stmt.execute_update('CREATE INDEX IDX_FLIGHT_01 ON Flights(orig_airport)')
42
+ stmt.execute_update('CREATE INDEX IDX_FLIGHT_02 ON Flights(orig_airport, DEPART_TIME desc)')
43
+ stmt.execute_update('CREATE INDEX IDX_FLIGHT_03 ON Flights(DEST_AIRPORT, ARRIVE_TIME desc)')
44
+ create_table_after_drop(<<-"EOS", stmt)
45
+ CREATE TABLE CITIES(
46
+ ID INT NOT NULL CONSTRAINT CITIES_PK PRIMARY KEY,
47
+ CITY_NAME VARCHAR(50)
48
+ );
49
+ CREATE TABLE METROPOLITAN(
50
+ HOTEL_ID INT NOT NULL CONSTRAINT HOTELS_PK PRIMARY KEY,
51
+ HOTEL_NAME VARCHAR(40) NOT NULL,
52
+ CITY_ID INT CONSTRAINT METRO_FK REFERENCES CITIES
53
+ );
54
+ EOS
55
+ stmt.execute_update('CREATE UNIQUE INDEX IDX_CITIES_01 ON CITIES(CITY_NAME)')
56
+ stmt.execute_update('CREATE UNIQUE INDEX IDX_METROPOLITAN_01 ON METROPOLITAN(CITY_ID, HOTEL_NAME)')
57
+ create_table_after_drop(<<-"EOS", stmt)
58
+ CREATE TABLE TEST1(
59
+ ID INT NOT NULL,
60
+ NAME VARCHAR(60)
61
+ );
62
+ EOS
63
+ end
64
+ end
65
+
66
+ def teardown
67
+ teardown_connection
68
+ end
69
+
70
+ def test_table_objects
71
+ tables = @con.meta_data.tables(:schema => "APP", :name_case => :downcase)
72
+ assert_equal 5, tables.length
73
+ assert_equal ['cities', 'flights', 'fltavail', 'metropolitan', 'test1'], tables.map{|t|t.name}.sort
74
+ assert_not_nil tables['flights']
75
+ assert_not_nil tables['fltavail']
76
+ assert_not_nil tables['cities']
77
+ assert_not_nil tables['metropolitan']
78
+ assert_not_nil tables['test1']
79
+ rescue => e
80
+ puts e.to_s
81
+ puts e.backtrace.join("\n ")
82
+ raise e
83
+ end
84
+
85
+ def assert_column(table, name, type, size, nullable)
86
+ column = table.columns[name]
87
+ assert_not_nil column, "column '#{name}' not found"
88
+ assert_equal(java.sql.Types.const_get(type.to_s.upcase), column.data_type,
89
+ "column '#{name}' type expected #{java.sql.Types.const_get(type.to_s.upcase).inspect} but #{column.data_type.inspect}")
90
+ assert_equal(size, column.size,
91
+ "column '#{name}' size expected #{size.inspect} but #{column.size.inspect}")
92
+ assert_equal(nullable, column.nullable?,
93
+ "column '#{name}' nullable expected #{nullable.inspect} but #{column.nullable?.inspect}")
94
+ assert_equal(nullable ?
95
+ java.sql.DatabaseMetaData.columnNullable :
96
+ java.sql.DatabaseMetaData.columnNoNulls, column.nullable)
97
+ assert_equal column, table[name]
98
+ end
99
+
100
+ def test_table_object_columns
101
+ tables = @con.meta_data.tables(:schema => "APP", :name_case => :downcase)
102
+ #
103
+ assert_not_nil flights = tables['flights']
104
+ assert_equal 7, flights.columns.length
105
+ assert_column(flights, 'flight_id', :char, 6, false)
106
+ assert_column(flights, 'segment_number', :integer, 10, false)
107
+ assert_column(flights, 'orig_airport', :char, 3, true)
108
+ assert_column(flights, 'depart_time', :time, 8, true)
109
+ assert_column(flights, 'dest_airport', :char, 3, true)
110
+ assert_column(flights, 'arrive_time', :time, 8, true)
111
+ assert_column(flights, 'meal', :char, 1, true)
112
+ #
113
+ assert_not_nil fltavail = tables['fltavail']
114
+ assert_equal 6, fltavail.columns.length
115
+ assert_column(fltavail, 'flight_id', :char, 6, false)
116
+ assert_column(fltavail, 'segment_number', :integer, 10, false)
117
+ assert_column(fltavail, 'flight_date', :date, 10, false)
118
+ assert_column(fltavail, 'economy_seats_taken', :integer, 10, true)
119
+ assert_column(fltavail, 'business_seats_taken', :integer, 10, true)
120
+ assert_column(fltavail, 'firstclass_seats_taken', :integer, 10, true)
121
+ #
122
+ assert_not_nil ctiies = tables['cities']
123
+ assert_equal 2, ctiies.columns.length
124
+ assert_column(ctiies, 'id', :integer, 10, false)
125
+ assert_column(ctiies, 'city_name', :varchar, 50, true)
126
+ #
127
+ assert_not_nil metropolitan = tables['metropolitan']
128
+ assert_equal 3, metropolitan.columns.length
129
+ assert_column(metropolitan, 'hotel_id', :integer, 10, false)
130
+ assert_column(metropolitan, 'hotel_name', :varchar, 40, false)
131
+ assert_column(metropolitan, 'city_id', :integer, 10, true)
132
+ #
133
+ assert_not_nil test1 = tables['test1']
134
+ assert_equal 2, test1.columns.length
135
+ assert_column(test1, 'id', :integer, 10, false)
136
+ assert_column(test1, 'name', :varchar, 60, true)
137
+ rescue => e
138
+ puts e.to_s
139
+ puts e.backtrace.join("\n ")
140
+ raise e
141
+ end
142
+
143
+ def assert_pk(table, names)
144
+ assert_equal names.length, table.primary_keys.length
145
+ assert_equal names, table.pks.map{|k| k.name}
146
+ assert_equal names, table.primary_keys.map{|k| k.name}
147
+ assert_equal names, table.pk_names
148
+ assert_equal names, table.primary_key_names
149
+ names.each_with_index do |name, index|
150
+ assert_equal name, table.primary_keys[name].name
151
+ assert_equal index + 1, table.primary_keys[name].seq
152
+ assert_equal table.columns[name], table.primary_key_columns[name]
153
+ assert_equal table.columns[name], table.pk_columns[name]
154
+ end
155
+ case names.length
156
+ when 0
157
+ assert_equal nil, table.pk
158
+ assert_equal nil, table.primary_key
159
+ assert_equal nil, table.pk_name
160
+ assert_equal nil, table.primary_key_name
161
+ assert_equal nil, table.pk_column
162
+ assert_equal nil, table.primary_key_column
163
+ when 1
164
+ assert_equal table.pks.first, table.pk
165
+ assert_equal table.pks.first, table.primary_key
166
+ assert_equal table.pk_names.first, table.pk_name
167
+ assert_equal table.pk_names.first, table.primary_key_name
168
+ assert_equal table.pk_columns.first, table.pk_column
169
+ assert_equal table.pk_columns.first, table.primary_key_column
170
+ else
171
+ assert_equal table.pks, table.pk
172
+ assert_equal table.pks, table.primary_key
173
+ assert_equal table.pk_names, table.pk_name
174
+ assert_equal table.pk_names, table.primary_key_name
175
+ assert_equal table.pk_columns, table.pk_column
176
+ assert_equal table.pk_columns, table.primary_key_column
177
+ end
178
+ table.columns.each do |column|
179
+ if table.pk_names.include?(column.name)
180
+ assert_equal true, column.primary_key?, "#{table.name}.#{column.name} shoud be one of pk"
181
+ assert_equal true, column.pk?, "#{table.name}.#{column.name} shoud be one of pk"
182
+ else
183
+ assert_equal false, column.primary_key?, "#{table.name}.#{column.name} shoud not be one of pk"
184
+ assert_equal false, column.pk?, "#{table.name}.#{column.name} shoud not be one of pk"
185
+ end
186
+ end
187
+ end
188
+
189
+ def test_table_objects_pk
190
+ tables = @con.meta_data.tables(:schema => "APP", :name_case => :downcase)
191
+ assert_pk(tables['flights'], %w(flight_id segment_number))
192
+ assert_pk(tables['fltavail'], %w(flight_id segment_number))
193
+ assert_pk(tables['cities'], %w(id))
194
+ assert_pk(tables['metropolitan'], %w(hotel_id))
195
+ assert_pk(tables['test1'], [])
196
+ end
197
+
198
+ def assert_index(table, index_name, key_names, asc_descs)
199
+ assert_equal key_names, table.indexes[index_name].keys.map{|k| k.name}
200
+ assert_equal asc_descs, table.indexes[index_name].keys.map{|k| k.asc?}
201
+ end
202
+
203
+ def test_table_objects_index
204
+ tables = @con.meta_data.tables(:schema => "APP", :name_case => :downcase)
205
+ # assert_equal %w(idx_flight_01 idx_flight_02 idx_flight_03), tables['flights'].indexes.map{|idx| idx.name}
206
+ # assert_equal 3, tables['flights'].indexes.length
207
+ assert_index(tables['flights'], 'idx_flight_01', %w(orig_airport), [true])
208
+ assert_index(tables['flights'], 'idx_flight_02', %w(orig_airport depart_time), [true, false])
209
+ assert_index(tables['flights'], 'idx_flight_03', %w(dest_airport arrive_time), [true, false])
210
+ # assert_equal 0, tables['fltavail'].indexes.length
211
+
212
+ # assert_equal 1, tables['cities'].indexes.length
213
+ assert_index(tables['cities'], 'idx_cities_01', %w(city_name), [true])
214
+ # assert_equal 1, tables['metropolitan'].indexes.length
215
+ assert_index(tables['metropolitan'], 'idx_metropolitan_01', %w(city_id hotel_name), [true, true])
216
+
217
+ # assert_equal 0, tables['test1'].indexes.length
218
+ end
219
+
220
+ def assert_fk(fk_name, pktable, pkcolumn_names, fktable, fkcolumn_names)
221
+ imported_key = fktable.imported_keys[fk_name]
222
+ exported_key = pktable.exported_keys[fk_name]
223
+ assert_equal fk_name, imported_key.name
224
+ assert_equal fk_name, exported_key.name
225
+
226
+ assert_equal pktable.name, imported_key.pktable.name
227
+ assert_equal fktable.name, imported_key.fktable.name
228
+ assert_equal pktable.name, exported_key.pktable.name
229
+ assert_equal fktable.name, exported_key.fktable.name
230
+
231
+ assert_equal pkcolumn_names.length, imported_key.length
232
+ assert_equal fkcolumn_names.length, exported_key.length
233
+ assert_equal imported_key.length, exported_key.length
234
+
235
+ pkcolumn_names.each_with_index do |column_name, index|
236
+ [imported_key, exported_key].each do |key|
237
+ assert_equal pkcolumn_names[index], key.pkcolumn_names[index]
238
+ assert_equal pkcolumn_names[index], key.pkcolumns[index].name
239
+ assert_equal pktable, key.pkcolumns[index].table
240
+ assert_equal fkcolumn_names[index], key.fkcolumn_names[index]
241
+ assert_equal fkcolumn_names[index], key.fkcolumns[index].name
242
+ assert_equal fktable, key.fkcolumns[index].table
243
+ end
244
+ end
245
+ end
246
+
247
+ def test_table_objects_imported_keys_and_exported_keys
248
+ tables = @con.meta_data.tables(:schema => "APP", :name_case => :downcase)
249
+ assert_fk('flts_fk',
250
+ tables['flights'], %w(flight_id segment_number),
251
+ tables['fltavail'], %w(flight_id segment_number))
252
+ assert_fk('metro_fk',
253
+ tables['cities'], %w(id),
254
+ tables['metropolitan'], %w(city_id))
255
+ end
256
+
257
+ end