activerecord-jdbcteradata-adapter 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +4 -4
- data/activerecord-jdbcteradata-adapter.gemspec +3 -2
- data/lib/arel/visitors/teradata.rb +17 -18
- data/lib/arjdbc/teradata/adapter.rb +63 -13
- data/lib/arjdbc/teradata/connection_methods.rb +37 -11
- data/lib/arjdbc/teradata/explain_support.rb +15 -0
- data/lib/arjdbc/teradata/teradata_java.jar +0 -0
- data/spec/adapter_spec.rb +37 -0
- data/spec/associations_spec.rb +9 -8
- data/spec/commons-dbcp-1.4.jar +0 -0
- data/spec/commons-pool-1.6.jar +0 -0
- data/spec/connection_spec.rb +40 -0
- data/spec/fixtures/wikimedia-commons-poty-2006.jpg +0 -0
- data/spec/models/model_with_blob.rb +17 -0
- data/spec/spec_helper.rb +9 -1
- metadata +15 -6
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activerecord-jdbcteradata-adapter (0.4.
|
5
|
-
activerecord
|
4
|
+
activerecord-jdbcteradata-adapter (0.4.2)
|
5
|
+
activerecord (<= 3.2.13)
|
6
6
|
activerecord-jdbc-adapter
|
7
7
|
jdbc-teradata
|
8
8
|
|
@@ -17,7 +17,7 @@ GEM
|
|
17
17
|
activesupport (= 3.2.13)
|
18
18
|
arel (~> 3.0.2)
|
19
19
|
tzinfo (~> 0.3.29)
|
20
|
-
activerecord-jdbc-adapter (1.2.9)
|
20
|
+
activerecord-jdbc-adapter (1.2.9.1)
|
21
21
|
activesupport (3.2.13)
|
22
22
|
i18n (= 0.6.1)
|
23
23
|
multi_json (~> 1.0)
|
@@ -26,7 +26,7 @@ GEM
|
|
26
26
|
diff-lcs (1.2.4)
|
27
27
|
i18n (0.6.1)
|
28
28
|
jdbc-teradata (0.3.0)
|
29
|
-
multi_json (1.7.
|
29
|
+
multi_json (1.7.7)
|
30
30
|
rake (10.0.4)
|
31
31
|
rspec (2.13.0)
|
32
32
|
rspec-core (~> 2.13.0)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'activerecord-jdbcteradata-adapter'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.5.0'
|
4
4
|
s.authors = ['Chris Parker']
|
5
5
|
s.email = %w(mrcsparker@gmail.com)
|
6
6
|
s.homepage = 'https://github.com/mrcsparker/activerecord-jdbcteradata-adapter'
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
lib/arjdbc/teradata/adapter.rb
|
25
25
|
lib/arjdbc/teradata/connection_methods.rb
|
26
26
|
lib/arjdbc/teradata/teradata_java.jar
|
27
|
+
lib/arjdbc/teradata/explain_support.rb
|
27
28
|
lib/arjdbc/teradata.rb
|
28
29
|
]
|
29
30
|
|
@@ -34,6 +35,6 @@ Gem::Specification.new do |s|
|
|
34
35
|
s.add_development_dependency 'rake'
|
35
36
|
s.add_development_dependency 'rspec'
|
36
37
|
s.add_dependency 'activerecord-jdbc-adapter'
|
37
|
-
s.add_dependency 'activerecord'
|
38
|
+
s.add_dependency 'activerecord', '<= 3.2.13'
|
38
39
|
s.add_dependency 'jdbc-teradata'
|
39
40
|
end
|
@@ -23,9 +23,9 @@ module Arel
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class SelectManager < Arel::TreeManager
|
26
|
-
|
26
|
+
|
27
27
|
AR_CA_SQLSA_NAME = 'Teradata'.freeze
|
28
|
-
|
28
|
+
|
29
29
|
# Getting real Ordering objects is very important for us. We need to be able to call #uniq on
|
30
30
|
# a colleciton of them reliably as well as using their true object attributes to mutate them
|
31
31
|
# to grouping objects for the inner sql during a select statment with an offset/rownumber. So this
|
@@ -76,13 +76,13 @@ module Arel
|
|
76
76
|
lock_without_teradata(locking)
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
private
|
81
|
-
|
81
|
+
|
82
82
|
def engine_activerecord_teradata_adapter?
|
83
83
|
@engine.connection && @engine.connection.adapter_name == AR_CA_SQLSA_NAME
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
end
|
87
87
|
|
88
88
|
module Visitors
|
@@ -101,7 +101,7 @@ module Arel
|
|
101
101
|
visit_Arel_Nodes_SelectStatementWithOutOffset(o)
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def visit_Arel_Nodes_UpdateStatement(o)
|
106
106
|
if o.orders.any? && o.limit.nil?
|
107
107
|
o.limit = Nodes::Limit.new(214748364)
|
@@ -120,7 +120,7 @@ module Arel
|
|
120
120
|
def visit_Arel_Nodes_Lock(o)
|
121
121
|
visit o.expr
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
def visit_Arel_Nodes_Ordering(o)
|
125
125
|
if o.respond_to?(:direction)
|
126
126
|
"#{visit o.expr} #{o.ascending? ? 'ASC' : 'DESC'}"
|
@@ -128,7 +128,7 @@ module Arel
|
|
128
128
|
visit o.expr
|
129
129
|
end
|
130
130
|
end
|
131
|
-
|
131
|
+
|
132
132
|
def visit_Arel_Nodes_Bin(o)
|
133
133
|
"#{visit o.expr} #{@connection.cs_equality_operator}"
|
134
134
|
end
|
@@ -203,7 +203,6 @@ module Arel
|
|
203
203
|
].compact.join ' '
|
204
204
|
end
|
205
205
|
|
206
|
-
|
207
206
|
# Teradata Helpers
|
208
207
|
|
209
208
|
def source_with_lock_for_select_statement(o)
|
@@ -248,18 +247,18 @@ module Arel
|
|
248
247
|
((p1.respond_to?(:distinct) && p1.distinct) ||
|
249
248
|
p1.respond_to?(:include?) && p1.include?('DISTINCT'))
|
250
249
|
end
|
251
|
-
|
250
|
+
|
252
251
|
def windowed_single_distinct_select_statement?(o)
|
253
252
|
o.limit && o.offset && single_distinct_select_statement?(o)
|
254
253
|
end
|
255
|
-
|
254
|
+
|
256
255
|
def single_distinct_select_everything_statement?(o)
|
257
256
|
single_distinct_select_statement?(o) && visit(o.cores.first.projections.first).ends_with?('.*')
|
258
257
|
end
|
259
|
-
|
258
|
+
|
260
259
|
def top_one_everything_for_through_join?(o)
|
261
|
-
single_distinct_select_everything_statement?(o) &&
|
262
|
-
(o.limit && !o.offset) &&
|
260
|
+
single_distinct_select_everything_statement?(o) &&
|
261
|
+
(o.limit && !o.offset) &&
|
263
262
|
join_in_select_statement?(o)
|
264
263
|
end
|
265
264
|
|
@@ -277,9 +276,9 @@ module Arel
|
|
277
276
|
|
278
277
|
def eager_limiting_select_statement?(o)
|
279
278
|
core = o.cores.first
|
280
|
-
single_distinct_select_statement?(o) &&
|
281
|
-
(o.limit && !o.offset) &&
|
282
|
-
core.groups.empty? &&
|
279
|
+
single_distinct_select_statement?(o) &&
|
280
|
+
(o.limit && !o.offset) &&
|
281
|
+
core.groups.empty? &&
|
283
282
|
!single_distinct_select_everything_statement?(o)
|
284
283
|
end
|
285
284
|
|
@@ -295,7 +294,7 @@ module Arel
|
|
295
294
|
o.limit &&
|
296
295
|
!join_in_select_statement?(o)
|
297
296
|
end
|
298
|
-
|
297
|
+
|
299
298
|
def select_primary_key_sql?(o)
|
300
299
|
core = o.cores.first
|
301
300
|
return false if core.projections.size != 1
|
@@ -1,8 +1,32 @@
|
|
1
1
|
require 'arjdbc/mssql/limit_helpers'
|
2
|
+
require 'arjdbc/teradata/explain_support'
|
2
3
|
|
3
4
|
module ::ArJdbc
|
4
5
|
module Teradata
|
5
6
|
|
7
|
+
require 'arjdbc/jdbc/serialized_attributes_helper'
|
8
|
+
ActiveRecord::Base.class_eval do
|
9
|
+
def after_save_with_teradata_lob
|
10
|
+
lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/i }
|
11
|
+
lob_columns.each do |column|
|
12
|
+
value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
|
13
|
+
next if value.nil? # already set NULL
|
14
|
+
self.class.connection.write_large_object(
|
15
|
+
column.type == :binary, column.name,
|
16
|
+
self.class.table_name,
|
17
|
+
self.class.primary_key,
|
18
|
+
self.class.connection.quote(id), value
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#Used to add after_save lob saving method to ActiveRecord when
|
25
|
+
#this adapter is used.
|
26
|
+
def self.included(base)
|
27
|
+
ActiveRecord::Base.after_save :after_save_with_teradata_lob
|
28
|
+
end
|
29
|
+
|
6
30
|
def self.column_selector
|
7
31
|
[ /teradata/i, lambda { |cfg, column| column.extend(::ArJdbc::Teradata::Column) } ]
|
8
32
|
end
|
@@ -70,6 +94,7 @@ module ::ArJdbc
|
|
70
94
|
:time => { :name => 'TIMESTAMP'},
|
71
95
|
:date => { :name => 'DATE'},
|
72
96
|
:binary => { :name => 'BLOB'},
|
97
|
+
:text => { :name => 'CLOB'},
|
73
98
|
:boolean => { :name => 'BYTEINT'},
|
74
99
|
:raw => { :name => 'BYTE'}
|
75
100
|
}
|
@@ -89,8 +114,6 @@ module ::ArJdbc
|
|
89
114
|
|
90
115
|
#- disconnect!
|
91
116
|
|
92
|
-
#- jdbc_columns
|
93
|
-
|
94
117
|
#- exec_query
|
95
118
|
|
96
119
|
#- exec_insert
|
@@ -136,9 +159,9 @@ module ::ArJdbc
|
|
136
159
|
|
137
160
|
#- select
|
138
161
|
def select(sql, *rest)
|
139
|
-
|
140
|
-
|
141
|
-
|
162
|
+
# TJC - Teradata does not like "= NULL", "!= NULL", or "<> NULL".
|
163
|
+
# TJC - Also does not like != so transforming that to <>
|
164
|
+
execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL").gsub("!=","<>"), *rest)
|
142
165
|
end
|
143
166
|
|
144
167
|
#- select_rows
|
@@ -175,7 +198,7 @@ module ::ArJdbc
|
|
175
198
|
|
176
199
|
schema = database_name unless schema
|
177
200
|
|
178
|
-
output = execute("SELECT count(*) as table_count FROM dbc.tables WHERE TableName = '#{table}' AND DatabaseName = '#{schema}'")
|
201
|
+
output = execute("SELECT count(*) as table_count FROM dbc.tables WHERE TableName (NOT CS) = '#{table}' (NOT CS) AND DatabaseName (NOT CS) = '#{schema}' (NOT CS) ")
|
179
202
|
output.first['table_count'].to_i > 0
|
180
203
|
end
|
181
204
|
|
@@ -189,10 +212,10 @@ module ::ArJdbc
|
|
189
212
|
|
190
213
|
schema = database_name unless schema
|
191
214
|
|
192
|
-
result = select_rows(
|
193
|
-
|
194
|
-
|
195
|
-
"
|
215
|
+
result = select_rows("SELECT DatabaseName, TableName, ColumnName, IndexType, IndexName, UniqueFlag" <<
|
216
|
+
" FROM DBC.Indices" <<
|
217
|
+
" WHERE TableName (NOT CS) = '#{table}' (NOT CS)" <<
|
218
|
+
" AND DatabaseName (NOT CS) = '#{schema}' (NOT CS)")
|
196
219
|
|
197
220
|
result.map do |row|
|
198
221
|
idx_table_name = row[1].to_s.strip
|
@@ -224,6 +247,15 @@ module ::ArJdbc
|
|
224
247
|
#- primary_key
|
225
248
|
|
226
249
|
#- primary_keys
|
250
|
+
def primary_keys(table)
|
251
|
+
if self.class.lowercase_schema_reflection
|
252
|
+
@connection.primary_keys(table).map do |key|
|
253
|
+
key.downcase
|
254
|
+
end
|
255
|
+
else
|
256
|
+
@connection.primary_keys(table)
|
257
|
+
end
|
258
|
+
end
|
227
259
|
|
228
260
|
#- to_sql
|
229
261
|
|
@@ -238,9 +270,7 @@ module ::ArJdbc
|
|
238
270
|
return false unless table_name
|
239
271
|
schema, table = extract_schema_and_table(table_name.to_s)
|
240
272
|
return false unless table
|
241
|
-
|
242
273
|
schema = database_name unless schema
|
243
|
-
|
244
274
|
@connection.columns_internal(table, nil, schema)
|
245
275
|
end
|
246
276
|
|
@@ -319,6 +349,7 @@ module ::ArJdbc
|
|
319
349
|
case field_type
|
320
350
|
when /^timestamp with(?:out)? time zone$/ then :datetime
|
321
351
|
when /byteint/i then :boolean
|
352
|
+
when /blob/i then :binary
|
322
353
|
else
|
323
354
|
super
|
324
355
|
end
|
@@ -335,7 +366,17 @@ module ::ArJdbc
|
|
335
366
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
336
367
|
case value
|
337
368
|
when String
|
338
|
-
|
369
|
+
if String === value && column && (column.type == :binary || column.type == :text)
|
370
|
+
'NULL'
|
371
|
+
else
|
372
|
+
%Q{'#{quote_string(value)}'}
|
373
|
+
end
|
374
|
+
when Fixnum
|
375
|
+
if Fixnum === value && column and column.type == :string
|
376
|
+
%Q{'#{quote_string(value.to_s)}'}
|
377
|
+
else
|
378
|
+
super
|
379
|
+
end
|
339
380
|
when TrueClass
|
340
381
|
'1'
|
341
382
|
when FalseClass
|
@@ -417,6 +458,15 @@ module ActiveRecord
|
|
417
458
|
def jdbc_column_class
|
418
459
|
TeradataColumn
|
419
460
|
end
|
461
|
+
|
462
|
+
#- jdbc_columns
|
463
|
+
def jdbc_columns(table_name, name = nil)
|
464
|
+
return false unless table_name
|
465
|
+
schema, table = extract_schema_and_table(table_name.to_s)
|
466
|
+
return false unless table
|
467
|
+
schema = database_name unless schema
|
468
|
+
@connection.columns(table, nil, schema)
|
469
|
+
end
|
420
470
|
alias_chained_method :columns, :query_cache, :jdbc_columns
|
421
471
|
|
422
472
|
# some QUOTING caching :
|
@@ -7,18 +7,44 @@ class ActiveRecord::Base
|
|
7
7
|
rescue LoadError # assuming driver.jar is on the class-path
|
8
8
|
end
|
9
9
|
|
10
|
-
config[:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
if config[:jndi]
|
11
|
+
jndi = config[:jndi].to_s
|
12
|
+
ctx = javax.naming.InitialContext.new
|
13
|
+
ds = nil
|
14
|
+
|
15
|
+
# Taken from oracle-enhanced (https://github.com/rsim/oracle-enhanced)
|
16
|
+
# tomcat needs first lookup method, oc4j (and maybe other application servers) need second method
|
17
|
+
begin
|
18
|
+
env = ctx.lookup('java:/comp/env')
|
19
|
+
ds = env.lookup(jndi)
|
20
|
+
rescue
|
21
|
+
ds = ctx.lookup(jndi)
|
22
|
+
end
|
23
|
+
|
24
|
+
# For ARJDBC we only need the URL, username, and password
|
25
|
+
# We set the database config entry because it's used by the adapter to determine database_name
|
26
|
+
config[:url] = ds.getUrl
|
27
|
+
config[:username] ||= ds.getUsername
|
28
|
+
config[:database] ||= config[:url][/DATABASE=(.*?),/m, 1] unless config[:url].nil?
|
29
|
+
config[:password] ||= ds.getPassword
|
30
|
+
|
31
|
+
else
|
32
|
+
config[:username] ||= Java::JavaLang::System.get_property('user.name')
|
33
|
+
config[:host] ||= 'localhost'
|
34
|
+
config[:port] ||= 1025
|
35
|
+
config[:tmode] ||= 'ANSI' # ANSI, Teradata, DEFAULT
|
36
|
+
config[:charset] ||= 'UTF8'
|
37
|
+
config[:cop] ||= 'OFF'
|
38
|
+
config[:log_level] ||= 'ERROR'
|
39
|
+
config[:xviews] ||= 'OFF'
|
40
|
+
config[:url] ||= "jdbc:teradata://#{config[:host]}/DATABASE=#{config[:database]},DBS_PORT=#{config[:port]},COP=#{config[:cop]},tmode=#{config[:tmode]},charset=#{config[:charset]},LOG=#{config[:log_level]},USEXVIEWS=#{config[:xviews]}"
|
41
|
+
end
|
42
|
+
config[:driver] ||= 'com.teradata.jdbc.TeraDriver'
|
43
|
+
config[:adapter_class] = ActiveRecord::ConnectionAdapters::TeradataAdapter
|
44
|
+
config[:adapter_spec] = ::ArJdbc::Teradata
|
45
|
+
jdbc_connection(config)
|
21
46
|
end
|
47
|
+
|
22
48
|
alias_method :jdbcteradata_connection, :teradata_connection
|
23
49
|
end
|
24
50
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ::ArJdbc
|
2
|
+
module Teradata
|
3
|
+
def supports_explain?
|
4
|
+
true
|
5
|
+
end
|
6
|
+
|
7
|
+
def explain(arel, binds = [])
|
8
|
+
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
9
|
+
raw_result = @connection.execute_query(sql)
|
10
|
+
raw_result
|
11
|
+
rows = raw_result.map { |hash| hash.values }
|
12
|
+
rows.join("\n")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
Binary file
|
data/spec/adapter_spec.rb
CHANGED
@@ -2,6 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
require 'models/simple_article'
|
4
4
|
require 'models/lowercase_model'
|
5
|
+
require 'models/model_with_blob'
|
5
6
|
|
6
7
|
describe 'Adapter' do
|
7
8
|
|
@@ -40,6 +41,13 @@ describe 'Adapter' do
|
|
40
41
|
articles.select { |i| i['title'] == article_2.title }.first.should_not be_nil
|
41
42
|
end
|
42
43
|
|
44
|
+
it '#explain' do
|
45
|
+
article_1 = Article.create(:title => 'exec_query_1', :body => 'exec_query_1')
|
46
|
+
explain_plan = @adapter.explain('select * from articles')
|
47
|
+
explain_plan.should include('WEBLOG_DEVELOPMENT.articles')
|
48
|
+
explain_plan.should include('total estimated time')
|
49
|
+
end
|
50
|
+
|
43
51
|
it '#last_insert_id(table)' do
|
44
52
|
article_1 = Article.create(:title => 'exec_query_1', :body => 'exec_query_1')
|
45
53
|
article_1.id.should eq(@adapter.last_insert_id('articles'))
|
@@ -135,4 +143,33 @@ describe 'Adapter' do
|
|
135
143
|
CreateShirts.down
|
136
144
|
end
|
137
145
|
end
|
146
|
+
|
147
|
+
context 'testing BLOB support' do
|
148
|
+
before(:each) do
|
149
|
+
CreateTestFiles.up
|
150
|
+
@connection = TestFile.connection
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should be able to save a BLOB' do
|
154
|
+
file = TestFile.new
|
155
|
+
file.name = 'test'
|
156
|
+
|
157
|
+
path = File.join(File.dirname(__FILE__), '')
|
158
|
+
|
159
|
+
bytes = File.open(File.join(path, '/fixtures/wikimedia-commons-poty-2006.jpg'), 'rb')\
|
160
|
+
.read\
|
161
|
+
.to_java_bytes
|
162
|
+
file.data = bytes.to_s
|
163
|
+
file.save
|
164
|
+
TestFile.where(:name => 'test').count.should eq(1)
|
165
|
+
TestFile.where(:name => 'test').first.data.should eq(file.data)
|
166
|
+
#Uncomment this line to perform a visual test.
|
167
|
+
#The test.jpg image should be the same as the wikimedia commons jpg image.
|
168
|
+
#File.open(File.join(path, '/fixtures/test.jpg'), 'wb') { |file| file.write(TestFile.first.data.to_s) }
|
169
|
+
end
|
170
|
+
|
171
|
+
after(:each) do
|
172
|
+
CreateTestFiles.down
|
173
|
+
end
|
174
|
+
end
|
138
175
|
end
|
data/spec/associations_spec.rb
CHANGED
@@ -13,6 +13,7 @@ describe 'AssociationsSpec' do
|
|
13
13
|
|
14
14
|
it 'should create all of the tables' do
|
15
15
|
vendor = Vendor.new(:name => 'Test vendor', :catch_phrase => 'Hello, world')
|
16
|
+
puts vendor.inspect
|
16
17
|
vendor.products.build(:name => 'Test product', :price => 100.00)
|
17
18
|
vendor.save
|
18
19
|
|
@@ -38,8 +39,8 @@ describe 'AssociationsSpec' do
|
|
38
39
|
:product_id => vendor.products.first.id,
|
39
40
|
:code => 'Order 2',
|
40
41
|
:quantity => 1,
|
41
|
-
:order_line_items_attributes => [
|
42
|
-
{ :item_name => 'Test item' }
|
42
|
+
:order_line_items_attributes => [
|
43
|
+
{ :item_name => 'Test item' }
|
43
44
|
]
|
44
45
|
} }
|
45
46
|
|
@@ -57,14 +58,14 @@ describe 'AssociationsSpec' do
|
|
57
58
|
:code => 'Order 2',
|
58
59
|
:quantity => 1,
|
59
60
|
:order_feeling_attributes =>
|
60
|
-
{ :status => 'Wonderful' }
|
61
|
-
|
61
|
+
{ :status => 'Wonderful' }
|
62
|
+
|
62
63
|
} }
|
63
64
|
|
64
65
|
purchase_order = PurchaseOrder.create(params[:purchase_order])
|
65
66
|
purchase_order.order_feeling.status.should eq('Wonderful')
|
66
67
|
end
|
67
|
-
|
68
|
+
|
68
69
|
it 'it has_one#new' do
|
69
70
|
vendor = Vendor.new(:name => 'Test vendor', :catch_phrase => 'Hello, world')
|
70
71
|
vendor.products.build(:name => 'Test product', :price => 100.00)
|
@@ -75,15 +76,15 @@ describe 'AssociationsSpec' do
|
|
75
76
|
:code => 'Order 3',
|
76
77
|
:quantity => 1,
|
77
78
|
:order_feeling_attributes =>
|
78
|
-
{ :status => 'Wonderful' }
|
79
|
-
|
79
|
+
{ :status => 'Wonderful' }
|
80
|
+
|
80
81
|
} }
|
81
82
|
|
82
83
|
purchase_order = PurchaseOrder.new(params[:purchase_order])
|
83
84
|
purchase_order.save
|
84
85
|
purchase_order.order_feeling.status.should eq('Wonderful')
|
85
86
|
end
|
86
|
-
|
87
|
+
|
87
88
|
end
|
88
89
|
|
89
90
|
after(:all) do
|
Binary file
|
Binary file
|
data/spec/connection_spec.rb
CHANGED
@@ -1,8 +1,48 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'java'
|
3
|
+
require 'commons-pool-1.6.jar'
|
4
|
+
require 'commons-dbcp-1.4.jar'
|
2
5
|
|
3
6
|
describe 'Connection' do
|
4
7
|
it 'should create a connection' do
|
5
8
|
ActiveRecord::Base.connection.execute('select * from dbc.tables')
|
6
9
|
ActiveRecord::Base.connected?.should be_true
|
7
10
|
end
|
11
|
+
|
12
|
+
it "should create a new connection using JNDI" do
|
13
|
+
begin
|
14
|
+
import 'org.apache.commons.pool.impl.GenericObjectPool'
|
15
|
+
import 'org.apache.commons.dbcp.BasicDataSource'
|
16
|
+
import 'org.apache.commons.dbcp.BasicDataSourceFactory'
|
17
|
+
import 'org.apache.commons.dbcp.DriverManagerConnectionFactory'
|
18
|
+
rescue NameError => e
|
19
|
+
return pending e.message
|
20
|
+
end
|
21
|
+
|
22
|
+
class InitialContextMock
|
23
|
+
def initialize
|
24
|
+
url = "jdbc:teradata://#{TERADATA_CONFIG[:host]}/DATABASE=#{TERADATA_CONFIG[:database]},DBS_PORT=#{TERADATA_CONFIG[:port]}"
|
25
|
+
@data_source = BasicDataSource.new()
|
26
|
+
@data_source.set_driver_class_name('com.teradata.jdbc.TeraDriver')
|
27
|
+
@data_source.set_url(url)
|
28
|
+
@data_source.set_username(TERADATA_CONFIG[:username])
|
29
|
+
@data_source.set_password(TERADATA_CONFIG[:password])
|
30
|
+
|
31
|
+
@data_source.access_to_underlying_connection_allowed = true
|
32
|
+
end
|
33
|
+
def lookup(path)
|
34
|
+
if (path == 'java:/comp/env')
|
35
|
+
return self
|
36
|
+
else
|
37
|
+
return @data_source
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
javax.naming.InitialContext.stub!(:new).and_return(InitialContextMock.new)
|
43
|
+
|
44
|
+
ActiveRecord::Base.establish_connection(TERADATA_JNDI_CONFIG)
|
45
|
+
ActiveRecord::Base.connection.execute('select * from dbc.tables')
|
46
|
+
ActiveRecord::Base.connected?.should be_true
|
47
|
+
end
|
8
48
|
end
|
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateTestFiles < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table 'test_files' do |t|
|
4
|
+
t.string 'name', :null => false
|
5
|
+
t.binary 'data'
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
drop_table 'test_files'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestFile < ActiveRecord::Base
|
16
|
+
self.table_name = 'test_files'
|
17
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,11 +2,19 @@ require 'active_record'
|
|
2
2
|
|
3
3
|
TERADATA_CONFIG = {
|
4
4
|
:adapter => 'teradata',
|
5
|
-
:host => '
|
5
|
+
:host => (ENV['TERADATA_HOST'] || 'localhost'),
|
6
6
|
:database => 'weblog_development',
|
7
7
|
:port => 1025,
|
8
8
|
:username => 'dbc',
|
9
9
|
:password => 'dbc'
|
10
10
|
}
|
11
11
|
|
12
|
+
TERADATA_JNDI_CONFIG = {
|
13
|
+
:adapter => 'teradata',
|
14
|
+
:jndi => 'jdbc/TeradataDS',
|
15
|
+
:username => 'dbc',
|
16
|
+
:password => 'dbc',
|
17
|
+
:pool => 20
|
18
|
+
}
|
19
|
+
|
12
20
|
ActiveRecord::Base.establish_connection(TERADATA_CONFIG)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-jdbcteradata-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -63,15 +63,15 @@ dependencies:
|
|
63
63
|
name: activerecord
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - <=
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 3.2.13
|
69
69
|
none: false
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- -
|
72
|
+
- - <=
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 3.2.13
|
75
75
|
none: false
|
76
76
|
prerelease: false
|
77
77
|
type: :runtime
|
@@ -112,14 +112,19 @@ files:
|
|
112
112
|
- lib/arjdbc/teradata/adapter.rb
|
113
113
|
- lib/arjdbc/teradata/connection_methods.rb
|
114
114
|
- lib/arjdbc/teradata/teradata_java.jar
|
115
|
+
- lib/arjdbc/teradata/explain_support.rb
|
115
116
|
- lib/arjdbc/teradata.rb
|
116
117
|
- spec/active_record_schema_spec.rb
|
117
118
|
- spec/adapter_spec.rb
|
118
119
|
- spec/associations_spec.rb
|
120
|
+
- spec/commons-dbcp-1.4.jar
|
121
|
+
- spec/commons-pool-1.6.jar
|
119
122
|
- spec/connection_spec.rb
|
123
|
+
- spec/fixtures/wikimedia-commons-poty-2006.jpg
|
120
124
|
- spec/models/active_record_models.rb
|
121
125
|
- spec/models/active_record_schema.rb
|
122
126
|
- spec/models/lowercase_model.rb
|
127
|
+
- spec/models/model_with_blob.rb
|
123
128
|
- spec/models/purchase_orders.rb
|
124
129
|
- spec/models/simple_article.rb
|
125
130
|
- spec/simple_spec.rb
|
@@ -152,10 +157,14 @@ test_files:
|
|
152
157
|
- spec/active_record_schema_spec.rb
|
153
158
|
- spec/adapter_spec.rb
|
154
159
|
- spec/associations_spec.rb
|
160
|
+
- spec/commons-dbcp-1.4.jar
|
161
|
+
- spec/commons-pool-1.6.jar
|
155
162
|
- spec/connection_spec.rb
|
163
|
+
- spec/fixtures/wikimedia-commons-poty-2006.jpg
|
156
164
|
- spec/models/active_record_models.rb
|
157
165
|
- spec/models/active_record_schema.rb
|
158
166
|
- spec/models/lowercase_model.rb
|
167
|
+
- spec/models/model_with_blob.rb
|
159
168
|
- spec/models/purchase_orders.rb
|
160
169
|
- spec/models/simple_article.rb
|
161
170
|
- spec/simple_spec.rb
|