rubeus 0.0.7-java → 0.0.8-java
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rubeus.rb +2 -1
- data/lib/rubeus/awt/setters.rb +10 -13
- data/lib/rubeus/extensions/java/sql/connection.rb +6 -1
- data/lib/rubeus/extensions/java/sql/database_meta_data.rb +63 -0
- data/lib/rubeus/extensions/java/sql/result_set_meta_data.rb +2 -2
- data/lib/rubeus/extensions/javax/swing/j_component.rb +7 -8
- data/lib/rubeus/extensions/javax/swing/j_frame.rb +5 -6
- data/lib/rubeus/jdbc.rb +11 -5
- data/lib/rubeus/jdbc/column.rb +81 -48
- data/lib/rubeus/jdbc/foreign_key.rb +66 -0
- data/lib/rubeus/jdbc/index.rb +68 -0
- data/lib/rubeus/jdbc/meta_element.rb +58 -0
- data/lib/rubeus/jdbc/primary_key.rb +25 -0
- data/lib/rubeus/jdbc/result_set_column.rb +54 -0
- data/lib/rubeus/jdbc/table.rb +207 -0
- data/lib/rubeus/util.rb +5 -0
- data/lib/rubeus/util/name_access_array.rb +34 -0
- data/test/rubeus/extensions/java/sql/test_connection.rb +6 -14
- data/test/rubeus/extensions/java/sql/test_database_meta_data.rb +257 -0
- data/test/rubeus/extensions/java/sql/test_result_set.rb +6 -18
- data/test/rubeus/extensions/java/sql/test_result_set_meta_data.rb +6 -16
- data/test/rubeus/extensions/java/sql/test_sql_helper.rb +43 -0
- data/test/rubeus/extensions/java/sql/test_statement.rb +5 -3
- metadata +141 -128
@@ -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
|
data/lib/rubeus/util.rb
ADDED
@@ -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
|
-
|
8
|
+
include TestSqlHelper
|
9
|
+
|
8
10
|
def setup
|
9
|
-
|
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
|
-
|
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
|
-
|
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
|